urlmon: Implement HlinkSimpleNavigateToMoniker.
[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
89     /* This test is not themed */
90     SetLastError(0xdeadbeef);
91     bAppThemed = pIsAppThemed();
92
93     if (bThemeActive)
94         todo_wine
95             ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
96     else
97         /* Although Wine currently returns FALSE, the logic behind it is wrong. It is not a todo_wine though in the testing sense */
98         ok( bAppThemed == FALSE, "Expected FALSE as this test executable is not (yet) themed.\n");
99
100     ok( GetLastError() == ERROR_SUCCESS,
101         "Expected ERROR_SUCCESS, got 0x%08x\n",
102         GetLastError());
103
104     SetLastError(0xdeadbeef);
105     bTPDefined = pIsThemePartDefined(NULL, 0 , 0);
106     ok( bTPDefined == FALSE, "Expected FALSE\n");
107     ok( GetLastError() == E_HANDLE,
108         "Expected E_HANDLE, got 0x%08x\n",
109         GetLastError());
110 }
111
112 static void test_GetWindowTheme(void)
113 {
114     HTHEME    hTheme;
115     HWND      hWnd;
116     BOOL    bDestroyed;
117
118     SetLastError(0xdeadbeef);
119     hTheme = pGetWindowTheme(NULL);
120     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
121     todo_wine
122         ok( GetLastError() == E_HANDLE,
123             "Expected E_HANDLE, got 0x%08x\n",
124             GetLastError());
125
126     /* Only do the bare minimum to get a valid hwnd */
127     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
128     if (!hWnd) return;
129
130     SetLastError(0xdeadbeef);
131     hTheme = pGetWindowTheme(hWnd);
132     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
133     ok( GetLastError() == 0xdeadbeef,
134         "Expected 0xdeadbeef, got 0x%08x\n",
135         GetLastError());
136
137     bDestroyed = DestroyWindow(hWnd);
138     if (!bDestroyed)
139         trace("Window %p couldn't be destroyed : 0x%08x\n",
140             hWnd, GetLastError());
141 }
142
143 static void test_SetWindowTheme(void)
144 {
145     HRESULT hRes;
146     HWND    hWnd;
147     BOOL    bDestroyed;
148
149     SetLastError(0xdeadbeef);
150     hRes = pSetWindowTheme(NULL, NULL, NULL);
151     todo_wine
152     {
153         ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
154         ok( GetLastError() == 0xdeadbeef,
155             "Expected 0xdeadbeef, got 0x%08x\n",
156             GetLastError());
157     }
158
159     /* Only do the bare minimum to get a valid hwnd */
160     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
161     if (!hWnd) return;
162
163     SetLastError(0xdeadbeef);
164     hRes = pSetWindowTheme(hWnd, NULL, NULL);
165     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
166     ok( GetLastError() == 0xdeadbeef,
167         "Expected 0xdeadbeef, got 0x%08x\n",
168         GetLastError());
169
170     bDestroyed = DestroyWindow(hWnd);
171     if (!bDestroyed)
172         trace("Window %p couldn't be destroyed : 0x%08x\n",
173             hWnd, GetLastError());
174 }
175
176 static void test_OpenThemeData(void)
177 {
178     HTHEME    hTheme, hTheme2;
179     HWND      hWnd;
180     BOOL      bThemeActive;
181     HRESULT   hRes;
182     BOOL      bDestroyed;
183     BOOL      bTPDefined;
184
185     WCHAR szInvalidClassList[] = {'D','E','A','D','B','E','E','F', 0 };
186     WCHAR szButtonClassList[]  = {'B','u','t','t','o','n', 0 };
187     WCHAR szButtonClassList2[]  = {'b','U','t','T','o','N', 0 };
188     WCHAR szClassList[]        = {'B','u','t','t','o','n',';','L','i','s','t','B','o','x', 0 };
189
190     bThemeActive = pIsThemeActive();
191
192     /* All NULL */
193     SetLastError(0xdeadbeef);
194     hTheme = pOpenThemeData(NULL, NULL);
195     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
196     todo_wine
197         ok( GetLastError() == E_POINTER,
198             "Expected GLE() to be E_POINTER, got 0x%08x\n",
199             GetLastError());
200
201     /* A NULL hWnd and an invalid classlist */
202     SetLastError(0xdeadbeef);
203     hTheme = pOpenThemeData(NULL, szInvalidClassList);
204     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
205     todo_wine
206         ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
207             "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
208             GetLastError());
209
210     SetLastError(0xdeadbeef);
211     hTheme = pOpenThemeData(NULL, szClassList);
212     if (bThemeActive)
213     {
214         ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
215         todo_wine
216             ok( GetLastError() == ERROR_SUCCESS,
217                 "Expected ERROR_SUCCESS, got 0x%08x\n",
218                 GetLastError());
219     }
220     else
221     {
222         ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
223         todo_wine
224             ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
225                 "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
226                 GetLastError());
227     }
228
229     /* Only do the bare minimum to get a valid hdc */
230     hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
231     if (!hWnd) return;
232
233     SetLastError(0xdeadbeef);
234     hTheme = pOpenThemeData(hWnd, NULL);
235     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
236     todo_wine
237         ok( GetLastError() == E_POINTER,
238             "Expected GLE() to be E_POINTER, got 0x%08x\n",
239             GetLastError());
240
241     SetLastError(0xdeadbeef);
242     hTheme = pOpenThemeData(hWnd, szInvalidClassList);
243     ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
244     todo_wine
245         ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
246             "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
247             GetLastError());
248
249     if (!bThemeActive)
250     {
251         SetLastError(0xdeadbeef);
252         hTheme = pOpenThemeData(hWnd, szButtonClassList);
253         ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
254         todo_wine
255             ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
256                 "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
257                 GetLastError());
258         skip("No active theme, skipping rest of OpenThemeData tests\n");
259         return;
260     }
261
262     /* Only do the next checks if we have an active theme */
263
264     SetLastError(0xdeadbeef);
265     hTheme = pOpenThemeData(hWnd, szButtonClassList);
266     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
267     todo_wine
268         ok( GetLastError() == ERROR_SUCCESS,
269             "Expected ERROR_SUCCESS, got 0x%08x\n",
270             GetLastError());
271
272     /* Test with bUtToN instead of Button */
273     SetLastError(0xdeadbeef);
274     hTheme = pOpenThemeData(hWnd, szButtonClassList2);
275     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
276     todo_wine
277         ok( GetLastError() == ERROR_SUCCESS,
278             "Expected ERROR_SUCCESS, got 0x%08x\n",
279             GetLastError());
280
281     SetLastError(0xdeadbeef);
282     hTheme = pOpenThemeData(hWnd, szClassList);
283     ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
284     todo_wine
285         ok( GetLastError() == ERROR_SUCCESS,
286             "Expected ERROR_SUCCESS, got 0x%08x\n",
287             GetLastError());
288
289     /* GetWindowTheme should return the last handle opened by OpenThemeData */
290     SetLastError(0xdeadbeef);
291     hTheme2 = pGetWindowTheme(hWnd);
292     ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
293         hTheme, hTheme2);
294     ok( GetLastError() == 0xdeadbeef,
295         "Expected 0xdeadbeef, got 0x%08x\n",
296         GetLastError());
297
298     SetLastError(0xdeadbeef);
299     hRes = pCloseThemeData(hTheme);
300     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
301     ok( GetLastError() == 0xdeadbeef,
302         "Expected 0xdeadbeef, got 0x%08x\n",
303         GetLastError());
304
305     /* Close a second time */
306     SetLastError(0xdeadbeef);
307     hRes = pCloseThemeData(hTheme);
308     ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
309     ok( GetLastError() == 0xdeadbeef,
310         "Expected 0xdeadbeef, got 0x%08x\n",
311         GetLastError());
312
313     /* See if closing makes a difference for GetWindowTheme */
314     SetLastError(0xdeadbeef);
315     hTheme2 = NULL;
316     hTheme2 = pGetWindowTheme(hWnd);
317     ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
318         hTheme, hTheme2);
319     ok( GetLastError() == 0xdeadbeef,
320         "Expected 0xdeadbeef, got 0x%08x\n",
321         GetLastError());
322
323     SetLastError(0xdeadbeef);
324     bTPDefined = pIsThemePartDefined(hTheme, 0 , 0);
325     todo_wine
326     {
327         ok( bTPDefined == FALSE, "Expected FALSE\n");
328         ok( GetLastError() == ERROR_SUCCESS,
329             "Expected ERROR_SUCCESS, got 0x%08x\n",
330             GetLastError());
331     }
332
333     bDestroyed = DestroyWindow(hWnd);
334     if (!bDestroyed)
335         trace("Window %p couldn't be destroyed : 0x%08x\n",
336             hWnd, GetLastError());
337 }
338
339 static void test_GetCurrentThemeName(void)
340 {
341     BOOL    bThemeActive;
342     HRESULT hRes;
343     WCHAR currentTheme[MAX_PATH];
344     WCHAR currentColor[MAX_PATH];
345     WCHAR currentSize[MAX_PATH];
346
347     bThemeActive = pIsThemeActive();
348
349     /* All NULLs */
350     SetLastError(0xdeadbeef);
351     hRes = pGetCurrentThemeName(NULL, 0, NULL, 0, NULL, 0);
352     if (bThemeActive)
353         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
354     else
355         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
356     ok( GetLastError() == 0xdeadbeef,
357         "Expected 0xdeadbeef, got 0x%08x\n",
358         GetLastError());
359
360     /* Number of characters given is 0 */
361     SetLastError(0xdeadbeef);
362     hRes = pGetCurrentThemeName(currentTheme, 0, NULL, 0, NULL, 0);
363     if (bThemeActive)
364         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
365     else
366         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
367     ok( GetLastError() == 0xdeadbeef,
368         "Expected 0xdeadbeef, got 0x%08x\n",
369         GetLastError());
370
371     /* When the number of characters given is too small (not 0, see above), GetCurrentThemeName returns 0x8007007a.
372      * The only definition I found was in strsafe.h:
373      *
374      * #define STRSAFE_E_INSUFFICIENT_BUFFER       ((HRESULT)0x8007007AL)  // 0x7A = 122L = ERROR_INSUFFICIENT_BUFFER
375      */
376     SetLastError(0xdeadbeef);
377     hRes = pGetCurrentThemeName(currentTheme, 2, NULL, 0, NULL, 0);
378     if (bThemeActive)
379         todo_wine
380             ok(hRes == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "Expected HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), got 0x%08x\n", hRes);
381     else
382         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
383     ok( GetLastError() == 0xdeadbeef,
384         "Expected 0xdeadbeef, got 0x%08x\n",
385         GetLastError());
386
387     /* The same is true if the number of characters is too small for Color and/or Size */
388     SetLastError(0xdeadbeef);
389     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
390                                 currentColor, 2,
391                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
392     if (bThemeActive)
393         todo_wine
394             ok(hRes == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "Expected HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), got 0x%08x\n", hRes);
395     else
396         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
397     ok( GetLastError() == 0xdeadbeef,
398         "Expected 0xdeadbeef, got 0x%08x\n",
399         GetLastError());
400
401     /* Given number of characters is correct */
402     SetLastError(0xdeadbeef);
403     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), NULL, 0, NULL, 0);
404     if (bThemeActive)
405         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
406     else
407         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
408     ok( GetLastError() == 0xdeadbeef,
409         "Expected 0xdeadbeef, got 0x%08x\n",
410         GetLastError());
411
412     /* Given number of characters for the theme name is too large */
413     SetLastError(0xdeadbeef);
414     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0);
415     if (bThemeActive)
416         ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes);
417     else
418         ok( hRes == E_PROP_ID_UNSUPPORTED ||
419             hRes == E_POINTER, /* win2k3 */
420             "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
421     ok( GetLastError() == 0xdeadbeef,
422         "Expected 0xdeadbeef, got 0x%08x\n",
423         GetLastError());
424  
425     /* The too large case is only for the theme name, not for color name or size name */
426     SetLastError(0xdeadbeef);
427     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
428                                 currentColor, sizeof(currentTheme),
429                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
430     if (bThemeActive)
431         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
432     else
433         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
434     ok( GetLastError() == 0xdeadbeef,
435         "Expected 0xdeadbeef, got 0x%08x\n",
436         GetLastError());
437
438     SetLastError(0xdeadbeef);
439     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
440                                 currentColor, sizeof(currentTheme) / sizeof(WCHAR),
441                                 currentSize,  sizeof(currentSize));
442     if (bThemeActive)
443         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
444     else
445         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
446     ok( GetLastError() == 0xdeadbeef,
447         "Expected 0xdeadbeef, got 0x%08x\n",
448         GetLastError());
449
450     /* Correct call */
451     SetLastError(0xdeadbeef);
452     hRes = pGetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), 
453                                 currentColor, sizeof(currentColor) / sizeof(WCHAR),
454                                 currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
455     if (bThemeActive)
456         ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
457     else
458         ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
459     ok( GetLastError() == 0xdeadbeef,
460         "Expected 0xdeadbeef, got 0x%08x\n",
461         GetLastError());
462 }
463
464 static void test_CloseThemeData(void)
465 {
466     HRESULT hRes;
467
468     SetLastError(0xdeadbeef);
469     hRes = pCloseThemeData(NULL);
470     ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
471     ok( GetLastError() == 0xdeadbeef,
472         "Expected 0xdeadbeef, got 0x%08x\n",
473         GetLastError());
474 }
475
476 START_TEST(system)
477 {
478     if(!InitFunctionPtrs())
479         return;
480
481     /* No real functional tests will be done (yet). The current tests
482      * only show input/return behaviour
483      */
484
485     /* IsThemeActive, IsAppThemed and IsThemePartDefined*/
486     trace("Starting test_IsThemed()\n");
487     test_IsThemed();
488
489     /* GetWindowTheme */
490     trace("Starting test_GetWindowTheme()\n");
491     test_GetWindowTheme();
492
493     /* SetWindowTheme */
494     trace("Starting test_SetWindowTheme()\n");
495     test_SetWindowTheme();
496
497     /* OpenThemeData, a bit more functional now */
498     trace("Starting test_OpenThemeData()\n");
499     test_OpenThemeData();
500
501     /* GetCurrentThemeName */
502     trace("Starting test_GetCurrentThemeName()\n");
503     test_GetCurrentThemeName();
504
505     /* CloseThemeData */
506     trace("Starting test_CloseThemeData()\n");
507     test_CloseThemeData();
508
509     FreeLibrary(hUxtheme);
510 }