Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
3.9 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. EmulateToolHelp32.cpp
  5. Abstract:
  6. We've discovered 2 incompatibilities between the 9x and NT Toolhelp implementation so far that affect
  7. apps.
  8. 1) On 9x for the szExeFile field in PROCESSENTRY32 it simply uses the name of the executable
  9. module (which includes the full path and the executable name); on NT this is the image name.
  10. Nuclear Strike looks for '\' in szExeFile.
  11. 2) On 9x the cntUsage field of PROCESSENTRY32 is always non-zero while on NT it's always 0. We
  12. make it 1.
  13. there are others (like on NT the th32ModuleID is always 1 while on 9x it's unique for each module)
  14. but we haven't seen any apps having problems with those so we aren't putting them in.
  15. Notes:
  16. This is a general purpose shim.
  17. History:
  18. 11/14/2000 maonis Created
  19. --*/
  20. #include "precomp.h"
  21. #include "LegalStr.h"
  22. // The toolhelp APIs are lame - they define all the APIs to the W version when UNICODE is defined.
  23. // We want to hook the ANSI version so undefine UNICODE.
  24. #ifdef UNICODE
  25. #undef UNICODE
  26. #include <Tlhelp32.h>
  27. #endif
  28. typedef BOOL (WINAPI *_pfn_Process32First)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
  29. typedef BOOL (WINAPI *_pfn_Process32Next)(HANDLE hSnapshot, LPPROCESSENTRY32 lppe);
  30. IMPLEMENT_SHIM_BEGIN(EmulateToolHelp32)
  31. #include "ShimHookMacro.h"
  32. APIHOOK_ENUM_BEGIN
  33. APIHOOK_ENUM_ENTRY(Process32First)
  34. APIHOOK_ENUM_ENTRY(Process32Next)
  35. APIHOOK_ENUM_END
  36. /*++
  37. MSDN says the szExeFile field of PROCESSENTRY32 is supposed to contain the "Path and filename
  38. of the executable file for the process". But really, a process doesn't really have a path - only
  39. modules in the process do. NT does it right (it takes the image name), 9x doesn't.
  40. --*/
  41. BOOL GetProcessNameFullPath(DWORD dwPID, LPSTR szExeName)
  42. {
  43. BOOL bRet = FALSE;
  44. HANDLE hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
  45. if (hModuleSnap != (HANDLE)-1) {
  46. MODULEENTRY32 me32;
  47. me32.dwSize = sizeof(MODULEENTRY32);
  48. // The first module in the process is the one we want.
  49. if (Module32First(hModuleSnap, &me32)) {
  50. strcpy(szExeName, me32.szExePath);
  51. bRet = TRUE;
  52. }
  53. CloseHandle (hModuleSnap);
  54. }
  55. return bRet;
  56. }
  57. /*++
  58. This stub function skips the first few processes that don't apply in 9x and returns the first
  59. 9x-like process with the full path and name of the executable in lppe->szExeFile.
  60. --*/
  61. BOOL
  62. APIHOOK(Process32First)(
  63. HANDLE hSnapshot,
  64. LPPROCESSENTRY32 lppe
  65. )
  66. {
  67. // Skip till we find the first one we can get the module path and name.
  68. BOOL bRet = ORIGINAL_API(Process32First)(hSnapshot, lppe);
  69. // The 1st process in [System Process], we ignore it.
  70. if (!bRet) {
  71. return bRet;
  72. }
  73. // We can't get the first (or first few) process's module list - we return the first one we can.
  74. while (bRet = ORIGINAL_API(Process32Next)(hSnapshot, lppe)) {
  75. if (GetProcessNameFullPath(lppe->th32ProcessID, lppe->szExeFile)) {
  76. DPFN(eDbgLevelInfo, "[APIHook_Process32First] the 1st process name is %s\n", lppe->szExeFile);
  77. lppe->cntUsage = 1;
  78. return TRUE;
  79. }
  80. }
  81. return bRet;
  82. }
  83. /*++
  84. This stub function calls the API and get the full path and the name of the executable
  85. and put it in lppe->szExeFile.
  86. --*/
  87. BOOL
  88. APIHOOK(Process32Next)(
  89. HANDLE hSnapshot,
  90. LPPROCESSENTRY32 lppe
  91. )
  92. {
  93. BOOL bRet;
  94. if (bRet = ORIGINAL_API(Process32Next)(hSnapshot, lppe)) {
  95. if (!GetProcessNameFullPath(lppe->th32ProcessID, lppe->szExeFile)) {
  96. return FALSE;
  97. }
  98. DPFN(eDbgLevelInfo, "[APIHook_Process32Next] process name is %s\n", lppe->szExeFile);
  99. lppe->cntUsage = 1;
  100. }
  101. return bRet;
  102. }
  103. HOOK_BEGIN
  104. APIHOOK_ENTRY(KERNEL32.DLL, Process32First)
  105. APIHOOK_ENTRY(KERNEL32.DLL, Process32Next)
  106. HOOK_END
  107. IMPLEMENT_SHIM_END