#include "stdafx.h"
#include "Global.h"
#include <SetupAPI.h>
#include <InitGuid.h>
#include <WinIoCtl.h>
#pragma comment(lib, "SetupAPI.lib")
#include "cJSON.h"
#include <direct.h>

namespace Global
{
	//////////////////////////////////////////////////////////////////////////
	// 全局变量;
	BOOL g_bTestHost = FALSE;
	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
	TCHAR g_szFna[MAX_PATH] = { 0 };
	TCHAR g_szConfig[MAX_PATH] = { 0 };
	std::string g_strMacs;
	std::vector<MacAddress> g_vtMac;
	TConfig g_tConfig;
	Global::TChassis g_AutoOnlineChassis;

	// usb;
	static GUID UsbClassGuid = { 0xA5DCBF10L, 0x6530, 0x11D2, {0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED} };
	// mac;
	static GUID MacClassGuid = { 0xAD498944, 0x762F, 0x11D0, {0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C} };
	// hdd;
	static GUID HDDClassGuid = { 0x53F56307, 0xB6BF, 0x11D0, {0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B} };

	//////////////////////////////////////////////////////////////////////////
	// 全局函数;
	void Init()
	{
		TCHAR szDrive[_MAX_DRIVE] = { 0 };
		TCHAR szDir[_MAX_DIR] = { 0 };
		TCHAR szExt[_MAX_DIR] = { 0 };
		::GetModuleFileName(NULL, g_szCurModulePath, sizeof(g_szCurModulePath) / sizeof(TCHAR));
		_tsplitpath_s(g_szCurModulePath, szDrive, szDir, g_szFna, szExt);
		_tcscpy_s(g_szCurModuleDir, szDrive);
		_tcscat_s(g_szCurModuleDir, szDir);

		// 创建cache目录;
		TCHAR szPath[MAX_PATH] = {0};
		_stprintf_s(szPath, _T("%scache"), g_szCurModuleDir);
		MKDIR(szPath);

		_stprintf_s(szPath, _T("%sdb"), g_szCurModuleDir);
		MKDIR(szPath);
	}

	void MKDIR(LPCTSTR dir) 
	{
		//////////////////////////////////////////////////////////////////////////
		// 创建目录;
		int nleft = 0;
		int nIndex = -1;
		std::string strdir = dir;
		if (strdir.at(strdir.size() - 1) != _T('\\'))
			strdir.append(_T("\\"));

		// 共享路径和硬盘盘符;
		if (_tcscmp(strdir.substr(0, 2).c_str(), _T("\\\\")) == 0)
			nleft = strdir.find_first_of(_T("\\"), 2) + 1;	// 去除共享主机名;
		else if (strdir.at(2) == _T('\\'))
			nleft = 3;

		do
		{
			nIndex = strdir.substr(nleft, -1).find_first_of(_T("\\"));

			if (nIndex != std::string::npos)
			{
				std::string sub = strdir.substr(0, nIndex + nleft);
				if (_mkdir(sub.c_str()) == -1 && (errno != EEXIST))
				{
					//WriteTextLog(_T("创建目录失败：%s，错误码：%d"), strdir.substr(0, nIndex + nleft).c_str(), errno);
					break;
				}

				nleft += nIndex + 1;
			}
		} while (nIndex != -1);
	}

