#include "StdAfx.h" #include "Global.h" // 获取文件版本号函数头文件; #include #pragma comment(lib,"version.lib") using namespace std; #include #pragma comment(lib,"Psapi.lib") #include #include //_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 FindAllProcess(LPCTSTR lpProName) { ASSERT(lpProName!=NULL); vector vtPID; PROCESSENTRY32 pe32 = { 0 }; HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == NULL) return vector(); 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; }