#pragma once

#include "stdafx.h"
#include "Global.h"

#include <tlhelp32.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <WinVer.h>		
#pragma comment(lib,"version.lib")

namespace Global
{
	//////////////////////////////////////////////////////////////////////////
	// 全局变量;
	TCHAR g_szIniFile[MAX_PATH] = {0};
	TCHAR g_szHostName[MAX_PATH] = {0};			// 主机计算机名;
	TCHAR g_szModulePath[MAX_PATH];				// 软件目录;
	TCHAR g_szModuleFileName[MAX_PATH];			// 软件名称;
	TCHAR g_szConnectString[MAX_PATH];			// DB连接串;
	TCHAR g_szBranchId[MAX_PATH];				// 本店加密锁域名;

	// 服务器信息;
	TCHAR g_szDBSource[MAX_PATH];				// 数据库源(服务所在IP或计算机名);
	TCHAR g_szDBSourcePort[MAX_PATH];			// 数据库源端口;
	DWORD g_dwDBServerPort;						// 数据库源端口;
	TCHAR g_szDBAccount[MAX_PATH];				// 数据库登录用户;
	TCHAR g_szDBPassWord[MAX_PATH];				// 数据库登录密码;
	TCHAR g_szDBName[MAX_PATH];					// 数据库名称;	
	TCHAR g_szDBType[MAX_PATH];					// 数据库类型：mysql、mssql、psql、sqlite3
	DWORD g_dwDBPoolMaxCount = 1;						// 数据库连接池最大对象数;
	DWORD g_dwDBPoolDef = 1;							// 数据库连接池默认对象数;

	//////////////////////////////////////////////////////////////////////////
	static const int BEGIN_YEAR = 1901;
	static const int NUMBER_YEAR = 199;
	static const unsigned int LUNAR_YEARS[199] =
	{
		0x04AE53, 0x0A5748, 0x5526BD, 0x0D2650, 0x0D9544, 0x46AAB9, 0x056A4D, 0x09AD42, 0x24AEB6, 0x04AE4A, //1901-1910
		0x6A4DBE, 0x0A4D52, 0x0D2546, 0x5D52BA, 0x0B544E, 0x0D6A43, 0x296D37, 0x095B4B, 0x749BC1, 0x049754, //1911-1920
		0x0A4B48, 0x5B25BC, 0x06A550, 0x06D445, 0x4ADAB8, 0x02B64D, 0x095742, 0x2497B7, 0x04974A, 0x664B3E, //1921-1930
		0x0D4A51, 0x0EA546, 0x56D4BA, 0x05AD4E, 0x02B644, 0x393738, 0x092E4B, 0x7C96BF, 0x0C9553, 0x0D4A48, //1931-1940
		0x6DA53B, 0x0B554F, 0x056A45, 0x4AADB9, 0x025D4D, 0x092D42, 0x2C95B6, 0x0A954A, 0x7B4ABD, 0x06CA51, //1941-1950
		0x0B5546, 0x555ABB, 0x04DA4E, 0x0A5B43, 0x352BB8, 0x052B4C, 0x8A953F, 0x0E9552, 0x06AA48, 0x7AD53C, //1951-1960
		0x0AB54F, 0x04B645, 0x4A5739, 0x0A574D, 0x052642, 0x3E9335, 0x0D9549, 0x75AABE, 0x056A51, 0x096D46, //1961-1970
		0x54AEBB, 0x04AD4F, 0x0A4D43, 0x4D26B7, 0x0D254B, 0x8D52BF, 0x0B5452, 0x0B6A47, 0x696D3C, 0x095B50, //1971-1980
		0x049B45, 0x4A4BB9, 0x0A4B4D, 0xAB25C2, 0x06A554, 0x06D449, 0x6ADA3D, 0x0AB651, 0x093746, 0x5497BB, //1981-1990
		0x04974F, 0x064B44, 0x36A537, 0x0EA54A, 0x86B2BF, 0x05AC53, 0x0AB647, 0x5936BC, 0x092E50, 0x0C9645, //1991-2000
		0x4D4AB8, 0x0D4A4C, 0x0DA541, 0x25AAB6, 0x056A49, 0x7AADBD, 0x025D52, 0x092D47, 0x5C95BA, 0x0A954E, //2001-2010
		0x0B4A43, 0x4B5537, 0x0AD54A, 0x955ABF, 0x04BA53, 0x0A5B48, 0x652BBC, 0x052B50, 0x0A9345, 0x474AB9, //2011-2020
		0x06AA4C, 0x0AD541, 0x24DAB6, 0x04B64A, 0x69573D, 0x0A4E51, 0x0D2646, 0x5E933A, 0x0D534D, 0x05AA43, //2021-2030
		0x36B537, 0x096D4B, 0xB4AEBF, 0x04AD53, 0x0A4D48, 0x6D25BC, 0x0D254F, 0x0D5244, 0x5DAA38, 0x0B5A4C, //2031-2040
		0x056D41, 0x24ADB6, 0x049B4A, 0x7A4BBE, 0x0A4B51, 0x0AA546, 0x5B52BA, 0x06D24E, 0x0ADA42, 0x355B37, //2041-2050
		0x09374B, 0x8497C1, 0x049753, 0x064B48, 0x66A53C, 0x0EA54F, 0x06B244, 0x4AB638, 0x0AAE4C, 0x092E42, //2051-2060
		0x3C9735, 0x0C9649, 0x7D4ABD, 0x0D4A51, 0x0DA545, 0x55AABA, 0x056A4E, 0x0A6D43, 0x452EB7, 0x052D4B, //2061-2070
		0x8A95BF, 0x0A9553, 0x0B4A47, 0x6B553B, 0x0AD54F, 0x055A45, 0x4A5D38, 0x0A5B4C, 0x052B42, 0x3A93B6, //2071-2080
		0x069349, 0x7729BD, 0x06AA51, 0x0AD546, 0x54DABA, 0x04B64E, 0x0A5743, 0x452738, 0x0D264A, 0x8E933E, //2081-2090
		0x0D5252, 0x0DAA47, 0x66B53B, 0x056D4F, 0x04AE45, 0x4A4EB9, 0x0A4D4C, 0x0D1541, 0x2D92B5 //2091-2099
	};