	/************************************************************************/
	/*  函数：WriteTextLog[7/28/2009 Jeff];
	/*  描述：写文本日志;
	/*  参数：;
	/*  	[IN] ：;
	/*  返回：void;
	/*  注意：;
	/*  示例：;
	/*
	/*  修改：;
	/*  日期：;
	/*  内容：;
	/************************************************************************/
	void WriteTextLog(const TCHAR* format, ...)
	{
		// 将日志内容输入到文件中;
		// 获取今年年份;
		__time64_t gmt = time(NULL); // 获取当前日历时间(1900-01-01开始的Unix时间戳);
		struct tm gmtm = { 0 };
		localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;

		// 解析出日志路径;
		TCHAR szlogpath[MAX_PATH] = { 0 };
		_stprintf_s(szlogpath, _T("%slog\\Serial Port Log %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
		// 打开或创建文件;
		FILE* fp = NULL;
		//if (_taccess(szlogpath, 0) != -1)
#ifndef UNICODE
		if (_access(szlogpath, 0) != -1)
#else
		if (_taccess(szlogpath, 0) != -1)
#endif
		{ // 存在;
			if (0 == _tfopen_s(&fp, szlogpath, _T("a+")))
				// 移动到末尾;
				fseek(fp, 0, SEEK_END);
		}
		else
		{ // 不存在;
			_tfopen_s(&fp, szlogpath, _T("w+"));
		}

		if (fp == NULL)
			return;

		// 格式化前设置语言区域;
		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
		_tsetlocale(LC_CTYPE, _T("chs")); //设定中文;

		// 格式化日志内容;
		va_list args = NULL;
		int len = 0;
		TCHAR* buffer = NULL;
		va_start(args, format);
		// _vscprintf doesn't count. terminating '\0'
		len = _vsctprintf(format, args) + 1;
		buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
		_vstprintf_s(buffer, len, format, args);
		_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);

		// 关闭文件，释放资源并设置回原语言区域;
		free(buffer);
		fclose(fp);
		_tsetlocale(LC_CTYPE, old_locale);
		free(old_locale); //还原区域设定;
	}

	// 读取配置文件-预留;
	void GetConfig()
	{
		// 读取文件;
		FILE* pf = NULL;
		_tfopen_s(&pf, _T("./Config.json"), _T("rb"));
		if (!pf)
			return;
		// 获取文件长度;
		fseek(pf, 0, SEEK_END);
		size_t file_size = ftell(pf);
		fseek(pf, 0, SEEK_SET);
		// 读取文件内容;
		byte* pdata = (byte*)malloc(file_size);
		fread(pdata, file_size, 1, pf);
		fclose(pf);

		// Json数据;
		cJSON* pJson = cJSON_Parse((const char*)pdata);
		if (pJson == NULL)
		{
			goto end;
		}

		// 获取数据;
		g_tConfig.com = cJSON_GetObjectItem(pJson, _T("COM")) ? cJSON_GetObjectItem(pJson, _T("COM"))->valuestring : "";
		g_tConfig.baudrate = cJSON_GetObjectItem(pJson, _T("Baudrate")) ? cJSON_GetObjectItem(pJson, _T("Baudrate"))->valuestring : "115200";
		g_tConfig.mode = cJSON_GetObjectItem(pJson, _T("Mode")) ? cJSON_GetObjectItem(pJson, _T("Mode"))->valueint : 0;
		g_tConfig.warncount = cJSON_GetObjectItem(pJson, _T("WarnCount")) ? cJSON_GetObjectItem(pJson, _T("WarnCount"))->valueint : 200;
		g_tConfig.waitboot = cJSON_GetObjectItem(pJson, _T("WaitBoot")) ? cJSON_GetObjectItem(pJson, _T("WaitBoot"))->valueint : 5000;
		g_tConfig.serverurl = cJSON_GetObjectItem(pJson, _T("server-url")) ? cJSON_GetObjectItem(pJson, _T("server-url"))->valuestring : "";
		g_tConfig.chassis = cJSON_GetObjectItem(pJson, _T("Chassis")) ? cJSON_GetObjectItem(pJson, _T("Chassis"))->valuestring : "";

		// 频道;
		cJSON* pItem = NULL;
		cJSON* pChannel = cJSON_GetObjectItem(pJson, "Channel");
		if (pChannel)
		{
			int nCount = cJSON_GetArraySize(pChannel);
			for (int i = 0; i < nCount; i++)
			{
				pItem = cJSON_GetArrayItem(pChannel, i);
				if (pItem && pItem->child)
				{
					g_tConfig.channel.insert(std::pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
				}
			}
		}
		// 语言;
		cJSON* pLanguage = cJSON_GetObjectItem(pJson, "Language");
		if (pLanguage)
		{
			int nCount = cJSON_GetArraySize(pLanguage);
			for (int i = 0; i < nCount; i++)
			{
				pItem = cJSON_GetArrayItem(pLanguage, i);
				if (pItem && pItem->child)
				{
					g_tConfig.language.insert(std::pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
				}
			}
		}
		// 文件夹;
		cJSON* pKeyFolder = cJSON_GetObjectItem(pJson, "KeyFolder");
		if (pKeyFolder)
		{
			int nCount = cJSON_GetArraySize(pKeyFolder);
			for (int i = 0; i < nCount; i++)
			{
				pItem = cJSON_GetArrayItem(pKeyFolder, i);
				if (pItem && pItem->child)
				{
					g_tConfig.keyfolder.insert(std::pair<std::string, std::string>(pItem->child->string, pItem->child->valuestring));
				}
			}
		}
		// read check;
		cJSON *pReadCheck = cJSON_GetObjectItem(pJson, "ReadCheck");
		if ( pReadCheck )
		{
			g_tConfig.readcheck.IsPID = cJSON_GetObjectItem(pReadCheck, _T("PID")) ? cJSON_GetObjectItem(pReadCheck, _T("PID"))->valueint : 1;
			g_tConfig.readcheck.IsCHANNEL = cJSON_GetObjectItem(pReadCheck, _T("CHANNEL")) ? cJSON_GetObjectItem(pReadCheck, _T("CHANNEL"))->valueint : 1;
			g_tConfig.readcheck.IsOSD = cJSON_GetObjectItem(pReadCheck, _T("OSD")) ? cJSON_GetObjectItem(pReadCheck, _T("OSD"))->valueint : 1;
			g_tConfig.readcheck.IsSHOP = cJSON_GetObjectItem(pReadCheck, _T("SHOP")) ? cJSON_GetObjectItem(pReadCheck, _T("SHOP"))->valueint : 1;
			g_tConfig.readcheck.IsDID = cJSON_GetObjectItem(pReadCheck, _T("DID")) ? cJSON_GetObjectItem(pReadCheck, _T("DID"))->valueint : 1;
			g_tConfig.readcheck.IsMAC = cJSON_GetObjectItem(pReadCheck, _T("MAC")) ? cJSON_GetObjectItem(pReadCheck, _T("MAC"))->valueint : 1;
			g_tConfig.readcheck.IsHDCP = cJSON_GetObjectItem(pReadCheck, _T("HDCP")) ? cJSON_GetObjectItem(pReadCheck, _T("HDCP"))->valueint : 1;
			g_tConfig.readcheck.IsHDCP22 = cJSON_GetObjectItem(pReadCheck, _T("HDCP22")) ? cJSON_GetObjectItem(pReadCheck, _T("HDCP22"))->valueint : 1;
			g_tConfig.readcheck.IsWIDI = cJSON_GetObjectItem(pReadCheck, _T("WIDI")) ? cJSON_GetObjectItem(pReadCheck, _T("WIDI"))->valueint : 1;
			g_tConfig.readcheck.IsWIDEVINE = cJSON_GetObjectItem(pReadCheck, _T("WIDEVINE")) ? cJSON_GetObjectItem(pReadCheck, _T("WIDEVINE"))->valueint : 1;
			g_tConfig.readcheck.IsESN = cJSON_GetObjectItem(pReadCheck, _T("ESN")) ? cJSON_GetObjectItem(pReadCheck, _T("ESN"))->valueint : 1;
			g_tConfig.readcheck.IsCI = cJSON_GetObjectItem(pReadCheck, _T("CI")) ? cJSON_GetObjectItem(pReadCheck, _T("CI"))->valueint : 1;
		}

#ifdef SUPER_VER
		// write check;
		cJSON* pWriteCheck = cJSON_GetObjectItem(pJson, "WriteCheck");
		if (pWriteCheck)
		{
			//g_tConfig.writecheck.IsPID = cJSON_GetObjectItem(pWriteCheck, _T("PID")) ? cJSON_GetObjectItem(pWriteCheck, _T("PID"))->valueint : 1;
			//g_tConfig.writecheck.IsCHANNEL = cJSON_GetObjectItem(pWriteCheck, _T("CHANNEL")) ? cJSON_GetObjectItem(pWriteCheck, _T("CHANNEL"))->valueint : 1;
			//g_tConfig.writecheck.IsOSD = cJSON_GetObjectItem(pWriteCheck, _T("OSD")) ? cJSON_GetObjectItem(pWriteCheck, _T("OSD"))->valueint : 1;
			//g_tConfig.writecheck.IsSHOP = cJSON_GetObjectItem(pWriteCheck, _T("SHOP")) ? cJSON_GetObjectItem(pWriteCheck, _T("SHOP"))->valueint : 1;
			g_tConfig.writecheck.IsDID = cJSON_GetObjectItem(pWriteCheck, _T("DID")) ? cJSON_GetObjectItem(pWriteCheck, _T("DID"))->valueint : 1;
			g_tConfig.writecheck.IsMAC = cJSON_GetObjectItem(pWriteCheck, _T("MAC")) ? cJSON_GetObjectItem(pWriteCheck, _T("MAC"))->valueint : 1;
			g_tConfig.writecheck.IsHDCP = cJSON_GetObjectItem(pWriteCheck, _T("HDCP")) ? cJSON_GetObjectItem(pWriteCheck, _T("HDCP"))->valueint : 1;
			g_tConfig.writecheck.IsHDCP22 = cJSON_GetObjectItem(pWriteCheck, _T("HDCP22")) ? cJSON_GetObjectItem(pWriteCheck, _T("HDCP22"))->valueint : 1;
			g_tConfig.writecheck.IsWIDI = cJSON_GetObjectItem(pWriteCheck, _T("WIDI")) ? cJSON_GetObjectItem(pWriteCheck, _T("WIDI"))->valueint : 1;
			g_tConfig.writecheck.IsWIDEVINE = cJSON_GetObjectItem(pWriteCheck, _T("WIDEVINE")) ? cJSON_GetObjectItem(pWriteCheck, _T("WIDEVINE"))->valueint : 1;
			g_tConfig.writecheck.IsESN = cJSON_GetObjectItem(pWriteCheck, _T("ESN")) ? cJSON_GetObjectItem(pWriteCheck, _T("ESN"))->valueint : 1;
			g_tConfig.writecheck.IsCI = cJSON_GetObjectItem(pWriteCheck, _T("CI")) ? cJSON_GetObjectItem(pWriteCheck, _T("CI"))->valueint : 1;
		}

		// write done;
		cJSON* pWriteDone = cJSON_GetObjectItem(pJson, "WriteDone");
		if (pWriteDone)
		{
			g_tConfig.writedone.IsPID = cJSON_GetObjectItem(pWriteDone, _T("PID")) ? cJSON_GetObjectItem(pWriteDone, _T("PID"))->valueint : 1;
			g_tConfig.writedone.IsCHANNEL = cJSON_GetObjectItem(pWriteDone, _T("CHANNEL")) ? cJSON_GetObjectItem(pWriteDone, _T("CHANNEL"))->valueint : 1;
			g_tConfig.writedone.IsOSD = cJSON_GetObjectItem(pWriteDone, _T("OSD")) ? cJSON_GetObjectItem(pWriteDone, _T("OSD"))->valueint : 1;
			g_tConfig.writedone.IsSHOP = cJSON_GetObjectItem(pWriteDone, _T("SHOP")) ? cJSON_GetObjectItem(pWriteDone, _T("SHOP"))->valueint : 1;
			g_tConfig.writedone.IsDID = cJSON_GetObjectItem(pWriteDone, _T("DID")) ? cJSON_GetObjectItem(pWriteDone, _T("DID"))->valueint : 1;
			g_tConfig.writedone.IsMAC = cJSON_GetObjectItem(pWriteDone, _T("MAC")) ? cJSON_GetObjectItem(pWriteDone, _T("MAC"))->valueint : 1;
			g_tConfig.writedone.IsHDCP = cJSON_GetObjectItem(pWriteDone, _T("HDCP")) ? cJSON_GetObjectItem(pWriteDone, _T("HDCP"))->valueint : 1;
			g_tConfig.writedone.IsHDCP22 = cJSON_GetObjectItem(pWriteDone, _T("HDCP22")) ? cJSON_GetObjectItem(pWriteDone, _T("HDCP22"))->valueint : 1;
			g_tConfig.writedone.IsWIDI = cJSON_GetObjectItem(pWriteDone, _T("WIDI")) ? cJSON_GetObjectItem(pWriteDone, _T("WIDI"))->valueint : 1;
			g_tConfig.writedone.IsWIDEVINE = cJSON_GetObjectItem(pWriteDone, _T("WIDEVINE")) ? cJSON_GetObjectItem(pWriteDone, _T("WIDEVINE"))->valueint : 1;
			g_tConfig.writedone.IsESN = cJSON_GetObjectItem(pWriteDone, _T("ESN")) ? cJSON_GetObjectItem(pWriteDone, _T("ESN"))->valueint : 1;
			g_tConfig.writedone.IsCI = cJSON_GetObjectItem(pWriteDone, _T("CI")) ? cJSON_GetObjectItem(pWriteDone, _T("CI"))->valueint : 1;
		}
#endif
		// 配置;
		cJSON* pChassis = cJSON_GetObjectItem(pJson, "Chassis-list");
		if (pChassis)
		{
			int nCount = cJSON_GetArraySize(pChassis);
			for (int i = 0; i < nCount; i++)
			{
				pItem = cJSON_GetArrayItem(pChassis, i);
				if (pItem && pItem->child)
				{
					std::string name;
					TChassis tchassis;

					name = cJSON_GetObjectItem(pItem, _T("name")) ? cJSON_GetObjectItem(pItem, _T("name"))->valuestring : "";
					tchassis.IsCopyDID = cJSON_GetObjectItem(pItem, _T("IsCopyDID")) ? cJSON_GetObjectItem(pItem, _T("IsCopyDID"))->valueint : 0;
					tchassis.IsCopyMAC = cJSON_GetObjectItem(pItem, _T("IsCopyMAC")) ? cJSON_GetObjectItem(pItem, _T("IsCopyMAC"))->valueint : 0;
					tchassis.IsCopyKEY = cJSON_GetObjectItem(pItem, _T("IsCopyKEY")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY"))->valueint : 0;
					tchassis.IsCopyESN = cJSON_GetObjectItem(pItem, _T("IsCopyESN")) ? cJSON_GetObjectItem(pItem, _T("IsCopyESN"))->valueint : 0;
					tchassis.IsCopyWiDi = cJSON_GetObjectItem(pItem, _T("IsCopyWiDi")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWiDi"))->valueint : 0;
					tchassis.IsCopyWidevine = cJSON_GetObjectItem(pItem, _T("IsCopyWidevine")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWidevine"))->valueint : 0;
					tchassis.IsCopyKEY2_2 = cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_2")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_2"))->valueint : 0;
					tchassis.IsCopyKEY2_3 = cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_3")) ? cJSON_GetObjectItem(pItem, _T("IsCopyKEY2_3"))->valueint : 0;
					tchassis.IsCopyCikey = cJSON_GetObjectItem(pItem, _T("IsCopyCikey")) ? cJSON_GetObjectItem(pItem, _T("IsCopyCikey"))->valueint : 0;
					tchassis.IsCopyChannel = cJSON_GetObjectItem(pItem, _T("IsCopyChannel")) ? cJSON_GetObjectItem(pItem, _T("IsCopyChannel"))->valueint : 0;
					tchassis.IsCopyWB = cJSON_GetObjectItem(pItem, _T("IsCopyWB")) ? cJSON_GetObjectItem(pItem, _T("IsCopyWB"))->valueint : 0;
					tchassis.IsDisplayClientType = cJSON_GetObjectItem(pItem, _T("IsDisplayClientType")) ? cJSON_GetObjectItem(pItem, _T("IsDisplayClientType"))->valueint : 0;
					tchassis.IsWritePID = cJSON_GetObjectItem(pItem, _T("IsWritePID")) ? cJSON_GetObjectItem(pItem, _T("IsWritePID"))->valueint : 0;
					tchassis.IsWBInit = cJSON_GetObjectItem(pItem, _T("IsWBInit")) ? cJSON_GetObjectItem(pItem, _T("IsWBInit"))->valueint : 0;
					tchassis.IsMTKInit = cJSON_GetObjectItem(pItem, _T("IsMTKInit")) ? cJSON_GetObjectItem(pItem, _T("IsMTKInit"))->valueint : 0;
					tchassis.IsOsdLanguage = cJSON_GetObjectItem(pItem, _T("IsOsdLanguage")) ? cJSON_GetObjectItem(pItem, _T("IsOsdLanguage"))->valueint : 0;
					tchassis.IsShopLanguage = cJSON_GetObjectItem(pItem, _T("IsShopLanguage")) ? cJSON_GetObjectItem(pItem, _T("IsShopLanguage"))->valueint : 0;
					tchassis.IsCopyClientType = cJSON_GetObjectItem(pItem, _T("IsCopyClientType")) ? cJSON_GetObjectItem(pItem, _T("IsCopyClientType"))->valueint : 0;
					tchassis.IsMGKKeyEnb = cJSON_GetObjectItem(pItem, _T("IsMGKKeyEnb")) ? cJSON_GetObjectItem(pItem, _T("IsMGKKeyEnb"))->valueint : 0;
					tchassis.IsNovaTakHDCPEnb = cJSON_GetObjectItem(pItem, _T("IsNovaTakHDCPEnb")) ? cJSON_GetObjectItem(pItem, _T("IsNovaTakHDCPEnb"))->valueint : 0;

					tchassis.ProjectID = cJSON_GetObjectItem(pItem, _T("ProjectID")) ? cJSON_GetObjectItem(pItem, _T("ProjectID"))->valueint : 0;
					tchassis.Channel = cJSON_GetObjectItem(pItem, _T("Channel")) ? cJSON_GetObjectItem(pItem, _T("Channel"))->valuestring : "";
					tchassis.WBFile = cJSON_GetObjectItem(pItem, _T("WBFile")) ? cJSON_GetObjectItem(pItem, _T("WBFile"))->valuestring : "";
					tchassis.Delay = cJSON_GetObjectItem(pItem, _T("Delay")) ? cJSON_GetObjectItem(pItem, _T("Delay"))->valueint : 50;
					tchassis.CheckString = cJSON_GetObjectItem(pItem, _T("CheckString")) ? cJSON_GetObjectItem(pItem, _T("CheckString"))->valuestring : "";
					tchassis.ClientType = cJSON_GetObjectItem(pItem, _T("ClientType")) ? cJSON_GetObjectItem(pItem, _T("ClientType"))->valuestring : "";
					tchassis.MACType = cJSON_GetObjectItem(pItem, _T("MACType")) ? cJSON_GetObjectItem(pItem, _T("MACType"))->valuestring : "";
					tchassis.HDCPKeyType = cJSON_GetObjectItem(pItem, _T("HDCPKeyType")) ? cJSON_GetObjectItem(pItem, _T("HDCPKeyType"))->valuestring : "";
					tchassis.HDCPKey22Type = cJSON_GetObjectItem(pItem, _T("HDCPKey22Type")) ? cJSON_GetObjectItem(pItem, _T("HDCPKey22Type"))->valuestring : "";
					tchassis.HDCPKey23Type = cJSON_GetObjectItem(pItem, _T("HDCPKey23Type")) ? cJSON_GetObjectItem(pItem, _T("HDCPKey23Type"))->valuestring : "";
					tchassis.ESNType = cJSON_GetObjectItem(pItem, _T("ESNType")) ? cJSON_GetObjectItem(pItem, _T("ESNType"))->valuestring : "";
					tchassis.WiDiType = cJSON_GetObjectItem(pItem, _T("WiDiType")) ? cJSON_GetObjectItem(pItem, _T("WiDiType"))->valuestring : "";
					tchassis.WidevineType = cJSON_GetObjectItem(pItem, _T("WidevineType")) ? cJSON_GetObjectItem(pItem, _T("WidevineType"))->valuestring : "";
					tchassis.CIKeyType = cJSON_GetObjectItem(pItem, _T("CIKeyType")) ? cJSON_GetObjectItem(pItem, _T("CIKeyType"))->valuestring : "";
					tchassis.MGKKeyType = cJSON_GetObjectItem(pItem, _T("MGKKeyType")) ? cJSON_GetObjectItem(pItem, _T("MGKKeyType"))->valuestring : "";
					tchassis.NovaTakHDCPType = cJSON_GetObjectItem(pItem, _T("NovaTakHDCPType")) ? cJSON_GetObjectItem(pItem, _T("NovaTakHDCPType"))->valuestring : "";

					g_tConfig.chassislist.insert(std::pair<std::string, CHASSIS>(name, tchassis));
				}
			}
		}

	end:
		if (pdata)
			free(pdata);

		if (pJson)
			cJSON_Delete(pJson);
	}

	void SetConfig()
	{
		// Json数据;
		cJSON* pJson = cJSON_CreateObject();
		cJSON_AddStringToObject(pJson, "COM", g_tConfig.com.c_str());
		cJSON_AddStringToObject(pJson, "server-url", g_tConfig.serverurl.c_str());
		cJSON_AddStringToObject(pJson, "Chassis", g_tConfig.chassis.c_str());
		cJSON_AddNumberToObject(pJson, "Mode", g_tConfig.mode);
		cJSON_AddNumberToObject(pJson, "WarnCount", g_tConfig.warncount);
		cJSON_AddNumberToObject(pJson, "WaitBoot", g_tConfig.waitboot);
		cJSON_AddStringToObject(pJson, "Baudrate", g_tConfig.baudrate.c_str());

		// 频道;
		cJSON* pItem = NULL;
		cJSON* pChannel = cJSON_AddArrayToObject(pJson, _T("Channel"));
		if (pChannel)
		{
			std::map<std::string, std::string>::iterator it = g_tConfig.channel.begin();
			for (; it != g_tConfig.channel.end(); it++)
			{
				pItem = cJSON_AddObjectToObject(pChannel, it->first.c_str());
				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
			}
		}

		// 语言;
		cJSON* pLanguage = cJSON_AddArrayToObject(pJson, _T("Language"));
		if (pLanguage)
		{
			std::map<std::string, std::string>::iterator it = g_tConfig.language.begin();
			for (; it != g_tConfig.language.end(); it++)
			{
				pItem = cJSON_AddObjectToObject(pLanguage, it->first.c_str());
				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
			}
		}

		// 文件夹;
		cJSON* pKeyFolder = cJSON_AddArrayToObject(pJson, _T("KeyFolder"));
		if (pKeyFolder)
		{
			std::map<std::string, std::string>::iterator it = g_tConfig.keyfolder.begin();
			for (; it != g_tConfig.keyfolder.end(); it++)
			{
				pItem = cJSON_AddObjectToObject(pKeyFolder, it->first.c_str());
				cJSON_AddStringToObject(pItem, it->first.c_str(), it->second.c_str());
			}
		}

		// read check;
		cJSON* pReadCheck = cJSON_AddObjectToObject(pJson, "ReadCheck");
		if (pReadCheck)
		{
			cJSON_AddBoolToObject(pReadCheck, _T("PID"), g_tConfig.readcheck.IsPID);
			cJSON_AddBoolToObject(pReadCheck, _T("CHANNEL"), g_tConfig.readcheck.IsCHANNEL);
			cJSON_AddBoolToObject(pReadCheck, _T("OSD"), g_tConfig.readcheck.IsOSD);
			cJSON_AddBoolToObject(pReadCheck, _T("SHOP"), g_tConfig.readcheck.IsSHOP);
			cJSON_AddBoolToObject(pReadCheck, _T("DID"), g_tConfig.readcheck.IsDID);
			cJSON_AddBoolToObject(pReadCheck, _T("MAC"), g_tConfig.readcheck.IsMAC);
			cJSON_AddBoolToObject(pReadCheck, _T("HDCP"), g_tConfig.readcheck.IsHDCP);
			cJSON_AddBoolToObject(pReadCheck, _T("HDCP22"), g_tConfig.readcheck.IsHDCP22);
			cJSON_AddBoolToObject(pReadCheck, _T("WIDI"), g_tConfig.readcheck.IsWIDI);
			cJSON_AddBoolToObject(pReadCheck, _T("WIDEVINE"), g_tConfig.readcheck.IsWIDEVINE);
			cJSON_AddBoolToObject(pReadCheck, _T("ESN"), g_tConfig.readcheck.IsESN);
			cJSON_AddBoolToObject(pReadCheck, _T("CI"), g_tConfig.readcheck.IsCI);
		}
#ifdef SUPER_VER
		// write check;
		cJSON* pWriteCheck = cJSON_AddObjectToObject(pJson, "WriteCheck");
		if (pWriteCheck)
		{
			//cJSON_AddBoolToObject(pWriteCheck, _T("PID"), g_tConfig.writecheck.IsPID);
			//cJSON_AddBoolToObject(pWriteCheck, _T("CHANNEL"), g_tConfig.writecheck.IsCHANNEL);
			//cJSON_AddBoolToObject(pWriteCheck, _T("OSD"), g_tConfig.writecheck.IsOSD);
			//cJSON_AddBoolToObject(pWriteCheck, _T("SHOP"), g_tConfig.writecheck.IsSHOP);
			cJSON_AddBoolToObject(pWriteCheck, _T("DID"), g_tConfig.writecheck.IsDID);
			cJSON_AddBoolToObject(pWriteCheck, _T("MAC"), g_tConfig.writecheck.IsMAC);
			cJSON_AddBoolToObject(pWriteCheck, _T("HDCP"), g_tConfig.writecheck.IsHDCP);
			cJSON_AddBoolToObject(pWriteCheck, _T("HDCP22"), g_tConfig.writecheck.IsHDCP22);
			cJSON_AddBoolToObject(pWriteCheck, _T("WIDI"), g_tConfig.writecheck.IsWIDI);
			cJSON_AddBoolToObject(pWriteCheck, _T("WIDEVINE"), g_tConfig.writecheck.IsWIDEVINE);
			cJSON_AddBoolToObject(pWriteCheck, _T("ESN"), g_tConfig.writecheck.IsESN);
			cJSON_AddBoolToObject(pWriteCheck, _T("CI"), g_tConfig.writecheck.IsCI);
		}

		// write done;
		cJSON* pWriteDone= cJSON_AddObjectToObject(pJson, "WriteDone");
		if (pWriteDone)
		{
			cJSON_AddBoolToObject(pWriteDone, _T("PID"), g_tConfig.writedone.IsPID);
			cJSON_AddBoolToObject(pWriteDone, _T("CHANNEL"), g_tConfig.writedone.IsCHANNEL);
			cJSON_AddBoolToObject(pWriteDone, _T("OSD"), g_tConfig.writedone.IsOSD);
			cJSON_AddBoolToObject(pWriteDone, _T("SHOP"), g_tConfig.writedone.IsSHOP);
			cJSON_AddBoolToObject(pWriteDone, _T("DID"), g_tConfig.writedone.IsDID);
			cJSON_AddBoolToObject(pWriteDone, _T("MAC"), g_tConfig.writedone.IsMAC);
			cJSON_AddBoolToObject(pWriteDone, _T("HDCP"), g_tConfig.writedone.IsHDCP);
			cJSON_AddBoolToObject(pWriteDone, _T("HDCP22"), g_tConfig.writedone.IsHDCP22);
			cJSON_AddBoolToObject(pWriteDone, _T("WIDI"), g_tConfig.writedone.IsWIDI);
			cJSON_AddBoolToObject(pWriteDone, _T("WIDEVINE"), g_tConfig.writedone.IsWIDEVINE);
			cJSON_AddBoolToObject(pWriteDone, _T("ESN"), g_tConfig.writedone.IsESN);
			cJSON_AddBoolToObject(pWriteDone, _T("CI"), g_tConfig.writedone.IsCI);
		}
#endif
		// 配置;
		cJSON* pChassis = cJSON_AddArrayToObject(pJson, _T("Chassis-list"));
		if (pChassis)
		{
			std::map<std::string, TChassis>::iterator it = g_tConfig.chassislist.begin();
			for (; it != g_tConfig.chassislist.end(); it++)
			{
				pItem = cJSON_AddObjectToObject(pChassis, it->first.c_str());
				cJSON_AddStringToObject(pItem, _T("name"), it->first.c_str());
				// bool
				cJSON_AddBoolToObject(pItem, _T("IsCopyDID"), it->second.IsCopyDID);
				cJSON_AddBoolToObject(pItem, _T("IsCopyMAC"), it->second.IsCopyMAC);
				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY"), it->second.IsCopyKEY);
				cJSON_AddBoolToObject(pItem, _T("IsCopyESN"), it->second.IsCopyESN);
				cJSON_AddBoolToObject(pItem, _T("IsCopyWiDi"), it->second.IsCopyWiDi);
				cJSON_AddBoolToObject(pItem, _T("IsCopyWidevine"), it->second.IsCopyWidevine);
				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY2_2"), it->second.IsCopyKEY2_2);
				cJSON_AddBoolToObject(pItem, _T("IsCopyKEY2_3"), it->second.IsCopyKEY2_3);
				cJSON_AddBoolToObject(pItem, _T("IsCopyCikey"), it->second.IsCopyCikey);
				cJSON_AddBoolToObject(pItem, _T("IsCopyChannel"), it->second.IsCopyChannel);
				cJSON_AddBoolToObject(pItem, _T("IsCopyWB"), it->second.IsCopyWB);
				cJSON_AddBoolToObject(pItem, _T("IsDisplayClientType"), it->second.IsDisplayClientType);
				cJSON_AddBoolToObject(pItem, _T("IsWritePID"), it->second.IsWritePID);
				cJSON_AddBoolToObject(pItem, _T("IsWBInit"), it->second.IsWBInit);
				cJSON_AddBoolToObject(pItem, _T("IsMTKInit"), it->second.IsMTKInit);
				cJSON_AddBoolToObject(pItem, _T("IsOsdLanguage"), it->second.IsOsdLanguage);
				cJSON_AddBoolToObject(pItem, _T("IsShopLanguage"), it->second.IsShopLanguage);
				cJSON_AddBoolToObject(pItem, _T("IsCopyClientType"), it->second.IsCopyClientType);
				cJSON_AddBoolToObject(pItem, _T("IsMGKKeyEnb"), it->second.IsMGKKeyEnb);
				cJSON_AddBoolToObject(pItem, _T("IsNovaTakHDCPEnb"), it->second.IsNovaTakHDCPEnb);
				// ini
				cJSON_AddNumberToObject(pItem, _T("ProjectID"), it->second.ProjectID);
				cJSON_AddNumberToObject(pItem, _T("Delay"), it->second.Delay);
				// string
				cJSON_AddStringToObject(pItem, _T("Channel"), it->second.Channel.c_str());
				cJSON_AddStringToObject(pItem, _T("WBFile"), it->second.WBFile.c_str());
				cJSON_AddStringToObject(pItem, _T("CheckString"), it->second.CheckString.c_str());
				cJSON_AddStringToObject(pItem, _T("ClientType"), it->second.ClientType.c_str());
				cJSON_AddStringToObject(pItem, _T("MACType"), it->second.MACType.c_str());
				cJSON_AddStringToObject(pItem, _T("HDCPKeyType"), it->second.HDCPKeyType.c_str());
				cJSON_AddStringToObject(pItem, _T("HDCPKey22Type"), it->second.HDCPKey22Type.c_str());
				cJSON_AddStringToObject(pItem, _T("HDCPKey23Type"), it->second.HDCPKey23Type.c_str());
				cJSON_AddStringToObject(pItem, _T("ESNType"), it->second.ESNType.c_str());
				cJSON_AddStringToObject(pItem, _T("WiDiType"), it->second.WiDiType.c_str());
				cJSON_AddStringToObject(pItem, _T("WidevineType"), it->second.WidevineType.c_str());
				cJSON_AddStringToObject(pItem, _T("CIKeyType"), it->second.CIKeyType.c_str());
				cJSON_AddStringToObject(pItem, _T("MGKKeyType"), it->second.MGKKeyType.c_str());
				cJSON_AddStringToObject(pItem, _T("NovaTakHDCPType"), it->second.NovaTakHDCPType.c_str());
			}
		}

		char* pJsonText = cJSON_Print(pJson);

		// 保存到文件中;
		FILE* pf = NULL;
		_tfopen_s(&pf, _T("./Config.json"), _T("wb"));
		if (pf)
		{
			fwrite(pJsonText, _tcslen(pJsonText), 1, pf);
			fclose(pf);
		}

		if (pJsonText)
			delete[] pJsonText;
		cJSON_Delete(pJson);
	}

	// 去除空格;
	std::string& trim(std::string& str)
	{
		int nIndex = 0;
		while ((nIndex = str.find_first_of(' ')) != std::string::npos)
			str.erase(nIndex, 1);

		return str;
	}

	// hModule 模块句柄 NULL表示当前模块;
	bool GetVersion(IN const TCHAR* fname, OUT WORD* pdwFileVersion, OUT WORD* pdwProductVerion)
	{
		VS_FIXEDFILEINFO* pVi = NULL;
		DWORD dwHandle = 0;
		int size = GetFileVersionInfoSize(fname, &dwHandle);
		if (size > 0)
		{
			BYTE* buffer = new BYTE[size];
			memset(buffer, 0, size);

			if (GetFileVersionInfo(fname, 0, size, buffer))
			{
				if (VerQueryValue(buffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& size))
				{
					pdwFileVersion[0] = HIWORD(pVi->dwFileVersionMS);
					pdwFileVersion[1] = LOWORD(pVi->dwFileVersionMS);
					pdwFileVersion[2] = HIWORD(pVi->dwFileVersionLS);
					pdwFileVersion[3] = LOWORD(pVi->dwFileVersionLS);

					pdwProductVerion[0] = HIWORD(pVi->dwProductVersionMS);
					pdwProductVerion[1] = LOWORD(pVi->dwProductVersionMS);
					pdwProductVerion[2] = HIWORD(pVi->dwProductVersionLS);
					pdwProductVerion[3] = LOWORD(pVi->dwProductVersionLS);

					delete[] buffer;
					return true;
				}
			}

			delete[] buffer;
		}

		return false;
	}

	BOOL GetVersion(IN HMODULE hModule, OUT DWORD(&dwFVArray)[4], OUT DWORD(&dwPVArray)[4])
	{
		TCHAR fname[MAX_PATH];
		VS_FIXEDFILEINFO* pVi;
		DWORD dwHandle;

		if (GetModuleFileName(hModule, fname, MAX_PATH))
		{
			INT nSize = GetFileVersionInfoSize(fname, &dwHandle);

			if (nSize > 0)
			{
				BYTE* pBuffer = new BYTE[nSize];
				memset(pBuffer, 0, nSize);

				if (GetFileVersionInfo(fname, 0, nSize, pBuffer))
				{
					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID*)& pVi, (PUINT)& nSize))
					{
						dwFVArray[0] = HIWORD(pVi->dwFileVersionMS);
						dwFVArray[1] = LOWORD(pVi->dwFileVersionMS);
						dwFVArray[2] = HIWORD(pVi->dwFileVersionLS);
						dwFVArray[3] = LOWORD(pVi->dwFileVersionLS);

						dwPVArray[0] = HIWORD(pVi->dwProductVersionMS);
						dwPVArray[1] = LOWORD(pVi->dwProductVersionMS);
						dwPVArray[2] = HIWORD(pVi->dwProductVersionLS);
						dwPVArray[3] = LOWORD(pVi->dwProductVersionLS);

						delete[]pBuffer;
						return TRUE;
					}
				}

				if (pBuffer)
					delete[]pBuffer;
			}
		}

		return FALSE;
	}

	WCHAR* ASCII2UNICODE(IN LPCCH lpASCIIStr)
	{
		if (lpASCIIStr == NULL)
			return NULL;

		// 获取宽字符字节数;
		int cchWideChar = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, NULL, 0);
		if (cchWideChar == 0)
			return NULL;

		// 转换成宽字符串;
		WCHAR* pWideChar = new WCHAR[cchWideChar + 1];
		memset(pWideChar, 0, sizeof(WCHAR) * (cchWideChar + 1));
		int nWriteNum = MultiByteToWideChar(CP_ACP, 0, lpASCIIStr, -1, pWideChar, cchWideChar);
		if (nWriteNum != cchWideChar)
		{
			if (pWideChar)
				delete[] pWideChar;
			return NULL;
		}

		return pWideChar;
	}

