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

namespace Global
{
	//////////////////////////////////////////////////////////////////////////
	// ȫ�ֱ���;
	TCHAR g_szCurModuleDir[MAX_PATH] = { 0 };
	TCHAR g_szCurModulePath[MAX_PATH] = { 0 };
	TCHAR g_szFna[MAX_PATH] = { 0 };
	TCHAR g_szConfig[MAX_PATH] = { 0 };
	TCHAR g_szLogPath[MAX_PATH] = { 0 };
	bool g_bEnableLog = false;
	time_t g_time = time(NULL);
	
	//////////////////////////////////////////////////////////////////////////
	void MKDIR(LPCTSTR dir) 
	{
		//////////////////////////////////////////////////////////////////////////
		// ����Ŀ¼;
		int nleft = 0;
		int nIndex = -1;
		string strdir = dir;
		strdir = strdir.substr(0, strdir.find_last_of(_T("\\")));

		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 != string::npos)
			{
				if (_mkdir(strdir.substr(0, nIndex + nleft).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("%sredratlog %02d%02d.txt"), g_szCurModuleDir, gmtm.tm_mon + 1, gmtm.tm_mday);
		// �򿪻򴴽��ļ�;
		FILE* fp = NULL;
		MKDIR(szlogpath);
		//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 WritePythonLog(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;
		MKDIR(g_szLogPath);
		//if (_taccess(szlogpath, 0) != -1)
#ifndef UNICODE
		if (_access(g_szLogPath, 0) != -1)
#else
		if (_taccess(g_szLogPath, 0) != -1)
#endif
		{ // ����;
			if (0 == _tfopen_s(&fp, g_szLogPath, _T("a+")))
				// �ƶ���ĩβ;
				fseek(fp, 0, SEEK_END);
		}
		else
		{ // ������;
			_tfopen_s(&fp, g_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); //��ԭ�����趨;
	}

	// ȥ���ո�;
	std::string& trim(std::string& str)
	{
		int nIndex = 0;
		while ((nIndex = str.find_first_of(' ')) != std::string::npos)
			str.erase(nIndex, 1);

		return str;
	}

	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);
		SetCurrentDirectory(g_szCurModulePath);
	}

	// 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 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 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;
	}

	string EnCode_UTF8URL(IN const CHAR* pText)
	{
		string tt = "";
		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 string& strResult)
	{
		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);
			}
		}
	}

	//��Ϊ��Urlʹ��
	char CharToInt(char ch)
	{
		if (ch >= '0' && ch <= '9')return (char)(ch - '0');
		if (ch >= 'a' && ch <= 'f')return (char)(ch - 'a' + 10);
		if (ch >= 'A' && ch <= 'F')return (char)(ch - 'A' + 10);
		return -1;
	}

	char StrToBin(IN char(&str)[2])
	{
		char tempWord[2];
		char chn;

		tempWord[0] = CharToInt(str[0]);                         //make the B to 11 -- 00001011
		tempWord[1] = CharToInt(str[1]);                         //make the 0 to 0  -- 00000000

		chn = (tempWord[0] << 4) | tempWord[1];                //to change the BO to 10110000

		return chn;
	}

	CHAR* UNICODE2ASCII(IN LPWCH lpUNICODEStr)
	{
		if (lpUNICODEStr == NULL)
			return NULL;

		// ��ȡ���ֽ��ַ��ֽ���;
		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
		if (cbMultiByte == 0)
			return NULL;

		// ת���ɶ��ֽ��ַ�;
		CHAR *pMultiByteStr = new CHAR[cbMultiByte + 1];
		memset(pMultiByteStr, 0, cbMultiByte + 1);
		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pMultiByteStr, cbMultiByte, NULL, NULL);
		if (nWriteNum != cbMultiByte)
		{
			if (pMultiByteStr)
				delete[]pMultiByteStr;
			return NULL;
		}

		pMultiByteStr[cbMultiByte] = '\0';

		return pMultiByteStr;
	}

	BOOL UNICODE2ASCII(IN LPWCH lpUNICODEStr, OUT LPCH pASCIIStr, IN CONST INT& nASCIIStrLen)
	{
		if (lpUNICODEStr == NULL)
			return FALSE;

		// ��ȡ���ֽ��ַ��ֽ���;
		int cbMultiByte = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, NULL, 0, NULL, NULL);
		if (cbMultiByte == 0 || cbMultiByte >= nASCIIStrLen)
			return FALSE;

		// ת���ɶ��ֽ��ַ�;
		memset((void*)pASCIIStr, 0, nASCIIStrLen);
		int nWriteNum = WideCharToMultiByte(CP_OEMCP, 0, lpUNICODEStr, -1, pASCIIStr, cbMultiByte, NULL, NULL);
		if (nWriteNum != cbMultiByte)
		{
			return FALSE;
		}

		return TRUE;
	}

	/************************************************************************/
	/*  ������[7/26/2016 IT];
	/*  ������;
	/*  ������;
	/*  	[IN] ��;
	/*  	[OUT] ��;
	/*  	[IN/OUT] ��;
	/*  ���أ�void;
	/*  ע�⣺;
	/*  ʾ����;
	/*
	/*  �޸ģ�;
	/*  ���ڣ�;
	/*  ���ݣ�;
	/************************************************************************/
	string DeCode_URLUNICODE(IN const CHAR* pURLText)
	{
		string str = pURLText;
		string strResult = "";

		INT nIndex = 0;
		string strTemp = "";

		while (str.find("\\u", 0, 2) != string::npos)
		{
			nIndex = str.find("\\u", 0, 2);
			strResult.append(str.substr(0, nIndex));
			strTemp = str.substr(nIndex + 2, 4);
			str = str.substr(nIndex + 2 + 4);
			CHAR szReturn[10] = { 0 };

			union  __UNION_VAR_INT {
				BYTE   ch[2];
				int	   value;
			}unionVarInt;

			unionVarInt.ch[0] = (CharToInt(strTemp.at(2)) << 4) | (CharToInt(strTemp.at(3)) & 0x00FF);
			unionVarInt.ch[1] = (CharToInt(strTemp.at(0)) << 4) | (CharToInt(strTemp.at(1)) & 0x00FF);

			WCHAR szWide[2] = { 0 };
			szWide[0] = unionVarInt.value;
			UNICODE2ASCII(szWide, szReturn, 10);
			strResult.append(szReturn);
		}
		strResult.append(str);

		return strResult;
	}

	// ͨ��ע�������ϵͳ��ǰ������Ϣ;
	
	BOOL IsValidString(LPCTSTR lpszString)
	{
		if (lpszString == NULL)
			return FALSE;

		do
		{
			// ASCII����ʾ���ַ�;
			if (*lpszString < 32 || *lpszString > 126)
			{
				return FALSE;
			}
		} while (*++lpszString);

		return TRUE;
	}
} // namespace Global