Ver código fonte

添加服务项目,初步完成后台服务模型。

Jeff 6 anos atrás
pai
commit
b194ca5e31

+ 6 - 0
source/hook/WeChats.sln

@@ -5,6 +5,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "hook", "hook\hook.vcproj",
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WeChats", "WeChats\WeChats.vcproj", "{7704A546-A786-41C8-B22A-04BC05AE4F82}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WxService", "WxService\WxService.vcproj", "{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Win32 = Debug|Win32
@@ -19,6 +21,10 @@ Global
 		{7704A546-A786-41C8-B22A-04BC05AE4F82}.Debug|Win32.Build.0 = Debug|Win32
 		{7704A546-A786-41C8-B22A-04BC05AE4F82}.Release|Win32.ActiveCfg = Release|Win32
 		{7704A546-A786-41C8-B22A-04BC05AE4F82}.Release|Win32.Build.0 = Release|Win32
+		{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}.Debug|Win32.Build.0 = Debug|Win32
+		{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}.Release|Win32.ActiveCfg = Release|Win32
+		{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}.Release|Win32.Build.0 = Release|Win32
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 981 - 0
source/hook/WxService/Global.cpp

@@ -0,0 +1,981 @@
+#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];					// 数据库名称;	
+
+	CHAR g_szKeyPath[MAX_PATH];					// 加密狗USB位置;
+
+	//////////////////////////////////////////////////////////////////////////
+	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);
+
+		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) )
+				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
+	}
+
+};

+ 109 - 0
source/hook/WxService/Global.h

@@ -0,0 +1,109 @@
+///************************************************************************/
+/*  Copyright (C), 2016-2020, [home], 保留所有权利;
+/*  模 块 名:;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[home];
+/*  日    期:[4/23/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[home];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __HOME_GLOBAL__
+#define __HOME_GLOBAL__
+
+#pragma once
+
+#include <string>
+#include <vector>
+using namespace std;
+
+#ifndef _UNICODE
+typedef string TString;
+#else
+typedef wstring TString;
+#endif
+
+namespace Global
+{
+	//////////////////////////////////////////////////////////////////////////
+	// 全局变量;
+	//////////////////////////////////////////////////////////////////////////
+	extern TCHAR g_szIniFile[MAX_PATH];
+	extern TCHAR g_szHostName[MAX_PATH];			// 主机计算机名;
+	extern TCHAR g_szModulePath[MAX_PATH];			// 软件目录;
+	extern TCHAR g_szModuleFileName[MAX_PATH];		// 软件名称;
+	extern TCHAR g_szConnectString[MAX_PATH];		// DB连接串;
+	extern TCHAR g_szBranchId[MAX_PATH];			// 分店域名;
+
+	// 服务器信息;
+	extern TCHAR g_szDBSource[MAX_PATH];			// 数据库源(服务所在IP或计算机名);
+	extern TCHAR g_szDBSourcePort[MAX_PATH];		// 数据库源端口;
+	extern DWORD g_dwDBServerPort;					// 数据库源端口;
+	extern TCHAR g_szDBAccount[MAX_PATH];			// 数据库登录用户;
+	extern TCHAR g_szDBPassWord[MAX_PATH];			// 数据库登录密码;
+	extern TCHAR g_szDBName[MAX_PATH];				// 数据库名称;	
+
+	extern CHAR g_szKeyPath[MAX_PATH];				// 加密狗USB位置;
+
+	//////////////////////////////////////////////////////////////////////////
+	// 全局函数;
+	// 判断公历是否有效;
+	extern BOOL IsValidDate(IN LPCTSTR lpDate);
+	// 判断农历是否有效;
+	extern BOOL IsValidLunanrDate(IN LPCTSTR lpDate);
+	// 获取配置文件函数;
+	extern int GetIniInfo(IN const TCHAR *szPath = NULL, const TCHAR *szIniName = NULL);
+
+	//////////////////////////////////////////////////////////////////////////
+	// 字符串系列全局函数;
+	extern BOOL CompareNoCase(IN TString& str1, IN TString& str2);
+	extern BOOL IsStringExist(IN CString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExist(IN TString& str, IN vector<TString> &tagVt);
+	extern BOOL IsStringExistNoCase(IN CString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExistNoCase(IN CONST TString& str, IN CStringArray &tagAry);
+	extern BOOL IsStringExistNoCase(IN CONST TString& str, IN vector<TString> &tagVt);
+	extern TString lowercase(IN const TString &Str);
+	extern TString uppercase(IN const TString &Str);
+	extern int match(IN CONST TString &sExt, IN CONST TString &sFile);
+	extern TString getfilename(IN CONST TString &file);
+	extern CString getfilename(IN CONST CString &file);
+
+	//////////////////////////////////////////////////////////////////////////
+	// 进程相关函数;
+	extern BOOL FindAppProcessID(IN CString path, OUT DWORD &dwProcessID);
+	extern DWORD FindProcess(IN CString strProName);
+	extern DWORD FindProcessCount(IN LPCTSTR lpExeName);
+	extern int FindAndCloseProcess(IN CString strProName);
+
+	// 文件函数;
+	extern  BOOL GetDiskSpaceInfo(IN LPCTSTR lpRootPathName,IN OUT double &dTotalNum, IN OUT double &dFreeNum);
+
+	extern BOOL GetFileVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+	extern BOOL GetFileVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+	extern BOOL GetProductVersion( IN HMODULE hModule, IN DWORD (&dwArray)[4]);
+	extern BOOL GetProductVersionEx( IN LPCTSTR lpFileName, IN DWORD (&dwArray)[4] );
+
+	// 获取文件夹的修改时间;
+	extern BOOL GetDirLastWriteTime(IN LPCTSTR lpDirName, OUT LPTSTR lpszString, IN CONST DWORD& dwSize);
+	// 设置文件夹的修改时间;
+	extern BOOL SetDirLastWriteTime();
+	// 获取指定文件句柄的修改时间;
+	extern BOOL GetLastWriteTime(IN HANDLE hFile, OUT LPTSTR lpszString, IN CONST DWORD& dwSize);
+	// 设置指定文件夹的修改时间;
+	extern BOOL SetFileLastWirteTime(IN LPCTSTR lpDirName, IN SYSTEMTIME &st);
+	// 删除指定的目录所有文件;
+	extern void DeleteDirectory(CString strDir);
+	//
+	extern void GetHostName();
+
+};
+
+#endif

BIN
source/hook/WxService/IDI_MICON


+ 56 - 0
source/hook/WxService/MTVERIFY.H

@@ -0,0 +1,56 @@
+/*
+ * MtVerify.h
+ *
+ * Error handling for applications in
+ * "Multitheading Applications in Win32"
+ *
+ * The function PrintError() is marked as __inline so that it can be
+ * included from one or more C or C++ files without multiple definition
+ * errors. For the examples in this book, this works fine.
+ * To use the PrintError() in an application, it should be taken out,
+ * placed in its own source file, and the "__inline" declaration removed
+ * so the function will be globally available.
+ */
+#ifndef _MTVERIFY_HEADER_
+#define _MTVERIFY_HEADER_
+
+#pragma comment( lib, "USER32" )
+
+#include <strsafe.h>
+#include <crtdbg.h>
+#define MTASSERT(a) _ASSERTE(a)
+
+
+#define MTVERIFY(a) if (!(a)) PrintError(#a,__FILE__,__LINE__,GetLastError())
+
+__inline void PrintError(LPTSTR linedesc, LPTSTR filename, int lineno, DWORD errnum)
+{
+	LPTSTR lpBuffer;
+	TCHAR errbuf[MAX_PATH];
+#ifdef _WINDOWS
+	TCHAR modulename[MAX_PATH];
+#else // _WINDOWS
+	DWORD numread;
+#endif // _WINDOWS
+
+	FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_SYSTEM,
+		NULL,
+		errnum,
+		LANG_NEUTRAL,
+		(LPTSTR)&lpBuffer,
+		0,
+		NULL );
+
+//	_stprintf(errbuf, _T("\nThe following call failed at line %d in %s:\n\n%s\n\nReason: %s\n"), lineno, filename, linedesc, lpBuffer);
+	StringCchPrintf(errbuf, MAX_PATH, _T("\nThe following call failed at line %d in %s:\n\n%s\n\nReason: %s\n"), lineno, filename, linedesc, lpBuffer);
+#ifndef _WINDOWS
+	WriteFile(GetStdHandle(STD_ERROR_HANDLE), errbuf, _tcslen(errbuf), &numread, FALSE );
+	Sleep(3000);
+#else
+	GetModuleFileName(NULL, modulename, MAX_PATH);
+	//MessageBox(NULL, errbuf, modulename, MB_ICONWARNING|MB_OK|MB_TASKMODAL|MB_SETFOREGROUND);
+#endif
+	exit(EXIT_FAILURE);
+}
+
+#endif

+ 89 - 0
source/hook/WxService/MainProcess.cpp

