Reputation: 387
I'm writing a c++ program with visual studio and I have written this code
DWORD GetProcIDByName(const char* procName) {
HANDLE hSnap;
BOOL done;
PROCESSENTRY32 procEntry;
ZeroMemory(&procEntry, sizeof(PROCESSENTRY32));
procEntry.dwSize = sizeof(PROCESSENTRY32);
hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
done = Process32First(hSnap, &procEntry);
do {
/* here */ char file_str[sizeof(procEntry.szExeFile)];
int wc_convert = WideCharToMultiByte(CP_ACP, 0, procEntry.szExeFile, sizeof(procEntry.szExeFile), file_str, sizeof(file_str), NULL, NULL);
if (_strnicmp(file_str, procName, sizeof(file_str)) == 0) {
return procEntry.th32ProcessID;
}
} while (Process32Next(hSnap, &procEntry));
return 0;
}
in order to convert the value procEntry.szExeFile from a WCHAR* (wide unicode character array), to a standard char* to compare, I had to make a char* buffer for it. I wrote the line
char file_str[sizeof(procEntry.szExeFile)];
and realized later that I should use heap memory for this buffer that will change sizes depending on the process name, but I was surprised to see that my visual studio had no problem with this code and I was able to build it with no compiler errors. I haven't run it yet and I probably will not because I imagine if this runs there is a potential for buffer overflow and undefined behaviour
I don't have any issue, but I am curious about why I was able to write this code without getting a compiler error. If the process name is not known at compile time, how can I allocate this buffer on the stack?
Upvotes: 0
Views: 147
Reputation: 595402
The szExeFile
field is not dynamic length. It is a fixed-length array of MAX_PATH
characters, holding a null-terminated string.
Note that:
sizeof()
reports a size in bytesszExeFile
is an array of wchar_t
characters, in your casewchar_t
is 2 bytes in size on Windows.So, when you declare your char[]
array as char file_str[sizeof(procEntry.szExeFile)];
, it will have a static compile-time size of MAX_PATH*2
char
s. Which should be large enough to easily handle most conversions from wchar_t[]
to char[]
in this case.
BTW, your use of sizeof(procEntry.szExeFile)
in the 4th parameter of WideCharToMultiByte()
is wrong. That parameter expects a character count, not a byte count. Use lstrlenW(procEntry.szExeFile)
or wcslen(procEntry.szExeFile)
instead. Or just -1 to let WideCharToMultiByte()
count the wide characters for you.
That being said, an easier solution is to use Process32FirstA()
/Process32NextA()
instead. Or, change your function to take a Unicode wchar_t
string as input. Either way, then you won't have to convert the procEntry.szExeFile
at all, just use it as-is.
Also, you are leaking the HANDLE
from CreateToolhelp32Snapshot()
, you need to call CloseHandle()
when you are done using it.
Try this:
DWORD GetProcIDByName(const char* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32A procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstA(hSnap, &procEntry);
while (ok) {
if (_stricmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextA(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
Or this:
DWORD GetProcIDByName(const wchar_t* procName) {
DWORD dwProcessID = 0;
PROCESSENTRY32W procEntry = {};
procEntry.dwSize = sizeof(procEntry);
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE) {
BOOL ok = Process32FirstW(hSnap, &procEntry);
while (ok) {
if (_wcsicmp(procEntry.szExeFile, procName) == 0) {
dwProcessID = procEntry.th32ProcessID;
break;
}
ok = Process32NextW(hSnap, &procEntry);
}
CloseHandle(hSnap);
}
return dwProcessID;
}
Upvotes: 3