system.c 26.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/* Unit test suite for uxtheme API functions
 *
 * Copyright 2006 Paul Vriens
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 *
 */

#include <stdarg.h>

#include "windows.h"
24
#include "vfwmsgs.h"
25 26 27 28
#include "uxtheme.h"

#include "wine/test.h"

29
static HTHEME  (WINAPI * pOpenThemeDataEx)(HWND, LPCWSTR, DWORD);
30 31 32 33 34 35 36
static HPAINTBUFFER (WINAPI *pBeginBufferedPaint)(HDC, const RECT *, BP_BUFFERFORMAT, BP_PAINTPARAMS *, HDC *);
static HRESULT (WINAPI *pBufferedPaintClear)(HPAINTBUFFER, const RECT *);
static HRESULT (WINAPI *pEndBufferedPaint)(HPAINTBUFFER, BOOL);
static HRESULT (WINAPI *pGetBufferedPaintBits)(HPAINTBUFFER, RGBQUAD **, int *);
static HDC (WINAPI *pGetBufferedPaintDC)(HPAINTBUFFER);
static HDC (WINAPI *pGetBufferedPaintTargetDC)(HPAINTBUFFER);
static HRESULT (WINAPI *pGetBufferedPaintTargetRect)(HPAINTBUFFER, RECT *);
37

38
static void init_funcs(void)
39
{
40
    HMODULE hUxtheme = GetModuleHandleA("uxtheme.dll");
41 42 43 44 45 46 47 48 49 50 51 52 53

#define UXTHEME_GET_PROC(func) p ## func = (void*)GetProcAddress(hUxtheme, #func)
    UXTHEME_GET_PROC(BeginBufferedPaint);
    UXTHEME_GET_PROC(BufferedPaintClear);
    UXTHEME_GET_PROC(EndBufferedPaint);
    UXTHEME_GET_PROC(GetBufferedPaintBits);
    UXTHEME_GET_PROC(GetBufferedPaintDC);
    UXTHEME_GET_PROC(GetBufferedPaintTargetDC);
    UXTHEME_GET_PROC(GetBufferedPaintTargetRect);
    UXTHEME_GET_PROC(BufferedPaintClear);

    UXTHEME_GET_PROC(OpenThemeDataEx);
#undef UXTHEME_GET_PROC
54 55
}

56 57 58 59
static void test_IsThemed(void)
{
    BOOL bThemeActive;
    BOOL bAppThemed;
60
    BOOL bTPDefined;
61

62
    bThemeActive = IsThemeActive();
63 64
    trace("Theming is %s\n", (bThemeActive) ? "active" : "inactive");

65
    bAppThemed = IsAppThemed();
66
    trace("Test executable is %s\n", (bAppThemed) ? "themed" : "not themed");
67 68

    SetLastError(0xdeadbeef);
69
    bTPDefined = IsThemePartDefined(NULL, 0 , 0);
70 71
    ok( bTPDefined == FALSE, "Expected FALSE\n");
    ok( GetLastError() == E_HANDLE,
72
        "Expected E_HANDLE, got 0x%08x\n",
73
        GetLastError());
74 75
}

76 77 78 79
static void test_GetWindowTheme(void)
{
    HTHEME    hTheme;
    HWND      hWnd;
80
    BOOL    bDestroyed;
81 82

    SetLastError(0xdeadbeef);
83
    hTheme = GetWindowTheme(NULL);
84 85 86
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    todo_wine
        ok( GetLastError() == E_HANDLE,
87
            "Expected E_HANDLE, got 0x%08x\n",
88 89
            GetLastError());

90
    /* Only do the bare minimum to get a valid hwnd */
91 92 93 94
    hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
    if (!hWnd) return;

    SetLastError(0xdeadbeef);
95
    hTheme = GetWindowTheme(hWnd);
96 97
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    ok( GetLastError() == 0xdeadbeef,
98
        "Expected 0xdeadbeef, got 0x%08x\n",
99
        GetLastError());
100 101 102

    bDestroyed = DestroyWindow(hWnd);
    if (!bDestroyed)
103
        trace("Window %p couldn't be destroyed : 0x%08x\n",
104
            hWnd, GetLastError());
105 106
}

