/*
from http://msdn.microsoft.com/msdnmag/issues/02/06/debug/
Escape from DLL Hell with Custom Debugging and
Instrumentation Tools and Utilities
The PEB (Process Environment Block) is an undocumented structure
which varies from version to version of Windows.
However, WinDbg
(from http://www.microsoft.com/whdc/devtools/debugging/default.mspx)
provides a command that list the "documented" fields of a structure.
dt nt!_PEB
dt nt!_RTL_USER_PROCESS_PARAMETERS
*/
// Note that function name is not UNICODE
PFN_NTQUERYINFORMATIONPROCESS pfnNtQIP =
(PFN_NTQUERYINFORMATIONPROCESS)GetProcAddress(
hNtDll, "NtQueryInformationProcess");
if (pfnNtQIP != NULL) {
lStatus = pfnNtQIP(hProcess, pic, pPI, cbSize, pLength);
}
// 0. Get the Process Environment Block address
int iReturn = 1;
DWORD dwSize;
SIZE_T size;
PROCESS_BASIC_INFORMATION pbi;
// The PEB was supposed to always be at address 0x7ffdf000 in XP...
// ... but, here is the "right" way to get it now in Vista.
iReturn =
_NtQueryInformationProcess(
hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &dwSize);
// NtQueryInformationProcess returns a negative value if it fails
if (iReturn >= 0) {
// 1. Find the Process Environment Block
__PEB PEB;
size = dwSize;
if (!ReadProcessMemory(hProcess, pbi.PebBaseAddress, &PEB,
sizeof(PEB), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 2. From this PEB, get the address of the block containing
// a pointer to the CmdLine
__INFOBLOCK Block;
if (!ReadProcessMemory(hProcess, (LPVOID)PEB.InfoBlockAddress,
&Block, sizeof(Block), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 3. Get the CmdLine
wchar_t wszCmdLine[MAX_PATH+1];
if (!ReadProcessMemory(hProcess, (LPVOID)Block.wszCmdLineAddress,
wszCmdLine, MAX_PATH*sizeof(wchar_t), &size)) {
// Call GetLastError() if you need to know why
return(FALSE);
}
// 4. Skip the application pathname
// it can be empty, "c:\...\app.exe" or c:\...\app.exe
wchar_t* pPos = wszCmdLine;
if (*pPos != L'\0') {
if (*pPos == L'"') {
// Find the next " character
pPos = wcschr(&pPos[1], L'"');
} else {
// Find the next SPACE character
pPos = wcschr(&pPos[1], L' ');
}
// Skip it
if (pPos != NULL)
pPos++;
}
// Copy it back
if (pPos != NULL) {
if (*pPos != L'\0') {
#ifdef UNICODE
// Both strings are in UNICODE.
_tcscpy_s(szCmdLine, Size, pPos);
#else
// from UNICODE to ANSI
MultiByteToWideChar(CP_ACP, 0, szCmdLine, Size,
pPos, wcslen(pPos));
#endif
}
else
szCmdLine[0] = TEXT('\0');
}
else
szCmdLine[0] = TEXT('\0');
}
else {
return(FALSE);
}
// Check if we can get information for this process
HANDLE hProcess =
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, PID);
if (hProcess == NULL)
return(FALSE);