浏览代码

WxMgr:添加GetButton、GetWxChatWnd、GetWxObject

Jeff 6 年之前
父节点
当前提交
83e092b447

+ 16 - 0
source/hook/WeChats/WeChatsDlg.cpp

@@ -69,6 +69,7 @@ BEGIN_MESSAGE_MAP(CWeChatsDlg, CDialog)
 	ON_BN_CLICKED(BTN_OPEN_WX, &CWeChatsDlg::OnBnClickedOpenWx)
 	ON_WM_CTLCOLOR()
 	ON_BN_CLICKED(BTN_ATTACH_WX, &CWeChatsDlg::OnBnClickedAttachWx)
+	ON_COMMAND_RANGE(10000, 10010, OnBtnClickedWxName)
 END_MESSAGE_MAP()
 
 
@@ -176,6 +177,21 @@ void CWeChatsDlg::OnBnClickedAttachWx()
 	m_wxMgr.AttachUnMgrWxProc(GetDlgItem(WX_RECT));
 }
 
+void CWeChatsDlg::OnBtnClickedWxName(UINT uID)
+{
+	static UINT lastID = 10000;
+	if ( m_wxMgr.m_mapIds[uID] == 0 )
+	{
+#ifdef DEBUG
+		OutputDebugString(_T("对应按钮的微信ID空\n"));
+#endif // DEBUG
+
+		return;
+	}
+
+	// 单击了则显示当前微信窗口,隐藏上一个;
+}
+
 HBRUSH CWeChatsDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
 {
 	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

+ 1 - 0
source/hook/WeChats/WeChatsDlg.h

@@ -41,4 +41,5 @@ public:
 	virtual BOOL DestroyWindow();
 	virtual BOOL PreTranslateMessage(MSG* pMsg);
 	afx_msg void OnBnClickedAttachWx();
+	afx_msg void OnBtnClickedWxName(UINT uID);
 };

+ 46 - 0
source/hook/WeChats/WxMgr.cpp