107 108 109 110
static void test_SetWindowTheme(void)
{
    HRESULT hRes;
    HWND    hWnd;
111
    BOOL    bDestroyed;
112

113
    hRes = SetWindowTheme(NULL, NULL, NULL);
114 115
todo_wine
    ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
116

117
    /* Only do the bare minimum to get a valid hwnd */
118 119 120
    hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
    if (!hWnd) return;

121
    hRes = SetWindowTheme(hWnd, NULL, NULL);
122
    ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
123 124 125

    bDestroyed = DestroyWindow(hWnd);
    if (!bDestroyed)
126
        trace("Window %p couldn't be destroyed : 0x%08x\n",
127
            hWnd, GetLastError());
128 129 130 131
}

static void test_OpenThemeData(void)
{
132
    HTHEME    hTheme, hTheme2;
133 134
    HWND      hWnd;
    BOOL      bThemeActive;
135
    HRESULT   hRes;
136
    BOOL      bDestroyed;
137
    BOOL      bTPDefined;
138 139 140

    WCHAR szInvalidClassList[] = {'D','E','A','D','B','E','E','F', 0 };
    WCHAR szButtonClassList[]  = {'B','u','t','t','o','n', 0 };
141
    WCHAR szButtonClassList2[]  = {'b','U','t','T','o','N', 0 };
142 143
    WCHAR szClassList[]        = {'B','u','t','t','o','n',';','L','i','s','t','B','o','x', 0 };

144
    bThemeActive = IsThemeActive();
145 146 147

    /* All NULL */
    SetLastError(0xdeadbeef);
148
    hTheme = OpenThemeData(NULL, NULL);
149
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
150
    ok( GetLastError() == E_POINTER,
151
            "Expected GLE() to be E_POINTER, got 0x%08x\n",
152 153 154 155
            GetLastError());

    /* A NULL hWnd and an invalid classlist */
    SetLastError(0xdeadbeef);
156
    hTheme = OpenThemeData(NULL, szInvalidClassList);
157 158 159
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    todo_wine
        ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
160
            "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
161 162 163
            GetLastError());

    SetLastError(0xdeadbeef);
164
    hTheme = OpenThemeData(NULL, szClassList);
165 166 167 168
    if (bThemeActive)
    {
        ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
        todo_wine
169
            ok( GetLastError() == ERROR_SUCCESS,
170
                "Expected ERROR_SUCCESS, got 0x%08x\n",
171 172 173 174 175 176 177
                GetLastError());
    }
    else
    {
        ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
        todo_wine
            ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
178
                "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
179 180 181
                GetLastError());
    }

182
    /* Only do the bare minimum to get a valid hdc */
183 184 185 186
    hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
    if (!hWnd) return;

    SetLastError(0xdeadbeef);
187
    hTheme = OpenThemeData(hWnd, NULL);
188
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
189
    ok( GetLastError() == E_POINTER,
190
            "Expected GLE() to be E_POINTER, got 0x%08x\n",
191 192 193
            GetLastError());

    SetLastError(0xdeadbeef);
194
    hTheme = OpenThemeData(hWnd, szInvalidClassList);
195 196 197
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    todo_wine
        ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
198
            "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
199 200 201 202 203
            GetLastError());

    if (!bThemeActive)
    {
        SetLastError(0xdeadbeef);
204
        hTheme = OpenThemeData(hWnd, szButtonClassList);
205 206 207
        ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
        todo_wine
            ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
208
                "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
209
                GetLastError());
210
        skip("No active theme, skipping rest of OpenThemeData tests\n");
211 212 213 214 215 216
        return;
    }

    /* Only do the next checks if we have an active theme */

    SetLastError(0xdeadbeef);
217
    hTheme = OpenThemeData(hWnd, szButtonClassList);
218 219
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
220
        ok( GetLastError() == ERROR_SUCCESS,
221
            "Expected ERROR_SUCCESS, got 0x%08x\n",
222 223
            GetLastError());

224 225
    /* Test with bUtToN instead of Button */
    SetLastError(0xdeadbeef);
226
    hTheme = OpenThemeData(hWnd, szButtonClassList2);
227 228 229
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
230
            "Expected ERROR_SUCCESS, got 0x%08x\n",
231 232
            GetLastError());

233
    SetLastError(0xdeadbeef);
234
    hTheme = OpenThemeData(hWnd, szClassList);
235 236
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
237
        ok( GetLastError() == ERROR_SUCCESS,
238
            "Expected ERROR_SUCCESS, got 0x%08x\n",
239
            GetLastError());
240

