reactos/dll/win32/uxtheme/themehooks.c
Giannis Adamopoulos 88a69b446b [UXTHEME] Fix a series of problems regarding ThemeCalculateCaptionButtonsPos
Only call it when needed. Also make it fail properly if the window theme could not be opened.
CORE-15564
2019-01-07 11:38:42 +02:00

760 lines
22 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS uxtheme.dll
* FILE: dll/win32/uxtheme/themehooks.c
* PURPOSE: uxtheme user api hook functions
* PROGRAMMER: Giannis Adamopoulos
*/
#include "uxthemep.h"
USERAPIHOOK g_user32ApiHook;
BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
BYTE gabDLGPmessages[UAHOWP_MAX_SIZE];
BOOL g_bThemeHooksActive = FALSE;
PWND_DATA ThemeGetWndData(HWND hWnd)
{
PWND_DATA pwndData;
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
if(pwndData == NULL)
{
pwndData = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof(WND_DATA));
if(pwndData == NULL)
{
return NULL;
}
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), pwndData);
}
return pwndData;
}
void ThemeDestroyWndData(HWND hWnd)
{
PWND_DATA pwndData;
DWORD ProcessId;
/*Do not destroy WND_DATA of a window that belong to another process */
GetWindowThreadProcessId(hWnd, &ProcessId);
if(ProcessId != GetCurrentProcessId())
{
return;
}
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
if(pwndData == NULL)
{
return;
}
if(pwndData->HasThemeRgn)
{
g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
if (pwndData->hTabBackgroundBrush != NULL)
{
CloseThemeData(GetWindowTheme(hWnd));
DeleteObject(pwndData->hTabBackgroundBrush);
}
if (pwndData->hTabBackgroundBmp != NULL)
{
DeleteObject(pwndData->hTabBackgroundBmp);
}
if (pwndData->hthemeWindow)
{
CloseThemeData(pwndData->hthemeWindow);
}
if (pwndData->hthemeScrollbar)
{
CloseThemeData(pwndData->hthemeScrollbar);
}
HeapFree(GetProcessHeap(), 0, pwndData);
SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), NULL);
}
HTHEME GetNCCaptionTheme(HWND hWnd, DWORD style)
{
PWND_DATA pwndData;
/* We only get the theme for the window class if the window has a caption */
if((style & WS_CAPTION) != WS_CAPTION)
return NULL;
/* Get theme data for this window */
pwndData = ThemeGetWndData(hWnd);
if (pwndData == NULL)
return NULL;
if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
{
if (pwndData->hthemeWindow)
{
CloseThemeData(pwndData->hthemeWindow);
pwndData->hthemeWindow = NULL;
}
return NULL;
}
/* If the theme data was not cached, open it now */
if (!pwndData->hthemeWindow)
pwndData->hthemeWindow = OpenThemeDataEx(hWnd, L"WINDOW", OTD_NONCLIENT);
return pwndData->hthemeWindow;
}
HTHEME GetNCScrollbarTheme(HWND hWnd, DWORD style)
{
PWND_DATA pwndData;
/* We only get the theme for the scrollbar class if the window has a scrollbar */
if((style & (WS_HSCROLL|WS_VSCROLL)) == 0)
return NULL;
/* Get theme data for this window */
pwndData = ThemeGetWndData(hWnd);
if (pwndData == NULL)
return NULL;
if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
{
if (pwndData->hthemeScrollbar)
{
CloseThemeData(pwndData->hthemeScrollbar);
pwndData->hthemeScrollbar = NULL;
}
return NULL;
}
/* If the theme data was not cached, open it now */
if (!pwndData->hthemeScrollbar)
pwndData->hthemeScrollbar = OpenThemeDataEx(hWnd, L"SCROLLBAR", OTD_NONCLIENT);
return pwndData->hthemeScrollbar;
}
static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
{
ThemeDestroyWndData(hWnd);
return TRUE;
}
static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
{
if (hWnd == NULL)
{
EnumWindows (ThemeCleanupWndContext, 0);
}
else
{
ThemeDestroyWndData(hWnd);
EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
}
return TRUE;
}
void SetThemeRegion(HWND hWnd)
{
HTHEME hTheme;
RECT rcWindow;
HRGN hrgn, hrgn1;
int CaptionHeight, iPart;
WINDOWINFO wi;
TRACE("SetThemeRegion %d\n", hWnd);
wi.cbSize = sizeof(wi);
GetWindowInfo(hWnd, &wi);
/* Get the caption part id */
if (wi.dwStyle & WS_MINIMIZE)
iPart = WP_MINCAPTION;
else if (wi.dwExStyle & WS_EX_TOOLWINDOW)
iPart = WP_SMALLCAPTION;
else if (wi.dwStyle & WS_MAXIMIZE)
iPart = WP_MAXCAPTION;
else
iPart = WP_CAPTION;
CaptionHeight = wi.cyWindowBorders;
CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
GetWindowRect(hWnd, &rcWindow);
rcWindow.right -= rcWindow.left;
rcWindow.bottom = CaptionHeight;
rcWindow.top = 0;
rcWindow.left = 0;
hTheme = GetNCCaptionTheme(hWnd, wi.dwStyle);
GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
GetWindowRect(hWnd, &rcWindow);
rcWindow.right -= rcWindow.left;
rcWindow.bottom -= rcWindow.top;
rcWindow.top = CaptionHeight;
rcWindow.left = 0;
hrgn1 = CreateRectRgnIndirect(&rcWindow);
CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
DeleteObject(hrgn1);
g_user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
}
int OnPostWinPosChanged(HWND hWnd, WINDOWPOS* pWinPos)
{
PWND_DATA pwndData;
DWORD style;
/* We only proceed to change the window shape if it has a caption */
style = GetWindowLongW(hWnd, GWL_STYLE);
if((style & WS_CAPTION)!=WS_CAPTION)
return 0;
/* Get theme data for this window */
pwndData = ThemeGetWndData(hWnd);
if (pwndData == NULL)
return 0;
/* Do not change the region of the window if its size wasn't changed */
if ((pWinPos->flags & SWP_NOSIZE) != 0 && pwndData->DirtyThemeRegion == FALSE)
return 0;
/* We don't touch the shape of the window if the application sets it on its own */
if (pwndData->HasAppDefinedRgn != FALSE)
return 0;
/* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
if (pwndData->UpdatingRgn != FALSE)
return 0;
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
{
if(pwndData->HasThemeRgn)
{
pwndData->HasThemeRgn = FALSE;
g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
}
return 0;
}
pwndData->DirtyThemeRegion = FALSE;
pwndData->HasThemeRgn = TRUE;
pwndData->UpdatingRgn = TRUE;
SetThemeRegion(hWnd);
pwndData->UpdatingRgn = FALSE;
return 0;
}
/**********************************************************************
* Hook Functions
*/
static LRESULT CALLBACK
ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PWND_DATA pwndData;
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
if(!IsAppThemed() ||
!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
(pwndData && pwndData->HasAppDefinedRgn))
{
return g_user32ApiHook.DefWindowProcW(hWnd,
Msg,
wParam,
lParam);
}
return ThemeWndProc(hWnd,
Msg,
wParam,
lParam,
g_user32ApiHook.DefWindowProcW);
}
static LRESULT CALLBACK
ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PWND_DATA pwndData;
pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
if(!IsAppThemed() ||
!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
(pwndData && pwndData->HasAppDefinedRgn))
{
return g_user32ApiHook.DefWindowProcA(hWnd,
Msg,
wParam,
lParam);
}
return ThemeWndProc(hWnd,
Msg,
wParam,
lParam,
g_user32ApiHook.DefWindowProcA);
}
static LRESULT CALLBACK
ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
switch(Msg)
{
case WM_CREATE:
case WM_STYLECHANGED:
case WM_SIZE:
case WM_WINDOWPOSCHANGED:
{
if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
ThemeCalculateCaptionButtonsPos(hWnd, NULL);
break;
}
case WM_THEMECHANGED:
{
PWND_DATA pwndData = ThemeGetWndData(hWnd);
if (GetAncestor(hWnd, GA_PARENT) == GetDesktopWindow())
UXTHEME_LoadTheme(TRUE);
if (pwndData == NULL)
return 0;
if (pwndData->hTabBackgroundBrush != NULL)
{
DeleteObject(pwndData->hTabBackgroundBrush);
pwndData->hTabBackgroundBrush = NULL;
}
if (pwndData->hTabBackgroundBmp != NULL)
{
DeleteObject(pwndData->hTabBackgroundBmp);
pwndData->hTabBackgroundBmp = NULL;
}
if (pwndData->hthemeWindow)
{
CloseThemeData(pwndData->hthemeWindow);
pwndData->hthemeWindow = NULL;
}
if (pwndData->hthemeScrollbar)
{
CloseThemeData(pwndData->hthemeScrollbar);
pwndData->hthemeScrollbar = NULL;
}
if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
ThemeCalculateCaptionButtonsPos(hWnd, NULL);
pwndData->DirtyThemeRegion = TRUE;
break;
}
case WM_NCCREATE:
{
PWND_DATA pwndData = ThemeGetWndData(hWnd);
if (pwndData == NULL)
return 0;
pwndData->DirtyThemeRegion = TRUE;
}
}
return 0;
}
static LRESULT CALLBACK
ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
switch(Msg)
{
case WM_WINDOWPOSCHANGED:
{
return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
}
case WM_NCDESTROY:
{
ThemeDestroyWndData(hWnd);
return 0;
}
}
return 0;
}
HRESULT GetDiaogTextureBrush(HTHEME theme, HWND hwnd, HDC hdc, HBRUSH* result, BOOL changeOrigin)
{
PWND_DATA pwndData;
pwndData = ThemeGetWndData(hwnd);
if (pwndData == NULL)
return E_FAIL;
if (pwndData->hTabBackgroundBrush == NULL)
{
HBITMAP hbmp;
RECT dummy, bmpRect;
BOOL hasImageAlpha;
HRESULT hr;
hr = UXTHEME_LoadImage(theme, 0, TABP_BODY, 0, &dummy, FALSE, &hbmp, &bmpRect, &hasImageAlpha);
if (FAILED(hr))
return hr;
if (changeOrigin)
{
/* Unfortunately SetBrushOrgEx doesn't work at all */
RECT rcWindow, rcParent;
UINT y;
HDC hdcPattern, hdcHackPattern;
HBITMAP hbmpOld1, hbmpold2, hbmpHack;
GetWindowRect(hwnd, &rcWindow);
GetWindowRect(GetParent(hwnd), &rcParent);
y = (rcWindow.top - rcParent.top) % bmpRect.bottom;
hdcPattern = CreateCompatibleDC(hdc);
hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmp);
hdcHackPattern = CreateCompatibleDC(hdc);
hbmpHack = CreateCompatibleBitmap(hdc, bmpRect.right, bmpRect.bottom);
hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpHack);
BitBlt(hdcHackPattern, 0, 0, bmpRect.right, bmpRect.bottom - y, hdcPattern, 0, y, SRCCOPY);
BitBlt(hdcHackPattern, 0, bmpRect.bottom - y, bmpRect.right, y, hdcPattern, 0, 0, SRCCOPY);
hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpold2);
hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmpOld1);
DeleteDC(hdcPattern);
DeleteDC(hdcHackPattern);
/* Keep the handle of the bitmap we created so that it can be used later */
pwndData->hTabBackgroundBmp = hbmpHack;
hbmp = hbmpHack;
}
/* hbmp is cached so there is no need to free it */
pwndData->hTabBackgroundBrush = CreatePatternBrush(hbmp);
}
if (!pwndData->hTabBackgroundBrush)
return E_FAIL;
*result = pwndData->hTabBackgroundBrush;
return S_OK;
}
void HackFillStaticBg(HWND hwnd, HDC hdc, HBRUSH* result)
{
RECT rcStatic;
GetClientRect(hwnd, &rcStatic);
FillRect(hdc, &rcStatic, *result);
SetBkMode (hdc, TRANSPARENT);
*result = GetStockObject (NULL_BRUSH);
}
static LRESULT CALLBACK
ThemeDlgPreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
return 0;
}
static LRESULT CALLBACK
ThemeDlgPostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
{
switch(Msg)
{
case WM_CTLCOLORDLG:
case WM_CTLCOLORBTN:
case WM_CTLCOLORSTATIC:
{
HWND hwndTarget = (HWND)lParam;
HDC hdc = (HDC)wParam;
HBRUSH* phbrush = (HBRUSH*)ret;
HTHEME hTheme;
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
break;
if (!IsThemeDialogTextureEnabled (hWnd))
break;
hTheme = GetWindowTheme(hWnd);
if (!hTheme)
hTheme = OpenThemeData(hWnd, L"TAB");
if (!hTheme)
break;
GetDiaogTextureBrush(hTheme, hwndTarget, hdc, phbrush, Msg != WM_CTLCOLORDLG);
#if 1
{
WCHAR controlClass[32];
GetClassNameW (hwndTarget, controlClass, sizeof(controlClass) / sizeof(controlClass[0]));
/* This is a hack for the static class. Windows have a v6 static class just for this. */
if (lstrcmpiW (controlClass, WC_STATICW) == 0)
HackFillStaticBg(hwndTarget, hdc, phbrush);
}
#endif
SetBkMode( hdc, TRANSPARENT );
break;
}
}
return 0;
}
int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
{
PWND_DATA pwndData = ThemeGetWndData(hWnd);
if(pwndData)
{
pwndData->HasAppDefinedRgn = TRUE;
pwndData->HasThemeRgn = FALSE;
}
return g_user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
}
BOOL WINAPI ThemeGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
{
PWND_DATA pwndData;
DWORD style;
BOOL ret;
/* Avoid creating a window context if it is not needed */
if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
goto dodefault;
style = GetWindowLongW(hwnd, GWL_STYLE);
if((style & (WS_HSCROLL|WS_VSCROLL))==0)
goto dodefault;
pwndData = ThemeGetWndData(hwnd);
if (pwndData == NULL)
goto dodefault;
/*
* Uxtheme needs to handle the tracking of the scrollbar itself
* This means than if an application needs to get the track position
* with GetScrollInfo, it will get wrong data. So uxtheme needs to
* hook it and set the correct tracking position itself
*/
ret = g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
if ( lpsi &&
(lpsi->fMask & SIF_TRACKPOS) &&
pwndData->SCROLL_TrackingWin == hwnd &&
pwndData->SCROLL_TrackingBar == fnBar)
{
lpsi->nTrackPos = pwndData->SCROLL_TrackingVal;
}
return ret;
dodefault:
return g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
}
/**********************************************************************
* Exports
*/
BOOL CALLBACK
ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
{
if (!puah || State != uahLoadInit)
{
UXTHEME_LoadTheme(FALSE);
ThemeCleanupWndContext(NULL, 0);
g_bThemeHooksActive = FALSE;
return TRUE;
}
g_bThemeHooksActive = TRUE;
/* Store the original functions from user32 */
g_user32ApiHook = *puah;
puah->DefWindowProcA = ThemeDefWindowProcA;
puah->DefWindowProcW = ThemeDefWindowProcW;
puah->PreWndProc = ThemePreWindowProc;
puah->PostWndProc = ThemePostWindowProc;
puah->PreDefDlgProc = ThemeDlgPreWindowProc;
puah->PostDefDlgProc = ThemeDlgPostWindowProc;
puah->DefWndProcArray.MsgBitArray = gabDWPmessages;
puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
puah->WndProcArray.MsgBitArray = gabMSGPmessages;
puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
puah->SetWindowRgn = ThemeSetWindowRgn;
puah->GetScrollInfo = ThemeGetScrollInfo;
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_INITDIALOG);
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORMSGBOX);
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORBTN);
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORDLG);
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORSTATIC);
UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_PRINTCLIENT);
UXTHEME_LoadTheme(TRUE);
return TRUE;
}
typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
BOOL WINAPI
ThemeHooksInstall()
{
PVOID lpFunc;
OSVERSIONINFO osvi;
BOOL ret;
lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&osvi);
if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
{
PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
ret = lpfuncxp(hDllInst, ThemeInitApiHook);
}
else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
{
PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
USERAPIHOOKINFO uah;
uah.m_size = sizeof(uah);
uah.m_dllname1 = L"uxtheme.dll";
uah.m_funname1 = L"ThemeInitApiHook";
uah.m_dllname2 = NULL;
uah.m_funname2 = NULL;
ret = lpfunc2003(&uah);
}
else
{
UNIMPLEMENTED;
ret = FALSE;
}
UXTHEME_broadcast_theme_changed (NULL, TRUE);
return ret;
}
BOOL WINAPI
ThemeHooksRemove()
{
BOOL ret;
ret = UnregisterUserApiHook();
UXTHEME_broadcast_theme_changed (NULL, FALSE);
return ret;
}
INT WINAPI ClassicSystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
{
if (g_bThemeHooksActive)
{
return g_user32ApiHook.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
}
return SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
}
INT WINAPI ClassicSystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
{
if (g_bThemeHooksActive)
{
return g_user32ApiHook.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
}
return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
}
INT WINAPI ClassicGetSystemMetrics(int nIndex)
{
if (g_bThemeHooksActive)
{
return g_user32ApiHook.GetSystemMetrics(nIndex);
}
return GetSystemMetrics(nIndex);
}
BOOL WINAPI ClassicAdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle)
{
if (g_bThemeHooksActive)
{
return g_user32ApiHook.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
}
return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
}