@@ -32,6 +32,7 @@ DWORD CWxMgr::GetFreeButtonId(DWORD dwProcId)
 {
 	for (pair<DWORD, DWORD> ids : m_mapIds)
 	{
+		// ÅжϽø³ÌidÊÇ·ñΪ0;
 		if ( ids.second == 0 )
 		{
 			ids.second = dwProcId;
@@ -63,6 +64,51 @@ void CWxMgr::InitButtonIds()
 	}
 }
 
+CButtonST * CWxMgr::GetButton(DWORD dwProcId)
+{
+	CButtonST *pButton = NULL;
+	for (pair<DWORD, WXOBJINFO> wxinfo : m_mapWx)
+	{
+		if (wxinfo.first == dwProcId)
+		{
+			pButton = wxinfo.second.pWxButton;
+			break;
+		}
+	}
+
+	return pButton;
+}
+
+CStatic * CWxMgr::GetWxChatWnd(DWORD dwProcId)
+{
+	CStatic *pWxChatWnd = NULL;
+	for (pair<DWORD, WXOBJINFO> wxinfo : m_mapWx)
+	{
+		if (wxinfo.first == dwProcId)
+		{
+			pWxChatWnd = wxinfo.second.pWxChatWnd;
+			break;
+		}
+	}
+
+	return pWxChatWnd;
+}
+
+CWxObject * CWxMgr::GetWxObject(DWORD dwProcId)
+{
+	CWxObject *pWxObject = NULL;
+	for (pair<DWORD, WXOBJINFO> wxinfo : m_mapWx)
+	{
+		if (wxinfo.first == dwProcId)
+		{
+			pWxObject = wxinfo.second.pWxObject;
+			break;
+		}
+	}
+
+	return pWxObject;
+}
+
 BOOL CWxMgr::AttachUnMgrWxProc(CWnd *pWnd)
 {
 	vector<DWORD> vtWxProcId = FindAllProcess(WECHAT);

+ 3 - 0
source/hook/WeChats/WxMgr.h

@@ -38,6 +38,9 @@ public:
 	// °´Å¥ID<°´Å¥Id,½ø³ÌID>
 	std::map<DWORD, DWORD> m_mapIds;
 
+	CButtonST *GetButton(DWORD dwProcId);
+	CStatic *GetWxChatWnd(DWORD dwProcId);
+	CWxObject *GetWxObject(DWORD dwProcId);
 public:
 	VOID SetMainWnd(CWnd *pWnd, CRect rcWxList, CRect rcWxShow) {
 		m_pMainWnd = pWnd;

+ 1178 - 0
source/hook/common/Global.cpp

@@ -0,0 +1,1178 @@
+#include "StdAfx.h"
+#include "Global.h"
+
+// 获取文件版本号函数头文件;
+#include <WinVer.h>		
+#pragma comment(lib,"version.lib")
+using namespace std;
+#include <psapi.h>
+#pragma comment(lib,"Psapi.lib")
+#include <locale.h>
+#include <io.h>//_access头文件;
+
+TCHAR g_szModulePath[MAX_PATH] = _T("");			// 软件目录;
+TCHAR g_szModuleFileName[MAX_PATH] = _T("");		// 软件名称;
+TCHAR g_szIniFile[MAX_PATH] = _T("");
+
+// 配置文件信息;
+TCHAR g_szServAddress[MAX_PATH] = _T("");		
+DWORD g_dwServPort = 0;		
+TCHAR g_szAccount[MAX_PATH] = _T("");		
+TCHAR g_szPassword[MAX_PATH] = _T("");	
+TCHAR g_szWeChatPath[MAX_PATH] = _T("");		
+TCHAR g_szCacheDir[MAX_PATH] = _T("");		
+TCHAR g_szDynamicLibraryPath[MAX_PATH] = _T("");
+
+// 控制台输出;
+BOOL g_bStdOut = FALSE;
+
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+int GetIniInfo(LPCTSTR lpIniDir /* = NULL */, LPCTSTR lpIniName /* = NULL */)
+{
+	TCHAR szDrive[_MAX_DRIVE] = { 0 };
+	TCHAR szDir[_MAX_DIR] = { 0 };
+	TCHAR szFna[_MAX_DIR] = { 0 };
+	TCHAR szExt[_MAX_DIR] = { 0 };
+	::GetModuleFileName(NULL, g_szModulePath, sizeof(g_szModulePath) / sizeof(TCHAR));
+	_stprintf_s(g_szModuleFileName, _T("%s"), g_szModulePath);
+
+	_tsplitpath_s(g_szModulePath, szDrive, szDir, szFna, szExt);
+	_tcscpy_s(g_szModulePath, szDrive);
+	_tcscat_s(g_szModulePath, szDir);
+
+	// 动态库路径;
+	_stprintf_s(g_szDynamicLibraryPath, _T("%shook.dll"), g_szModulePath);
+#ifdef _DEBUG
+	_stprintf_s(g_szDynamicLibraryPath, _T("%shook.dll"), _T("E:\\bin\\WeChats2017\\"));
+	WriteTextLog(_T("DLL路径=%s"),g_szDynamicLibraryPath);
+#endif
+
+	if (lpIniDir != NULL && lpIniName != NULL)
+		_stprintf_s(g_szIniFile, _T("%s%s"), lpIniDir, lpIniName);
+	else
+		_stprintf_s(g_szIniFile, _T("%sconfig.ini"), g_szModulePath);
+
+	HANDLE hFile = CreateFile(g_szIniFile, 0/*GENERIC_READ*/, 0, NULL, OPEN_EXISTING, 0, NULL);
+
+	if (ERROR_FILE_NOT_FOUND == GetLastError())
+	{
+		return -1;
+	}
+
+	CloseHandle(hFile);
+	hFile = NULL;
+
+	// 获取服务器端信息;
+	GetPrivateProfileString(_T("ServerInfo"), _T("IP"), _T(""), g_szServAddress, MAX_PATH, g_szIniFile);
+	g_dwServPort = GetPrivateProfileInt(_T("ServerInfo"), _T("Port"), 0, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Account"), _T(""), g_szAccount, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Password"), _T(""), g_szPassword, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("WeChat"), _T(""), g_szWeChatPath, MAX_PATH, g_szIniFile);
+	GetPrivateProfileString(_T("CustomerInfo"), _T("Cache"), _T(""), g_szCacheDir, MAX_PATH, g_szIniFile);
+
+	g_bStdOut = GetPrivateProfileInt(_T("CustomerInfo"), _T("StdOut"), 0, g_szIniFile);
+	if ( g_bStdOut )
+	{
+		AllocConsole();                             // 开辟控制台;
+		SetConsoleTitle(_T("调试输出"));			// 设置控制台窗口标题;
+		freopen("CONOUT$", "w+t", stdout);			// 重定向输出;
+		freopen("CONIN$", "r+t", stdin);			// 重定向输入;
+
+		HWND hWnd = NULL;
+again:
+		hWnd = ::FindWindow(NULL, _T("调试输出"));
+		if( hWnd )
+		{
+			if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE | SWP_NOSIZE)) 
+			{
+				_tprintf_s(_T("前置设置失败\n"));
+			}
+			else
+			{
+				_tprintf_s(_T("前置设置成功\n"));
+			}
+		}
+		else
+		{
+			goto again;
+		}
+	}
+
+	return 0;
+}
+
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+DWORD FindProcess(LPCTSTR lpProName)
+{
+	ASSERT(lpProName!=NULL);
+
+	DWORD dwPID = 0;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hSnapshot == NULL)
+	{
+		return 0;
+	}
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+
+	if (Process32First(hSnapshot, &pe32))
+	{
+		do {
+			if (_tcsicmp(lpProName, pe32.szExeFile) == 0)
+			{
+				dwPID = pe32.th32ProcessID;
+				break;
+			}
+		} while (Process32Next(hSnapshot, &pe32));
+	}
+	CloseHandle(hSnapshot);
+
+	return dwPID;
+}
+
+vector<DWORD> FindAllProcess(LPCTSTR lpProName)
+{
+	ASSERT(lpProName!=NULL);
+
+	vector<DWORD> vtPID;
+	PROCESSENTRY32 pe32 = { 0 };
+
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
+	if (hSnapshot == NULL)
+		return vector<DWORD>();
+
+	pe32.dwSize = sizeof(PROCESSENTRY32);
+	if (Process32First(hSnapshot, &pe32))
+	{
+		do {
+			if (_tcsicmp(lpProName, pe32.szExeFile) == 0)
+			{
+				vtPID.push_back(pe32.th32ProcessID);
+			}
+		} while (Process32Next(hSnapshot, &pe32));
+	}
+	CloseHandle(hSnapshot);
+
+	return vtPID;
+}
+
+HANDLE FindModule(LPCTSTR lpModuleName, DWORD dwPID)
+{
+	ASSERT(lpModuleName!=NULL);
+
+	DWORD dwMID = 0;
+	MODULEENTRY32 me32 = { 0 };
+	HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, dwPID);
+	if (hSnapshot == NULL)
+		return NULL;
+
+	me32.dwSize = sizeof(PROCESSENTRY32);
+	if (Module32First(hSnapshot, &me32))
+	{
+		do {
+			if (_tcsicmp(lpModuleName, me32.szModule) == 0)
+			{
+				break;
+			}
+		} while (Module32Next(hSnapshot, &me32));
+	}
+	CloseHandle(hSnapshot);
+
+	return me32.hModule;
+}
+
+HANDLE FindModuleEx(LPCTSTR lpModuleName, DWORD dwPid)
+{
+	HMODULE hMods[1024] = {0};
+	DWORD cbNeeded = 0;
+	TCHAR szModName[MAX_PATH];
+	BOOL Wow64Process;
+
+	HANDLE hProcess = ::OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPid);
+	IsWow64Process(hProcess, &Wow64Process); //判断是32位还是64位进程
+	if ( EnumProcessModulesEx(hProcess, hMods, sizeof(hMods), &cbNeeded, Wow64Process?LIST_MODULES_32BIT:LIST_MODULES_64BIT) )
+	{
+		for (UINT i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
+		{
+			GetModuleFileNameEx(hProcess, hMods[i], szModName, _countof(szModName));
+#ifdef _DEBUG
+			WriteTextLog(_T("目标=%s, 原始=%s, 地址=%p"), szModName, lpModuleName, hMods[i]);
+#endif
+			if (_tcsicmp(lpModuleName, szModName) == 0)
+			{
+				CloseHandle(hProcess);
+				WriteTextLog(_T("目标=%s, 原始=%s, 地址=%p"), szModName, lpModuleName, hMods[i]);
+				return hMods[i];
+			}
+		}
+	}
+
+	CloseHandle(hProcess);
+
+	return NULL;
+}
+
+// WINDOWS NT 以上的内核需要提权,才能对系统进行高级管理;
+/************************************************************************/
+/*  函数:[1/6/2019 Home];
+/*  描述:;
+/*  参数:;
+/*  	[IN] :;
+/*  	[OUT] :;
+/*  	[IN/OUT] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+BOOL GetDebugPriv()
+{
+	// 返回的访问令牌指针;
+	HANDLE	hToken;
+	// 接收所返回的制定特权名称的信息;
+	LUID	sedebugnameValue;
+	// 新特权信息的指针(结构体);
+	TOKEN_PRIVILEGES tkp;
+	//DWORD	dwCurProcId = GetCurrentProcessId();
+	// 要修改访问权限的进程句柄;
+	HANDLE	hCurProc = ::GetCurrentProcess();
+	//hCurProc = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwCurProcId);
+
+	if (!::OpenProcessToken(hCurProc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+	{
+		return FALSE;
+	}
+
+	if (!::LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
+	{
+		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))
+	{
+		CloseHandle(hToken);
+		return FALSE;
+	}
+
+	CloseHandle(hCurProc);
+	CloseHandle(hToken);
+	return TRUE;
+}
+
+/************************************************************************/
+/* 
+	函数: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;
+}
+
+/************************************************************************/
+/*  函数:WriteTextLog[7/28/2016 IT];
+/*  描述:写文本日志;
+/*  参数:;
+/*  	[IN] :;
+/*  返回:void;
+/*  注意:;
+/*  示例:;
+/*
+/*  修改:;
+/*  日期:;
+/*  内容:;
+/************************************************************************/
+void WriteTextLog(const TCHAR *format, ...)
+{
+#if 0
+	try
+	{
+		//static ThreadSection _critSection;
+		//AutoThreadSection aSection(&_critSection);
+		// 解析出日志路径;
+		TCHAR szlogpath[MAX_PATH] = {0};
+		static TCHAR szModulePath[MAX_PATH] = {0};
+		static TCHAR szFna[_MAX_DIR] = { 0 };
+		if ( szModulePath[0] == _T('\0') )
+		{
+			TCHAR szDrive[_MAX_DRIVE] = { 0 };
+			TCHAR szDir[_MAX_DIR] = { 0 };
+			TCHAR szExt[_MAX_DIR] = { 0 };
+			::GetModuleFileName(NULL, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
+			_tsplitpath_s(szModulePath, szDrive, szDir, szFna, szExt);
+			_tcscpy_s(szModulePath, szDrive);
+			_tcscat_s(szModulePath, szDir);
+		}
+
+		_stprintf_s(szlogpath, _T("%s日志\\%s%s.txt"), szModulePath, szFna, CTime::GetCurrentTime().Format("[%Y-%m-%d]"));
+
+		// 打开或创建文件;
+		CStdioFile fp;
+		if (PathFileExists(szlogpath))
+		{
+			if (fp.Open(szlogpath, CFile::modeWrite) == FALSE)
+			{
+				return;
+			}
+			fp.SeekToEnd();
+		}
+		else
+		{
+			fp.Open(szlogpath, CFile::modeCreate | CFile::modeWrite);
+		}
+
+		// 格式化前设置语言区域;
+		TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+		_tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
+
+		// 格式化日志内容;
+		va_list		args = NULL;
+		int			len = 0;
+		TCHAR		*buffer = NULL;
+		va_start( args, format );
+		// _vscprintf doesn't count. terminating '\0'
+		len = _vsctprintf( format, args )  + 1;
+		buffer = (TCHAR*)malloc( len * sizeof(TCHAR) );
+		_vstprintf_s( buffer, len, format, args ); // C4996
+		// Note: vsprintf is deprecated; consider using vsprintf_s instead
+
+		// 将日志内容输入到文件中;
+		fp.WriteString( CTime::GetCurrentTime().Format(_T("%Y-%m-%d %H:%M:%S ")) );
+		fp.WriteString(buffer);
+		fp.WriteString(_T("\n"));
+
+		// 关闭文件,释放资源并设置回原语言区域;
+		free( buffer );
+		_tsetlocale(LC_CTYPE, old_locale);
+		free(old_locale);//还原区域设定;
+		fp.Close();
+	}
+	catch (CException *e)
+	{
+		e->ReportError();
+		e->Delete();
+	}
+#else
+	// 解析出日志路径;
+	TCHAR szlogpath[MAX_PATH] = { 0 };
+	static TCHAR szModulePath[MAX_PATH] = { 0 };
+	static TCHAR szFna[MAX_PATH] = { 0 };
+	if (szModulePath[0] == _T('\0'))
+	{
+		TCHAR szDrive[MAX_PATH] = { 0 };
+		TCHAR szDir[MAX_PATH] = { 0 };
+		TCHAR szExt[MAX_PATH] = { 0 };
+		::GetModuleFileName(NULL, szModulePath, sizeof(szModulePath) / sizeof(TCHAR));
+		_tsplitpath_s(szModulePath, szDrive, szDir, szFna, szExt);
+		_tcscpy_s(szModulePath, szDrive);
+		_tcscat_s(szModulePath, szDir);
+	}
+
+	_stprintf_s(szlogpath, _T("%s%s.txt"), szModulePath, szFna);
+	// 打开或创建文件;
+	FILE *fp = NULL;
+	//if (_taccess(szlogpath, 0) != -1)
+#ifndef UNICODE
+	if (_access(szlogpath, 0) != -1)
+#else
+	if (_taccess(szlogpath, 0) != -1)
+#endif
+	{// 存在;
+		fp = _tfopen(szlogpath, _T("a+"));
+		// 移动到末尾;
+		fseek(fp, 0, SEEK_END);
+	}
+	else
+	{// 不存在;
+		fp = _tfopen(szlogpath, _T("w+"));
+	}
+
+	if (fp == NULL)
+		return;
+
+	// 格式化前设置语言区域;
+	TCHAR* old_locale = _tcsdup(_tsetlocale(LC_CTYPE, NULL));
+	_tsetlocale(LC_CTYPE, _T("chs"));//设定中文;
+
+	// 格式化日志内容;
+	va_list		args = NULL;
+	int			len = 0;
+	TCHAR		*buffer = NULL;
+	va_start(args, format);
+	// _vscprintf doesn't count. terminating '\0'
+	len = _vsctprintf(format, args) + 1;
+	buffer = (TCHAR*)malloc(len * sizeof(TCHAR));
+	_vstprintf_s(buffer, len, format, args);
+	// 将日志内容输入到文件中;
+	// 获取今年年份;
+	__time64_t gmt = time(NULL);// 获取当前日历时间(1900-01-01开始的Unix时间戳);
+	struct tm gmtm = { 0 };
+	localtime_s(&gmtm, &gmt); // 时间戳转成本地时间;
+	_ftprintf(fp, _T("%04d-%02d-%02d %02d:%02d:%02d %s\n"), gmtm.tm_year + 1990, gmtm.tm_mon + 1, gmtm.tm_mday, gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, buffer);
+
+	// 关闭文件,释放资源并设置回原语言区域;
+	free(buffer);
+	fclose(fp);
+	_tsetlocale(LC_CTYPE, old_locale);
+	free(old_locale);//还原区域设定;
+#endif
+}
+
+
+//---------------------------------------------------------------------
+// add by Jeff 2014.10.27
+// 函数:全局函数IsDirectoryLegitimate,多字节版本,非UNICODE
+// 描述:判断一个目录路径字符串,是否属于合法的、可创建的目录路径。
+// 参数:strDirectory 被验证的路径字符串;
+//		
+// 返回:合法路径返回TRUE;
+//---------------------------------------------------------------------
+BOOL IsDirectoryLegitimate(const CString &strDirectory)
+{
+	if (strDirectory.Find('/') != -1 ||
+		strDirectory.Find('\\') != -1 ||
+		strDirectory.Find(':') != -1 ||
+		strDirectory.Find('*') != -1 ||
+		strDirectory.Find('?') != -1 ||
+		strDirectory.Find('\"') != -1 ||
+		strDirectory.Find('>') != -1 ||
+		strDirectory.Find('<') != -1 ||
+		strDirectory.Find('|') != -1
+		)
+		return FALSE;
+
+	return TRUE;
+}
+
+
+//--------------------------------------------------------------------------------
+// Jeff add 2014.06.23;
+// 函数:ErrorExit
+// 描述:
+// 参数:
+//     lpszFunction:函数名;
+//     dwError:错误码; 
+//
+//--------------------------------------------------------------------------------
+void ShowSystemErrorInfo(CString strDescription, const DWORD &dwError)
+{
+#if 1
+	LPVOID lpMsgBuf;
+
+	BOOL fOk = FormatMessage(
+		FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		dwError,
+		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+		(LPTSTR)&lpMsgBuf,
+		0, NULL);
+
+	if (!fOk)
+	{
+		// Is it a network-related error?
+		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
+
+		if (hDll != NULL)
+		{
+			FormatMessage(
+				FORMAT_MESSAGE_FROM_HMODULE |
+				FORMAT_MESSAGE_FROM_SYSTEM |
+				FORMAT_MESSAGE_IGNORE_INSERTS,
+				hDll,
+				dwError,
+				MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+				(LPTSTR)&lpMsgBuf,
+				0,
+				NULL);
+
+			FreeLibrary(hDll);
+		}
+	}
+
+	if (lpMsgBuf != NULL)
+	{
+		CString strDisplay;
+		strDisplay.Format(_T("%s.错误码=%d,Windows描述:%s"), strDescription, dwError, (PCTSTR)LocalLock(lpMsgBuf));
+		//WriteLog(strDisplay);
+		LocalFree(lpMsgBuf);
+	}
+	else
+	{
+		//WriteLog(strDescription);
+	}
+#else
+	HLOCAL hlocal = NULL;   // Buffer that gets the error message string
+
+	// Get the error code's textual description
+	BOOL fOk = FormatMessage(
+		FORMAT_MESSAGE_FROM_SYSTEM |
+		FORMAT_MESSAGE_ALLOCATE_BUFFER |
+		FORMAT_MESSAGE_IGNORE_INSERTS,
+		NULL,
+		dwError,
+		MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+		(PTSTR)&hlocal,
+		0,
+		NULL);
+
+	if (!fOk)
+	{
+		// Is it a network-related error?
+		HMODULE hDll = LoadLibraryEx(TEXT("netmsg.dll"), NULL, DONT_RESOLVE_DLL_REFERENCES);
+
+		if (hDll != NULL)
+		{
+			FormatMessage(
+				FORMAT_MESSAGE_FROM_HMODULE |
+				FORMAT_MESSAGE_FROM_SYSTEM |
+				FORMAT_MESSAGE_IGNORE_INSERTS,
+				hDll,
+				dwError,
+				MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
+				(PTSTR)&hlocal,
+				0,
+				NULL);
+			FreeLibrary(hDll);
+		}
+	}
+
+	if (hlocal != NULL)
+	{
+		CString strDisplay;
+		strDisplay.Format("%s 失败错误码=%d,Windows系统描述:%s", strDescription, dwError, (PCTSTR)LocalLock(hlocal));
+		//WriteLog(strDisplay);
+		LocalFree(hlocal);
+	}
+	else
+	{
+		//WriteLog("Error number not found.");
+	}
+#endif
+
+}
+
+// The system displays a dialog box with a custom message and a message to the user to close applications within the specified time-out interval (30 seconds). 
+// After the time-out interval elapses, the system is restarted.
+//The application must enable the SE_SHUTDOWN_NAME privilege before calling InitiateSystemShutdown
+BOOL MySystemShutdown(LPTSTR lpMsg)
+{
+	HANDLE hToken;              // handle to process token 
+	TOKEN_PRIVILEGES tkp;       // pointer to token structure 
+
+	BOOL fResult;               // system shutdown flag 
+
+	// Get the current process token handle so we can get shutdown 
+	// privilege. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return FALSE;
+
+	// Get the LUID for shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	// Cannot test the return value of AdjustTokenPrivileges. 
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Display the shutdown dialog box and start the countdown. 
+
+	fResult = InitiateSystemShutdown(
+		NULL,    // shut down local computer 
+		lpMsg,   // message for user
+		30,      // time-out period, in seconds 
+		FALSE,   // ask user to close apps 
+		TRUE);   // reboot after shutdown 
+
+	if (!fResult)
+		return FALSE;
+
+	// Disable shutdown privilege. 
+
+	tkp.Privileges[0].Attributes = 0;
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	return TRUE;
+}
+
+// If the AbortSystemShutdown function is executed in the time-out period specified by InitiateSystemShutdown, 
+// the system does not shut down. For example, if PreventSystemShutdown is called after MySystemShutdown, 
+// the system closes the dialog box and does not restart the system.
+BOOL PreventSystemShutdown()
+{
+	HANDLE hToken;              // handle to process token 
+	TOKEN_PRIVILEGES tkp;       // pointer to token structure 
+
+	// Get the current process token handle  so we can get shutdown 
+	// privilege. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return FALSE;
+
+	// Get the LUID for shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Prevent the system from shutting down. 
+
+	if (!AbortSystemShutdown(NULL))
+		return FALSE;
+
+	// Disable shutdown privilege. 
+
+	tkp.Privileges[0].Attributes = 0;
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	return TRUE;
+}
+
+// Shutting down flushes file buffers to disk and brings the system to a condition in which it is safe to turn off the computer
+// The application must first enable the SE_SHUTDOWN_NAME privilege. 
+// The final parameter in the call to ExitWindowsEx indicates that the system was shut down for a planning update of the operating system.
+BOOL MySystemShutdown()
+{
+	HANDLE hToken;
+	TOKEN_PRIVILEGES tkp;
+
+	// Get a token for this process. 
+
+	if (!OpenProcessToken(GetCurrentProcess(),
+		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
+		return(FALSE);
+
+	// Get the LUID for the shutdown privilege. 
+
+	LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME,
+		&tkp.Privileges[0].Luid);
+
+	tkp.PrivilegeCount = 1;  // one privilege to set    
+	tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+
+	// Get the shutdown privilege for this process. 
+
+	AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
+		(PTOKEN_PRIVILEGES)NULL, 0);
+
+	if (GetLastError() != ERROR_SUCCESS)
+		return FALSE;
+
+	// Shut down the system and force all applications to close. 
+
+	if (!ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE,
+		SHTDN_REASON_MAJOR_OPERATINGSYSTEM |
+		SHTDN_REASON_MINOR_UPGRADE |
+		SHTDN_REASON_FLAG_PLANNED))
+		return FALSE;
+
+	return TRUE;
+}
+
+BOOL GetWeChatPath()
+{
+	// 通过注册表获取微信安装目录;
+	HKEY hKey = NULL;
+	if(ERROR_SUCCESS != RegOpenKey(HKEY_CURRENT_USER, _T("Software\\Tencent\\WeChat"), &hKey))
+	{
+		return FALSE;
+	}
+
+	DWORD Type = REG_SZ;
+	DWORD cbData = MAX_PATH*sizeof(WCHAR);
+	if(ERROR_SUCCESS != RegQueryValueEx(hKey, _T("InstallPath"), 0, &Type, (LPBYTE)g_szWeChatPath, &cbData))
+	{
+		RegCloseKey(hKey);
+		return FALSE;
+	}
+
+	PathAppend(g_szWeChatPath, _T("WeChat.exe"));
+
+	return TRUE;
+}
+
+BOOL OpenWeChat()
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&si, sizeof(si));
+	si.cb = sizeof(si);
+	ZeroMemory(&pi, sizeof(pi));
+
+	si.dwFlags = STARTF_USESHOWWINDOW;		// 指定wShowWindow成员有效
+	si.wShowWindow = SW_HIDE;				// 设置创建进程时,窗口不显示,
+	// 为FALSE的话则不显示
+	BOOL bRet = ::CreateProcess (
+		g_szWeChatPath,		// 不在此指定可执行文件的文件名
+		NULL,				// 命令行参数
+		NULL,				// 默认进程安全性
+		NULL,				// 默认线程安全性
+		FALSE,				// 指定当前进程内的句柄不可以被子进程继承
+		NULL,
+		NULL,				// 使用本进程的环境变量
+		NULL,				// 使用本进程的驱动器和目录
+		&si,
+		&pi);
+
+	if(bRet)
+	{
+		// 进程挂起后,仍能成功注入dll;
+// 		TCHAR szDllPath[MAX_PATH];
+// 		ZeroMemory(szDllPath,MAX_PATH);
+// 		_stprintf_s(szDllPath, _T("%shook.dll"), g_szModulePath);
+// 		for (int i = 0; i < 10; i++)
+// 		{
+// 			CInjection inject(pi.dwProcessId,szDllPath);
+// 			inject.InjectDynamicLibrary();
+// 			inject.EjectDynamicLibrary();
+// 		}
+
+		// 既然我们不使用两个句柄,最好是立刻将它们关闭
+		::CloseHandle (pi.hThread);
+		::CloseHandle (pi.hProcess);
+
+		// 当进程挂起时,是无法修改关闭微信句柄;
+		PatchWeChat();
+	}
+
+	return TRUE;
+}
+
+BOOL OpenWeChat2()
+{
+	SHELLEXECUTEINFO sei;
+	memset(&sei, 0, sizeof(SHELLEXECUTEINFO));
+	sei.cbSize = sizeof(SHELLEXECUTEINFO);
+	sei.hwnd = NULL;
+	sei.lpVerb = _T("open");
+	//sei.lpVerb = _T("runas");
+	//sei.fMask = SEE_MASK_NOCLOSEPROCESS;
+	sei.lpFile = g_szWeChatPath;
+	sei.lpParameters = NULL;
+	sei.lpDirectory = NULL;
+	sei.nShow = SW_NORMAL;
+	sei.hInstApp = NULL;
+
+	if (!ShellExecuteEx(&sei))
+	{
+		DWORD dw = GetLastError();
+		return FALSE;
+	}
+	PatchWeChat();
+
+	return TRUE;
+}
+
+BOOL OpenWeChatAndSuspended()
+{
+	STARTUPINFO si;
+	PROCESS_INFORMATION pi;
+	ZeroMemory(&si, sizeof(si));
+	si.cb = sizeof(si);
+	ZeroMemory(&pi, sizeof(pi));
+
+	si.dwFlags = STARTF_USESHOWWINDOW;  // 指定wShowWindow成员有效
+	si.wShowWindow = TRUE;				// 此成员设为TRUE的话则显示新建进程的主窗口,
+	// 为FALSE的话则不显示
+	BOOL bRet = ::CreateProcess(
+		g_szWeChatPath,		// 不在此指定可执行文件的文件名
+		NULL,				// 命令行参数
+		NULL,				// 默认进程安全性
+		NULL,				// 默认线程安全性
+		FALSE,				// 指定当前进程内的句柄不可以被子进程继承
+		CREATE_SUSPENDED,	// 挂起进程;CREATE_SUSPENDED
+		NULL,				// 使用本进程的环境变量
+		NULL,				// 使用本进程的驱动器和目录
+		&si,
+		&pi);
+
+	if (bRet)
+	{
+		// 进程挂起后,仍能成功注入dll;
+// 		TCHAR szDllPath[MAX_PATH];
+// 		ZeroMemory(szDllPath,MAX_PATH);
+// 		_stprintf_s(szDllPath, _T("%shook.dll"), g_szModulePath);
+// 		for (int i = 0; i < 10; i++)
+// 		{
+// 			CInjection inject(pi.dwProcessId,szDllPath);
+// 			inject.InjectDynamicLibrary();
+// 			inject.EjectDynamicLibrary();
+// 		}
+
+		//不sleep就会出现读取不到的297错误
+		//Sleep(5000);				
+
+		//获取线程上下文
+ 		CONTEXT ct = { 0 };
+ 		ct.ContextFlags = CONTEXT_CONTROL;
+ 		GetThreadContext(pi.hThread, &ct);
+
+ 		::ResumeThread(pi.hThread);	
+
+		// 既然我们不使用两个句柄,最好是立刻将它们关闭
+		::CloseHandle(pi.hThread);
+		::CloseHandle(pi.hProcess);
+
+		// 当进程挂起时,是无法修改关闭微信句柄;
+		PatchWeChat();
+	}
+
+
+	return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+	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;
+	}

