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.

135 lines
2.7 KiB

  1. /*++
  2. Copyright (c) 2002 Microsoft Corporation
  3. Module Name:
  4. EmulateSlowCPU.cpp
  5. Abstract:
  6. Modify performance testing routines to emulate slower processors.
  7. Notes:
  8. This is a general purpose shim.
  9. History:
  10. 07/16/2002 mnikkel Created.
  11. --*/
  12. #include "precomp.h"
  13. #include <mmsystem.h>
  14. IMPLEMENT_SHIM_BEGIN(EmulateSlowCPU)
  15. #include "ShimHookMacro.h"
  16. APIHOOK_ENUM_BEGIN
  17. APIHOOK_ENUM_ENTRY(timeGetTime)
  18. APIHOOK_ENUM_ENTRY(QueryPerformanceCounter)
  19. APIHOOK_ENUM_ENTRY(QueryPerformanceFrequency)
  20. APIHOOK_ENUM_END
  21. typedef BOOL (*_pfn_QueryPerformanceCounter)(LARGE_INTEGER *lpPerformanceCount);
  22. typedef BOOL (*_pfn_QueryPerformanceFrequency)(LARGE_INTEGER *lpPerformanceFreq);
  23. DWORD g_dwDivide = 1;
  24. BOOL g_btimeGetTime = FALSE;
  25. /*++
  26. Don't allow the current time to be equal to the prev time.
  27. --*/
  28. DWORD
  29. APIHOOK(timeGetTime)(VOID)
  30. {
  31. if (g_btimeGetTime) {
  32. LARGE_INTEGER PerfFreq;
  33. LARGE_INTEGER PerfCount1, PerfCount2;
  34. if (QueryPerformanceFrequency(&PerfFreq) &&
  35. QueryPerformanceCounter(&PerfCount1)) {
  36. do {
  37. if (!QueryPerformanceCounter(&PerfCount2)) break;
  38. } while (((double)(PerfCount2.QuadPart - PerfCount1.QuadPart) / PerfFreq.QuadPart) < 0.0001);
  39. }
  40. }
  41. return ORIGINAL_API(timeGetTime)();
  42. }
  43. BOOL
  44. APIHOOK(QueryPerformanceCounter)(
  45. LARGE_INTEGER *lpPerformanceCount
  46. )
  47. {
  48. BOOL bRet = ORIGINAL_API(QueryPerformanceCounter)(lpPerformanceCount);
  49. if (lpPerformanceCount) {
  50. lpPerformanceCount->QuadPart /= g_dwDivide;
  51. }
  52. return bRet;
  53. }
  54. BOOL
  55. APIHOOK(QueryPerformanceFrequency)(
  56. LARGE_INTEGER *lpPerformanceFreq
  57. )
  58. {
  59. BOOL bRet = ORIGINAL_API(QueryPerformanceFrequency)(lpPerformanceFreq);
  60. if (lpPerformanceFreq) {
  61. lpPerformanceFreq->QuadPart /= g_dwDivide;
  62. }
  63. return bRet;
  64. }
  65. BOOL
  66. NOTIFY_FUNCTION(
  67. DWORD fdwReason
  68. )
  69. {
  70. if (fdwReason == DLL_PROCESS_ATTACH) {
  71. g_btimeGetTime = COMMAND_LINE && (_stricmp(COMMAND_LINE, "+timeGetTime") == 0);
  72. INT64 l1, l2;
  73. if (QueryPerformanceCounter((LARGE_INTEGER *)&l1) &&
  74. QueryPerformanceCounter((LARGE_INTEGER *)&l2)) {
  75. // Calculate the divide factor
  76. g_dwDivide = (DWORD_PTR)((l2 - l1)) / 5;
  77. if (g_dwDivide == 0) {
  78. g_dwDivide = 1;
  79. }
  80. LOGN(eDbgLevelInfo, "[NotifyFn] EmulateSlowCPU initialized with divisor %d", g_dwDivide);
  81. return TRUE;
  82. }
  83. }
  84. return TRUE;
  85. }
  86. /*++
  87. Register hooked functions
  88. --*/
  89. HOOK_BEGIN
  90. CALL_NOTIFY_FUNCTION
  91. APIHOOK_ENTRY(WINMM.DLL, timeGetTime)
  92. APIHOOK_ENTRY(KERNEL32.DLL, QueryPerformanceCounter)
  93. APIHOOK_ENTRY(KERNEL32.DLL, QueryPerformanceFrequency)
  94. HOOK_END
  95. IMPLEMENT_SHIM_END