241 242
    /* GetWindowTheme should return the last handle opened by OpenThemeData */
    SetLastError(0xdeadbeef);
243
    hTheme2 = GetWindowTheme(hWnd);
244 245 246
    ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
        hTheme, hTheme2);
    ok( GetLastError() == 0xdeadbeef,
247
        "Expected 0xdeadbeef, got 0x%08x\n",
248 249
        GetLastError());

250
    hRes = CloseThemeData(hTheme);
251
    ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
252 253

    /* Close a second time */
254
    hRes = CloseThemeData(hTheme);
255
    ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
256 257 258 259

    /* See if closing makes a difference for GetWindowTheme */
    SetLastError(0xdeadbeef);
    hTheme2 = NULL;
260
    hTheme2 = GetWindowTheme(hWnd);
261 262 263
    ok( hTheme == hTheme2, "Expected the same HTHEME handle (%p<->%p)\n",
        hTheme, hTheme2);
    ok( GetLastError() == 0xdeadbeef,
264
        "Expected 0xdeadbeef, got 0x%08x\n",
265 266
        GetLastError());

267
    SetLastError(0xdeadbeef);
268
    bTPDefined = IsThemePartDefined(hTheme, 0 , 0);
269 270 271 272
    todo_wine
    {
        ok( bTPDefined == FALSE, "Expected FALSE\n");
        ok( GetLastError() == ERROR_SUCCESS,
273
            "Expected ERROR_SUCCESS, got 0x%08x\n",
274 275 276
            GetLastError());
    }

277 278
    bDestroyed = DestroyWindow(hWnd);
    if (!bDestroyed)
279
        trace("Window %p couldn't be destroyed : 0x%08x\n",
280
            hWnd, GetLastError());
281 282
}

283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
static void test_OpenThemeDataEx(void)
{
    HTHEME    hTheme;
    HWND      hWnd;
    BOOL      bThemeActive;
    BOOL      bDestroyed;

    WCHAR szInvalidClassList[] = {'D','E','A','D','B','E','E','F', 0 };
    WCHAR szButtonClassList[]  = {'B','u','t','t','o','n', 0 };
    WCHAR szButtonClassList2[]  = {'b','U','t','T','o','N', 0 };
    WCHAR szClassList[]        = {'B','u','t','t','o','n',';','L','i','s','t','B','o','x', 0 };

    if (!pOpenThemeDataEx)
    {
        win_skip("OpenThemeDataEx not available\n");
        return;
    }

301
    bThemeActive = IsThemeActive();
302 303 304 305 306

    /* All NULL */
    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(NULL, NULL, 0);
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
307
    ok( GetLastError() == E_POINTER,
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
            "Expected GLE() to be E_POINTER, got 0x%08x\n",
            GetLastError());

    /* A NULL hWnd and an invalid classlist without flags */
    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(NULL, szInvalidClassList, 0);
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    todo_wine
        ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
            "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(NULL, szClassList, 0);
    if (bThemeActive)
    {
        ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
        todo_wine
            ok( GetLastError() == ERROR_SUCCESS,
                "Expected ERROR_SUCCESS, got 0x%08x\n",
                GetLastError());
    }
    else
    {
        ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
        todo_wine
            ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
                "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
                GetLastError());
    }

    /* Only do the bare minimum to get a valid hdc */
    hWnd = CreateWindowExA(0, "static", "", WS_POPUP, 0,0,100,100,0, 0, 0, NULL);
    if (!hWnd) return;

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, NULL, 0);
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
346
    ok( GetLastError() == E_POINTER,
347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
            "Expected GLE() to be E_POINTER, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szInvalidClassList, 0);
    ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
    todo_wine
        ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
            "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
            GetLastError());

    if (!bThemeActive)
    {
        SetLastError(0xdeadbeef);
        hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0);
        ok( hTheme == NULL, "Expected a NULL return, got %p\n", hTheme);
        todo_wine
            ok( GetLastError() == E_PROP_ID_UNSUPPORTED,
                "Expected GLE() to be E_PROP_ID_UNSUPPORTED, got 0x%08x\n",
                GetLastError());
