uxtheme: Fix the system tests so they pass on Vista.
[wine] / dlls / uxtheme / tests / system.c
1 /* Unit test suite for uxtheme API functions
2  *
3  * Copyright 2006 Paul Vriens
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  *
19  */
20
21 #include <stdarg.h>
22
23 #include "windows.h"
24 #include "vfwmsgs.h"
25 #include "uxtheme.h"
26
27 #include "wine/test.h"
28
29 static HRESULT (WINAPI * pCloseThemeData)(HTHEME);
30 static HRESULT (WINAPI * pGetCurrentThemeName)(LPWSTR, int, LPWSTR, int, LPWSTR, int);
31 static HTHEME  (WINAPI * pGetWindowTheme)(HWND);
32 static BOOL    (WINAPI * pIsAppThemed)(VOID);
33 static BOOL    (WINAPI * pIsThemeActive)(VOID);
34 static BOOL    (WINAPI * pIsThemePartDefined)(HTHEME, int, int);
35 static HTHEME  (WINAPI * pOpenThemeData)(HWND, LPCWSTR);
36 static HRESULT (WINAPI * pSetWindowTheme)(HWND, LPCWSTR, LPCWSTR);
37
38 static HMODULE hUxtheme = 0;
39
40 #define UXTHEME_GET_PROC(func) \
41     p ## func = (void*)GetProcAddress(hUxtheme, #func); \
42     if(!p ## func) { \
43       trace("GetProcAddress(%s) failed\n", #func); \
44       FreeLibrary(hUxtheme); \
45       return FALSE; \
46     }
47
48 static BOOL InitFunctionPtrs(void)
49 {
50     hUxtheme = LoadLibraryA("uxtheme.dll");
51     if(!hUxtheme) {
52       trace("Could not load uxtheme.dll\n");
53       return FALSE;
54     }
55     if (hUxtheme)
56     {
57       UXTHEME_GET_PROC(CloseThemeData)
58       UXTHEME_GET_PROC(GetCurrentThemeName)
59       UXTHEME_GET_PROC(GetWindowTheme)
60       UXTHEME_GET_PROC(IsAppThemed)
61       UXTHEME_GET_PROC(IsThemeActive)
62       UXTHEME_GET_PROC(IsThemePartDefined)
63       UXTHEME_GET_PROC(OpenThemeData)
64       UXTHEME_GET_PROC(SetWindowTheme)
65     }
66     /* The following functions should be available, if not return FALSE. The Vista functions will
67      * be checked (at some point in time) within the single tests if needed. All used functions for
68      * now are present on WinXP, W2K3 and Wine.
69      */
70     if (!pCloseThemeData || !pGetCurrentThemeName ||
71         !pGetWindowTheme || !pIsAppThemed ||
72         !pIsThemeActive || !pIsThemePartDefined ||
73         !pOpenThemeData || !pSetWindowTheme)
74         return FALSE;
75
76     return TRUE;
77 }
78
79 static void test_IsThemed(void)
80 {
81     BOOL bThemeActive;
82     BOOL bAppThemed;
83     BOOL bTPDefined;
84
85     SetLastError(0xdeadbeef);
86     bThemeActive = pIsThemeActive();
87     trace("Theming is %s\n", (bThemeActive) ? "active" : "inactive");
88     todo_wine
89         ok( GetLastError() == ERROR_SUCCESS,
90             "Expected ERROR_SUCCESS, got 0x%08x\n",
91             GetLastError());
92
93     /* This test is not themed */
94     SetLastError(0xdeadbeef);
95     bAppThemed = pIsAppThemed();
96
97     if (bThemeActive)
98         todo_wine
99             ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
100     else
101         /* Although Wine currently returns FALSE, the logic behind it is wrong. It is not a todo_wine though in the testing sense */
102         ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
103
104     todo_wine
105         ok( GetLastError() == ERROR_SUCCESS,
106             "Expected ERROR_SUCCESS, got 0x%08x\n",
107             GetLastError());
108
109     SetLastError(0xdeadbeef);
110     bTPDefined = pIsThemePartDefined(NULL, 0 , 0);
111     ok( bTPDefined == FALSE, "Expected FALSE\n");
112     ok( GetLastError() == E_HANDLE,
113         "Expected E_HANDLE, got 0x%08x\n",
114         GetLastError());
115 }
116
117 static void test_GetWindowTheme(void)
118 {
119     HTHEME    hTheme;
120     HWND      hWnd;
121     BOOL    bDestroyed;
122
123     SetLastError(0xdeadbeef);
124     hTheme = pGetWindowTheme(NULL);
125     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
126     todo_wine
127         ok( GetLastError() == E_HANDLE,
128             "Expected E_HANDLE, got 0x%08x\n",
129             GetLastError());
130
131     /* Only do the bare minimum to get a valid hwnd */
132     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
133     if (!hWnd) return;
134
135     SetLastError(0xdeadbeef);
136     hTheme = pGetWindowTheme(hWnd);
137     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
138     ok( GetLastError() == 0xdeadbeef,
139         "Expected 0xdeadbeef, got 0x%08x\n",
140         GetLastError());
141
142     bDestroyed = DestroyWindow(hWnd);
143     if (!bDestroyed)
144         trace("Window %p couldn't be destroyed : 0x%08x\n",
145             hWnd, GetLastError());
146 }
147
148 static void test_SetWindowTheme(void)
149 {
150     HRESULT hRes;
151     HWND    hWnd;
152     BOOL    bDestroyed;
153
154     SetLastError(0xdeadbeef);
155     hRes = pSetWindowTheme(NULL, NULL, NULL);
156     todo_wine
157     {
158         ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
159         ok( GetLastError() == 0xdeadbeef,
160             "Expected 0xdeadbeef, got 0x%08x\n",
161             GetLastError());
162     }
163
164     /* Only do the bare minimum to get a valid hwnd */
165     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
166     if (!hWnd) return;
167
168     SetLastError(0xdeadbeef);
169     hRes = pSetWindowTheme(hWnd, NULL, NULL);
170     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
171     ok( GetLastError() == 0xdeadbeef,
172         "Expected 0xdeadbeef, got 0x%08x\n",
173         GetLastError());
174
175     bDestroyed = DestroyWindow(hWnd);
176     if (!bDestroyed)
177         trace("Window %p couldn't be destroyed : 0x%08x\n",
178             hWnd, GetLastError());
179 }
180
181 static void test_OpenThemeData(void)
182 {
183     HTHEME    hTheme, hTheme2;
184     HWND      hWnd;
185     BOOL      bThemeActive;
186     HRESULT   hRes;
187     BOOL      bDestroyed;
188     BOOL      bTPDefined;
189
190     WCHAR szInvalidClassList[] = {'D','E','A','D','B','E','E','F', 0 };
191     WCHAR szButtonClassList[]  = {'B','u','t','t','o','n', 0 };
192     WCHAR szButtonClassList2[]  = {'b','U','t','T','o','N', 0 };
193     WCHAR szClassList[]        = {'B','u','t','t','o','n',';','L','i','s','t','B','o','x', 0 };
194
195     bThemeActive = pIsThemeActive();
196
197     /* All NULL */
198     SetLastError(0xdeadbeef);
199     hTheme = pOpenThemeData(NULL, NULL);
200     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
201     todo_wine
202         ok( GetLastError() == E_POINTER,
203             "Expected GLE() to be E_POINTER, got 0x%08x\n",
204             GetLastError());
205
206     /* A NULL hWnd and an invalid classlist */
207     SetLastError(0xdeadbeef);
208     hTheme = pOpenThemeData(NULL, szInvalidClassList);
209     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
210     todo_wine
211         ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
212             "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
213             GetLastError());
214
215     SetLastError(0xdeadbeef);
216     hTheme = pOpenThemeData(NULL, szClassList);
217     if (bThemeActive)
218     {
219         ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
220         todo_wine
221             ok( GetLastError() == ERROR_SUCCESS,
222                 "Expected ERROR_SUCCESS, got 0x%08x\n",
223                 GetLastError());
224     }
225     else
226     {
227         ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
228         todo_wine
229             ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
230                 "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
231                 GetLastError());
232     }
233
234     /* Only do the bare minimum to get a valid hdc */
235     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
236     if (!hWnd) return;
237
238     SetLastError(0xdeadbeef);
239     hTheme = pOpenThemeData(hWnd, NULL);
240     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
241     todo_wine
242         ok( GetLastError() == E_POINTER,
243             "Expected GLE() to be E_POINTER, got 0x%08x\n",
244             GetLastError());
245
246     SetLastError(0xdeadbeef);
247     hTheme = pOpenThemeData(hWnd, szInvalidClassList);
248     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
249     todo_wine
250         ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
251             "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
252             GetLastError());
253
254     if (!bThemeActive)
255     {
256         SetLastError(0xdeadbeef);
257         hTheme = pOpenThemeData(hWnd, szButtonClassList);
258         ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
259         todo_wine
260             ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
261                 "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
262                 GetLastError());
263         trace("No active theme, skipping rest of OpenThemeData tests\n");
264         return;
265     }
266
267     /* Only do the next checks if we have an active theme */
268
269     SetLastError(0xdeadbeef);
270     hTheme = pOpenThemeData(hWnd, szButtonClassList);
271     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
272     todo_wine
273         ok( GetLastError() == ERROR_SUCCESS,
274             "Expected ERROR_SUCCESS, got 0x%08x\n",
275             GetLastError());
276
277     /* Test with bUtToN instead of Button */
278     SetLastError(0xdeadbeef);
279     hTheme = pOpenThemeData(hWnd, szButtonClassList2);
280     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
281     todo_wine
282         ok( GetLastError() == ERROR_SUCCESS,
283             "Expected ERROR_SUCCESS, got 0x%08x\n",
284             GetLastError());
285
286     SetLastError(0xdeadbeef);
287     hTheme = pOpenThemeData(hWnd, szClassList);
288     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
289     todo_wine
290         ok( GetLastError() == ERROR_SUCCESS,
291             "Expected ERROR_SUCCESS, got 0x%08x\n",
292             GetLastError());
293
294     /* GetWindowTheme should return the last handle opened by OpenThemeData */
295     SetLastError(0xdeadbeef);
296     hTheme2 = pGetWindowTheme(hWnd);
297     ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
298         hTheme, hTheme2);
299     ok( GetLastError() == 0xdeadbeef,
300         "Expected 0xdeadbeef, got 0x%08x\n",
301         GetLastError());
302
303     SetLastError(0xdeadbeef);
304     hRes = pCloseThemeData(hTheme);
305     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
306     ok( GetLastError() == 0xdeadbeef,
307         "Expected 0xdeadbeef, got 0x%08x\n",
308         GetLastError());
309
310     /* Close a second time */
311     SetLastError(0xdeadbeef);
312     hRes = pCloseThemeData(hTheme);
313     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
314     ok( GetLastError() == 0xdeadbeef,
315         "Expected 0xdeadbeef, got 0x%08x\n",
316         GetLastError());
317
318     /* See if closing makes a difference for GetWindowTheme */
319     SetLastError(0xdeadbeef);
320     hTheme2 = NULL;
321     hTheme2 = pGetWindowTheme(hWnd);
322     ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
323         hTheme, hTheme2);
324     ok( GetLastError() == 0xdeadbeef,
325         "Expected 0xdeadbeef, got 0x%08x\n",
326         GetLastError());
327
328     SetLastError(0xdeadbeef);
329     bTPDefined = pIsThemePartDefined(hTheme, 0 , 0);
330     todo_wine
331     {
332         ok( bTPDefined == FALSE, "Expected FALSE\n");
333         ok( GetLastError() == ERROR_SUCCESS,
334             "Expected ERROR_SUCCESS, got 0x%08x\n",
335             GetLastError());
336     }
337
338     bDestroyed = DestroyWindow(hWnd);
339     if (!bDestroyed)
340         trace("Window %p couldn't be destroyed : 0x%08x\n",
341             hWnd, GetLastError());
342 }
343
344 static void test_GetCurrentThemeName(void)
345 {
346     BOOL    bThemeActive;
347     HRESULT hRes;
348     WCHAR currentTheme[MAX_PATH];
349     WCHAR currentColor[MAX_PATH];
350     WCHAR currentSize[MAX_PATH];
351
352     bThemeActive = pIsThemeActive();
353
354     /* All NULLs */
355     SetLastError(0xdeadbeef);
356     hRes = pGetCurrentThemeName(NULL, 0, NULL, 0, NULL, 0);
357     if (bThemeActive)
358         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
359     else
360         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
361     ok( GetLastError() == 0xdeadbeef,
362         "Expected 0xdeadbeef, got 0x%08x\n",
363         GetLastError());
364
365     /* Number of characters given is 0 */
366     SetLastError(0xdeadbeef);
367     hRes = pGetCurrentThemeName(currentTheme, 0, NULL, 0, NULL, 0);
368     if (bThemeActive)
369         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
370     else
371         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
372     ok( GetLastError() == 0xdeadbeef,
373         "Expected 0xdeadbeef, got 0x%08x\n",
374         GetLastError());
375
376     /* When the number of characters given is too small (not 0, see above), GetCurrentThemeName returns 0x8007007a.
377      * The only definition I found was in strsafe.h:
378      *
379      * #define STRSAFE_E_INSUFFICIENT_BUFFER       ((HRESULT)0x8007007AL)  // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
380      */
381     SetLastError(0xdeadbeef);
382     hRes = pGetCurrentThemeName(currentTheme, 2, NULL, 0, NULL, 0);
383     if (bThemeActive)
384         todo_wine
385             ok( LOWORD(hRes) == ERROR_INSUFFICIENT_BUFFER, "Expected 0x8007007A, got 0x%08x\n", hRes);
386     else
387         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
388     ok( GetLastError() == 0xdeadbeef,
389         "Expected 0xdeadbeef, got 0x%08x\n",
390         GetLastError());
391
392     /* The same is true if the number of characters is too small for Color and/or Size */
393     SetLastError(0xdeadbeef);
394     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
395                                 currentColor, 2,
396                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
397     if (bThemeActive)
398         todo_wine
399             ok( LOWORD(hRes) == ERROR_INSUFFICIENT_BUFFER, "Expected 0x8007007A, got 0x%08x\n", hRes);
400     else
401         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
402     ok( GetLastError() == 0xdeadbeef,
403         "Expected 0xdeadbeef, got 0x%08x\n",
404         GetLastError());
405
406     /* Given number of characters is correct */
407     SetLastError(0xdeadbeef);
408     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), NULL, 0, NULL, 0);
409     if (bThemeActive)
410         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
411     else
412         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
413     ok( GetLastError() == 0xdeadbeef,
414         "Expected 0xdeadbeef, got 0x%08x\n",
415         GetLastError());
416
417     /* Given number of characters for the theme name is too large */
418     SetLastError(0xdeadbeef);
419     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0);
420     if (bThemeActive)
421         ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes);
422     else
423         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
424     ok( GetLastError() == 0xdeadbeef,
425         "Expected 0xdeadbeef, got 0x%08x\n",
426         GetLastError());
427  
428     /* The too large case is only for the theme name, not for color name or size name */
429     SetLastError(0xdeadbeef);
430     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
431                                 currentColor, sizeof(currentTheme),
432                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
433     if (bThemeActive)
434         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
435     else
436         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
437     ok( GetLastError() == 0xdeadbeef,
438         "Expected 0xdeadbeef, got 0x%08x\n",
439         GetLastError());
440
441     SetLastError(0xdeadbeef);
442     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
443                                 currentColor, sizeof(currentTheme) / sizeof(WCHAR),
444                                 currentSize,  sizeof(currentSize));
445     if (bThemeActive)
446         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
447     else
448         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
449     ok( GetLastError() == 0xdeadbeef,
450         "Expected 0xdeadbeef, got 0x%08x\n",
451         GetLastError());
452
453     /* Correct call */
454     SetLastError(0xdeadbeef);
455     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
456                                 currentColor, sizeof(currentColor) / sizeof(WCHAR),
457                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
458     if (bThemeActive)
459         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
460     else
461         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
462     ok( GetLastError() == 0xdeadbeef,
463         "Expected 0xdeadbeef, got 0x%08x\n",
464         GetLastError());
465 }
466
467 static void test_CloseThemeData(void)
468 {
469     HRESULT hRes;
470
471     SetLastError(0xdeadbeef);
472     hRes = pCloseThemeData(NULL);
473     ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
474     ok( GetLastError() == 0xdeadbeef,
475         "Expected 0xdeadbeef, got 0x%08x\n",
476         GetLastError());
477 }
478
479 START_TEST(system)
480 {
481     if(!InitFunctionPtrs())
482         return;
483
484     /* No real functional tests will be done (yet). The current tests
485      * only show input/return behaviour
486      */
487
488     /* IsThemeActive, IsAppThemed and IsThemePartDefined*/
489     trace("Starting test_IsThemed()\n");
490     test_IsThemed();
491
492     /* GetWindowTheme */
493     trace("Starting test_GetWindowTheme()\n");
494     test_GetWindowTheme();
495
496     /* SetWindowTheme */
497     trace("Starting test_SetWindowTheme()\n");
498     test_SetWindowTheme();
499
500     /* OpenThemeData, a bit more functional now */
501     trace("Starting test_OpenThemeData()\n");
502     test_OpenThemeData();
503
504     /* GetCurrentThemeName */
505     trace("Starting test_GetCurrentThemeName()\n");
506     test_GetCurrentThemeName();
507
508     /* CloseThemeData */
509     trace("Starting test_CloseThemeData()\n");
510     test_CloseThemeData();
511
512     FreeLibrary(hUxtheme);
513 }