	BOOL UNICODE2UTF8(IN LPWCH lpUNICODEStr, OUT std::string& strResult)
	{
		if (lpUNICODEStr == NULL)
			return FALSE;

		// 获取多字节字符字节数;
		int cbMultiByte = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
		if (cbMultiByte == 0)
			return FALSE;

		// 转换成多字节字符;
		CHAR* pResult = new CHAR[cbMultiByte];
		memset(pResult, 0, cbMultiByte);
		int nWriteNum = WideCharToMultiByte(CP_UTF8, 0, lpUNICODEStr, -1, pResult, cbMultiByte, NULL, NULL);
		if (nWriteNum != cbMultiByte)
			return FALSE;

		strResult = pResult;
		if (pResult)
			delete[] pResult;

		return TRUE;
	}

	BOOL ASCII2UTF8(IN LPCCH lpASCIIStr, OUT std::string& strResult)
	{
		// 将ASCII字符串转成UNICODE字符串;
		WCHAR* pWideChar = ASCII2UNICODE(lpASCIIStr);
		if (pWideChar == NULL)
			return FALSE;

		// 再将UICODE转成UTF8;
		BOOL bResult = UNICODE2UTF8(pWideChar, strResult);

		if (pWideChar)
			delete[] pWideChar;

		return bResult;
	}