367
        skip("No active theme, skipping rest of OpenThemeDataEx tests\n");
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427
        return;
    }

    /* Only do the next checks if we have an active theme */

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, OTD_FORCE_RECT_SIZING);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, OTD_NONCLIENT);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szButtonClassList, 0x3);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    /* Test with bUtToN instead of Button */
    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szButtonClassList2, 0);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    SetLastError(0xdeadbeef);
    hTheme = pOpenThemeDataEx(hWnd, szClassList, 0);
    ok( hTheme != NULL, "got NULL, expected a HTHEME handle\n");
    todo_wine
        ok( GetLastError() == ERROR_SUCCESS,
            "Expected ERROR_SUCCESS, got 0x%08x\n",
            GetLastError());

    bDestroyed = DestroyWindow(hWnd);
    if (!bDestroyed)
        trace("Window %p couldn't be destroyed : 0x%08x\n",
            hWnd, GetLastError());
}

428 429 430 431 432 433 434 435
static void test_GetCurrentThemeName(void)
{
    BOOL    bThemeActive;
    HRESULT hRes;
    WCHAR currentTheme[MAX_PATH];
    WCHAR currentColor[MAX_PATH];
    WCHAR currentSize[MAX_PATH];

436
    bThemeActive = IsThemeActive();
437 438

    /* All NULLs */
439
    hRes = GetCurrentThemeName(NULL, 0, NULL, 0, NULL, 0);
440
    if (bThemeActive)
441
        ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
442
    else
443
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
444 445

    /* Number of characters given is 0 */
446
    hRes = GetCurrentThemeName(currentTheme, 0, NULL, 0, NULL, 0);
447
    if (bThemeActive)
448
        ok( hRes == S_OK || broken(hRes == E_FAIL /* WinXP SP1 */), "Expected S_OK, got 0x%08x\n", hRes);
449
    else
450
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
451

452
    hRes = GetCurrentThemeName(currentTheme, 2, NULL, 0, NULL, 0);
453 454
    if (bThemeActive)
        todo_wine
455
            ok(hRes == E_NOT_SUFFICIENT_BUFFER ||
456
               broken(hRes == E_FAIL /* WinXP SP1 */),
457
               "Expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hRes);
458
    else
459
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
460 461

    /* The same is true if the number of characters is too small for Color and/or Size */
462
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
463 464 465 466
                                currentColor, 2,
                                currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
    if (bThemeActive)
        todo_wine
467
            ok(hRes == E_NOT_SUFFICIENT_BUFFER ||
468
               broken(hRes == E_FAIL /* WinXP SP1 */),
469
               "Expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hRes);
470
    else
471
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
472 473

    /* Given number of characters is correct */
474
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR), NULL, 0, NULL, 0);
475
    if (bThemeActive)
476
        ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
477
    else
478
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
479 480

    /* Given number of characters for the theme name is too large */
481
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme), NULL, 0, NULL, 0);
482 483 484
    if (bThemeActive)
        ok( hRes == E_POINTER || hRes == S_OK, "Expected E_POINTER or S_OK, got 0x%08x\n", hRes);
    else
485 486 487
        ok( hRes == E_PROP_ID_UNSUPPORTED ||
            hRes == E_POINTER, /* win2k3 */
            "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
488 489
 
    /* The too large case is only for the theme name, not for color name or size name */
490
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
491 492 493
                                currentColor, sizeof(currentTheme),
                                currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
    if (bThemeActive)
494
        ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
495
    else
496
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
497

498
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
499 500 501
                                currentColor, sizeof(currentTheme) / sizeof(WCHAR),
                                currentSize,  sizeof(currentSize));
    if (bThemeActive)
502
        ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
503
    else
504
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
505 506

    /* Correct call */
507
    hRes = GetCurrentThemeName(currentTheme, sizeof(currentTheme) / sizeof(WCHAR),
508 509 510
                                currentColor, sizeof(currentColor) / sizeof(WCHAR),
                                currentSize,  sizeof(currentSize)  / sizeof(WCHAR));
    if (bThemeActive)
511
        ok( hRes == S_OK, "Expected S_OK, got 0x%08x\n", hRes);
512
    else
513
        ok( hRes == E_PROP_ID_UNSUPPORTED, "Expected E_PROP_ID_UNSUPPORTED, got 0x%08x\n", hRes);
514 515
}

516 517 518 519
static void test_CloseThemeData(void)
{
    HRESULT hRes;

520
    hRes = CloseThemeData(NULL);
521
    ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
522
    hRes = CloseThemeData(INVALID_HANDLE_VALUE);
523
    ok( hRes == E_HANDLE, "Expected E_HANDLE, got 0x%08x\n", hRes);
524 525
}