@@ -0,0 +1,89 @@
+#include "StdAfx.h"
+#include "MainProcess.h"
+#include "WinService.h"
+
+CMainProcess::CMainProcess(void)
+{
+	m_hBackupDatabase = NULL;
+	m_hCheckServices = NULL;
+	m_hEvent1 = NULL;
+	m_hEvent2 = NULL;
+}
+
+CMainProcess::~CMainProcess(void)
+{
+}
+
+void CMainProcess::StartWork()
+{
+	m_hEvent1 = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if ( m_hEvent1 == NULL )
+	{
+		_tprintf_s(_T("创建事件失败\n"));
+		return;
+	}
+
+	m_hEvent2 = CreateEvent(NULL, TRUE, FALSE, NULL);
+	if ( m_hEvent2 == NULL )
+	{
+		_tprintf_s(_T("创建事件失败2\n"));
+		return;
+	}
+
+	m_hCheckServices = CreateThread(NULL, 0, CheckSvcStatusThread, this, 0, NULL);
+	if ( m_hCheckServices == NULL)
+	{
+		SetEvent(m_hEvent1);
+		SetEvent(m_hEvent2);
+		CloseHandle(m_hEvent1);
+		CloseHandle(m_hEvent2);
+		m_hEvent1 = NULL;
+		m_hEvent2 = NULL;
+		_tprintf_s(_T("创建线程失败\n"));
+		return;
+	}
+
+	m_hBackupDatabase = CreateThread(NULL, 0, BackupDatabaseThread, this, 0, NULL);
+	if ( m_hBackupDatabase == NULL )
+	{
+		SetEvent(m_hEvent1);
+		SetEvent(m_hEvent2);
+		CloseHandle(m_hEvent1);
+		CloseHandle(m_hEvent2);
+		m_hEvent1 = NULL;
+		m_hEvent2 = NULL;
+		WaitForSingleObject(m_hCheckServices,INFINITE);
+		if (m_hBackupDatabase)
+			CloseHandle(m_hBackupDatabase);
+		m_hBackupDatabase = NULL;
+		_tprintf_s(_T("创建线程失败2\n"));
+		return;
+	}
+}
+
+void CMainProcess::EndofWork()
+{
+
+}
+
+DWORD CMainProcess::CheckSvcStatusThread(LPVOID lpVoid)
+{
+	CMainProcess *pthis = (CMainProcess*)lpVoid;
+
+	do 
+	{
+	} while ( WaitForSingleObject(pthis->m_hEvent1, 200) == WAIT_TIMEOUT );
+
+	return 0;
+}
+
+DWORD CMainProcess::BackupDatabaseThread(LPVOID lpVoid)
+{
+	CMainProcess *pthis = (CMainProcess*)lpVoid;
+
+	do 
+	{
+	} while ( WaitForSingleObject(pthis->m_hEvent2, 200) == WAIT_TIMEOUT );
+
+	return 0;
+}

+ 65 - 0
source/hook/WxService/MainProcess.h

@@ -0,0 +1,65 @@
+/************************************************************************/
+/*  Copyright (C), 2016-2020, [IT], 保留所有权利;
+/*  模 块 名:服务的主要处理类;
+/*  描    述:;
+/*
+/*  版    本:[V];	
+/*  作    者:[IT];
+/*  日    期:[5/6/2016];
+/*
+/*
+/*  注    意:;
+/*
+/*  修改记录:[IT];
+/*  修改日期:;
+/*  修改版本:;
+/*  修改内容:;
+/************************************************************************/
+
+#ifndef __MAIN_PROCESS__
+#define __MAIN_PROCESS__
+
+#pragma once
+
+class CMainProcess
+{
+	CMainProcess(void);
+public:
+	// 单例对象模式;
+	static CMainProcess* GetInstance()
+	{
+		static CMainProcess* pInstance = NULL;
+		if ( pInstance == NULL )
+		{
+			pInstance = new CMainProcess;
+		}
+
+		return pInstance;
+	}
+
+	~CMainProcess(void);
+
+protected:
+	// 线程控制句柄;
+	HANDLE  m_hEvent1;
+	// 检查服务线程句柄;
+	HANDLE	m_hCheckServices;
+	// 线程控制句柄;
+	HANDLE  m_hEvent2;
+	// 备份数据库线程句柄;
+	HANDLE	m_hBackupDatabase;
+
+	// 其他接口;
+public:
+	// 工作开始函数;	
+	void StartWork();
+	// 工作结束函数;
+	void EndofWork();
+
+	// 检测服务在线线程;
+	static DWORD WINAPI CheckSvcStatusThread(LPVOID lpVoid);
+	static DWORD WINAPI BackupDatabaseThread(LPVOID lpVoid);
+
+};
+
+#endif

+ 40 - 0
source/hook/WxService/ReadMe.txt

@@ -0,0 +1,40 @@
+========================================================================
+    控制台应用程序:WxService 项目概述
+========================================================================
+
+应用程序向导已为您创建了此 WxService 应用程序。
+
+本文件概要介绍组成 WxService 应用程序的
+的每个文件的内容。
+
+
+WxService.vcproj
+    这是使用应用程序向导生成的 VC++ 项目的主项目文件,
+    其中包含生成该文件的 Visual C++ 的版本信息,以及有关使用应用程序向导选择的平台、配置和项目功能的信息。
+
+WxService.cpp
+    这是主应用程序源文件。
+
+/////////////////////////////////////////////////////////////////////////////
+应用程序向导创建了下列资源:
+
+WxService.rc
+这是程序使用的所有 Microsoft Windows 资源的列表。它包括 RES 子目录中存储的图标、位图和光标。
+此文件可以直接在 Microsoft Visual C++ 中进行编辑。
+
+Resource.h
+    这是标准头文件,可用于定义新的资源 ID。
+    Microsoft Visual C++ 将读取并更新此文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他标准文件:
+
+StdAfx.h, StdAfx.cpp
+    这些文件用于生成名为 WxService.pch 的预编译头 (PCH) 文件和名为 StdAfx.obj 的预编译类型文件。
+
+/////////////////////////////////////////////////////////////////////////////
+其他注释:
+
+应用程序向导使用“TODO:”注释来指示应添加或自定义的源代码部分。
+
+/////////////////////////////////////////////////////////////////////////////

BIN
source/hook/WxService/Watchdog.ico


+ 1808 - 0
source/hook/WxService/WinService.cpp