	std::string EnCode_UTF8URL(IN const CHAR* pText)
	{
		std::string tt = "";
		std::string dd = "";
		ASCII2UTF8(pText, tt);

		size_t len = tt.length();
		for (size_t i = 0; i < len; i++)
		{
			if (isalnum((BYTE)tt.at(i)))
			{
				char tempbuff[2] = { 0 };
				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
				dd.append(tempbuff);
			}
			else if (isspace((BYTE)tt.at(i)))
			{
				dd.append("+");
			}
			else
			{
				char tempbuff[4];
				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
				dd.append(tempbuff);
			}
		}
		return dd;
	}

	void EnCode_UTF8URL(IN const CHAR* pText, OUT std::string& strResult)
	{
		std::string tt = "";
		ASCII2UTF8(pText, tt);

		size_t len = tt.length();
		for (size_t i = 0; i < len; i++)
		{
			if (isalnum((BYTE)tt.at(i)))
			{
				char tempbuff[2] = { 0 };
				sprintf_s(tempbuff, "%c", (BYTE)tt.at(i));
				strResult.append(tempbuff);
			}
			else if (isspace((BYTE)tt.at(i)))
			{
				strResult.append("+");
			}
			else
			{
				char tempbuff[4];
				sprintf_s(tempbuff, "%%%X%X", ((BYTE)tt.at(i)) >> 4, ((BYTE)tt.at(i)) % 16);
				strResult.append(tempbuff);
			}
		}
	}

