Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Unicode and use the spellings of the Win32 function names that aren't affected by the _UNICODE macro #115

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/memoryjs.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<PROCESSENTRY32> processEntries = Process.getProcesses(&errorMessage);
std::vector<PROCESSENTRY32A> 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).
Expand All @@ -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<PROCESSENTRY32>::size_type i = 0; i != processEntries.size(); i++) {
for (std::vector<PROCESSENTRY32A>::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);

Expand Down
44 changes: 30 additions & 14 deletions lib/process.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<PROCESSENTRY32> processes = getProcesses(errorMessage);
// A list of processes (PROCESSENTRY32A)
std::vector<PROCESSENTRY32A> processes = getProcesses(errorMessage);

for (std::vector<PROCESSENTRY32>::size_type i = 0; i != processes.size(); i++) {
for (std::vector<PROCESSENTRY32A>::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);
Expand All @@ -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<PROCESSENTRY32> processes = getProcesses(errorMessage);
// A list of processes (PROCESSENTRY32A)
std::vector<PROCESSENTRY32A> processes = getProcesses(errorMessage);

for (std::vector<PROCESSENTRY32>::size_type i = 0; i != processes.size(); i++) {
for (std::vector<PROCESSENTRY32A>::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);
Expand All @@ -64,10 +64,10 @@ process::Pair process::openProcess(DWORD processId, char** errorMessage) {
};
}

std::vector<PROCESSENTRY32> process::getProcesses(char** errorMessage) {
std::vector<PROCESSENTRY32A> 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";
Expand All @@ -77,18 +77,34 @@ std::vector<PROCESSENTRY32> 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<PROCESSENTRY32> processes;
std::vector<PROCESSENTRY32A> 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;
Expand Down
25 changes: 23 additions & 2 deletions lib/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,32 @@
#include <TlHelp32.h>
#include <vector>

// 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();
Expand All @@ -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<PROCESSENTRY32> getProcesses(char** errorMessage);
std::vector<PROCESSENTRY32A> getProcesses(char** errorMessage);
};

#endif
Expand Down