xref: /reactos/dll/win32/uxtheme/themehooks.c (revision e9d8fa57)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS uxtheme.dll
4  * FILE:            dll/win32/uxtheme/themehooks.c
5  * PURPOSE:         uxtheme user api hook functions
6  * PROGRAMMER:      Giannis Adamopoulos
7  */
8 
9 #include "uxthemep.h"
10 
11 USERAPIHOOK g_user32ApiHook;
12 BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
13 BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
14 BYTE gabDLGPmessages[UAHOWP_MAX_SIZE];
15 BOOL g_bThemeHooksActive = FALSE;
16 
17 PWND_DATA ThemeGetWndData(HWND hWnd)
18 {
19     PWND_DATA pwndData;
20 
21     pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
22     if(pwndData == NULL)
23     {
24         pwndData = HeapAlloc(GetProcessHeap(),
25                             HEAP_ZERO_MEMORY,
26                             sizeof(WND_DATA));
27         if(pwndData == NULL)
28         {
29             return NULL;
30         }
31 
32         SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), pwndData);
33     }
34 
35     return pwndData;
36 }
37 
38 void ThemeDestroyWndData(HWND hWnd)
39 {
40     PWND_DATA pwndData;
41     DWORD ProcessId;
42 
43     /*Do not destroy WND_DATA of a window that belong to another process */
44     GetWindowThreadProcessId(hWnd, &ProcessId);
45     if(ProcessId != GetCurrentProcessId())
46     {
47         return;
48     }
49 
50     pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
51     if(pwndData == NULL)
52     {
53         return;
54     }
55 
56     if(pwndData->HasThemeRgn)
57     {
58         g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
59     }
60 
61     if (pwndData->hTabBackgroundBrush != NULL)
62     {
63         CloseThemeData(GetWindowTheme(hWnd));
64 
65         DeleteObject(pwndData->hTabBackgroundBrush);
66     }
67 
68     if (pwndData->hTabBackgroundBmp != NULL)
69     {
70         DeleteObject(pwndData->hTabBackgroundBmp);
71     }
72 
73     if (pwndData->hthemeWindow)
74     {
75         CloseThemeData(pwndData->hthemeWindow);
76     }
77 
78     if (pwndData->hthemeScrollbar)
79     {
80         CloseThemeData(pwndData->hthemeScrollbar);
81     }
82 
83     HeapFree(GetProcessHeap(), 0, pwndData);
84 
85     SetPropW( hWnd, (LPCWSTR)MAKEINTATOM(atWndContext), NULL);
86 }
87 
88 HTHEME GetNCCaptionTheme(HWND hWnd, DWORD style)
89 {
90     PWND_DATA pwndData;
91 
92     /* We only get the theme for the window class if the window has a caption */
93     if((style & WS_CAPTION) != WS_CAPTION)
94         return NULL;
95 
96     /* Get theme data for this window */
97     pwndData = ThemeGetWndData(hWnd);
98     if (pwndData == NULL)
99         return NULL;
100 
101     if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
102     {
103         if (pwndData->hthemeWindow)
104         {
105             CloseThemeData(pwndData->hthemeWindow);
106             pwndData->hthemeWindow = NULL;
107         }
108         return NULL;
109     }
110 
111     /* If the theme data was not cached, open it now */
112     if (!pwndData->hthemeWindow)
113         pwndData->hthemeWindow = OpenThemeDataEx(hWnd, L"WINDOW", OTD_NONCLIENT);
114 
115     return pwndData->hthemeWindow;
116 }
117 
118 HTHEME GetNCScrollbarTheme(HWND hWnd, DWORD style)
119 {
120     PWND_DATA pwndData;
121 
122     /* We only get the theme for the scrollbar class if the window has a scrollbar */
123     if((style & (WS_HSCROLL|WS_VSCROLL)) == 0)
124         return NULL;
125 
126     /* Get theme data for this window */
127     pwndData = ThemeGetWndData(hWnd);
128     if (pwndData == NULL)
129         return NULL;
130 
131     if (!(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
132     {
133         if (pwndData->hthemeScrollbar)
134         {
135             CloseThemeData(pwndData->hthemeScrollbar);
136             pwndData->hthemeScrollbar = NULL;
137         }
138         return NULL;
139     }
140 
141     /* If the theme data was not cached, open it now */
142     if (!pwndData->hthemeScrollbar)
143         pwndData->hthemeScrollbar = OpenThemeDataEx(hWnd, L"SCROLLBAR", OTD_NONCLIENT);
144 
145     return pwndData->hthemeScrollbar;
146 }
147 
148 static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
149 {
150     ThemeDestroyWndData(hWnd);
151     return TRUE;
152 }
153 
154 static BOOL CALLBACK ThemeCleanupWndContext(HWND hWnd, LPARAM msg)
155 {
156     if (hWnd == NULL)
157     {
158         EnumWindows (ThemeCleanupWndContext, 0);
159     }
160     else
161     {
162         ThemeDestroyWndData(hWnd);
163         EnumChildWindows (hWnd, ThemeCleanupChildWndContext, 0);
164     }
165 
166     return TRUE;
167 }
168 
169 void SetThemeRegion(HWND hWnd)
170 {
171     HTHEME hTheme;
172     RECT rcWindow;
173     HRGN hrgn, hrgn1;
174     int CaptionHeight, iPart;
175     WINDOWINFO wi;
176 
177     TRACE("SetThemeRegion %d\n", hWnd);
178 
179     wi.cbSize = sizeof(wi);
180     GetWindowInfo(hWnd, &wi);
181 
182     /* Get the caption part id */
183     if (wi.dwStyle & WS_MINIMIZE)
184         iPart = WP_MINCAPTION;
185     else if (wi.dwExStyle & WS_EX_TOOLWINDOW)
186         iPart = WP_SMALLCAPTION;
187     else if (wi.dwStyle & WS_MAXIMIZE)
188         iPart = WP_MAXCAPTION;
189     else
190         iPart = WP_CAPTION;
191 
192     CaptionHeight = wi.cyWindowBorders;
193     CaptionHeight += GetSystemMetrics(wi.dwExStyle & WS_EX_TOOLWINDOW ? SM_CYSMCAPTION : SM_CYCAPTION );
194 
195     GetWindowRect(hWnd, &rcWindow);
196     rcWindow.right -= rcWindow.left;
197     rcWindow.bottom = CaptionHeight;
198     rcWindow.top = 0;
199     rcWindow.left = 0;
200 
201     hTheme = GetNCCaptionTheme(hWnd, wi.dwStyle);
202     GetThemeBackgroundRegion(hTheme, 0, iPart, FS_ACTIVE, &rcWindow, &hrgn);
203 
204     GetWindowRect(hWnd, &rcWindow);
205     rcWindow.right -= rcWindow.left;
206     rcWindow.bottom -= rcWindow.top;
207     rcWindow.top = CaptionHeight;
208     rcWindow.left = 0;
209     hrgn1 = CreateRectRgnIndirect(&rcWindow);
210 
211     CombineRgn(hrgn, hrgn, hrgn1, RGN_OR );
212 
213     DeleteObject(hrgn1);
214 
215     g_user32ApiHook.SetWindowRgn(hWnd, hrgn, TRUE);
216 }
217 
218 int OnPostWinPosChanged(HWND hWnd, WINDOWPOS* pWinPos)
219 {
220     PWND_DATA pwndData;
221     DWORD style;
222 
223     /* We only proceed to change the window shape if it has a caption */
224     style = GetWindowLongW(hWnd, GWL_STYLE);
225     if((style & WS_CAPTION)!=WS_CAPTION)
226         return 0;
227 
228     /* Get theme data for this window */
229     pwndData = ThemeGetWndData(hWnd);
230     if (pwndData == NULL)
231         return 0;
232 
233     /* Do not change the region of the window if its size wasn't changed */
234     if ((pWinPos->flags & SWP_NOSIZE) != 0 && pwndData->DirtyThemeRegion == FALSE)
235         return 0;
236 
237     /* We don't touch the shape of the window if the application sets it on its own */
238     if (pwndData->HasAppDefinedRgn != FALSE)
239         return 0;
240 
241     /* Calling SetWindowRgn will call SetWindowPos again so we need to avoid this recursion */
242     if (pwndData->UpdatingRgn != FALSE)
243         return 0;
244 
245     if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
246     {
247         if(pwndData->HasThemeRgn)
248         {
249             pwndData->HasThemeRgn = FALSE;
250             g_user32ApiHook.SetWindowRgn(hWnd, 0, TRUE);
251         }
252         return 0;
253     }
254 
255     pwndData->DirtyThemeRegion = FALSE;
256     pwndData->HasThemeRgn = TRUE;
257     pwndData->UpdatingRgn = TRUE;
258     SetThemeRegion(hWnd);
259     pwndData->UpdatingRgn = FALSE;
260 
261      return 0;
262  }
263 
264 /**********************************************************************
265  *      Hook Functions
266  */
267 
268 static LRESULT CALLBACK
269 ThemeDefWindowProcW(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
270 {
271     PWND_DATA pwndData;
272 
273     pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
274 
275     if(!IsAppThemed() ||
276        !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
277        (pwndData && pwndData->HasAppDefinedRgn))
278     {
279         return g_user32ApiHook.DefWindowProcW(hWnd,
280                                             Msg,
281                                             wParam,
282                                             lParam);
283     }
284 
285     return ThemeWndProc(hWnd,
286                         Msg,
287                         wParam,
288                         lParam,
289                         g_user32ApiHook.DefWindowProcW);
290 }
291 
292 static LRESULT CALLBACK
293 ThemeDefWindowProcA(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
294 {
295     PWND_DATA pwndData;
296 
297     pwndData = (PWND_DATA)GetPropW(hWnd, (LPCWSTR)MAKEINTATOM(atWndContext));
298 
299     if(!IsAppThemed() ||
300        !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT) ||
301        (pwndData && pwndData->HasAppDefinedRgn))
302     {
303         return g_user32ApiHook.DefWindowProcA(hWnd,
304                                             Msg,
305                                             wParam,
306                                             lParam);
307     }
308 
309     return ThemeWndProc(hWnd,
310                         Msg,
311                         wParam,
312                         lParam,
313                         g_user32ApiHook.DefWindowProcA);
314 }
315 
316 static LRESULT CALLBACK
317 ThemePreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
318 {
319     switch(Msg)
320     {
321         case WM_CREATE:
322         case WM_STYLECHANGED:
323         case WM_SIZE:
324         case WM_WINDOWPOSCHANGED:
325         {
326             ThemeCalculateCaptionButtonsPos(hWnd, NULL);
327             break;
328         }
329         case WM_THEMECHANGED:
330         {
331             PWND_DATA pwndData = ThemeGetWndData(hWnd);
332 
333             if (GetAncestor(hWnd, GA_PARENT) == GetDesktopWindow())
334                 UXTHEME_LoadTheme(TRUE);
335 
336             if (pwndData == NULL)
337                 return 0;
338 
339             if (pwndData->hTabBackgroundBrush != NULL)
340             {
341                 DeleteObject(pwndData->hTabBackgroundBrush);
342                 pwndData->hTabBackgroundBrush = NULL;
343             }
344 
345             if (pwndData->hTabBackgroundBmp != NULL)
346             {
347                 DeleteObject(pwndData->hTabBackgroundBmp);
348                 pwndData->hTabBackgroundBmp = NULL;
349             }
350 
351             if (pwndData->hthemeWindow)
352             {
353                 CloseThemeData(pwndData->hthemeWindow);
354                 pwndData->hthemeWindow = NULL;
355             }
356 
357             if (pwndData->hthemeScrollbar)
358             {
359                 CloseThemeData(pwndData->hthemeScrollbar);
360                 pwndData->hthemeScrollbar = NULL;
361             }
362 
363             ThemeCalculateCaptionButtonsPos(hWnd, NULL);
364         }
365         case WM_NCCREATE:
366         {
367             PWND_DATA pwndData = ThemeGetWndData(hWnd);
368             if (pwndData == NULL)
369                 return 0;
370             pwndData->DirtyThemeRegion = TRUE;
371         }
372     }
373 
374     return 0;
375 }
376 
377 
378 static LRESULT CALLBACK
379 ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
380 {
381     switch(Msg)
382     {
383         case WM_WINDOWPOSCHANGED:
384         {
385             return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
386         }
387         case WM_NCDESTROY:
388         {
389             ThemeDestroyWndData(hWnd);
390             return 0;
391         }
392     }
393 
394     return 0;
395 }
396 
397 HRESULT GetDiaogTextureBrush(HTHEME theme, HWND hwnd, HDC hdc, HBRUSH* result, BOOL changeOrigin)
398 {
399     PWND_DATA pwndData;
400 
401     pwndData = ThemeGetWndData(hwnd);
402     if (pwndData == NULL)
403         return E_FAIL;
404 
405     if (pwndData->hTabBackgroundBrush == NULL)
406     {
407         HBITMAP hbmp;
408         RECT dummy, bmpRect;
409         BOOL hasImageAlpha;
410         HRESULT hr;
411 
412         hr = UXTHEME_LoadImage(theme, 0, TABP_BODY, 0, &dummy, FALSE, &hbmp, &bmpRect, &hasImageAlpha);
413         if (FAILED(hr))
414             return hr;
415 
416         if (changeOrigin)
417         {
418             /* Unfortunately SetBrushOrgEx doesn't work at all */
419             RECT rcWindow, rcParent;
420             UINT y;
421             HDC hdcPattern, hdcHackPattern;
422             HBITMAP hbmpOld1, hbmpold2, hbmpHack;
423 
424             GetWindowRect(hwnd, &rcWindow);
425             GetWindowRect(GetParent(hwnd), &rcParent);
426             y = (rcWindow.top - rcParent.top) % bmpRect.bottom;
427 
428             hdcPattern = CreateCompatibleDC(hdc);
429             hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmp);
430 
431             hdcHackPattern = CreateCompatibleDC(hdc);
432             hbmpHack = CreateCompatibleBitmap(hdc, bmpRect.right, bmpRect.bottom);
433             hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpHack);
434 
435             BitBlt(hdcHackPattern, 0, 0, bmpRect.right, bmpRect.bottom - y, hdcPattern, 0, y, SRCCOPY);
436             BitBlt(hdcHackPattern, 0, bmpRect.bottom - y, bmpRect.right, y, hdcPattern, 0, 0, SRCCOPY);
437 
438             hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpold2);
439             hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmpOld1);
440 
441             DeleteDC(hdcPattern);
442             DeleteDC(hdcHackPattern);
443 
444             /* Keep the handle of the bitmap we created so that it can be used later */
445             pwndData->hTabBackgroundBmp = hbmpHack;
446             hbmp = hbmpHack;
447         }
448 
449         /* hbmp is cached so there is no need to free it */
450         pwndData->hTabBackgroundBrush = CreatePatternBrush(hbmp);
451     }
452 
453     if (!pwndData->hTabBackgroundBrush)
454         return E_FAIL;
455 
456     *result = pwndData->hTabBackgroundBrush;
457     return S_OK;
458 }
459 
460 void HackFillStaticBg(HWND hwnd, HDC hdc, HBRUSH* result)
461 {
462     RECT rcStatic;
463 
464     GetClientRect(hwnd, &rcStatic);
465     FillRect(hdc, &rcStatic, *result);
466 
467     SetBkMode (hdc, TRANSPARENT);
468     *result = GetStockObject (NULL_BRUSH);
469 }
470 
471 static LRESULT CALLBACK
472 ThemeDlgPreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
473 {
474     return 0;
475 }
476 
477 static LRESULT CALLBACK
478 ThemeDlgPostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
479 {
480     switch(Msg)
481     {
482         case WM_CTLCOLORDLG:
483         case WM_CTLCOLORBTN:
484         case WM_CTLCOLORSTATIC:
485         {
486             HWND hwndTarget = (HWND)lParam;
487             HDC hdc = (HDC)wParam;
488             HBRUSH* phbrush = (HBRUSH*)ret;
489             HTHEME hTheme;
490 
491             if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
492                 break;
493 
494             if (!IsThemeDialogTextureEnabled (hWnd))
495                 break;
496 
497             hTheme = GetWindowTheme(hWnd);
498             if (!hTheme)
499                 hTheme = OpenThemeData(hWnd, L"TAB");
500 
501             if (!hTheme)
502                 break;
503 
504             GetDiaogTextureBrush(hTheme, hwndTarget, hdc, phbrush, Msg != WM_CTLCOLORDLG);
505 
506 #if 1
507             {
508                 WCHAR controlClass[32];
509                 GetClassNameW (hwndTarget, controlClass, sizeof(controlClass) / sizeof(controlClass[0]));
510 
511                 /* This is a hack for the static class. Windows have a v6 static class just for this. */
512                 if (lstrcmpiW (controlClass, WC_STATICW) == 0)
513                     HackFillStaticBg(hwndTarget, hdc, phbrush);
514             }
515 #endif
516             SetBkMode( hdc, TRANSPARENT );
517             break;
518         }
519     }
520 
521     return 0;
522 }
523 
524 int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
525 {
526     PWND_DATA pwndData = ThemeGetWndData(hWnd);
527     if(pwndData)
528     {
529         pwndData->HasAppDefinedRgn = TRUE;
530         pwndData->HasThemeRgn = FALSE;
531     }
532 
533     return g_user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
534 }
535 
536 BOOL WINAPI ThemeGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
537 {
538     PWND_DATA pwndData;
539     DWORD style;
540     BOOL ret;
541 
542     /* Avoid creating a window context if it is not needed */
543     if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
544         goto dodefault;
545 
546     style = GetWindowLongW(hwnd, GWL_STYLE);
547     if((style & (WS_HSCROLL|WS_VSCROLL))==0)
548         goto dodefault;
549 
550     pwndData = ThemeGetWndData(hwnd);
551     if (pwndData == NULL)
552         goto dodefault;
553 
554     /*
555      * Uxtheme needs to handle the tracking of the scrollbar itself
556      * This means than if an application needs to get the track position
557      * with GetScrollInfo, it will get wrong data. So uxtheme needs to
558      * hook it and set the correct tracking position itself
559      */
560     ret = g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
561     if ( lpsi &&
562         (lpsi->fMask & SIF_TRACKPOS) &&
563          pwndData->SCROLL_TrackingWin == hwnd &&
564          pwndData->SCROLL_TrackingBar == fnBar)
565     {
566         lpsi->nTrackPos = pwndData->SCROLL_TrackingVal;
567     }
568     return ret;
569 
570 dodefault:
571     return g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
572 }
573 
574 /**********************************************************************
575  *      Exports
576  */
577 
578 BOOL CALLBACK
579 ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
580 {
581     if (!puah || State != uahLoadInit)
582     {
583         UXTHEME_LoadTheme(FALSE);
584         ThemeCleanupWndContext(NULL, 0);
585         g_bThemeHooksActive = FALSE;
586         return TRUE;
587     }
588 
589     g_bThemeHooksActive = TRUE;
590 
591     /* Store the original functions from user32 */
592     g_user32ApiHook = *puah;
593 
594     puah->DefWindowProcA = ThemeDefWindowProcA;
595     puah->DefWindowProcW = ThemeDefWindowProcW;
596     puah->PreWndProc = ThemePreWindowProc;
597     puah->PostWndProc = ThemePostWindowProc;
598     puah->PreDefDlgProc = ThemeDlgPreWindowProc;
599     puah->PostDefDlgProc = ThemeDlgPostWindowProc;
600     puah->DefWndProcArray.MsgBitArray  = gabDWPmessages;
601     puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
602     puah->WndProcArray.MsgBitArray = gabMSGPmessages;
603     puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
604     puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
605     puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
606 
607     puah->SetWindowRgn = ThemeSetWindowRgn;
608     puah->GetScrollInfo = ThemeGetScrollInfo;
609 
610     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
611     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
612     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
613     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
614     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
615     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
616     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
617     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
618     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
619     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
620     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
621     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
622     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
623     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
624     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
625     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
626     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
627     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
628 
629     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
630     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
631     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
632     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
633     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
634     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
635     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
636     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
637     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
638     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
639     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
640     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
641     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
642     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
643     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
644 
645     puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
646     puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
647 
648     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_INITDIALOG);
649     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORMSGBOX);
650     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORBTN);
651     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORDLG);
652     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORSTATIC);
653     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_PRINTCLIENT);
654 
655     UXTHEME_LoadTheme(TRUE);
656 
657     return TRUE;
658 }
659 
660 typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
661 typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
662 
663 BOOL WINAPI
664 ThemeHooksInstall()
665 {
666     PVOID lpFunc;
667     OSVERSIONINFO osvi;
668     BOOL ret;
669 
670     lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
671 
672     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
673     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
674     GetVersionEx(&osvi);
675 
676     if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
677     {
678         PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
679         ret = lpfuncxp(hDllInst, ThemeInitApiHook);
680     }
681     else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
682     {
683         PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
684         USERAPIHOOKINFO uah;
685 
686         uah.m_size = sizeof(uah);
687         uah.m_dllname1 = L"uxtheme.dll";
688         uah.m_funname1 = L"ThemeInitApiHook";
689         uah.m_dllname2 = NULL;
690         uah.m_funname2 = NULL;
691 
692         ret = lpfunc2003(&uah);
693     }
694     else
695     {
696         UNIMPLEMENTED;
697         ret = FALSE;
698     }
699 
700     UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
701 
702     return ret;
703 }
704 
705 BOOL WINAPI
706 ThemeHooksRemove()
707 {
708     BOOL ret;
709 
710     ret = UnregisterUserApiHook();
711 
712     UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
713 
714     return ret;
715 }
716 
717 INT WINAPI ClassicSystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
718 {
719     if (g_bThemeHooksActive)
720     {
721         return g_user32ApiHook.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
722     }
723 
724     return SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
725 }
726 
727 INT WINAPI ClassicSystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
728 {
729     if (g_bThemeHooksActive)
730     {
731         return g_user32ApiHook.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
732     }
733 
734     return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
735 }
736 
737 INT WINAPI ClassicGetSystemMetrics(int nIndex)
738 {
739     if (g_bThemeHooksActive)
740     {
741         return g_user32ApiHook.GetSystemMetrics(nIndex);
742     }
743 
744     return GetSystemMetrics(nIndex);
745 }
746 
747 BOOL WINAPI ClassicAdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle)
748 {
749     if (g_bThemeHooksActive)
750     {
751         return g_user32ApiHook.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
752     }
753 
754     return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
755 }
756