diff --git a/lib/memoryjs.cc b/lib/memoryjs.cc index 754906b..ced8896 100644 --- a/lib/memoryjs.cc +++ b/lib/memoryjs.cc @@ -127,7 +127,7 @@ Napi::Value getProcesses(const Napi::CallbackInfo& args) { // Define error message that may be set by the function that gets the processes char* errorMessage = ""; - std::vector processEntries = Process.getProcesses(&errorMessage); + std::vector processEntries = Process.getProcesses(&errorMessage); // If an error message was returned from the function that gets the processes, throw the error. // Only throw an error if there is no callback (if there's a callback, the error is passed there). @@ -140,7 +140,7 @@ Napi::Value getProcesses(const Napi::CallbackInfo& args) { Napi::Array processes = Napi::Array::New(env, processEntries.size()); // Loop over all processes found - for (std::vector::size_type i = 0; i != processEntries.size(); i++) { + for (std::vector::size_type i = 0; i != processEntries.size(); i++) { // Create a v8 object to store the current process' information Napi::Object process = Napi::Object::New(env); diff --git a/lib/process.cc b/lib/process.cc index b493d99..76c99b4 100644 --- a/lib/process.cc +++ b/lib/process.cc @@ -13,13 +13,13 @@ using v8::Isolate; using v8::String; process::Pair process::openProcess(const char* processName, char** errorMessage){ - PROCESSENTRY32 process; + PROCESSENTRY32A process; HANDLE handle = NULL; - // A list of processes (PROCESSENTRY32) - std::vector processes = getProcesses(errorMessage); + // A list of processes (PROCESSENTRY32A) + std::vector processes = getProcesses(errorMessage); - for (std::vector::size_type i = 0; i != processes.size(); i++) { + for (std::vector::size_type i = 0; i != processes.size(); i++) { // Check to see if this is the process we want. if (!strcmp(processes[i].szExeFile, processName)) { handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processes[i].th32ProcessID); @@ -39,13 +39,13 @@ process::Pair process::openProcess(const char* processName, char** errorMessage) } process::Pair process::openProcess(DWORD processId, char** errorMessage) { - PROCESSENTRY32 process; + PROCESSENTRY32A process; HANDLE handle = NULL; - // A list of processes (PROCESSENTRY32) - std::vector processes = getProcesses(errorMessage); + // A list of processes (PROCESSENTRY32A) + std::vector processes = getProcesses(errorMessage); - for (std::vector::size_type i = 0; i != processes.size(); i++) { + for (std::vector::size_type i = 0; i != processes.size(); i++) { // Check to see if this is the process we want. if (processId == processes[i].th32ProcessID) { handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processes[i].th32ProcessID); @@ -64,10 +64,10 @@ process::Pair process::openProcess(DWORD processId, char** errorMessage) { }; } -std::vector process::getProcesses(char** errorMessage) { +std::vector process::getProcesses(char** errorMessage) { // Take a snapshot of all processes. HANDLE hProcessSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); - PROCESSENTRY32 pEntry; + PROCESSENTRY32W pEntry; if (hProcessSnapshot == INVALID_HANDLE_VALUE) { *errorMessage = "method failed to take snapshot of the process"; @@ -77,18 +77,34 @@ std::vector process::getProcesses(char** errorMessage) { pEntry.dwSize = sizeof(pEntry); // Exit if unable to find the first process. - if (!Process32First(hProcessSnapshot, &pEntry)) { + if (!Process32FirstW(hProcessSnapshot, &pEntry)) { CloseHandle(hProcessSnapshot); *errorMessage = "method failed to retrieve the first process"; } - std::vector processes; + std::vector processes; // Loop through processes. do { // Add the process to the vector - processes.push_back(pEntry); - } while (Process32Next(hProcessSnapshot, &pEntry)); + PROCESSENTRY32A pEntryReal; + pEntryReal.dwSize = sizeof(pEntryReal); + + pEntryReal.cntUsage = pEntry.cntUsage; + pEntryReal.th32ProcessID = pEntry.th32ProcessID; + pEntryReal.th32DefaultHeapID = pEntry.th32DefaultHeapID; + pEntryReal.th32ModuleID = pEntry.th32ModuleID; + pEntryReal.cntThreads = pEntry.cntThreads; + pEntryReal.th32ParentProcessID = pEntry.th32ParentProcessID; + pEntryReal.pcPriClassBase = pEntry.pcPriClassBase; + pEntryReal.dwFlags = pEntry.dwFlags; + + // We use UTF-8 strings everywhere else in the program, but because the Windows API only supports Unicode through UTF-16, + // we have to convert the UTF-16 strings that Windows gives us to UTF-8 for use in the rest of the program + WideCharToMultiByte(CP_UTF8, 0, pEntry.szExeFile, -1, pEntryReal.szExeFile, sizeof(pEntryReal.szExeFile), NULL, NULL); + + processes.push_back(pEntryReal); + } while (Process32NextW(hProcessSnapshot, &pEntry)); CloseHandle(hProcessSnapshot); return processes; diff --git a/lib/process.h b/lib/process.h index 31a241e..ffb9a38 100644 --- a/lib/process.h +++ b/lib/process.h @@ -7,11 +7,32 @@ #include #include +// Struct definition copy pasted from Microsoft's documentation. + +// For some reason, TiHelp.h doesn't allow you to use the non-unicode version of this struct explicity +// You either explititly use the Unicode version by using PROCESSENTRY32W, or you use PROCESSENTRY32, +// which, if _UNICODE is defined, will resolve to PROCESSENTRY32W. + +// Perhaps defining a completely new struct with just the stuff that's needed would be better +struct PROCESSENTRY32A +{ + DWORD dwSize; + DWORD cntUsage; + DWORD th32ProcessID; // this process + ULONG_PTR th32DefaultHeapID; + DWORD th32ModuleID; // associated exe + DWORD cntThreads; + DWORD th32ParentProcessID; // this process's parent process + LONG pcPriClassBase; // Base priority of process's threads + DWORD dwFlags; + CHAR szExeFile[MAX_PATH]; // Path +} ; + class process { public: struct Pair { HANDLE handle; - PROCESSENTRY32 process; + PROCESSENTRY32A process; }; process(); @@ -20,7 +41,7 @@ class process { Pair openProcess(const char* processName, char** errorMessage); Pair openProcess(DWORD processId, char** errorMessage); void closeProcess(HANDLE hProcess); - std::vector getProcesses(char** errorMessage); + std::vector getProcesses(char** errorMessage); }; #endif