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.

154 lines
3.3 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. WinExecRaceConditionFix.cpp
  5. Abstract:
  6. This Shim uses the command line parameter to indicate how it works:
  7. If passed 'nowait', it enables the WinExec functionality:
  8. The WinExec in this DLL is identical to the actual WinExec API but without
  9. the WaitForUserinputIdleRoutine, which inverts an almost race condition
  10. between the launcher and the launchee. 9x does not have this wait, so the
  11. programmers were able to (possibly inadvertently) use the same window class
  12. exclusion matching for both since, in 9x, the launcher kills itself before
  13. the launchee can check for a duplicate window. This shim leaves out the
  14. wait condition, allowing 9x like behavior.
  15. If passed a number, it sleeps in initialization for that number of
  16. microseconds.
  17. Notes:
  18. This shim has no app specific information.
  19. History:
  20. 03/22/2000 a-charr Created
  21. --*/
  22. #include "precomp.h"
  23. IMPLEMENT_SHIM_BEGIN(WinExecRaceConditionFix)
  24. #include "ShimHookMacro.h"
  25. APIHOOK_ENUM_BEGIN
  26. APIHOOK_ENUM_ENTRY(WinExec)
  27. APIHOOK_ENUM_END
  28. /*++
  29. This function breaks into WinExec and calls CreateProcessA without
  30. waiting afterward.
  31. --*/
  32. UINT
  33. APIHOOK(WinExec)(
  34. LPCSTR lpCmdLine,
  35. UINT uCmdShow
  36. )
  37. /*++
  38. This is a direct copy of the actual WinExec API minus two sections,
  39. 1. UserWaitForInputIdleRoutine is removed because it is waiting for the spawned
  40. process to begin its event loop, but the spawned process is killing itself
  41. before starting the event loop because the spawning process is waiting for
  42. it.
  43. 2. Some app specific appcompat code that seems to be hanging around from who
  44. knows when.
  45. --*/
  46. {
  47. STARTUPINFOA StartupInfo;
  48. PROCESS_INFORMATION ProcessInformation;
  49. BOOL CreateProcessStatus;
  50. DWORD ErrorCode;
  51. LOGN(
  52. eDbgLevelInfo,
  53. "[WinExec] Called. Returning without waiting for new process to start.");
  54. RtlZeroMemory(&StartupInfo,sizeof(StartupInfo));
  55. StartupInfo.cb = sizeof(StartupInfo);
  56. StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
  57. StartupInfo.wShowWindow = (WORD)uCmdShow;
  58. CreateProcessStatus = CreateProcessA(
  59. NULL,
  60. (LPSTR)lpCmdLine,
  61. NULL,
  62. NULL,
  63. FALSE,
  64. 0,
  65. NULL,
  66. NULL,
  67. &StartupInfo,
  68. &ProcessInformation);
  69. if (CreateProcessStatus) {
  70. return 33;
  71. } else {
  72. ErrorCode = GetLastError();
  73. switch (ErrorCode) {
  74. case ERROR_FILE_NOT_FOUND:
  75. return 2;
  76. case ERROR_PATH_NOT_FOUND:
  77. return 3;
  78. case ERROR_BAD_EXE_FORMAT:
  79. return 11;
  80. default:
  81. return 0;
  82. }
  83. }
  84. }
  85. BOOL
  86. NOTIFY_FUNCTION(
  87. DWORD fdwReason
  88. )
  89. {
  90. if (fdwReason == DLL_PROCESS_ATTACH) {
  91. //
  92. // Sleep when starting up, if the command line is a number.
  93. //
  94. long lSleepTicks = atol(COMMAND_LINE);
  95. if (lSleepTicks > 0) {
  96. Sleep((DWORD)lSleepTicks);
  97. }
  98. }
  99. return TRUE;
  100. }
  101. /*++
  102. Register hooked functions
  103. --*/
  104. HOOK_BEGIN
  105. APIHOOK_ENTRY(KERNEL32.DLL, WinExec)
  106. CALL_NOTIFY_FUNCTION
  107. HOOK_END
  108. IMPLEMENT_SHIM_END