	// 通过注册表查找系统当前串口信息;
	BOOL GetSysSerialPort(std::vector<std::string>& vtports)
	{
		HKEY hKey;
		LSTATUS lReg = 0;
		DWORD dwMaxValLen = 0;
		DWORD dwValNum = 0;
		lReg = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "HARDWARE\\DEVICEMAP\\SERIALCOMM", 0, KEY_QUERY_VALUE, &hKey);
		if (lReg != ERROR_SUCCESS)
		{
			//LOG4C((LOG_WARN, "Open Registry Error"));
			return FALSE;
		}

		lReg = RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValNum, &dwMaxValLen, NULL, NULL, NULL);
		if (lReg != ERROR_SUCCESS)
		{
			//LOG4C((LOG_WARN, "Getting Key Info Error"));
			return FALSE;
		}

		if (vtports.size())
		{
			vtports.clear();
		}

		LPSTR lpValName, lpComNum;
		DWORD dwValName, dwValSize = 6;
		for (DWORD i = 0; i < dwValNum; i++)
		{
			dwValName = dwMaxValLen + 1;
			dwValSize = 6;
			lpValName = (LPSTR)VirtualAlloc(NULL, dwValName, MEM_COMMIT, PAGE_READWRITE);
			lReg = RegEnumValueA(hKey, i, lpValName, &dwValName, NULL, NULL, NULL, NULL);
			if ((lReg != ERROR_SUCCESS) && (lReg != ERROR_NO_MORE_ITEMS))
			{
				//LOG4C((LOG_WARN, "Enum  Registry  Error or No More Items"));
				continue;
			}
			lpComNum = (LPSTR)VirtualAlloc(NULL, 6, MEM_COMMIT, PAGE_READWRITE);
			lReg = RegQueryValueExA(hKey, lpValName, NULL, NULL, (LPBYTE)lpComNum, &dwValSize);
			if (lReg != ERROR_SUCCESS)
			{
				//LOG4C((LOG_WARN, "Can not get the name of the port"));
				continue;
			}

			vtports.push_back(lpComNum);
			VirtualFree(lpValName, 0, MEM_RELEASE);
			VirtualFree(lpComNum, 0, MEM_RELEASE);
		}

		return TRUE;
	}

	INT GetMacAddress()
	{
		HDEVINFO hDevInfo;
		DWORD MemberIndex, RequiredSize;
		SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
		PSP_DEVICE_INTERFACE_DETAIL_DATA DeviceInterfaceDetailData;
		INT nTotal = 0;
		INT nNICKind = 0;

		// 获取设备信息集;
		hDevInfo = SetupDiGetClassDevs(&MacClassGuid, NULL, NULL, DIGCF_PRESENT | DIGCF_INTERFACEDEVICE);
		if (hDevInfo == INVALID_HANDLE_VALUE)
		{
			return -1;
		}

		g_vtMac.clear();
		// 枚举设备信息集中所有设备;
		DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
		for (MemberIndex = 0; SetupDiEnumDeviceInterfaces(hDevInfo, NULL, &MacClassGuid, MemberIndex, &DeviceInterfaceData); MemberIndex++)
		{
			// 获取接收缓冲区大小，函数返回值为FALSE，GetLastError()=ERROR_INSUFFICIENT_BUFFER;
			SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, NULL, 0, &RequiredSize, NULL);

			// 申请接收缓冲区;
			DeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
			DeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

			// 获取设备细节信息;
			if (SetupDiGetDeviceInterfaceDetail(hDevInfo, &DeviceInterfaceData, DeviceInterfaceDetailData, RequiredSize, NULL, NULL))
			{
				HANDLE hDeviceFile;
				BOOL isOK = FALSE;
				if (_tcsnicmp(DeviceInterfaceDetailData->DevicePath + 4, TEXT("pci"), 3) != 0)
				{
					free(DeviceInterfaceDetailData);
					DeviceInterfaceDetailData = NULL;
					continue;
				}

				MacAddress tagMacAddress;
				tagMacAddress.nNICKind = NIC_PCI;
				_stprintf_s(tagMacAddress.szNICKind, _T("%s"), _T("NIC_PCI"));

				// 获取设备句柄;
				hDeviceFile = CreateFile(DeviceInterfaceDetailData->DevicePath,
					0,
					FILE_SHARE_READ | FILE_SHARE_WRITE,
					NULL,
					OPEN_EXISTING,
					0,
					NULL);

				if (hDeviceFile != INVALID_HANDLE_VALUE)
				{
					ULONG dwID;
					BYTE ucData[8];
					DWORD dwByteRet;

					// 获取原生MAC地址;
					dwID = OID_802_3_PERMANENT_ADDRESS;
					isOK = DeviceIoControl(hDeviceFile, IOCTL_NDIS_QUERY_GLOBAL_STATS, &dwID, sizeof(dwID), ucData, sizeof(ucData), &dwByteRet, NULL);
					if (isOK)
					{
						++nTotal;
						_stprintf_s(tagMacAddress.szDevicePath, _T("%s"), DeviceInterfaceDetailData->DevicePath);
						memset(tagMacAddress.szMacAddress, 0, sizeof(TCHAR) * MAX_PATH);
						// 将字节数组转换成16进制字符串;
						for (DWORD i = 0; i < dwByteRet; i++)
						{
							_stprintf_s(&tagMacAddress.szMacAddress[i * 3], MAX_PATH - (i * 3), (i != dwByteRet - 1) ? _T("%02X-") : _T("%02X"), ucData[i]);
						}

						g_vtMac.push_back(tagMacAddress);
					}
					CloseHandle(hDeviceFile);
				}
			}

			free(DeviceInterfaceDetailData);
			DeviceInterfaceDetailData = NULL;
		}

		SetupDiDestroyDeviceInfoList(hDevInfo);

#if 1
		g_strMacs.clear();
		std::vector<MacAddress>::iterator it = g_vtMac.begin();
		for (; it != g_vtMac.end(); it++)
		{
			g_strMacs.append(it->szMacAddress);
			g_strMacs.append("&");
		}
#endif

		return nTotal;
	}

	BOOL IsValidString(LPCTSTR lpszString)
	{
		if (lpszString == NULL)
			return FALSE;

		do
		{
			// ASCII可显示的字符;
			if (*lpszString < 32 || *lpszString > 126)
			{
				return FALSE;
			}
		} while (*++lpszString);

		return TRUE;
	}
} // namespace Global