	//////////////////////////////////////////////////////////////////////////
	BOOL IsValidDate(IN LPCTSTR lpDate)	// 判断公历;
	{
		if (lpDate == NULL || _tcscmp(lpDate, _T("")) == 0)
			return FALSE;

		CString strDate = lpDate;
		if (strDate.IsEmpty()) return FALSE;

		// 判断日期合法性;
		static int nYear = 0;
		static int nMonth = 0;
		static int nDay = 0;

		nYear = nMonth = nDay = 0;
		nYear = _ttoi(strDate.Left(4));

		nMonth = _ttoi(strDate.Mid(5, 2));
		nDay = _ttoi(strDate.Mid(8, 2));

		CONST static INT nNormalMonth[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		CONST static INT nLeapMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

		if ((nDay <= 0) || (nDay > 31) || (nMonth <= 0) || (nMonth > 12)) return FALSE;

		if ((nYear % 400 == 0) || (nYear % 4 == 0 && nYear % 100 != 0))
		{
			if (nDay > nLeapMonth[nMonth - 1])	return FALSE;
		}
		else
		{
			if (nDay > nNormalMonth[nMonth - 1]) return FALSE;
		}

		return TRUE;
	}

	BOOL IsValidLunanrDate(IN LPCTSTR lpDate)	// 判断农历;
	{
		if (lpDate == NULL || _tcscmp(lpDate, _T("")) == 0)
			return FALSE;

		CString strDate = lpDate;
		if (strDate.IsEmpty()) return FALSE;

		static int lunar_year, lunar_month, lunar_day;
		lunar_year = lunar_month = lunar_day = 0;

		lunar_year = _ttoi(strDate.Left(4));
		lunar_month = _ttoi(strDate.Mid(5, 2));
		lunar_day = _ttoi(strDate.Mid(8, 2));

		//越界检查，如果越界，返回无效日期;
		if (lunar_year <= BEGIN_YEAR || lunar_year > BEGIN_YEAR + NUMBER_YEAR - 1)
			return FALSE;

		if (lunar_month < 1 || lunar_month > 12)
			return FALSE;

		// 1.农历年是否有闰月;
		int nYearIndex = lunar_year - BEGIN_YEAR;
		int leap_month = (LUNAR_YEARS[nYearIndex] >> 20) & 0xF;

		// 2.月份大小月天数;
		int month_day = 0;
		if ((LUNAR_YEARS[nYearIndex] >> (7 + 13 - lunar_month)) & 0x1)
			month_day = 30;
		else
			month_day = 29;

		if (lunar_day < 0 || lunar_day > month_day)
			return FALSE;

		return TRUE;
	}

	int GetIniInfo(IN const TCHAR *szPath , const TCHAR *szIniName )
	{
		TCHAR szDrive[_MAX_DRIVE] = { 0 };
		TCHAR szDir[_MAX_DIR] = { 0 };
		TCHAR szFna[_MAX_DIR] = { 0 };
		TCHAR szExt[_MAX_DIR] = { 0 };
		DWORD dwRet = ::GetModuleFileName(NULL, g_szModuleFileName, sizeof(g_szModuleFileName) / sizeof(TCHAR));

		_tsplitpath_s(g_szModuleFileName, szDrive, szDir, szFna, szExt);
		StringCchCat(g_szModulePath, MAX_PATH, szDrive);
		StringCchCat(g_szModulePath, MAX_PATH, szDir);

		// -----------------------------------------------------//
		TCHAR szIniPath[MAX_PATH] = {0};
		if (szPath != NULL && szIniName != NULL)
			StringCchPrintf(szIniPath, MAX_PATH, _T("%s%s"), szPath, szIniName);
		else
			StringCchPrintf(szIniPath, MAX_PATH, _T("%sServiceInfo.ini"), g_szModulePath);

		HANDLE hFile = CreateFile(szIniPath, 0/*GENERIC_READ*/, 0, NULL, OPEN_EXISTING, 0, NULL);

		if (ERROR_FILE_NOT_FOUND == GetLastError())
		{
			return -1;
		}

		// 获取服务器端信息;
		//GetPrivateProfileString(_T("DatabaseInfo"), _T("dbSource"), _T(""), g_szDBSource, MAX_PATH, szIniPath);
		//g_dwDBServerPort = GetPrivateProfileInt(_T("DatabaseInfo"), _T("dbServerPort"), 0, szIniPath);
		//GetPrivateProfileString(_T("DatabaseInfo"), _T("dbAccount"), _T(""), g_szDBAccount, MAX_PATH, szIniPath);
		//GetPrivateProfileString(_T("DatabaseInfo"), _T("dbPassWord"), _T(""), g_szDBPassWord, MAX_PATH, szIniPath);
		//GetPrivateProfileString(_T("DatabaseInfo"), _T("dbName"), _T(""), g_szDBName, MAX_PATH, szIniPath);

		////g_dwCSPort = GetPrivateProfileInt(_T("NetWorkInfo"), _T("TCPChatPort"), 5678, szIniPath);

		//if (g_dwDBServerPort != 0)
		//	StringCchPrintf(g_szConnectString, MAX_PATH, _T("driver={SQL Server};Server=%s,%d;database=%s;uid=%s;pwd=%s"),
		//	g_szDBSource, g_dwDBServerPort, g_szDBName, g_szDBAccount, g_szDBPassWord);
		//else
		//	StringCchPrintf(g_szConnectString, MAX_PATH, _T("driver={SQL Server};Server=%s;database=%s;uid=%s;pwd=%s"),
		//	g_szDBSource, g_szDBName, g_szDBAccount, g_szDBPassWord);
		// 获取服务器端信息;
		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbSource"), _T(""), g_szDBSource, MAX_PATH, szIniPath);
		g_dwDBServerPort = GetPrivateProfileInt(_T("DatabaseInfo"), _T("dbServerPort"), 0, szIniPath);
		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbAccount"), _T(""), g_szDBAccount, MAX_PATH, szIniPath);
		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbPassWord"), _T(""), g_szDBPassWord, MAX_PATH, szIniPath);
		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbName"), _T(""), g_szDBName, MAX_PATH, szIniPath);

		GetPrivateProfileString(_T("DatabaseInfo"), _T("dbType"), _T("mssql"), g_szDBType, MAX_PATH, szIniPath);
		g_dwDBPoolMaxCount = GetPrivateProfileInt(_T("DatabaseInfo"), _T("dbpoolMaxObj"), 1, szIniPath);
		g_dwDBPoolDef = GetPrivateProfileInt(_T("DatabaseInfo"), _T("dbpoolDef"), 1, szIniPath);
		//g_dwSvrPort = GetPrivateProfileInt(_T("NetWorkInfo"), _T("TCPChatPort"), 0, szIniPath);
		if (g_dwDBServerPort != 0)
		{
			if (_tcscmp(g_szDBAccount, _T("")) == 0)
				_stprintf_s(g_szConnectString, DB_SW_CONN_WITH_PORT, g_szDBSource, g_dwDBServerPort, g_szDBName);
			else
				_stprintf_s(g_szConnectString, DB_SS_CONN_WITH_PORT, g_szDBSource, g_dwDBServerPort, g_szDBName, g_szDBAccount, g_szDBPassWord);

			_stprintf_s(g_szConnectString,
				_T("Provider=sqloledb;Data Source=%s,%ld;Initial Catalog=%s;User Id=%s;Password=%s; "),
				g_szDBSource,			// IP地址或服务名称;
				g_dwDBServerPort,
				g_szDBName,
				g_szDBAccount,
				g_szDBPassWord);
		}
		else
		{
			if (_tcscmp(g_szDBAccount, _T("")) == 0)
				_stprintf_s(g_szConnectString, DB_SW_CONN_WITHOUT_PORT, g_szDBSource, g_szDBName);
			else
				_stprintf_s(g_szConnectString, DB_SS_CONN_WITHOUT_PORT, g_szDBSource, g_szDBName, g_szDBAccount, g_szDBPassWord);

			_stprintf_s(g_szConnectString,
				_T("Provider=sqloledb;Data Source=%s;Initial Catalog=%s;User Id=%s;Password=%s; "),
				g_szDBSource,			// IP地址或服务名称;
				g_szDBName,
				g_szDBAccount,
				g_szDBPassWord);
		}

		return 0;
	}

	// 判断指定字符串是否在数组里（区分大小写）;
	BOOL IsStringExist(IN CString& str, IN CStringArray &tagAry)
	{
		int nSize = tagAry.GetSize();
		if (nSize == 0) return FALSE;

		BOOL bExist = FALSE;
		for (int i = 0; i < nSize; i++)
		{
			if (str == tagAry.ElementAt(i))
			{
				bExist = TRUE;
				break;
			}
		}

		return bExist;
	}

	// 判断指定字符串是否在数组里（区分大小写）;
	BOOL IsStringExist(IN TString& str, IN vector<TString> &tagVt)
	{
		int nSize = tagVt.size();
		if (nSize == 0) return FALSE;

		BOOL bExist = FALSE;
		for (vector<TString>::iterator it = tagVt.begin(); it != tagVt.end(); it++)
		{
			if (str.compare(it->c_str()) == 0)
			{
				bExist = TRUE;
				break;
			}
		}

		return bExist;
	}

	// 判断指定字符串是否在数组里（不区分大小写）;
	BOOL IsStringExistNoCase(IN CString& str, IN CStringArray &tagAry)
	{
		int nSize = tagAry.GetSize();
		if (nSize == 0) return FALSE;

		BOOL bExist = FALSE;
		for (int i = 0; i < nSize; i++)
		{
			if (str.CompareNoCase(tagAry.ElementAt(i)) == 0)
			{
				bExist = TRUE;
				break;
			}
		}

		return bExist;
	}

	BOOL IsStringExistNoCase(IN CONST TString& str, IN CStringArray &tagAry)
	{
		int nSize = tagAry.GetSize();
		if (nSize == 0) return FALSE;

		BOOL bExist = FALSE;
		for (int i = 0; i < nSize; i++)
		{
			if ((tagAry.ElementAt(i).CompareNoCase(str.c_str())) == 0)
			{
				bExist = TRUE;
				break;
			}
		}

		return bExist;
	}

	// 判断指定字符串是否在数组里（不区分大小写）;
	BOOL IsStringExistNoCase(IN CONST TString& str, IN vector<TString> &tagVt)
	{
		int nSize = tagVt.size();
		if (nSize == 0) return FALSE;

		BOOL bExist = FALSE;
		TString stmp1 = uppercase(str);
		TString stmp2;
		for (vector<TString>::iterator it = tagVt.begin(); it != tagVt.end(); it++)
		{
			stmp2 = uppercase(*it);
			if (stmp1.compare(stmp2) == 0)
			{
				bExist = TRUE;
				break;
			}
		}

		return bExist;
	}


	TString uppercase(IN const TString &Str)
	{
		const TCHAR aazz = _T('z') - _T('Z');
		TString sResult;
		for (TString::const_iterator it = Str.begin(); Str.end() != it; it++)
		{
			if (_T('a') <= *it && *it <= _T('z'))
				sResult.append(1, *it - aazz);
			else
				sResult.append(1, *it);
		}
		return sResult;
	}

	int match(IN CONST TString &sFileExt, IN CONST TString &sFile)
	{
		TString fext = uppercase(sFileExt);
		TString file = uppercase(sFile);

		int pos = file.find_last_of(_T('.'));
		if (TString::npos != pos)
			file = file.substr(pos);

		return (TString::npos != fext.find(file));
	}

	TString getfilename(IN CONST TString &file)
	{
		TString name;
		TString strfile = file;
		int nIndex = strfile.find_last_of(_T('\\'));	// 如果file不包含 '\\' ,得不到文件名;
		if (nIndex == TString::npos)
		{
			nIndex = strfile.find_last_of(_T('.'));
			if ( nIndex == TString::npos )
				return _T("");

			return strfile.substr(0, nIndex);
		}

		name = strfile.substr(nIndex+1);
		nIndex = name.find_last_of(_T('.'));
		if (nIndex == TString::npos)
			return _T("");

		return name.substr(0, nIndex);
	}

	// 获取文件名;
	CString getfilename(IN CONST CString &file)
	{
		CString name;
		CString strfile = file;
		int nIndex = strfile.ReverseFind(_T('\\'));	// 如果file不包含 '\\' ,得不到文件名;
		if (nIndex == -1)
		{
			nIndex = strfile.ReverseFind(_T('.'));
			if (nIndex == -1)
				return _T("");

			return strfile.Left(nIndex);
		}

		name = strfile.Mid(nIndex+1);
		nIndex = name.Find(_T('.'));
		if (nIndex == -1)
			return _T("");

		return name.Left(nIndex);
	}

	// 通过路径名查找进程,返回进程ID;
	BOOL FindAppProcessID(IN CString path, OUT DWORD &dwProcessID)
	{
		int nIndex = path.ReverseFind('\\');
		path = path.Right(path.GetLength() - nIndex - 1);
		dwProcessID = FindProcess(path);
		return (dwProcessID != 0 ? TRUE : FALSE);

		BOOL bFound = FALSE;

		HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
		if ( handle == NULL )
			return FALSE;

		PROCESSENTRY32 Info;
		Info.dwSize = sizeof(PROCESSENTRY32);
		path.MakeLower();
		if (::Process32First(handle, &Info))
		{
			do{
				CString ss = Info.szExeFile;
				ss.MakeLower();
				if (ss == path)
				{
					dwProcessID = Info.th32ProcessID;
					bFound = TRUE;
					break;
				}
			} while (::Process32Next(handle, &Info));
		}

		CloseHandle(handle);
		return (bFound ? TRUE : FALSE);
	}

	// 根据路径名查找进程,返回进程ID;
	DWORD FindProcess(IN CString strProName)
	{
		DWORD dwProcessID = 0;
		PROCESSENTRY32 pe32 = { 0 };

		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (hProcessSnap == NULL)
		{
			return 0;
		}
		pe32.dwSize = sizeof(PROCESSENTRY32);

		if (Process32First(hProcessSnap, &pe32))
		{
			do
			{
				if (_tcscmp(strProName.GetString(), pe32.szExeFile) == 0)
				{
					dwProcessID = pe32.th32ProcessID;
					break;
				}
			} while (Process32Next(hProcessSnap, &pe32));
		}
		CloseHandle(hProcessSnap);

		return dwProcessID;
	}

	DWORD FindProcessCount(IN LPCTSTR lpExeName)
	{
		DWORD dwCount = 0;
		if ( lpExeName && lpExeName[0] != _T('\0'))
		{
			PROCESSENTRY32 pe32 = { 0 };
			HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
			if (hProcessSnap == NULL) return 0;

			pe32.dwSize = sizeof(PROCESSENTRY32);
			if ( !Process32First(hProcessSnap, &pe32) )
			{
				CloseHandle(hProcessSnap);
				return 0;
			}

			do
			{
				if (_tcscmp(lpExeName, pe32.szExeFile) == 0)
					dwCount++;
			} while (Process32Next(hProcessSnap, &pe32));

			CloseHandle(hProcessSnap);
		}
		
		return dwCount;
	}

	// 根据路径名查找进程,查找成功并结束;
	int FindAndCloseProcess(IN CString strProName)
	{
		int nIndex = strProName.ReverseFind('\\');
		if (nIndex != -1)	// 如果传的是全路径;
			strProName = strProName.Right(strProName.GetLength() - nIndex - 1);

		DWORD dwProcessID = 0;
		PROCESSENTRY32 pe32 = { 0 };

		HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
		if (hProcessSnap == NULL)
		{
			return 0;
		}
		pe32.dwSize = sizeof(PROCESSENTRY32);

		if (Process32First(hProcessSnap, &pe32))
		{
			do
			{
				if (_tcscmp(strProName.GetBuffer(), pe32.szExeFile) == 0)
				{
					dwProcessID = pe32.th32ProcessID;
					break;
				}
			} while (Process32Next(hProcessSnap, &pe32));
		}
		CloseHandle(hProcessSnap);

		if (dwProcessID == 0)
			return 0;

		HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessID);
		if (hProcess == NULL)
			return 0;

		DWORD dwError;
		if (!TerminateProcess(hProcess, 0))
		{
			dwError = GetLastError();
			CloseHandle(hProcess);
			return -1;
		}

		// 等待进程结束响应;
		if (WAIT_OBJECT_0 != WaitForSingleObject(hProcess, INFINITE))
		{
			CloseHandle(hProcess);
			AfxMessageBox(_T("结束进程失败"));
			return -1;
		}

		CloseHandle(hProcess);

		return 1;
	}

