mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 14:30:57 +00:00
c7c36702d2
Fixes stack pointer corruption when using Windows's uxtheme.dll.
397 lines
9.1 KiB
C
397 lines
9.1 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS user32.dll
|
|
* FILE: win32ss/user/user32/misc/usrapihk.c
|
|
* PURPOSE: User32.dll User32 Api Hook interface and support functions
|
|
* PROGRAMMER:
|
|
*
|
|
*
|
|
*
|
|
* Information:
|
|
* http://www.reactos.org/wiki/RegisterUserApiHook
|
|
*
|
|
*/
|
|
|
|
#include <user32.h>
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(user32);
|
|
|
|
BOOL WINAPI RealAdjustWindowRectEx(LPRECT,DWORD,BOOL,DWORD);
|
|
LRESULT WINAPI RealDefWindowProcA(HWND,UINT,WPARAM,LPARAM);
|
|
LRESULT WINAPI RealDefWindowProcW(HWND,UINT,WPARAM,LPARAM);
|
|
BOOL WINAPI RealDrawFrameControl(HDC,LPRECT,UINT,UINT);
|
|
BOOL WINAPI RealGetScrollInfo(HWND,INT,LPSCROLLINFO);
|
|
int WINAPI RealGetSystemMetrics(int);
|
|
BOOL WINAPI RealMDIRedrawFrame(HWND,DWORD);
|
|
INT WINAPI RealSetScrollInfo(HWND,int,LPCSCROLLINFO,BOOL);
|
|
BOOL WINAPI RealSystemParametersInfoA(UINT,UINT,PVOID,UINT);
|
|
BOOL WINAPI RealSystemParametersInfoW(UINT,UINT,PVOID,UINT);
|
|
DWORD WINAPI GetRealWindowOwner(HWND);
|
|
BOOL WINAPI RealUserDrawCaption(HWND hWnd, HDC hDC, LPCRECT lpRc, UINT uFlags);
|
|
|
|
/* GLOBALS *******************************************************************/
|
|
|
|
DWORD gcLoadUserApiHook = 0;
|
|
LONG gcCallUserApiHook = 0;
|
|
DWORD gfUserApiHook = 0;
|
|
HINSTANCE ghmodUserApiHook = NULL;
|
|
USERAPIHOOKPROC gpfnInitUserApi;
|
|
RTL_CRITICAL_SECTION gcsUserApiHook;
|
|
// API Hooked Message group bitmaps
|
|
BYTE grgbDwpLiteHookMsg[128];
|
|
BYTE grgbWndLiteHookMsg[128];
|
|
BYTE grgbDlgLiteHookMsg[128];
|
|
|
|
/* INTERNAL ******************************************************************/
|
|
|
|
/*
|
|
Pre and Post Message handler stub.
|
|
*/
|
|
LRESULT
|
|
WINAPI
|
|
DefaultOWP(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR lResult, PDWORD pData)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
Check for API Hooked Message Overrides. Using message bitmapping.. One bit
|
|
corresponds to one message number.
|
|
*/
|
|
BOOL
|
|
FASTCALL
|
|
IsMsgOverride( UINT Msg, PUAHOWP puaowpOverride)
|
|
{
|
|
UINT nMsg = Msg / 8; // Group Indexed, (Msg 1024) / 8 = (0 -> 127) bytes Max
|
|
|
|
if ( puaowpOverride && nMsg < puaowpOverride->Size )
|
|
{
|
|
return (puaowpOverride->MsgBitArray[nMsg] & (1 << (Msg & WM_SETFOCUS)));
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
CopyMsgMask(PUAHOWP Dest, PUAHOWP Src, PVOID hkmsg, DWORD Size)
|
|
{
|
|
DWORD nSize;
|
|
|
|
if ( Src && Src->Size > 0 )
|
|
{
|
|
Dest->MsgBitArray = hkmsg;
|
|
nSize = Src->Size;
|
|
if ( Size < nSize) nSize = Size;
|
|
Dest->Size = nSize;
|
|
RtlCopyMemory(Dest->MsgBitArray, Src->MsgBitArray, nSize);
|
|
return;
|
|
}
|
|
|
|
Dest->MsgBitArray = NULL;
|
|
Dest->Size = 0;
|
|
return;
|
|
}
|
|
|
|
|
|
BOOL
|
|
FASTCALL
|
|
IsInsideUserApiHook(VOID)
|
|
{
|
|
if ( ghmodUserApiHook && gfUserApiHook ) return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
BeginIfHookedUserApiHook(VOID)
|
|
{
|
|
InterlockedIncrement(&gcCallUserApiHook);
|
|
if (IsInsideUserApiHook()) return TRUE;
|
|
|
|
InterlockedDecrement(&gcCallUserApiHook);
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
ForceResetUserApiHook(HINSTANCE hInstance)
|
|
{
|
|
if ( ghmodUserApiHook == hInstance &&
|
|
RtlIsThreadWithinLoaderCallout() )
|
|
{
|
|
ResetUserApiHook(&guah);
|
|
gpfnInitUserApi = NULL;
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
ResetUserApiHook(PUSERAPIHOOK puah)
|
|
{
|
|
// Setup Structure.....
|
|
puah->size = sizeof(USERAPIHOOK);
|
|
puah->DefWindowProcA = RealDefWindowProcA;
|
|
puah->DefWindowProcW = RealDefWindowProcW;
|
|
puah->DefWndProcArray.MsgBitArray = NULL;
|
|
puah->DefWndProcArray.Size = 0;
|
|
puah->GetScrollInfo = RealGetScrollInfo;
|
|
puah->SetScrollInfo = RealSetScrollInfo;
|
|
puah->EnableScrollBar = NtUserEnableScrollBar;
|
|
puah->AdjustWindowRectEx = RealAdjustWindowRectEx;
|
|
puah->SetWindowRgn = NtUserSetWindowRgn;
|
|
puah->PreWndProc = DefaultOWP;
|
|
puah->PostWndProc = DefaultOWP;
|
|
puah->WndProcArray.MsgBitArray = NULL;
|
|
puah->WndProcArray.Size = 0;
|
|
puah->PreDefDlgProc = DefaultOWP;
|
|
puah->PostDefDlgProc = DefaultOWP;
|
|
puah->DlgProcArray.MsgBitArray = NULL;
|
|
puah->DlgProcArray.Size = 0;
|
|
puah->GetSystemMetrics = RealGetSystemMetrics;
|
|
puah->SystemParametersInfoA = RealSystemParametersInfoA;
|
|
puah->SystemParametersInfoW = RealSystemParametersInfoW;
|
|
puah->ForceResetUserApiHook = ForceResetUserApiHook;
|
|
puah->DrawFrameControl = RealDrawFrameControl;
|
|
puah->DrawCaption = RealUserDrawCaption;
|
|
puah->MDIRedrawFrame = RealMDIRedrawFrame;
|
|
puah->GetRealWindowOwner = GetRealWindowOwner;
|
|
}
|
|
|
|
BOOL
|
|
FASTCALL
|
|
EndUserApiHook(VOID)
|
|
{
|
|
HMODULE hModule;
|
|
USERAPIHOOKPROC pfn;
|
|
BOOL Ret = FALSE;
|
|
|
|
if ( !InterlockedDecrement(&gcCallUserApiHook) )
|
|
{
|
|
if ( !gcLoadUserApiHook )
|
|
{
|
|
RtlEnterCriticalSection(&gcsUserApiHook);
|
|
|
|
pfn = gpfnInitUserApi;
|
|
hModule = ghmodUserApiHook;
|
|
ghmodUserApiHook = NULL;
|
|
gpfnInitUserApi = NULL;
|
|
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
|
|
if ( pfn ) Ret = pfn(uahStop, 0);
|
|
|
|
if ( hModule ) Ret = FreeLibrary(hModule);
|
|
}
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
ClearUserApiHook(HINSTANCE hInstance)
|
|
{
|
|
HMODULE hModule;
|
|
USERAPIHOOKPROC pfn = NULL, pfn1 = NULL;
|
|
|
|
RtlEnterCriticalSection(&gcsUserApiHook);
|
|
hModule = ghmodUserApiHook;
|
|
if ( ghmodUserApiHook == hInstance )
|
|
{
|
|
pfn1 = gpfnInitUserApi;
|
|
if ( --gcLoadUserApiHook == 0 )
|
|
{
|
|
gfUserApiHook = 0;
|
|
ResetUserApiHook(&guah);
|
|
if ( gcCallUserApiHook )
|
|
{
|
|
hInstance = NULL;
|
|
pfn1 = NULL;
|
|
pfn = gpfnInitUserApi;
|
|
gcLoadUserApiHook = 1;
|
|
}
|
|
else
|
|
{
|
|
hInstance = hModule;
|
|
ghmodUserApiHook = NULL;
|
|
gpfnInitUserApi = NULL;
|
|
}
|
|
}
|
|
}
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
|
|
if ( pfn )
|
|
{
|
|
pfn(uahShutdown, 0); // Shutdown.
|
|
|
|
RtlEnterCriticalSection(&gcsUserApiHook);
|
|
pfn1 = gpfnInitUserApi;
|
|
|
|
if ( --gcLoadUserApiHook == 0 )
|
|
{
|
|
if ( gcCallUserApiHook )
|
|
{
|
|
hInstance = NULL;
|
|
pfn1 = NULL;
|
|
}
|
|
else
|
|
{
|
|
hInstance = ghmodUserApiHook;
|
|
ghmodUserApiHook = NULL;
|
|
gpfnInitUserApi = NULL;
|
|
}
|
|
}
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
}
|
|
|
|
if ( pfn1 ) pfn1(uahStop, 0);
|
|
|
|
return hInstance != 0;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
InitUserApiHook(HINSTANCE hInstance, USERAPIHOOKPROC pfn)
|
|
{
|
|
USERAPIHOOK uah;
|
|
|
|
ResetUserApiHook(&uah);
|
|
|
|
RtlEnterCriticalSection(&gcsUserApiHook);
|
|
|
|
if (!pfn(uahLoadInit,&uah) || // Swap data, User32 to and Uxtheme from!
|
|
uah.ForceResetUserApiHook != ForceResetUserApiHook ||
|
|
uah.size <= 0 )
|
|
{
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
return FALSE;
|
|
}
|
|
|
|
if ( ghmodUserApiHook )
|
|
{
|
|
if ( ghmodUserApiHook != hInstance )
|
|
{
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
pfn(uahStop, 0);
|
|
return FALSE;
|
|
}
|
|
gcLoadUserApiHook++;
|
|
}
|
|
else
|
|
{
|
|
ghmodUserApiHook = hInstance;
|
|
// Do not over write GetRealWindowOwner.
|
|
RtlCopyMemory(&guah, &uah, sizeof(USERAPIHOOK) - sizeof(LONG));
|
|
gpfnInitUserApi = pfn;
|
|
gcLoadUserApiHook = 1;
|
|
gfUserApiHook = 1;
|
|
// Copy Message Masks
|
|
CopyMsgMask(&guah.DefWndProcArray,
|
|
&uah.DefWndProcArray,
|
|
&grgbDwpLiteHookMsg,
|
|
sizeof(grgbDwpLiteHookMsg));
|
|
|
|
CopyMsgMask(&guah.WndProcArray,
|
|
&uah.WndProcArray,
|
|
&grgbWndLiteHookMsg,
|
|
sizeof(grgbWndLiteHookMsg));
|
|
|
|
CopyMsgMask(&guah.DlgProcArray,
|
|
&uah.DlgProcArray,
|
|
&grgbDlgLiteHookMsg,
|
|
sizeof(grgbDlgLiteHookMsg));
|
|
}
|
|
RtlLeaveCriticalSection(&gcsUserApiHook);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
RealMDIRedrawFrame(HWND hWnd, DWORD flags)
|
|
{
|
|
return NtUserxMDIRedrawFrame(hWnd);
|
|
}
|
|
|
|
BOOL
|
|
WINAPI
|
|
MDIRedrawFrame(HWND hWnd, DWORD flags)
|
|
{
|
|
BOOL Hook, Ret = FALSE;
|
|
|
|
LoadUserApiHook();
|
|
|
|
Hook = BeginIfHookedUserApiHook();
|
|
|
|
/* Bypass SEH and go direct. */
|
|
if (!Hook) return RealMDIRedrawFrame(hWnd, flags);
|
|
|
|
_SEH2_TRY
|
|
{
|
|
Ret = guah.MDIRedrawFrame(hWnd, flags);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ERR("Got exception in hooked MDIRedrawFrame!\n");
|
|
}
|
|
_SEH2_END;
|
|
|
|
EndUserApiHook();
|
|
|
|
return Ret;
|
|
}
|
|
|
|
USERAPIHOOK guah =
|
|
{
|
|
sizeof(USERAPIHOOK),
|
|
RealDefWindowProcA,
|
|
RealDefWindowProcW,
|
|
{NULL, 0},
|
|
RealGetScrollInfo,
|
|
RealSetScrollInfo,
|
|
NtUserEnableScrollBar,
|
|
RealAdjustWindowRectEx,
|
|
NtUserSetWindowRgn,
|
|
DefaultOWP,
|
|
DefaultOWP,
|
|
{NULL, 0},
|
|
DefaultOWP,
|
|
DefaultOWP,
|
|
{NULL, 0},
|
|
RealGetSystemMetrics,
|
|
RealSystemParametersInfoA,
|
|
RealSystemParametersInfoW,
|
|
ForceResetUserApiHook,
|
|
RealDrawFrameControl,
|
|
NtUserDrawCaption,
|
|
RealMDIRedrawFrame,
|
|
GetRealWindowOwner,
|
|
};
|
|
|
|
/* FUNCTIONS *****************************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL WINAPI RegisterUserApiHook(PUSERAPIHOOKINFO puah)
|
|
{
|
|
UNICODE_STRING m_dllname1;
|
|
UNICODE_STRING m_funname1;
|
|
|
|
if (puah->m_size == sizeof(USERAPIHOOKINFO))
|
|
{
|
|
WARN("RegisterUserApiHook: %S and %S",puah->m_dllname1, puah->m_funname1);
|
|
RtlInitUnicodeString(&m_dllname1, puah->m_dllname1);
|
|
RtlInitUnicodeString(&m_funname1, puah->m_funname1);
|
|
return NtUserRegisterUserApiHook( &m_dllname1, &m_funname1, 0, 0);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL WINAPI UnregisterUserApiHook(VOID)
|
|
{
|
|
return NtUserUnregisterUserApiHook();
|
|
}
|