@@ -0,0 +1,1808 @@
+#include "stdafx.h"
+#include "WinService.h"
+#include <psapi.h>
+#include <tlhelp32.h>
+#pragma comment ( lib, "psapi.lib" )
+#include <Aclapi.h>
+#include <strsafe.h>
+#include <shlwapi.h>
+
+
+namespace WinService
+{
+	SCVariant g_scVariant;
+
+	int InitWinSock()
+	{
+		WORD	wVersionRequested;
+		WSADATA	wsaData;
+		int		nErrCode;
+
+		wVersionRequested = MAKEWORD(2, 2);
+		nErrCode = WSAStartup(wVersionRequested, &wsaData);
+		if (0 != nErrCode)
+			return -1;
+
+		return 0;
+	}
+
+	/************************************************************************/
+	/*  函数:[7/20/2017 IT];
+	/*  描述:初始化服务名称和描述名称;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void InitServiceName(IN LPCTSTR lpServiceName, IN LPCTSTR lpServiceDescription)
+	{
+		if (lpServiceName == NULL || lpServiceName[0] == '\0')
+		{
+			TCHAR szModuleFileName[MAX_PATH] = { 0 };
+			TCHAR szExeName[MAX_PATH] = { 0 };
+			TCHAR szDrive[_MAX_DRIVE] = { 0 };
+			TCHAR szDir[_MAX_DIR] = { 0 };
+			TCHAR szFna[_MAX_DIR] = { 0 };
+			TCHAR szExt[_MAX_DIR] = { 0 };
+			::GetModuleFileName(NULL, szModuleFileName, sizeof(szModuleFileName) / sizeof(TCHAR));
+			_tsplitpath_s(szModuleFileName, szDrive, szDir, szFna, szExt);
+
+			// 用程序名来当服务名称;
+			_stprintf_s(g_scVariant.scName, _T("%s"), szFna);
+		}
+		else
+		{
+			_stprintf_s(g_scVariant.scName, _T("%s"), lpServiceName);
+		}
+
+		if (lpServiceDescription == NULL || lpServiceDescription[0] == '\0')
+			_stprintf_s(g_scVariant.scDescription, _T("%s"), g_scVariant.scName);
+		else
+			_stprintf_s(g_scVariant.scDescription, _T("%s"), lpServiceDescription);
+	}
+
+	/************************************************************************/
+	/*  函数:[7/20/2017 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL IsInstalled()
+	{
+		BOOL bResult = FALSE;
+		// 打开服务控制管理器;
+		SC_HANDLE schSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+		if (schSCM != NULL)
+		{// 打开服务;
+			SC_HANDLE schSvc = ::OpenService(schSCM, g_scVariant.scName, SERVICE_QUERY_CONFIG);
+			if (schSvc != NULL)
+			{
+				bResult = TRUE;
+				::CloseServiceHandle(schSvc);
+			}
+			::CloseServiceHandle(schSCM);
+		}
+
+		return bResult;
+	}
+
+	/************************************************************************/
+	/*  函数:[7/20/2017 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL Install()
+	{
+		// 获取服务程序的绝对路径;
+		TCHAR szFilePath[MAX_PATH];
+		if (0 == ::GetModuleFileName(NULL, szFilePath, MAX_PATH))
+		{
+			_tprintf_s(_T("Cannot Install Service (%d)\n"), GetLastError());
+			return FALSE;
+		}
+
+		// 打开服务控制管理器,获取SCM数据库句柄;
+		SC_HANDLE schSCM = ::OpenSCManager(
+			NULL,						// 本地计算机;
+			NULL,						// ServicesActive database;
+			SC_MANAGER_ALL_ACCESS		// 所有权限;
+		);
+
+		if (schSCM == NULL)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return FALSE;
+		}
+
+		// 创建服务;
+		SC_HANDLE schSvc = ::CreateService(
+			schSCM,								// SCM数据库;
+			g_scVariant.scName,					// 服务名称;
+			g_scVariant.scDisplayName,			// 服务显示名称;
+			SERVICE_ALL_ACCESS,					// 需要的访问权限;
+			SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,		// 服务类型;
+			SERVICE_AUTO_START, //SERVICE_DEMAND_START,		// 启动类型;
+			SERVICE_ERROR_NORMAL,				// 错误控制类型;
+			szFilePath,							// 服务程序路径;
+			NULL,								// 无加载顺序组;
+			NULL,								// 无标签标识;
+			_T(""),								// 无依赖;
+			NULL,								// 本地系统账号;
+			NULL								// 无密码(no password);
+		);
+
+		if (schSvc == NULL)
+		{
+			_tprintf_s(_T("CreateService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSvc);
+			return FALSE;
+		}
+
+		// 设置服务的描述;
+		SERVICE_DESCRIPTION ServiceDesc;
+		ServiceDesc.lpDescription = g_scVariant.scDescription;
+		::ChangeServiceConfig2(schSvc, SERVICE_CONFIG_DESCRIPTION, &ServiceDesc);
+
+		// 释放资源;
+		::CloseServiceHandle(schSvc);
+		::CloseServiceHandle(schSCM);
+
+		return TRUE;
+	}
+
+	/************************************************************************/
+	/*  函数:[7/20/2017 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL Uninstall()
+	{
+		if (!IsInstalled()) return TRUE;
+
+		SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+
+		if (hSCM == NULL) return FALSE;
+
+		SC_HANDLE hService = ::OpenService(hSCM, g_scVariant.scName, SERVICE_STOP | DELETE);
+
+		if (hService == NULL)
+		{
+			::CloseServiceHandle(hSCM);
+			return FALSE;
+		}
+
+		SERVICE_STATUS scStatus;
+		::ControlService(hService, SERVICE_CONTROL_STOP, &scStatus);
+
+		// 删除服务;
+		BOOL bDelete = ::DeleteService(hService);
+		::CloseServiceHandle(hService);
+		::CloseServiceHandle(hSCM);
+
+		if (bDelete)
+		{
+			//LOG4C((LOG_NOTICE,"服务成功卸载"));
+			return TRUE;
+		}
+
+		//LOG4C((LOG_NOTICE,"服务卸载失败"));
+		LogEvent(_T("Service could not be deleted"));
+		return FALSE;
+	}
+
+	/************************************************************************/
+	/*  函数:ServiceMain[4/23/2016 home];
+	/*  描述:服务入口函数;
+	/*  参数:;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WINAPI ServiceMain()
+	{
+		// 注册服务的控制函数;
+		g_scVariant.scStatusHandle = RegisterServiceCtrlHandler(g_scVariant.scName, SvcCtrlHandler);
+		if (g_scVariant.scStatusHandle == NULL)
+		{
+			SvcReportEvent(_T("Handler not installed"));
+			return;
+		}
+
+		// 在这里设置服务状态;
+		g_scVariant.scStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
+		g_scVariant.scStatus.dwServiceSpecificExitCode = 0;
+
+		// 注册成功后向SCM报告服务状态信息,因为服务还没初始化完成;
+		// 所以当前服务状态为SERVICE_START_PENDING ;
+		ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, 3000); // 处理第一个事件大约需要3秒钟;
+
+		//////////////////////////////////////////////////////////////////////////
+		// 开始初始化服务;
+		g_scVariant.hscEvent = ::CreateEvent(NULL, TRUE, FALSE, _T("CtrlService::g_hCtrlSvc"));
+		if (g_scVariant.hscEvent == NULL)
+		{
+			// 向SCM报告服务已停止;
+			ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 1, 0);
+			return;
+		}
+
+		// 向SCM报告服务正在运行;
+		ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0);
+
+		// 开启工作者;
+		if (g_scVariant.lpStartWorkCallBack)
+			g_scVariant.lpStartWorkCallBack();
+
+		// 线程中的处理函数运行结束后返回ServiceMain(),
+		// ServiceMain()调用WaitForSingleObject,
+		// 因为服务被停止之前ServiceMain()不会结束 
+		WaitForSingleObject(g_scVariant.hscEvent, INFINITE); // INFINITE表示无限等待,等待SCM的信号;
+		CloseHandle(g_scVariant.hscEvent);
+
+		// 结束工作者;
+		if (g_scVariant.lpEndofWorkCallBack)
+			g_scVariant.lpEndofWorkCallBack();
+
+		SvcReportEvent(_T("Service stopped"));
+
+		// 向SCM报告服务已停止工作;
+		ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0, 0, 0);
+	}
+
+	/************************************************************************/
+	/*  函数:SvcCtrlHandler[4/23/2016 home];
+	/*  描述:每当有控制码发送给服务时被SCM调用;
+	/*  参数:;
+	/*  	[IN] dwControlCode:发送给服务的控制码;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void WINAPI SvcCtrlHandler(IN DWORD dwControlCode)
+	{
+		BOOL bsucc = FALSE;
+		switch (dwControlCode)
+		{
+		case SERVICE_CONTROL_SHUTDOWN:		// 关掉服务;
+		case SERVICE_CONTROL_STOP:			// 停止服务;
+			bsucc = ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0, 1, 0);
+			if (bsucc)
+			{
+				if (g_scVariant.lpEndofWorkCallBack)
+					g_scVariant.lpEndofWorkCallBack();
+				KillService();
+			}
+			break;
+		case SERVICE_CONTROL_PAUSE:
+			// 暂停服务;
+			break;
+		case SERVICE_CONTROL_CONTINUE:
+			// 恢复被暂停的服务;
+			break;
+		case SERVICE_CONTROL_INTERROGATE:
+			break;
+		default:
+			SvcReportEvent(_T("Bad service request"));
+		}
+	}
+
+	/************************************************************************/
+	/*  函数:ReportSvcStatus[4/22/2016 home];
+	/*  描述:设置当前服务状态,并将其报告给SCM;
+	/*  参数:;
+	/*  	[IN] dwCurrentState:服务当前状态(详情见 SERVICE_STATUS);
+	/*  	[IN] dwWin32ExitCode:系统返回服务的错误码;
+	/*  	[IN] dwServiceSpecificExitCode:用户自定义的服务错误码;
+	/*  	[OUT] dwCheckPoint:;
+	/*  	[IN/OUT] dwWaitHint:挂起操作的估计用时;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint)
+	{
+		BOOL bSuccess;
+		// 填充SERVICE_STATUS结构体,以便用于设置服务状态;
+		g_scVariant.scStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;		// 表示我们的服务是独占一个进程的服务 ;
+		g_scVariant.scStatus.dwCurrentState = dwCurrentState;				// 当前服务状态;
+		g_scVariant.scStatus.dwWaitHint = dwWaitHint;
+
+		if (dwCurrentState == SERVICE_START_PENDING)
+		{
+			g_scVariant.scStatus.dwControlsAccepted = 0; // 不接受任何控制通知; 
+		}
+		else
+		{
+			// 通知 SCM 服务接受哪个控制通知:这里允许停止、关机、暂停继续;
+			g_scVariant.scStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; //|SERVICE_ACCEPT_PAUSE_CONTINUE;
+		}
+
+		if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED))
+			g_scVariant.scStatus.dwCheckPoint = 0;
+		else
+			g_scVariant.scStatus.dwCheckPoint = dwCheckPoint++;
+
+		// dwServiceSpecificExitCode在你终止服务并报告退出细节时很有用。
+		// 初始化服务时并不退出,因此值为 0; 
+		if (dwServiceSpecificExitCode == 0)
+		{
+			g_scVariant.scStatus.dwWin32ExitCode = dwWin32ExitCode;
+		}
+		else
+		{
+			g_scVariant.scStatus.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; //用户自定义错误代码;
+		}
+		g_scVariant.scStatus.dwServiceSpecificExitCode = dwServiceSpecificExitCode;
+
+		//设置好nServiceStatus后,向SCM报告服务状态,非0表示成功,0表示失败;
+		bSuccess = SetServiceStatus(g_scVariant.scStatusHandle, &g_scVariant.scStatus);
+		if (!bSuccess)
+		{
+			SvcReportEvent(_T("Set Service Status failed (%d) "), GetLastError());
+			KillService();
+			return FALSE;
+		}
+		else
+			return TRUE;
+	}
+
+	// 结束服务;
+	void KillService()
+	{
+		if (g_scVariant.hscEvent)
+			SetEvent(g_scVariant.hscEvent); //如果操作成功,则返回非零值,否则为0。设置事件的状态为有标记,释放任意等待线程。如果事件是手工的,此事件将保持有标记直到调用ResetEvent。这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设置事件的状态为无标记。如果没有线程在等待,则此事件将保持有标记,直到一个线程被释放。
+		//ReportStatusToSCMgr(SERVICE_STOPPED,NO_ERROR,0,0,0); 
+	}
+
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void SvcReportEvent(IN LPCTSTR pFormat, ...)
+	{
+		TCHAR    szReport[MAX_PATH] = { 0 };
+		HANDLE   hEventSource;
+		LPCTSTR  lpszStrings[2];
+		va_list  pArg = NULL;
+
+		va_start(pArg, pFormat);
+		StringCchVPrintf(szReport, MAX_PATH, pFormat, pArg);
+		va_end(pArg);
+
+		hEventSource = RegisterEventSource(NULL, g_scVariant.scName);
+		if (hEventSource != NULL)
+		{
+			lpszStrings[0] = g_scVariant.scName;
+			lpszStrings[1] = szReport;
+
+			ReportEvent(
+				hEventSource,					// 事件日志句柄;
+				EVENTLOG_INFORMATION_TYPE,		// 事件类型;
+				0,								// 事件类别;
+				0/*SVC_ERROR*/,					// 事件标识;
+				NULL,							// 无安全标识;
+				2,								// lpszStrings数组大小;
+				0,								// 无二进制数据;
+				lpszStrings,					// 字符串数组;
+				NULL							// 无二进制数据;
+			);
+
+			DeregisterEventSource(hEventSource);
+		}
+	}
+
+	/************************************************************************/
+	/*  函数:StartSvc[4/23/2016 home];
+	/*  描述:启动服务;
+	/*  参数:;
+	/*  	[IN] lpSvcName:要打开的服务名称;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void StartSvc(IN LPCTSTR lpSvcName)
+	{
+		TCHAR szSvcName[MAX_PATH] = { 0 };
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+			_stprintf_s(szSvcName, _T("%s"), g_scVariant.scName);
+		else
+			_stprintf_s(szSvcName, _T("%s"), lpSvcName);
+
+		SC_HANDLE schSCM;
+		SC_HANDLE schService;
+		SERVICE_STATUS_PROCESS ssStatus;
+		DWORD dwOldCheckPoint;
+		DWORD dwStartTickCount;
+		DWORD dwWaitTime;
+		DWORD dwBytesNeeded;
+
+		// 打开服务管理器; 
+		schSCM = OpenSCManager(
+			NULL,                    // NULL表示要地计算机;
+			NULL,                    // NULl表示服务活动数据库; 
+			SC_MANAGER_ALL_ACCESS);  // 全部管理权限; 
+
+		if (NULL == schSCM)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		schService = OpenService(
+			schSCM,					// SCM数据库; 
+			szSvcName,				// 服务名称;
+			SERVICE_ALL_ACCESS);	// 全部权限;
+
+		if (schService == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// 启动服务前,检查服务状态以防服务不是停止的状态;
+		if (!QueryServiceStatusEx(
+			schService,                     // 服务句柄; 
+			SC_STATUS_PROCESS_INFO,         // 要查询的服务状态类型;
+			(LPBYTE)&ssStatus,             // 服务状态对象地址;
+			sizeof(SERVICE_STATUS_PROCESS), // 结构体大小;
+			&dwBytesNeeded))              // size needed if buffer is too small
+		{
+			_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService);
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// Check if the service is already running. It would be possible 
+		// to stop the service here, but for simplicity this example just returns. 
+		// 如果服务已经在运行,检查;可以在这里停止服务,简单起见,这里只返回;
+		if (ssStatus.dwCurrentState != SERVICE_STOPPED && ssStatus.dwCurrentState != SERVICE_STOP_PENDING)
+		{
+			_tprintf_s(_T("Cannot start the service because it is already running\n"));
+			CloseServiceHandle(schService);
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// Save the tick count and initial checkpoint.
+		// 保持计数值并初始化检查点;
+		dwStartTickCount = GetTickCount();
+		dwOldCheckPoint = ssStatus.dwCheckPoint;
+
+		// Wait for the service to stop before attempting to start it.
+		// 在尝试启动服务前,等待服务停止;
+		while (ssStatus.dwCurrentState == SERVICE_STOP_PENDING)
+		{
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth of the wait hint but not less than 1 second  
+			// and not more than 10 seconds. 
+
+			dwWaitTime = ssStatus.dwWaitHint / 10;
+
+			if (dwWaitTime < 1000)
+				dwWaitTime = 1000;
+			else if (dwWaitTime > 10000)
+				dwWaitTime = 10000;
+
+			Sleep(dwWaitTime);
+
+			// Check the status until the service is no longer stop pending. 
+			// 检测状态直到服务不再停止等待;
+			if (!QueryServiceStatusEx(
+				schService,                     // handle to service 
+				SC_STATUS_PROCESS_INFO,         // information level
+				(LPBYTE)&ssStatus,             // address of structure
+				sizeof(SERVICE_STATUS_PROCESS), // size of structure
+				&dwBytesNeeded))              // size needed if buffer is too small
+			{
+				_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+				CloseServiceHandle(schService);
+				CloseServiceHandle(schSCM);
+				return;
+			}
+
+			if (ssStatus.dwCheckPoint > dwOldCheckPoint)
+			{
+				// Continue to wait and check.
+				// 继续等待并检测;
+				dwStartTickCount = GetTickCount();
+				dwOldCheckPoint = ssStatus.dwCheckPoint;
+			}
+			else
+			{
+				if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint)
+				{
+					_tprintf_s(_T("Timeout waiting for service to stop\n"));
+					CloseServiceHandle(schService);
+					CloseServiceHandle(schSCM);
+					return;
+				}
+			}
+		}
+
+		// Attempt to start the service.
+		// 尝试启动服务;
+		if (!StartService(
+			schService,  // handle to service 
+			0,           // number of arguments 
+			NULL))      // no arguments 
+		{
+			_tprintf_s(_T("StartService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService);
+			CloseServiceHandle(schSCM);
+			return;
+		}
+		else printf("Service start pending...\n");
+
+		// Check the status until the service is no longer start pending. 
+		// 检测服务状态直到服务不再启动挂起操作;
+		if (!QueryServiceStatusEx(
+			schService,                     // handle to service 
+			SC_STATUS_PROCESS_INFO,         // info level
+			(LPBYTE)&ssStatus,             // address of structure
+			sizeof(SERVICE_STATUS_PROCESS), // size of structure
+			&dwBytesNeeded))              // if buffer too small
+		{
+			_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schService);
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// Save the tick count and initial checkpoint.
+		dwStartTickCount = GetTickCount();
+		dwOldCheckPoint = ssStatus.dwCheckPoint;
+
+		while (ssStatus.dwCurrentState == SERVICE_START_PENDING)
+		{
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth the wait hint, but no less than 1 second and no 
+			// more than 10 seconds. 
+
+			dwWaitTime = ssStatus.dwWaitHint / 10;
+
+			if (dwWaitTime < 1000)
+				dwWaitTime = 1000;
+			else if (dwWaitTime > 10000)
+				dwWaitTime = 10000;
+
+			Sleep(dwWaitTime);
+
+			// Check the status again. 
+			if (!QueryServiceStatusEx(
+				schService,             // handle to service 
+				SC_STATUS_PROCESS_INFO, // info level
+				(LPBYTE)&ssStatus,             // address of structure
+				sizeof(SERVICE_STATUS_PROCESS), // size of structure
+				&dwBytesNeeded))              // if buffer too small
+			{
+				_tprintf_s(_T("QueryServiceStatusEx failed (%d)\n"), GetLastError());
+				break;
+			}
+
+			if (ssStatus.dwCheckPoint > dwOldCheckPoint)
+			{
+				// Continue to wait and check.
+				dwStartTickCount = GetTickCount();
+				dwOldCheckPoint = ssStatus.dwCheckPoint;
+			}
+			else
+			{
+				if (GetTickCount() - dwStartTickCount > ssStatus.dwWaitHint)
+				{
+					// No progress made within the wait hint.
+					break;
+				}
+			}
+		}
+
+		// Determine whether the service is running.
+		if (ssStatus.dwCurrentState == SERVICE_RUNNING)
+		{
+			_tprintf_s(_T("Service started successfully.\n"));
+		}
+		else
+		{
+			_tprintf_s(_T("Service not started. \n"));
+			_tprintf_s(_T("  Current State: %d\n"), ssStatus.dwCurrentState);
+			_tprintf_s(_T("  Exit Code: %d\n"), ssStatus.dwWin32ExitCode);
+			_tprintf_s(_T("  Check Point: %d\n"), ssStatus.dwCheckPoint);
+			_tprintf_s(_T("  Wait Hint: %d\n"), ssStatus.dwWaitHint);
+		}
+
+		CloseServiceHandle(schService);
+		CloseServiceHandle(schSCM);
+
+	}
+
+	/************************************************************************/
+	/*  函数:UpdateSvcDacl[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void UpdateSvcDacl(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+			return;
+
+		EXPLICIT_ACCESS      ea;
+		SECURITY_DESCRIPTOR  sd;
+		PSECURITY_DESCRIPTOR psd = NULL;
+		PACL                 pacl = NULL;
+		PACL                 pNewAcl = NULL;
+		BOOL                 bDaclPresent = FALSE;
+		BOOL                 bDaclDefaulted = FALSE;
+		DWORD                dwError = 0;
+		DWORD                dwSize = 0;
+		DWORD                dwBytesNeeded = 0;
+
+		SC_HANDLE schSCManager;
+		SC_HANDLE schService;
+
+		// 获取SCM数据库的句柄值;
+		schSCManager = OpenSCManager(
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCManager)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// Get a handle to the service
+
+		schService = OpenService(
+			schSCManager,              // SCManager database 
+			lpSvcName,                 // name of service 
+			READ_CONTROL | WRITE_DAC); // access
+
+		if (schService == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCManager);
+			return;
+		}
+
+		// Get the current security descriptor.
+		// 获取当前服务的安全描述符;
+		if (!QueryServiceObjectSecurity(schService,
+			DACL_SECURITY_INFORMATION,
+			&psd,           // using NULL does not work on all versions
+			0,
+			&dwBytesNeeded))
+		{
+			if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+			{
+				dwSize = dwBytesNeeded;
+				psd = (PSECURITY_DESCRIPTOR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwSize);
+				if (psd == NULL)
+				{
+					// Note: HeapAlloc does not support GetLastError.
+					_tprintf_s(_T("HeapAlloc failed\n"));
+					goto dacl_cleanup;
+				}
+
+				if (!QueryServiceObjectSecurity(schService,
+					DACL_SECURITY_INFORMATION, psd, dwSize, &dwBytesNeeded))
+				{
+					_tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
+					goto dacl_cleanup;
+				}
+			}
+			else
+			{
+				_tprintf_s(_T("QueryServiceObjectSecurity failed (%d)\n"), GetLastError());
+				goto dacl_cleanup;
+			}
+		}
+
+		// Get the DACL.
+
+		if (!GetSecurityDescriptorDacl(psd, &bDaclPresent, &pacl,
+			&bDaclDefaulted))
+		{
+			_tprintf_s(_T("GetSecurityDescriptorDacl failed(%d)\n"), GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Build the ACE.
+
+		BuildExplicitAccessWithName(&ea, TEXT("GUEST"),
+			SERVICE_START | SERVICE_STOP | READ_CONTROL | DELETE,
+			SET_ACCESS, NO_INHERITANCE);
+
+		dwError = SetEntriesInAcl(1, &ea, pacl, &pNewAcl);
+		if (dwError != ERROR_SUCCESS)
+		{
+			printf("SetEntriesInAcl failed(%d)\n", dwError);
+			goto dacl_cleanup;
+		}
+
+		// Initialize a new security descriptor.
+
+		if (!InitializeSecurityDescriptor(&sd,
+			SECURITY_DESCRIPTOR_REVISION))
+		{
+			printf("InitializeSecurityDescriptor failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Set the new DACL in the security descriptor.
+
+		if (!SetSecurityDescriptorDacl(&sd, TRUE, pNewAcl, FALSE))
+		{
+			printf("SetSecurityDescriptorDacl failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+
+		// Set the new DACL for the service object.
+
+		if (!SetServiceObjectSecurity(schService,
+			DACL_SECURITY_INFORMATION, &sd))
+		{
+			printf("SetServiceObjectSecurity failed(%d)\n", GetLastError());
+			goto dacl_cleanup;
+		}
+		else printf("Service DACL updated successfully\n");
+
+	dacl_cleanup:
+		CloseServiceHandle(schSCManager);
+		CloseServiceHandle(schService);
+
+		if (NULL != pNewAcl)
+			LocalFree((HLOCAL)pNewAcl);
+		if (NULL != psd)
+			HeapFree(GetProcessHeap(), 0, (LPVOID)psd);
+
+	}
+
+	void StopSvc(IN LPCTSTR lpSvcName)
+	{
+		TCHAR szSvcName[MAX_PATH] = { 0 };
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+			_stprintf_s(szSvcName, _T("%s"), g_scVariant.scName);
+		else
+			_stprintf_s(szSvcName, _T("%s"), lpSvcName);
+
+		SERVICE_STATUS_PROCESS ssp;
+		DWORD dwStartTime = GetTickCount();
+		DWORD dwBytesNeeded;
+		DWORD dwTimeout = 30000; // 30-second time-out
+		DWORD dwWaitTime;
+
+		SC_HANDLE schSCManager;
+		SC_HANDLE schService;
+		// Get a handle to the SCM database. 
+
+		schSCManager = OpenSCManager(
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCManager)
+		{
+			printf("OpenSCManager failed (%d)\n", GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+
+		schService = OpenService(
+			schSCManager,         // SCM database 
+			szSvcName,            // name of service 
+			SERVICE_STOP |
+			SERVICE_QUERY_STATUS |
+			SERVICE_ENUMERATE_DEPENDENTS);
+
+		if (schService == NULL)
+		{
+			printf("OpenService failed (%d)\n", GetLastError());
+			CloseServiceHandle(schSCManager);
+			return;
+		}
+
+		// Make sure the service is not already stopped.
+
+		if (!QueryServiceStatusEx(
+			schService,
+			SC_STATUS_PROCESS_INFO,
+			(LPBYTE)&ssp,
+			sizeof(SERVICE_STATUS_PROCESS),
+			&dwBytesNeeded))
+		{
+			printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
+			goto stop_cleanup;
+		}
+
+		if (ssp.dwCurrentState == SERVICE_STOPPED)
+		{
+			printf("Service is already stopped.\n");
+			goto stop_cleanup;
+		}
+
+		// If a stop is pending, wait for it.
+
+		while (ssp.dwCurrentState == SERVICE_STOP_PENDING)
+		{
+			printf("Service stop pending...\n");
+
+			// Do not wait longer than the wait hint. A good interval is 
+			// one-tenth of the wait hint but not less than 1 second  
+			// and not more than 10 seconds. 
+
+			dwWaitTime = ssp.dwWaitHint / 10;
+
+			if (dwWaitTime < 1000)
+				dwWaitTime = 1000;
+			else if (dwWaitTime > 10000)
+				dwWaitTime = 10000;
+
+			Sleep(dwWaitTime);
+
+			if (!QueryServiceStatusEx(
+				schService,
+				SC_STATUS_PROCESS_INFO,
+				(LPBYTE)&ssp,
+				sizeof(SERVICE_STATUS_PROCESS),
+				&dwBytesNeeded))
+			{
+				printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
+				goto stop_cleanup;
+			}
+
+			if (ssp.dwCurrentState == SERVICE_STOPPED)
+			{
+				printf("Service stopped successfully.\n");
+				goto stop_cleanup;
+			}
+
+			if (GetTickCount() - dwStartTime > dwTimeout)
+			{
+				printf("Service stop timed out.\n");
+				goto stop_cleanup;
+			}
+		}
+
+		// If the service is running, dependencies must be stopped first.
+
+		StopDependentServices();
+
+		// Send a stop code to the service.
+
+		if (!ControlService(
+			schService,
+			SERVICE_CONTROL_STOP,
+			(LPSERVICE_STATUS)&ssp))
+		{
+			printf("ControlService failed (%d)\n", GetLastError());
+			goto stop_cleanup;
+		}
+
+		// Wait for the service to stop.
+
+		while (ssp.dwCurrentState != SERVICE_STOPPED)
+		{
+			Sleep(ssp.dwWaitHint);
+			if (!QueryServiceStatusEx(
+				schService,
+				SC_STATUS_PROCESS_INFO,
+				(LPBYTE)&ssp,
+				sizeof(SERVICE_STATUS_PROCESS),
+				&dwBytesNeeded))
+			{
+				printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
+				goto stop_cleanup;
+			}
+
+			if (ssp.dwCurrentState == SERVICE_STOPPED)
+				break;
+
+			if (GetTickCount() - dwStartTime > dwTimeout)
+			{
+				printf("Wait timed out\n");
+				goto stop_cleanup;
+			}
+		}
+		printf("Service stopped successfully\n");
+
+	stop_cleanup:
+		CloseServiceHandle(schService);
+		CloseServiceHandle(schSCManager);
+
+	}
+
+	BOOL StopDependentServices()
+	{
+		DWORD i;
+		DWORD dwBytesNeeded;
+		DWORD dwCount;
+
+		LPENUM_SERVICE_STATUS   lpDependencies = NULL;
+		ENUM_SERVICE_STATUS     ess;
+		SC_HANDLE               hDepService;
+		SERVICE_STATUS_PROCESS  ssp;
+
+		DWORD dwStartTime = GetTickCount();
+		DWORD dwTimeout = 30000; // 30-second time-out
+
+		SC_HANDLE schSCManager = NULL;
+		SC_HANDLE schService = NULL;
+
+		// Pass a zero-length buffer to get the required buffer size.
+		if (EnumDependentServices(schService, SERVICE_ACTIVE,
+			lpDependencies, 0, &dwBytesNeeded, &dwCount))
+		{
+			// If the Enum call succeeds, then there are no dependent
+			// services, so do nothing.
+			return TRUE;
+		}
+		else
+		{
+			if (GetLastError() != ERROR_MORE_DATA)
+				return FALSE; // Unexpected error
+
+			// Allocate a buffer for the dependencies.
+			lpDependencies = (LPENUM_SERVICE_STATUS)HeapAlloc(
+				GetProcessHeap(), HEAP_ZERO_MEMORY, dwBytesNeeded);
+
+			if (!lpDependencies)
+				return FALSE;
+
+			__try {
+				// Enumerate the dependencies.
+				if (!EnumDependentServices(schService, SERVICE_ACTIVE,
+					lpDependencies, dwBytesNeeded, &dwBytesNeeded,
+					&dwCount))
+					return FALSE;
+
+				for (i = 0; i < dwCount; i++)
+				{
+					ess = *(lpDependencies + i);
+					// Open the service.
+					hDepService = OpenService(schSCManager,
+						ess.lpServiceName,
+						SERVICE_STOP | SERVICE_QUERY_STATUS);
+
+					if (!hDepService)
+						return FALSE;
+
+					__try {
+						// Send a stop code.
+						if (!ControlService(hDepService,
+							SERVICE_CONTROL_STOP,
+							(LPSERVICE_STATUS)&ssp))
+							return FALSE;
+
+						// Wait for the service to stop.
+						while (ssp.dwCurrentState != SERVICE_STOPPED)
+						{
+							Sleep(ssp.dwWaitHint);
+							if (!QueryServiceStatusEx(
+								hDepService,
+								SC_STATUS_PROCESS_INFO,
+								(LPBYTE)&ssp,
+								sizeof(SERVICE_STATUS_PROCESS),
+								&dwBytesNeeded))
+								return FALSE;
+
+							if (ssp.dwCurrentState == SERVICE_STOPPED)
+								break;
+
+							if (GetTickCount() - dwStartTime > dwTimeout)
+								return FALSE;
+						}
+					}
+					__finally
+					{
+						// Always release the service handle.
+						CloseServiceHandle(hDepService);
+					}
+				}
+			}
+			__finally
+			{
+				// Always free the enumeration buffer.
+				HeapFree(GetProcessHeap(), 0, lpDependencies);
+			}
+		}
+		return TRUE;
+
+	}
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoQuerySvc(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要查询的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE hSCM;
+		SC_HANDLE hSvc;
+		LPQUERY_SERVICE_CONFIG lpsc;
+		LPSERVICE_DESCRIPTION lpsd;
+		DWORD dwBytesNeeded, cbBfuSize, dwError;
+
+		// 获取SCM句柄;
+		hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+		if (hSCM == NULL)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		hSvc = OpenService(
+			hSCM,
+			lpSvcName,
+			SERVICE_QUERY_CONFIG			// 需要查询设置的权限;
+		);
+		if (hSvc == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(hSCM);
+			return;
+		}
+
+		// 获取服务设置信息;
+		if (!QueryServiceConfig(hSvc, NULL, 0, &dwBytesNeeded))
+		{
+			dwError = GetLastError();
+			if (ERROR_INSUFFICIENT_BUFFER == dwError)
+			{
+				cbBfuSize = dwBytesNeeded;
+				lpsc = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LMEM_FIXED, cbBfuSize);
+			}
+			else
+			{
+				_tprintf_s(_T("QueryServiceConfig failed (%d)\n"), dwError);
+				goto cleanup;
+			}
+		}
+
+		if (!QueryServiceConfig(hSvc, lpsc, cbBfuSize, &dwBytesNeeded))
+		{
+			_tprintf_s(_T("QuerySericeConfig failed (%d)\n"), GetLastError());
+			goto cleanup;
+		}
+
+		if (!QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, NULL, 0, &dwBytesNeeded))
+		{
+			dwError = GetLastError();
+			if (ERROR_INSUFFICIENT_BUFFER == dwError)
+			{
+				cbBfuSize = dwBytesNeeded;
+				lpsd = (LPSERVICE_DESCRIPTION)LocalAlloc(LMEM_FIXED, cbBfuSize);
+			}
+			else
+			{
+				_tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
+				goto cleanup;
+			}
+		}
+
+		if (!QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, (LPBYTE)lpsd, cbBfuSize, &dwBytesNeeded))
+		{
+			_tprintf_s(_T("QuerySericeConfig2 failed (%d)\n"), GetLastError());
+			goto cleanup;
+		}
+
+		//////////////////////////////////////////////////////////////////////////
+		// 查询成功,组织要返回的东西;
+		_tprintf(TEXT("%s configuration: \n"), g_scVariant.scName);
+		_tprintf(TEXT("  Type: 0x%x\n"), lpsc->dwServiceType);
+		_tprintf(TEXT("  Start Type: 0x%x\n"), lpsc->dwStartType);
+		_tprintf(TEXT("  Error Control: 0x%x\n"), lpsc->dwErrorControl);
+		_tprintf(TEXT("  Binary path: %s\n"), lpsc->lpBinaryPathName);
+		_tprintf(TEXT("  Account: %s\n"), lpsc->lpServiceStartName);
+
+		if (lpsd->lpDescription != NULL && lstrcmp(lpsd->lpDescription, TEXT("")) != 0)
+			_tprintf(TEXT("  Description: %s\n"), lpsd->lpDescription);
+		if (lpsc->lpLoadOrderGroup != NULL && lstrcmp(lpsc->lpLoadOrderGroup, TEXT("")) != 0)
+			_tprintf(TEXT("  Load order group: %s\n"), lpsc->lpLoadOrderGroup);
+		if (lpsc->dwTagId != 0)
+			_tprintf(TEXT("  Tag ID: %d\n"), lpsc->dwTagId);
+		if (lpsc->lpDependencies != NULL && lstrcmp(lpsc->lpDependencies, TEXT("")) != 0)
+			_tprintf(TEXT("  Dependencies: %s\n"), lpsc->lpDependencies);
+
+		// 释放资源;
+		LocalFree(lpsc);
+		LocalFree(lpsd);
+
+	cleanup:
+		CloseServiceHandle(hSvc);
+		CloseServiceHandle(hSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoDisableSvc(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要禁用的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+
+		// 打开SCM;
+		schSCM = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
+		if (schSCM == NULL)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 获取服务句柄;
+		schSvc = OpenService(schSCM, lpSvcName, SERVICE_CHANGE_CONFIG);
+		if (schSvc == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		if (!ChangeServiceConfig(
+			schSvc,
+			SERVICE_NO_CHANGE, // service type: no change 
+			SERVICE_DISABLED,  // service start type 
+			SERVICE_NO_CHANGE, // error control: no change 
+			NULL,              // binary path: no change 
+			NULL,              // load order group: no change 
+			NULL,              // tag ID: no change 
+			NULL,              // dependencies: no change 
+			NULL,              // account name: no change 
+			NULL,              // password: no change 
+			NULL))            // display name: no change
+		{
+			_tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
+		}
+
+		CloseServiceHandle(schSvc);
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoEnableSvc(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要启用的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+
+		// Get a handle to the SCM database. 
+		// 获取SCM数据库句柄;
+		schSCM = OpenSCManager(
+			NULL,                    // local computer
+			NULL,                    // ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM)
+		{
+			printf("OpenSCManager failed (%d)\n", GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+		// 获取服务句柄值;
+		schSvc = OpenService(
+			schSCM,						// SCM database 
+			lpSvcName,                // name of service 
+			SERVICE_CHANGE_CONFIG);		// need change config access 
+
+		if (schSvc == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// Change the service start type.
+		// 改变服务启动类型;
+		if (!ChangeServiceConfig(
+			schSvc,					// 服务句柄; 
+			SERVICE_NO_CHANGE,     // service type: no change 
+			SERVICE_DEMAND_START,  // service start type 
+			SERVICE_NO_CHANGE,     // error control: no change 
+			NULL,                  // binary path: no change 
+			NULL,                  // load order group: no change 
+			NULL,                  // tag ID: no change 
+			NULL,                  // dependencies: no change 
+			NULL,                  // account name: no change 
+			NULL,                  // password: no change 
+			NULL))                // display name: no change
+		{
+			_tprintf_s(_T("ChangeServiceConfig failed (%d)\n"), GetLastError());
+		}
+		else
+		{
+			_tprintf_s(_T("Service enabled successfully.\n"));
+		}
+
+		CloseServiceHandle(schSvc);
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoUpdateSvcDesc(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要更新描述的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+		SERVICE_DESCRIPTION sd;
+		LPTSTR szDesc = TEXT("This is a test description");
+
+		// Get a handle to the SCM database. 
+		// 获取SCM数据库句柄;
+		schSCM = OpenSCManager(
+			NULL,                    // NULL表示本地计算机;
+			NULL,                    // NULL表示:ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// Get a handle to the service.
+		// 获取服务句柄值;
+		schSvc = OpenService(
+			schSCM,						// SCM 数据库句柄; 
+			lpSvcName,                // 服务名称; 
+			SERVICE_CHANGE_CONFIG);     // need change config access 
+
+		if (schSvc == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// Change the service description.
+		// 改变服务描述;
+		sd.lpDescription = szDesc;
+
+		if (!ChangeServiceConfig2(
+			schSvc,						// 服务句柄;
+			SERVICE_CONFIG_DESCRIPTION, // 要改变的类型: description;
+			&sd))                      // 新描述;
+		{
+			_tprintf_s(_T("ChangeServiceConfig2 failed\n"));
+		}
+		else
+		{
+			_tprintf_s(_T("Service description updated successfully.\n"));
+		}
+
+		CloseServiceHandle(schSvc);
+		CloseServiceHandle(schSCM);
+
+	}
+
+	/************************************************************************/
+	/*  函数:[4/23/2016 home];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void DoDeleteSvc(IN LPCTSTR lpSvcName)
+	{
+		if (lpSvcName == NULL || lpSvcName[0] == _T('\0'))
+		{
+			_tprintf_s(_T("要删除的服务名称无效\n"));
+			return;
+		}
+		SC_HANDLE schSCM;
+		SC_HANDLE schSvc;
+		SERVICE_STATUS ssStatus;
+
+		// 打开服务管理器;
+		schSCM = OpenSCManager(
+			NULL,                    // NULL表示本地计算机;
+			NULL,                    // NULL表示ServicesActive database 
+			SC_MANAGER_ALL_ACCESS);  // full access rights 
+
+		if (NULL == schSCM)
+		{
+			_tprintf_s(_T("OpenSCManager failed (%d)\n"), GetLastError());
+			return;
+		}
+
+		// 打开服务;
+		schSvc = OpenService(
+			schSCM,								// SCM database 
+			lpSvcName,							// name of service 
+			SERVICE_STOP | DELETE					// need delete access 
+		);
+
+		if (schSvc == NULL)
+		{
+			_tprintf_s(_T("OpenService failed (%d)\n"), GetLastError());
+			CloseServiceHandle(schSCM);
+			return;
+		}
+
+		// 删除服务关,需要先停止服务;
+		if (!::ControlService(schSvc, SERVICE_CONTROL_STOP, &ssStatus))
+		{
+			_tprintf_s(_T("删除服务前停止服务失败 (%d)\n"), GetLastError());
+		}
+
+		// 删除服务;
+		if (!DeleteService(schSvc))
+		{
+			_tprintf_s(_T("DeleteService failed (%d)\n"), GetLastError());
+			SvcReportEvent(_T("Service could not be deleted"));
+		}
+		else
+		{
+			_tprintf_s(_T("Service deleted successfully\n"));
+		}
+
+		CloseServiceHandle(schSvc);
+		CloseServiceHandle(schSCM);
+	}
+
+	/************************************************************************/
+	/*  函数:SetCallBack[5/5/2016 Home];
+	/*  描述:设置回调函数;
+	/*  参数:;
+	/*  	[IN] lpStartWorkCallBack:工作开始回调指针;
+	/*  	[IN] lpEndofWorkCallBack:工作结束回调指针;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	void SetCallBack(IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack)
+	{
+		if (g_scVariant.lpStartWorkCallBack == NULL)
+			g_scVariant.lpStartWorkCallBack = (WorkEndofCallback)lpStartWorkCallBack;
+
+		if (g_scVariant.lpEndofWorkCallBack == NULL)
+			g_scVariant.lpEndofWorkCallBack = (WorkEndofCallback)lpEndofWorkCallBack;
+	}
+
+	/************************************************************************/
+	/*  函数:StartProcess[5/6/2016 IT];
+	/*  描述:在服务进程里,调用外部EXE;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL StartProcess(IN LPCTSTR lpExePath)
+	{
+#if 0
+		if (!lpExePath || !PathFileExists(lpExePath))
+		{
+			return FALSE;
+		}
+
+		HANDLE hToken;
+		if (!GetTokenByName(hToken, _T("EXPLORER.EXE")))
+		{
+			return   FALSE;
+		}
+
+		STARTUPINFO   si;
+		PROCESS_INFORMATION   pi;
+
+		ZeroMemory(&si, sizeof(STARTUPINFO));
+		si.cb = sizeof(STARTUPINFO);
+		si.lpDesktop = TEXT("winsta0\\default");
+
+		BOOL bResult = CreateProcessAsUser(hToken, lpExePath, NULL, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
+		DWORD dwError = GetLastError();// 返回740错误,表示服务必须在Admin账号下运行才能创建成功;
+
+		//CreateProcessWithTokenW(hToken, )
+
+
+		CloseHandle(hToken);
+		if (bResult)
+		{
+			// WriteLogAlways(_T("C:\\serverlog.txt"),_T("CreateProcessAsUser   ok"));
+		}
+		else
+		{
+			//WriteLogAlways(_T("C:\\servererrlog.txt"),_T("CreateProcessAsUser   failed"));
+		}
+#else
+		HANDLE hPtoken = NULL;
+		GetExplorerToken(&hPtoken);
+		//if(!GetTokenByName(hPtoken,_T("EXPLORER.EXE")))   
+		//{   
+		//	return   FALSE;   
+		//} 
+		PROCESS_INFORMATION pi;
+		STARTUPINFOW si = { sizeof(STARTUPINFO), NULL, L"", NULL, 0, 0, 0, 0, 0, 0, 0, STARTF_USESHOWWINDOW, 0, 0, NULL, 0, 0, 0 };
+		si.wShowWindow = SW_SHOW;
+		si.lpDesktop = NULL;
+		ZeroMemory(&pi, sizeof(pi));
+
+		static HMODULE advapi32_dll = LoadLibraryW(L"advapi32.dll");
+		if (!advapi32_dll)
+			return FALSE;
+
+		/*static F_CreateProcessWithTokenW f_CreateProcessWithTokenW = (F_CreateProcessWithTokenW)(
+			GetProcAddress(advapi32_dll,"CreateProcessWithTokenW"));
+			if (f_CreateProcessWithTokenW == NULL)
+			return ;
+			*/
+		BOOL bResult = CreateProcessWithTokenW(hPtoken, LOGON_WITH_PROFILE, NULL, (LPWSTR)lpExePath, NULL, NULL, NULL, &si, &pi);
+
+		DWORD dwError = GetLastError();
+		Sleep(1000);
+		CloseHandle(pi.hProcess);
+
+		CloseHandle(pi.hThread);
+#endif
+		return   bResult;
+	}
+
+	/************************************************************************/
+	/*  函数:[5/6/2016 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	BOOL GetTokenByName(IN HANDLE &hToken, IN LPCTSTR lpName)
+	{
+		if (!lpName)
+		{
+			return FALSE;
+		}
+
+		BOOL bRet = FALSE;
+		HANDLE hProcessSnap = NULL;
+		PROCESSENTRY32 pe32 = { 0 };
+		hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+		if (hProcessSnap == INVALID_HANDLE_VALUE)
+			return FALSE;
+
+		pe32.dwSize = sizeof(PROCESSENTRY32);
+		if (Process32First(hProcessSnap, &pe32))
+		{
+			do
+			{
+				CString exefile = pe32.szExeFile;
+				CString paraname = lpName;
+				if (!exefile.CompareNoCase(lpName))
+				{
+					HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pe32.th32ProcessID);
+					bRet = OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken);
+					CloseHandle(hProcessSnap);
+					return bRet;
+				}
+			} while (Process32Next(hProcessSnap, &pe32));
+			bRet = TRUE;
+		}
+		else
+			bRet = FALSE;
+
+		CloseHandle(hProcessSnap);
+		return bRet;
+	}
+
+	/************************************************************************/
+	/*  函数:[5/6/2016 IT];
+	/*  描述:;
+	/*  参数:;
+	/*  	[IN] :;
+	/*  	[OUT] :;
+	/*  	[IN/OUT] :;
+	/*  返回:void;
+	/*  注意:;
+	/*  示例:;
+	/*
+	/*  修改:;
+	/*  日期:;
+	/*  内容:;
+	/************************************************************************/
+	// Jeff.Hacker. WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
+	BOOL GetDebugPriv()
+	{
+		// 返回的访问令牌指针;
+		HANDLE	hToken;
+		// 接收所返回的制定特权名称的信息;
+		LUID	sedebugnameValue;
+		// 新特权信息的指针(结构体);
+		TOKEN_PRIVILEGES tkp;
+		DWORD	dwCurProcId = GetCurrentProcessId();
+		// 要修改访问权限的进程句柄;
+		HANDLE	hCurProc;
+		hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
+
+		if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		{
+			//ShowSystemErrorInfo(_T("升级包OpenProcessToken失败."),GetLastError());
+			return FALSE;
+		}
+
+		if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
+		{
+			//ShowSystemErrorInfo(_T("升级包LookupPrivilegeValue失败."),GetLastError());
+			CloseHandle(hToken);
+			return FALSE;
+		}
+
+		tkp.PrivilegeCount = 1;
+		tkp.Privileges[0].Luid = sedebugnameValue;
+		tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+		if (!::AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
+		{
+			//ShowSystemErrorInfo(_T("升级包AdjustTokenPrivileges失败."),GetLastError());
+			CloseHandle(hToken);
+			return FALSE;
+		}
+
+		CloseHandle(hCurProc);
+		CloseHandle(hToken);
+		return TRUE;
+	}
+
+	DWORD GetExplorerToken(OUT HANDLE* phExplorerToken)
+	{
+		DWORD       dwStatus = ERROR_FILE_NOT_FOUND;
+		BOOL        bRet = FALSE;
+		HANDLE      hProcess = NULL;
+		HANDLE      hProcessSnap = NULL;
+		TCHAR       szExplorerPath[MAX_PATH] = { 0 };
+		TCHAR       FileName[MAX_PATH] = { 0 };
+		PROCESSENTRY32 pe32 = { 0 };
+		__try
+		{
+			GetWindowsDirectory(szExplorerPath, MAX_PATH);
+			_tcscat_s(szExplorerPath, MAX_PATH, _T("\\Explorer.EXE"));
+			hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+			if (hProcessSnap == INVALID_HANDLE_VALUE)
+			{
+				dwStatus = GetLastError();
+				__leave;
+			}
+			pe32.dwSize = sizeof(PROCESSENTRY32);
+			if (!Process32First(hProcessSnap, &pe32))
+			{
+				dwStatus = GetLastError();
+				__leave;
+			}
+
+			int ii = 0;
+			do
+			{
+				hProcess = OpenProcess(PROCESS_ALL_ACCESS/*PROCESS_QUERY_INFORMATION*/, FALSE, pe32.th32ProcessID);
+				if (NULL != hProcess)
+				{
+					ii++;
+					//if ( GetModuleFileNameEx(hProcess , NULL , FileName , MAX_PATH) )  
+					//{  
+					if (_tcsicmp(pe32.szExeFile, _T("Explorer.EXE")) == 0)
+					{
+						HANDLE  hToken;
+						if (OpenProcessToken(hProcess, TOKEN_DUPLICATE, &hToken))
+						{
+							HANDLE hNewToken = NULL;
+							DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hNewToken);
+							*phExplorerToken = hNewToken;
+							dwStatus = 0;
+							CloseHandle(hToken);
+						}
+						break;
+					}
+					//}  
+					CloseHandle(hProcess);
+					hProcess = NULL;
+				}
+
+			} while (Process32Next(hProcessSnap, &pe32));
+		}
+		__finally
+		{
+			if (NULL != hProcess)
+			{
+				CloseHandle(hProcess);
+			}
+			if (NULL != hProcessSnap)
+			{
+				CloseHandle(hProcessSnap);
+			}
+		}
+		return dwStatus;
+	}
+
+	// 打进服务事件日志里;
+	void LogEvent(IN LPCTSTR pFormat, ...)
+	{
+		TCHAR   chMsg[MAX_PATH];
+		HANDLE  hEventLog;
+		LPTSTR  lpszStrings[1];
+		va_list pArg;
+
+		va_start(pArg, pFormat);
+		StringCchVPrintf(chMsg, MAX_PATH, pFormat, pArg);
+		va_end(pArg);
+
+		lpszStrings[0] = chMsg;
+
+		hEventLog = RegisterEventSource(NULL, g_scVariant.scName);
+		if (hEventLog != NULL)
+		{
+			ReportEvent(hEventLog, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*)&lpszStrings[0], NULL);
+			if (hEventLog)
+				DeregisterEventSource(hEventLog);
+		}
+	}
+};