526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
static void test_buffer_dc_props(HDC hdc, const RECT *rect)
{
    static const XFORM ident = { 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f };
    XFORM xform;
    POINT org;
    RECT box;
    BOOL ret;

    ret = GetWorldTransform(hdc, &xform);
    ok(ret, "Failed to get world transform\n");
    ok(!memcmp(&xform, &ident, sizeof(xform)), "Unexpected world transform\n");

    ret = GetViewportOrgEx(hdc, &org);
    ok(ret, "Failed to get vport origin\n");
    ok(org.x == 0 && org.y == 0, "Unexpected vport origin\n");

    ret = GetWindowOrgEx(hdc, &org);
    ok(ret, "Failed to get vport origin\n");
    ok(org.x == rect->left && org.y == rect->top, "Unexpected window origin\n");

    ret = GetClipBox(hdc, &box);
    ok(ret, "Failed to get clip box\n");
    ok(box.left == rect->left && box.top == rect->top, "Unexpected clip box\n");

    ok(GetGraphicsMode(hdc) == GM_COMPATIBLE, "wrong graphics mode\n");
}

553 554
static void test_buffered_paint(void)
{
555
    HDC target, src, hdc, screen_dc;
556 557 558 559
    BP_PAINTPARAMS params = { 0 };
    BP_BUFFERFORMAT format;
    HPAINTBUFFER buffer;
    RECT rect, rect2;
560
    RGBQUAD *bits;
561
    HBITMAP hbm;
562
    HRESULT hr;
563
    int row;
564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584

    if (!pBeginBufferedPaint)
    {
        win_skip("Buffered painting API is not supported.\n");
        return;
    }

    buffer = pBeginBufferedPaint(NULL, NULL, BPBF_COMPATIBLEBITMAP,
            NULL, NULL);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);

    target = CreateCompatibleDC(0);
    buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
            NULL, NULL);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);

    params.cbSize = sizeof(params);
    buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
            &params, NULL);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);

585
    src = (void *)0xdeadbeef;
586 587 588
    buffer = pBeginBufferedPaint(target, NULL, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
589
    ok(src == NULL, "Unexpected buffered dc %p\n", src);
590 591

    /* target rect is mandatory */
592 593
    SetRectEmpty(&rect);
    src = (void *)0xdeadbeef;
594 595 596
    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
597
    ok(src == NULL, "Unexpected buffered dc %p\n", src);
598

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
    /* inverted rectangle */
    SetRect(&rect, 10, 0, 5, 5);
    src = (void *)0xdeadbeef;
    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
    ok(src == NULL, "Unexpected buffered dc %p\n", src);

    SetRect(&rect, 0, 10, 5, 0);
    src = (void *)0xdeadbeef;
    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
    ok(src == NULL, "Unexpected buffered dc %p\n", src);

    /* valid rectangle, no target dc */
    SetRect(&rect, 0, 0, 5, 5);
    src = (void *)0xdeadbeef;
    buffer = pBeginBufferedPaint(NULL, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer == NULL, "Unexpected buffer %p\n", buffer);
    ok(src == NULL, "Unexpected buffered dc %p\n", src);

    SetRect(&rect, 0, 0, 5, 5);
    src = NULL;
624 625 626
    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer != NULL, "Unexpected buffer %p\n", buffer);
627
    ok(src != NULL, "Expected buffered dc\n");
628 629 630
    hr = pEndBufferedPaint(buffer, FALSE);
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);

631
    SetRect(&rect, 0, 0, 5, 5);
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP,
            &params, &src);
    ok(buffer != NULL, "Unexpected buffer %p\n", buffer);

    /* clearing */
    hr = pBufferedPaintClear(NULL, NULL);
todo_wine
    ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);

    hr = pBufferedPaintClear(buffer, NULL);
todo_wine
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);

    /* access buffer attributes */
    hdc = pGetBufferedPaintDC(buffer);
    ok(hdc == src, "Unexpected hdc, %p, buffered dc %p\n", hdc, src);

    hdc = pGetBufferedPaintTargetDC(buffer);
    ok(hdc == target, "Unexpected target hdc %p, original %p\n", hdc, target);

652 653 654
    hr = pGetBufferedPaintTargetRect(NULL, NULL);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

655 656 657
    hr = pGetBufferedPaintTargetRect(buffer, NULL);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

