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.

163 lines
3.7 KiB

  1. /*++
  2. eDbgLevelError
  3. Copyright (c) 2000 Microsoft Corporation
  4. Module Name:
  5. UnInstallShield.cpp
  6. Abstract:
  7. UnInstallShield has an insidious bug where it calls WaitForSingleObject
  8. on the HINSTANCE returned by ShellExecute. Since an HINSTANCE is not
  9. an actual HANDLE, the WaitForSingleObject behaviour was completely random
  10. and in some cases caused UnInstallShield to hang. The fix is to change
  11. the HINSTANCE returned from ShellExecute to 0x0BADF00D and then look for
  12. it being passed in to WaitForSingleObject. If found, WAIT_OBJECT_0 is
  13. returned immediately to prevent deadlock.
  14. Notes:
  15. This is an app specific shim.
  16. History:
  17. 12/04/2000 jdoherty Created
  18. --*/
  19. #include "precomp.h"
  20. IMPLEMENT_SHIM_BEGIN(UnInstallShield)
  21. #include "ShimHookMacro.h"
  22. APIHOOK_ENUM_BEGIN
  23. APIHOOK_ENUM_ENTRY(ShellExecuteA)
  24. APIHOOK_ENUM_ENTRY(ShellExecuteW)
  25. APIHOOK_ENUM_ENTRY(WaitForSingleObject)
  26. APIHOOK_ENUM_END
  27. /*++
  28. Hook ShellExecuteA so we can check the return value.
  29. --*/
  30. HINSTANCE
  31. APIHOOK(ShellExecuteA)(
  32. HWND hwnd,
  33. LPSTR lpVerb,
  34. LPSTR lpFile,
  35. LPSTR lpParameters,
  36. LPSTR lpDirectory,
  37. INT nShowCmd
  38. )
  39. {
  40. HINSTANCE hRet = ORIGINAL_API(ShellExecuteA)(
  41. hwnd,
  42. lpVerb,
  43. lpFile,
  44. lpParameters,
  45. lpDirectory,
  46. nShowCmd
  47. );
  48. DPFN( eDbgLevelInfo, "[ShellExecuteA] Checking return value for 0x0000002a");
  49. if (hRet == (HINSTANCE)0x0000002a)
  50. {
  51. DPFN( eDbgLevelInfo, "[ShellExecuteA] 0x0000002a found to be return value. Return 0x0BADF00D");
  52. //
  53. // if the HINSTANCE returned is 0x0000002a then return BAADF00D
  54. //
  55. hRet = (HINSTANCE)0x0BADF00D;
  56. }
  57. return hRet;
  58. }
  59. /*++
  60. Hook ShellExecuteW so we can check the return value.
  61. --*/
  62. HINSTANCE
  63. APIHOOK(ShellExecuteW)(
  64. HWND hwnd,
  65. LPWSTR lpVerb,
  66. LPWSTR lpFile,
  67. LPWSTR lpParameters,
  68. LPWSTR lpDirectory,
  69. INT nShowCmd
  70. )
  71. {
  72. HINSTANCE hRet = ORIGINAL_API(ShellExecuteW)(
  73. hwnd,
  74. lpVerb,
  75. lpFile,
  76. lpParameters,
  77. lpDirectory,
  78. nShowCmd
  79. );
  80. DPFN( eDbgLevelInfo, "[ShellExecuteW] Checking return value for 0x0000002a");
  81. if (hRet == (HINSTANCE)0x0000002a)
  82. {
  83. DPFN( eDbgLevelInfo, "[ShellExecuteW] 0x0000002a found to be return value. Return 0x0BADF00D");
  84. //
  85. // if the HINSTANCE returned is 0x0000002a then return BAADF00D
  86. //
  87. hRet = (HINSTANCE)0x0BADF00D;
  88. }
  89. return hRet;
  90. }
  91. /*++
  92. Hook WaitForSingleObject to see if we are waiting for the known HINSTANCE.
  93. --*/
  94. DWORD
  95. APIHOOK(WaitForSingleObject)(
  96. HANDLE hHandle,
  97. DWORD dwMilliseconds
  98. )
  99. {
  100. DWORD dRet;
  101. DPFN( eDbgLevelInfo, "[WaitForSingleObject] Checking to see if hHandle waiting on is 0x0000002A");
  102. if (hHandle == (HANDLE)0x0BADF00D)
  103. {
  104. DPFN( eDbgLevelInfo, "[WaitForSingleObject] hHandle waiting on is 0x0000002A, returning WAIT_OBJECT_0");
  105. //
  106. // if the hHandle is 0x0BADF00D then return WAIT_OBJECT_0
  107. //
  108. dRet = WAIT_OBJECT_0;
  109. }
  110. else
  111. {
  112. dRet = ORIGINAL_API(WaitForSingleObject)(
  113. hHandle,
  114. dwMilliseconds
  115. );
  116. }
  117. return dRet;
  118. }
  119. /*++
  120. Register hooked functions
  121. --*/
  122. HOOK_BEGIN
  123. APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteA)
  124. APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteW)
  125. APIHOOK_ENTRY(KERNEL32.DLL, WaitForSingleObject)
  126. HOOK_END
  127. IMPLEMENT_SHIM_END