+ 102 - 0
source/hook/WxService/WinService.h

@@ -0,0 +1,102 @@
+#ifndef __WINDOWS_SERVICE_20160113__
+#define __WINDOWS_SERVICE_20160113__
+
+#include <WinSvc.h>
+
+namespace WinService
+{
+	// 工作启动回调函数;
+	typedef void (CALLBACK *WorkStartCallback)();
+	// 工作结束回调函数;
+	typedef void (CALLBACK *WorkEndofCallback)();
+
+	typedef struct SCVARIANT {
+		TCHAR					scName[MAX_PATH];					// 服务名称;
+		TCHAR					scDisplayName[MAX_PATH];			// 服务显示名称;
+		TCHAR					scDescription[MAX_PATH];			// 服务描述内容;
+		HANDLE					hscEvent;							// 服务控制事件;
+		SERVICE_STATUS			scStatus;							// 服务状态;
+		SERVICE_STATUS_HANDLE	scStatusHandle;						// 服务状态句柄;
+		WorkStartCallback		lpStartWorkCallBack;				// 开启工作者;
+		WorkEndofCallback		lpEndofWorkCallBack;				// 结束工作者;
+
+		SCVARIANT()
+		{
+			hscEvent = NULL;
+			scStatusHandle = NULL;
+			lpStartWorkCallBack = NULL;
+			lpEndofWorkCallBack = NULL;
+			memset(scName, 0, MAX_PATH * sizeof(TCHAR));
+			memset(scDescription, 0, MAX_PATH * sizeof(TCHAR));
+
+			// 设置服务类型;
+			scStatus.dwServiceType =
+				SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; // | SERVICE_INTERACTIVE_PROCESS与桌面交互;
+			// 设置服务默认状态为停止;
+			scStatus.dwCurrentState = SERVICE_STOPPED; // SERVICE_RUNNING;
+			// 设置服务接受停止控制;
+			scStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
+			scStatus.dwWin32ExitCode = 0;
+			scStatus.dwServiceSpecificExitCode = 0;
+			scStatus.dwCheckPoint = 0;
+			scStatus.dwWaitHint = 0;
+		}
+	}SCVariant, *pSCVariant;
+
+	extern SCVariant g_scVariant;
+
+	// 设置服务名称和描述名称;
+	void InitServiceName(IN LPCTSTR lpServiceName = NULL, IN LPCTSTR lpServiceDescription = NULL);
+	// 服务是否安装;
+	BOOL IsInstalled();
+	// 安装服务;
+	BOOL Install();
+	BOOL Uninstall();
+	// windows服务程序入口函数;
+	extern void WINAPI ServiceMain();
+	// windows服务状态控制;
+	extern void WINAPI SvcCtrlHandler(IN DWORD dwControlCode);
+	// 初始化SOCKET库;
+	extern int InitWinSock();
+	// 服务日志事件;
+	extern void SvcReportEvent(IN LPCTSTR pFormat, ...);
+	// 向SCM报告服务状态;
+	extern BOOL ReportSvcStatus(
+		IN DWORD dwCurrentState,
+		IN DWORD dwWin32ExitCode,
+		IN DWORD dwServiceSpecificExitCode,
+		IN DWORD dwCheckPoint,
+		IN DWORD dwWaitHint);
+
+	// 启动指定的服务;
+	extern void StartSvc(IN LPCTSTR lpSvcName = NULL);
+	extern void StopSvc(IN LPCTSTR lpSvcName = NULL);
+	extern void KillService();
+	// 设置回调函数指针;
+	extern void SetCallBack(IN LPVOID lpStartWorkCallBack, IN LPVOID lpEndofWorkCallBack);
+	// 在服务进程里调用外部exe;
+	extern BOOL StartProcess(IN LPCTSTR lpExePath);
+	// 服务日志;
+	extern void LogEvent(IN LPCTSTR pFormat, ...);
+
+
+	extern void UpdateSvcDacl(IN LPCTSTR lpSvcName);
+	extern BOOL StopDependentServices();
+	// 查询服务状态;
+	extern void DoQuerySvc(IN LPCTSTR lpSvcName);
+	// 更新服务描述;
+	extern void DoUpdateSvcDesc(IN LPCTSTR lpSvcName);
+	extern void DoDisableSvc(IN LPCTSTR lpSvcName);
+	extern void DoEnableSvc(IN LPCTSTR lpSvcName);
+	extern void DoDeleteSvc(IN LPCTSTR lpSvcName);
+	//
+	extern BOOL GetTokenByName(IN HANDLE &hToken, IN LPCTSTR lpName);
+	//
+	extern BOOL GetDebugPriv();
+	//
+	extern DWORD GetExplorerToken(OUT HANDLE* phExplorerToken);
+
+};
+
+
+#endif

