xref: /reactos/dll/win32/uxtheme/themehooks.c (revision 9393fc32)
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 
ThemeGetWndData(HWND hWnd)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 
ThemeDestroyWndData(HWND hWnd)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 
GetNCCaptionTheme(HWND hWnd,DWORD style)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 
GetNCScrollbarTheme(HWND hWnd,DWORD style)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 
ThemeCleanupChildWndContext(HWND hWnd,LPARAM msg)148 static BOOL CALLBACK ThemeCleanupChildWndContext (HWND hWnd, LPARAM msg)
149 {
150     ThemeDestroyWndData(hWnd);
151     return TRUE;
152 }
153 
ThemeCleanupWndContext(HWND hWnd,LPARAM msg)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 
SetThemeRegion(HWND hWnd)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 
OnPostWinPosChanged(HWND hWnd,WINDOWPOS * pWinPos)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
ThemeDefWindowProcW(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)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
ThemeDefWindowProcA(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)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
ThemePreWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam,ULONG_PTR ret,PDWORD unknown)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             if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
327                 ThemeCalculateCaptionButtonsPos(hWnd, NULL);
328             break;
329         }
330         case WM_THEMECHANGED:
331         {
332             PWND_DATA pwndData = ThemeGetWndData(hWnd);
333 
334             if (GetAncestor(hWnd, GA_PARENT) == GetDesktopWindow())
335                 UXTHEME_LoadTheme(TRUE);
336 
337             if (pwndData == NULL)
338                 return 0;
339 
340             if (pwndData->hTabBackgroundBrush != NULL)
341             {
342                 DeleteObject(pwndData->hTabBackgroundBrush);
343                 pwndData->hTabBackgroundBrush = NULL;
344             }
345 
346             if (pwndData->hTabBackgroundBmp != NULL)
347             {
348                 DeleteObject(pwndData->hTabBackgroundBmp);
349                 pwndData->hTabBackgroundBmp = NULL;
350             }
351 
352             if (pwndData->hthemeWindow)
353             {
354                 CloseThemeData(pwndData->hthemeWindow);
355                 pwndData->hthemeWindow = NULL;
356             }
357 
358             if (pwndData->hthemeScrollbar)
359             {
360                 CloseThemeData(pwndData->hthemeScrollbar);
361                 pwndData->hthemeScrollbar = NULL;
362             }
363 
364             if(IsAppThemed() && (GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
365                 ThemeCalculateCaptionButtonsPos(hWnd, NULL);
366 
367             pwndData->DirtyThemeRegion = TRUE;
368             break;
369         }
370         case WM_NCCREATE:
371         {
372             PWND_DATA pwndData = ThemeGetWndData(hWnd);
373             if (pwndData == NULL)
374                 return 0;
375             pwndData->DirtyThemeRegion = TRUE;
376         }
377     }
378 
379     return 0;
380 }
381 
382 
383 static LRESULT CALLBACK
ThemePostWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam,ULONG_PTR ret,PDWORD unknown)384 ThemePostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
385 {
386     switch(Msg)
387     {
388         case WM_WINDOWPOSCHANGED:
389         {
390             return OnPostWinPosChanged(hWnd, (WINDOWPOS*)lParam);
391         }
392         case WM_NCDESTROY:
393         {
394             ThemeDestroyWndData(hWnd);
395             return 0;
396         }
397     }
398 
399     return 0;
400 }
401 
GetDiaogTextureBrush(HTHEME theme,HWND hwnd,HDC hdc,HBRUSH * result,BOOL changeOrigin)402 HRESULT GetDiaogTextureBrush(HTHEME theme, HWND hwnd, HDC hdc, HBRUSH* result, BOOL changeOrigin)
403 {
404     PWND_DATA pwndData;
405 
406     pwndData = ThemeGetWndData(hwnd);
407     if (pwndData == NULL)
408         return E_FAIL;
409 
410     if (pwndData->hTabBackgroundBrush == NULL)
411     {
412         HBITMAP hbmp;
413         RECT dummy, bmpRect;
414         BOOL hasImageAlpha;
415         HRESULT hr;
416 
417         hr = UXTHEME_LoadImage(theme, 0, TABP_BODY, 0, &dummy, FALSE, &hbmp, &bmpRect, &hasImageAlpha);
418         if (FAILED(hr))
419             return hr;
420 
421         if (changeOrigin)
422         {
423             /* Unfortunately SetBrushOrgEx doesn't work at all */
424             RECT rcWindow, rcParent;
425             UINT y;
426             HDC hdcPattern, hdcHackPattern;
427             HBITMAP hbmpOld1, hbmpold2, hbmpHack;
428 
429             GetWindowRect(hwnd, &rcWindow);
430             GetWindowRect(GetParent(hwnd), &rcParent);
431             y = (rcWindow.top - rcParent.top) % bmpRect.bottom;
432 
433             hdcPattern = CreateCompatibleDC(hdc);
434             hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmp);
435 
436             hdcHackPattern = CreateCompatibleDC(hdc);
437             hbmpHack = CreateCompatibleBitmap(hdc, bmpRect.right, bmpRect.bottom);
438             hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpHack);
439 
440             BitBlt(hdcHackPattern, 0, 0, bmpRect.right, bmpRect.bottom - y, hdcPattern, 0, y, SRCCOPY);
441             BitBlt(hdcHackPattern, 0, bmpRect.bottom - y, bmpRect.right, y, hdcPattern, 0, 0, SRCCOPY);
442 
443             hbmpold2 = (HBITMAP)SelectObject(hdcHackPattern, hbmpold2);
444             hbmpOld1 = (HBITMAP)SelectObject(hdcPattern, hbmpOld1);
445 
446             DeleteDC(hdcPattern);
447             DeleteDC(hdcHackPattern);
448 
449             /* Keep the handle of the bitmap we created so that it can be used later */
450             pwndData->hTabBackgroundBmp = hbmpHack;
451             hbmp = hbmpHack;
452         }
453 
454         /* hbmp is cached so there is no need to free it */
455         pwndData->hTabBackgroundBrush = CreatePatternBrush(hbmp);
456     }
457 
458     if (!pwndData->hTabBackgroundBrush)
459         return E_FAIL;
460 
461     *result = pwndData->hTabBackgroundBrush;
462     return S_OK;
463 }
464 
HackFillStaticBg(HWND hwnd,HDC hdc,HBRUSH * result)465 void HackFillStaticBg(HWND hwnd, HDC hdc, HBRUSH* result)
466 {
467     RECT rcStatic;
468 
469     GetClientRect(hwnd, &rcStatic);
470     FillRect(hdc, &rcStatic, *result);
471 
472     SetBkMode (hdc, TRANSPARENT);
473     *result = GetStockObject (NULL_BRUSH);
474 }
475 
476 static LRESULT CALLBACK
ThemeDlgPreWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam,ULONG_PTR ret,PDWORD unknown)477 ThemeDlgPreWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
478 {
479     return 0;
480 }
481 
482 static LRESULT CALLBACK
ThemeDlgPostWindowProc(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam,ULONG_PTR ret,PDWORD unknown)483 ThemeDlgPostWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, ULONG_PTR ret,PDWORD unknown)
484 {
485     switch(Msg)
486     {
487         case WM_CTLCOLORDLG:
488         case WM_CTLCOLORBTN:
489         case WM_CTLCOLORSTATIC:
490         {
491             HWND hwndTarget = (HWND)lParam;
492             HDC hdc = (HDC)wParam;
493             HBRUSH* phbrush = (HBRUSH*)ret;
494             HTHEME hTheme;
495 
496             if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
497                 break;
498 
499             if (!IsThemeDialogTextureEnabled (hWnd))
500                 break;
501 
502             hTheme = GetWindowTheme(hWnd);
503             if (!hTheme)
504                 hTheme = OpenThemeData(hWnd, L"TAB");
505 
506             if (!hTheme)
507                 break;
508 
509             GetDiaogTextureBrush(hTheme, hwndTarget, hdc, phbrush, Msg != WM_CTLCOLORDLG);
510 
511 #if 1
512             {
513                 WCHAR controlClass[32];
514                 GetClassNameW (hwndTarget, controlClass, sizeof(controlClass) / sizeof(controlClass[0]));
515 
516                 /* This is a hack for the static class. Windows have a v6 static class just for this. */
517                 if (lstrcmpiW (controlClass, WC_STATICW) == 0)
518                     HackFillStaticBg(hwndTarget, hdc, phbrush);
519             }
520 #endif
521             SetBkMode( hdc, TRANSPARENT );
522             break;
523         }
524     }
525 
526     return 0;
527 }
528 
ThemeSetWindowRgn(HWND hWnd,HRGN hRgn,BOOL bRedraw)529 int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
530 {
531     PWND_DATA pwndData = ThemeGetWndData(hWnd);
532     if(pwndData)
533     {
534         pwndData->HasAppDefinedRgn = TRUE;
535         pwndData->HasThemeRgn = FALSE;
536     }
537 
538     return g_user32ApiHook.SetWindowRgn(hWnd, hRgn, bRedraw);
539 }
540 
ThemeGetScrollInfo(HWND hwnd,int fnBar,LPSCROLLINFO lpsi)541 BOOL WINAPI ThemeGetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi)
542 {
543     PWND_DATA pwndData;
544     DWORD style;
545     BOOL ret;
546 
547     /* Avoid creating a window context if it is not needed */
548     if(!IsAppThemed() || !(GetThemeAppProperties() & STAP_ALLOW_NONCLIENT))
549         goto dodefault;
550 
551     style = GetWindowLongW(hwnd, GWL_STYLE);
552     if((style & (WS_HSCROLL|WS_VSCROLL))==0)
553         goto dodefault;
554 
555     pwndData = ThemeGetWndData(hwnd);
556     if (pwndData == NULL)
557         goto dodefault;
558 
559     /*
560      * Uxtheme needs to handle the tracking of the scrollbar itself
561      * This means than if an application needs to get the track position
562      * with GetScrollInfo, it will get wrong data. So uxtheme needs to
563      * hook it and set the correct tracking position itself
564      */
565     ret = g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
566     if ( lpsi &&
567         (lpsi->fMask & SIF_TRACKPOS) &&
568          pwndData->SCROLL_TrackingWin == hwnd &&
569          pwndData->SCROLL_TrackingBar == fnBar)
570     {
571         lpsi->nTrackPos = pwndData->SCROLL_TrackingVal;
572     }
573     return ret;
574 
575 dodefault:
576     return g_user32ApiHook.GetScrollInfo(hwnd, fnBar, lpsi);
577 }
578 
ThemeSetScrollInfo(HWND hWnd,int fnBar,LPCSCROLLINFO lpsi,BOOL bRedraw)579 INT WINAPI ThemeSetScrollInfo(HWND hWnd, int fnBar, LPCSCROLLINFO lpsi, BOOL bRedraw)
580 {
581     PWND_DATA pwndData;
582     SCROLLINFO siout;
583     LPSCROLLINFO lpsiout = &siout;
584     BOOL IsThemed = FALSE;
585 
586     pwndData = ThemeGetWndData(hWnd);
587 
588     if (!pwndData)
589         goto dodefault;
590 
591     if (pwndData->hthemeScrollbar)
592         IsThemed = TRUE;
593 
594     memcpy(&siout, lpsi, sizeof(SCROLLINFO));
595     if (IsThemed)
596         siout.fMask |= SIF_THEMED;
597 
598 dodefault:
599     return g_user32ApiHook.SetScrollInfo(hWnd, fnBar, lpsiout, bRedraw);
600 }
601 
602 /**********************************************************************
603  *      Exports
604  */
605 
606 BOOL CALLBACK
ThemeInitApiHook(UAPIHK State,PUSERAPIHOOK puah)607 ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
608 {
609     if (!puah || State != uahLoadInit)
610     {
611         UXTHEME_LoadTheme(FALSE);
612         ThemeCleanupWndContext(NULL, 0);
613         g_bThemeHooksActive = FALSE;
614         return TRUE;
615     }
616 
617     g_bThemeHooksActive = TRUE;
618 
619     /* Store the original functions from user32 */
620     g_user32ApiHook = *puah;
621 
622     puah->DefWindowProcA = ThemeDefWindowProcA;
623     puah->DefWindowProcW = ThemeDefWindowProcW;
624     puah->PreWndProc = ThemePreWindowProc;
625     puah->PostWndProc = ThemePostWindowProc;
626     puah->PreDefDlgProc = ThemeDlgPreWindowProc;
627     puah->PostDefDlgProc = ThemeDlgPostWindowProc;
628     puah->DefWndProcArray.MsgBitArray  = gabDWPmessages;
629     puah->DefWndProcArray.Size = UAHOWP_MAX_SIZE;
630     puah->WndProcArray.MsgBitArray = gabMSGPmessages;
631     puah->WndProcArray.Size = UAHOWP_MAX_SIZE;
632     puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
633     puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
634 
635     puah->SetWindowRgn = ThemeSetWindowRgn;
636     puah->GetScrollInfo = ThemeGetScrollInfo;
637     puah->SetScrollInfo = ThemeSetScrollInfo;
638 
639     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCPAINT);
640     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCACTIVATE);
641     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSEMOVE);
642     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCMOUSELEAVE);
643     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCHITTEST);
644     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCLBUTTONDOWN);
645     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWCAPTION);
646     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCUAHDRAWFRAME);
647     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETTEXT);
648     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_WINDOWPOSCHANGED);
649     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CONTEXTMENU);
650     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_STYLECHANGED);
651     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SETICON);
652     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_NCDESTROY);
653     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_SYSCOMMAND);
654     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORMSGBOX);
655     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORBTN);
656     UAH_HOOK_MESSAGE(puah->DefWndProcArray, WM_CTLCOLORSTATIC);
657 
658     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_CREATE);
659     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_SETTINGCHANGE);
660     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_DRAWITEM);
661     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MEASUREITEM);
662     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGING);
663     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_WINDOWPOSCHANGED);
664     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGING);
665     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_STYLECHANGED);
666     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCCREATE);
667     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCDESTROY);
668     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_NCPAINT);
669     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MENUCHAR);
670     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_MDISETMENU);
671     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_THEMECHANGED);
672     UAH_HOOK_MESSAGE(puah->WndProcArray, WM_UAHINIT);
673 
674     puah->DlgProcArray.MsgBitArray = gabDLGPmessages;
675     puah->DlgProcArray.Size = UAHOWP_MAX_SIZE;
676 
677     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_INITDIALOG);
678     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORMSGBOX);
679     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORBTN);
680     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORDLG);
681     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_CTLCOLORSTATIC);
682     UAH_HOOK_MESSAGE(puah->DlgProcArray, WM_PRINTCLIENT);
683 
684     UXTHEME_LoadTheme(TRUE);
685 
686     return TRUE;
687 }
688 
689 typedef BOOL (WINAPI * PREGISTER_UAH_WINXP)(HINSTANCE hInstance, USERAPIHOOKPROC CallbackFunc);
690 typedef BOOL (WINAPI * PREGISTER_UUAH_WIN2003)(PUSERAPIHOOKINFO puah);
691 
692 BOOL WINAPI
ThemeHooksInstall()693 ThemeHooksInstall()
694 {
695     PVOID lpFunc;
696     OSVERSIONINFO osvi;
697     BOOL ret;
698 
699     lpFunc = GetProcAddress(GetModuleHandle("user32.dll"), "RegisterUserApiHook");
700 
701     ZeroMemory(&osvi, sizeof(OSVERSIONINFO));
702     osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
703     GetVersionEx(&osvi);
704 
705     if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
706     {
707         PREGISTER_UAH_WINXP lpfuncxp = (PREGISTER_UAH_WINXP)lpFunc;
708         ret = lpfuncxp(hDllInst, ThemeInitApiHook);
709     }
710     else if ( osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
711     {
712         PREGISTER_UUAH_WIN2003 lpfunc2003 = (PREGISTER_UUAH_WIN2003)lpFunc;
713         USERAPIHOOKINFO uah;
714 
715         uah.m_size = sizeof(uah);
716         uah.m_dllname1 = L"uxtheme.dll";
717         uah.m_funname1 = L"ThemeInitApiHook";
718         uah.m_dllname2 = NULL;
719         uah.m_funname2 = NULL;
720 
721         ret = lpfunc2003(&uah);
722     }
723     else
724     {
725         UNIMPLEMENTED;
726         ret = FALSE;
727     }
728 
729     UXTHEME_broadcast_theme_changed (NULL, TRUE);
730 
731     return ret;
732 }
733 
734 BOOL WINAPI
ThemeHooksRemove()735 ThemeHooksRemove()
736 {
737     BOOL ret;
738 
739     ret = UnregisterUserApiHook();
740 
741     UXTHEME_broadcast_theme_changed (NULL, FALSE);
742 
743     return ret;
744 }
745 
ClassicSystemParametersInfoW(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinIni)746 INT WINAPI ClassicSystemParametersInfoW(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
747 {
748     if (g_bThemeHooksActive)
749     {
750         return g_user32ApiHook.SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
751     }
752 
753     return SystemParametersInfoW(uiAction, uiParam, pvParam, fWinIni);
754 }
755 
ClassicSystemParametersInfoA(UINT uiAction,UINT uiParam,PVOID pvParam,UINT fWinIni)756 INT WINAPI ClassicSystemParametersInfoA(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni)
757 {
758     if (g_bThemeHooksActive)
759     {
760         return g_user32ApiHook.SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
761     }
762 
763     return SystemParametersInfoA(uiAction, uiParam, pvParam, fWinIni);
764 }
765 
ClassicGetSystemMetrics(int nIndex)766 INT WINAPI ClassicGetSystemMetrics(int nIndex)
767 {
768     if (g_bThemeHooksActive)
769     {
770         return g_user32ApiHook.GetSystemMetrics(nIndex);
771     }
772 
773     return GetSystemMetrics(nIndex);
774 }
775 
ClassicAdjustWindowRectEx(LPRECT lpRect,DWORD dwStyle,BOOL bMenu,DWORD dwExStyle)776 BOOL WINAPI ClassicAdjustWindowRectEx(LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle)
777 {
778     if (g_bThemeHooksActive)
779     {
780         return g_user32ApiHook.AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
781     }
782 
783     return AdjustWindowRectEx(lpRect, dwStyle, bMenu, dwExStyle);
784 }
785