+ 66 - 0
source/hook/common/Global.h

@@ -0,0 +1,66 @@
+#ifndef __GLOBAL_WECHAT__
+#define __GLOBAL_WECHAT__
+
+#include <tlhelp32.h>
+#include <vector>
+#include <string>
+using namespace std;
+
+#ifdef UNICODE
+typedef wstring TString;
+#else
+typedef string TString;
+#endif
+
+#define WECHAT _T("WeChat.exe")
+
+// 全局变量;
+extern TCHAR g_szModulePath[MAX_PATH];			// 软件目录;
+extern TCHAR g_szModuleFileName[MAX_PATH];		// 软件名称;
+extern TCHAR g_szIniFile[MAX_PATH];
+
+// 配置文件信息;
+extern TCHAR g_szServAddress[MAX_PATH];		
+extern DWORD g_dwServPort;					
+extern TCHAR g_szAccount[MAX_PATH];			
+extern TCHAR g_szPassword[MAX_PATH];		
+extern TCHAR g_szWeChatPath[MAX_PATH];		
+extern TCHAR g_szCacheDir[MAX_PATH];	
+extern TCHAR g_szDynamicLibraryPath[MAX_PATH];
+
+
+// 控制台输出;
+extern BOOL g_bStdOut;
+
+extern int GetIniInfo(LPCTSTR lpIniDir = NULL, LPCTSTR lpIniName = NULL);
+extern DWORD FindProcess(LPCTSTR lpProName);
+extern vector<DWORD> FindAllProcess(LPCTSTR lpProName);
+extern HANDLE FindModule(LPCTSTR lpModuleName, DWORD dwPID);
+extern HANDLE FindModuleEx(LPCTSTR lpModuleName, DWORD dwPid);
+extern BOOL GetDebugPriv();
+
+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 GetOSDisplayString(LPTSTR pszOS);
+extern void WriteTextLog(const TCHAR *format, ...);
+extern BOOL CopyFileEx(LPCTSTR lpExistingFileName, LPCTSTR lpNewFileName, const BOOL &bFailIfExists=TRUE);
+extern void tSplitpath(const char *path, char *drive, char *dir, char *fname, char *ext);
+extern void tSplitpath(const char *path, char *drive, char *dir, const int &nTimes);
+extern BOOL IsDirectoryLegitimate(const CString &strDirectory);
+extern void ShowSystemErrorInfo(CString strDescription, const DWORD &dwError);
+extern BOOL MySystemShutdown(LPTSTR lpMsg);
+extern BOOL PreventSystemShutdown();
+extern BOOL MySystemShutdown();
+// 判断公历是否有效;
+extern BOOL IsValidDate(IN LPCTSTR lpDate);
+// 判断农历是否有效;
+extern BOOL IsValidLunanrDate(IN LPCTSTR lpDate);
+
+//////////////////////////////////////////////////////////////////////////
+extern BOOL GetWeChatPath();
+extern BOOL OpenWeChat();
+
+#endif

+ 1 - 1
source/hook/hook/dllmain.cpp

@@ -111,7 +111,7 @@ BOOL APIENTRY DllMain(HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserve
 		GetProcInfo(dwThreadId);
 		if (ghk_CBT == NULL)
 		{
-			ghk_CBT = SetWindowsHookEx(WH_CBT, CBTProc, LPDWORD(0x000604F4), dwThreadId);
+			ghk_CBT = SetWindowsHookEx(WH_CBT, CBTProc, HINSTANCE(0x000604F4), dwThreadId);
 			if (ghk_CBT == NULL)
 				WriteTextLog(_T("hook apiʧ°Ü"));
 			else