BIN
source/hook/WxService/WxService.aps


+ 124 - 0
source/hook/WxService/WxService.cpp

@@ -0,0 +1,124 @@
+// WxService.cpp : 定义控制台应用程序的入口点。
+//
+
+#include "stdafx.h"
+#include "WxService.h"
+#include "MainProcess.h"
+
+#ifdef _DEBUG
+#define new DEBUG_NEW
+#endif
+
+
+// 唯一的应用程序对象
+
+CWinApp theApp;
+
+using namespace std;
+
+// 工作启动回调函数;
+void CALLBACK WorkStart()
+{
+#ifdef _DEBUG
+	Sleep(8000);
+#endif
+	WinService::GetDebugPriv();
+	CMainProcess::GetInstance()->StartWork();
+}
+
+// 工作结束回调函数;
+void CALLBACK WorkEndof()
+{
+	CMainProcess::GetInstance()->EndofWork();
+}
+
+
+int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
+{
+	int nRetCode = 0;
+
+	// 直接获得前景窗口的句柄;
+	HWND hwnd = GetForegroundWindow(); 
+	SendMessage(hwnd , WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NULL,MAKEINTRESOURCE(IDI_MICON)));
+	HMODULE hModule = ::GetModuleHandle(NULL);
+
+	// 初始化 MFC 并在失败时显示错误
+	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
+	{
+		// TODO: 更改错误代码以符合您的需要
+		_tprintf(_T("错误: MFC 初始化失败\n"));
+		nRetCode = 1;
+	}
+	else
+	{
+		Global::GetIniInfo();
+
+		// 进程存在,直接退出;
+		TCHAR szExeName[MAX_PATH] = {0};
+		TCHAR szDrive[_MAX_DRIVE] = { 0 };
+		TCHAR szDir[_MAX_DIR] = { 0 };
+		TCHAR szFna[_MAX_DIR] = { 0 };
+		TCHAR szExt[_MAX_DIR] = { 0 };
+		_tsplitpath_s(Global::g_szModuleFileName, szDrive, szDir, szFna, szExt);
+		_stprintf_s(szExeName, _T("%s%s"), szFna, szExt);
+		if ( Global::FindProcessCount(szExeName) > 1)
+		{// 进程计数大于1,退出;
+			return 0;
+		}
+
+#if _DEBUG
+		WorkStart();
+		system("pause");
+		WorkEndof();
+#else
+		// 设置服务名和描述;
+		_stprintf_s(WinService::g_scVariant.scName, _T("WxService"));
+		_stprintf_s(WinService::g_scVariant.scDisplayName, _T("WxService"));
+		_stprintf_s(WinService::g_scVariant.scDescription, _T("微信服务"));
+
+		// 1.先判断服务是否存在;
+		if ( WinService::IsInstalled())
+		{
+			// 卸载服务;
+			if ( argc > 1)
+			{
+				if (_tcscmp((TCHAR *)argv[1], _T("/uninstall")) == 0)
+					WinService::DoDeleteSvc(WinService::g_scVariant.scName);
+				else
+					printf(_T("未有卸载服务参数行\n"));
+
+				system("pause");
+				return 0;
+			}
+			else 
+			{
+				WinService::SetCallBack(WorkStart, WorkEndof);
+				SERVICE_TABLE_ENTRY st[] =
+				{
+					{ WinService::g_scVariant.scName, (LPSERVICE_MAIN_FUNCTION)WinService::ServiceMain },
+					{ NULL, NULL }
+				};
+
+				if (!::StartServiceCtrlDispatcher(st))	// 在直接双击.exe时,这步会运行失败;
+				{
+					WinService::SvcReportEvent(_T("Register Service Main Function Error!"));
+					printf(_T("双击无法安装\n"));
+					system("pause");
+					return 0;
+				}
+			}
+		}
+
+		// 2.不存在,安装服务;
+		WinService::SetCallBack(WorkStart, WorkEndof);
+		SERVICE_TABLE_ENTRY st[] =
+		{
+			{ WinService::g_scVariant.scName, (LPSERVICE_MAIN_FUNCTION)WinService::ServiceMain },
+			{ NULL, NULL }
+		};
+
+		WinService::Install();
+	}
+#endif
+	return nRetCode;
+}

