|
@@ -0,0 +1,1098 @@
|
|
|
+#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;
|
|
|
+}
|
|
|
+
|
|
|
+void FindAllProcess(std::vector<ProInfo> &vtProInfo)
|
|
|
+{
|
|
|
+ PROCESSENTRY32 pe32 = { 0 };
|
|
|
+ HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
|
+ if (hSnapshot == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ pe32.dwSize = sizeof(PROCESSENTRY32);
|
|
|
+ if (!Process32First(hSnapshot, &pe32))
|
|
|
+ goto end;
|
|
|
+
|
|
|
+ do
|
|
|
+ {
|
|
|
+ ProInfo proinfo;
|
|
|
+ proinfo.dwProId = pe32.th32ProcessID;
|
|
|
+ proinfo.strProName = pe32.szExeFile;
|
|
|
+ vtProInfo.push_back(proinfo);
|
|
|
+ } while (Process32Next(hSnapshot, &pe32));
|
|
|
+
|
|
|
+end:
|
|
|
+ CloseHandle(hSnapshot);
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+}
|