You cannot pass a std::wstring
(or any C++ container) directly to a Win32 API function. The Win32 API is written with a C interface, and so it knows nothing about C++ types. As such, you must use C semantics when calling the API.
In your example, you can allocate a C style WCHAR[]
buffer to receive the filename, and then assign that buffer to your std::wstring
:
void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
WCHAR szFileName[MAX_PATH];
DWORD dwLength = 0;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL) {
dwLength = GetModuleFileNameExW(hProcess, NULL, szFileName, MAX_PATH);
CloseHandle(hProcess);
}
o_processName->assign(szFileName, dwLength);
}
Alternatively, if you want to use a C++ container, you have to preallocate it and then pass its internal data buffer to the API:
void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
std::wstring wFileName;
wFileName.resize(MAX_PATH);
DWORD dwLength = 0;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL) {
dwLength = GetModuleFileNameExW(hProcess, NULL, &wFileName[0], MAX_PATH); // or wFileName.data() in C++17 and later
CloseHandle(hProcess);
}
o_processName->assign(wFileName.c_str(), dwLength);
}
void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
std::vector<WCHAR> vecFileName(MAX_PATH, 0);
DWORD dwLength = 0;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL) {
dwLength = GetModuleFileNameExW(hProcess, NULL, &vecFileName[0], MAX_PATH); // or vecFileName.data() in C++11 and later
CloseHandle(hProcess);
}
o_processName->assign(&vecFileName[0], dwLength); // or vecFileName.data()
}
void GetProcessNameById(DWORD i_processId, std::wstring *o_processName) {
std::array<WCHAR, MAX_PATH> arrFileName;
DWORD dwLength = 0;
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, i_processId);
if (hProcess != NULL) {
dwLength = GetModuleFileNameExW(hProcess, NULL, arrFileName.data(), MAX_PATH);
CloseHandle(hProcess);
}
o_processName->assign(arrFileName.data(), dwLength);
}
If you want, you can take this a step further by using std::unique_ptr
in C++11 and later to ensure the HANDLE
is closed automatically when it goes out of scope.
And lastly, you should be using GetProcessImageFileNameW()
instead of GetModuleFileNameExW()
:
To retrieve the name of the main executable module for a remote process, use the GetProcessImageFileName
or QueryFullProcessImageName
function. This is more efficient and more reliable than calling the GetModuleFileNameEx
function with a NULL module handle.
Also, because GetProcessImageFileName()
requires only PROCESS_QUERY_LIMITED_INFORMATION
access rights, which you are more likely to be able to obtain than PROCESS_QUERY_INFORMATION | PROCESS_VM_READ
rights, especially for system/restricted processes.