	/************************************************************************/
	/*
	函数：GetDiskSpaceInfo
	描述：获取指定目录或盘符的容量信息;
	参数：
	IN:	lpRootPathName 根目录名称;
	INOUT: dTotalNum  总容量;
	INOUT: dFreeNum 可用容量;
	返回：
	注意：
	GetDiskFreeSpace函数不能满足当前超过2T的硬盘容量,因为里面的数据类型是UINT,最大支持32位(4G);
	GetDiskFreeSpaceEx支持64位(16384P=1024*16384T)
	能获取本机硬盘信息,但路径必须包含":"冒号, 同时还可以获取网络路径的共享硬盘大小;
	调用约定：
	*/
	/************************************************************************/
	BOOL GetDiskSpaceInfo(IN LPCTSTR lpRootPathName, IN OUT double &dTotalNum, IN OUT double &dFreeNum)
	{
#if 1
		// 校验参数有效性;
		if (lpRootPathName == NULL || _tcscmp(lpRootPathName, _T("")) == 0)
		{
			//_tprintf_s(_T("根目录为空!"));
			return FALSE;
		}

		// 如果长度==1;
		int nlen = _tcslen(lpRootPathName);
		if ((1 == nlen) || (2 == nlen && lpRootPathName[nlen - 1] != _T(':')))
		{
			//_tprintf_s(_T("根目录无效!\n"));
			return FALSE;
		}

		if (!PathFileExists(lpRootPathName))
		{
			//_tprintf_s(_T("根目录不存在!\n"));
			return FALSE;
		}
#else
		// 使用IsValipath判断网络路径时较慢;
		if (!IsValidpath(lpRootPathName) || !PathFileExists(lpRootPathName)) return FALSE;
#endif

		BOOL fResult = FALSE;
		DWORD dwSectPerClust;	// 每簇的扇区数;
		DWORD dwBytesPerSect;	// 每个扇区的字节数;
		DWORD dwFreeClusters;	// 可用簇数;
		DWORD dwTotalClusters;	// 总簇数;

		typedef BOOL(WINAPI *P_GDFSE)(LPCTSTR, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER);
		P_GDFSE pGetDiskFreeSpaceEx = NULL;

		/*unsigned*/ __int64 i64FreeBytesToCaller;
		/*unsigned*/ __int64 i64TotalBytes;
		/*unsigned*/ __int64 i64FreeBytes;

		// 调用GetDiskFreeSpaceEx失败则调用GetDiskSpace;
#ifdef UNICODE
		pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "GetDiskFreeSpaceExW");
#else
		pGetDiskFreeSpaceEx = (P_GDFSE)GetProcAddress(GetModuleHandle("kernel32.dll"), "GetDiskFreeSpaceExA");
#endif

