|
This program
takes two parameters: the process Id and the function’s absolute
address. If you have the other program still running, you can run the
program from listing 3 with the parameters as the first program has
printed them. You can see how OpenProcess
is used to obtain the process handle.
This handle needs
to be passed to all of the DebugHlp functions. Note
specifically how SymInitialize
is called: the fInvadeProcess
parameter is set to TRUE.
This makes sure that all modules within a process have their debug
information loaded. For debugging purposes the function
GetModuleFileNameEx
function is used to print the filename of the executing process.
To compile and
run both program listings, create a win32 console project, paste
these pieces of code into each main.cpp, and adjust the link
settings so that DebugHlp.lib and psapi.lib are linked
with them. The latter is for linking GetModuleFileNameEx.
The code was tested using Visual Studio 2005.
Note: before
running, make sure you have the latest version of DbgHelp.dll.
DbgHelp.dll is contained in the Debugging Tools for Windows 7.
The following
program output shows that the Id correctly matches the process’s
filename and that the function address indeed has been resolved to
the function name Foo:
Process
refers to: f:\work\tests\somedummyprocess\debug\somedummyprocess.exe
Function
name: Foo
As you can see from
this sample, we need the process Id to obtain the process handle.
That process handle is used to load symbol information. The next
question to answer is: how does the tool obtain the process Id?
Surely we can let the game send over the process Id by calling
GetCurrentProcessId
and transmit it to the tool.
This works fine but it does introduce a
very platform specific implementation in the networking part, which
may not be desirable. We can also let the tool enumerate all the
running processes, display a dialog box with the running processes,
and let the user select the process to obtain symbol information
from. Maybe you recognize this strategy from the way Visual Studio is
capable of attaching to a process for debugging. This solution is
obviously also a platform specific solution, but no matter which way
we go about it, symbol loading in the tool is going to be platform
specific anyway. Let’s see how this can be done.
Process handling is
done through the PSAPI library, which is the Process Status
Helper API. PSAPI is also part of the Windows Platform
SDK. We already used the function GetModuleFileNameEx
from this library in listing 3. The next listing, listing 4,
demonstrates how to enumerate the processes and how to obtain the
process handles.
|
|
#include "stdafx.h"
#include
#include
#include
#include
#include
#include "psapi.h"
std::string GetFileName(const char* fullPath)
{
char file[_MAX_FNAME], ext[_MAX_EXT];
_splitpath_s(fullPath, NULL, 0, NULL, 0,
file, sizeof(file), ext, sizeof(ext));
strcat_s(file, sizeof(file), ext);
return file;
}
void PrintProcessNameAndID(DWORD processID)
{
char processName[MAX_PATH] = "";
HANDLE processHandle =
::OpenProcess(PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, processID );
if(NULL != processHandle)
{
char imageName[MAX_PATH];
::GetProcessImageFileNameA(
processHandle,
imageName,
sizeof(imageName));
std::cout << GetFileName(imageName) <<
" (Process Id: 0x" <<
std::hex << processID << ")" << std::endl;
::CloseHandle(processHandle);
}
}
int main(int argc, char* argv[])
{
DWORD processes[1024], nrBytesWritten, nrProcesses;
unsigned int i;
int result = -1;
if(::EnumProcesses(
processes, sizeof(processes),
&nrBytesWritten))
{
nrProcesses = nrBytesWritten / sizeof(DWORD);
for(i = 0; i < nrProcesses; i++)
{
PrintProcessNameAndID(processes[i]);
}
result = 0;
}
return result;
}
|
 |
 |
 |
Listing 4: The
EnumerateProcesses program.
|
The program output
shows a list of the active processes along with their Id:
SMSS.EXE
(Process Id: 0x21c)
WINLOGON.EXE
(Process Id: 0x278)
SERVICES.EXE
(Process Id: 0x2a4)
LSASS.EXE
(Process Id: 0x2b0)
ATI2EVXX.EXE
(Process Id: 0x340)
SVCHOST.EXE
(Process Id: 0x360)
SVCHOST.EXE
(Process Id: 0x3ec)
ATI2EVXX.EXE
(Process Id: 0x478)
CLI.EXE
(Process Id: 0x9d4)
CLI.EXE
(Process Id: 0xf8c)
NSCSRVCE.EXE
(Process Id: 0x974)
VCExpress.exe
(Process Id: 0x950)
dexplore.exe
(Process Id: 0xca4)
mspdbsrv.exe
(Process Id: 0xf0)
WINWORD.EXE
(Process Id: 0xf18)
msmsgs.exe
(Process Id: 0x65c)
EnumerateProcesses.exe
(Process Id: 0x118)
|