#ifndef W_PUBLIC_H_
#define W_PUBLIC_H_

#include <WinSock2.h>
#include <Iphlpapi.h>
#include <iostream>
#include <windows.h>
#include <tlhelp32.h>
#include <algorithm>

#pragma comment(lib,"Iphlpapi.lib") //需要添加Iphlpapi.lib库

// 工程是否是 Unicode 编码
//#define CHARSET_UNICODE_DEFINE
namespace cpppub {

bool IsLocalIPExist(const char* pszIP)
{
	bool isHave = false;
	//PIP_ADAPTER_INFO结构体指针存储本机网卡信息
	auto pIpAdapterInfo = new IP_ADAPTER_INFO();
	//得到结构体大小,用于GetAdaptersInfo参数
	unsigned long stSize = sizeof(IP_ADAPTER_INFO);
	//调用GetAdaptersInfo函数,填充pIpAdapterInfo指针变量;其中stSize参数既是一个输入量也是一个输出量
	ULONG nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
    delete pIpAdapterInfo;
    // 这里的操作:重新分配是为了保证有足够的空间来进行存储。
    pIpAdapterInfo = (IP_ADAPTER_INFO*)(new BYTE[stSize]);
    nRel = GetAdaptersInfo(pIpAdapterInfo, &stSize);
	//记录网卡数量
	int netCardNum = 0;
	//记录每张网卡上的IP地址数量
	int IPnumPerNetCard = 0;
	PIP_ADAPTER_INFO header = pIpAdapterInfo;
	if (ERROR_SUCCESS == nRel)
	{
		//输出网卡信息
		//可能有多网卡,因此通过循环去判断
		while (pIpAdapterInfo)
		{
			IP_ADDR_STRING *pIpAddrString = &(pIpAdapterInfo->IpAddressList);
			do
			{
				if (strcmp(pIpAddrString->IpAddress.String, pszIP) == 0)
				{
					isHave = true;
					break;
				}
				pIpAddrString = pIpAddrString->Next;
			} while (pIpAddrString);

			if (isHave)
				break;

			pIpAdapterInfo = pIpAdapterInfo->Next;
		}
	}
	//释放内存空间
	delete[] header;
	return isHave;
}


char* Wchar2Char(const wchar_t* wp)
{
	int len = WideCharToMultiByte(CP_ACP, 0, wp,
                                  static_cast<int>(wcslen(wp)), nullptr, 0, nullptr, nullptr);
	char* m_char = new char[len + 1];
	WideCharToMultiByte(CP_ACP, 0, wp, static_cast<int>(wcslen(wp)), m_char, len, nullptr, nullptr);
	m_char[len] = '\0';
	return m_char;
}

void Wchar2CharFree(const char* pszChar)
{
	delete[] pszChar;
}

BOOL KillProcessFromName(const std::string& strProcessName)
{
	std::string szTemProcessName = strProcessName;
    //创建进程快照(TH32CS_SNAPPROCESS表示创建所有进程的快照) 
    HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    //PROCESSENTRY32进程快照的结构体 
    PROCESSENTRY32 pe;
    //实例化后使用Process32First获取第一个快照的进程前必做的初始化操作 
    pe.dwSize = sizeof(PROCESSENTRY32);
    //下面的IF效果同: 
    //if(hProcessSnap == INVALID_HANDLE_VALUE) 无效的句柄 
    if (!Process32First(hSnapShot, &pe))
    {
        return FALSE;
    }
    //将字符串转换为小写 
    std::transform(szTemProcessName.begin(), szTemProcessName.end(), szTemProcessName.begin(), ::tolower);
    //如果句柄有效 则一直获取下一个句柄循环下去 
    while (Process32Next(hSnapShot, &pe))
    {
		std::string scTmp;

		// Unicode 编码时
		// pe.szExeFile获取当前进程的可执行文件名称
#ifdef CHARSET_UNICODE_DEFINE
		char* pszTem = Wchar2Char(pe.szExeFile);
		scTmp = std::string(pszTem);
		Wchar2CharFree(pszTem);
		pszTem = nullptr;
#else
		scTmp = std::string(pe.szExeFile);
#endif // CHARSET_UNICODE_DEFINE

        //将可执行文件名称所有英文字母修改为小写 
        std::transform(scTmp.begin(), scTmp.end(), scTmp.begin(), ::tolower);
        //scTmp.MakeLower();
        //比较当前进程的可执行文件名称和传递进来的文件名称是否相同 
        //相同的话Compare返回0 
        if (scTmp == strProcessName)
        {
            //从快照进程中获取该进程的PID(即任务管理器中的PID) 
            DWORD dwProcessID = pe.th32ProcessID;
            HANDLE hProcess = ::OpenProcess(PROCESS_TERMINATE, FALSE, dwProcessID);
            ::TerminateProcess(hProcess, 0);
            CloseHandle(hProcess);
            return TRUE;
        }
        //scTmp.ReleaseBuffer();
    }
    //strProcessName.ReleaseBuffer();
    return FALSE;
}

}
#endif