		if (pGetDiskFreeSpaceEx)
		{
			fResult = pGetDiskFreeSpaceEx(lpRootPathName,
				(PULARGE_INTEGER)&i64FreeBytesToCaller,
				(PULARGE_INTEGER)&i64TotalBytes,
				(PULARGE_INTEGER)&i64FreeBytes);

			if (fResult)
			{
				// 将单位由byte转为G byte;
				dTotalNum = (double)i64TotalBytes / 1024 / 1024 / 1024;
				dFreeNum = (double)i64FreeBytes / 1024 / 1024 / 1024;
			}
		}
		else
		{
			fResult = GetDiskFreeSpace(lpRootPathName,
				&dwSectPerClust,
				&dwBytesPerSect,
				&dwFreeClusters,
				&dwTotalClusters);

			if (fResult)
			{
				// 成功获得容量信息;
				i64TotalBytes = (__int64)dwTotalClusters * dwSectPerClust * dwBytesPerSect;
				i64FreeBytes = (__int64)dwFreeClusters * dwSectPerClust * dwBytesPerSect;

				// 将单位由byte转为G byte;
				dTotalNum = (double)i64TotalBytes / 1024 / 1024 / 1024;
				dFreeNum = (double)i64FreeBytes / 1024 / 1024 / 1024;
			}
		}

