#include "stdafx.h" #include "ManageClientDispatch.h" #include #include #include #include #include #include #include #include #include #include #pragma comment(lib, "winmm.lib") /* // forward decl HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID); */ enum ManageClientConst { MANAGE_CLIENT_DEFAULT_DISPATCH_NUM = 10 }; CManageClientDispatch::RunExtraInfo::RunExtraInfo(const ServerManage::RunInfo& runInfo, HANDLE hProcess, unsigned long dwProcessID) : m_RunInfo(runInfo), m_hProcess(hProcess), m_dwProcessID(dwProcessID), m_hWnd(0), m_dwCustomStatus(0), m_dwLastSetWindowHandleTime(0) { char szCommand[MAX_PATH]; _snprintf(szCommand, MAX_PATH - 1, "%s", m_RunInfo.m_szOption); szCommand[MAX_PATH - 1] = 0; char* szData = strtok(szCommand, " \t\r\n"); while(0 != szData) { m_CommandSet.insert(szData); szData = strtok(0, " \t\r\n"); } } CSingleDispatch& CManageClientDispatch::GetDispatchTable() { static CSingleDispatch singleDispatch; return singleDispatch; } CManageClientDispatch::CManageClientDispatch(CSession& Session) : CRylServerDispatch(Session, MANAGE_CLIENT_DEFAULT_DISPATCH_NUM), m_hPatchFile(INVALID_HANDLE_VALUE), m_bDoPatchNow(false) { TCHAR* szTempFileName = _T("./mytmp_patch.tmp"); memset(m_szTempPatchFileName, 0, sizeof(TCHAR) * MAX_PATH); _tcscpy(m_szTempPatchFileName, szTempFileName); TCHAR szFullPathModuleName[MAX_PATH]; GetModuleFileName(NULL, szFullPathModuleName, MAX_PATH - 1); szFullPathModuleName[MAX_PATH - 1] = 0; TCHAR szDrive[MAX_PATH]; TCHAR szPath[MAX_PATH]; TCHAR szName[MAX_PATH]; TCHAR szExtension[MAX_PATH]; _tsplitpath(szFullPathModuleName, szDrive, szPath, szName, szExtension); _sntprintf(m_szTempPatchFileName, MAX_PATH - 1, _T("%s\\%s\\%s"), szDrive, szPath, szTempFileName); m_szTempPatchFileName[MAX_PATH - 1] = 0; DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Created", this); } CManageClientDispatch::~CManageClientDispatch() { if(INVALID_HANDLE_VALUE != m_hPatchFile) { // ִ. ݴ´. ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now", this, m_hPatchFile); CloseHandle(m_hPatchFile); } DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Destroyed", this); } void CManageClientDispatch::Connected() { GetDispatchTable().SetDispatch(this); DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Connected", this); } void CManageClientDispatch::Disconnected() { GetDispatchTable().RemoveDispatch(this); DETLOG1(g_Log, "this:0x%p/CManageClientDispatch Disconnected", this); } bool CManageClientDispatch::DispatchPacket(PktBase* lpPktBase) { PktBase::LengthType nPacketLen = lpPktBase->GetLen(); if(nPacketLen < sizeof(ServerManage::ManageCommand)) { ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length or command", GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd()); } else { ServerManage::ManageCommand* lpManageCommand = reinterpret_cast(lpPktBase); if(nPacketLen != sizeof(ServerManage::ManageCommand) + lpManageCommand->usDataLen) { ERRLOG3(g_Log, "IP:%15s/PacketLen:%d/Cmd:0x%02x/Invalid packet length", GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetLen(), lpPktBase->GetCmd()); } else { TCHAR* szWindowName = 0; char* lpData = (0 != lpManageCommand->usDataLen) ? reinterpret_cast(lpManageCommand + 1) : 0; const TCHAR* szErrorMessage = 0; switch(lpManageCommand->GetCmd()) { case ServerManage::CMD::UpdateRunList: // ش (ManageServer -> ManageClient, ManageTool), Ack. ProcessUpdateRunList(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags); break; case ServerManage::CMD::RunProcess: // Ѵ. (ManageTool -> ManageServer -> ManageClient), Ack ݴ ProcessRunServer(lpManageCommand->dwRunID); break; case ServerManage::CMD::QuitProcess: // Ѵ. (ManageTool -> ManageServer -> ManageClient), Ack ݴ ProcessQuitServer(lpManageCommand->dwRunID); break; case ServerManage::CMD::ForceTerminate: // Ѵ. (ManageTool -> ManageServer -> ManageClient), Ack ݴ ProcessTerminateServer(lpManageCommand->dwRunID); break; case ServerManage::CMD::RelayCommand: // Ŷ Ŀǵ带 ޽ Ἥ ߰ؼ ѱ. /* if(!ProcessRelayCommand(lpManageCommand->nMessage, lpManageCommand->wParam, lpManageCommand->lParam, szWindowName, lpData, lpManageCommand->usDataLen, lpManageCommand->cFlag)) { szErrorMessage = _T("RelayCommand : RelayCommand Failed"); } */ break; case ServerManage::CMD::AutoPatch: // ڱ ڽ ġѴ if(!ProcessAutoPatch(lpData, lpManageCommand->usDataLen, lpManageCommand->usFlags)) { szErrorMessage = _T("AutoPatch : AutoPatch packet process failed"); } break; case ServerManage::CMD::ChangeSetup: // ٲٰ Ѵ. if(!ManageSetup::ClientSetup::GetInstance().SerializeIn(lpData, lpManageCommand->usDataLen)) { szErrorMessage = _T("ChangeSetup : Change setup failed"); } else { ManageSetup::ClientSetup::GetInstance().Save(); } break; case ServerManage::CMD::ReloadSetup: // εѴ. ManageSetup::ClientSetup::GetInstance().Load(); break; case ServerManage::CMD::ExecuteCommand: ProcessExecuteConsoleCommand(lpManageCommand); break; default: szErrorMessage = _T("Unknown message : Process failed"); break; } if(0 != szErrorMessage) { ERRLOG4(g_Log, "IP:%15s/DetailCmd:0x%02x/Error:%d/%s", GetSession().GetRemoteAddr().get_addr_string(), lpPktBase->GetCmd(), GetLastError(), szErrorMessage); } } } return true; } bool CManageClientDispatch::ProcessRelayCommand(unsigned int nMessage, WPARAM wParam, LPARAM lParam, const char* szWindowName, const char* lpData, unsigned short usDataLen, unsigned char cFlag) { if(0 != szWindowName) { HWND hWnd = FindWindow(0, szWindowName); if(0 != hWnd) { if(0 != lpData && WM_COPYDATA == nMessage) { COPYDATASTRUCT copyDataStruct; copyDataStruct.dwData = 0; copyDataStruct.cbData = usDataLen; copyDataStruct.lpData = (void*)lpData; // ޽ . SendMessage(hWnd, nMessage, wParam, reinterpret_cast(©DataStruct)); } else { SendMessage(hWnd, nMessage, wParam, lParam); } } } return true; } bool CManageClientDispatch::ProcessAutoPatch(const char* lpData, unsigned short usDataLen, unsigned short usFlag) { switch(usFlag) { case ServerManage::ManageCommand::AUTOPATCH_OPENFILE: if(INVALID_HANDLE_VALUE != m_hPatchFile) { // ġ . ݴ´. ERRLOG2(g_Log, "this:0x%0p/HANDLE:0x%p/PatchFile is not closed. close now for create new one", this, m_hPatchFile); CloseHandle(m_hPatchFile); } // Ѵ. m_hPatchFile = CreateFile(m_szTempPatchFileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); if(INVALID_HANDLE_VALUE == m_hPatchFile) { ERRLOG2(g_Log, "this:0x%p/Error:%d/Patch tempfile create failed", this, GetLastError()); } break; case ServerManage::ManageCommand::AUTOPATCH_DATA: if(INVALID_HANDLE_VALUE != m_hPatchFile) { unsigned long dwWritten = 0; unsigned long dwTotalWritten = 0; while(usDataLen != dwTotalWritten) { if(!WriteFile(m_hPatchFile, lpData, usDataLen, &dwWritten, 0)) { ERRLOG3(g_Log, "this:0x%p/HANDLE:0x%p/Error:%d/Patchfile write failed.", this, m_hPatchFile, GetLastError()); CloseHandle(m_hPatchFile); m_hPatchFile = INVALID_HANDLE_VALUE; DeleteFile(m_szTempPatchFileName); break; } dwTotalWritten += dwWritten; } if(0 == usDataLen && INVALID_HANDLE_VALUE != m_hPatchFile) { // ޾Ҵ. ϰ ġ Ѵ. m_bDoPatchNow = true; } } else { ERRLOG1(g_Log, "this:0x%p/Patchfile is invalid", this); } break; } return true; } bool CManageClientDispatch::ProcessUpdateRunList(const char* szData, unsigned short usDataLen, unsigned short usFlags) { if(ServerManage::SEND_RUNINFO_START == usFlags) { // Process鿡 ؼ ڵ ݴ´. RunTable::iterator pos = m_RunTable.begin(); RunTable::iterator end = m_RunTable.end(); for(; pos != end; ++pos) { RunExtraInfo& runExtraInfo = pos->second; if(0 != runExtraInfo.m_hProcess) { CloseHandle(runExtraInfo.m_hProcess); } } m_RunTable.clear(); } else if(ServerManage::SEND_RUNINFO_NOW == usFlags) { // RunTable ϰ, μ . const ServerManage::RunInfo* lpRunInfo = reinterpret_cast(szData); const ServerManage::RunInfo* lpEndRunInfo = lpRunInfo + (usDataLen / sizeof(ServerManage::RunInfo)); for(; lpRunInfo != lpEndRunInfo; ++lpRunInfo) { m_RunTable.insert(RunTable::value_type(lpRunInfo->m_dwRunID, RunExtraInfo(*lpRunInfo, 0, 0))); } } else if(ServerManage::SEND_RUNINFO_FINISH == usFlags) { // μ Ŷ . CheckProcessStatus(); } return true; } bool CManageClientDispatch::ProcessRunServer(unsigned long dwRunID) { RunTable::iterator pos = m_RunTable.find(dwRunID); if(pos != m_RunTable.end()) { RunExtraInfo& runExInfo = pos->second; TCHAR szDrive[MAX_PATH]; TCHAR szPath[MAX_PATH]; TCHAR szDefaultPath[MAX_PATH]; _splitpath(runExInfo.m_RunInfo.m_szPath, szDrive, szPath, 0, 0); _snprintf(szDefaultPath, MAX_PATH - 1, "%s%s", szDrive, szPath); szDefaultPath[MAX_PATH - 1] = 0; STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi)); // Start the child process. /* if(CreateProcess(runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, 0, 0, FALSE, 0, 0, szDefaultPath, &si, &pi)) */ char szExecutePath[MAX_PATH * 2]; _snprintf(szExecutePath, MAX_PATH * 2 - 1, "\"%s\" %s", runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption); szExecutePath[MAX_PATH * 2 - 1] = 0; if(CreateProcess(0, szExecutePath, 0, 0, FALSE, 0, 0, szDefaultPath, &si, &pi)) { runExInfo.m_hProcess = pi.hProcess; runExInfo.m_dwProcessID = pi.dwProcessId; DETLOG4(g_Log, "Execute file success, RunID(%u), Path(%s), Option(%s), DefaultPath(%s)", runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, szDefaultPath); } else { ERRLOG5(g_Log, "Cannot execute file : CreateProcess failed(%d), RunID(%u), " "Path(%s), Option(%s), DefaultPath(%s)", WSAGetLastError(), runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption, szDefaultPath); } } else { ERRLOG1(g_Log, "Cannot execute file : Unknown RunID(%d)", dwRunID); } return true; } bool CManageClientDispatch::ProcessQuitServer(unsigned long dwRunID) { RunTable::iterator pos = m_RunTable.find(dwRunID); if(pos != m_RunTable.end()) { RunExtraInfo& runExInfo = pos->second; if(0 != runExInfo.m_hWnd) { TCHAR szWindowName[MAX_PATH]; GetWindowText(runExInfo.m_hWnd, szWindowName, MAX_PATH - 1); szWindowName[MAX_PATH - 1] = 0; SendMessage(runExInfo.m_hWnd, WM_DESTROY, 0, 0); DETLOG6(g_Log, "Send quit message : HANDLE(0x%p), PID(0x%08x), WindowName(%s), " "RunID(%u), Path(%s), Option(%s)", runExInfo.m_hProcess, runExInfo.m_dwProcessID, szWindowName, runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption); } else { ERRLOG5(g_Log, "Cannot send quit message (Get window failed) : " "HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s), Option(%s)", runExInfo.m_hProcess, runExInfo.m_dwProcessID, runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption); } } return true; } bool CManageClientDispatch::ProcessTerminateServer(unsigned long dwRunID) { RunTable::iterator pos = m_RunTable.find(dwRunID); if(pos != m_RunTable.end()) { RunExtraInfo& runExInfo = pos->second; if(0 != runExInfo.m_hProcess) { if(TerminateProcess(runExInfo.m_hProcess, -1)) { DETLOG5(g_Log, "Terminate process. HANDLE(0x%p), PID(0x%08x), " "RunID(%u), Path(%s), Option(%s)", runExInfo.m_hProcess, runExInfo.m_dwProcessID, runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption); } else { ERRLOG6(g_Log, "Cannot terminate process. Err(%d), HANDLE(0x%p), PID(0x%08x), " "RunID(%u), Path(%s), Option(%s)", GetLastError(), runExInfo.m_hProcess, runExInfo.m_dwProcessID, runExInfo.m_RunInfo.m_dwRunID, runExInfo.m_RunInfo.m_szPath, runExInfo.m_RunInfo.m_szOption); } } } return true; } bool CManageClientDispatch::ProcessExecuteConsoleCommand(ServerManage::ManageCommand* lpManageCmd) { RunTable::iterator pos = m_RunTable.find(lpManageCmd->dwRunID); if(pos != m_RunTable.end()) { RunExtraInfo& runExInfo = pos->second; if(0 != runExInfo.m_hWnd) { COPYDATASTRUCT copyDataStruct; copyDataStruct.dwData = 0; copyDataStruct.cbData = lpManageCmd->GetLen(); copyDataStruct.lpData = lpManageCmd; SendMessage(runExInfo.m_hWnd, WM_COPYDATA, 0, (LPARAM)©DataStruct); } } return true; } void CManageClientDispatch::CheckProcessStatus() { const int MAX_PROCESS_STATUS_SEND_ONCE = (PktMaxLen - sizeof(ServerManage::ManageCommand)) / sizeof(ServerManage::ProcessStatus); ServerManage::ProcessStatus procesStatus[MAX_PROCESS_STATUS_SEND_ONCE]; RunTable::iterator pos = m_RunTable.begin(); RunTable::iterator end = m_RunTable.end(); for(; pos != end; ++pos) { RunExtraInfo& runExtraInfo = pos->second; // üũϰ, PID ִµ μ α׷, μ . if(0 != runExtraInfo.m_dwProcessID && 0 != runExtraInfo.m_hWnd && 0 == runExtraInfo.m_hProcess) { runExtraInfo.m_hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, runExtraInfo.m_dwProcessID); } } unsigned long dwExitCode = 0; unsigned long dwErrorCode = 0; unsigned short usSendProcessStatus = 0; pos = m_RunTable.begin(); end = m_RunTable.end(); for(; pos != end; ++pos) { RunExtraInfo& runExtraInfo = pos->second; // Default - Deactivated Process. ServerManage::ProcessStatus* lpCurrentProcessStatus = procesStatus + usSendProcessStatus; memset(lpCurrentProcessStatus, 0, sizeof(ServerManage::ProcessStatus)); lpCurrentProcessStatus->m_dwRunID = runExtraInfo.m_RunInfo.m_dwRunID; lpCurrentProcessStatus->m_dwStatusFlags = 0; lpCurrentProcessStatus->m_dwCurrentTime = timeGetTime(); lpCurrentProcessStatus->m_dwCustomStatus = runExtraInfo.m_dwCustomStatus; lpCurrentProcessStatus->m_dwLastSetWindowHandleTime = runExtraInfo.m_dwLastSetWindowHandleTime; if(0 != runExtraInfo.m_hProcess) { GetProcessTimes(runExtraInfo.m_hProcess, &lpCurrentProcessStatus->m_CreationTIme, &lpCurrentProcessStatus->m_ExitTime, &lpCurrentProcessStatus->m_KernelTime, &lpCurrentProcessStatus->m_UserTime); GetProcessMemoryInfo(runExtraInfo.m_hProcess, &lpCurrentProcessStatus->m_ProcessMemoryCounters, sizeof(PROCESS_MEMORY_COUNTERS)); if(!GetExitCodeProcess(runExtraInfo.m_hProcess, &dwExitCode)) { ERRLOG3(g_Log, "GetExitCodeProcess failed(%d) : RunID(%u), Path(%s)", dwErrorCode, runExtraInfo.m_RunInfo.m_dwRunID, runExtraInfo.m_RunInfo.m_szPath); } else if(dwExitCode != STILL_ACTIVE) { DETLOG4(g_Log, "Close process handle : HANDLE(0x%p), PID(0x%08x), RunID(%u), Path(%s)", runExtraInfo.m_hProcess, runExtraInfo.m_dwProcessID, runExtraInfo.m_RunInfo.m_dwRunID, runExtraInfo.m_RunInfo.m_szPath); CloseHandle(runExtraInfo.m_hProcess); runExtraInfo.m_hProcess = 0; runExtraInfo.m_dwProcessID = 0; runExtraInfo.m_hWnd = 0; runExtraInfo.m_dwLastSetWindowHandleTime = 0; } else { lpCurrentProcessStatus->m_dwStatusFlags = ServerManage::PROCESS_RUNNING; } } ++usSendProcessStatus; if(usSendProcessStatus == MAX_PROCESS_STATUS_SEND_ONCE) { ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus, 0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0); usSendProcessStatus = 0; } } if(0 < usSendProcessStatus) { ServerManage::SendManagePacket(GetSession(), ServerManage::CMD::ProcessStatus, 0, 0, 0, 0, sizeof(ServerManage::ProcessStatus) * usSendProcessStatus, 0, procesStatus, 0); usSendProcessStatus = 0; } } bool CManageClientDispatch::SetAppData(unsigned long dwRunID, HWND hWnd, unsigned long dwPID, unsigned long dwCustomStatus) { RunTable::iterator pos = m_RunTable.find(dwRunID); RunTable::iterator end = m_RunTable.end(); if(pos != end) { RunExtraInfo& runExtraInfo = pos->second; runExtraInfo.m_dwProcessID = dwPID; runExtraInfo.m_hWnd = hWnd; runExtraInfo.m_dwCustomStatus = dwCustomStatus; runExtraInfo.m_dwLastSetWindowHandleTime = timeGetTime(); return true; } return false; } bool CManageClientDispatch::GetRunIDFromString(const char* szAppName, const char* szCommandLine, unsigned long& dwRunID_Out) { char szProcessName[MAX_PATH]; char szProcessSnapName[MAX_PATH]; _snprintf(szProcessSnapName, MAX_PATH - 1, "%s", szAppName); szProcessSnapName[MAX_PATH - 1] = 0; _strupr(szProcessSnapName); char szCommandLineData[MAX_PATH * 2]; _snprintf(szCommandLineData, MAX_PATH * 2 - 1, "%s", szCommandLine); szCommandLineData[MAX_PATH * 2 - 1] = 0; RunExtraInfo::CommandSet commandSet; char* szData = 0; if('\"' == szCommandLineData[0]) { szData = strtok(szCommandLineData, "\""); szData = strtok(0, "\""); if(0 != szData) { // ϸ и Argument ޾Ƽ ó.. char szRealCommandLine[MAX_PATH]; _snprintf(szRealCommandLine, MAX_PATH - 1, "%s", szData); szRealCommandLine[MAX_PATH - 1] = 0; szData = strtok(szRealCommandLine, " \t\r\n"); while(0 != szData) { commandSet.insert(szData); szData = strtok(0, " \t\r\n"); } } } else { szData = strtok(szCommandLineData, " \t\r\n"); // ù° Argument ϸ̹Ƿ . szData = strtok(0, " \t\r\n"); while(0 != szData) { commandSet.insert(szData); szData = strtok(0, " \t\r\n"); } } RunTable::iterator pos = m_RunTable.begin(); RunTable::iterator end = m_RunTable.end(); for(; pos != end; ++pos) { RunExtraInfo& runExtraInfo = pos->second; _snprintf(szProcessName, MAX_PATH - 1, "%s", runExtraInfo.m_RunInfo.m_szPath); szProcessName[MAX_PATH - 1] = 0; _strupr(szProcessName); if(0 == strncmp(szProcessName, szProcessSnapName, MAX_PATH)) { if((runExtraInfo.m_CommandSet.size() == commandSet.size() && std::equal(runExtraInfo.m_CommandSet.begin(), runExtraInfo.m_CommandSet.end(), commandSet.begin()))) { dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID; return true; } } } dwRunID_Out = 0; return false; } bool CManageClientDispatch::GetRunIDFromPID(unsigned long dwPID, unsigned long& dwRunID_Out) { RunTable::iterator pos = m_RunTable.begin(); RunTable::iterator end = m_RunTable.end(); for(; pos != end; ++pos) { RunExtraInfo& runExtraInfo = pos->second; if(runExtraInfo.m_dwProcessID == dwPID) { dwRunID_Out = runExtraInfo.m_RunInfo.m_dwRunID; return true; } } dwRunID_Out = 0; return false; } /* HANDLE GetProcessHandle(const char* szProcessFullPathName, unsigned long* lpdwPID) { HANDLE hProcess = INVALID_HANDLE_VALUE; if(0 == lpdwPID) { return hProcess; } // Take a snapshot of all processes in the system. HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) { return hProcess; } // Fill in the size of the structure before using it. PROCESSENTRY32 pe32 = {0}; pe32.dwSize = sizeof(PROCESSENTRY32); // Walk the snapshot of the processes, and for each process, // display information. char szProcessName[MAX_PATH]; char szProcessSnapName[MAX_PATH]; _snprintf(szProcessName, MAX_PATH - 1, "%s", szProcessFullPathName); szProcessName[MAX_PATH - 1] = 0; _strupr(szProcessName); bool bFound = false; if (Process32First(hProcessSnap, &pe32)) { do { MODULEENTRY32 me32 = {0}; HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe32.th32ProcessID); if (hModuleSnap != INVALID_HANDLE_VALUE) { me32.dwSize = sizeof(MODULEENTRY32); if (Module32First(hModuleSnap, &me32)) { do { _snprintf(szProcessSnapName, MAX_PATH - 1, "%s", me32.szExePath); szProcessSnapName[MAX_PATH - 1] = 0; _strupr(szProcessSnapName); if(0 == strcmp(szProcessName, szProcessSnapName)) { // Get the actual priority class. hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); if(INVALID_HANDLE_VALUE == hProcess) { ERRLOG2(g_Log, "Process open failed(%d) : %s", GetLastError(), me32.szExePath); } *lpdwPID = pe32.th32ProcessID; bFound = true; break; } } while (!bFound && Module32Next(hModuleSnap, &me32)); } CloseHandle (hModuleSnap); } } while (!bFound && Process32Next(hProcessSnap, &pe32)); } CloseHandle(hProcessSnap); return hProcess; } */