windows-nt/Source/XPSP1/NT/windows/appcompat/shims/specific/uninstallshield.cpp
2020-09-26 16:20:57 +08:00

164 lines
3.7 KiB
C++

/*++
eDbgLevelError
Copyright (c) 2000 Microsoft Corporation
Module Name:
UnInstallShield.cpp
Abstract:
UnInstallShield has an insidious bug where it calls WaitForSingleObject
on the HINSTANCE returned by ShellExecute. Since an HINSTANCE is not
an actual HANDLE, the WaitForSingleObject behaviour was completely random
and in some cases caused UnInstallShield to hang. The fix is to change
the HINSTANCE returned from ShellExecute to 0x0BADF00D and then look for
it being passed in to WaitForSingleObject. If found, WAIT_OBJECT_0 is
returned immediately to prevent deadlock.
Notes:
This is an app specific shim.
History:
12/04/2000 jdoherty Created
--*/
#include "precomp.h"
IMPLEMENT_SHIM_BEGIN(UnInstallShield)
#include "ShimHookMacro.h"
APIHOOK_ENUM_BEGIN
APIHOOK_ENUM_ENTRY(ShellExecuteA)
APIHOOK_ENUM_ENTRY(ShellExecuteW)
APIHOOK_ENUM_ENTRY(WaitForSingleObject)
APIHOOK_ENUM_END
/*++
Hook ShellExecuteA so we can check the return value.
--*/
HINSTANCE
APIHOOK(ShellExecuteA)(
HWND hwnd,
LPSTR lpVerb,
LPSTR lpFile,
LPSTR lpParameters,
LPSTR lpDirectory,
INT nShowCmd
)
{
HINSTANCE hRet = ORIGINAL_API(ShellExecuteA)(
hwnd,
lpVerb,
lpFile,
lpParameters,
lpDirectory,
nShowCmd
);
DPFN( eDbgLevelInfo, "[ShellExecuteA] Checking return value for 0x0000002a");
if (hRet == (HINSTANCE)0x0000002a)
{
DPFN( eDbgLevelInfo, "[ShellExecuteA] 0x0000002a found to be return value. Return 0x0BADF00D");
//
// if the HINSTANCE returned is 0x0000002a then return BAADF00D
//
hRet = (HINSTANCE)0x0BADF00D;
}
return hRet;
}
/*++
Hook ShellExecuteW so we can check the return value.
--*/
HINSTANCE
APIHOOK(ShellExecuteW)(
HWND hwnd,
LPWSTR lpVerb,
LPWSTR lpFile,
LPWSTR lpParameters,
LPWSTR lpDirectory,
INT nShowCmd
)
{
HINSTANCE hRet = ORIGINAL_API(ShellExecuteW)(
hwnd,
lpVerb,
lpFile,
lpParameters,
lpDirectory,
nShowCmd
);
DPFN( eDbgLevelInfo, "[ShellExecuteW] Checking return value for 0x0000002a");
if (hRet == (HINSTANCE)0x0000002a)
{
DPFN( eDbgLevelInfo, "[ShellExecuteW] 0x0000002a found to be return value. Return 0x0BADF00D");
//
// if the HINSTANCE returned is 0x0000002a then return BAADF00D
//
hRet = (HINSTANCE)0x0BADF00D;
}
return hRet;
}
/*++
Hook WaitForSingleObject to see if we are waiting for the known HINSTANCE.
--*/
DWORD
APIHOOK(WaitForSingleObject)(
HANDLE hHandle,
DWORD dwMilliseconds
)
{
DWORD dRet;
DPFN( eDbgLevelInfo, "[WaitForSingleObject] Checking to see if hHandle waiting on is 0x0000002A");
if (hHandle == (HANDLE)0x0BADF00D)
{
DPFN( eDbgLevelInfo, "[WaitForSingleObject] hHandle waiting on is 0x0000002A, returning WAIT_OBJECT_0");
//
// if the hHandle is 0x0BADF00D then return WAIT_OBJECT_0
//
dRet = WAIT_OBJECT_0;
}
else
{
dRet = ORIGINAL_API(WaitForSingleObject)(
hHandle,
dwMilliseconds
);
}
return dRet;
}
/*++
Register hooked functions
--*/
HOOK_BEGIN
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteA)
APIHOOK_ENTRY(SHELL32.DLL, ShellExecuteW)
APIHOOK_ENTRY(KERNEL32.DLL, WaitForSingleObject)
HOOK_END
IMPLEMENT_SHIM_END