+ 3 - 0
source/hook/WxService/WxService.h

@@ -0,0 +1,3 @@
+#pragma once
+
+#include "resource.h"

+ 83 - 0
source/hook/WxService/WxService.rc

@@ -0,0 +1,83 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// 中文(中华人民共和国) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
+#ifdef _WIN32
+LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
+#pragma code_page(936)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MICON               ICON                    "Watchdog.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// String Table
+//
+
+STRINGTABLE 
+BEGIN
+    IDS_APP_TITLE           "WxService"
+END
+
+#endif    // 中文(中华人民共和国) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+

+ 279 - 0
source/hook/WxService/WxService.vcproj

@@ -0,0 +1,279 @@
+<?xml version="1.0" encoding="gb2312"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="9.00"
+	Name="WxService"
+	ProjectGUID="{F6D9B47B-95FF-4A7D-BA72-F33A0506BE21}"
+	RootNamespace="WxService"
+	Keyword="Win32Proj"
+	TargetFrameworkVersion="196613"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				MinimalRebuild="true"
+				BasicRuntimeChecks="3"
+				RuntimeLibrary="3"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="4"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="2"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="..\..\..\..\bin\$(SolutionName)"
+			IntermediateDirectory="$(OutDir)\$(ProjectName)\$(ConfigurationName)\"
+			ConfigurationType="1"
+			UseOfMFC="2"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="true"
+				UsePrecompiledHeader="2"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				LinkIncremental="1"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<Filter
+			Name="Ô´Îļþ"
+			Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+			UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+			>
+			<File
+				RelativePath=".\stdafx.cpp"
+				>
+				<FileConfiguration
+					Name="Debug|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+				<FileConfiguration
+					Name="Release|Win32"
+					>
+					<Tool
+						Name="VCCLCompilerTool"
+						UsePrecompiledHeader="1"
+					/>
+				</FileConfiguration>
+			</File>
+			<File
+				RelativePath=".\WxService.cpp"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Í·Îļþ"
+			Filter="h;hpp;hxx;hm;inl;inc;xsd"
+			UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+			>
+			<File
+				RelativePath=".\Resource.h"
+				>
+			</File>
+			<File
+				RelativePath=".\stdafx.h"
+				>
+			</File>
+			<File
+				RelativePath=".\targetver.h"
+				>
+			</File>
+			<File
+				RelativePath=".\WxService.h"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="×ÊÔ´Îļþ"
+			Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+			UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+			>
+			<File
+				RelativePath=".\IDI_MICON"
+				>
+			</File>
+			<File
+				RelativePath=".\Watchdog.ico"
+				>
+			</File>
+			<File
+				RelativePath=".\WxService.rc"
+				>
+			</File>
+		</Filter>
+		<Filter
+			Name="Common"
+			>
+			<File
+				RelativePath=".\Global.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\Global.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MainProcess.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\MainProcess.h"
+				>
+			</File>
+			<File
+				RelativePath=".\MTVERIFY.H"
+				>
+			</File>
+			<File
+				RelativePath=".\WinService.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\WinService.h"
+				>
+			</File>
+		</Filter>
+		<File
+			RelativePath=".\ReadMe.txt"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>

