164 lines
3.7 KiB
C++
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
|
|
|