1c3ea2ab01523056ea32e9bf19bedf0e8ae72da6
[reactos.git] / dll / win32 / uxtheme / system.c
1 /*
2 * Win32 5.1 Theme system
3 *
4 * Copyright (C) 2003 Kevin Koltzau
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24 #include <stdio.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "winreg.h"
31 #include "vfwmsgs.h"
32 #include "uxtheme.h"
33 #include "tmschema.h"
34
35 #include "uxthemedll.h"
36 #include "msstyles.h"
37 #include "ncthm.h"
38
39 #include "wine/debug.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
42
43 /***********************************************************************
44 * Defines and global variables
45 */
46
47 static const WCHAR szThemeManager[] = {
48 'S','o','f','t','w','a','r','e','\\',
49 'M','i','c','r','o','s','o','f','t','\\',
50 'W','i','n','d','o','w','s','\\',
51 'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
52 'T','h','e','m','e','M','a','n','a','g','e','r','\0'
53 };
54 static const WCHAR szThemeActive[] = {'T','h','e','m','e','A','c','t','i','v','e','\0'};
55 static const WCHAR szSizeName[] = {'S','i','z','e','N','a','m','e','\0'};
56 static const WCHAR szColorName[] = {'C','o','l','o','r','N','a','m','e','\0'};
57 static const WCHAR szDllName[] = {'D','l','l','N','a','m','e','\0'};
58
59 static const WCHAR szIniDocumentation[] = {'d','o','c','u','m','e','n','t','a','t','i','o','n','\0'};
60
61 HINSTANCE hDllInst;
62 ATOM atDialogThemeEnabled;
63
64 static DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
65 ATOM atWindowTheme;
66 static ATOM atSubAppName;
67 static ATOM atSubIdList;
68 ATOM atWndContrext;
69
70 static BOOL bThemeActive = FALSE;
71 static WCHAR szCurrentTheme[MAX_PATH];
72 static WCHAR szCurrentColor[64];
73 static WCHAR szCurrentSize[64];
74
75 /***********************************************************************/
76
77 static BOOL CALLBACK UXTHEME_broadcast_msg_enumchild (HWND hWnd, LPARAM msg)
78 {
79 PostMessageW(hWnd, msg, 0, 0);
80 return TRUE;
81 }
82
83 /* Broadcast a message to *all* windows, including children */
84 BOOL CALLBACK UXTHEME_broadcast_msg (HWND hWnd, LPARAM msg)
85 {
86 if (hWnd == NULL)
87 {
88 EnumWindows (UXTHEME_broadcast_msg, msg);
89 }
90 else
91 {
92 PostMessageW(hWnd, msg, 0, 0);
93 EnumChildWindows (hWnd, UXTHEME_broadcast_msg_enumchild, msg);
94 }
95 return TRUE;
96 }
97
98 /* At the end of the day this is a subset of what SHRegGetPath() does - copied
99 * here to avoid linking against shlwapi. */
100 static DWORD query_reg_path (HKEY hKey, LPCWSTR lpszValue,
101 LPVOID pvData)
102 {
103 DWORD dwRet, dwType, dwUnExpDataLen = MAX_PATH, dwExpDataLen;
104
105 TRACE("(hkey=%p,%s,%p)\n", hKey, debugstr_w(lpszValue),
106 pvData);
107
108 dwRet = RegQueryValueExW(hKey, lpszValue, 0, &dwType, pvData, &dwUnExpDataLen);
109 if (dwRet!=ERROR_SUCCESS && dwRet!=ERROR_MORE_DATA)
110 return dwRet;
111
112 if (dwType == REG_EXPAND_SZ)
113 {
114 DWORD nBytesToAlloc;
115
116 /* Expand type REG_EXPAND_SZ into REG_SZ */
117 LPWSTR szData;
118
119 /* If the caller didn't supply a buffer or the buffer is too small we have
120 * to allocate our own
121 */
122 if (dwRet == ERROR_MORE_DATA)
123 {
124 WCHAR cNull = '\0';
125 nBytesToAlloc = dwUnExpDataLen;
126
127 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc);
128 RegQueryValueExW (hKey, lpszValue, 0, NULL, (LPBYTE)szData, &nBytesToAlloc);
129 dwExpDataLen = ExpandEnvironmentStringsW(szData, &cNull, 1);
130 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
131 LocalFree(szData);
132 }
133 else
134 {
135 nBytesToAlloc = (lstrlenW(pvData) + 1) * sizeof(WCHAR);
136 szData = LocalAlloc(LMEM_ZEROINIT, nBytesToAlloc );
137 lstrcpyW(szData, pvData);
138 dwExpDataLen = ExpandEnvironmentStringsW(szData, pvData, MAX_PATH );
139 if (dwExpDataLen > MAX_PATH) dwRet = ERROR_MORE_DATA;
140 dwUnExpDataLen = max(nBytesToAlloc, dwExpDataLen);
141 LocalFree(szData);
142 }
143 }
144
145 return dwRet;
146 }
147
148 /***********************************************************************
149 * UXTHEME_LoadTheme
150 *
151 * Set the current active theme from the registry
152 */
153 void UXTHEME_LoadTheme(BOOL bLoad)
154 {
155 HKEY hKey;
156 DWORD buffsize;
157 HRESULT hr;
158 WCHAR tmp[10];
159 PTHEME_FILE pt;
160
161 if(bLoad == TRUE)
162 {
163 /* Get current theme configuration */
164 if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
165 TRACE("Loading theme config\n");
166 buffsize = sizeof(tmp)/sizeof(tmp[0]);
167 if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
168 bThemeActive = (tmp[0] != '0');
169 }
170 else {
171 bThemeActive = FALSE;
172 TRACE("Failed to get ThemeActive: %d\n", GetLastError());
173 }
174 buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
175 if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
176 szCurrentColor[0] = '\0';
177 buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
178 if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
179 szCurrentSize[0] = '\0';
180 if (query_reg_path (hKey, szDllName, szCurrentTheme))
181 szCurrentTheme[0] = '\0';
182 RegCloseKey(hKey);
183 }
184 else
185 TRACE("Failed to open theme registry key\n");
186 }
187 else
188 {
189 bThemeActive = FALSE;
190 }
191
192 if(bThemeActive) {
193 /* Make sure the theme requested is actually valid */
194 hr = MSSTYLES_OpenThemeFile(szCurrentTheme,
195 szCurrentColor[0]?szCurrentColor:NULL,
196 szCurrentSize[0]?szCurrentSize:NULL,
197 &pt);
198 if(FAILED(hr)) {
199 bThemeActive = FALSE;
200 szCurrentTheme[0] = '\0';
201 szCurrentColor[0] = '\0';
202 szCurrentSize[0] = '\0';
203 }
204 else {
205 /* Make sure the global color & size match the theme */
206 lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
207 lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
208
209 MSSTYLES_SetActiveTheme(pt, FALSE);
210 TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
211 debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
212 MSSTYLES_CloseThemeFile(pt);
213 }
214 }
215 if(!bThemeActive) {
216 MSSTYLES_SetActiveTheme(NULL, FALSE);
217 TRACE("Theming not active\n");
218 }
219 }
220
221 /***********************************************************************/
222
223 static const char * const SysColorsNames[] =
224 {
225 "Scrollbar", /* COLOR_SCROLLBAR */
226 "Background", /* COLOR_BACKGROUND */
227 "ActiveTitle", /* COLOR_ACTIVECAPTION */
228 "InactiveTitle", /* COLOR_INACTIVECAPTION */
229 "Menu", /* COLOR_MENU */
230 "Window", /* COLOR_WINDOW */
231 "WindowFrame", /* COLOR_WINDOWFRAME */
232 "MenuText", /* COLOR_MENUTEXT */
233 "WindowText", /* COLOR_WINDOWTEXT */
234 "TitleText", /* COLOR_CAPTIONTEXT */
235 "ActiveBorder", /* COLOR_ACTIVEBORDER */
236 "InactiveBorder", /* COLOR_INACTIVEBORDER */
237 "AppWorkSpace", /* COLOR_APPWORKSPACE */
238 "Hilight", /* COLOR_HIGHLIGHT */
239 "HilightText", /* COLOR_HIGHLIGHTTEXT */
240 "ButtonFace", /* COLOR_BTNFACE */
241 "ButtonShadow", /* COLOR_BTNSHADOW */
242 "GrayText", /* COLOR_GRAYTEXT */
243 "ButtonText", /* COLOR_BTNTEXT */
244 "InactiveTitleText", /* COLOR_INACTIVECAPTIONTEXT */
245 "ButtonHilight", /* COLOR_BTNHIGHLIGHT */
246 "ButtonDkShadow", /* COLOR_3DDKSHADOW */
247 "ButtonLight", /* COLOR_3DLIGHT */
248 "InfoText", /* COLOR_INFOTEXT */
249 "InfoWindow", /* COLOR_INFOBK */
250 "ButtonAlternateFace", /* COLOR_ALTERNATEBTNFACE */
251 "HotTrackingColor", /* COLOR_HOTLIGHT */
252 "GradientActiveTitle", /* COLOR_GRADIENTACTIVECAPTION */
253 "GradientInactiveTitle", /* COLOR_GRADIENTINACTIVECAPTION */
254 "MenuHilight", /* COLOR_MENUHILIGHT */
255 "MenuBar", /* COLOR_MENUBAR */
256 };
257 static const WCHAR strColorKey[] =
258 { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
259 'C','o','l','o','r','s',0 };
260 static const WCHAR keyFlatMenus[] = { 'F','l','a','t','M','e','n','u', 0};
261 static const WCHAR keyGradientCaption[] = { 'G','r','a','d','i','e','n','t',
262 'C','a','p','t','i','o','n', 0 };
263 static const WCHAR keyNonClientMetrics[] = { 'N','o','n','C','l','i','e','n','t',
264 'M','e','t','r','i','c','s',0 };
265 static const WCHAR keyIconTitleFont[] = { 'I','c','o','n','T','i','t','l','e',
266 'F','o','n','t',0 };
267
268 static const struct BackupSysParam
269 {
270 int spiGet, spiSet;
271 const WCHAR* keyName;
272 } backupSysParams[] =
273 {
274 {SPI_GETFLATMENU, SPI_SETFLATMENU, keyFlatMenus},
275 {SPI_GETGRADIENTCAPTIONS, SPI_SETGRADIENTCAPTIONS, keyGradientCaption},
276 {-1, -1, 0}
277 };
278
279 #define NUM_SYS_COLORS (COLOR_MENUBAR+1)
280
281 static void save_sys_colors (HKEY baseKey)
282 {
283 char colorStr[13];
284 HKEY hKey;
285 int i;
286
287 if (RegCreateKeyExW( baseKey, strColorKey,
288 0, 0, 0, KEY_ALL_ACCESS,
289 0, &hKey, 0 ) == ERROR_SUCCESS)
290 {
291 for (i = 0; i < NUM_SYS_COLORS; i++)
292 {
293 COLORREF col = GetSysColor (i);
294
295 sprintf (colorStr, "%d %d %d",
296 GetRValue (col), GetGValue (col), GetBValue (col));
297
298 RegSetValueExA (hKey, SysColorsNames[i], 0, REG_SZ,
299 (BYTE*)colorStr, strlen (colorStr)+1);
300 }
301 RegCloseKey (hKey);
302 }
303 }
304
305 /* Before activating a theme, query current system colors, certain settings
306 * and backup them in the registry, so they can be restored when the theme
307 * is deactivated */
308 static void UXTHEME_BackupSystemMetrics(void)
309 {
310 HKEY hKey;
311 const struct BackupSysParam* bsp = backupSysParams;
312
313 if (RegCreateKeyExW( HKEY_CURRENT_USER, szThemeManager,
314 0, 0, 0, KEY_ALL_ACCESS,
315 0, &hKey, 0) == ERROR_SUCCESS)
316 {
317 NONCLIENTMETRICSW ncm;
318 LOGFONTW iconTitleFont;
319
320 /* back up colors */
321 save_sys_colors (hKey);
322
323 /* back up "other" settings */
324 while (bsp->spiGet >= 0)
325 {
326 DWORD value;
327
328 SystemParametersInfoW (bsp->spiGet, 0, &value, 0);
329 RegSetValueExW (hKey, bsp->keyName, 0, REG_DWORD,
330 (LPBYTE)&value, sizeof (value));
331
332 bsp++;
333 }
334
335 /* back up non-client metrics */
336 memset (&ncm, 0, sizeof (ncm));
337 ncm.cbSize = sizeof (ncm);
338 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof (ncm), &ncm, 0);
339 RegSetValueExW (hKey, keyNonClientMetrics, 0, REG_BINARY, (LPBYTE)&ncm,
340 sizeof (ncm));
341 memset (&iconTitleFont, 0, sizeof (iconTitleFont));
342 SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof (iconTitleFont),
343 &iconTitleFont, 0);
344 RegSetValueExW (hKey, keyIconTitleFont, 0, REG_BINARY,
345 (LPBYTE)&iconTitleFont, sizeof (iconTitleFont));
346
347 RegCloseKey (hKey);
348 }
349 }
350
351 /* Read back old settings after a theme was deactivated */
352 static void UXTHEME_RestoreSystemMetrics(void)
353 {
354 HKEY hKey;
355 const struct BackupSysParam* bsp = backupSysParams;
356
357 if (RegOpenKeyExW (HKEY_CURRENT_USER, szThemeManager,
358 0, KEY_QUERY_VALUE, &hKey) == ERROR_SUCCESS)
359 {
360 HKEY colorKey;
361
362 /* read backed-up colors */
363 if (RegOpenKeyExW (hKey, strColorKey,
364 0, KEY_QUERY_VALUE, &colorKey) == ERROR_SUCCESS)
365 {
366 int i;
367 COLORREF sysCols[NUM_SYS_COLORS];
368 int sysColsIndices[NUM_SYS_COLORS];
369 int sysColCount = 0;
370
371 for (i = 0; i < NUM_SYS_COLORS; i++)
372 {
373 DWORD type;
374 char colorStr[13];
375 DWORD count = sizeof(colorStr);
376
377 if (RegQueryValueExA (colorKey, SysColorsNames[i], 0,
378 &type, (LPBYTE) colorStr, &count) == ERROR_SUCCESS)
379 {
380 int r, g, b;
381 if (sscanf (colorStr, "%d %d %d", &r, &g, &b) == 3)
382 {
383 sysColsIndices[sysColCount] = i;
384 sysCols[sysColCount] = RGB(r, g, b);
385 sysColCount++;
386 }
387 }
388 }
389 RegCloseKey (colorKey);
390
391 SetSysColors (sysColCount, sysColsIndices, sysCols);
392 }
393
394 /* read backed-up other settings */
395 while (bsp->spiGet >= 0)
396 {
397 DWORD value;
398 DWORD count = sizeof(value);
399 DWORD type;
400
401 if (RegQueryValueExW (hKey, bsp->keyName, 0,
402 &type, (LPBYTE)&value, &count) == ERROR_SUCCESS)
403 {
404 SystemParametersInfoW (bsp->spiSet, 0, UlongToPtr(value), SPIF_UPDATEINIFILE);
405 }
406
407 bsp++;
408 }
409
410 /* read backed-up non-client metrics */
411 {
412 NONCLIENTMETRICSW ncm;
413 LOGFONTW iconTitleFont;
414 DWORD count = sizeof(ncm);
415 DWORD type;
416
417 if (RegQueryValueExW (hKey, keyNonClientMetrics, 0,
418 &type, (LPBYTE)&ncm, &count) == ERROR_SUCCESS)
419 {
420 SystemParametersInfoW (SPI_SETNONCLIENTMETRICS,
421 count, &ncm, SPIF_UPDATEINIFILE);
422 }
423
424 count = sizeof(iconTitleFont);
425
426 if (RegQueryValueExW (hKey, keyIconTitleFont, 0,
427 &type, (LPBYTE)&iconTitleFont, &count) == ERROR_SUCCESS)
428 {
429 SystemParametersInfoW (SPI_SETICONTITLELOGFONT,
430 count, &iconTitleFont, SPIF_UPDATEINIFILE);
431 }
432 }
433
434 RegCloseKey (hKey);
435 }
436 }
437
438 /* Make system settings persistent, so they're in effect even w/o uxtheme
439 * loaded.
440 * For efficiency reasons, only the last SystemParametersInfoW sets
441 * SPIF_SENDWININICHANGE */
442 static void UXTHEME_SaveSystemMetrics(void)
443 {
444 const struct BackupSysParam* bsp = backupSysParams;
445 NONCLIENTMETRICSW ncm;
446 LOGFONTW iconTitleFont;
447
448 save_sys_colors (HKEY_CURRENT_USER);
449
450 while (bsp->spiGet >= 0)
451 {
452 DWORD value;
453
454 SystemParametersInfoW (bsp->spiGet, 0, &value, 0);
455 SystemParametersInfoW (bsp->spiSet, 0, UlongToPtr(value), SPIF_UPDATEINIFILE);
456 bsp++;
457 }
458
459 memset (&ncm, 0, sizeof (ncm));
460 ncm.cbSize = sizeof (ncm);
461 SystemParametersInfoW (SPI_GETNONCLIENTMETRICS, sizeof (ncm), &ncm, 0);
462 SystemParametersInfoW (SPI_SETNONCLIENTMETRICS, sizeof (ncm), &ncm,
463 SPIF_UPDATEINIFILE);
464
465 memset (&iconTitleFont, 0, sizeof (iconTitleFont));
466 SystemParametersInfoW (SPI_GETICONTITLELOGFONT, sizeof (iconTitleFont),
467 &iconTitleFont, 0);
468 SystemParametersInfoW (SPI_SETICONTITLELOGFONT, sizeof (iconTitleFont),
469 &iconTitleFont, SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
470 }
471
472 /***********************************************************************
473 * UXTHEME_SetActiveTheme
474 *
475 * Change the current active theme
476 */
477 static HRESULT UXTHEME_SetActiveTheme(PTHEME_FILE tf)
478 {
479 HKEY hKey;
480 WCHAR tmp[2];
481 HRESULT hr;
482
483 if(tf && !bThemeActive) UXTHEME_BackupSystemMetrics();
484 hr = MSSTYLES_SetActiveTheme(tf, TRUE);
485 if(FAILED(hr))
486 return hr;
487 if(tf) {
488 bThemeActive = TRUE;
489 lstrcpynW(szCurrentTheme, tf->szThemeFile, sizeof(szCurrentTheme)/sizeof(szCurrentTheme[0]));
490 lstrcpynW(szCurrentColor, tf->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
491 lstrcpynW(szCurrentSize, tf->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
492 }
493 else {
494 UXTHEME_RestoreSystemMetrics();
495 bThemeActive = FALSE;
496 szCurrentTheme[0] = '\0';
497 szCurrentColor[0] = '\0';
498 szCurrentSize[0] = '\0';
499 }
500
501 TRACE("Writing theme config to registry\n");
502 if(!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
503 tmp[0] = bThemeActive?'1':'0';
504 tmp[1] = '\0';
505 RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2);
506 if(bThemeActive) {
507 RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)szCurrentColor,
508 (lstrlenW(szCurrentColor)+1)*sizeof(WCHAR));
509 RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)szCurrentSize,
510 (lstrlenW(szCurrentSize)+1)*sizeof(WCHAR));
511 RegSetValueExW(hKey, szDllName, 0, REG_SZ, (const BYTE*)szCurrentTheme,
512 (lstrlenW(szCurrentTheme)+1)*sizeof(WCHAR));
513 }
514 else {
515 RegDeleteValueW(hKey, szColorName);
516 RegDeleteValueW(hKey, szSizeName);
517 RegDeleteValueW(hKey, szDllName);
518
519 }
520 RegCloseKey(hKey);
521 }
522 else
523 TRACE("Failed to open theme registry key\n");
524
525 UXTHEME_SaveSystemMetrics ();
526
527 return hr;
528 }
529
530 /***********************************************************************
531 * UXTHEME_InitSystem
532 */
533 void UXTHEME_InitSystem(HINSTANCE hInst)
534 {
535 static const WCHAR szWindowTheme[] = {
536 'u','x','_','t','h','e','m','e','\0'
537 };
538 static const WCHAR szSubAppName[] = {
539 'u','x','_','s','u','b','a','p','p','\0'
540 };
541 static const WCHAR szSubIdList[] = {
542 'u','x','_','s','u','b','i','d','l','s','t','\0'
543 };
544 static const WCHAR szDialogThemeEnabled[] = {
545 'u','x','_','d','i','a','l','o','g','t','h','e','m','e','\0'
546 };
547
548 hDllInst = hInst;
549
550 atWindowTheme = GlobalAddAtomW(szWindowTheme);
551 atSubAppName = GlobalAddAtomW(szSubAppName);
552 atSubIdList = GlobalAddAtomW(szSubIdList);
553 atDialogThemeEnabled = GlobalAddAtomW(szDialogThemeEnabled);
554 atWndContrext = GlobalAddAtomW(L"ux_WndContext");
555 }
556
557 /***********************************************************************
558 * IsAppThemed (UXTHEME.@)
559 */
560 BOOL WINAPI IsAppThemed(void)
561 {
562 return IsThemeActive();
563 }
564
565 /***********************************************************************
566 * IsThemeActive (UXTHEME.@)
567 */
568 BOOL WINAPI IsThemeActive(void)
569 {
570 TRACE("\n");
571 SetLastError(ERROR_SUCCESS);
572 return bThemeActive;
573 }
574
575 /***********************************************************************
576 * EnableTheming (UXTHEME.@)
577 *
578 * NOTES
579 * This is a global and persistent change
580 */
581 HRESULT WINAPI EnableTheming(BOOL fEnable)
582 {
583 HKEY hKey;
584 WCHAR szEnabled[] = {'0','\0'};
585
586 TRACE("(%d)\n", fEnable);
587
588 if(fEnable != bThemeActive) {
589 if(fEnable)
590 UXTHEME_BackupSystemMetrics();
591 else
592 UXTHEME_RestoreSystemMetrics();
593 UXTHEME_SaveSystemMetrics ();
594 bThemeActive = fEnable;
595 if(bThemeActive) szEnabled[0] = '1';
596 if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
597 RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
598 RegCloseKey(hKey);
599 }
600 UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
601 }
602 return S_OK;
603 }
604
605 /***********************************************************************
606 * UXTHEME_SetWindowProperty
607 *
608 * I'm using atoms as there may be large numbers of duplicated strings
609 * and they do the work of keeping memory down as a cause of that quite nicely
610 */
611 static HRESULT UXTHEME_SetWindowProperty(HWND hwnd, ATOM aProp, LPCWSTR pszValue)
612 {
613 ATOM oldValue = (ATOM)(size_t)RemovePropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp));
614 if(oldValue)
615 DeleteAtom(oldValue);
616 if(pszValue) {
617 ATOM atValue = AddAtomW(pszValue);
618 if(!atValue
619 || !SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp), (LPWSTR)MAKEINTATOM(atValue))) {
620 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
621 if(atValue) DeleteAtom(atValue);
622 return hr;
623 }
624 }
625 return S_OK;
626 }
627
628 static LPWSTR UXTHEME_GetWindowProperty(HWND hwnd, ATOM aProp, LPWSTR pszBuffer, int dwLen)
629 {
630 ATOM atValue = (ATOM)(size_t)GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(aProp));
631 if(atValue) {
632 if(GetAtomNameW(atValue, pszBuffer, dwLen))
633 return pszBuffer;
634 TRACE("property defined, but unable to get value\n");
635 }
636 return NULL;
637 }
638
639 /***********************************************************************
640 * OpenThemeData (UXTHEME.@)
641 */
642 HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
643 {
644 WCHAR szAppBuff[256];
645 WCHAR szClassBuff[256];
646 LPCWSTR pszAppName;
647 LPCWSTR pszUseClassList;
648 HTHEME hTheme = NULL;
649 TRACE("(%p,%s)\n", hwnd, debugstr_w(pszClassList));
650
651 if(bThemeActive)
652 {
653 pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0]));
654 /* If SetWindowTheme was used on the window, that overrides the class list passed to this function */
655 pszUseClassList = UXTHEME_GetWindowProperty(hwnd, atSubIdList, szClassBuff, sizeof(szClassBuff)/sizeof(szClassBuff[0]));
656 if(!pszUseClassList)
657 pszUseClassList = pszClassList;
658
659 if (pszUseClassList)
660 hTheme = MSSTYLES_OpenThemeClass(pszAppName, pszUseClassList);
661 }
662 if(IsWindow(hwnd))
663 SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), hTheme);
664 TRACE(" = %p\n", hTheme);
665 return hTheme;
666 }
667
668 /***********************************************************************
669 * GetWindowTheme (UXTHEME.@)
670 *
671 * Retrieve the last theme opened for a window.
672 *
673 * PARAMS
674 * hwnd [I] window to retrieve the theme for
675 *
676 * RETURNS
677 * The most recent theme.
678 */
679 HTHEME WINAPI GetWindowTheme(HWND hwnd)
680 {
681 TRACE("(%p)\n", hwnd);
682 return GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme));
683 }
684
685 /***********************************************************************
686 * SetWindowTheme (UXTHEME.@)
687 *
688 * Persistent through the life of the window, even after themes change
689 */
690 HRESULT WINAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName,
691 LPCWSTR pszSubIdList)
692 {
693 HRESULT hr;
694 TRACE("(%p,%s,%s)\n", hwnd, debugstr_w(pszSubAppName),
695 debugstr_w(pszSubIdList));
696 hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName);
697 if(SUCCEEDED(hr))
698 hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
699 if(SUCCEEDED(hr))
700 UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
701 return hr;
702 }
703
704 /***********************************************************************
705 * GetCurrentThemeName (UXTHEME.@)
706 */
707 HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
708 LPWSTR pszColorBuff, int cchMaxColorChars,
709 LPWSTR pszSizeBuff, int cchMaxSizeChars)
710 {
711 if(!bThemeActive)
712 return E_PROP_ID_UNSUPPORTED;
713 if(pszThemeFileName) lstrcpynW(pszThemeFileName, szCurrentTheme, dwMaxNameChars);
714 if(pszColorBuff) lstrcpynW(pszColorBuff, szCurrentColor, cchMaxColorChars);
715 if(pszSizeBuff) lstrcpynW(pszSizeBuff, szCurrentSize, cchMaxSizeChars);
716 return S_OK;
717 }
718
719 /***********************************************************************
720 * GetThemeAppProperties (UXTHEME.@)
721 */
722 DWORD WINAPI GetThemeAppProperties(void)
723 {
724 return dwThemeAppProperties;
725 }
726
727 /***********************************************************************
728 * SetThemeAppProperties (UXTHEME.@)
729 */
730 void WINAPI SetThemeAppProperties(DWORD dwFlags)
731 {
732 TRACE("(0x%08x)\n", dwFlags);
733 dwThemeAppProperties = dwFlags;
734 }
735
736 /***********************************************************************
737 * CloseThemeData (UXTHEME.@)
738 */
739 HRESULT WINAPI CloseThemeData(HTHEME hTheme)
740 {
741 TRACE("(%p)\n", hTheme);
742 if(!hTheme)
743 return E_HANDLE;
744 return MSSTYLES_CloseThemeClass(hTheme);
745 }
746
747 /***********************************************************************
748 * HitTestThemeBackground (UXTHEME.@)
749 */
750 HRESULT WINAPI HitTestThemeBackground(HTHEME hTheme, HDC hdc, int iPartId,
751 int iStateId, DWORD dwOptions,
752 const RECT *pRect, HRGN hrgn,
753 POINT ptTest, WORD *pwHitTestCode)
754 {
755 FIXME("%d %d 0x%08x: stub\n", iPartId, iStateId, dwOptions);
756 if(!hTheme)
757 return E_HANDLE;
758 return ERROR_CALL_NOT_IMPLEMENTED;
759 }
760
761 /***********************************************************************
762 * IsThemePartDefined (UXTHEME.@)
763 */
764 BOOL WINAPI IsThemePartDefined(HTHEME hTheme, int iPartId, int iStateId)
765 {
766 TRACE("(%p,%d,%d)\n", hTheme, iPartId, iStateId);
767 if(!hTheme) {
768 SetLastError(E_HANDLE);
769 return FALSE;
770 }
771 if(MSSTYLES_FindPartState(hTheme, iPartId, iStateId, NULL))
772 return TRUE;
773 return FALSE;
774 }
775
776 /***********************************************************************
777 * GetThemeDocumentationProperty (UXTHEME.@)
778 *
779 * Try and retrieve the documentation property from string resources
780 * if that fails, get it from the [documentation] section of themes.ini
781 */
782 HRESULT WINAPI GetThemeDocumentationProperty(LPCWSTR pszThemeName,
783 LPCWSTR pszPropertyName,
784 LPWSTR pszValueBuff,
785 int cchMaxValChars)
786 {
787 const WORD wDocToRes[] = {
788 TMT_DISPLAYNAME,5000,
789 TMT_TOOLTIP,5001,
790 TMT_COMPANY,5002,
791 TMT_AUTHOR,5003,
792 TMT_COPYRIGHT,5004,
793 TMT_URL,5005,
794 TMT_VERSION,5006,
795 TMT_DESCRIPTION,5007
796 };
797
798 PTHEME_FILE pt;
799 HRESULT hr;
800 unsigned int i;
801 int iDocId;
802 TRACE("(%s,%s,%p,%d)\n", debugstr_w(pszThemeName), debugstr_w(pszPropertyName),
803 pszValueBuff, cchMaxValChars);
804
805 hr = MSSTYLES_OpenThemeFile(pszThemeName, NULL, NULL, &pt);
806 if(FAILED(hr)) return hr;
807
808 /* Try to load from string resources */
809 hr = E_PROP_ID_UNSUPPORTED;
810 if(MSSTYLES_LookupProperty(pszPropertyName, NULL, &iDocId)) {
811 for(i=0; i<sizeof(wDocToRes)/sizeof(wDocToRes[0]); i+=2) {
812 if(wDocToRes[i] == iDocId) {
813 if(LoadStringW(pt->hTheme, wDocToRes[i+1], pszValueBuff, cchMaxValChars)) {
814 hr = S_OK;
815 break;
816 }
817 }
818 }
819 }
820 /* If loading from string resource failed, try getting it from the theme.ini */
821 if(FAILED(hr)) {
822 PUXINI_FILE uf = MSSTYLES_GetThemeIni(pt);
823 if(UXINI_FindSection(uf, szIniDocumentation)) {
824 LPCWSTR lpValue;
825 DWORD dwLen;
826 if(UXINI_FindValue(uf, pszPropertyName, &lpValue, &dwLen)) {
827 lstrcpynW(pszValueBuff, lpValue, min(dwLen+1,cchMaxValChars));
828 hr = S_OK;
829 }
830 }
831 UXINI_CloseINI(uf);
832 }
833
834 MSSTYLES_CloseThemeFile(pt);
835 return hr;
836 }
837
838 /**********************************************************************
839 * Undocumented functions
840 */
841
842 /**********************************************************************
843 * QueryThemeServices (UXTHEME.1)
844 *
845 * RETURNS
846 * some kind of status flag
847 */
848 DWORD WINAPI QueryThemeServices(void)
849 {
850 FIXME("stub\n");
851 return 3; /* This is what is returned under XP in most cases */
852 }
853
854
855 /**********************************************************************
856 * OpenThemeFile (UXTHEME.2)
857 *
858 * Opens a theme file, which can be used to change the current theme, etc
859 *
860 * PARAMS
861 * pszThemeFileName Path to a msstyles theme file
862 * pszColorName Color defined in the theme, eg. NormalColor
863 * pszSizeName Size defined in the theme, eg. NormalSize
864 * hThemeFile Handle to theme file
865 *
866 * RETURNS
867 * Success: S_OK
868 * Failure: HRESULT error-code
869 */
870 HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
871 LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile,
872 DWORD unknown)
873 {
874 TRACE("(%s,%s,%s,%p,%d)\n", debugstr_w(pszThemeFileName),
875 debugstr_w(pszColorName), debugstr_w(pszSizeName),
876 hThemeFile, unknown);
877 return MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, (PTHEME_FILE*)hThemeFile);
878 }
879
880 /**********************************************************************
881 * CloseThemeFile (UXTHEME.3)
882 *
883 * Releases theme file handle returned by OpenThemeFile
884 *
885 * PARAMS
886 * hThemeFile Handle to theme file
887 *
888 * RETURNS
889 * Success: S_OK
890 * Failure: HRESULT error-code
891 */
892 HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile)
893 {
894 TRACE("(%p)\n", hThemeFile);
895 MSSTYLES_CloseThemeFile(hThemeFile);
896 return S_OK;
897 }
898
899 /**********************************************************************
900 * ApplyTheme (UXTHEME.4)
901 *
902 * Set a theme file to be the currently active theme
903 *
904 * PARAMS
905 * hThemeFile Handle to theme file
906 * unknown See notes
907 * hWnd Window requesting the theme change
908 *
909 * RETURNS
910 * Success: S_OK
911 * Failure: HRESULT error-code
912 *
913 * NOTES
914 * I'm not sure what the second parameter is (the datatype is likely wrong), other then this:
915 * Under XP if I pass
916 * char b[] = "";
917 * the theme is applied with the screen redrawing really badly (flickers)
918 * char b[] = "\0"; where \0 can be one or more of any character, makes no difference
919 * the theme is applied smoothly (screen does not flicker)
920 * char *b = "\0" or NULL; where \0 can be zero or more of any character, makes no difference
921 * the function fails returning invalid parameter... very strange
922 */
923 HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd)
924 {
925 HRESULT hr;
926 TRACE("(%p,%s,%p)\n", hThemeFile, unknown, hWnd);
927 hr = UXTHEME_SetActiveTheme(hThemeFile);
928 UXTHEME_broadcast_msg (NULL, WM_THEMECHANGED);
929 return hr;
930 }
931
932 /**********************************************************************
933 * GetThemeDefaults (UXTHEME.7)
934 *
935 * Get the default color & size for a theme
936 *
937 * PARAMS
938 * pszThemeFileName Path to a msstyles theme file
939 * pszColorName Buffer to receive the default color name
940 * dwColorNameLen Length, in characters, of color name buffer
941 * pszSizeName Buffer to receive the default size name
942 * dwSizeNameLen Length, in characters, of size name buffer
943 *
944 * RETURNS
945 * Success: S_OK
946 * Failure: HRESULT error-code
947 */
948 HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
949 DWORD dwColorNameLen, LPWSTR pszSizeName,
950 DWORD dwSizeNameLen)
951 {
952 PTHEME_FILE pt;
953 HRESULT hr;
954 TRACE("(%s,%p,%d,%p,%d)\n", debugstr_w(pszThemeFileName),
955 pszColorName, dwColorNameLen,
956 pszSizeName, dwSizeNameLen);
957
958 hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, NULL, &pt);
959 if(FAILED(hr)) return hr;
960
961 lstrcpynW(pszColorName, pt->pszSelectedColor, dwColorNameLen);
962 lstrcpynW(pszSizeName, pt->pszSelectedSize, dwSizeNameLen);
963
964 MSSTYLES_CloseThemeFile(pt);
965 return S_OK;
966 }
967
968 /**********************************************************************
969 * EnumThemes (UXTHEME.8)
970 *
971 * Enumerate available themes, calls specified EnumThemeProc for each
972 * theme found. Passes lpData through to callback function.
973 *
974 * PARAMS
975 * pszThemePath Path containing themes
976 * callback Called for each theme found in path
977 * lpData Passed through to callback
978 *
979 * RETURNS
980 * Success: S_OK
981 * Failure: HRESULT error-code
982 */
983 HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
984 LPVOID lpData)
985 {
986 WCHAR szDir[MAX_PATH];
987 WCHAR szPath[MAX_PATH];
988 static const WCHAR szStar[] = {'*','.','*','\0'};
989 static const WCHAR szFormat[] = {'%','s','%','s','\\','%','s','.','m','s','s','t','y','l','e','s','\0'};
990 static const WCHAR szDisplayName[] = {'d','i','s','p','l','a','y','n','a','m','e','\0'};
991 static const WCHAR szTooltip[] = {'t','o','o','l','t','i','p','\0'};
992 WCHAR szName[60];
993 WCHAR szTip[60];
994 HANDLE hFind;
995 WIN32_FIND_DATAW wfd;
996 HRESULT hr;
997 size_t pathLen;
998
999 TRACE("(%s,%p,%p)\n", debugstr_w(pszThemePath), callback, lpData);
1000
1001 if(!pszThemePath || !callback)
1002 return E_POINTER;
1003
1004 lstrcpyW(szDir, pszThemePath);
1005 pathLen = lstrlenW (szDir);
1006 if ((pathLen > 0) && (pathLen < MAX_PATH-1) && (szDir[pathLen - 1] != '\\'))
1007 {
1008 szDir[pathLen] = '\\';
1009 szDir[pathLen+1] = 0;
1010 }
1011
1012 lstrcpyW(szPath, szDir);
1013 lstrcatW(szPath, szStar);
1014 TRACE("searching %s\n", debugstr_w(szPath));
1015
1016 hFind = FindFirstFileW(szPath, &wfd);
1017 if(hFind != INVALID_HANDLE_VALUE) {
1018 do {
1019 if(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
1020 && !(wfd.cFileName[0] == '.' && ((wfd.cFileName[1] == '.' && wfd.cFileName[2] == 0) || wfd.cFileName[1] == 0))) {
1021 wsprintfW(szPath, szFormat, szDir, wfd.cFileName, wfd.cFileName);
1022
1023 hr = GetThemeDocumentationProperty(szPath, szDisplayName, szName, sizeof(szName)/sizeof(szName[0]));
1024 if(SUCCEEDED(hr))
1025 hr = GetThemeDocumentationProperty(szPath, szTooltip, szTip, sizeof(szTip)/sizeof(szTip[0]));
1026 if(SUCCEEDED(hr)) {
1027 TRACE("callback(%s,%s,%s,%p)\n", debugstr_w(szPath), debugstr_w(szName), debugstr_w(szTip), lpData);
1028 if(!callback(NULL, szPath, szName, szTip, NULL, lpData)) {
1029 TRACE("callback ended enum\n");
1030 break;
1031 }
1032 }
1033 }
1034 } while(FindNextFileW(hFind, &wfd));
1035 FindClose(hFind);
1036 }
1037 return S_OK;
1038 }
1039
1040
1041 /**********************************************************************
1042 * EnumThemeColors (UXTHEME.9)
1043 *
1044 * Enumerate theme colors available with a particular size
1045 *
1046 * PARAMS
1047 * pszThemeFileName Path to a msstyles theme file
1048 * pszSizeName Theme size to enumerate available colors
1049 * If NULL the default theme size is used
1050 * dwColorNum Color index to retrieve, increment from 0
1051 * pszColorNames Output color names
1052 *
1053 * RETURNS
1054 * S_OK on success
1055 * E_PROP_ID_UNSUPPORTED when dwColorName does not refer to a color
1056 * or when pszSizeName does not refer to a valid size
1057 *
1058 * NOTES
1059 * XP fails with E_POINTER when pszColorNames points to a buffer smaller than
1060 * sizeof(THEMENAMES).
1061 *
1062 * Not very efficient that I'm opening & validating the theme every call, but
1063 * this is undocumented and almost never called..
1064 * (and this is how windows works too)
1065 */
1066 HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
1067 DWORD dwColorNum, PTHEMENAMES pszColorNames)
1068 {
1069 PTHEME_FILE pt;
1070 HRESULT hr;
1071 LPWSTR tmp;
1072 UINT resourceId = dwColorNum + 1000;
1073 TRACE("(%s,%s,%d)\n", debugstr_w(pszThemeFileName),
1074 debugstr_w(pszSizeName), dwColorNum);
1075
1076 hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, pszSizeName, &pt);
1077 if(FAILED(hr)) return hr;
1078
1079 tmp = pt->pszAvailColors;
1080 while(dwColorNum && *tmp) {
1081 dwColorNum--;
1082 tmp += lstrlenW(tmp)+1;
1083 }
1084 if(!dwColorNum && *tmp) {
1085 TRACE("%s\n", debugstr_w(tmp));
1086 lstrcpyW(pszColorNames->szName, tmp);
1087 LoadStringW (pt->hTheme, resourceId,
1088 pszColorNames->szDisplayName,
1089 sizeof (pszColorNames->szDisplayName) / sizeof (WCHAR));
1090 LoadStringW (pt->hTheme, resourceId+1000,
1091 pszColorNames->szTooltip,
1092 sizeof (pszColorNames->szTooltip) / sizeof (WCHAR));
1093 }
1094 else
1095 hr = E_PROP_ID_UNSUPPORTED;
1096
1097 MSSTYLES_CloseThemeFile(pt);
1098 return hr;
1099 }
1100
1101 /**********************************************************************
1102 * EnumThemeSizes (UXTHEME.10)
1103 *
1104 * Enumerate theme colors available with a particular size
1105 *
1106 * PARAMS
1107 * pszThemeFileName Path to a msstyles theme file
1108 * pszColorName Theme color to enumerate available sizes
1109 * If NULL the default theme color is used
1110 * dwSizeNum Size index to retrieve, increment from 0
1111 * pszSizeNames Output size names
1112 *
1113 * RETURNS
1114 * S_OK on success
1115 * E_PROP_ID_UNSUPPORTED when dwSizeName does not refer to a size
1116 * or when pszColorName does not refer to a valid color
1117 *
1118 * NOTES
1119 * XP fails with E_POINTER when pszSizeNames points to a buffer smaller than
1120 * sizeof(THEMENAMES).
1121 *
1122 * Not very efficient that I'm opening & validating the theme every call, but
1123 * this is undocumented and almost never called..
1124 * (and this is how windows works too)
1125 */
1126 HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
1127 DWORD dwSizeNum, PTHEMENAMES pszSizeNames)
1128 {
1129 PTHEME_FILE pt;
1130 HRESULT hr;
1131 LPWSTR tmp;
1132 UINT resourceId = dwSizeNum + 3000;
1133 TRACE("(%s,%s,%d)\n", debugstr_w(pszThemeFileName),
1134 debugstr_w(pszColorName), dwSizeNum);
1135
1136 hr = MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, NULL, &pt);
1137 if(FAILED(hr)) return hr;
1138
1139 tmp = pt->pszAvailSizes;
1140 while(dwSizeNum && *tmp) {
1141 dwSizeNum--;
1142 tmp += lstrlenW(tmp)+1;
1143 }
1144 if(!dwSizeNum && *tmp) {
1145 TRACE("%s\n", debugstr_w(tmp));
1146 lstrcpyW(pszSizeNames->szName, tmp);
1147 LoadStringW (pt->hTheme, resourceId,
1148 pszSizeNames->szDisplayName,
1149 sizeof (pszSizeNames->szDisplayName) / sizeof (WCHAR));
1150 LoadStringW (pt->hTheme, resourceId+1000,
1151 pszSizeNames->szTooltip,
1152 sizeof (pszSizeNames->szTooltip) / sizeof (WCHAR));
1153 }
1154 else
1155 hr = E_PROP_ID_UNSUPPORTED;
1156
1157 MSSTYLES_CloseThemeFile(pt);
1158 return hr;
1159 }
1160
1161 /**********************************************************************
1162 * ParseThemeIniFile (UXTHEME.11)
1163 *
1164 * Enumerate data in a theme INI file.
1165 *
1166 * PARAMS
1167 * pszIniFileName Path to a theme ini file
1168 * pszUnknown Cannot be NULL, L"" is valid
1169 * callback Called for each found entry
1170 * lpData Passed through to callback
1171 *
1172 * RETURNS
1173 * S_OK on success
1174 * 0x800706488 (Unknown property) when enumeration is canceled from callback
1175 *
1176 * NOTES
1177 * When pszUnknown is NULL the callback is never called, the value does not seem to serve
1178 * any other purpose
1179 */
1180 HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
1181 ParseThemeIniFileProc callback, LPVOID lpData)
1182 {
1183 FIXME("%s %s: stub\n", debugstr_w(pszIniFileName), debugstr_w(pszUnknown));
1184 return ERROR_CALL_NOT_IMPLEMENTED;
1185 }
1186
1187 /**********************************************************************
1188 * CheckThemeSignature (UXTHEME.29)
1189 *
1190 * Validates the signature of a theme file
1191 *
1192 * PARAMS
1193 * pszIniFileName Path to a theme file
1194 *
1195 * RETURNS
1196 * Success: S_OK
1197 * Failure: HRESULT error-code
1198 */
1199 HRESULT WINAPI CheckThemeSignature(LPCWSTR pszThemeFileName)
1200 {
1201 PTHEME_FILE pt;
1202 HRESULT hr;
1203 TRACE("(%s)\n", debugstr_w(pszThemeFileName));
1204 hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, NULL, &pt);
1205 if(FAILED(hr))
1206 return hr;
1207 MSSTYLES_CloseThemeFile(pt);
1208 return S_OK;
1209 }