wined3d: Merge the various resource desc structures.
[wine] / dlls / user32 / tests / cursoricon.c
1 /*
2  * Unit test suite for cursors and icons.
3  *
4  * Copyright 2006 Michael Kaufmann
5  * Copyright 2007 Dmitry Timoshkov
6  * Copyright 2007-2008 Andrew Riedi
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include <assert.h>
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <stdio.h>
27
28 #include "wine/test.h"
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winreg.h"
32 #include "wingdi.h"
33 #include "winuser.h"
34
35 #include "pshpack1.h"
36
37 typedef struct
38 {
39     BYTE bWidth;
40     BYTE bHeight;
41     BYTE bColorCount;
42     BYTE bReserved;
43     WORD xHotspot;
44     WORD yHotspot;
45     DWORD dwDIBSize;
46     DWORD dwDIBOffset;
47 } CURSORICONFILEDIRENTRY;
48
49 typedef struct
50 {
51     WORD idReserved;
52     WORD idType;
53     WORD idCount;
54     CURSORICONFILEDIRENTRY idEntries[1];
55 } CURSORICONFILEDIR;
56
57 #define RIFF_FOURCC( c0, c1, c2, c3 ) \
58         ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \
59         ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) )
60
61 #define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F')
62 #define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T')
63 #define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N')
64 #define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h')
65 #define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ')
66 #define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm')
67 #define ANI_icon_ID RIFF_FOURCC('i', 'c', 'o', 'n')
68
69 #define ANI_FLAG_ICON       0x1
70 #define ANI_FLAG_SEQUENCE   0x2
71
72 typedef struct {
73     DWORD header_size;
74     DWORD num_frames;
75     DWORD num_steps;
76     DWORD width;
77     DWORD height;
78     DWORD bpp;
79     DWORD num_planes;
80     DWORD display_rate;
81     DWORD flags;
82 } ani_header;
83
84 typedef struct {
85     BYTE data[32*32*4];
86 } ani_data32x32x32;
87
88 typedef struct {
89     CURSORICONFILEDIR    icon_info;  /* animated cursor frame information */
90     BITMAPINFOHEADER     bmi_header; /* animated cursor frame header */
91     ani_data32x32x32     bmi_data;   /* animated cursor frame DIB data */
92 } ani_frame32x32x32;
93
94 typedef struct {
95     DWORD                chunk_id;   /* ANI_anih_ID */
96     DWORD                chunk_size; /* actual size of data */
97     ani_header           header;     /* animated cursor header */
98 } riff_header_t;
99
100 typedef struct {
101     DWORD                chunk_id;   /* ANI_LIST_ID */
102     DWORD                chunk_size; /* actual size of data */
103     DWORD                chunk_type; /* ANI_fram_ID */
104 } riff_list_t;
105
106 typedef struct {
107     DWORD                chunk_id;   /* ANI_icon_ID */
108     DWORD                chunk_size; /* actual size of data */
109     ani_frame32x32x32    data;       /* animated cursor frame */
110 } riff_icon32x32x32_t;
111
112 typedef struct {
113     DWORD                chunk_id;   /* ANI_RIFF_ID */
114     DWORD                chunk_size; /* actual size of data */
115     DWORD                chunk_type; /* ANI_ACON_ID */
116     riff_header_t        header;     /* RIFF animated cursor header */
117     riff_list_t          frame_list; /* RIFF animated cursor frame list info */
118     riff_icon32x32x32_t  frames[1];  /* array of animated cursor frames */
119 } riff_cursor1_t;
120
121 typedef struct {
122     DWORD                chunk_id;   /* ANI_RIFF_ID */
123     DWORD                chunk_size; /* actual size of data */
124     DWORD                chunk_type; /* ANI_ACON_ID */
125     riff_header_t        header;     /* RIFF animated cursor header */
126     riff_list_t          frame_list; /* RIFF animated cursor frame list info */
127     riff_icon32x32x32_t  frames[3];  /* array of animated cursor frames */
128 } riff_cursor3_t;
129
130 riff_cursor1_t empty_anicursor = {
131     ANI_RIFF_ID,
132     sizeof(empty_anicursor) - sizeof(DWORD)*2,
133     ANI_ACON_ID,
134     {
135         ANI_anih_ID,
136         sizeof(ani_header),
137         {
138             sizeof(ani_header),
139             1,            /* frames */
140             1,            /* steps */
141             32,           /* width */
142             32,           /* height */
143             32,           /* depth */
144             1,            /* planes */
145             10,           /* display rate in jiffies */
146             ANI_FLAG_ICON /* flags */
147         }
148     },
149     {
150         ANI_LIST_ID,
151         sizeof(riff_icon32x32x32_t)*1 + sizeof(DWORD),
152         ANI_fram_ID,
153     },
154     {
155         {
156             ANI_icon_ID,
157             sizeof(ani_frame32x32x32),
158             {
159                 {
160                     0x0, /* reserved */
161                     0,   /* type: icon(1), cursor(2) */
162                     1,   /* count */
163                     {
164                         {
165                             32,                        /* width */
166                             32,                        /* height */
167                             0,                         /* color count */
168                             0x0,                       /* reserved */
169                             16,                        /* x hotspot */
170                             16,                        /* y hotspot */
171                             sizeof(ani_data32x32x32),  /* DIB size */
172                             sizeof(CURSORICONFILEDIR)  /* DIB offset */
173                         }
174                     }
175                 },
176                 {
177                       sizeof(BITMAPINFOHEADER),  /* structure for DIB-type data */
178                       32,                        /* width */
179                       32*2,                      /* actual height times two */
180                       1,                         /* planes */
181                       32,                        /* bpp */
182                       BI_RGB,                    /* compression */
183                       0,                         /* image size */
184                       0,                         /* biXPelsPerMeter */
185                       0,                         /* biYPelsPerMeter */
186                       0,                         /* biClrUsed */
187                       0                          /* biClrImportant */
188                 },
189                 { /* DIB data: left uninitialized */ }
190             }
191         }
192     }
193 };
194
195 riff_cursor3_t empty_anicursor3 = {
196     ANI_RIFF_ID,
197     sizeof(empty_anicursor3) - sizeof(DWORD)*2,
198     ANI_ACON_ID,
199     {
200         ANI_anih_ID,
201         sizeof(ani_header),
202         {
203             sizeof(ani_header),
204             3,            /* frames */
205             1,            /* steps */
206             32,           /* width */
207             32,           /* height */
208             32,           /* depth */
209             1,            /* planes */
210             0xbeef,       /* display rate in jiffies */
211             ANI_FLAG_ICON /* flags */
212         }
213     },
214     {
215         ANI_LIST_ID,
216         sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD),
217         ANI_fram_ID,
218     },
219     {
220         {
221             ANI_icon_ID,
222             sizeof(ani_frame32x32x32),
223             {
224                 {
225                     0x0, /* reserved */
226                     0,   /* type: icon(1), cursor(2) */
227                     1,   /* count */
228                     {
229                         {
230                             32,                        /* width */
231                             32,                        /* height */
232                             0,                         /* color count */
233                             0x0,                       /* reserved */
234                             16,                        /* x hotspot */
235                             16,                        /* y hotspot */
236                             sizeof(ani_data32x32x32),  /* DIB size */
237                             sizeof(CURSORICONFILEDIR)  /* DIB offset */
238                         }
239                     }
240                 },
241                 {
242                       sizeof(BITMAPINFOHEADER),  /* structure for DIB-type data */
243                       32,                        /* width */
244                       32*2,                      /* actual height times two */
245                       1,                         /* planes */
246                       32,                        /* bpp */
247                       BI_RGB,                    /* compression */
248                       0,                         /* image size */
249                       0,                         /* biXPelsPerMeter */
250                       0,                         /* biYPelsPerMeter */
251                       0,                         /* biClrUsed */
252                       0                          /* biClrImportant */
253                 },
254                 { /* DIB data: left uninitialized */ }
255             }
256         },
257         {
258             ANI_icon_ID,
259             sizeof(ani_frame32x32x32),
260             {
261                 {
262                     0x0, /* reserved */
263                     0,   /* type: icon(1), cursor(2) */
264                     1,   /* count */
265                     {
266                         {
267                             32,                        /* width */
268                             32,                        /* height */
269                             0,                         /* color count */
270                             0x0,                       /* reserved */
271                             16,                        /* x hotspot */
272                             16,                        /* y hotspot */
273                             sizeof(ani_data32x32x32),  /* DIB size */
274                             sizeof(CURSORICONFILEDIR)  /* DIB offset */
275                         }
276                     }
277                 },
278                 {
279                       sizeof(BITMAPINFOHEADER),  /* structure for DIB-type data */
280                       32,                        /* width */
281                       32*2,                      /* actual height times two */
282                       1,                         /* planes */
283                       32,                        /* bpp */
284                       BI_RGB,                    /* compression */
285                       0,                         /* image size */
286                       0,                         /* biXPelsPerMeter */
287                       0,                         /* biYPelsPerMeter */
288                       0,                         /* biClrUsed */
289                       0                          /* biClrImportant */
290                 },
291                 { /* DIB data: left uninitialized */ }
292             }
293         },
294         {
295             ANI_icon_ID,
296             sizeof(ani_frame32x32x32),
297             {
298                 {
299                     0x0, /* reserved */
300                     0,   /* type: icon(1), cursor(2) */
301                     1,   /* count */
302                     {
303                         {
304                             32,                        /* width */
305                             32,                        /* height */
306                             0,                         /* color count */
307                             0x0,                       /* reserved */
308                             16,                        /* x hotspot */
309                             16,                        /* y hotspot */
310                             sizeof(ani_data32x32x32),  /* DIB size */
311                             sizeof(CURSORICONFILEDIR)  /* DIB offset */
312                         }
313                     }
314                 },
315                 {
316                       sizeof(BITMAPINFOHEADER),  /* structure for DIB-type data */
317                       32,                        /* width */
318                       32*2,                      /* actual height times two */
319                       1,                         /* planes */
320                       32,                        /* bpp */
321                       BI_RGB,                    /* compression */
322                       0,                         /* image size */
323                       0,                         /* biXPelsPerMeter */
324                       0,                         /* biYPelsPerMeter */
325                       0,                         /* biClrUsed */
326                       0                          /* biClrImportant */
327                 },
328                 { /* DIB data: left uninitialized */ }
329             }
330         }
331     }
332 };
333
334 #include "poppack.h"
335
336 static char **test_argv;
337 static int test_argc;
338 static HWND child = 0;
339 static HWND parent = 0;
340 static HANDLE child_process;
341
342 #define PROC_INIT (WM_USER+1)
343
344 static BOOL (WINAPI *pGetCursorInfo)(CURSORINFO *);
345 static BOOL (WINAPI *pGetIconInfoExA)(HICON,ICONINFOEXA *);
346 static BOOL (WINAPI *pGetIconInfoExW)(HICON,ICONINFOEXW *);
347
348 static const int is_win64 = (sizeof(void *) > sizeof(int));
349
350 static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
351 {
352     BOOL ret;
353     DWORD error;
354
355     switch (msg)
356     {
357         /* Destroy the cursor. */
358         case WM_USER+1:
359             SetLastError(0xdeadbeef);
360             ret = DestroyCursor((HCURSOR) lParam);
361             error = GetLastError();
362             ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n");
363             ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD ||
364                error == 0xdeadbeef,  /* vista */
365                 "Last error: %u\n", error);
366             return TRUE;
367         case WM_DESTROY:
368             PostQuitMessage(0);
369             return 0;
370     }
371
372     return DefWindowProc(hwnd, msg, wParam, lParam);
373 }
374
375 static LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
376 {
377     if (msg == PROC_INIT)
378     {
379         child = (HWND) wParam;
380         return TRUE;
381     }
382
383     return DefWindowProc(hwnd, msg, wParam, lParam);
384 }
385
386 static void do_child(void)
387 {
388     WNDCLASS class;
389     MSG msg;
390     BOOL ret;
391
392     /* Register a new class. */
393     class.style = CS_GLOBALCLASS;
394     class.lpfnWndProc = callback_child;
395     class.cbClsExtra = 0;
396     class.cbWndExtra = 0;
397     class.hInstance = GetModuleHandle(NULL);
398     class.hIcon = NULL;
399     class.hCursor = NULL;
400     class.hbrBackground = NULL;
401     class.lpszMenuName = NULL;
402     class.lpszClassName = "cursor_child";
403
404     SetLastError(0xdeadbeef);
405     ret = RegisterClass(&class);
406     ok(ret, "Failed to register window class.  Error: %u\n", GetLastError());
407
408     /* Create a window. */
409     child = CreateWindowA("cursor_child", "cursor_child", WS_POPUP | WS_VISIBLE,
410         0, 0, 200, 200, 0, 0, 0, NULL);
411     ok(child != 0, "CreateWindowA failed.  Error: %u\n", GetLastError());
412
413     /* Let the parent know our HWND. */
414     PostMessage(parent, PROC_INIT, (WPARAM) child, 0);
415
416     /* Receive messages. */
417     while ((ret = GetMessage(&msg, 0, 0, 0)))
418     {
419         ok(ret != -1, "GetMessage failed.  Error: %u\n", GetLastError());
420         TranslateMessage(&msg);
421         DispatchMessage(&msg);
422     }
423 }
424
425 static void do_parent(void)
426 {
427     char path_name[MAX_PATH];
428     PROCESS_INFORMATION info;
429     STARTUPINFOA startup;
430     WNDCLASS class;
431     MSG msg;
432     BOOL ret;
433
434     /* Register a new class. */
435     class.style = CS_GLOBALCLASS;
436     class.lpfnWndProc = callback_parent;
437     class.cbClsExtra = 0;
438     class.cbWndExtra = 0;
439     class.hInstance = GetModuleHandle(NULL);
440     class.hIcon = NULL;
441     class.hCursor = NULL;
442     class.hbrBackground = NULL;
443     class.lpszMenuName = NULL;
444     class.lpszClassName = "cursor_parent";
445
446     SetLastError(0xdeadbeef);
447     ret = RegisterClass(&class);
448     ok(ret, "Failed to register window class.  Error: %u\n", GetLastError());
449
450     /* Create a window. */
451     parent = CreateWindowA("cursor_parent", "cursor_parent", WS_POPUP | WS_VISIBLE,
452         0, 0, 200, 200, 0, 0, 0, NULL);
453     ok(parent != 0, "CreateWindowA failed.  Error: %u\n", GetLastError());
454
455     /* Start child process. */
456     memset(&startup, 0, sizeof(startup));
457     startup.cb = sizeof(startup);
458     startup.dwFlags = STARTF_USESHOWWINDOW;
459     startup.wShowWindow = SW_SHOWNORMAL;
460
461     sprintf(path_name, "%s cursoricon %lx", test_argv[0], (INT_PTR)parent);
462     ok(CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed.\n");
463     child_process = info.hProcess;
464
465     /* Wait for child window handle. */
466     while ((child == 0) && (ret = GetMessage(&msg, parent, 0, 0)))
467     {
468         ok(ret != -1, "GetMessage failed.  Error: %u\n", GetLastError());
469         TranslateMessage(&msg);
470         DispatchMessage(&msg);
471     }
472 }
473
474 static void finish_child_process(void)
475 {
476     SendMessage(child, WM_CLOSE, 0, 0);
477     winetest_wait_child_process( child_process );
478     CloseHandle(child_process);
479 }
480
481 static void test_child_process(void)
482 {
483     static const BYTE bmp_bits[4096];
484     HCURSOR cursor;
485     ICONINFO cursorInfo;
486     UINT display_bpp;
487     HDC hdc;
488
489     /* Create and set a dummy cursor. */
490     hdc = GetDC(0);
491     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
492     ReleaseDC(0, hdc);
493
494     cursorInfo.fIcon = FALSE;
495     cursorInfo.xHotspot = 0;
496     cursorInfo.yHotspot = 0;
497     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
498     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
499
500     cursor = CreateIconIndirect(&cursorInfo);
501     ok(cursor != NULL, "CreateIconIndirect returned %p.\n", cursor);
502
503     SetCursor(cursor);
504
505     /* Destroy the cursor. */
506     SendMessage(child, WM_USER+1, 0, (LPARAM) cursor);
507 }
508
509 static BOOL color_match(COLORREF a, COLORREF b)
510 {
511     /* 5-bit accuracy is a sufficient test. This will match as long as
512      * colors are never truncated to less that 3x5-bit accuracy i.e.
513      * palettized. */
514     return (a & 0x00F8F8F8) == (b & 0x00F8F8F8);
515 }
516
517 static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
518                                   INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
519 {
520     HBITMAP copy;
521     BITMAP origBitmap;
522     BITMAP copyBitmap;
523     BOOL orig_is_dib;
524     BOOL copy_is_dib;
525
526     copy = CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags);
527     ok(copy != NULL, "CopyImage() failed\n");
528     if (copy != NULL)
529     {
530         GetObject(bitmap, sizeof(origBitmap), &origBitmap);
531         GetObject(copy, sizeof(copyBitmap), &copyBitmap);
532         orig_is_dib = (origBitmap.bmBits != NULL);
533         copy_is_dib = (copyBitmap.bmBits != NULL);
534
535         if (copy_is_dib && dibExpected
536             && copyBitmap.bmBitsPixel == 24
537             && (expectedDepth == 16 || expectedDepth == 32))
538         {
539             /* Windows 95 doesn't create DIBs with a depth of 16 or 32 bit */
540             if (GetVersion() & 0x80000000)
541             {
542                 expectedDepth = 24;
543             }
544         }
545
546         if (copy_is_dib && !dibExpected && !(flags & LR_CREATEDIBSECTION))
547         {
548             /* It's not forbidden to create a DIB section if the flag
549                LR_CREATEDIBSECTION is absent.
550                Windows 9x does this if the bitmap has a depth that doesn't
551                match the screen depth, Windows NT doesn't */
552             dibExpected = TRUE;
553             expectedDepth = origBitmap.bmBitsPixel;
554         }
555
556         ok((!(dibExpected ^ copy_is_dib)
557              && (copyBitmap.bmWidth == expectedWidth)
558              && (copyBitmap.bmHeight == expectedHeight)
559              && (copyBitmap.bmBitsPixel == expectedDepth)),
560              "CopyImage ((%s, %dx%d, %u bpp), %d, %d, %#x): Expected (%s, %dx%d, %u bpp), got (%s, %dx%d, %u bpp)\n",
561                   orig_is_dib ? "DIB" : "DDB", origBitmap.bmWidth, origBitmap.bmHeight, origBitmap.bmBitsPixel,
562                   copyWidth, copyHeight, flags,
563                   dibExpected ? "DIB" : "DDB", expectedWidth, expectedHeight, expectedDepth,
564                   copy_is_dib ? "DIB" : "DDB", copyBitmap.bmWidth, copyBitmap.bmHeight, copyBitmap.bmBitsPixel);
565
566         DeleteObject(copy);
567     }
568 }
569
570 static void test_CopyImage_Bitmap(int depth)
571 {
572     HBITMAP ddb, dib;
573     HDC screenDC;
574     BITMAPINFO * info;
575     VOID * bits;
576     int screen_depth;
577     unsigned int i;
578
579     /* Create a device-independent bitmap (DIB) */
580     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
581     info->bmiHeader.biSize = sizeof(info->bmiHeader);
582     info->bmiHeader.biWidth = 2;
583     info->bmiHeader.biHeight = 2;
584     info->bmiHeader.biPlanes = 1;
585     info->bmiHeader.biBitCount = depth;
586     info->bmiHeader.biCompression = BI_RGB;
587
588     for (i=0; i < 256; i++)
589     {
590         info->bmiColors[i].rgbRed = i;
591         info->bmiColors[i].rgbGreen = i;
592         info->bmiColors[i].rgbBlue = 255 - i;
593         info->bmiColors[i].rgbReserved = 0;
594     }
595
596     dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
597
598     /* Create a device-dependent bitmap (DDB) */
599     screenDC = GetDC(NULL);
600     screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
601     if (depth == 1 || depth == screen_depth)
602     {
603         ddb = CreateBitmap(2, 2, 1, depth, NULL);
604     }
605     else
606     {
607         ddb = NULL;
608     }
609     ReleaseDC(NULL, screenDC);
610
611     if (ddb != NULL)
612     {
613         test_CopyImage_Check(ddb, 0, 0, 0, 2, 2, depth == 1 ? 1 : screen_depth, FALSE);
614         test_CopyImage_Check(ddb, 0, 0, 5, 2, 5, depth == 1 ? 1 : screen_depth, FALSE);
615         test_CopyImage_Check(ddb, 0, 5, 0, 5, 2, depth == 1 ? 1 : screen_depth, FALSE);
616         test_CopyImage_Check(ddb, 0, 5, 5, 5, 5, depth == 1 ? 1 : screen_depth, FALSE);
617
618         test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
619         test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
620         test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
621         test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
622
623         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
624         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
625         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
626         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
627
628         /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
629         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
630         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
631         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
632         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
633
634         DeleteObject(ddb);
635     }
636
637     if (depth != 1)
638     {
639         test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
640         test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
641         test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
642         test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
643     }
644
645     test_CopyImage_Check(dib, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
646     test_CopyImage_Check(dib, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
647     test_CopyImage_Check(dib, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
648     test_CopyImage_Check(dib, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
649
650     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
651     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
652     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
653     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
654
655     /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
656     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
657     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
658     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
659     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
660
661     DeleteObject(dib);
662
663     if (depth == 1)
664     {
665         /* Special case: A monochrome DIB is converted to a monochrome DDB if
666            the colors in the color table are black and white.
667
668            Skip this test on Windows 95, it always creates a monochrome DDB
669            in this case */
670
671         if (!(GetVersion() & 0x80000000))
672         {
673             info->bmiHeader.biBitCount = 1;
674             info->bmiColors[0].rgbRed = 0xFF;
675             info->bmiColors[0].rgbGreen = 0;
676             info->bmiColors[0].rgbBlue = 0;
677             info->bmiColors[1].rgbRed = 0;
678             info->bmiColors[1].rgbGreen = 0xFF;
679             info->bmiColors[1].rgbBlue = 0;
680
681             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
682             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
683             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
684             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
685             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
686             DeleteObject(dib);
687
688             info->bmiHeader.biBitCount = 1;
689             info->bmiColors[0].rgbRed = 0;
690             info->bmiColors[0].rgbGreen = 0;
691             info->bmiColors[0].rgbBlue = 0;
692             info->bmiColors[1].rgbRed = 0xFF;
693             info->bmiColors[1].rgbGreen = 0xFF;
694             info->bmiColors[1].rgbBlue = 0xFF;
695
696             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
697             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
698             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
699             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
700             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
701             DeleteObject(dib);
702
703             info->bmiHeader.biBitCount = 1;
704             info->bmiColors[0].rgbRed = 0xFF;
705             info->bmiColors[0].rgbGreen = 0xFF;
706             info->bmiColors[0].rgbBlue = 0xFF;
707             info->bmiColors[1].rgbRed = 0;
708             info->bmiColors[1].rgbGreen = 0;
709             info->bmiColors[1].rgbBlue = 0;
710
711             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
712             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
713             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
714             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
715             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
716             DeleteObject(dib);
717         }
718     }
719
720     HeapFree(GetProcessHeap(), 0, info);
721 }
722
723 static void test_initial_cursor(void)
724 {
725     HCURSOR cursor, cursor2;
726     DWORD error;
727
728     cursor = GetCursor();
729
730     /* Check what handle GetCursor() returns if a cursor is not set yet. */
731     SetLastError(0xdeadbeef);
732     cursor2 = LoadCursor(NULL, IDC_WAIT);
733     todo_wine {
734         ok(cursor == cursor2, "cursor (%p) is not IDC_WAIT (%p).\n", cursor, cursor2);
735     }
736     error = GetLastError();
737     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
738 }
739
740 static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_bpp, int line)
741 {
742     ICONINFO info;
743     DWORD ret;
744     BITMAP bmMask, bmColor;
745
746     ret = GetIconInfo(hIcon, &info);
747     ok_(__FILE__, line)(ret, "GetIconInfo failed\n");
748
749     /* CreateIcon under XP causes info.fIcon to be 0 */
750     ok_(__FILE__, line)(info.xHotspot == exp_cx/2, "info.xHotspot = %u\n", info.xHotspot);
751     ok_(__FILE__, line)(info.yHotspot == exp_cy/2, "info.yHotspot = %u\n", info.yHotspot);
752     ok_(__FILE__, line)(info.hbmMask != 0, "info.hbmMask is NULL\n");
753
754     ret = GetObject(info.hbmMask, sizeof(bmMask), &bmMask);
755     ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
756
757     if (exp_bpp == 1)
758         ok_(__FILE__, line)(info.hbmColor == 0, "info.hbmColor should be NULL\n");
759
760     if (info.hbmColor)
761     {
762         HDC hdc;
763         UINT display_bpp;
764
765         hdc = GetDC(0);
766         display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
767         ReleaseDC(0, hdc);
768
769         ret = GetObject(info.hbmColor, sizeof(bmColor), &bmColor);
770         ok_(__FILE__, line)(ret == sizeof(bmColor), "GetObject(info.hbmColor) failed, ret %u\n", ret);
771
772         ok_(__FILE__, line)(bmColor.bmBitsPixel == display_bpp /* XP */ ||
773            bmColor.bmBitsPixel == exp_bpp /* Win98 */,
774            "bmColor.bmBitsPixel = %d\n", bmColor.bmBitsPixel);
775         ok_(__FILE__, line)(bmColor.bmWidth == exp_cx, "bmColor.bmWidth = %d\n", bmColor.bmWidth);
776         ok_(__FILE__, line)(bmColor.bmHeight == exp_cy, "bmColor.bmHeight = %d\n", bmColor.bmHeight);
777
778         ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
779         ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
780         ok_(__FILE__, line)(bmMask.bmHeight == exp_cy, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
781     }
782     else
783     {
784         ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
785         ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
786         ok_(__FILE__, line)(bmMask.bmHeight == exp_cy * 2, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
787     }
788     if (pGetIconInfoExA)
789     {
790         ICONINFOEXA infoex;
791
792         memset( &infoex, 0xcc, sizeof(infoex) );
793         SetLastError( 0xdeadbeef );
794         infoex.cbSize = sizeof(infoex) - 1;
795         ret = pGetIconInfoExA( hIcon, &infoex );
796         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
797         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError());
798
799         SetLastError( 0xdeadbeef );
800         infoex.cbSize = sizeof(infoex) + 1;
801         ret = pGetIconInfoExA( hIcon, &infoex );
802         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
803         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError());
804
805         SetLastError( 0xdeadbeef );
806         infoex.cbSize = sizeof(infoex);
807         ret = pGetIconInfoExA( (HICON)0xdeadbabe, &infoex );
808         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
809         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_CURSOR_HANDLE,
810                             "wrong error %d\n", GetLastError());
811
812         infoex.cbSize = sizeof(infoex);
813         ret = pGetIconInfoExA( hIcon, &infoex );
814         ok_(__FILE__, line)(ret, "GetIconInfoEx failed err %d\n", GetLastError());
815         ok_(__FILE__, line)(infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID);
816         ok_(__FILE__, line)(infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName);
817         ok_(__FILE__, line)(infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName);
818     }
819 }
820
821 #define test_icon_info(a,b,c,d) test_icon_info_dbg((a),(b),(c),(d),__LINE__)
822
823 static void test_CreateIcon(void)
824 {
825     static const BYTE bmp_bits[1024];
826     HICON hIcon;
827     HBITMAP hbmMask, hbmColor;
828     BITMAPINFO *bmpinfo;
829     ICONINFO info;
830     HDC hdc;
831     void *bits;
832     UINT display_bpp;
833
834     hdc = GetDC(0);
835     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
836
837     /* these crash under XP
838     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
839     hIcon = CreateIcon(0, 16, 16, 1, 1, NULL, bmp_bits);
840     */
841
842     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
843     ok(hIcon != 0, "CreateIcon failed\n");
844     test_icon_info(hIcon, 16, 16, 1);
845     DestroyIcon(hIcon);
846
847     hIcon = CreateIcon(0, 16, 16, 1, display_bpp, bmp_bits, bmp_bits);
848     ok(hIcon != 0, "CreateIcon failed\n");
849     test_icon_info(hIcon, 16, 16, display_bpp);
850     DestroyIcon(hIcon);
851
852     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
853     ok(hbmMask != 0, "CreateBitmap failed\n");
854     hbmColor = CreateBitmap(16, 16, 1, display_bpp, bmp_bits);
855     ok(hbmColor != 0, "CreateBitmap failed\n");
856
857     info.fIcon = TRUE;
858     info.xHotspot = 8;
859     info.yHotspot = 8;
860     info.hbmMask = 0;
861     info.hbmColor = 0;
862     SetLastError(0xdeadbeaf);
863     hIcon = CreateIconIndirect(&info);
864     ok(!hIcon, "CreateIconIndirect should fail\n");
865     ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
866
867     info.fIcon = TRUE;
868     info.xHotspot = 8;
869     info.yHotspot = 8;
870     info.hbmMask = 0;
871     info.hbmColor = hbmColor;
872     SetLastError(0xdeadbeaf);
873     hIcon = CreateIconIndirect(&info);
874     ok(!hIcon, "CreateIconIndirect should fail\n");
875     ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
876
877     info.fIcon = TRUE;
878     info.xHotspot = 8;
879     info.yHotspot = 8;
880     info.hbmMask = hbmMask;
881     info.hbmColor = hbmColor;
882     hIcon = CreateIconIndirect(&info);
883     ok(hIcon != 0, "CreateIconIndirect failed\n");
884     test_icon_info(hIcon, 16, 16, display_bpp);
885     DestroyIcon(hIcon);
886
887     DeleteObject(hbmMask);
888     DeleteObject(hbmColor);
889
890     hbmMask = CreateBitmap(16, 32, 1, 1, bmp_bits);
891     ok(hbmMask != 0, "CreateBitmap failed\n");
892
893     info.fIcon = TRUE;
894     info.xHotspot = 8;
895     info.yHotspot = 8;
896     info.hbmMask = hbmMask;
897     info.hbmColor = 0;
898     SetLastError(0xdeadbeaf);
899     hIcon = CreateIconIndirect(&info);
900     ok(hIcon != 0, "CreateIconIndirect failed\n");
901     test_icon_info(hIcon, 16, 16, 1);
902     DestroyIcon(hIcon);
903
904     DeleteObject(hbmMask);
905     DeleteObject(hbmColor);
906
907     /* test creating an icon from a DIB section */
908
909     bmpinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO,bmiColors[256]));
910     bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
911     bmpinfo->bmiHeader.biWidth = 32;
912     bmpinfo->bmiHeader.biHeight = 32;
913     bmpinfo->bmiHeader.biPlanes = 1;
914     bmpinfo->bmiHeader.biBitCount = 8;
915     bmpinfo->bmiHeader.biCompression = BI_RGB;
916     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
917     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
918     if (bits)
919         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
920     bmpinfo->bmiHeader.biBitCount = 1;
921     hbmMask = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
922     ok(hbmMask != NULL, "Expected a handle to the DIB\n");
923     if (bits)
924         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
925
926     info.fIcon = TRUE;
927     info.xHotspot = 8;
928     info.yHotspot = 8;
929     info.hbmMask = hbmColor;
930     info.hbmColor = hbmMask;
931     SetLastError(0xdeadbeaf);
932     hIcon = CreateIconIndirect(&info);
933     ok(hIcon != 0, "CreateIconIndirect failed\n");
934     test_icon_info(hIcon, 32, 32, 8);
935     DestroyIcon(hIcon);
936     DeleteObject(hbmColor);
937
938     bmpinfo->bmiHeader.biBitCount = 16;
939     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
940     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
941     if (bits)
942         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
943
944     info.fIcon = TRUE;
945     info.xHotspot = 8;
946     info.yHotspot = 8;
947     info.hbmMask = hbmColor;
948     info.hbmColor = hbmMask;
949     SetLastError(0xdeadbeaf);
950     hIcon = CreateIconIndirect(&info);
951     ok(hIcon != 0, "CreateIconIndirect failed\n");
952     test_icon_info(hIcon, 32, 32, 8);
953     DestroyIcon(hIcon);
954     DeleteObject(hbmColor);
955
956     bmpinfo->bmiHeader.biBitCount = 32;
957     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
958     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
959     if (bits)
960         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
961
962     info.fIcon = TRUE;
963     info.xHotspot = 8;
964     info.yHotspot = 8;
965     info.hbmMask = hbmColor;
966     info.hbmColor = hbmMask;
967     SetLastError(0xdeadbeaf);
968     hIcon = CreateIconIndirect(&info);
969     ok(hIcon != 0, "CreateIconIndirect failed\n");
970     test_icon_info(hIcon, 32, 32, 8);
971     DestroyIcon(hIcon);
972
973     DeleteObject(hbmMask);
974     DeleteObject(hbmColor);
975     HeapFree( GetProcessHeap(), 0, bmpinfo );
976
977     ReleaseDC(0, hdc);
978 }
979
980 /* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */
981 /* 1x1 pixel gif */
982 static unsigned char gifimage[35] = {
983 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
984 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
985 0x01,0x00,0x3b
986 };
987
988 /* 1x1 pixel jpg */
989 static unsigned char jpgimage[285] = {
990 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
991 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
992 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
993 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
994 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
995 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
996 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
997 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
998 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
999 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
1000 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
1001 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1002 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
1003 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
1004 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
1005 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
1006 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
1007 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
1008 };
1009
1010 /* 1x1 pixel png */
1011 static unsigned char pngimage[285] = {
1012 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1013 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1014 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1015 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1016 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1017 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1018 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1019 };
1020
1021 /* 1x1 pixel bmp with gap between palette and bitmap. Correct bitmap contains only
1022    zeroes, gap is 0xFF. */
1023 static unsigned char bmpimage[70] = {
1024 0x42,0x4d,0x46,0x00,0x00,0x00,0xDE,0xAD,0xBE,0xEF,0x42,0x00,0x00,0x00,0x28,0x00,
1025 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1026 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1027 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x55,0x55,0x55,0x00,0xFF,0xFF,
1028 0xFF,0xFF,0x00,0x00,0x00,0x00
1029 };
1030
1031 /* 1x1 pixel bmp using BITMAPCOREHEADER */
1032 static unsigned char bmpcoreimage[38] = {
1033 0x42,0x4d,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x0c,0x00,
1034 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xff,0xff,0xff,0x00,0x55,0x55,
1035 0x55,0x00,0x00,0x00,0x00,0x00
1036 };
1037
1038 /* 2x2 pixel gif */
1039 static unsigned char gif4pixel[42] = {
1040 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
1041 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
1042 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
1043 };
1044
1045 static const DWORD biSize_tests[] = {
1046     0,
1047     sizeof(BITMAPCOREHEADER) - 1,
1048     sizeof(BITMAPCOREHEADER) + 1,
1049     sizeof(BITMAPINFOHEADER) - 1,
1050     sizeof(BITMAPINFOHEADER) + 1,
1051     sizeof(BITMAPV4HEADER) - 1,
1052     sizeof(BITMAPV4HEADER) + 1,
1053     sizeof(BITMAPV5HEADER) - 1,
1054     sizeof(BITMAPV5HEADER) + 1,
1055     (sizeof(BITMAPCOREHEADER) + sizeof(BITMAPINFOHEADER)) / 2,
1056     (sizeof(BITMAPV4HEADER) + sizeof(BITMAPV5HEADER)) / 2,
1057     0xdeadbeef,
1058     0xffffffff
1059 };
1060
1061 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
1062
1063 static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm)
1064 {
1065     BITMAP bm;
1066     BITMAPINFO bmi;
1067     DWORD ret, pixel = 0;
1068     HDC hdc = GetDC(NULL);
1069
1070     ret = GetObject(hbm, sizeof(bm), &bm);
1071     ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
1072
1073     memset(&bmi, 0, sizeof(bmi));
1074     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1075     bmi.bmiHeader.biWidth = bm.bmWidth;
1076     bmi.bmiHeader.biHeight = bm.bmHeight;
1077     bmi.bmiHeader.biPlanes = 1;
1078     bmi.bmiHeader.biBitCount= 24;
1079     bmi.bmiHeader.biCompression= BI_RGB;
1080     ret = GetDIBits(hdc, hbm, 0, bm.bmHeight, &pixel, &bmi, DIB_RGB_COLORS);
1081     ok(ret == bm.bmHeight, "%s: %d lines were converted, not %d\n", test_desc, ret, bm.bmHeight);
1082
1083     ok(color_match(pixel, 0x00ffffff), "%s: Pixel is 0x%08x\n", test_desc, pixel);
1084 }
1085
1086 static void test_LoadImageFile(const char * test_desc, unsigned char * image_data,
1087     unsigned int image_size, const char * ext, BOOL expect_success)
1088 {
1089     HANDLE handle;
1090     BOOL ret;
1091     DWORD error, bytes_written;
1092     char filename[64];
1093
1094     strcpy(filename, "test.");
1095     strcat(filename, ext);
1096
1097     /* Create the test image. */
1098     handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW,
1099         FILE_ATTRIBUTE_NORMAL, NULL);
1100     ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1101     ret = WriteFile(handle, image_data, image_size, &bytes_written, NULL);
1102     ok(ret && bytes_written == image_size, "test file created improperly.\n");
1103     CloseHandle(handle);
1104
1105     /* Load as cursor. For all tested formats, this should fail */
1106     SetLastError(0xdeadbeef);
1107     handle = LoadImageA(NULL, filename, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1108     ok(handle == NULL, "%s: IMAGE_CURSOR succeeded incorrectly.\n", test_desc);
1109     error = GetLastError();
1110     ok(error == 0 ||
1111         broken(error == 0xdeadbeef) || /* Win9x */
1112         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1113         "Last error: %u\n", error);
1114     if (handle != NULL) DestroyCursor(handle);
1115
1116     /* Load as icon. For all tested formats, this should fail */
1117     SetLastError(0xdeadbeef);
1118     handle = LoadImageA(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
1119     ok(handle == NULL, "%s: IMAGE_ICON succeeded incorrectly.\n", test_desc);
1120     error = GetLastError();
1121     ok(error == 0 ||
1122         broken(error == 0xdeadbeef) || /* Win9x */
1123         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1124         "Last error: %u\n", error);
1125     if (handle != NULL) DestroyIcon(handle);
1126
1127     /* Load as bitmap. Should succeed for correct bmp, fail for everything else */
1128     SetLastError(0xdeadbeef);
1129     handle = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
1130     error = GetLastError();
1131     ok(error == 0 ||
1132         error == 0xdeadbeef, /* Win9x, WinMe */
1133         "Last error: %u\n", error);
1134
1135     if (expect_success) {
1136         ok(handle != NULL, "%s: IMAGE_BITMAP failed.\n", test_desc);
1137         if (handle != NULL) test_LoadImageBitmap(test_desc, handle);
1138     }
1139     else ok(handle == NULL, "%s: IMAGE_BITMAP succeeded incorrectly.\n", test_desc);
1140
1141     if (handle != NULL) DeleteObject(handle);
1142     DeleteFileA(filename);
1143 }
1144
1145 static void test_LoadImage(void)
1146 {
1147     HANDLE handle;
1148     BOOL ret;
1149     DWORD error, bytes_written;
1150     CURSORICONFILEDIR *icon_data;
1151     CURSORICONFILEDIRENTRY *icon_entry;
1152     BITMAPINFOHEADER *icon_header, *bitmap_header;
1153     ICONINFO icon_info;
1154     int i;
1155
1156 #define ICON_WIDTH 32
1157 #define ICON_HEIGHT 32
1158 #define ICON_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1159 #define ICON_BPP 32
1160 #define ICON_SIZE \
1161     (sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) \
1162     + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1163
1164     /* Set icon data. */
1165     icon_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ICON_SIZE);
1166     icon_data->idReserved = 0;
1167     icon_data->idType = 1;
1168     icon_data->idCount = 1;
1169
1170     icon_entry = icon_data->idEntries;
1171     icon_entry->bWidth = ICON_WIDTH;
1172     icon_entry->bHeight = ICON_HEIGHT;
1173     icon_entry->bColorCount = 0;
1174     icon_entry->bReserved = 0;
1175     icon_entry->xHotspot = 1;
1176     icon_entry->yHotspot = 1;
1177     icon_entry->dwDIBSize = ICON_SIZE - sizeof(CURSORICONFILEDIR);
1178     icon_entry->dwDIBOffset = sizeof(CURSORICONFILEDIR);
1179
1180     icon_header = (BITMAPINFOHEADER *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
1181     icon_header->biSize = sizeof(BITMAPINFOHEADER);
1182     icon_header->biWidth = ICON_WIDTH;
1183     icon_header->biHeight = ICON_HEIGHT*2;
1184     icon_header->biPlanes = 1;
1185     icon_header->biBitCount = ICON_BPP;
1186     icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1187
1188     /* Create the icon. */
1189     handle = CreateFileA("icon.ico", GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW,
1190         FILE_ATTRIBUTE_NORMAL, NULL);
1191     ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1192     ret = WriteFile(handle, icon_data, ICON_SIZE, &bytes_written, NULL);
1193     ok(ret && bytes_written == ICON_SIZE, "icon.ico created improperly.\n");
1194     CloseHandle(handle);
1195
1196     /* Test loading an icon as a cursor. */
1197     SetLastError(0xdeadbeef);
1198     handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1199     ok(handle != NULL, "LoadImage() failed.\n");
1200     error = GetLastError();
1201     ok(error == 0 ||
1202         broken(error == 0xdeadbeef) || /* Win9x */
1203         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1204         "Last error: %u\n", error);
1205
1206     /* Test the icon information. */
1207     SetLastError(0xdeadbeef);
1208     ret = GetIconInfo(handle, &icon_info);
1209     ok(ret, "GetIconInfo() failed.\n");
1210     error = GetLastError();
1211     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1212
1213     if (ret)
1214     {
1215         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1216         ok(icon_info.xHotspot == 1, "xHotspot is %u.\n", icon_info.xHotspot);
1217         ok(icon_info.yHotspot == 1, "yHotspot is %u.\n", icon_info.yHotspot);
1218         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1219            "No hbmColor!\n");
1220         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1221     }
1222
1223     if (pGetIconInfoExA)
1224     {
1225         ICONINFOEXA infoex;
1226         infoex.cbSize = sizeof(infoex);
1227         ret = pGetIconInfoExA( handle, &infoex );
1228         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1229         ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1230         ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1231         ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1232     }
1233     else win_skip( "GetIconInfoEx not available\n" );
1234
1235     /* Clean up. */
1236     SetLastError(0xdeadbeef);
1237     ret = DestroyCursor(handle);
1238     ok(ret, "DestroyCursor() failed.\n");
1239     error = GetLastError();
1240     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1241
1242     HeapFree(GetProcessHeap(), 0, icon_data);
1243     DeleteFileA("icon.ico");
1244
1245     /* Test a system icon */
1246     handle = LoadIcon( 0, IDI_HAND );
1247     ok(handle != NULL, "LoadImage() failed.\n");
1248     if (pGetIconInfoExA)
1249     {
1250         ICONINFOEXA infoexA;
1251         ICONINFOEXW infoexW;
1252         infoexA.cbSize = sizeof(infoexA);
1253         ret = pGetIconInfoExA( handle, &infoexA );
1254         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1255         ok( infoexA.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexA.wResID );
1256         /* the A version is broken on 64-bit, it truncates the string after the first char */
1257         if (is_win64 && infoexA.szModName[0] && infoexA.szModName[1] == 0)
1258             trace( "GetIconInfoExA broken on Win64\n" );
1259         else
1260             ok( GetModuleHandleA(infoexA.szModName) == GetModuleHandleA("user32.dll"),
1261                 "GetIconInfoEx wrong module %s\n", infoexA.szModName );
1262         ok( infoexA.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoexA.szResName );
1263         infoexW.cbSize = sizeof(infoexW);
1264         ret = pGetIconInfoExW( handle, &infoexW );
1265         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1266         ok( infoexW.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexW.wResID );
1267         ok( GetModuleHandleW(infoexW.szModName) == GetModuleHandleA("user32.dll"),
1268             "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(infoexW.szModName) );
1269         ok( infoexW.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", wine_dbgstr_w(infoexW.szResName) );
1270     }
1271     SetLastError(0xdeadbeef);
1272     DestroyIcon(handle);
1273
1274     test_LoadImageFile("BMP", bmpimage, sizeof(bmpimage), "bmp", 1);
1275     test_LoadImageFile("BMP (coreinfo)", bmpcoreimage, sizeof(bmpcoreimage), "bmp", 1);
1276     test_LoadImageFile("GIF", gifimage, sizeof(gifimage), "gif", 0);
1277     test_LoadImageFile("GIF (2x2 pixel)", gif4pixel, sizeof(gif4pixel), "gif", 0);
1278     test_LoadImageFile("JPG", jpgimage, sizeof(jpgimage), "jpg", 0);
1279     test_LoadImageFile("PNG", pngimage, sizeof(pngimage), "png", 0);
1280
1281     /* Check failure for broken BMP images */
1282     bitmap_header = (BITMAPINFOHEADER *)(bmpimage + sizeof(BITMAPFILEHEADER));
1283
1284     bitmap_header->biHeight = 65536;
1285     test_LoadImageFile("BMP (too high)", bmpimage, sizeof(bmpimage), "bmp", 0);
1286     bitmap_header->biHeight = 1;
1287
1288     bitmap_header->biWidth = 65536;
1289     test_LoadImageFile("BMP (too wide)", bmpimage, sizeof(bmpimage), "bmp", 0);
1290     bitmap_header->biWidth = 1;
1291
1292     for (i = 0; i < ARRAY_SIZE(biSize_tests); i++) {
1293         bitmap_header->biSize = biSize_tests[i];
1294         test_LoadImageFile("BMP (broken biSize)", bmpimage, sizeof(bmpimage), "bmp", 0);
1295     }
1296     bitmap_header->biSize = sizeof(BITMAPINFOHEADER);
1297 }
1298
1299 #undef ARRAY_SIZE
1300
1301 static void test_CreateIconFromResource(void)
1302 {
1303     HANDLE handle;
1304     BOOL ret;
1305     DWORD error;
1306     BITMAPINFOHEADER *icon_header;
1307     INT16 *hotspot;
1308     ICONINFO icon_info;
1309
1310 #define ICON_RES_WIDTH 32
1311 #define ICON_RES_HEIGHT 32
1312 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1313 #define ICON_RES_BPP 32
1314 #define ICON_RES_SIZE \
1315     (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1316 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1317
1318     /* Set icon data. */
1319     hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE);
1320
1321     /* Cursor resources have an extra hotspot, icon resources not. */
1322     hotspot[0] = 3;
1323     hotspot[1] = 3;
1324
1325     icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1326     icon_header->biSize = sizeof(BITMAPINFOHEADER);
1327     icon_header->biWidth = ICON_WIDTH;
1328     icon_header->biHeight = ICON_HEIGHT*2;
1329     icon_header->biPlanes = 1;
1330     icon_header->biBitCount = ICON_BPP;
1331     icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1332
1333     /* Test creating a cursor. */
1334     SetLastError(0xdeadbeef);
1335     handle = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1336     ok(handle != NULL, "Create cursor failed.\n");
1337
1338     /* Test the icon information. */
1339     SetLastError(0xdeadbeef);
1340     ret = GetIconInfo(handle, &icon_info);
1341     ok(ret, "GetIconInfo() failed.\n");
1342     error = GetLastError();
1343     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1344
1345     if (ret)
1346     {
1347         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1348         ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1349         ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1350         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1351            "No hbmColor!\n");
1352         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1353     }
1354
1355     if (pGetIconInfoExA)
1356     {
1357         ICONINFOEXA infoex;
1358         infoex.cbSize = sizeof(infoex);
1359         ret = pGetIconInfoExA( handle, &infoex );
1360         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1361         ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1362         ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1363         ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1364     }
1365
1366     /* Clean up. */
1367     SetLastError(0xdeadbeef);
1368     ret = DestroyCursor(handle);
1369     ok(ret, "DestroyCursor() failed.\n");
1370     error = GetLastError();
1371     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1372
1373     /* Test creating an icon. */
1374     SetLastError(0xdeadbeef);
1375     handle = CreateIconFromResource((PBYTE) icon_header, ICON_RES_SIZE, TRUE,
1376                                     0x00030000);
1377     ok(handle != NULL, "Create icon failed.\n");
1378
1379     /* Test the icon information. */
1380     SetLastError(0xdeadbeef);
1381     ret = GetIconInfo(handle, &icon_info);
1382     ok(ret, "GetIconInfo() failed.\n");
1383     error = GetLastError();
1384     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1385
1386     if (ret)
1387     {
1388         ok(icon_info.fIcon == TRUE, "fIcon != TRUE.\n");
1389         /* Icons always have hotspot in the middle */
1390         ok(icon_info.xHotspot == ICON_WIDTH/2, "xHotspot is %u.\n", icon_info.xHotspot);
1391         ok(icon_info.yHotspot == ICON_HEIGHT/2, "yHotspot is %u.\n", icon_info.yHotspot);
1392         ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
1393         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1394     }
1395
1396     /* Clean up. */
1397     SetLastError(0xdeadbeef);
1398     ret = DestroyCursor(handle);
1399     ok(ret, "DestroyCursor() failed.\n");
1400     error = GetLastError();
1401     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1402
1403     /* Rejection of NULL pointer crashes at least on WNT4WSSP6, W2KPROSP4, WXPPROSP3
1404      *
1405      * handle = CreateIconFromResource(NULL, ICON_RES_SIZE, TRUE, 0x00030000);
1406      * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
1407      */
1408     HeapFree(GetProcessHeap(), 0, hotspot);
1409
1410     /* Test creating an animated cursor. */
1411     empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1412     empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
1413     empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
1414     handle = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
1415     ok(handle != NULL, "Create cursor failed.\n");
1416
1417     /* Test the animated cursor's information. */
1418     SetLastError(0xdeadbeef);
1419     ret = GetIconInfo(handle, &icon_info);
1420     ok(ret, "GetIconInfo() failed.\n");
1421     error = GetLastError();
1422     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1423
1424     if (ret)
1425     {
1426         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1427         ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1428         ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1429         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1430            "No hbmColor!\n");
1431         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1432     }
1433
1434     /* Clean up. */
1435     SetLastError(0xdeadbeef);
1436     ret = DestroyCursor(handle);
1437     ok(ret, "DestroyCursor() failed.\n");
1438     error = GetLastError();
1439     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1440 }
1441
1442 static HCURSOR WINAPI (*pGetCursorFrameInfo)(HCURSOR hCursor, VOID *unk1, VOID *unk2, VOID *unk3, VOID *unk4);
1443 static void test_GetCursorFrameInfo(void)
1444 {
1445     DWORD unk1, unk2, unk3, unk4;
1446     BITMAPINFOHEADER *icon_header;
1447     INT16 *hotspot;
1448     HANDLE h1, h2;
1449     BOOL ret;
1450
1451     if (!pGetCursorFrameInfo)
1452     {
1453         win_skip( "GetCursorFrameInfo not supported, skipping tests.\n" );
1454         return;
1455     }
1456 #define ICON_RES_WIDTH 32
1457 #define ICON_RES_HEIGHT 32
1458 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1459 #define ICON_RES_BPP 32
1460 #define ICON_RES_SIZE \
1461     (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1462 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1463
1464     /* Set icon data. */
1465     hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE);
1466
1467     /* Cursor resources have an extra hotspot, icon resources not. */
1468     hotspot[0] = 3;
1469     hotspot[1] = 3;
1470
1471     icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1472     icon_header->biSize = sizeof(BITMAPINFOHEADER);
1473     icon_header->biWidth = ICON_WIDTH;
1474     icon_header->biHeight = ICON_HEIGHT*2;
1475     icon_header->biPlanes = 1;
1476     icon_header->biBitCount = ICON_BPP;
1477     icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1478
1479     /* Creating a static cursor. */
1480     SetLastError(0xdeadbeef);
1481     h1 = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1482     ok(h1 != NULL, "Create cursor failed.\n");
1483
1484     /* Check GetCursorFrameInfo behavior on a static cursor */
1485     unk1 = unk2 = unk3 = unk4 = 0xdead;
1486     h2 = pGetCursorFrameInfo(h1, &unk1, &unk2, &unk3, &unk4);
1487     ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1488     ok(unk1 == 0xdead, "GetCursorFrameInfo() unexpected param 2 value (%d != 0xdead).\n", unk1);
1489     ok(unk2 == 0xdead, "GetCursorFrameInfo() unexpected param 3 value (%d != 0xdead).\n", unk2);
1490     ok(unk3 == 0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", unk3);
1491     ok(unk4 == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", unk4);
1492
1493     /* Clean up static cursor. */
1494     ret = DestroyCursor(h1);
1495     ok(ret, "DestroyCursor() failed.\n");
1496
1497     /* Creating a single-frame animated cursor. */
1498     empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1499     empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
1500     empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
1501     h1 = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor3), FALSE, 0x00030000);
1502     ok(h1 != NULL, "Create cursor failed.\n");
1503
1504     /* Check GetCursorFrameInfo behavior on a single-frame animated cursor */
1505     unk1 = unk2 = unk3 = unk4 = 0xdead;
1506     h2 = pGetCursorFrameInfo(h1, &unk1, (VOID*)0, &unk3, &unk4);
1507     ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1508     ok(unk1 == 0xdead, "GetCursorFrameInfo() unexpected param 2 value (%d != 0xdead).\n", unk1);
1509     ok(unk2 == 0xdead, "GetCursorFrameInfo() unexpected param 3 value (%d != 0xdead).\n", unk2);
1510     ok(unk3 == 0x0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", unk3);
1511     ok(unk4 == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", unk4);
1512
1513     /* Clean up single-frame animated cursor. */
1514     ret = DestroyCursor(h1);
1515     ok(ret, "DestroyCursor() failed.\n");
1516
1517     /* Creating a multi-frame animated cursor. */
1518     empty_anicursor3.frames[0].data.icon_info.idType = 2; /* type: cursor */
1519     empty_anicursor3.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
1520     empty_anicursor3.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
1521     empty_anicursor3.frames[1].data.icon_info.idType = 2; /* type: cursor */
1522     empty_anicursor3.frames[1].data.icon_info.idEntries[0].xHotspot = 3;
1523     empty_anicursor3.frames[1].data.icon_info.idEntries[0].yHotspot = 3;
1524     empty_anicursor3.frames[2].data.icon_info.idType = 2; /* type: cursor */
1525     empty_anicursor3.frames[2].data.icon_info.idEntries[0].xHotspot = 3;
1526     empty_anicursor3.frames[2].data.icon_info.idEntries[0].yHotspot = 3;
1527     h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1528     ok(h1 != NULL, "Create cursor failed.\n");
1529
1530     /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor */
1531     unk1 = unk2 = unk3 = unk4 = 0xdead;
1532     h2 = pGetCursorFrameInfo(h1, &unk1, (VOID*)0, &unk3, &unk4);
1533     ok(h2 != 0, "GetCursorFrameInfo() failed: (%p != 0).\n", h2);
1534     ok(unk1 == 0xdead, "GetCursorFrameInfo() unexpected param 2 value (%d != 0xdead).\n", unk1);
1535     ok(unk2 == 0xdead, "GetCursorFrameInfo() unexpected param 3 value (%d != 0xdead).\n", unk2);
1536     ok(unk3 == 0xbeef, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xbeef).\n", unk3);
1537     ok(unk4 == ~0 || broken(unk4 == 1) /*win2k*/, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", unk4);
1538
1539     /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor */
1540     unk1 = unk2 = unk3 = unk4 = 0xdead;
1541     h2 = pGetCursorFrameInfo(h1, &unk1, (VOID*)1, &unk3, &unk4);
1542     ok(h2 == 0, "GetCursorFrameInfo() failed: (%p != 0).\n", h2);
1543     ok(unk1 == 0xdead, "GetCursorFrameInfo() unexpected param 2 value (%d != 0xdead).\n", unk1);
1544     ok(unk2 == 0xdead, "GetCursorFrameInfo() unexpected param 3 value (%d != 0xdead).\n", unk2);
1545     ok(unk3 == 0xdead || broken(unk3 == 0xbeef) /*win2k*/, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", unk3);
1546     ok(unk4 == 0xdead || broken(unk4 == 1) /*win2k*/, "GetCursorFrameInfo() unexpected param 5 value (%d != 0xdead).\n", unk4);
1547
1548     /* Clean up multi-frame animated cursor. */
1549     ret = DestroyCursor(h1);
1550     ok(ret, "DestroyCursor() failed.\n");
1551
1552 }
1553
1554 static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
1555                               BOOL maskvalue, UINT32 *color, int colorSize)
1556 {
1557     ICONINFO iconInfo;
1558     BITMAPINFO bitmapInfo;
1559     void *buffer = NULL;
1560     UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000;
1561
1562     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1563     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1564     bitmapInfo.bmiHeader.biWidth = width;
1565     bitmapInfo.bmiHeader.biHeight = height;
1566     bitmapInfo.bmiHeader.biPlanes = 1;
1567     bitmapInfo.bmiHeader.biBitCount = bpp;
1568     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1569     bitmapInfo.bmiHeader.biSizeImage = colorSize;
1570
1571     iconInfo.fIcon = TRUE;
1572     iconInfo.xHotspot = 0;
1573     iconInfo.yHotspot = 0;
1574
1575     iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask );
1576     if(!iconInfo.hbmMask) return NULL;
1577
1578     iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &buffer, NULL, 0);
1579     if(!iconInfo.hbmColor || !buffer)
1580     {
1581         DeleteObject(iconInfo.hbmMask);
1582         return NULL;
1583     }
1584
1585     memcpy(buffer, color, colorSize);
1586
1587     return CreateIconIndirect(&iconInfo);
1588 }
1589
1590 static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
1591 {
1592     HICON hicon;
1593     UINT32 color[2];
1594     COLORREF modern_expected, legacy_expected, result;
1595
1596     color[0] = 0x00A0B0C0;
1597     color[1] = alpha ? 0xFF000000 : 0x00000000;
1598     modern_expected = alpha ? 0x00FFFFFF : 0x00C0B0A0;
1599     legacy_expected = 0x00C0B0A0;
1600
1601     hicon = create_test_icon(hdc, 2, 1, bpp, 0, color, sizeof(color));
1602     if (!hicon) return;
1603
1604     SetPixelV(hdc, 0, 0, 0x00FFFFFF);
1605
1606     if(drawiconex)
1607         DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL);
1608     else
1609         DrawIcon(hdc, 0, 0, hicon);
1610
1611     result = GetPixel(hdc, 0, 0);
1612     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1613         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1614         "%s. Expected a close match to %06X (modern) or %06X (legacy) with %s. "
1615         "Got %06X from line %d\n",
1616         alpha ? "Alpha blending" : "Not alpha blending", modern_expected, legacy_expected,
1617         drawiconex ? "DrawIconEx" : "DrawIcon", result, line);
1618 }
1619
1620 static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
1621                            COLORREF modern_expected, COLORREF legacy_expected, int line)
1622 {
1623     COLORREF result;
1624     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1625     if (!hicon) return;
1626     SetPixelV(hdc, 0, 0, background);
1627     SetPixelV(hdc, GetSystemMetrics(SM_CXICON)-1, GetSystemMetrics(SM_CYICON)-1, background);
1628     SetPixelV(hdc, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), background);
1629     DrawIcon(hdc, 0, 0, hicon);
1630     result = GetPixel(hdc, 0, 0);
1631
1632     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1633         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1634         "Overlaying Mask %d on Color %06X with DrawIcon. "
1635         "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1636         maskvalue, color, modern_expected, legacy_expected, result, line);
1637
1638     result = GetPixel(hdc, GetSystemMetrics(SM_CXICON)-1, GetSystemMetrics(SM_CYICON)-1);
1639
1640     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1641         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1642         "Overlaying Mask %d on Color %06X with DrawIcon. "
1643         "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1644         maskvalue, color, modern_expected, legacy_expected, result, line);
1645
1646     result = GetPixel(hdc, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
1647
1648     ok (color_match(result, background),
1649         "Overlaying Mask %d on Color %06X with DrawIcon. "
1650         "Expected unchanged background color %06X. Got %06X from line %d\n",
1651         maskvalue, color, background, result, line);
1652 }
1653
1654 static void test_DrawIcon(void)
1655 {
1656     BITMAPINFO bitmapInfo;
1657     HDC hdcDst = NULL;
1658     HBITMAP bmpDst = NULL;
1659     HBITMAP bmpOld = NULL;
1660     void *bits = 0;
1661
1662     hdcDst = CreateCompatibleDC(0);
1663     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1664     if (!hdcDst)
1665         return;
1666
1667     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
1668     {
1669         skip("Windows will distort DrawIcon colors at 8-bpp and less due to palletizing.\n");
1670         goto cleanup;
1671     }
1672
1673     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1674     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1675     bitmapInfo.bmiHeader.biWidth = GetSystemMetrics(SM_CXICON)+1;
1676     bitmapInfo.bmiHeader.biHeight = GetSystemMetrics(SM_CYICON)+1;
1677     bitmapInfo.bmiHeader.biBitCount = 32;
1678     bitmapInfo.bmiHeader.biPlanes = 1;
1679     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1680     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1681
1682     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1683     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1684     if (!bmpDst || !bits)
1685         goto cleanup;
1686     bmpOld = SelectObject(hdcDst, bmpDst);
1687
1688     /* Mask is only heeded if alpha channel is always zero */
1689     check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1690     check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
1691
1692     /* Test alpha blending */
1693     /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
1694     check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1695     check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
1696
1697     check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1698     check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1699     check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
1700     check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
1701
1702     check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1703     check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1704
1705     /* Test detecting of alpha channel */
1706     /* If a single pixel's alpha channel is non-zero, the icon
1707        will be alpha blended, otherwise it will be draw with
1708        and + xor blts. */
1709     check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__);
1710     check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__);
1711
1712 cleanup:
1713     if(bmpOld)
1714         SelectObject(hdcDst, bmpOld);
1715     if(bmpDst)
1716         DeleteObject(bmpDst);
1717     if(hdcDst)
1718         DeleteDC(hdcDst);
1719 }
1720
1721 static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background,
1722                              COLORREF modern_expected, COLORREF legacy_expected, int line)
1723 {
1724     COLORREF result;
1725     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1726     if (!hicon) return;
1727     SetPixelV(hdc, 0, 0, background);
1728     DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags);
1729     result = GetPixel(hdc, 0, 0);
1730
1731     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1732         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1733         "Overlaying Mask %d on Color %06X with DrawIconEx flags %08X. "
1734         "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
1735         maskvalue, color, flags, modern_expected, legacy_expected, result, line);
1736 }
1737
1738 static void test_DrawIconEx(void)
1739 {
1740     BITMAPINFO bitmapInfo;
1741     HDC hdcDst = NULL;
1742     HBITMAP bmpDst = NULL;
1743     HBITMAP bmpOld = NULL;
1744     void *bits = 0;
1745
1746     hdcDst = CreateCompatibleDC(0);
1747     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1748     if (!hdcDst)
1749         return;
1750
1751     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
1752     {
1753         skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palletizing.\n");
1754         goto cleanup;
1755     }
1756
1757     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1758     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1759     bitmapInfo.bmiHeader.biWidth = 1;
1760     bitmapInfo.bmiHeader.biHeight = 1;
1761     bitmapInfo.bmiHeader.biBitCount = 32;
1762     bitmapInfo.bmiHeader.biPlanes = 1;
1763     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1764     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1765     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1766     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1767     if (!bmpDst || !bits)
1768         goto cleanup;
1769     bmpOld = SelectObject(hdcDst, bmpDst);
1770
1771     /* Test null, image only, and mask only drawing */
1772     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
1773     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
1774
1775     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00000000, 0x00000000, __LINE__);
1776     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00FFFFFF, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
1777
1778     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1779     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1780
1781     /* Test normal drawing */
1782     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1783     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
1784     check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1785
1786     /* Test alpha blending */
1787     /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
1788     check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
1789
1790     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1791     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1792     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
1793     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
1794
1795     check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1796     check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1797
1798     /* Test detecting of alpha channel */
1799     /* If a single pixel's alpha channel is non-zero, the icon
1800        will be alpha blended, otherwise it will be draw with
1801        and + xor blts. */
1802     check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
1803     check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
1804
1805 cleanup:
1806     if(bmpOld)
1807         SelectObject(hdcDst, bmpOld);
1808     if(bmpDst)
1809         DeleteObject(bmpDst);
1810     if(hdcDst)
1811         DeleteDC(hdcDst);
1812 }
1813
1814 static void check_DrawState_Size(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags, int line)
1815 {
1816     COLORREF result, background;
1817     BOOL passed[2];
1818     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1819     background = 0x00FFFFFF;
1820     /* Set color of the 2 pixels that will be checked afterwards */
1821     SetPixelV(hdc, 0, 0, background);
1822     SetPixelV(hdc, 2, 2, background);
1823
1824     /* Let DrawState calculate the size of the icon (it's 1x1) */
1825     DrawState(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, (DST_ICON | flags ));
1826
1827     result = GetPixel(hdc, 0, 0);
1828     passed[0] = color_match(result, background);
1829     result = GetPixel(hdc, 2, 2);
1830     passed[0] = passed[0] & color_match(result, background);
1831
1832     /* Check if manually specifying the icon size DOESN'T work */
1833
1834     /* IMPORTANT: For Icons, DrawState wants the size of the source image, not the
1835      *            size in which it should be ultimately drawn. Therefore giving
1836      *            width/height 2x2 if the icon is only 1x1 pixels in size should
1837      *            result in drawing it with size 1x1. The size parameters must be
1838      *            ignored if a Icon has to be drawn! */
1839     DrawState(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 2, 2, (DST_ICON | flags ));
1840
1841     result = GetPixel(hdc, 0, 0);
1842     passed[1] = color_match(result, background);
1843     result = GetPixel(hdc, 2, 2);
1844     passed[1] = passed[0] & color_match(result, background);
1845
1846     if(!passed[0]&&!passed[1])
1847         ok (passed[1],
1848         "DrawState failed to draw a 1x1 Icon in the correct size, independent of the "
1849         "width and height settings passed to it, for Icon with: Overlaying Mask %d on "
1850         "Color %06X with flags %08X. Line %d\n",
1851         maskvalue, color, (DST_ICON | flags), line);
1852     else if(!passed[1])
1853         ok (passed[1],
1854         "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
1855         "parameters passed to it are bigger than the real Icon size, for Icon with: Overlaying "
1856         "Mask %d on Color %06X with flags %08X. Line %d\n",
1857         maskvalue, color, (DST_ICON | flags), line);
1858     else
1859         ok (passed[0],
1860         "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
1861         "parameters passed to it are 0, for Icon with: Overlaying Mask %d on "
1862         "Color %06X with flags %08X. Line %d\n",
1863         maskvalue, color, (DST_ICON | flags), line);
1864 }
1865
1866 static void check_DrawState_Color(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags,
1867                              COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
1868 {
1869     COLORREF result;
1870     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1871     if (!hicon) return;
1872     /* Set color of the pixel that will be checked afterwards */
1873     SetPixelV(hdc, 1, 1, background);
1874
1875     DrawState(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, ( DST_ICON | flags ));
1876
1877     /* Check the color of the pixel is correct */
1878     result = GetPixel(hdc, 1, 1);
1879
1880     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1881         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1882         "DrawState drawing Icon with Overlaying Mask %d on Color %06X with flags %08X. "
1883         "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
1884         maskvalue, color, (DST_ICON | flags), modern_expected, legacy_expected, result, line);
1885 }
1886
1887 static void test_DrawState(void)
1888 {
1889     BITMAPINFO bitmapInfo;
1890     HDC hdcDst = NULL;
1891     HBITMAP bmpDst = NULL;
1892     HBITMAP bmpOld = NULL;
1893     void *bits = 0;
1894
1895     hdcDst = CreateCompatibleDC(0);
1896     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1897     if (!hdcDst)
1898         return;
1899
1900     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
1901     {
1902         skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palletizing.\n");
1903         goto cleanup;
1904     }
1905
1906     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1907     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1908     bitmapInfo.bmiHeader.biWidth = 3;
1909     bitmapInfo.bmiHeader.biHeight = 3;
1910     bitmapInfo.bmiHeader.biBitCount = 32;
1911     bitmapInfo.bmiHeader.biPlanes = 1;
1912     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1913     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1914     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1915     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1916     if (!bmpDst || !bits)
1917         goto cleanup;
1918     bmpOld = SelectObject(hdcDst, bmpDst);
1919
1920     /* potential flags to test with DrawState are: */
1921     /* DSS_DISABLED embosses the icon */
1922     /* DSS_MONO draw Icon using a brush as parameter 5 */
1923     /* DSS_NORMAL draw Icon without any modifications */
1924     /* DSS_UNION draw the Icon dithered */
1925
1926     check_DrawState_Size(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, __LINE__);
1927     check_DrawState_Color(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1928
1929 cleanup:
1930     if(bmpOld)
1931         SelectObject(hdcDst, bmpOld);
1932     if(bmpDst)
1933         DeleteObject(bmpDst);
1934     if(hdcDst)
1935         DeleteDC(hdcDst);
1936 }
1937
1938 static DWORD parent_id;
1939
1940 static DWORD CALLBACK set_cursor_thread( void *arg )
1941 {
1942     HCURSOR ret;
1943
1944     PeekMessage( 0, 0, 0, 0, PM_NOREMOVE );  /* create a msg queue */
1945     if (parent_id)
1946     {
1947         BOOL ret = AttachThreadInput( GetCurrentThreadId(), parent_id, TRUE );
1948         ok( ret, "AttachThreadInput failed\n" );
1949     }
1950     if (arg) ret = SetCursor( (HCURSOR)arg );
1951     else ret = GetCursor();
1952     return (DWORD_PTR)ret;
1953 }
1954
1955 static void test_SetCursor(void)
1956 {
1957     static const BYTE bmp_bits[4096];
1958     ICONINFO cursorInfo;
1959     HCURSOR cursor, old_cursor, global_cursor = 0;
1960     DWORD error, id, result;
1961     UINT display_bpp;
1962     HDC hdc;
1963     HANDLE thread;
1964     CURSORINFO info;
1965
1966     if (pGetCursorInfo)
1967     {
1968         memset( &info, 0, sizeof(info) );
1969         info.cbSize = sizeof(info);
1970         if (!pGetCursorInfo( &info ))
1971         {
1972             win_skip( "GetCursorInfo not working\n" );
1973             pGetCursorInfo = NULL;
1974         }
1975         else global_cursor = info.hCursor;
1976     }
1977     cursor = GetCursor();
1978     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
1979     WaitForSingleObject( thread, 1000 );
1980     GetExitCodeThread( thread, &result );
1981     ok( result == (DWORD_PTR)cursor, "wrong thread cursor %x/%p\n", result, cursor );
1982
1983     hdc = GetDC(0);
1984     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
1985     ReleaseDC(0, hdc);
1986
1987     cursorInfo.fIcon = FALSE;
1988     cursorInfo.xHotspot = 0;
1989     cursorInfo.yHotspot = 0;
1990     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
1991     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
1992
1993     cursor = CreateIconIndirect(&cursorInfo);
1994     ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
1995     old_cursor = SetCursor( cursor );
1996
1997     if (pGetCursorInfo)
1998     {
1999         info.cbSize = sizeof(info);
2000         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2001         /* global cursor doesn't change since we don't have a window */
2002         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2003             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2004     }
2005     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2006     WaitForSingleObject( thread, 1000 );
2007     GetExitCodeThread( thread, &result );
2008     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2009
2010     SetCursor( 0 );
2011     ok( GetCursor() == 0, "wrong cursor %p\n", GetCursor() );
2012     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2013     WaitForSingleObject( thread, 1000 );
2014     GetExitCodeThread( thread, &result );
2015     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2016
2017     thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2018     WaitForSingleObject( thread, 1000 );
2019     GetExitCodeThread( thread, &result );
2020     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2021     ok( GetCursor() == 0, "wrong cursor %p/0\n", GetCursor() );
2022
2023     parent_id = GetCurrentThreadId();
2024     thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2025     WaitForSingleObject( thread, 1000 );
2026     GetExitCodeThread( thread, &result );
2027     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2028     ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor );
2029
2030     if (pGetCursorInfo)
2031     {
2032         info.cbSize = sizeof(info);
2033         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2034         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2035             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2036     }
2037     SetCursor( old_cursor );
2038     DestroyCursor( cursor );
2039
2040     SetLastError( 0xdeadbeef );
2041     cursor = SetCursor( (HCURSOR)0xbadbad );
2042     error = GetLastError();
2043     ok( cursor == 0, "wrong cursor %p/0\n", cursor );
2044     ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ),  /* win9x */
2045         "wrong error %u\n", error );
2046
2047     if (pGetCursorInfo)
2048     {
2049         info.cbSize = sizeof(info);
2050         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2051         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2052             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2053     }
2054 }
2055
2056 static HANDLE event_start, event_next;
2057
2058 static DWORD CALLBACK show_cursor_thread( void *arg )
2059 {
2060     DWORD count = (DWORD_PTR)arg;
2061     int ret;
2062
2063     PeekMessage( 0, 0, 0, 0, PM_NOREMOVE );  /* create a msg queue */
2064     if (parent_id)
2065     {
2066         BOOL ret = AttachThreadInput( GetCurrentThreadId(), parent_id, TRUE );
2067         ok( ret, "AttachThreadInput failed\n" );
2068     }
2069     if (!count) ret = ShowCursor( FALSE );
2070     else while (count--) ret = ShowCursor( TRUE );
2071     SetEvent( event_start );
2072     WaitForSingleObject( event_next, 2000 );
2073     return ret;
2074 }
2075
2076 static void test_ShowCursor(void)
2077 {
2078     int count;
2079     DWORD id, result;
2080     HANDLE thread;
2081     CURSORINFO info;
2082
2083     if (pGetCursorInfo)
2084     {
2085         memset( &info, 0, sizeof(info) );
2086         info.cbSize = sizeof(info);
2087         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2088         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2089     }
2090
2091     event_start = CreateEvent( NULL, FALSE, FALSE, NULL );
2092     event_next = CreateEvent( NULL, FALSE, FALSE, NULL );
2093
2094     count = ShowCursor( TRUE );
2095     ok( count == 1, "wrong count %d\n", count );
2096     count = ShowCursor( TRUE );
2097     ok( count == 2, "wrong count %d\n", count );
2098     count = ShowCursor( FALSE );
2099     ok( count == 1, "wrong count %d\n", count );
2100     count = ShowCursor( FALSE );
2101     ok( count == 0, "wrong count %d\n", count );
2102     count = ShowCursor( FALSE );
2103     ok( count == -1, "wrong count %d\n", count );
2104     count = ShowCursor( FALSE );
2105     ok( count == -2, "wrong count %d\n", count );
2106
2107     if (pGetCursorInfo)
2108     {
2109         info.cbSize = sizeof(info);
2110         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2111         /* global show count is not affected since we don't have a window */
2112         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2113     }
2114
2115     parent_id = 0;
2116     thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2117     WaitForSingleObject( event_start, 1000 );
2118     count = ShowCursor( FALSE );
2119     ok( count == -3, "wrong count %d\n", count );
2120     SetEvent( event_next );
2121     WaitForSingleObject( thread, 1000 );
2122     GetExitCodeThread( thread, &result );
2123     ok( result == -1, "wrong thread count %d\n", result );
2124     count = ShowCursor( FALSE );
2125     ok( count == -4, "wrong count %d\n", count );
2126
2127     thread = CreateThread( NULL, 0, show_cursor_thread, (void *)1, 0, &id );
2128     WaitForSingleObject( event_start, 1000 );
2129     count = ShowCursor( TRUE );
2130     ok( count == -3, "wrong count %d\n", count );
2131     SetEvent( event_next );
2132     WaitForSingleObject( thread, 1000 );
2133     GetExitCodeThread( thread, &result );
2134     ok( result == 1, "wrong thread count %d\n", result );
2135     count = ShowCursor( TRUE );
2136     ok( count == -2, "wrong count %d\n", count );
2137
2138     parent_id = GetCurrentThreadId();
2139     thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2140     WaitForSingleObject( event_start, 1000 );
2141     count = ShowCursor( TRUE );
2142     ok( count == -2, "wrong count %d\n", count );
2143     SetEvent( event_next );
2144     WaitForSingleObject( thread, 1000 );
2145     GetExitCodeThread( thread, &result );
2146     ok( result == -3, "wrong thread count %d\n", result );
2147     count = ShowCursor( FALSE );
2148     ok( count == -2, "wrong count %d\n", count );
2149
2150     thread = CreateThread( NULL, 0, show_cursor_thread, (void *)3, 0, &id );
2151     WaitForSingleObject( event_start, 1000 );
2152     count = ShowCursor( TRUE );
2153     ok( count == 2, "wrong count %d\n", count );
2154     SetEvent( event_next );
2155     WaitForSingleObject( thread, 1000 );
2156     GetExitCodeThread( thread, &result );
2157     ok( result == 1, "wrong thread count %d\n", result );
2158     count = ShowCursor( FALSE );
2159     ok( count == -2, "wrong count %d\n", count );
2160
2161     if (pGetCursorInfo)
2162     {
2163         info.cbSize = sizeof(info);
2164         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2165         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2166     }
2167
2168     count = ShowCursor( TRUE );
2169     ok( count == -1, "wrong count %d\n", count );
2170     count = ShowCursor( TRUE );
2171     ok( count == 0, "wrong count %d\n", count );
2172
2173     if (pGetCursorInfo)
2174     {
2175         info.cbSize = sizeof(info);
2176         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2177         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2178     }
2179 }
2180
2181
2182 static void test_DestroyCursor(void)
2183 {
2184     static const BYTE bmp_bits[4096];
2185     ICONINFO cursorInfo, new_info;
2186     HCURSOR cursor, cursor2, new_cursor;
2187     BOOL ret;
2188     DWORD error;
2189     UINT display_bpp;
2190     HDC hdc;
2191
2192     hdc = GetDC(0);
2193     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2194     ReleaseDC(0, hdc);
2195
2196     cursorInfo.fIcon = FALSE;
2197     cursorInfo.xHotspot = 0;
2198     cursorInfo.yHotspot = 0;
2199     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2200     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2201
2202     cursor = CreateIconIndirect(&cursorInfo);
2203     ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2204     if(!cursor) {
2205         return;
2206     }
2207     SetCursor(cursor);
2208
2209     SetLastError(0xdeadbeef);
2210     ret = DestroyCursor(cursor);
2211     ok(!ret || broken(ret)  /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n");
2212     error = GetLastError();
2213     ok(error == 0xdeadbeef, "Last error: %u\n", error);
2214
2215     new_cursor = GetCursor();
2216     if (ret)  /* win9x replaces cursor by another one on destroy */
2217         ok(new_cursor != cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2218     else
2219         ok(new_cursor == cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2220
2221     SetLastError(0xdeadbeef);
2222     ret = GetIconInfo( cursor, &new_info );
2223     ok( !ret || broken(ret), /* nt4 */ "GetIconInfo succeeded\n" );
2224     ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE ||
2225         broken(GetLastError() == 0xdeadbeef), /* win9x */
2226         "wrong error %u\n", GetLastError() );
2227
2228     if (ret)  /* nt4 delays destruction until cursor changes */
2229     {
2230         DeleteObject( new_info.hbmColor );
2231         DeleteObject( new_info.hbmMask );
2232
2233         SetLastError(0xdeadbeef);
2234         ret = DestroyCursor( cursor );
2235         ok( !ret, "DestroyCursor succeeded\n" );
2236         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2237             "wrong error %u\n", GetLastError() );
2238
2239         SetLastError(0xdeadbeef);
2240         cursor2 = SetCursor( cursor );
2241         ok( cursor2 == cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2242         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2243             "wrong error %u\n", GetLastError() );
2244     }
2245     else
2246     {
2247         SetLastError(0xdeadbeef);
2248         cursor2 = CopyCursor( cursor );
2249         ok(!cursor2, "CopyCursor succeeded\n" );
2250         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE ||
2251             broken(GetLastError() == 0xdeadbeef), /* win9x */
2252             "wrong error %u\n", GetLastError() );
2253
2254         SetLastError(0xdeadbeef);
2255         ret = DestroyCursor( cursor );
2256         if (new_cursor != cursor)  /* win9x */
2257             ok( ret, "DestroyCursor succeeded\n" );
2258         else
2259             ok( !ret, "DestroyCursor succeeded\n" );
2260         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2261             "wrong error %u\n", GetLastError() );
2262
2263         SetLastError(0xdeadbeef);
2264         cursor2 = SetCursor( cursor );
2265         ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2266         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2267             "wrong error %u\n", GetLastError() );
2268     }
2269
2270     cursor2 = GetCursor();
2271     ok(cursor2 == new_cursor, "GetCursor returned %p/%p\n", cursor2, new_cursor);
2272
2273     SetLastError(0xdeadbeef);
2274     cursor2 = SetCursor( 0 );
2275     if (new_cursor != cursor)  /* win9x */
2276         ok(cursor2 == new_cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2277     else
2278         ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2279     ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
2280
2281     cursor2 = GetCursor();
2282     ok(!cursor2, "GetCursor returned %p/%p\n", cursor2, cursor);
2283
2284     SetLastError(0xdeadbeef);
2285     ret = DestroyCursor(cursor);
2286     if (new_cursor != cursor)  /* win9x */
2287         ok( ret, "DestroyCursor succeeded\n" );
2288     else
2289         ok( !ret, "DestroyCursor succeeded\n" );
2290     ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2291         "wrong error %u\n", GetLastError() );
2292
2293     DeleteObject(cursorInfo.hbmMask);
2294     DeleteObject(cursorInfo.hbmColor);
2295
2296     /* Try testing DestroyCursor() now using LoadCursor() cursors. */
2297     cursor = LoadCursor(NULL, IDC_ARROW);
2298
2299     SetLastError(0xdeadbeef);
2300     ret = DestroyCursor(cursor);
2301     ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n");
2302     error = GetLastError();
2303     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2304
2305     /* Try setting the cursor to a destroyed OEM cursor. */
2306     SetLastError(0xdeadbeef);
2307     SetCursor(cursor);
2308     error = GetLastError();
2309     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2310
2311     /* Check if LoadCursor() returns the same handle with the same icon. */
2312     cursor2 = LoadCursor(NULL, IDC_ARROW);
2313     ok(cursor2 == cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2314
2315     /* Check if LoadCursor() returns the same handle with a different icon. */
2316     cursor2 = LoadCursor(NULL, IDC_WAIT);
2317     ok(cursor2 != cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2318 }
2319
2320 START_TEST(cursoricon)
2321 {
2322     pGetCursorInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorInfo" );
2323     pGetIconInfoExA = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExA" );
2324     pGetIconInfoExW = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExW" );
2325     pGetCursorFrameInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorFrameInfo" );
2326     test_argc = winetest_get_mainargs(&test_argv);
2327
2328     if (test_argc >= 3)
2329     {
2330         /* Child process. */
2331         sscanf (test_argv[2], "%x", (unsigned int *) &parent);
2332
2333         ok(parent != NULL, "Parent not found.\n");
2334         if (parent == NULL)
2335             ExitProcess(1);
2336
2337         do_child();
2338         return;
2339     }
2340
2341     test_CopyImage_Bitmap(1);
2342     test_CopyImage_Bitmap(4);
2343     test_CopyImage_Bitmap(8);
2344     test_CopyImage_Bitmap(16);
2345     test_CopyImage_Bitmap(24);
2346     test_CopyImage_Bitmap(32);
2347     test_initial_cursor();
2348     test_CreateIcon();
2349     test_LoadImage();
2350     test_CreateIconFromResource();
2351     test_GetCursorFrameInfo();
2352     test_DrawIcon();
2353     test_DrawIconEx();
2354     test_DrawState();
2355     test_SetCursor();
2356     test_ShowCursor();
2357     test_DestroyCursor();
2358     do_parent();
2359     test_child_process();
2360     finish_child_process();
2361 }