658 659 660
    hr = pGetBufferedPaintTargetRect(NULL, &rect2);
    ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);

661 662 663 664
    SetRectEmpty(&rect2);
    hr = pGetBufferedPaintTargetRect(buffer, &rect2);
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);
    ok(EqualRect(&rect, &rect2), "Wrong target rect\n");
665

666 667 668
    hr = pEndBufferedPaint(buffer, FALSE);
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);

669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
    /* invalid buffer handle */
    hr = pEndBufferedPaint(NULL, FALSE);
    ok(hr == E_INVALIDARG, "Unexpected return code %#x\n", hr);

    hdc = pGetBufferedPaintDC(NULL);
    ok(hdc == NULL, "Unexpected hdc %p\n", hdc);

    hdc = pGetBufferedPaintTargetDC(NULL);
    ok(hdc == NULL, "Unexpected target hdc %p\n", hdc);

    hr = pGetBufferedPaintTargetRect(NULL, &rect2);
    ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);

    hr = pGetBufferedPaintTargetRect(NULL, NULL);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

    bits = (void *)0xdeadbeef;
    row = 10;
    hr = pGetBufferedPaintBits(NULL, &bits, &row);
    ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
    ok(row == 10, "Unexpected row count %d\n", row);
    ok(bits == (void *)0xdeadbeef, "Unepexpected data pointer %p\n", bits);

    hr = pGetBufferedPaintBits(NULL, NULL, NULL);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

    hr = pGetBufferedPaintBits(NULL, &bits, NULL);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

    hr = pGetBufferedPaintBits(NULL, NULL, &row);
    ok(hr == E_POINTER, "Unexpected return code %#x\n", hr);

701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
    screen_dc = GetDC(0);

    hdc = CreateCompatibleDC(screen_dc);
    ok(hdc != NULL, "Failed to create a DC\n");
    hbm = CreateCompatibleBitmap(screen_dc, 64, 64);
    ok(hbm != NULL, "Failed to create a bitmap\n");
    SelectObject(hdc, hbm);

    ReleaseDC(0, screen_dc);

    SetRect(&rect, 1, 2, 34, 56);

    buffer = pBeginBufferedPaint(hdc, &rect, BPBF_COMPATIBLEBITMAP, NULL, &src);
    test_buffer_dc_props(src, &rect);
    hr = pEndBufferedPaint(buffer, FALSE);
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);

    DeleteObject(hbm);
    DeleteDC(hdc);

    buffer = pBeginBufferedPaint(target, &rect, BPBF_COMPATIBLEBITMAP, NULL, &src);
    test_buffer_dc_props(src, &rect);
    hr = pEndBufferedPaint(buffer, FALSE);
    ok(hr == S_OK, "Unexpected return code %#x\n", hr);

726 727 728 729 730 731 732 733 734 735 736 737 738 739 740
    /* access buffer bits */
    for (format = BPBF_COMPATIBLEBITMAP; format <= BPBF_TOPDOWNMONODIB; format++)
    {
        buffer = pBeginBufferedPaint(target, &rect, format, &params, &src);

        /* only works for DIB buffers */
        bits = NULL;
        row = 0;
        hr = pGetBufferedPaintBits(buffer, &bits, &row);
        if (format == BPBF_COMPATIBLEBITMAP)
            ok(hr == E_FAIL, "Unexpected return code %#x\n", hr);
        else
        {
            ok(hr == S_OK, "Unexpected return code %#x\n", hr);
            ok(bits != NULL, "Bitmap bits %p\n", bits);
741
            ok(row >= (rect.right - rect.left), "format %d: bitmap width %d\n", format, row);
742
        }
743

744 745 746 747 748 749 750
        hr = pEndBufferedPaint(buffer, FALSE);
        ok(hr == S_OK, "Unexpected return code %#x\n", hr);
    }

    DeleteDC(target);
}

751 752
START_TEST(system)
{
753
    init_funcs();
754

755
    /* No real functional theme API tests will be done (yet). The current tests
756 757 758
     * only show input/return behaviour
     */

759 760 761 762
    test_IsThemed();
    test_GetWindowTheme();
    test_SetWindowTheme();
    test_OpenThemeData();
763
    test_OpenThemeDataEx();
764
    test_GetCurrentThemeName();
765
    test_CloseThemeData();
766
    test_buffered_paint();
767
}