patterncppMinor
Using ::CreateToolhelp32Snapshot
Viewed 0 times
createtoolhelp32snapshotusingstackoverflow
Problem
I have a process, let's call it Proc1. It is installed in two different directories and one instance of each is running:
When iterating through all currently running processes, I need to be able to differentiate one from the other. I do this by looking at the full path to the process.
Unfortunately, a little piece of documentation from MSDN has forced me to make this code pretty ugly:
MSDN
If the function fails with ERROR_BAD_LENGTH when called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the function again until it succeeds.
Please assume that C++11 is not available for this project.
- C:\DirA\Proc1.exe
- C:\DirB\Proc1.exe
When iterating through all currently running processes, I need to be able to differentiate one from the other. I do this by looking at the full path to the process.
Unfortunately, a little piece of documentation from MSDN has forced me to make this code pretty ugly:
MSDN
If the function fails with ERROR_BAD_LENGTH when called with TH32CS_SNAPMODULE or TH32CS_SNAPMODULE32, call the function again until it succeeds.
Please assume that C++11 is not available for this project.
bool MyClass::IsCorrectPath (const DWORD dwPid, const std::string &strPath) const
{
DWORD dwError = 0 ;
NormalHandle hModSnap ; // RAII wrapper for HANDLE
do {
hModSnap = ::CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, dwPid) ;
if (hModSnap == INVALID_HANDLE_VALUE) {
dwError == ::GetLastError () ;
if (dwError == ERROR_PARTIAL_COPY) {
// This occurs when trying to read a 64 bit process from a 32 bit process.
return false ;
}
else if (dwError == ERROR_BAD_LENGTH) {
// We have to repeatedly call ::CreateToolhelp32Snapshot () if we get this error
continue ;
}
else {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()",
"::CreateToolhelp32Snapshot ()", ::GetLastError ()) ;
}
}
} while ((hModSnap == INVALID_HANDLE_VALUE) && (dwError == ERROR_BAD_LENGTH)) ;
MODULEENTRY32 me ;
me.dwSize = sizeof (me) ;
if (::Module32First (hModSnap.Get (), &me) == FALSE) {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()", "::Module32First ()", ::GetLastError ()) ;
}
return (::_stricmp (strPath.data (), me.szExePath) == 0) ;
}Solution
I think you don't need to check for errors twice, and that will make your code cleaner.
So, instead of checking for all errors in every step of the loop, only check for the expected error.
Once you're out of the loop, it means you received a different error or you have a valid handle. Check if success and continue.
Does that make sense to you?
edit: Changed dwError == ERROR_SUCCESS to dModSnap == INVALID_HANDLE_VALUE.
bool MyClass::IsCorrectPath (const DWORD dwPid, const std::string &strPath) const
{
DWORD dwError = 0 ;
NormalHandle hModSnap ; // RAII wrapper for HANDLE
::SetLastError (0) ;
do {
// repeat while the expected error occurs
hModSnap = ::CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, dwPid) ;
dwError == ::GetLastError () ;
} while ((hModSnap == INVALID_HANDLE_VALUE) && (dwError == ERROR_BAD_LENGTH)) ;
if (dwError == ERROR_PARTIAL_COPY) {
// This occurs when trying to read a 64 bit process from a 32 bit process.
return false ;
}
if (hModSnap == INVALID_HANDLE_VALUE) {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()",
"::CreateToolhelp32Snapshot ()", ::GetLastError ()) ;
}
MODULEENTRY32 me ;
me.dwSize = sizeof (me) ;
if (::Module32First (hModSnap.Get (), &me) == FALSE) {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()", "::Module32First ()", ::GetLastError ()) ;
}
return (::_stricmp (strPath.data (), me.szExePath) == 0) ;
}So, instead of checking for all errors in every step of the loop, only check for the expected error.
Once you're out of the loop, it means you received a different error or you have a valid handle. Check if success and continue.
Does that make sense to you?
edit: Changed dwError == ERROR_SUCCESS to dModSnap == INVALID_HANDLE_VALUE.
Code Snippets
bool MyClass::IsCorrectPath (const DWORD dwPid, const std::string &strPath) const
{
DWORD dwError = 0 ;
NormalHandle hModSnap ; // RAII wrapper for HANDLE
::SetLastError (0) ;
do {
// repeat while the expected error occurs
hModSnap = ::CreateToolhelp32Snapshot (TH32CS_SNAPMODULE, dwPid) ;
dwError == ::GetLastError () ;
} while ((hModSnap == INVALID_HANDLE_VALUE) && (dwError == ERROR_BAD_LENGTH)) ;
if (dwError == ERROR_PARTIAL_COPY) {
// This occurs when trying to read a 64 bit process from a 32 bit process.
return false ;
}
if (hModSnap == INVALID_HANDLE_VALUE) {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()",
"::CreateToolhelp32Snapshot ()", ::GetLastError ()) ;
}
MODULEENTRY32 me ;
me.dwSize = sizeof (me) ;
if (::Module32First (hModSnap.Get (), &me) == FALSE) {
ThrowFunctionFailure ("MyClass::IsCorrectPath ()", "::Module32First ()", ::GetLastError ()) ;
}
return (::_stricmp (strPath.data (), me.szExePath) == 0) ;
}Context
StackExchange Code Review Q#38839, answer score: 2
Revisions (0)
No revisions yet.