		return fResult;
	}


	/************************************************************************/
	/* 
	函数：GetFileVersion
	描述：获取可执行文件的文件版号;
	参数：
	hModule[IN]		可执行文件模块句柄;
	dwArray[OUT]	返回的文件版本号;
	返回：
	成功返回TRUE,失败返回FALSE;
	注意：
	当hModule为空时，表示要获取的可执行文件为本程序的文件版本号;
	*/
	/************************************************************************/
	BOOL GetFileVersion( IN HMODULE hModule, OUT DWORD (&dwArray)[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, dwHandle, nSize, pBuffer))
				{
					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
					{
						dwArray[0] = HIWORD(pVi->dwFileVersionMS);
						dwArray[1] = LOWORD(pVi->dwFileVersionMS);
						dwArray[2] = HIWORD(pVi->dwFileVersionLS);
						dwArray[3] = LOWORD(pVi->dwFileVersionLS);

						delete[]pBuffer;
						return TRUE;
					}
				}

				if ( pBuffer )
					delete[]pBuffer;
			}
		}

		return FALSE;
	}

	/************************************************************************/
	/* 
	函数：GetFileVersion
	描述：获取可执行文件的文件版号;
	参数：
	lpFileName[IN]	可执行文件名全路径;
	dwArray[OUT]	返回的文件版本号;
	返回：
	成功返回TRUE,失败返回FALSE;
	注意：
	*/
	/************************************************************************/
	BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
	{
		if ( lpFileName == NULL || !PathFileExists(lpFileName) )
		{
			OutputDebugString(_T("文件名错误或文件不存在\n"));
			return FALSE;
		}

		DWORD dwHandle = 0;
		VS_FIXEDFILEINFO *pVi = NULL;
		INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
		if ( nSize > 0 )
		{
			BYTE *pBuffer = new BYTE[nSize];
			memset(pBuffer, 0, nSize);

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

					if (pBuffer)
						delete[]pBuffer;
					return TRUE;
				}
			}

			if (pBuffer)
				delete[]pBuffer;
		}

		return FALSE;
	}

	/************************************************************************/
	/* 
	函数：GetProductVersion
	描述：获取可执行文件的产品版号;
	参数：
	hModule[IN]		可执行文件模块句柄;
	dwArray[OUT]	返回的产品版本号;
	返回：
	成功返回TRUE,失败返回FALSE;
	注意：
	当hModule为空时，表示要获取的可执行文件为本程序的产品版本号;
	*/
	/************************************************************************/
	BOOL GetProductVersion(IN HMODULE hModule, IN DWORD (&dwArray)[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, dwHandle, nSize, pBuffer))
				{
					if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
					{
						dwArray[0] = HIWORD(pVi->dwProductVersionMS);
						dwArray[1] = LOWORD(pVi->dwProductVersionMS);
						dwArray[2] = HIWORD(pVi->dwProductVersionLS);
						dwArray[3] = LOWORD(pVi->dwProductVersionLS);

						if(pBuffer)
							delete[]pBuffer;
						return TRUE;
					}
				}
				if(pBuffer)
					delete[]pBuffer;
			}
		}

		return FALSE;
	}

	/************************************************************************/
	/* 
	函数：GetProductVersion
	描述：获取可执行文件的产品版号;
	参数：
	lpFileName[IN]	可执行文件名全路径;
	dwArray[OUT]	返回的产品版本号;
	返回：
	成功返回TRUE,失败返回FALSE;
	注意：
	*/
	/************************************************************************/
	BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] )
	{
		if ( lpFileName == NULL || !PathFileExists(lpFileName) )
		{
			OutputDebugString(_T("文件名错误或文件不存在\n"));
			return FALSE;
		}

		DWORD dwHandle = 0;
		VS_FIXEDFILEINFO *pVi = NULL;
		INT nSize = GetFileVersionInfoSize(lpFileName, &dwHandle);
		if ( nSize > 0 )
		{
			BYTE *pBuffer = new BYTE[nSize];
			memset(pBuffer, 0, nSize);

			if ( GetFileVersionInfo(lpFileName, dwHandle, nSize, pBuffer) )
			{
				if (VerQueryValue(pBuffer, _T("\\"), (LPVOID *)&pVi, (PUINT)&nSize))
				{
					dwArray[0] = HIWORD(pVi->dwProductVersionMS);
					dwArray[1] = LOWORD(pVi->dwProductVersionMS);
					dwArray[2] = HIWORD(pVi->dwProductVersionLS);
					dwArray[3] = LOWORD(pVi->dwProductVersionLS);

					if (pBuffer)
						delete[]pBuffer;
					return TRUE;
				}
			}

			if (pBuffer)
				delete[]pBuffer;
		}

		return FALSE;
	}

	/************************************************************************/
	/* 
		函数：
		描述：
		参数：
		返回：
		注意：
	*/
	/************************************************************************/
	BOOL GetDirLastWriteTime(IN LPCTSTR lpDirName, OUT LPTSTR lpszString, IN CONST DWORD& dwSize)
	{
		if ( lpDirName == NULL || !PathFileExists(lpDirName))
		{
			OutputDebugString(_T("文件夹不存在\n"));
			return FALSE;
		}

		// 打开文件夹;
		HANDLE hDir = CreateFile(
			lpDirName, 
			GENERIC_READ,
			FILE_SHARE_READ|FILE_SHARE_DELETE,
			NULL, OPEN_EXISTING,
			FILE_FLAG_BACKUP_SEMANTICS, NULL);

		if ( hDir == INVALID_HANDLE_VALUE )
		{
			OutputDebugString(_T("打开文件夹失败\n"));
			return FALSE;
		}

		if ( !GetLastWriteTime(hDir, lpszString, dwSize) )
		{
			OutputDebugString(_T("获取文件修改时间失败\n"));
			return FALSE;
		}
		
		// 关闭文件句柄;
		CloseHandle(hDir);

		return TRUE;
	}

	BOOL GetLastWriteTime(IN HANDLE hFile, OUT LPTSTR lpszString, IN CONST DWORD& dwSize)
	{
		// 创建时间、访问时间、修改时间;
		FILETIME ftCreate, ftAccess, ftWrite;
		// UTC时间、系统时间;
		SYSTEMTIME stUTC, stLocal;
		// 返回的结果;
		DWORD dwRet = 0;

		// Retrieve the file times for the file.
		if (!GetFileTime(hFile, &ftCreate, &ftAccess, &ftWrite))
			return FALSE;

		// Convert the last-write time to local time.
		FileTimeToSystemTime(&ftWrite, &stUTC);
		SystemTimeToTzSpecificLocalTime(NULL, &stUTC, &stLocal);

		// Build a string showing the date and time.
		dwRet = StringCchPrintf(lpszString, dwSize, 
			TEXT("%02d/%02d/%d  %02d:%02d"),
			stLocal.wMonth, stLocal.wDay, stLocal.wYear,
			stLocal.wHour, stLocal.wMinute);

		return (S_OK == dwRet ? TRUE : FALSE);
	}

	BOOL SetFileLastWirteTime(IN LPCTSTR lpDirName, IN SYSTEMTIME &st)
	{
		if ( lpDirName == NULL || !PathFileExists(lpDirName))
		{
			OutputDebugString(_T("文件夹不存在\n"));
			return FALSE;
		}

		// 打开文件夹;
		HANDLE hDir = CreateFile(
			lpDirName, 
			GENERIC_WRITE,
			FILE_SHARE_READ|FILE_SHARE_DELETE,
			NULL, OPEN_EXISTING,
			FILE_FLAG_BACKUP_SEMANTICS, NULL);

		if ( hDir == INVALID_HANDLE_VALUE )
		{
			OutputDebugString(_T("打开文件夹失败\n"));
			return FALSE;
		}

		FILETIME ft;
		BOOL f;
		SystemTimeToFileTime(&st, &ft);  // converts to file time format
		// sets last-write time for file
		f = SetFileTime(hDir, (LPFILETIME) NULL, (LPFILETIME) NULL, &ft);
		CloseHandle(hDir);

		return f;
	}

	void DeleteDirectory(CString strDir)
	{
		if ( strDir.IsEmpty() || !PathFileExists(strDir) )
		{
			OutputDebugString(_T("DeleteDirectory:路径无效!"));
			return;
		}

		try
		{
			// 首先删除文件及子文件夹;   
			CFileFind   ff;
			BOOL   bFound = ff.FindFile(strDir + _T("\\*"), 0);
			while (bFound)
			{
				bFound = ff.FindNextFile();
				if (ff.GetFileName() == _T(".") || ff.GetFileName() == _T(".."))
					continue;
				// 去掉文件(夹)只读等属性;   
				if ( SetFileAttributes(ff.GetFilePath(), FILE_ATTRIBUTE_NORMAL) )
				{
					if (ff.IsDirectory())
					{   // 递归删除子文件夹;   
						DeleteDirectory(ff.GetFilePath());
						RemoveDirectory(ff.GetFilePath());
					}
					else
					{
						DeleteFile(ff.GetFilePath());   // Jeff：删除某文件夹下的所有子文件;
						OutputDebugString(ff.GetFilePath());
					}
				}
				else
				{
					DWORD dwError = GetLastError();
					CString strError = _T("");
					strError.Format(_T("设置文件[%s]属性失败：%d"), ff.GetFilePath(), dwError);
				}
			}
			ff.Close();
			// 然后删除该文件夹;   
			RemoveDirectory(strDir);
		}
		catch (...)
		{
			OutputDebugString(_T("出错在函数deldir中"));
		}
	}

	void GetHostName()
	{
		WSADATA WSAData = { 0 };
		if(0 != WSAStartup(MAKEWORD(2, 2), &WSAData))
		{
			AfxMessageBox(_T("网络环境初始化失败!"));
			return;
		}

		CHAR szHostName[MAX_PATH] = {0};
		gethostname(szHostName,MAX_PATH);

#ifdef UNICODE
		INT wSize = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, NULL, 0);
		if (wSize == 0) return ;

		WCHAR *pHostName = new WCHAR[wSize];
		int convresult = MultiByteToWideChar(CP_ACP, 0, szHostName, -1, pHostName, wSize);
		if (convresult != wSize)
		{
			if (pHostName) delete []pHostName;
			return;
		}
#else
		TCHAR *pHostName = szHostName;
#endif
		StringCchPrintf(g_szHostName, MAX_PATH, _T("%s"), pHostName);
#ifdef UNICODE
		delete []pHostName;
#endif
	}

};
