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.

153 lines
3.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. SpecOps2.cpp
  5. Abstract:
  6. App does too much within a DLLMain and hangs because dinput is waiting on
  7. a thread it just created.
  8. The fix is to prevent the DllMain from running during the loader lock. The
  9. only way to do this seems to be to hook an API that's called really early
  10. during the DllMain and jump back to the loader.
  11. The catch is that we still need to call the DllMain after the LoadLibrary
  12. has completed.
  13. Notes:
  14. This is an app specific shim.
  15. History:
  16. 05/01/2001 linstev Created
  17. --*/
  18. #include "precomp.h"
  19. #include "LegalStr.h"
  20. IMPLEMENT_SHIM_BEGIN(SpecOps2)
  21. #include "ShimHookMacro.h"
  22. APIHOOK_ENUM_BEGIN
  23. APIHOOK_ENUM_ENTRY(GetVersion)
  24. APIHOOK_ENUM_ENTRY(LoadLibraryA)
  25. APIHOOK_ENUM_END
  26. // Global state used to determine what to do for a particular call
  27. BOOL g_bState = FALSE;
  28. // The thread handle for matching synchronization logic
  29. HANDLE g_hThread = NULL;
  30. /*++
  31. This is the first API that the DllMain calls, so we're going to back out
  32. jump straight out of it, back into loader code as if it completed normally.
  33. --*/
  34. __declspec(naked)
  35. DWORD
  36. APIHOOK(GetVersion)(
  37. void
  38. )
  39. {
  40. __asm {
  41. //
  42. // Make sure we're on the right thread so we don't have to synchronize
  43. //
  44. call dword ptr [GetCurrentThread]
  45. cmp eax, g_hThread
  46. jne Exit
  47. // test for the right dll
  48. cmp g_bState, 1
  49. jne Exit
  50. // we're done
  51. mov g_bState, 0
  52. // leave the stack and registers as they were before
  53. add esp, 20
  54. pop edi
  55. pop esi
  56. pop ebx
  57. pop ebp
  58. ret 12
  59. Exit:
  60. // original api
  61. call dword ptr [GetVersion]
  62. ret
  63. }
  64. }
  65. /*++
  66. When "SO Menu.dll" is loaded, we start the sequence which prevents the DllMain
  67. from crashing, but it means we have to run the entry point after the load.
  68. --*/
  69. HINSTANCE
  70. APIHOOK(LoadLibraryA)(
  71. LPCSTR lpLibFileName
  72. )
  73. {
  74. BOOL bCheck = FALSE;
  75. if (_stricmp(lpLibFileName, "menu\\SO Menu.dll") == 0) {
  76. //
  77. // We assume *only* the main thread tries to load this library, so
  78. // we don't synchronize multiple threads trying to load this same dll
  79. //
  80. g_hThread = GetCurrentThread();
  81. bCheck = TRUE;
  82. g_bState = TRUE;
  83. }
  84. //
  85. // Load the library, if it's "SO Menu", we'll catch the GetVersion called
  86. // by its DllMain
  87. //
  88. HMODULE hMod = ORIGINAL_API(LoadLibraryA)(lpLibFileName);
  89. if (hMod && bCheck) {
  90. //
  91. // Run the DllMain
  92. //
  93. typedef BOOL (WINAPI *_pfn_DllMain)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
  94. PIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER) hMod;
  95. PIMAGE_NT_HEADERS pINTH = (PIMAGE_NT_HEADERS)((LPBYTE)hMod + pIDH->e_lfanew);
  96. _pfn_DllMain pfnMain = (_pfn_DllMain)((LPBYTE)hMod + pINTH->OptionalHeader.AddressOfEntryPoint);
  97. // Call the startup routine
  98. (*pfnMain)(hMod, DLL_PROCESS_ATTACH, NULL);
  99. }
  100. return hMod;
  101. }
  102. /*++
  103. Register hooked functions
  104. --*/
  105. HOOK_BEGIN
  106. APIHOOK_ENTRY(KERNEL32.DLL, GetVersion)
  107. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryA)
  108. HOOK_END
  109. IMPLEMENT_SHIM_END