Implement CryptRegisterOIDFunction and CryptSIPAddProvider.
[wine] / dlls / 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "wingdi.h"
29 #include "winreg.h"
30 #include "shlwapi.h"
31 #include "uxtheme.h"
32
33 #include "uxthemedll.h"
34 #include "msstyles.h"
35
36 #include "wine/debug.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
39
40 /***********************************************************************
41  * Defines and global variables
42  */
43
44 static const WCHAR szThemeManager[] = {
45     'S','o','f','t','w','a','r','e','\\',
46     'M','i','c','r','o','s','o','f','t','\\',
47     'W','i','n','d','o','w','s','\\',
48     'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
49     'T','h','e','m','e','M','a','n','a','g','e','r','\0'
50 };
51 static const WCHAR szThemeActive[] = {'T','h','e','m','e','A','c','t','i','v','e','\0'};
52 static const WCHAR szSizeName[] = {'S','i','z','e','N','a','m','e','\0'};
53 static const WCHAR szColorName[] = {'C','o','l','o','r','N','a','m','e','\0'};
54 static const WCHAR szDllName[] = {'D','l','l','N','a','m','e','\0'};
55
56 DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
57 ATOM atWindowTheme;
58 ATOM atSubAppName;
59 ATOM atSubIdList;
60
61 BOOL bThemeActive = FALSE;
62 WCHAR szCurrentTheme[MAX_PATH];
63 WCHAR szCurrentColor[64];
64 WCHAR szCurrentSize[64];
65
66 /***********************************************************************/
67
68 /***********************************************************************
69  *      UXTHEME_InitSystem
70  */
71 void UXTHEME_InitSystem()
72 {
73     const WCHAR szWindowTheme[] = {
74         'u','x','_','t','h','e','m','e','\0'
75     };
76     const WCHAR szSubAppName[] = {
77         'u','x','_','s','u','b','a','p','p','\0'
78     };
79     const WCHAR szSubIdList[] = {
80         'u','x','_','s','u','b','i','d','l','s','t','\0'
81     };
82     HKEY hKey;
83     LONG buffsize;
84     HRESULT hr;
85     WCHAR tmp[10];
86     PTHEME_FILE pt;
87
88     atWindowTheme = GlobalAddAtomW(szWindowTheme);
89     atSubAppName  = GlobalAddAtomW(szSubAppName);
90     atSubIdList   = GlobalAddAtomW(szSubIdList);
91
92     /* Get current theme configuration */
93     if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
94         TRACE("Loading theme config\n");
95         buffsize = sizeof(tmp)/sizeof(tmp[0]);
96         if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
97             bThemeActive = (tmp[0] != '0');
98         }
99         else {
100             bThemeActive = FALSE;
101             TRACE("Failed to get ThemeActive: %ld\n", GetLastError());
102         }
103         buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
104         if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
105             szCurrentColor[0] = '\0';
106         buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
107         if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
108             szCurrentSize[0] = '\0';
109         if(SHRegGetPathW(hKey, NULL, szDllName, szCurrentTheme, 0))
110             szCurrentTheme[0] = '\0';
111         RegCloseKey(hKey);
112     }
113     else
114         TRACE("Failed to open theme registry key\n");
115
116     if(bThemeActive) {
117         /* Make sure the theme requested is actually valid */
118         hr = MSSTYLES_OpenThemeFile(szCurrentTheme,
119                                     szCurrentColor[0]?szCurrentColor:NULL,
120                                     szCurrentSize[0]?szCurrentSize:NULL,
121                                     &pt);
122         if(FAILED(hr)) {
123             bThemeActive = FALSE;
124             szCurrentTheme[0] = '\0';
125             szCurrentColor[0] = '\0';
126             szCurrentSize[0] = '\0';
127         }
128         else {
129             /* Make sure the global color & size match the theme */
130             lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
131             lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
132             MSSTYLES_CloseThemeFile(pt);
133         }
134     }
135
136     if(!bThemeActive)
137         TRACE("Themeing not active\n");
138     else
139         TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
140               debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
141 }
142
143 /***********************************************************************
144  *      IsAppThemed                                         (UXTHEME.@)
145  */
146 BOOL WINAPI IsAppThemed(void)
147 {
148     return IsThemeActive();
149 }
150
151 /***********************************************************************
152  *      IsThemeActive                                       (UXTHEME.@)
153  */
154 BOOL WINAPI IsThemeActive(void)
155 {
156     TRACE("\n");
157     return bThemeActive;
158 }
159
160 /***********************************************************************
161  *      EnableTheming                                       (UXTHEME.@)
162  *
163  * NOTES
164  * This is a global and persistant change
165  */
166 HRESULT WINAPI EnableTheming(BOOL fEnable)
167 {
168     HKEY hKey;
169     WCHAR szEnabled[] = {'0','\0'};
170
171     TRACE("(%d)\n", fEnable);
172
173     if(fEnable != bThemeActive) {
174         bThemeActive = fEnable;
175         if(bThemeActive) szEnabled[0] = '1';
176         if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
177             RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
178             RegCloseKey(hKey);
179         }
180         PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
181     }
182     return S_OK;
183  }
184
185 /***********************************************************************
186  *      OpenThemeData                                       (UXTHEME.@)
187  */
188 HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR pszClassList)
189 {
190     FIXME("%p %s: stub\n", hwnd, debugstr_w(pszClassList));
191     return NULL;
192 }
193
194 /***********************************************************************
195  *      GetWindowTheme                                      (UXTHEME.@)
196  *
197  * Retrieve the last theme opened for a window
198  */
199 HTHEME WINAPI GetWindowTheme(HWND hwnd)
200 {
201     TRACE("(%p)\n", hwnd);
202     return GetPropW(hwnd, MAKEINTATOMW(atWindowTheme));
203 }
204
205 /***********************************************************************
206  *      UXTHEME_SetWindowProperty
207  *
208  * I'm using atoms as there may be large numbers of duplicated strings
209  * and they do the work of keeping memory down as a cause of that quite nicely
210  */
211 HRESULT UXTHEME_SetWindowProperty(HWND hwnd, ATOM aProp, LPCWSTR pszValue)
212 {
213     ATOM oldValue = (ATOM)(size_t)RemovePropW(hwnd, MAKEINTATOMW(aProp));
214     if(oldValue)
215         DeleteAtom(oldValue);
216     if(pszValue) {
217         ATOM atValue = AddAtomW(pszValue);
218         if(!atValue
219            || !SetPropW(hwnd, MAKEINTATOMW(aProp), (LPWSTR)MAKEINTATOMW(atValue))) {
220             HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
221             if(atValue) DeleteAtom(atValue);
222             return hr;
223         }
224     }
225     return S_OK;
226 }
227
228 /***********************************************************************
229  *      SetWindowTheme                                      (UXTHEME.@)
230  *
231  * Persistant through the life of the window, even after themes change
232  */
233 HRESULT WINAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName,
234                               LPCWSTR pszSubIdList)
235 {
236     HRESULT hr;
237     TRACE("(%p,%s,%s)\n", hwnd, debugstr_w(pszSubAppName),
238           debugstr_w(pszSubIdList));
239     hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName);
240     if(SUCCEEDED(hr))
241         hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
242     if(SUCCEEDED(hr))
243         PostMessageW(hwnd, WM_THEMECHANGED, 0, 0);
244     return hr;
245 }
246
247 /***********************************************************************
248  *      GetCurrentThemeName                                 (UXTHEME.@)
249  */
250 HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
251                                    LPWSTR pszColorBuff, int cchMaxColorChars,
252                                    LPWSTR pszSizeBuff, int cchMaxSizeChars)
253 {
254     if(!bThemeActive)
255         return E_PROP_ID_UNSUPPORTED;
256     if(pszThemeFileName) lstrcpynW(pszThemeFileName, szCurrentTheme, dwMaxNameChars);
257     if(pszColorBuff) lstrcpynW(pszColorBuff, szCurrentColor, cchMaxColorChars);
258     if(pszSizeBuff) lstrcpynW(pszSizeBuff, szCurrentSize, cchMaxSizeChars);
259     return S_OK;
260 }
261
262 /***********************************************************************
263  *      GetThemeAppProperties                               (UXTHEME.@)
264  */
265 DWORD WINAPI GetThemeAppProperties(void)
266 {
267     return dwThemeAppProperties;
268 }
269
270 /***********************************************************************
271  *      SetThemeAppProperties                               (UXTHEME.@)
272  */
273 void WINAPI SetThemeAppProperties(DWORD dwFlags)
274 {
275     TRACE("(0x%08lx)\n", dwFlags);
276     dwThemeAppProperties = dwFlags;
277 }
278
279 /***********************************************************************
280  *      CloseThemeData                                      (UXTHEME.@)
281  */
282 HRESULT WINAPI CloseThemeData(HTHEME hTheme)
283 {
284     FIXME("stub\n");
285     if(!hTheme)
286         return E_HANDLE;
287     return S_OK;
288 }
289
290 /***********************************************************************
291  *      HitTestThemeBackground                              (UXTHEME.@)
292  */
293 HRESULT WINAPI HitTestThemeBackground(HTHEME hTheme, HDC hdc, int iPartId,
294                                      int iStateId, DWORD dwOptions,
295                                      const RECT *pRect, HRGN hrgn,
296                                      POINT ptTest, WORD *pwHitTestCode)
297 {
298     FIXME("%d %d 0x%08lx: stub\n", iPartId, iStateId, dwOptions);
299     if(!hTheme)
300         return E_HANDLE;
301     return ERROR_CALL_NOT_IMPLEMENTED;
302 }
303
304 /***********************************************************************
305  *      IsThemePartDefined                                  (UXTHEME.@)
306  */
307 BOOL WINAPI IsThemePartDefined(HTHEME hTheme, int iPartId, int iStateId)
308 {
309     FIXME("%d %d: stub\n", iPartId, iStateId);
310     return FALSE;
311 }
312
313 /**********************************************************************
314  *      Undocumented functions
315  */
316
317 /**********************************************************************
318  *      QueryThemeServices                                 (UXTHEME.1)
319  *
320  * RETURNS
321  *     some kind of status flag
322  */
323 DWORD WINAPI QueryThemeServices()
324 {
325     FIXME("stub\n");
326     return 3; /* This is what is returned under XP in most cases */
327 }
328
329
330 /**********************************************************************
331  *      OpenThemeFile                                      (UXTHEME.2)
332  *
333  * Opens a theme file, which can be used to change the current theme, etc
334  *
335  * PARAMS
336  *     pszThemeFileName    Path to a msstyles theme file
337  *     pszColorName        Color defined in the theme, eg. NormalColor
338  *     pszSizeName         Size defined in the theme, eg. NormalSize
339  *     hThemeFile          Handle to theme file
340  */
341 HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
342                              LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile,
343                              DWORD unknown)
344 {
345     TRACE("(%s,%s,%s,%p,%ld)\n", debugstr_w(pszThemeFileName),
346           debugstr_w(pszColorName), debugstr_w(pszSizeName),
347           hThemeFile, unknown);
348     return MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, (PTHEME_FILE*)hThemeFile);
349 }
350
351 /**********************************************************************
352  *      CloseThemeFile                                     (UXTHEME.3)
353  *
354  * Releases theme file handle returned by OpenThemeFile
355  *
356  * PARAMS
357  *     hThemeFile           Handle to theme file
358  */
359 HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile)
360 {
361     TRACE("(%p)\n", hThemeFile);
362     MSSTYLES_CloseThemeFile(hThemeFile);
363     return S_OK;
364 }
365
366 /**********************************************************************
367  *      ApplyTheme                                         (UXTHEME.4)
368  *
369  * Set a theme file to be the currently active theme
370  *
371  * PARAMS
372  *     hThemeFile           Handle to theme file
373  *     unknown              See notes
374  *     hWnd                 Window requesting the theme change
375  *
376  * NOTES
377  * I'm not sure what the second parameter is (the datatype is likely wrong), other then this:
378  * Under XP if I pass
379  * char b[] = "";
380  *   the theme is applied with the screen redrawing really badly (flickers)
381  * char b[] = "\0"; where \0 can be one or more of any character, makes no difference
382  *   the theme is applied smoothly (screen does not flicker)
383  * char *b = "\0" or NULL; where \0 can be zero or more of any character, makes no difference
384  *   the function fails returning invalid parameter...very strange
385  */
386 HRESULT WINAPI ApplyTheme(HTHEMEFILE hThemeFile, char *unknown, HWND hWnd)
387 {
388     FIXME("%s: stub\n", unknown);
389     return ERROR_CALL_NOT_IMPLEMENTED;
390 }
391
392 /**********************************************************************
393  *      GetThemeDefaults                                   (UXTHEME.7)
394  *
395  * Get the default color & size for a theme
396  *
397  * PARAMS
398  *     pszThemeFileName    Path to a msstyles theme file
399  *     pszColorName        Buffer to recieve the default color name
400  *     dwColorNameLen      Length, in characters, of color name buffer
401  *     pszSizeName         Buffer to recieve the default size name
402  *     dwSizeNameLen       Length, in characters, of size name buffer
403  */
404 HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
405                                 DWORD dwColorNameLen, LPWSTR pszSizeName,
406                                 DWORD dwSizeNameLen)
407 {
408     PTHEME_FILE pt;
409     HRESULT hr;
410     TRACE("(%s,%p,%ld,%p,%ld)\n", debugstr_w(pszThemeFileName),
411           pszColorName, dwColorNameLen,
412           pszSizeName, dwSizeNameLen);
413
414     hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, NULL, &pt);
415     if(FAILED(hr)) return hr;
416
417     lstrcpynW(pszColorName, pt->pszSelectedColor, dwColorNameLen);
418     lstrcpynW(pszSizeName, pt->pszSelectedSize, dwSizeNameLen);
419
420     MSSTYLES_CloseThemeFile(pt);
421     return S_OK;
422 }
423
424 /**********************************************************************
425  *      EnumThemes                                         (UXTHEME.8)
426  *
427  * Enumerate available themes, calls specified EnumThemeProc for each
428  * theme found. Passes lpData through to callback function.
429  *
430  * PARAMS
431  *     pszThemePath        Path containing themes
432  *     callback            Called for each theme found in path
433  *     lpData              Passed through to callback
434  */
435 HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
436                           LPVOID lpData)
437 {
438     FIXME("%s: stub\n", debugstr_w(pszThemePath));
439     return ERROR_CALL_NOT_IMPLEMENTED;
440 }
441
442
443 /**********************************************************************
444  *      EnumThemeColors                                    (UXTHEME.9)
445  *
446  * Enumerate theme colors available with a particular size
447  *
448  * PARAMS
449  *     pszThemeFileName    Path to a msstyles theme file
450  *     pszSizeName         Theme size to enumerate available colors
451  *                         If NULL the default theme size is used
452  *     dwColorNum          Color index to retrieve, increment from 0
453  *     pszColorName        Output color name
454  *
455  * RETURNS
456  *     S_OK on success
457  *     E_PROP_ID_UNSUPPORTED when dwColorName does not refer to a color
458  *          or when pszSizeName does not refer to a valid size
459  *
460  * NOTES
461  * XP fails with E_POINTER when pszColorName points to a buffer smaller then 605
462  * characters
463  *
464  * Not very efficient that I'm opening & validating the theme every call, but
465  * this is undocumented and almost never called..
466  * (and this is how windows works too)
467  */
468 HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
469                                DWORD dwColorNum, LPWSTR pszColorName)
470 {
471     PTHEME_FILE pt;
472     HRESULT hr;
473     LPWSTR tmp;
474     TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
475           debugstr_w(pszSizeName), dwColorNum);
476
477     hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, pszSizeName, &pt);
478     if(FAILED(hr)) return hr;
479
480     tmp = pt->pszAvailColors;
481     while(dwColorNum && *tmp) {
482         dwColorNum--;
483         tmp += lstrlenW(tmp)+1;
484     }
485     if(!dwColorNum && *tmp) {
486         TRACE("%s\n", debugstr_w(tmp));
487         lstrcpyW(pszColorName, tmp);
488     }
489     else
490         hr = E_PROP_ID_UNSUPPORTED;
491
492     MSSTYLES_CloseThemeFile(pt);
493     return hr;
494 }
495
496 /**********************************************************************
497  *      EnumThemeSizes                                     (UXTHEME.10)
498  *
499  * Enumerate theme colors available with a particular size
500  *
501  * PARAMS
502  *     pszThemeFileName    Path to a msstyles theme file
503  *     pszColorName        Theme color to enumerate available sizes
504  *                         If NULL the default theme color is used
505  *     dwSizeNum           Size index to retrieve, increment from 0
506  *     pszSizeName         Output size name
507  *
508  * RETURNS
509  *     S_OK on success
510  *     E_PROP_ID_UNSUPPORTED when dwSizeName does not refer to a size
511  *          or when pszColorName does not refer to a valid color
512  *
513  * NOTES
514  * XP fails with E_POINTER when pszSizeName points to a buffer smaller then 605
515  * characters
516  *
517  * Not very efficient that I'm opening & validating the theme every call, but
518  * this is undocumented and almost never called..
519  * (and this is how windows works too)
520  */
521 HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
522                               DWORD dwSizeNum, LPWSTR pszSizeName)
523 {
524     PTHEME_FILE pt;
525     HRESULT hr;
526     LPWSTR tmp;
527     TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
528           debugstr_w(pszColorName), dwSizeNum);
529
530     hr = MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, NULL, &pt);
531     if(FAILED(hr)) return hr;
532
533     tmp = pt->pszAvailSizes;
534     while(dwSizeNum && *tmp) {
535         dwSizeNum--;
536         tmp += lstrlenW(tmp)+1;
537     }
538     if(!dwSizeNum && *tmp) {
539         TRACE("%s\n", debugstr_w(tmp));
540         lstrcpyW(pszSizeName, tmp);
541     }
542     else
543         hr = E_PROP_ID_UNSUPPORTED;
544
545     MSSTYLES_CloseThemeFile(pt);
546     return hr;
547 }
548
549 /**********************************************************************
550  *      ParseThemeIniFile                                  (UXTHEME.11)
551  *
552  * Enumerate data in a theme INI file.
553  *
554  * PARAMS
555  *     pszIniFileName      Path to a theme ini file
556  *     pszUnknown          Cannot be NULL, L"" is valid
557  *     callback            Called for each found entry
558  *     lpData              Passed through to callback
559  *
560  * RETURNS
561  *     S_OK on success
562  *     0x800706488 (Unknown property) when enumeration is canceled from callback
563  *
564  * NOTES
565  * When pszUnknown is NULL the callback is never called, the value does not seem to surve
566  * any other purpose
567  */
568 HRESULT WINAPI ParseThemeIniFile(LPCWSTR pszIniFileName, LPWSTR pszUnknown,
569                                  ParseThemeIniFileProc callback, LPVOID lpData)
570 {
571     FIXME("%s %s: stub\n", debugstr_w(pszIniFileName), debugstr_w(pszUnknown));
572     return ERROR_CALL_NOT_IMPLEMENTED;
573 }