+ 18 - 0
source/hook/WxService/resource.h

@@ -0,0 +1,18 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WxService.rc
+//
+#define IDI_ICON1                       101
+#define IDI_MICON                       101
+#define IDS_APP_TITLE                   103
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif

+ 8 - 0
source/hook/WxService/stdafx.cpp

@@ -0,0 +1,8 @@
+// stdafx.cpp : 只包括标准包含文件的源文件
+// WxService.pch 将作为预编译头
+// stdafx.obj 将包含预编译类型信息
+
+#include "stdafx.h"
+
+// TODO: 在 STDAFX.H 中
+// 引用任何所需的附加头文件,而不是在此文件中引用

+ 33 - 0
source/hook/WxService/stdafx.h

@@ -0,0 +1,33 @@
+// stdafx.h : 标准系统包含文件的包含文件,
+// 或是经常使用但不常更改的
+// 特定于项目的包含文件
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#include <stdio.h>
+#include <tchar.h>
+#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS      // 某些 CString 构造函数将是显式的
+
+#ifndef VC_EXTRALEAN
+#define VC_EXTRALEAN            // 从 Windows 头中排除极少使用的资料
+#endif
+
+#include <afx.h>
+#include <afxwin.h>         // MFC 核心组件和标准组件
+#include <afxext.h>         // MFC 扩展
+#ifndef _AFX_NO_OLE_SUPPORT
+#include <afxdtctl.h>           // MFC 对 Internet Explorer 4 公共控件的支持
+#endif
+#ifndef _AFX_NO_AFXCMN_SUPPORT
+#include <afxcmn.h>                     // MFC 对 Windows 公共控件的支持
+#endif // _AFX_NO_AFXCMN_SUPPORT
+
+#include <iostream>
+#include "WinService.h"
+#include "Global.h"
+
+
+// TODO: 在此处引用程序需要的其他头文件

+ 24 - 0
source/hook/WxService/targetver.h

@@ -0,0 +1,24 @@
+#pragma once
+
+// 以下宏定义要求的最低平台。要求的最低平台
+// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
+// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
+// 正常工作。
+
+// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
+// 有关不同平台对应值的最新信息,请参考 MSDN。
+#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
+#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
+#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
+#endif
+
+#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
+#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
+#endif
+
+#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
+#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
+#endif