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 <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26 
27 #include "wine/test.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 
34 #include "pshpack1.h"
35 
36 typedef struct
37 {
38     BYTE bWidth;
39     BYTE bHeight;
40     BYTE bColorCount;
41     BYTE bReserved;
42     WORD xHotspot;
43     WORD yHotspot;
44     DWORD dwDIBSize;
45     DWORD dwDIBOffset;
46 } CURSORICONFILEDIRENTRY;
47 
48 typedef struct
49 {
50     WORD idReserved;
51     WORD idType;
52     WORD idCount;
53     CURSORICONFILEDIRENTRY idEntries[1];
54 } CURSORICONFILEDIR;
55 
56 #define RIFF_FOURCC( c0, c1, c2, c3 ) \
57         ( (DWORD)(BYTE)(c0) | ( (DWORD)(BYTE)(c1) << 8 ) | \
58         ( (DWORD)(BYTE)(c2) << 16 ) | ( (DWORD)(BYTE)(c3) << 24 ) )
59 
60 #define ANI_RIFF_ID RIFF_FOURCC('R', 'I', 'F', 'F')
61 #define ANI_LIST_ID RIFF_FOURCC('L', 'I', 'S', 'T')
62 #define ANI_ACON_ID RIFF_FOURCC('A', 'C', 'O', 'N')
63 #define ANI_anih_ID RIFF_FOURCC('a', 'n', 'i', 'h')
64 #define ANI_seq__ID RIFF_FOURCC('s', 'e', 'q', ' ')
65 #define ANI_fram_ID RIFF_FOURCC('f', 'r', 'a', 'm')
66 #define ANI_icon_ID RIFF_FOURCC('i', 'c', 'o', 'n')
67 #define ANI_rate_ID RIFF_FOURCC('r', 'a', 't', 'e')
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     BYTE mask_data[32*32/8];
87 } ani_data32x32x32;
88 
89 typedef struct {
90     CURSORICONFILEDIR    icon_info;  /* animated cursor frame information */
91     BITMAPINFOHEADER     bmi_header; /* animated cursor frame header */
92     ani_data32x32x32     bmi_data;   /* animated cursor frame DIB data */
93 } ani_frame32x32x32;
94 
95 typedef struct {
96     DWORD                chunk_id;   /* ANI_anih_ID */
97     DWORD                chunk_size; /* actual size of data */
98     ani_header           header;     /* animated cursor header */
99 } riff_header_t;
100 
101 typedef struct {
102     DWORD                chunk_id;   /* ANI_LIST_ID */
103     DWORD                chunk_size; /* actual size of data */
104     DWORD                chunk_type; /* ANI_fram_ID */
105 } riff_list_t;
106 
107 typedef struct {
108     DWORD                chunk_id;   /* ANI_icon_ID */
109     DWORD                chunk_size; /* actual size of data */
110     ani_frame32x32x32    data;       /* animated cursor frame */
111 } riff_icon32x32x32_t;
112 
113 typedef struct {
114     DWORD                chunk_id;   /* ANI_RIFF_ID */
115     DWORD                chunk_size; /* actual size of data */
116     DWORD                chunk_type; /* ANI_ACON_ID */
117     riff_header_t        header;     /* RIFF animated cursor header */
118     riff_list_t          frame_list; /* RIFF animated cursor frame list info */
119     riff_icon32x32x32_t  frames[1];  /* array of animated cursor frames */
120 } riff_cursor1_t;
121 
122 typedef struct {
123     DWORD                chunk_id;   /* ANI_RIFF_ID */
124     DWORD                chunk_size; /* actual size of data */
125     DWORD                chunk_type; /* ANI_ACON_ID */
126     riff_header_t        header;     /* RIFF animated cursor header */
127     riff_list_t          frame_list; /* RIFF animated cursor frame list info */
128     riff_icon32x32x32_t  frames[3];  /* array of three animated cursor frames */
129 } riff_cursor3_t;
130 
131 typedef struct {
132     DWORD                chunk_id;   /* ANI_rate_ID */
133     DWORD                chunk_size; /* actual size of data */
134     DWORD                rate[3];    /* animated cursor rate data */
135 } riff_rate3_t;
136 
137 typedef struct {
138     DWORD                chunk_id;   /* ANI_seq__ID */
139     DWORD                chunk_size; /* actual size of data */
140     DWORD                order[3];   /* animated cursor sequence data */
141 } riff_seq3_t;
142 
143 typedef struct {
144     DWORD                chunk_id;   /* ANI_RIFF_ID */
145     DWORD                chunk_size; /* actual size of data */
146     DWORD                chunk_type; /* ANI_ACON_ID */
147     riff_header_t        header;     /* RIFF animated cursor header */
148     riff_seq3_t          seq;        /* sequence data for three cursor frames */
149     riff_rate3_t         rates;      /* rate data for three cursor frames */
150     riff_list_t          frame_list; /* RIFF animated cursor frame list info */
151     riff_icon32x32x32_t  frames[3];  /* array of three animated cursor frames */
152 } riff_cursor3_seq_t;
153 
154 #define EMPTY_ICON32 \
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 riff_cursor1_t empty_anicursor = {
194     ANI_RIFF_ID,
195     sizeof(empty_anicursor) - sizeof(DWORD)*2,
196     ANI_ACON_ID,
197     {
198         ANI_anih_ID,
199         sizeof(ani_header),
200         {
201             sizeof(ani_header),
202             1,            /* frames */
203             1,            /* steps */
204             32,           /* width */
205             32,           /* height */
206             32,           /* depth */
207             1,            /* planes */
208             10,           /* display rate in jiffies */
209             ANI_FLAG_ICON /* flags */
210         }
211     },
212     {
213         ANI_LIST_ID,
214         sizeof(riff_icon32x32x32_t)*(1 /*frames*/) + sizeof(DWORD),
215         ANI_fram_ID,
216     },
217     {
218         EMPTY_ICON32
219     }
220 };
221 
222 riff_cursor3_t empty_anicursor3 = {
223     ANI_RIFF_ID,
224     sizeof(empty_anicursor3) - sizeof(DWORD)*2,
225     ANI_ACON_ID,
226     {
227         ANI_anih_ID,
228         sizeof(ani_header),
229         {
230             sizeof(ani_header),
231             3,            /* frames */
232             3,            /* steps */
233             32,           /* width */
234             32,           /* height */
235             32,           /* depth */
236             1,            /* planes */
237             0xbeef,       /* display rate in jiffies */
238             ANI_FLAG_ICON /* flags */
239         }
240     },
241     {
242         ANI_LIST_ID,
243         sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD),
244         ANI_fram_ID,
245     },
246     {
247         EMPTY_ICON32,
248         EMPTY_ICON32,
249         EMPTY_ICON32
250     }
251 };
252 
253 riff_cursor3_seq_t empty_anicursor3_seq = {
254     ANI_RIFF_ID,
255     sizeof(empty_anicursor3_seq) - sizeof(DWORD)*2,
256     ANI_ACON_ID,
257     {
258         ANI_anih_ID,
259         sizeof(ani_header),
260         {
261             sizeof(ani_header),
262             3,                              /* frames */
263             3,                              /* steps */
264             32,                             /* width */
265             32,                             /* height */
266             32,                             /* depth */
267             1,                              /* planes */
268             0xbeef,                         /* display rate in jiffies */
269             ANI_FLAG_ICON|ANI_FLAG_SEQUENCE /* flags */
270         }
271     },
272     {
273         ANI_seq__ID,
274         sizeof(riff_seq3_t) - sizeof(DWORD)*2,
275         { 2, 0, 1} /* show frames in a uniquely identifiable order */
276     },
277     {
278         ANI_rate_ID,
279         sizeof(riff_rate3_t) - sizeof(DWORD)*2,
280         { 0xc0de, 0xcafe, 0xbabe}
281     },
282     {
283         ANI_LIST_ID,
284         sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD),
285         ANI_fram_ID,
286     },
287     {
288         EMPTY_ICON32,
289         EMPTY_ICON32,
290         EMPTY_ICON32
291     }
292 };
293 
294 #include "poppack.h"
295 
296 static char **test_argv;
297 static int test_argc;
298 static HWND child = 0;
299 static HWND parent = 0;
300 static HANDLE child_process;
301 
302 #define PROC_INIT (WM_USER+1)
303 
304 static BOOL (WINAPI *pGetCursorInfo)(CURSORINFO *);
305 static BOOL (WINAPI *pGetIconInfoExA)(HICON,ICONINFOEXA *);
306 static BOOL (WINAPI *pGetIconInfoExW)(HICON,ICONINFOEXW *);
307 
308 static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
309 
callback_child(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)310 static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
311 {
312     switch (msg)
313     {
314         /* Destroy the cursor. */
315         case WM_USER+1:
316         {
317             HCURSOR cursor = (HCURSOR)lParam;
318             ICONINFO info;
319             BOOL ret;
320             DWORD error;
321 
322             memset(&info, 0, sizeof(info));
323             ret = GetIconInfo(cursor, &info);
324             todo_wine ok(ret, "GetIconInfoEx failed with error %u\n", GetLastError());
325             todo_wine ok(info.hbmColor != NULL, "info.hmbColor was not set\n");
326             todo_wine ok(info.hbmMask != NULL, "info.hmbColor was not set\n");
327             DeleteObject(info.hbmColor);
328             DeleteObject(info.hbmMask);
329 
330             SetLastError(0xdeadbeef);
331             ret = DestroyCursor(cursor);
332             error = GetLastError();
333             ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n");
334             ok(error == ERROR_DESTROY_OBJECT_OF_OTHER_THREAD ||
335                error == 0xdeadbeef,  /* vista */
336                 "Last error: %u\n", error);
337             return TRUE;
338         }
339         case WM_DESTROY:
340             PostQuitMessage(0);
341             return 0;
342     }
343 
344     return DefWindowProcA(hwnd, msg, wParam, lParam);
345 }
346 
callback_parent(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)347 static LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
348 {
349     if (msg == PROC_INIT)
350     {
351         child = (HWND) wParam;
352         return TRUE;
353     }
354 
355     return DefWindowProcA(hwnd, msg, wParam, lParam);
356 }
357 
do_child(void)358 static void do_child(void)
359 {
360     WNDCLASSA class;
361     MSG msg;
362     BOOL ret;
363 
364     /* Register a new class. */
365     class.style = CS_GLOBALCLASS;
366     class.lpfnWndProc = callback_child;
367     class.cbClsExtra = 0;
368     class.cbWndExtra = 0;
369     class.hInstance = GetModuleHandleA(NULL);
370     class.hIcon = NULL;
371     class.hCursor = NULL;
372     class.hbrBackground = NULL;
373     class.lpszMenuName = NULL;
374     class.lpszClassName = "cursor_child";
375 
376     SetLastError(0xdeadbeef);
377     ret = RegisterClassA(&class);
378     ok(ret, "Failed to register window class.  Error: %u\n", GetLastError());
379 
380     /* Create a window. */
381     child = CreateWindowA("cursor_child", "cursor_child", WS_POPUP | WS_VISIBLE,
382         0, 0, 200, 200, 0, 0, 0, NULL);
383     ok(child != 0, "CreateWindowA failed.  Error: %u\n", GetLastError());
384 
385     /* Let the parent know our HWND. */
386     PostMessageA(parent, PROC_INIT, (WPARAM) child, 0);
387 
388     /* Receive messages. */
389     while ((ret = GetMessageA(&msg, 0, 0, 0)))
390     {
391         ok(ret != -1, "GetMessage failed.  Error: %u\n", GetLastError());
392         TranslateMessage(&msg);
393         DispatchMessageA(&msg);
394     }
395 }
396 
do_parent(void)397 static void do_parent(void)
398 {
399     char path_name[MAX_PATH];
400     PROCESS_INFORMATION info;
401     STARTUPINFOA startup;
402     WNDCLASSA class;
403     MSG msg;
404     BOOL ret;
405 
406     /* Register a new class. */
407     class.style = CS_GLOBALCLASS;
408     class.lpfnWndProc = callback_parent;
409     class.cbClsExtra = 0;
410     class.cbWndExtra = 0;
411     class.hInstance = GetModuleHandleA(NULL);
412     class.hIcon = NULL;
413     class.hCursor = NULL;
414     class.hbrBackground = NULL;
415     class.lpszMenuName = NULL;
416     class.lpszClassName = "cursor_parent";
417 
418     SetLastError(0xdeadbeef);
419     ret = RegisterClassA(&class);
420     ok(ret, "Failed to register window class.  Error: %u\n", GetLastError());
421 
422     /* Create a window. */
423     parent = CreateWindowA("cursor_parent", "cursor_parent", WS_POPUP | WS_VISIBLE,
424         0, 0, 200, 200, 0, 0, 0, NULL);
425     ok(parent != 0, "CreateWindowA failed.  Error: %u\n", GetLastError());
426 
427     /* Start child process. */
428     memset(&startup, 0, sizeof(startup));
429     startup.cb = sizeof(startup);
430     startup.dwFlags = STARTF_USESHOWWINDOW;
431     startup.wShowWindow = SW_SHOWNORMAL;
432 
433     sprintf(path_name, "%s cursoricon %lx", test_argv[0], (INT_PTR)parent);
434     ok(CreateProcessA(NULL, path_name, NULL, NULL, FALSE, 0L, NULL, NULL, &startup, &info), "CreateProcess failed.\n");
435     child_process = info.hProcess;
436 
437     /* Wait for child window handle. */
438     while ((child == 0) && (ret = GetMessageA(&msg, parent, 0, 0)))
439     {
440         ok(ret != -1, "GetMessage failed.  Error: %u\n", GetLastError());
441         TranslateMessage(&msg);
442         DispatchMessageA(&msg);
443     }
444 }
445 
finish_child_process(void)446 static void finish_child_process(void)
447 {
448     SendMessageA(child, WM_CLOSE, 0, 0);
449     winetest_wait_child_process( child_process );
450     CloseHandle(child_process);
451 }
452 
test_child_process(void)453 static void test_child_process(void)
454 {
455     static const BYTE bmp_bits[4096];
456     HCURSOR cursor;
457     ICONINFO cursorInfo;
458     UINT display_bpp;
459     HDC hdc;
460 
461     /* Create and set a dummy cursor. */
462     hdc = GetDC(0);
463     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
464     ReleaseDC(0, hdc);
465 
466     cursorInfo.fIcon = FALSE;
467     cursorInfo.xHotspot = 0;
468     cursorInfo.yHotspot = 0;
469     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
470     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
471 
472     cursor = CreateIconIndirect(&cursorInfo);
473     ok(cursor != NULL, "CreateIconIndirect returned %p.\n", cursor);
474 
475     SetCursor(cursor);
476 
477     /* Destroy the cursor. */
478     SendMessageA(child, WM_USER+1, 0, (LPARAM) cursor);
479 }
480 
color_match(COLORREF a,COLORREF b)481 static BOOL color_match(COLORREF a, COLORREF b)
482 {
483     /* 5-bit accuracy is a sufficient test. This will match as long as
484      * colors are never truncated to less that 3x5-bit accuracy i.e.
485      * palettized. */
486     return (a & 0x00F8F8F8) == (b & 0x00F8F8F8);
487 }
488 
test_CopyImage_Check(HBITMAP bitmap,UINT flags,INT copyWidth,INT copyHeight,INT expectedWidth,INT expectedHeight,WORD expectedDepth,BOOL dibExpected)489 static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
490                                   INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
491 {
492     HBITMAP copy;
493     BITMAP origBitmap;
494     BITMAP copyBitmap;
495     BOOL orig_is_dib;
496     BOOL copy_is_dib;
497 
498     copy = CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags);
499     ok(copy != NULL, "CopyImage() failed\n");
500     if (copy != NULL)
501     {
502         GetObjectA(bitmap, sizeof(origBitmap), &origBitmap);
503         GetObjectA(copy, sizeof(copyBitmap), &copyBitmap);
504         orig_is_dib = (origBitmap.bmBits != NULL);
505         copy_is_dib = (copyBitmap.bmBits != NULL);
506 
507         if (copy_is_dib && dibExpected
508             && copyBitmap.bmBitsPixel == 24
509             && (expectedDepth == 16 || expectedDepth == 32))
510         {
511             /* Windows 95 doesn't create DIBs with a depth of 16 or 32 bit */
512             if (GetVersion() & 0x80000000)
513             {
514                 expectedDepth = 24;
515             }
516         }
517 
518         if (copy_is_dib && !dibExpected && !(flags & LR_CREATEDIBSECTION))
519         {
520             /* It's not forbidden to create a DIB section if the flag
521                LR_CREATEDIBSECTION is absent.
522                Windows 9x does this if the bitmap has a depth that doesn't
523                match the screen depth, Windows NT doesn't */
524             dibExpected = TRUE;
525             expectedDepth = origBitmap.bmBitsPixel;
526         }
527 
528         ok((!(dibExpected ^ copy_is_dib)
529              && (copyBitmap.bmWidth == expectedWidth)
530              && (copyBitmap.bmHeight == expectedHeight)
531              && (copyBitmap.bmBitsPixel == expectedDepth)),
532              "CopyImage ((%s, %dx%d, %u bpp), %d, %d, %#x): Expected (%s, %dx%d, %u bpp), got (%s, %dx%d, %u bpp)\n",
533                   orig_is_dib ? "DIB" : "DDB", origBitmap.bmWidth, origBitmap.bmHeight, origBitmap.bmBitsPixel,
534                   copyWidth, copyHeight, flags,
535                   dibExpected ? "DIB" : "DDB", expectedWidth, expectedHeight, expectedDepth,
536                   copy_is_dib ? "DIB" : "DDB", copyBitmap.bmWidth, copyBitmap.bmHeight, copyBitmap.bmBitsPixel);
537 
538         DeleteObject(copy);
539     }
540 }
541 
test_CopyImage_Bitmap(int depth)542 static void test_CopyImage_Bitmap(int depth)
543 {
544     HBITMAP ddb, dib;
545     HDC screenDC;
546     BITMAPINFO * info;
547     VOID * bits;
548     int screen_depth;
549     unsigned int i;
550 
551     /* Create a device-independent bitmap (DIB) */
552     info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
553     info->bmiHeader.biSize = sizeof(info->bmiHeader);
554     info->bmiHeader.biWidth = 2;
555     info->bmiHeader.biHeight = 2;
556     info->bmiHeader.biPlanes = 1;
557     info->bmiHeader.biBitCount = depth;
558     info->bmiHeader.biCompression = BI_RGB;
559 
560     for (i=0; i < 256; i++)
561     {
562         info->bmiColors[i].rgbRed = i;
563         info->bmiColors[i].rgbGreen = i;
564         info->bmiColors[i].rgbBlue = 255 - i;
565         info->bmiColors[i].rgbReserved = 0;
566     }
567 
568     dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
569 
570     /* Create a device-dependent bitmap (DDB) */
571     screenDC = GetDC(NULL);
572     screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
573     if (depth == 1 || depth == screen_depth)
574     {
575         ddb = CreateBitmap(2, 2, 1, depth, NULL);
576     }
577     else
578     {
579         ddb = NULL;
580     }
581     ReleaseDC(NULL, screenDC);
582 
583     if (ddb != NULL)
584     {
585         test_CopyImage_Check(ddb, 0, 0, 0, 2, 2, depth == 1 ? 1 : screen_depth, FALSE);
586         test_CopyImage_Check(ddb, 0, 0, 5, 2, 5, depth == 1 ? 1 : screen_depth, FALSE);
587         test_CopyImage_Check(ddb, 0, 5, 0, 5, 2, depth == 1 ? 1 : screen_depth, FALSE);
588         test_CopyImage_Check(ddb, 0, 5, 5, 5, 5, depth == 1 ? 1 : screen_depth, FALSE);
589 
590         test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
591         test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
592         test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
593         test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
594 
595         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
596         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
597         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
598         test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
599 
600         /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
601         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
602         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
603         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
604         test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
605 
606         DeleteObject(ddb);
607     }
608 
609     if (depth != 1)
610     {
611         test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
612         test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
613         test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
614         test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
615     }
616 
617     test_CopyImage_Check(dib, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
618     test_CopyImage_Check(dib, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
619     test_CopyImage_Check(dib, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
620     test_CopyImage_Check(dib, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
621 
622     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
623     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
624     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
625     test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
626 
627     /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
628     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
629     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
630     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
631     test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
632 
633     DeleteObject(dib);
634 
635     if (depth == 1)
636     {
637         /* Special case: A monochrome DIB is converted to a monochrome DDB if
638            the colors in the color table are black and white.
639 
640            Skip this test on Windows 95, it always creates a monochrome DDB
641            in this case */
642 
643         if (!(GetVersion() & 0x80000000))
644         {
645             info->bmiHeader.biBitCount = 1;
646             info->bmiColors[0].rgbRed = 0xFF;
647             info->bmiColors[0].rgbGreen = 0;
648             info->bmiColors[0].rgbBlue = 0;
649             info->bmiColors[1].rgbRed = 0;
650             info->bmiColors[1].rgbGreen = 0xFF;
651             info->bmiColors[1].rgbBlue = 0;
652 
653             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
654             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
655             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
656             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
657             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
658             DeleteObject(dib);
659 
660             info->bmiHeader.biBitCount = 1;
661             info->bmiColors[0].rgbRed = 0;
662             info->bmiColors[0].rgbGreen = 0;
663             info->bmiColors[0].rgbBlue = 0;
664             info->bmiColors[1].rgbRed = 0xFF;
665             info->bmiColors[1].rgbGreen = 0xFF;
666             info->bmiColors[1].rgbBlue = 0xFF;
667 
668             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
669             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
670             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
671             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
672             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
673             DeleteObject(dib);
674 
675             info->bmiHeader.biBitCount = 1;
676             info->bmiColors[0].rgbRed = 0xFF;
677             info->bmiColors[0].rgbGreen = 0xFF;
678             info->bmiColors[0].rgbBlue = 0xFF;
679             info->bmiColors[1].rgbRed = 0;
680             info->bmiColors[1].rgbGreen = 0;
681             info->bmiColors[1].rgbBlue = 0;
682 
683             dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
684             test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
685             test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
686             test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
687             test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
688             DeleteObject(dib);
689         }
690     }
691 
692     HeapFree(GetProcessHeap(), 0, info);
693 }
694 
test_initial_cursor(void)695 static void test_initial_cursor(void)
696 {
697     HCURSOR cursor, cursor2;
698     DWORD error;
699 
700     cursor = GetCursor();
701 
702     /* Check what handle GetCursor() returns if a cursor is not set yet. */
703     SetLastError(0xdeadbeef);
704     cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_WAIT);
705     todo_wine {
706         ok(cursor == cursor2, "cursor (%p) is not IDC_WAIT (%p).\n", cursor, cursor2);
707     }
708     error = GetLastError();
709     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
710 }
711 
test_icon_info_dbg(HICON hIcon,UINT exp_cx,UINT exp_cy,UINT exp_mask_cy,UINT exp_bpp,int line)712 static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_mask_cy, UINT exp_bpp, int line)
713 {
714     ICONINFO info;
715     DWORD ret;
716     BITMAP bmMask, bmColor;
717 
718     ret = GetIconInfo(hIcon, &info);
719     ok_(__FILE__, line)(ret, "GetIconInfo failed\n");
720 
721     /* CreateIcon under XP causes info.fIcon to be 0 */
722     ok_(__FILE__, line)(info.xHotspot == exp_cx/2, "info.xHotspot = %u\n", info.xHotspot);
723     ok_(__FILE__, line)(info.yHotspot == exp_cy/2, "info.yHotspot = %u\n", info.yHotspot);
724     ok_(__FILE__, line)(info.hbmMask != 0, "info.hbmMask is NULL\n");
725 
726     ret = GetObjectA(info.hbmMask, sizeof(bmMask), &bmMask);
727     ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
728 
729     if (exp_bpp == 1)
730         ok_(__FILE__, line)(info.hbmColor == 0, "info.hbmColor should be NULL\n");
731 
732     if (info.hbmColor)
733     {
734         HDC hdc;
735         UINT display_bpp;
736 
737         hdc = GetDC(0);
738         display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
739         ReleaseDC(0, hdc);
740 
741         ret = GetObjectA(info.hbmColor, sizeof(bmColor), &bmColor);
742         ok_(__FILE__, line)(ret == sizeof(bmColor), "GetObject(info.hbmColor) failed, ret %u\n", ret);
743 
744         ok_(__FILE__, line)(bmColor.bmBitsPixel == display_bpp /* XP */ ||
745            bmColor.bmBitsPixel == exp_bpp /* Win98 */,
746            "bmColor.bmBitsPixel = %d\n", bmColor.bmBitsPixel);
747         ok_(__FILE__, line)(bmColor.bmWidth == exp_cx, "bmColor.bmWidth = %d\n", bmColor.bmWidth);
748         ok_(__FILE__, line)(bmColor.bmHeight == exp_cy, "bmColor.bmHeight = %d\n", bmColor.bmHeight);
749 
750         ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
751         ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
752         ok_(__FILE__, line)(bmMask.bmHeight == exp_mask_cy, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
753     }
754     else
755     {
756         ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
757         ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
758         ok_(__FILE__, line)(bmMask.bmHeight == exp_mask_cy, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
759     }
760     if (pGetIconInfoExA)
761     {
762         ICONINFOEXA infoex;
763 
764         memset( &infoex, 0xcc, sizeof(infoex) );
765         SetLastError( 0xdeadbeef );
766         infoex.cbSize = sizeof(infoex) - 1;
767         ret = pGetIconInfoExA( hIcon, &infoex );
768         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
769         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError());
770 
771         SetLastError( 0xdeadbeef );
772         infoex.cbSize = sizeof(infoex) + 1;
773         ret = pGetIconInfoExA( hIcon, &infoex );
774         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
775         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_PARAMETER, "wrong error %d\n", GetLastError());
776 
777         SetLastError( 0xdeadbeef );
778         infoex.cbSize = sizeof(infoex);
779         ret = pGetIconInfoExA( (HICON)0xdeadbabe, &infoex );
780         ok_(__FILE__, line)(!ret, "GetIconInfoEx succeeded\n");
781         ok_(__FILE__, line)(GetLastError() == ERROR_INVALID_CURSOR_HANDLE,
782                             "wrong error %d\n", GetLastError());
783 
784         infoex.cbSize = sizeof(infoex);
785         ret = pGetIconInfoExA( hIcon, &infoex );
786         ok_(__FILE__, line)(ret, "GetIconInfoEx failed err %d\n", GetLastError());
787         ok_(__FILE__, line)(infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID);
788         ok_(__FILE__, line)(infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName);
789         ok_(__FILE__, line)(infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName);
790     }
791 }
792 
793 #define test_icon_info(a,b,c,d,e) test_icon_info_dbg((a),(b),(c),(d),(e),__LINE__)
794 
test_CreateIcon(void)795 static void test_CreateIcon(void)
796 {
797     static const BYTE bmp_bits[1024];
798     HICON hIcon;
799     HBITMAP hbmMask, hbmColor;
800     BITMAPINFO *bmpinfo;
801     ICONINFO info;
802     HDC hdc;
803     void *bits;
804     UINT display_bpp;
805     int i;
806 
807     hdc = GetDC(0);
808     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
809 
810     /* these crash under XP
811     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
812     hIcon = CreateIcon(0, 16, 16, 1, 1, NULL, bmp_bits);
813     */
814 
815     hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
816     ok(hIcon != 0, "CreateIcon failed\n");
817     test_icon_info(hIcon, 16, 16, 32, 1);
818     DestroyIcon(hIcon);
819 
820     hIcon = CreateIcon(0, 16, 16, 1, display_bpp, bmp_bits, bmp_bits);
821     ok(hIcon != 0, "CreateIcon failed\n");
822     test_icon_info(hIcon, 16, 16, 16, display_bpp);
823     DestroyIcon(hIcon);
824 
825     hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
826     ok(hbmMask != 0, "CreateBitmap failed\n");
827     hbmColor = CreateBitmap(16, 16, 1, display_bpp, bmp_bits);
828     ok(hbmColor != 0, "CreateBitmap failed\n");
829 
830     info.fIcon = TRUE;
831     info.xHotspot = 8;
832     info.yHotspot = 8;
833     info.hbmMask = 0;
834     info.hbmColor = 0;
835     SetLastError(0xdeadbeaf);
836     hIcon = CreateIconIndirect(&info);
837     ok(!hIcon, "CreateIconIndirect should fail\n");
838     ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
839 
840     info.fIcon = TRUE;
841     info.xHotspot = 8;
842     info.yHotspot = 8;
843     info.hbmMask = 0;
844     info.hbmColor = hbmColor;
845     SetLastError(0xdeadbeaf);
846     hIcon = CreateIconIndirect(&info);
847     ok(!hIcon, "CreateIconIndirect should fail\n");
848     ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
849 
850     info.fIcon = TRUE;
851     info.xHotspot = 8;
852     info.yHotspot = 8;
853     info.hbmMask = hbmMask;
854     info.hbmColor = hbmColor;
855     hIcon = CreateIconIndirect(&info);
856     ok(hIcon != 0, "CreateIconIndirect failed\n");
857     test_icon_info(hIcon, 16, 16, 16, display_bpp);
858     DestroyIcon(hIcon);
859 
860     DeleteObject(hbmMask);
861     DeleteObject(hbmColor);
862 
863     hbmMask = CreateBitmap(16, 32, 1, 1, bmp_bits);
864     ok(hbmMask != 0, "CreateBitmap failed\n");
865 
866     info.fIcon = TRUE;
867     info.xHotspot = 8;
868     info.yHotspot = 8;
869     info.hbmMask = hbmMask;
870     info.hbmColor = 0;
871     SetLastError(0xdeadbeaf);
872     hIcon = CreateIconIndirect(&info);
873     ok(hIcon != 0, "CreateIconIndirect failed\n");
874     test_icon_info(hIcon, 16, 16, 32, 1);
875     DestroyIcon(hIcon);
876     DeleteObject(hbmMask);
877 
878     for (i = 0; i <= 4; i++)
879     {
880         hbmMask = CreateBitmap(1, i, 1, 1, bmp_bits);
881         ok(hbmMask != 0, "CreateBitmap failed\n");
882 
883         info.fIcon = TRUE;
884         info.xHotspot = 0;
885         info.yHotspot = 0;
886         info.hbmMask = hbmMask;
887         info.hbmColor = 0;
888         SetLastError(0xdeadbeaf);
889         hIcon = CreateIconIndirect(&info);
890         ok(hIcon != 0, "CreateIconIndirect failed\n");
891         test_icon_info(hIcon, 1, i / 2, max(i,1), 1);
892         DestroyIcon(hIcon);
893         DeleteObject(hbmMask);
894     }
895 
896     /* test creating an icon from a DIB section */
897 
898     bmpinfo = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, FIELD_OFFSET(BITMAPINFO,bmiColors[256]));
899     bmpinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
900     bmpinfo->bmiHeader.biWidth = 32;
901     bmpinfo->bmiHeader.biHeight = 32;
902     bmpinfo->bmiHeader.biPlanes = 1;
903     bmpinfo->bmiHeader.biBitCount = 8;
904     bmpinfo->bmiHeader.biCompression = BI_RGB;
905     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
906     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
907     if (bits)
908         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
909     bmpinfo->bmiHeader.biBitCount = 1;
910     hbmMask = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
911     ok(hbmMask != NULL, "Expected a handle to the DIB\n");
912     if (bits)
913         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
914 
915     info.fIcon = TRUE;
916     info.xHotspot = 8;
917     info.yHotspot = 8;
918     info.hbmMask = hbmColor;
919     info.hbmColor = hbmMask;
920     SetLastError(0xdeadbeaf);
921     hIcon = CreateIconIndirect(&info);
922     ok(hIcon != 0, "CreateIconIndirect failed\n");
923     test_icon_info(hIcon, 32, 32, 32, 8);
924     DestroyIcon(hIcon);
925     DeleteObject(hbmColor);
926 
927     bmpinfo->bmiHeader.biBitCount = 16;
928     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
929     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
930     if (bits)
931         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
932 
933     info.fIcon = TRUE;
934     info.xHotspot = 8;
935     info.yHotspot = 8;
936     info.hbmMask = hbmColor;
937     info.hbmColor = hbmMask;
938     SetLastError(0xdeadbeaf);
939     hIcon = CreateIconIndirect(&info);
940     ok(hIcon != 0, "CreateIconIndirect failed\n");
941     test_icon_info(hIcon, 32, 32, 32, 8);
942     DestroyIcon(hIcon);
943     DeleteObject(hbmColor);
944 
945     bmpinfo->bmiHeader.biBitCount = 32;
946     hbmColor = CreateDIBSection( hdc, bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
947     ok(hbmColor != NULL, "Expected a handle to the DIB\n");
948     if (bits)
949         memset( bits, 0x55, 32 * 32 * bmpinfo->bmiHeader.biBitCount / 8 );
950 
951     info.fIcon = TRUE;
952     info.xHotspot = 8;
953     info.yHotspot = 8;
954     info.hbmMask = hbmColor;
955     info.hbmColor = hbmMask;
956     SetLastError(0xdeadbeaf);
957     hIcon = CreateIconIndirect(&info);
958     ok(hIcon != 0, "CreateIconIndirect failed\n");
959     test_icon_info(hIcon, 32, 32, 32, 8);
960     DestroyIcon(hIcon);
961 
962     DeleteObject(hbmMask);
963     DeleteObject(hbmColor);
964     HeapFree( GetProcessHeap(), 0, bmpinfo );
965 
966     ReleaseDC(0, hdc);
967 }
968 
969 /* Shamelessly ripped from dlls/oleaut32/tests/olepicture.c */
970 /* 1x1 pixel gif */
971 static const unsigned char gifimage[35] = {
972 0x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
973 0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
974 0x01,0x00,0x3b
975 };
976 
977 /* 1x1 pixel jpg */
978 static const unsigned char jpgimage[285] = {
979 0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
980 0x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
981 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
982 0x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
983 0x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
984 0x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
985 0x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
986 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
987 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
988 0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
989 0x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
990 0x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
991 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
992 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
993 0x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
994 0x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
995 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
996 0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
997 };
998 
999 /* 1x1 pixel png */
1000 static const unsigned char pngimage[285] = {
1001 0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
1002 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
1003 0xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
1004 0x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
1005 0x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
1006 0x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
1007 0xe7,0x00,0x00,0x00,0x00,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82
1008 };
1009 
1010 /* 1x1 pixel bmp with gap between palette and bitmap. Correct bitmap contains only
1011    zeroes, gap is 0xFF. */
1012 static unsigned char bmpimage[70] = {
1013 0x42,0x4d,0x46,0x00,0x00,0x00,0xDE,0xAD,0xBE,0xEF,0x42,0x00,0x00,0x00,0x28,0x00,
1014 0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
1015 0x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
1016 0x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x55,0x55,0x55,0x00,0xFF,0xFF,
1017 0xFF,0xFF,0x00,0x00,0x00,0x00
1018 };
1019 
1020 /* 1x1 pixel bmp using BITMAPCOREHEADER */
1021 static const unsigned char bmpcoreimage[38] = {
1022 0x42,0x4d,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x0c,0x00,
1023 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xff,0xff,0xff,0x00,0x55,0x55,
1024 0x55,0x00,0x00,0x00,0x00,0x00
1025 };
1026 
1027 /* 2x2 pixel gif */
1028 static const unsigned char gif4pixel[42] = {
1029 0x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
1030 0x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
1031 0x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
1032 };
1033 
1034 /* An invalid cursor with an invalid dwDIBOffset */
1035 static const unsigned char invalid_dwDIBOffset[] = {
1036   0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1037   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00
1038 };
1039 
1040 static const DWORD biSize_tests[] = {
1041     0,
1042     sizeof(BITMAPCOREHEADER) - 1,
1043     sizeof(BITMAPCOREHEADER) + 1,
1044     sizeof(BITMAPINFOHEADER) - 1,
1045     sizeof(BITMAPINFOHEADER) + 1,
1046     sizeof(BITMAPV4HEADER) - 1,
1047     sizeof(BITMAPV4HEADER) + 1,
1048     sizeof(BITMAPV5HEADER) - 1,
1049     sizeof(BITMAPV5HEADER) + 1,
1050     (sizeof(BITMAPCOREHEADER) + sizeof(BITMAPINFOHEADER)) / 2,
1051     (sizeof(BITMAPV4HEADER) + sizeof(BITMAPV5HEADER)) / 2,
1052     0xdeadbeef,
1053     0xffffffff
1054 };
1055 
test_LoadImageBitmap(const char * test_desc,HBITMAP hbm)1056 static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm)
1057 {
1058     BITMAP bm;
1059     BITMAPINFO bmi;
1060     DWORD ret, pixel = 0;
1061     HDC hdc = GetDC(NULL);
1062 
1063     ret = GetObjectA(hbm, sizeof(bm), &bm);
1064     ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
1065 
1066     memset(&bmi, 0, sizeof(bmi));
1067     bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1068     bmi.bmiHeader.biWidth = bm.bmWidth;
1069     bmi.bmiHeader.biHeight = bm.bmHeight;
1070     bmi.bmiHeader.biPlanes = 1;
1071     bmi.bmiHeader.biBitCount= 24;
1072     bmi.bmiHeader.biCompression= BI_RGB;
1073     ret = GetDIBits(hdc, hbm, 0, bm.bmHeight, &pixel, &bmi, DIB_RGB_COLORS);
1074     ok(ret == bm.bmHeight, "%s: %d lines were converted, not %d\n", test_desc, ret, bm.bmHeight);
1075 
1076     ok(color_match(pixel, 0x00ffffff), "%s: Pixel is 0x%08x\n", test_desc, pixel);
1077 
1078     ReleaseDC(NULL, hdc);
1079 }
1080 
test_LoadImageFile(const char * test_desc,const unsigned char * image_data,unsigned int image_size,const char * ext,BOOL expect_success)1081 static void test_LoadImageFile(const char * test_desc, const unsigned char * image_data,
1082     unsigned int image_size, const char * ext, BOOL expect_success)
1083 {
1084     HANDLE handle;
1085     BOOL ret;
1086     DWORD error, bytes_written;
1087     char filename[64];
1088 
1089     strcpy(filename, "test.");
1090     strcat(filename, ext);
1091 
1092     /* Create the test image. */
1093     handle = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW,
1094         FILE_ATTRIBUTE_NORMAL, NULL);
1095     ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1096     ret = WriteFile(handle, image_data, image_size, &bytes_written, NULL);
1097     ok(ret && bytes_written == image_size, "test file created improperly.\n");
1098     CloseHandle(handle);
1099 
1100     /* Load as cursor. For all tested formats, this should fail */
1101     SetLastError(0xdeadbeef);
1102     handle = LoadImageA(NULL, filename, IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1103     ok(handle == NULL, "%s: IMAGE_CURSOR succeeded incorrectly.\n", test_desc);
1104     error = GetLastError();
1105     ok(error == 0 ||
1106         broken(error == 0xdeadbeef) || /* Win9x */
1107         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1108         "Last error: %u\n", error);
1109     if (handle != NULL) DestroyCursor(handle);
1110 
1111     /* Load as icon. For all tested formats, this should fail */
1112     SetLastError(0xdeadbeef);
1113     handle = LoadImageA(NULL, filename, IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
1114     ok(handle == NULL, "%s: IMAGE_ICON succeeded incorrectly.\n", test_desc);
1115     error = GetLastError();
1116     ok(error == 0 ||
1117         broken(error == 0xdeadbeef) || /* Win9x */
1118         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1119         "Last error: %u\n", error);
1120     if (handle != NULL) DestroyIcon(handle);
1121 
1122     /* Load as bitmap. Should succeed for correct bmp, fail for everything else */
1123     SetLastError(0xdeadbeef);
1124     handle = LoadImageA(NULL, filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
1125     error = GetLastError();
1126     ok(error == 0 ||
1127         error == 0xdeadbeef, /* Win9x, WinMe */
1128         "Last error: %u\n", error);
1129 
1130     if (expect_success) {
1131         ok(handle != NULL, "%s: IMAGE_BITMAP failed.\n", test_desc);
1132         if (handle != NULL) test_LoadImageBitmap(test_desc, handle);
1133     }
1134     else ok(handle == NULL, "%s: IMAGE_BITMAP succeeded incorrectly.\n", test_desc);
1135 
1136     if (handle != NULL) DeleteObject(handle);
1137     DeleteFileA(filename);
1138 }
1139 
1140 typedef struct {
1141     unsigned width;
1142     unsigned height;
1143     BOOL invalid_offset;
1144 } test_icon_entries_t;
1145 
create_ico_file(const char * filename,const test_icon_entries_t * test_icon_entries,unsigned entry_cnt)1146 static void create_ico_file(const char *filename, const test_icon_entries_t *test_icon_entries, unsigned entry_cnt)
1147 {
1148     CURSORICONFILEDIRENTRY *icon_entry;
1149     BITMAPINFOHEADER *icon_header;
1150     CURSORICONFILEDIR *dir;
1151     BYTE *buf, *bitmap_ptr;
1152     DWORD bytes_written;
1153     size_t icon_size;
1154     HANDLE file;
1155     unsigned i;
1156     BOOL ret;
1157 
1158     const unsigned icon_bpp = 32;
1159 
1160     icon_size = FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]) + sizeof(BITMAPINFOHEADER)*entry_cnt;
1161     for(i=0; i<entry_cnt; i++)
1162         icon_size += icon_bpp * test_icon_entries[i].width * test_icon_entries[i].height / 8;
1163 
1164     buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, icon_size);
1165     dir = (CURSORICONFILEDIR*)buf;
1166 
1167     dir->idReserved = 0;
1168     dir->idType = 1;
1169     dir->idCount = entry_cnt;
1170 
1171     bitmap_ptr = buf + FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]);
1172     for(i=0; i<entry_cnt; i++) {
1173         icon_entry = dir->idEntries+i;
1174         icon_entry->bWidth = test_icon_entries[i].width;
1175         icon_entry->bHeight = test_icon_entries[i].height;
1176         icon_entry->bColorCount = 0;
1177         icon_entry->bReserved = 0;
1178         icon_entry->xHotspot = 1;
1179         icon_entry->yHotspot = 1;
1180         icon_entry->dwDIBSize = sizeof(BITMAPINFOHEADER) + icon_entry->bWidth * icon_entry->bHeight * icon_bpp / 8;
1181         icon_entry->dwDIBOffset = test_icon_entries[i].invalid_offset ? 0xffffffff : bitmap_ptr - buf;
1182 
1183         icon_header = (BITMAPINFOHEADER*)bitmap_ptr;
1184         bitmap_ptr += icon_entry->dwDIBSize;
1185 
1186         icon_header->biSize = sizeof(BITMAPINFOHEADER);
1187         icon_header->biWidth = icon_entry->bWidth;
1188         icon_header->biHeight = icon_entry->bHeight;
1189         icon_header->biPlanes = 1;
1190         icon_header->biBitCount = icon_bpp;
1191         icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1192     }
1193 
1194     memset(bitmap_ptr, 0xf0, buf+icon_size-bitmap_ptr);
1195 
1196     /* Create the icon. */
1197     file = CreateFileA(filename, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
1198     ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1199     ret = WriteFile(file, buf, icon_size, &bytes_written, NULL);
1200     ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
1201     CloseHandle(file);
1202 
1203     HeapFree(GetProcessHeap(), 0, buf);
1204 }
1205 
create_bitmap_file(const char * filename,const BITMAPINFO * bmi,const unsigned char * bits)1206 static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits)
1207 {
1208     unsigned int clr_used, bmi_size, bits_size, stride;
1209     const BITMAPINFOHEADER *h = &bmi->bmiHeader;
1210     BITMAPFILEHEADER hdr;
1211     DWORD bytes_written;
1212     HANDLE file;
1213     BOOL ret;
1214 
1215     clr_used = h->biBitCount <= 8 ? 1u << h->biBitCount : 0;
1216     stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
1217     bits_size = h->biHeight * stride;
1218     bmi_size = h->biSize + clr_used * sizeof(RGBQUAD);
1219 
1220     hdr.bfType = 0x4d42;
1221     hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + bmi_size;
1222     hdr.bfSize = hdr.bfOffBits + bits_size;
1223     hdr.bfReserved1 = 0;
1224     hdr.bfReserved2 = 0;
1225 
1226     file = CreateFileA(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
1227     ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed, result %u.\n", GetLastError());
1228     ret = WriteFile(file, &hdr, sizeof(hdr), &bytes_written, NULL);
1229     ok(ret && bytes_written == sizeof(hdr), "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1230             ret, bytes_written);
1231     ret = WriteFile(file, bmi, bmi_size, &bytes_written, NULL);
1232     ok(ret && bytes_written == bmi_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1233             ret, bytes_written);
1234     ret = WriteFile(file, bits, bits_size, &bytes_written, NULL);
1235     ok(ret && bytes_written == bits_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1236             ret, bytes_written);
1237     CloseHandle(file);
1238 }
1239 
test_LoadImage_working_directory_run(char * path)1240 static void test_LoadImage_working_directory_run(char *path)
1241 {
1242     DWORD bytes_written;
1243     HANDLE handle;
1244     BOOL ret;
1245     char path_icon[MAX_PATH];
1246     char path_image[MAX_PATH];
1247     static const test_icon_entries_t icon_desc = {32, 32};
1248 
1249     sprintf(path_icon, "%s\\icon.ico", path);
1250     sprintf(path_image,  "%s\\test.bmp", path);
1251 
1252     /* Create Files */
1253     create_ico_file(path_icon, &icon_desc, 1);
1254 
1255     handle = CreateFileA(path_image, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
1256     ok(handle != INVALID_HANDLE_VALUE, "run %s: CreateFileA failed. %u\n", path, GetLastError());
1257     ret = WriteFile(handle, bmpimage, sizeof(bmpimage), &bytes_written, NULL);
1258     ok(ret && bytes_written == sizeof(bmpimage), "run %s: Test file created improperly.\n", path);
1259     CloseHandle(handle);
1260 
1261     /* Test cursor */
1262     handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1263     ok(handle != NULL, "run %s: LoadImage() failed.\n", path);
1264 
1265     ret = DestroyIcon(handle);
1266     ok(ret, "run %s: DestroyIcon failed: %d\n", path, GetLastError());
1267 
1268     /* Test image */
1269     handle = LoadImageA(NULL, "test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
1270     ok(handle != NULL, "run %s: LoadImageA failed.\n", path);
1271 
1272     ret = DeleteObject(handle);
1273     ok(ret, "run %s: DeleteObject failed: %d\n", path, GetLastError());
1274 
1275     /* Cleanup */
1276     ret = DeleteFileA(path_image);
1277     ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
1278     ret = DeleteFileA(path_icon);
1279     ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
1280 }
1281 
test_LoadImage_working_directory(void)1282 static void test_LoadImage_working_directory(void)
1283 {
1284     char old_working_dir[MAX_PATH];
1285     char temp_dir_current[MAX_PATH];
1286     char temp_dir_PATH[MAX_PATH];
1287     char executable_path[MAX_PATH];
1288     int pos_slash;
1289     char old_PATH[10000];
1290     char new_PATH[10000];
1291     BOOL ret;
1292 
1293     GetCurrentDirectoryA(ARRAY_SIZE(old_working_dir), old_working_dir);
1294 
1295     GetTempPathA(ARRAY_SIZE(temp_dir_current), temp_dir_current);
1296     strcat(temp_dir_current, "wine-test-dir-current\\");
1297     GetTempPathA(ARRAY_SIZE(temp_dir_PATH), temp_dir_PATH);
1298     strcat(temp_dir_PATH,    "wine-test-dir-path\\");
1299 
1300     GetModuleFileNameA(NULL, executable_path, ARRAY_SIZE(executable_path));
1301     pos_slash = strrchr(executable_path, '\\') - executable_path;
1302     executable_path[pos_slash + 1] = 0;
1303 
1304     CreateDirectoryA(temp_dir_current, NULL);
1305     CreateDirectoryA(temp_dir_PATH, NULL);
1306 
1307     SetCurrentDirectoryA(temp_dir_current);
1308 
1309     GetEnvironmentVariableA("PATH", old_PATH, ARRAY_SIZE(old_PATH));
1310     sprintf(new_PATH, "%s;%s", old_PATH, temp_dir_PATH);
1311     SetEnvironmentVariableA("PATH", new_PATH);
1312 
1313     test_LoadImage_working_directory_run(temp_dir_current);
1314     test_LoadImage_working_directory_run(executable_path);
1315     test_LoadImage_working_directory_run(temp_dir_PATH);
1316 
1317     SetCurrentDirectoryA(old_working_dir);
1318     SetEnvironmentVariableA("PATH", old_PATH);
1319 
1320     ret = RemoveDirectoryA(temp_dir_current);
1321     ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
1322     ret = RemoveDirectoryA(temp_dir_PATH);
1323     ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
1324 }
1325 
test_LoadImage(void)1326 static void test_LoadImage(void)
1327 {
1328     HANDLE handle;
1329     BOOL ret;
1330     DWORD error;
1331     BITMAPINFOHEADER *bitmap_header;
1332     ICONINFO icon_info;
1333     int i;
1334 
1335 #define ICON_WIDTH 32
1336 #define ICON_HEIGHT 32
1337 #define ICON_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1338 #define ICON_BPP 32
1339 #define ICON_SIZE \
1340     (sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) \
1341     + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1342 
1343     static const test_icon_entries_t icon_desc = {32, 32};
1344 
1345     create_ico_file("icon.ico", &icon_desc, 1);
1346 
1347     /* Test loading an icon as a cursor. */
1348     SetLastError(0xdeadbeef);
1349     handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1350     ok(handle != NULL, "LoadImage() failed.\n");
1351     error = GetLastError();
1352     ok(error == 0 ||
1353         broken(error == 0xdeadbeef) || /* Win9x */
1354         broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1355         "Last error: %u\n", error);
1356 
1357     /* Test the icon information. */
1358     SetLastError(0xdeadbeef);
1359     ret = GetIconInfo(handle, &icon_info);
1360     ok(ret, "GetIconInfo() failed.\n");
1361     error = GetLastError();
1362     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1363 
1364     if (ret)
1365     {
1366         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1367         ok(icon_info.xHotspot == 1, "xHotspot is %u.\n", icon_info.xHotspot);
1368         ok(icon_info.yHotspot == 1, "yHotspot is %u.\n", icon_info.yHotspot);
1369         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1370            "No hbmColor!\n");
1371         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1372     }
1373 
1374     if (pGetIconInfoExA)
1375     {
1376         ICONINFOEXA infoex;
1377         infoex.cbSize = sizeof(infoex);
1378         ret = pGetIconInfoExA( handle, &infoex );
1379         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1380         ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1381         ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1382         ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1383     }
1384     else win_skip( "GetIconInfoEx not available\n" );
1385 
1386     /* Clean up. */
1387     SetLastError(0xdeadbeef);
1388     ret = DestroyCursor(handle);
1389     ok(ret, "DestroyCursor() failed.\n");
1390     error = GetLastError();
1391     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1392 
1393     DeleteFileA("icon.ico");
1394 
1395     /* Test a system icon */
1396     handle = LoadIconA( 0, (LPCSTR)IDI_HAND );
1397     ok(handle != NULL, "LoadImage() failed.\n");
1398     if (pGetIconInfoExA)
1399     {
1400         ICONINFOEXA infoexA;
1401         ICONINFOEXW infoexW;
1402         infoexA.cbSize = sizeof(infoexA);
1403         ret = pGetIconInfoExA( handle, &infoexA );
1404         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1405         ok( infoexA.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexA.wResID );
1406         /* the A version is broken on 64-bit, it truncates the string after the first char */
1407         if (is_win64 && infoexA.szModName[0] && infoexA.szModName[1] == 0)
1408             trace( "GetIconInfoExA broken on Win64\n" );
1409         else
1410             ok( GetModuleHandleA(infoexA.szModName) == GetModuleHandleA("user32.dll"),
1411                 "GetIconInfoEx wrong module %s\n", infoexA.szModName );
1412         ok( infoexA.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoexA.szResName );
1413         infoexW.cbSize = sizeof(infoexW);
1414         ret = pGetIconInfoExW( handle, &infoexW );
1415         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1416         ok( infoexW.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexW.wResID );
1417         ok( GetModuleHandleW(infoexW.szModName) == GetModuleHandleA("user32.dll"),
1418             "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(infoexW.szModName) );
1419         ok( infoexW.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", wine_dbgstr_w(infoexW.szResName) );
1420     }
1421     SetLastError(0xdeadbeef);
1422     DestroyIcon(handle);
1423 
1424     test_LoadImageFile("BMP", bmpimage, sizeof(bmpimage), "bmp", 1);
1425     test_LoadImageFile("BMP (coreinfo)", bmpcoreimage, sizeof(bmpcoreimage), "bmp", 1);
1426     test_LoadImageFile("GIF", gifimage, sizeof(gifimage), "gif", 0);
1427     test_LoadImageFile("GIF (2x2 pixel)", gif4pixel, sizeof(gif4pixel), "gif", 0);
1428     test_LoadImageFile("JPG", jpgimage, sizeof(jpgimage), "jpg", 0);
1429     test_LoadImageFile("PNG", pngimage, sizeof(pngimage), "png", 0);
1430 
1431     /* Check failure for broken BMP images */
1432     bitmap_header = (BITMAPINFOHEADER *)(bmpimage + sizeof(BITMAPFILEHEADER));
1433 
1434     bitmap_header->biHeight = 65536;
1435     test_LoadImageFile("BMP (too high)", bmpimage, sizeof(bmpimage), "bmp", 0);
1436     bitmap_header->biHeight = 1;
1437 
1438     bitmap_header->biWidth = 65536;
1439     test_LoadImageFile("BMP (too wide)", bmpimage, sizeof(bmpimage), "bmp", 0);
1440     bitmap_header->biWidth = 1;
1441 
1442     for (i = 0; i < ARRAY_SIZE(biSize_tests); i++) {
1443         bitmap_header->biSize = biSize_tests[i];
1444         test_LoadImageFile("BMP (broken biSize)", bmpimage, sizeof(bmpimage), "bmp", 0);
1445     }
1446     bitmap_header->biSize = sizeof(BITMAPINFOHEADER);
1447 
1448     test_LoadImageFile("Cursor (invalid dwDIBOffset)", invalid_dwDIBOffset, sizeof(invalid_dwDIBOffset), "cur", 0);
1449 
1450     /* Test in which paths images with a relative path can be found */
1451     test_LoadImage_working_directory();
1452 }
1453 
test_CreateIconFromResource(void)1454 static void test_CreateIconFromResource(void)
1455 {
1456     HANDLE handle;
1457     BOOL ret;
1458     DWORD error;
1459     BITMAPINFOHEADER *icon_header;
1460     INT16 *hotspot;
1461     ICONINFO icon_info;
1462 
1463 #define ICON_RES_WIDTH 32
1464 #define ICON_RES_HEIGHT 32
1465 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1466 #define ICON_RES_BPP 32
1467 #define ICON_RES_SIZE \
1468     (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1469 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1470 
1471     /* Set icon data. */
1472     hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE);
1473 
1474     /* Cursor resources have an extra hotspot, icon resources not. */
1475     hotspot[0] = 3;
1476     hotspot[1] = 3;
1477 
1478     icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1479     icon_header->biSize = sizeof(BITMAPINFOHEADER);
1480     icon_header->biWidth = ICON_WIDTH;
1481     icon_header->biHeight = ICON_HEIGHT*2;
1482     icon_header->biPlanes = 1;
1483     icon_header->biBitCount = ICON_BPP;
1484     icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1485 
1486     /* Test creating a cursor. */
1487     SetLastError(0xdeadbeef);
1488     handle = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1489     ok(handle != NULL, "Create cursor failed.\n");
1490 
1491     /* Test the icon information. */
1492     SetLastError(0xdeadbeef);
1493     ret = GetIconInfo(handle, &icon_info);
1494     ok(ret, "GetIconInfo() failed.\n");
1495     error = GetLastError();
1496     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1497 
1498     if (ret)
1499     {
1500         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1501         ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1502         ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1503         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1504            "No hbmColor!\n");
1505         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1506     }
1507 
1508     if (pGetIconInfoExA)
1509     {
1510         ICONINFOEXA infoex;
1511         infoex.cbSize = sizeof(infoex);
1512         ret = pGetIconInfoExA( handle, &infoex );
1513         ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1514         ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1515         ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1516         ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1517     }
1518 
1519     /* Clean up. */
1520     SetLastError(0xdeadbeef);
1521     ret = DestroyCursor(handle);
1522     ok(ret, "DestroyCursor() failed.\n");
1523     error = GetLastError();
1524     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1525 
1526     /* Test creating an icon. */
1527     SetLastError(0xdeadbeef);
1528     handle = CreateIconFromResource((PBYTE) icon_header, ICON_RES_SIZE, TRUE,
1529 				    0x00030000);
1530     ok(handle != NULL, "Create icon failed.\n");
1531 
1532     /* Test the icon information. */
1533     SetLastError(0xdeadbeef);
1534     ret = GetIconInfo(handle, &icon_info);
1535     ok(ret, "GetIconInfo() failed.\n");
1536     error = GetLastError();
1537     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1538 
1539     if (ret)
1540     {
1541         ok(icon_info.fIcon == TRUE, "fIcon != TRUE.\n");
1542 	/* Icons always have hotspot in the middle */
1543         ok(icon_info.xHotspot == ICON_WIDTH/2, "xHotspot is %u.\n", icon_info.xHotspot);
1544         ok(icon_info.yHotspot == ICON_HEIGHT/2, "yHotspot is %u.\n", icon_info.yHotspot);
1545         ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
1546         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1547     }
1548 
1549     /* Clean up. */
1550     SetLastError(0xdeadbeef);
1551     ret = DestroyCursor(handle);
1552     ok(ret, "DestroyCursor() failed.\n");
1553     error = GetLastError();
1554     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1555 
1556     /* Rejection of NULL pointer crashes at least on WNT4WSSP6, W2KPROSP4, WXPPROSP3
1557      *
1558      * handle = CreateIconFromResource(NULL, ICON_RES_SIZE, TRUE, 0x00030000);
1559      * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
1560      */
1561     HeapFree(GetProcessHeap(), 0, hotspot);
1562 
1563     /* Test creating an animated cursor. */
1564     empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1565     empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
1566     empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
1567     handle = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
1568     ok(handle != NULL, "Create cursor failed.\n");
1569 
1570     /* Test the animated cursor's information. */
1571     SetLastError(0xdeadbeef);
1572     ret = GetIconInfo(handle, &icon_info);
1573     ok(ret, "GetIconInfo() failed.\n");
1574     error = GetLastError();
1575     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1576 
1577     if (ret)
1578     {
1579         ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1580         ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1581         ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1582         ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1583            "No hbmColor!\n");
1584         ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1585     }
1586 
1587     /* Clean up. */
1588     SetLastError(0xdeadbeef);
1589     ret = DestroyCursor(handle);
1590     ok(ret, "DestroyCursor() failed.\n");
1591     error = GetLastError();
1592     ok(error == 0xdeadbeef, "Last error: %u\n", error);
1593 }
1594 
check_cursor_data(HDC hdc,HCURSOR hCursor,void * data,int length)1595 static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
1596 {
1597     char *image = NULL;
1598     BITMAPINFO *info;
1599     ICONINFO iinfo;
1600     DWORD ret;
1601     int i;
1602 
1603     ret = GetIconInfo( hCursor, &iinfo );
1604     ok(ret, "GetIconInfo() failed\n");
1605     if (!ret) return 0;
1606     ret = 0;
1607     info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
1608     ok(info != NULL, "HeapAlloc() failed\n");
1609     if (!info) return 0;
1610 
1611     info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1612     info->bmiHeader.biWidth = 32;
1613     info->bmiHeader.biHeight = 32;
1614     info->bmiHeader.biPlanes = 1;
1615     info->bmiHeader.biBitCount = 32;
1616     info->bmiHeader.biCompression = BI_RGB;
1617     info->bmiHeader.biSizeImage = 32 * 32 * 4;
1618     info->bmiHeader.biXPelsPerMeter = 0;
1619     info->bmiHeader.biYPelsPerMeter = 0;
1620     info->bmiHeader.biClrUsed = 0;
1621     info->bmiHeader.biClrImportant = 0;
1622     image = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
1623     ok(image != NULL, "HeapAlloc() failed\n");
1624     if (!image) goto cleanup;
1625     ret = GetDIBits( hdc, iinfo.hbmColor, 0, 32, image, info, DIB_RGB_COLORS );
1626     ok(ret, "GetDIBits() failed\n");
1627     for (i = 0; ret && i < length / sizeof(COLORREF); i++)
1628     {
1629         ret = color_match( ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1630         ok(ret, "%04x: Expected 0x%x, actually 0x%x\n", i, ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1631     }
1632 cleanup:
1633     HeapFree( GetProcessHeap(), 0, image );
1634     HeapFree( GetProcessHeap(), 0, info );
1635     return ret;
1636 }
1637 
1638 static HCURSOR (WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor, DWORD unk1, DWORD istep, DWORD *rate, DWORD *steps);
test_GetCursorFrameInfo(void)1639 static void test_GetCursorFrameInfo(void)
1640 {
1641     DWORD frame_identifier[] = { 0x10Ad, 0xc001, 0x1c05 };
1642     HBITMAP bmp = NULL, bmpOld = NULL;
1643     DWORD rate, steps;
1644     BITMAPINFOHEADER *icon_header;
1645     BITMAPINFO bitmapInfo;
1646     HDC hdc = NULL;
1647     void *bits = 0;
1648     INT16 *hotspot;
1649     HANDLE h1, h2;
1650     BOOL ret;
1651     int i;
1652 
1653     if (!pGetCursorFrameInfo)
1654     {
1655         win_skip( "GetCursorFrameInfo not supported, skipping tests.\n" );
1656         return;
1657     }
1658 
1659     hdc = CreateCompatibleDC(0);
1660     ok(hdc != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1661     if (!hdc)
1662         return;
1663 
1664     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1665     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1666     bitmapInfo.bmiHeader.biWidth = 3;
1667     bitmapInfo.bmiHeader.biHeight = 3;
1668     bitmapInfo.bmiHeader.biBitCount = 32;
1669     bitmapInfo.bmiHeader.biPlanes = 1;
1670     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1671     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1672     bmp = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1673     ok (bmp && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1674     if (!bmp || !bits)
1675         goto cleanup;
1676     bmpOld = SelectObject(hdc, bmp);
1677 
1678 #define ICON_RES_WIDTH 32
1679 #define ICON_RES_HEIGHT 32
1680 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1681 #define ICON_RES_BPP 32
1682 #define ICON_RES_SIZE \
1683     (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1684 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1685 
1686     /* Set icon data. */
1687     hotspot = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, CRSR_RES_SIZE);
1688 
1689     /* Cursor resources have an extra hotspot, icon resources not. */
1690     hotspot[0] = 3;
1691     hotspot[1] = 3;
1692 
1693     icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1694     icon_header->biSize = sizeof(BITMAPINFOHEADER);
1695     icon_header->biWidth = ICON_WIDTH;
1696     icon_header->biHeight = ICON_HEIGHT*2;
1697     icon_header->biPlanes = 1;
1698     icon_header->biBitCount = ICON_BPP;
1699     icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1700 
1701     /* Creating a static cursor. */
1702     SetLastError(0xdeadbeef);
1703     h1 = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1704     ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1705 
1706     /* Check GetCursorFrameInfo behavior on a static cursor */
1707     rate = steps = 0xdead;
1708     h2 = pGetCursorFrameInfo(h1, 0xdead, 0xdead, &rate, &steps);
1709     ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1710     ok(rate == 0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1711     ok(steps == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1712 
1713     /* Clean up static cursor. */
1714     SetLastError(0xdeadbeef);
1715     ret = DestroyCursor(h1);
1716     ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1717 
1718     /* Creating a single-frame animated cursor. */
1719     empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1720     empty_anicursor.frames[0].data.icon_info.idEntries[0].xHotspot = 3;
1721     empty_anicursor.frames[0].data.icon_info.idEntries[0].yHotspot = 3;
1722     memcpy( &empty_anicursor.frames[0].data.bmi_data.data[0], &frame_identifier[0], sizeof(DWORD) );
1723     SetLastError(0xdeadbeef);
1724     h1 = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
1725     ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1726 
1727     /* Check GetCursorFrameInfo behavior on a single-frame animated cursor */
1728     rate = steps = 0xdead;
1729     h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1730     ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1731     ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1732     ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1733     ok(rate == 0x0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1734     ok(steps == empty_anicursor.header.header.num_steps,
1735         "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1736 
1737     /* Clean up single-frame animated cursor. */
1738     SetLastError(0xdeadbeef);
1739     ret = DestroyCursor(h1);
1740     ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1741 
1742     /* Creating a multi-frame animated cursor. */
1743     for (i=0; i<empty_anicursor3.header.header.num_frames; i++)
1744     {
1745         empty_anicursor3.frames[i].data.icon_info.idType = 2; /* type: cursor */
1746         empty_anicursor3.frames[i].data.icon_info.idEntries[0].xHotspot = 3;
1747         empty_anicursor3.frames[i].data.icon_info.idEntries[0].yHotspot = 3;
1748         memcpy( &empty_anicursor3.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1749     }
1750     SetLastError(0xdeadbeef);
1751     h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1752     ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1753 
1754     /* Check number of steps in multi-frame animated cursor */
1755     i=0;
1756     while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1757         i++;
1758     ok(i == empty_anicursor3.header.header.num_steps,
1759         "Unexpected number of steps in cursor (%d != %d)\n",
1760         i, empty_anicursor3.header.header.num_steps);
1761 
1762     /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor */
1763     for (i=0; i<empty_anicursor3.header.header.num_frames; i++)
1764     {
1765         rate = steps = 0xdead;
1766         h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1767         ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1768         ret = check_cursor_data( hdc, h2, &frame_identifier[i], sizeof(DWORD) );
1769         ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1770         ok(rate == empty_anicursor3.header.header.display_rate,
1771             "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1772             rate, empty_anicursor3.header.header.display_rate);
1773         ok(steps == empty_anicursor3.header.header.num_steps,
1774             "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1775             steps, empty_anicursor3.header.header.num_steps);
1776     }
1777 
1778     /* Check GetCursorFrameInfo behavior on rate 3 of a multi-frame animated cursor */
1779     rate = steps = 0xdead;
1780     h2 = pGetCursorFrameInfo(h1, 0xdead, 3, &rate, &steps);
1781     ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1782     ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1783        || broken(rate == ~0) /*win2k (sporadic)*/,
1784         "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1785     ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1786        || broken(steps == 0) /*win2k (sporadic)*/,
1787         "GetCursorFrameInfo() unexpected param 5 value (0x%x != 0xdead).\n", steps);
1788 
1789     /* Clean up multi-frame animated cursor. */
1790     SetLastError(0xdeadbeef);
1791     ret = DestroyCursor(h1);
1792     ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1793 
1794     /* Create a multi-frame animated cursor with num_steps == 1 */
1795     empty_anicursor3.header.header.num_steps = 1;
1796     SetLastError(0xdeadbeef);
1797     h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1798     ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1799 
1800     /* Check number of steps in multi-frame animated cursor (mismatch between steps and frames) */
1801     i=0;
1802     while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1803         i++;
1804     ok(i == empty_anicursor3.header.header.num_steps,
1805         "Unexpected number of steps in cursor (%d != %d)\n",
1806         i, empty_anicursor3.header.header.num_steps);
1807 
1808     /* Check GetCursorFrameInfo behavior on rate 0 for a multi-frame animated cursor (with num_steps == 1) */
1809     rate = steps = 0xdead;
1810     h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1811     ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1812     ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1813     ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1814     ok(rate == empty_anicursor3.header.header.display_rate,
1815         "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1816         rate, empty_anicursor3.header.header.display_rate);
1817     ok(steps == ~0 || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/,
1818         "GetCursorFrameInfo() unexpected param 5 value (%d != ~0).\n", steps);
1819 
1820     /* Check GetCursorFrameInfo behavior on rate 1 for a multi-frame animated cursor (with num_steps == 1) */
1821     rate = steps = 0xdead;
1822     h2 = pGetCursorFrameInfo(h1, 0xdead, 1, &rate, &steps);
1823     ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1824     ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1825        || broken(rate == ~0) /*win2k (sporadic)*/,
1826         "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1827     ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1828        || broken(steps == 0) /*win2k (sporadic)*/,
1829         "GetCursorFrameInfo() unexpected param 5 value (%d != 0xdead).\n", steps);
1830 
1831     /* Clean up multi-frame animated cursor. */
1832     SetLastError(0xdeadbeef);
1833     ret = DestroyCursor(h1);
1834     ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1835 
1836     /* Creating a multi-frame animated cursor with rate data. */
1837     for (i=0; i<empty_anicursor3_seq.header.header.num_frames; i++)
1838     {
1839         empty_anicursor3_seq.frames[i].data.icon_info.idType = 2; /* type: cursor */
1840         empty_anicursor3_seq.frames[i].data.icon_info.idEntries[0].xHotspot = 3;
1841         empty_anicursor3_seq.frames[i].data.icon_info.idEntries[0].yHotspot = 3;
1842         memcpy( &empty_anicursor3_seq.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1843     }
1844     SetLastError(0xdeadbeef);
1845     h1 = CreateIconFromResource((PBYTE) &empty_anicursor3_seq, sizeof(empty_anicursor3_seq), FALSE, 0x00030000);
1846     ok(h1 != NULL, "Create cursor failed (error = %x).\n", GetLastError());
1847 
1848     /* Check number of steps in multi-frame animated cursor with rate data */
1849     i=0;
1850     while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1851         i++;
1852     ok(i == empty_anicursor3_seq.header.header.num_steps,
1853         "Unexpected number of steps in cursor (%d != %d)\n",
1854         i, empty_anicursor3_seq.header.header.num_steps);
1855 
1856     /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor with rate data */
1857     for (i=0; i<empty_anicursor3_seq.header.header.num_frames; i++)
1858     {
1859         int frame_id = empty_anicursor3_seq.seq.order[i];
1860 
1861         rate = steps = 0xdead;
1862         h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1863         ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1864         ret = check_cursor_data( hdc, h2, &frame_identifier[frame_id], sizeof(DWORD) );
1865         ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1866         ok(rate == empty_anicursor3_seq.rates.rate[i],
1867             "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1868             rate, empty_anicursor3_seq.rates.rate[i]);
1869         ok(steps == empty_anicursor3_seq.header.header.num_steps,
1870             "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1871             steps, empty_anicursor3_seq.header.header.num_steps);
1872     }
1873 
1874     /* Clean up multi-frame animated cursor with rate data. */
1875     SetLastError(0xdeadbeef);
1876     ret = DestroyCursor(h1);
1877     ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1878 
1879     HeapFree(GetProcessHeap(), 0, hotspot);
1880 cleanup:
1881     if(bmpOld) SelectObject(hdc, bmpOld);
1882     if(bmp) DeleteObject(bmp);
1883     if(hdc) DeleteDC(hdc);
1884 }
1885 
create_test_icon(HDC hdc,int width,int height,int bpp,BOOL maskvalue,UINT32 * color,int colorSize)1886 static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
1887                               BOOL maskvalue, UINT32 *color, int colorSize)
1888 {
1889     ICONINFO iconInfo;
1890     BITMAPINFO bitmapInfo;
1891     void *buffer = NULL;
1892     UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000;
1893 
1894     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1895     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1896     bitmapInfo.bmiHeader.biWidth = width;
1897     bitmapInfo.bmiHeader.biHeight = height;
1898     bitmapInfo.bmiHeader.biPlanes = 1;
1899     bitmapInfo.bmiHeader.biBitCount = bpp;
1900     bitmapInfo.bmiHeader.biCompression = BI_RGB;
1901     bitmapInfo.bmiHeader.biSizeImage = colorSize;
1902 
1903     iconInfo.fIcon = TRUE;
1904     iconInfo.xHotspot = 0;
1905     iconInfo.yHotspot = 0;
1906 
1907     iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask );
1908     if(!iconInfo.hbmMask) return NULL;
1909 
1910     iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &buffer, NULL, 0);
1911     if(!iconInfo.hbmColor || !buffer)
1912     {
1913         DeleteObject(iconInfo.hbmMask);
1914         return NULL;
1915     }
1916 
1917     memcpy(buffer, color, colorSize);
1918 
1919     return CreateIconIndirect(&iconInfo);
1920 }
1921 
check_alpha_draw(HDC hdc,BOOL drawiconex,BOOL alpha,int bpp,int line)1922 static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
1923 {
1924     HICON hicon;
1925     UINT32 color[2];
1926     COLORREF modern_expected, legacy_expected, result;
1927 
1928     color[0] = 0x00A0B0C0;
1929     color[1] = alpha ? 0xFF000000 : 0x00000000;
1930     modern_expected = alpha ? 0x00FFFFFF : 0x00C0B0A0;
1931     legacy_expected = 0x00C0B0A0;
1932 
1933     hicon = create_test_icon(hdc, 2, 1, bpp, 0, color, sizeof(color));
1934     if (!hicon) return;
1935 
1936     SetPixelV(hdc, 0, 0, 0x00FFFFFF);
1937 
1938     if(drawiconex)
1939         DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL);
1940     else
1941         DrawIcon(hdc, 0, 0, hicon);
1942 
1943     result = GetPixel(hdc, 0, 0);
1944     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1945         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1946         "%s. Expected a close match to %06X (modern) or %06X (legacy) with %s. "
1947         "Got %06X from line %d\n",
1948         alpha ? "Alpha blending" : "Not alpha blending", modern_expected, legacy_expected,
1949         drawiconex ? "DrawIconEx" : "DrawIcon", result, line);
1950 }
1951 
check_DrawIcon(HDC hdc,BOOL maskvalue,UINT32 color,int bpp,COLORREF background,COLORREF modern_expected,COLORREF legacy_expected,int line)1952 static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
1953                            COLORREF modern_expected, COLORREF legacy_expected, int line)
1954 {
1955     COLORREF result;
1956     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1957     if (!hicon) return;
1958     SetPixelV(hdc, 0, 0, background);
1959     SetPixelV(hdc, GetSystemMetrics(SM_CXICON)-1, GetSystemMetrics(SM_CYICON)-1, background);
1960     SetPixelV(hdc, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON), background);
1961     DrawIcon(hdc, 0, 0, hicon);
1962     result = GetPixel(hdc, 0, 0);
1963 
1964     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1965         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1966         "Overlaying Mask %d on Color %06X with DrawIcon. "
1967         "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1968         maskvalue, color, modern_expected, legacy_expected, result, line);
1969 
1970     result = GetPixel(hdc, GetSystemMetrics(SM_CXICON)-1, GetSystemMetrics(SM_CYICON)-1);
1971 
1972     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
1973         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
1974         "Overlaying Mask %d on Color %06X with DrawIcon. "
1975         "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1976         maskvalue, color, modern_expected, legacy_expected, result, line);
1977 
1978     result = GetPixel(hdc, GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
1979 
1980     ok (color_match(result, background),
1981         "Overlaying Mask %d on Color %06X with DrawIcon. "
1982         "Expected unchanged background color %06X. Got %06X from line %d\n",
1983         maskvalue, color, background, result, line);
1984 }
1985 
test_DrawIcon(void)1986 static void test_DrawIcon(void)
1987 {
1988     BITMAPINFO bitmapInfo;
1989     HDC hdcDst = NULL;
1990     HBITMAP bmpDst = NULL;
1991     HBITMAP bmpOld = NULL;
1992     void *bits = 0;
1993 
1994     hdcDst = CreateCompatibleDC(0);
1995     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1996     if (!hdcDst)
1997         return;
1998 
1999     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2000     {
2001         skip("Windows will distort DrawIcon colors at 8-bpp and less due to palettizing.\n");
2002         goto cleanup;
2003     }
2004 
2005     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2006     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2007     bitmapInfo.bmiHeader.biWidth = GetSystemMetrics(SM_CXICON)+1;
2008     bitmapInfo.bmiHeader.biHeight = GetSystemMetrics(SM_CYICON)+1;
2009     bitmapInfo.bmiHeader.biBitCount = 32;
2010     bitmapInfo.bmiHeader.biPlanes = 1;
2011     bitmapInfo.bmiHeader.biCompression = BI_RGB;
2012     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2013 
2014     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2015     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2016     if (!bmpDst || !bits)
2017         goto cleanup;
2018     bmpOld = SelectObject(hdcDst, bmpDst);
2019 
2020     /* Mask is only heeded if alpha channel is always zero */
2021     check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2022     check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
2023 
2024     /* Test alpha blending */
2025     /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
2026     check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2027     check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
2028 
2029     check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2030     check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2031     check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
2032     check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
2033 
2034     check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2035     check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2036 
2037     /* Test detecting of alpha channel */
2038     /* If a single pixel's alpha channel is non-zero, the icon
2039        will be alpha blended, otherwise it will be draw with
2040        and + xor blts. */
2041     check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__);
2042     check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__);
2043 
2044 cleanup:
2045     if(bmpOld)
2046         SelectObject(hdcDst, bmpOld);
2047     if(bmpDst)
2048         DeleteObject(bmpDst);
2049     if(hdcDst)
2050         DeleteDC(hdcDst);
2051 }
2052 
check_DrawIconEx(HDC hdc,BOOL maskvalue,UINT32 color,int bpp,UINT flags,COLORREF background,COLORREF modern_expected,COLORREF legacy_expected,int line)2053 static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background,
2054                              COLORREF modern_expected, COLORREF legacy_expected, int line)
2055 {
2056     COLORREF result;
2057     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2058     if (!hicon) return;
2059     SetPixelV(hdc, 0, 0, background);
2060     DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags);
2061     result = GetPixel(hdc, 0, 0);
2062 
2063     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
2064         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
2065         "Overlaying Mask %d on Color %06X with DrawIconEx flags %08X. "
2066         "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
2067         maskvalue, color, flags, modern_expected, legacy_expected, result, line);
2068 }
2069 
test_DrawIconEx(void)2070 static void test_DrawIconEx(void)
2071 {
2072     BITMAPINFO bitmapInfo;
2073     HDC hdcDst = NULL;
2074     HBITMAP bmpDst = NULL;
2075     HBITMAP bmpOld = NULL;
2076     void *bits = 0;
2077 
2078     hdcDst = CreateCompatibleDC(0);
2079     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
2080     if (!hdcDst)
2081         return;
2082 
2083     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2084     {
2085         skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
2086         goto cleanup;
2087     }
2088 
2089     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2090     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2091     bitmapInfo.bmiHeader.biWidth = 1;
2092     bitmapInfo.bmiHeader.biHeight = 1;
2093     bitmapInfo.bmiHeader.biBitCount = 32;
2094     bitmapInfo.bmiHeader.biPlanes = 1;
2095     bitmapInfo.bmiHeader.biCompression = BI_RGB;
2096     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2097     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2098     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2099     if (!bmpDst || !bits)
2100         goto cleanup;
2101     bmpOld = SelectObject(hdcDst, bmpDst);
2102 
2103     /* Test null, image only, and mask only drawing */
2104     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
2105     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
2106 
2107     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00000000, 0x00000000, __LINE__);
2108     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
2109 
2110     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2111     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2112 
2113     /* Test normal drawing */
2114     check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2115     check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
2116     check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2117 
2118     /* Test alpha blending */
2119     /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
2120     check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
2121 
2122     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2123     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2124     check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
2125     check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
2126 
2127     check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2128     check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2129 
2130     /* Test detecting of alpha channel */
2131     /* If a single pixel's alpha channel is non-zero, the icon
2132        will be alpha blended, otherwise it will be draw with
2133        and + xor blts. */
2134     check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
2135     check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
2136 
2137 cleanup:
2138     if(bmpOld)
2139         SelectObject(hdcDst, bmpOld);
2140     if(bmpDst)
2141         DeleteObject(bmpDst);
2142     if(hdcDst)
2143         DeleteDC(hdcDst);
2144 }
2145 
check_DrawState_Size(HDC hdc,BOOL maskvalue,UINT32 color,int bpp,HBRUSH hbr,UINT flags,int line)2146 static void check_DrawState_Size(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags, int line)
2147 {
2148     COLORREF result, background;
2149     BOOL passed[2];
2150     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2151     background = 0x00FFFFFF;
2152     /* Set color of the 2 pixels that will be checked afterwards */
2153     SetPixelV(hdc, 0, 0, background);
2154     SetPixelV(hdc, 2, 2, background);
2155 
2156     /* Let DrawState calculate the size of the icon (it's 1x1) */
2157     DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, (DST_ICON | flags ));
2158 
2159     result = GetPixel(hdc, 0, 0);
2160     passed[0] = color_match(result, background);
2161     result = GetPixel(hdc, 2, 2);
2162     passed[0] = passed[0] & color_match(result, background);
2163 
2164     /* Check if manually specifying the icon size DOESN'T work */
2165 
2166     /* IMPORTANT: For Icons, DrawState wants the size of the source image, not the
2167      *            size in which it should be ultimately drawn. Therefore giving
2168      *            width/height 2x2 if the icon is only 1x1 pixels in size should
2169      *            result in drawing it with size 1x1. The size parameters must be
2170      *            ignored if a Icon has to be drawn! */
2171     DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 2, 2, (DST_ICON | flags ));
2172 
2173     result = GetPixel(hdc, 0, 0);
2174     passed[1] = color_match(result, background);
2175     result = GetPixel(hdc, 2, 2);
2176     passed[1] = passed[0] & color_match(result, background);
2177 
2178     if(!passed[0]&&!passed[1])
2179         ok (passed[1],
2180         "DrawState failed to draw a 1x1 Icon in the correct size, independent of the "
2181         "width and height settings passed to it, for Icon with: Overlaying Mask %d on "
2182         "Color %06X with flags %08X. Line %d\n",
2183         maskvalue, color, (DST_ICON | flags), line);
2184     else if(!passed[1])
2185         ok (passed[1],
2186         "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2187         "parameters passed to it are bigger than the real Icon size, for Icon with: Overlaying "
2188         "Mask %d on Color %06X with flags %08X. Line %d\n",
2189         maskvalue, color, (DST_ICON | flags), line);
2190     else
2191         ok (passed[0],
2192         "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2193         "parameters passed to it are 0, for Icon with: Overlaying Mask %d on "
2194         "Color %06X with flags %08X. Line %d\n",
2195         maskvalue, color, (DST_ICON | flags), line);
2196 }
2197 
check_DrawState_Color(HDC hdc,BOOL maskvalue,UINT32 color,int bpp,HBRUSH hbr,UINT flags,COLORREF background,COLORREF modern_expected,COLORREF legacy_expected,int line)2198 static void check_DrawState_Color(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags,
2199                              COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
2200 {
2201     COLORREF result;
2202     HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2203     if (!hicon) return;
2204     /* Set color of the pixel that will be checked afterwards */
2205     SetPixelV(hdc, 1, 1, background);
2206 
2207     DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, ( DST_ICON | flags ));
2208 
2209     /* Check the color of the pixel is correct */
2210     result = GetPixel(hdc, 1, 1);
2211 
2212     ok (color_match(result, modern_expected) ||         /* Windows 2000 and up */
2213         broken(color_match(result, legacy_expected)),   /* Windows NT 4.0, 9X and below */
2214         "DrawState drawing Icon with Overlaying Mask %d on Color %06X with flags %08X. "
2215         "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
2216         maskvalue, color, (DST_ICON | flags), modern_expected, legacy_expected, result, line);
2217 }
2218 
test_DrawState(void)2219 static void test_DrawState(void)
2220 {
2221     BITMAPINFO bitmapInfo;
2222     HDC hdcDst = NULL;
2223     HBITMAP bmpDst = NULL;
2224     HBITMAP bmpOld = NULL;
2225     void *bits = 0;
2226 
2227     hdcDst = CreateCompatibleDC(0);
2228     ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
2229     if (!hdcDst)
2230         return;
2231 
2232     if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2233     {
2234         skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
2235         goto cleanup;
2236     }
2237 
2238     memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2239     bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2240     bitmapInfo.bmiHeader.biWidth = 3;
2241     bitmapInfo.bmiHeader.biHeight = 3;
2242     bitmapInfo.bmiHeader.biBitCount = 32;
2243     bitmapInfo.bmiHeader.biPlanes = 1;
2244     bitmapInfo.bmiHeader.biCompression = BI_RGB;
2245     bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2246     bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2247     ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2248     if (!bmpDst || !bits)
2249         goto cleanup;
2250     bmpOld = SelectObject(hdcDst, bmpDst);
2251 
2252     /* potential flags to test with DrawState are: */
2253     /* DSS_DISABLED embosses the icon */
2254     /* DSS_MONO draw Icon using a brush as parameter 5 */
2255     /* DSS_NORMAL draw Icon without any modifications */
2256     /* DSS_UNION draw the Icon dithered */
2257 
2258     check_DrawState_Size(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, __LINE__);
2259     check_DrawState_Color(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2260 
2261 cleanup:
2262     if(bmpOld)
2263         SelectObject(hdcDst, bmpOld);
2264     if(bmpDst)
2265         DeleteObject(bmpDst);
2266     if(hdcDst)
2267         DeleteDC(hdcDst);
2268 }
2269 
2270 static DWORD parent_id;
2271 
set_cursor_thread(void * arg)2272 static DWORD CALLBACK set_cursor_thread( void *arg )
2273 {
2274     HCURSOR ret;
2275 
2276     PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE );  /* create a msg queue */
2277     if (parent_id)
2278     {
2279         BOOL ret = AttachThreadInput( GetCurrentThreadId(), parent_id, TRUE );
2280         ok( ret, "AttachThreadInput failed\n" );
2281     }
2282     if (arg) ret = SetCursor( (HCURSOR)arg );
2283     else ret = GetCursor();
2284     return (DWORD_PTR)ret;
2285 }
2286 
test_SetCursor(void)2287 static void test_SetCursor(void)
2288 {
2289     static const BYTE bmp_bits[4096];
2290     ICONINFO cursorInfo;
2291     HCURSOR cursor, old_cursor, global_cursor = 0;
2292     DWORD error, id, result;
2293     UINT display_bpp;
2294     HDC hdc;
2295     HANDLE thread;
2296     CURSORINFO info;
2297 
2298     if (pGetCursorInfo)
2299     {
2300         memset( &info, 0, sizeof(info) );
2301         info.cbSize = sizeof(info);
2302         if (!pGetCursorInfo( &info ))
2303         {
2304             win_skip( "GetCursorInfo not working\n" );
2305             pGetCursorInfo = NULL;
2306         }
2307         else global_cursor = info.hCursor;
2308     }
2309     cursor = GetCursor();
2310     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2311     WaitForSingleObject( thread, 1000 );
2312     GetExitCodeThread( thread, &result );
2313     ok( result == (DWORD_PTR)cursor, "wrong thread cursor %x/%p\n", result, cursor );
2314 
2315     hdc = GetDC(0);
2316     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2317     ReleaseDC(0, hdc);
2318 
2319     cursorInfo.fIcon = FALSE;
2320     cursorInfo.xHotspot = 0;
2321     cursorInfo.yHotspot = 0;
2322     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2323     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2324 
2325     cursor = CreateIconIndirect(&cursorInfo);
2326     ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2327     old_cursor = SetCursor( cursor );
2328 
2329     if (pGetCursorInfo)
2330     {
2331         info.cbSize = sizeof(info);
2332         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2333         /* global cursor doesn't change since we don't have a window */
2334         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2335             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2336     }
2337     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2338     WaitForSingleObject( thread, 1000 );
2339     GetExitCodeThread( thread, &result );
2340     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2341 
2342     SetCursor( 0 );
2343     ok( GetCursor() == 0, "wrong cursor %p\n", GetCursor() );
2344     thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2345     WaitForSingleObject( thread, 1000 );
2346     GetExitCodeThread( thread, &result );
2347     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2348 
2349     thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2350     WaitForSingleObject( thread, 1000 );
2351     GetExitCodeThread( thread, &result );
2352     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2353     ok( GetCursor() == 0, "wrong cursor %p/0\n", GetCursor() );
2354 
2355     parent_id = GetCurrentThreadId();
2356     thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2357     WaitForSingleObject( thread, 1000 );
2358     GetExitCodeThread( thread, &result );
2359     ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2360     ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor );
2361 
2362     if (pGetCursorInfo)
2363     {
2364         info.cbSize = sizeof(info);
2365         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2366         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2367             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2368     }
2369     SetCursor( old_cursor );
2370     DestroyCursor( cursor );
2371 
2372     SetLastError( 0xdeadbeef );
2373     cursor = SetCursor( (HCURSOR)0xbadbad );
2374     error = GetLastError();
2375     ok( cursor == 0, "wrong cursor %p/0\n", cursor );
2376     ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ),  /* win9x */
2377         "wrong error %u\n", error );
2378 
2379     if (pGetCursorInfo)
2380     {
2381         info.cbSize = sizeof(info);
2382         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2383         ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2384             "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2385     }
2386 }
2387 
2388 static HANDLE event_start, event_next;
2389 
show_cursor_thread(void * arg)2390 static DWORD CALLBACK show_cursor_thread( void *arg )
2391 {
2392     DWORD count = (DWORD_PTR)arg;
2393     int ret;
2394 
2395     PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE );  /* create a msg queue */
2396     if (parent_id)
2397     {
2398         BOOL ret = AttachThreadInput( GetCurrentThreadId(), parent_id, TRUE );
2399         ok( ret, "AttachThreadInput failed\n" );
2400     }
2401     if (!count) ret = ShowCursor( FALSE );
2402     else while (count--) ret = ShowCursor( TRUE );
2403     SetEvent( event_start );
2404     WaitForSingleObject( event_next, 2000 );
2405     return ret;
2406 }
2407 
test_ShowCursor(void)2408 static void test_ShowCursor(void)
2409 {
2410     int count;
2411     DWORD id, result;
2412     HANDLE thread;
2413     CURSORINFO info;
2414 
2415     if (pGetCursorInfo)
2416     {
2417         memset( &info, 0, sizeof(info) );
2418         info.cbSize = sizeof(info);
2419         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2420         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2421     }
2422 
2423     event_start = CreateEventW( NULL, FALSE, FALSE, NULL );
2424     event_next = CreateEventW( NULL, FALSE, FALSE, NULL );
2425 
2426     count = ShowCursor( TRUE );
2427     ok( count == 1, "wrong count %d\n", count );
2428     count = ShowCursor( TRUE );
2429     ok( count == 2, "wrong count %d\n", count );
2430     count = ShowCursor( FALSE );
2431     ok( count == 1, "wrong count %d\n", count );
2432     count = ShowCursor( FALSE );
2433     ok( count == 0, "wrong count %d\n", count );
2434     count = ShowCursor( FALSE );
2435     ok( count == -1, "wrong count %d\n", count );
2436     count = ShowCursor( FALSE );
2437     ok( count == -2, "wrong count %d\n", count );
2438 
2439     if (pGetCursorInfo)
2440     {
2441         info.cbSize = sizeof(info);
2442         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2443         /* global show count is not affected since we don't have a window */
2444         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2445     }
2446 
2447     parent_id = 0;
2448     thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2449     WaitForSingleObject( event_start, 1000 );
2450     count = ShowCursor( FALSE );
2451     ok( count == -3, "wrong count %d\n", count );
2452     SetEvent( event_next );
2453     WaitForSingleObject( thread, 1000 );
2454     GetExitCodeThread( thread, &result );
2455     ok( result == -1, "wrong thread count %d\n", result );
2456     count = ShowCursor( FALSE );
2457     ok( count == -4, "wrong count %d\n", count );
2458 
2459     thread = CreateThread( NULL, 0, show_cursor_thread, (void *)1, 0, &id );
2460     WaitForSingleObject( event_start, 1000 );
2461     count = ShowCursor( TRUE );
2462     ok( count == -3, "wrong count %d\n", count );
2463     SetEvent( event_next );
2464     WaitForSingleObject( thread, 1000 );
2465     GetExitCodeThread( thread, &result );
2466     ok( result == 1, "wrong thread count %d\n", result );
2467     count = ShowCursor( TRUE );
2468     ok( count == -2, "wrong count %d\n", count );
2469 
2470     parent_id = GetCurrentThreadId();
2471     thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2472     WaitForSingleObject( event_start, 1000 );
2473     count = ShowCursor( TRUE );
2474     ok( count == -2, "wrong count %d\n", count );
2475     SetEvent( event_next );
2476     WaitForSingleObject( thread, 1000 );
2477     GetExitCodeThread( thread, &result );
2478     ok( result == -3, "wrong thread count %d\n", result );
2479     count = ShowCursor( FALSE );
2480     ok( count == -2, "wrong count %d\n", count );
2481 
2482     thread = CreateThread( NULL, 0, show_cursor_thread, (void *)3, 0, &id );
2483     WaitForSingleObject( event_start, 1000 );
2484     count = ShowCursor( TRUE );
2485     ok( count == 2, "wrong count %d\n", count );
2486     SetEvent( event_next );
2487     WaitForSingleObject( thread, 1000 );
2488     GetExitCodeThread( thread, &result );
2489     ok( result == 1, "wrong thread count %d\n", result );
2490     count = ShowCursor( FALSE );
2491     ok( count == -2, "wrong count %d\n", count );
2492 
2493     if (pGetCursorInfo)
2494     {
2495         info.cbSize = sizeof(info);
2496         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2497         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2498     }
2499 
2500     count = ShowCursor( TRUE );
2501     ok( count == -1, "wrong count %d\n", count );
2502     count = ShowCursor( TRUE );
2503     ok( count == 0, "wrong count %d\n", count );
2504 
2505     if (pGetCursorInfo)
2506     {
2507         info.cbSize = sizeof(info);
2508         ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2509         ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2510     }
2511 }
2512 
2513 
test_DestroyCursor(void)2514 static void test_DestroyCursor(void)
2515 {
2516     static const BYTE bmp_bits[4096];
2517     ICONINFO cursorInfo, new_info;
2518     HCURSOR cursor, cursor2, new_cursor;
2519     BOOL ret;
2520     DWORD error;
2521     UINT display_bpp;
2522     HDC hdc;
2523 
2524     hdc = GetDC(0);
2525     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2526     ReleaseDC(0, hdc);
2527 
2528     cursorInfo.fIcon = FALSE;
2529     cursorInfo.xHotspot = 0;
2530     cursorInfo.yHotspot = 0;
2531     cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2532     cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2533 
2534     cursor = CreateIconIndirect(&cursorInfo);
2535     ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2536     if(!cursor) {
2537         return;
2538     }
2539     SetCursor(cursor);
2540 
2541     SetLastError(0xdeadbeef);
2542     ret = DestroyCursor(cursor);
2543     ok(!ret || broken(ret)  /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n");
2544     error = GetLastError();
2545     ok(error == 0xdeadbeef, "Last error: %u\n", error);
2546 
2547     new_cursor = GetCursor();
2548     if (ret)  /* win9x replaces cursor by another one on destroy */
2549         ok(new_cursor != cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2550     else
2551         ok(new_cursor == cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2552 
2553     SetLastError(0xdeadbeef);
2554     ret = GetIconInfo( cursor, &new_info );
2555     ok( !ret || broken(ret), /* nt4 */ "GetIconInfo succeeded\n" );
2556     ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE ||
2557         broken(GetLastError() == 0xdeadbeef), /* win9x */
2558         "wrong error %u\n", GetLastError() );
2559 
2560     if (ret)  /* nt4 delays destruction until cursor changes */
2561     {
2562         DeleteObject( new_info.hbmColor );
2563         DeleteObject( new_info.hbmMask );
2564 
2565         SetLastError(0xdeadbeef);
2566         ret = DestroyCursor( cursor );
2567         ok( !ret, "DestroyCursor succeeded\n" );
2568         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2569             "wrong error %u\n", GetLastError() );
2570 
2571         SetLastError(0xdeadbeef);
2572         cursor2 = SetCursor( cursor );
2573         ok( cursor2 == cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2574         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2575             "wrong error %u\n", GetLastError() );
2576     }
2577     else
2578     {
2579         SetLastError(0xdeadbeef);
2580         cursor2 = CopyCursor( cursor );
2581         ok(!cursor2, "CopyCursor succeeded\n" );
2582         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE ||
2583             broken(GetLastError() == 0xdeadbeef), /* win9x */
2584             "wrong error %u\n", GetLastError() );
2585 
2586         SetLastError(0xdeadbeef);
2587         ret = DestroyCursor( cursor );
2588         if (new_cursor != cursor)  /* win9x */
2589             ok( ret, "DestroyCursor succeeded\n" );
2590         else
2591             ok( !ret, "DestroyCursor succeeded\n" );
2592         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2593             "wrong error %u\n", GetLastError() );
2594 
2595         SetLastError(0xdeadbeef);
2596         cursor2 = SetCursor( cursor );
2597         ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2598         ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2599             "wrong error %u\n", GetLastError() );
2600     }
2601 
2602     cursor2 = GetCursor();
2603     ok(cursor2 == new_cursor, "GetCursor returned %p/%p\n", cursor2, new_cursor);
2604 
2605     SetLastError(0xdeadbeef);
2606     cursor2 = SetCursor( 0 );
2607     if (new_cursor != cursor)  /* win9x */
2608         ok(cursor2 == new_cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2609     else
2610         ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2611     ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
2612 
2613     cursor2 = GetCursor();
2614     ok(!cursor2, "GetCursor returned %p/%p\n", cursor2, cursor);
2615 
2616     SetLastError(0xdeadbeef);
2617     ret = DestroyCursor(cursor);
2618     if (new_cursor != cursor)  /* win9x */
2619         ok( ret, "DestroyCursor succeeded\n" );
2620     else
2621         ok( !ret, "DestroyCursor succeeded\n" );
2622     ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2623         "wrong error %u\n", GetLastError() );
2624 
2625     DeleteObject(cursorInfo.hbmMask);
2626     DeleteObject(cursorInfo.hbmColor);
2627 
2628     /* Try testing DestroyCursor() now using LoadCursor() cursors. */
2629     cursor = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2630 
2631     SetLastError(0xdeadbeef);
2632     ret = DestroyCursor(cursor);
2633     ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n");
2634     error = GetLastError();
2635     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2636 
2637     /* Try setting the cursor to a destroyed OEM cursor. */
2638     SetLastError(0xdeadbeef);
2639     SetCursor(cursor);
2640     error = GetLastError();
2641     ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2642 
2643     /* Check if LoadCursor() returns the same handle with the same icon. */
2644     cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2645     ok(cursor2 == cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2646 
2647     /* Check if LoadCursor() returns the same handle with a different icon. */
2648     cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_WAIT);
2649     ok(cursor2 != cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2650 }
2651 
test_PrivateExtractIcons(void)2652 static void test_PrivateExtractIcons(void)
2653 {
2654     HICON icon;
2655     UINT ret;
2656 
2657     static const test_icon_entries_t icon_desc[] = {{0,0,TRUE}, {16,16,TRUE}, {32,32}, {64,64,TRUE}};
2658 
2659     create_ico_file("extract.ico", icon_desc, ARRAY_SIZE(icon_desc));
2660 
2661     ret = PrivateExtractIconsA("extract.ico", 0, 32, 32, &icon, NULL, 1, 0);
2662     ok(ret == 1, "PrivateExtractIconsA returned %u\n", ret);
2663     ok(icon != NULL, "icon == NULL\n");
2664 
2665     test_icon_info(icon, 32, 32, 32, 32);
2666     DestroyIcon(icon);
2667 
2668     DeleteFileA("extract.ico");
2669 }
2670 
test_monochrome_icon(void)2671 static void test_monochrome_icon(void)
2672 {
2673     HANDLE handle;
2674     BOOL ret;
2675     DWORD bytes_written;
2676     CURSORICONFILEDIR *icon_data;
2677     CURSORICONFILEDIRENTRY *icon_entry;
2678     BITMAPINFO *bitmap_info;
2679     BITMAPCOREINFO *core_info;
2680     ICONINFO icon_info;
2681     ULONG icon_size;
2682     BOOL monochrome, use_core_info;
2683 
2684     icon_data = HeapAlloc(GetProcessHeap(), 0, sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) +
2685                                                2 * sizeof(RGBQUAD) + sizeof(ULONG));
2686 
2687     for (monochrome = FALSE; monochrome <= TRUE; monochrome++)
2688     for (use_core_info = FALSE; use_core_info <= TRUE; use_core_info++)
2689     {
2690         trace("%s, %s\n",
2691               monochrome ? "monochrome" : "colored",
2692               use_core_info ? "core info" : "bitmap info");
2693 
2694         icon_size = sizeof(CURSORICONFILEDIR) +
2695                     (use_core_info ? sizeof(BITMAPCOREHEADER) : sizeof(BITMAPINFOHEADER)) +
2696                     /* 2 * sizeof(RGBTRIPLE) + padding comes out the same */
2697                     2 * sizeof(RGBQUAD) +
2698                     sizeof(ULONG);
2699         ZeroMemory(icon_data, icon_size);
2700         icon_data->idReserved = 0;
2701         icon_data->idType = 1;
2702         icon_data->idCount = 1;
2703 
2704         icon_entry = icon_data->idEntries;
2705         icon_entry->bWidth = 1;
2706         icon_entry->bHeight = 1;
2707         icon_entry->bColorCount = 0;
2708         icon_entry->bReserved = 0;
2709         icon_entry->xHotspot = 0;
2710         icon_entry->yHotspot = 0;
2711         icon_entry->dwDIBSize = icon_size - sizeof(CURSORICONFILEDIR);
2712         icon_entry->dwDIBOffset = sizeof(CURSORICONFILEDIR);
2713 
2714         if (use_core_info)
2715         {
2716             core_info = (BITMAPCOREINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2717             core_info->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
2718             core_info->bmciHeader.bcWidth = 1;
2719             core_info->bmciHeader.bcHeight = 2;
2720             core_info->bmciHeader.bcPlanes = 1;
2721             core_info->bmciHeader.bcBitCount = 1;
2722             core_info->bmciColors[0].rgbtBlue = monochrome ? 0x00 : 0xff;
2723             core_info->bmciColors[0].rgbtGreen = 0x00;
2724             core_info->bmciColors[0].rgbtRed = 0x00;
2725             core_info->bmciColors[1].rgbtBlue = 0xff;
2726             core_info->bmciColors[1].rgbtGreen = 0xff;
2727             core_info->bmciColors[1].rgbtRed = 0xff;
2728         }
2729         else
2730         {
2731             bitmap_info = (BITMAPINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2732             bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2733             bitmap_info->bmiHeader.biWidth = 1;
2734             bitmap_info->bmiHeader.biHeight = 2;
2735             bitmap_info->bmiHeader.biPlanes = 1;
2736             bitmap_info->bmiHeader.biBitCount = 1;
2737             bitmap_info->bmiHeader.biSizeImage = 0; /* Uncompressed bitmap. */
2738             bitmap_info->bmiColors[0].rgbBlue = monochrome ? 0x00 : 0xff;
2739             bitmap_info->bmiColors[0].rgbGreen = 0x00;
2740             bitmap_info->bmiColors[0].rgbRed = 0x00;
2741             bitmap_info->bmiColors[1].rgbBlue = 0xff;
2742             bitmap_info->bmiColors[1].rgbGreen = 0xff;
2743             bitmap_info->bmiColors[1].rgbRed = 0xff;
2744         }
2745 
2746         handle = CreateFileA("icon.ico", GENERIC_WRITE, 0, NULL, CREATE_NEW,
2747             FILE_ATTRIBUTE_NORMAL, NULL);
2748         ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
2749         ret = WriteFile(handle, icon_data, icon_size, &bytes_written, NULL);
2750         ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
2751         CloseHandle(handle);
2752 
2753         handle = LoadImageA(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
2754         ok(handle != NULL ||
2755            broken(use_core_info && handle == NULL), /* Win 8, 10 */
2756            "LoadImage() failed with %u.\n", GetLastError());
2757         if (handle == NULL)
2758         {
2759             skip("Icon failed to load: %s, %s\n",
2760                  monochrome ? "monochrome" : "colored",
2761                  use_core_info ? "core info" : "bitmap info");
2762             DeleteFileA("icon.ico");
2763             continue;
2764         }
2765 
2766         ret = GetIconInfo(handle, &icon_info);
2767         ok(ret, "GetIconInfo() failed with %u.\n", GetLastError());
2768         if (ret)
2769         {
2770             ok(icon_info.fIcon == TRUE, "fIcon is %u.\n", icon_info.fIcon);
2771             ok(icon_info.xHotspot == 0, "xHotspot is %u.\n", icon_info.xHotspot);
2772             ok(icon_info.yHotspot == 0, "yHotspot is %u.\n", icon_info.yHotspot);
2773             if (monochrome)
2774                 ok(icon_info.hbmColor == NULL, "Got hbmColor %p!\n", icon_info.hbmColor);
2775             else
2776                 ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
2777             ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
2778         }
2779 
2780         ret = DestroyIcon(handle);
2781         ok(ret, "DestroyIcon() failed with %u.\n", GetLastError());
2782         DeleteFileA("icon.ico");
2783     }
2784 
2785     HeapFree(GetProcessHeap(), 0, icon_data);
2786 }
2787 
get_color_from_bits(const unsigned char * bits,const BITMAPINFO * bmi,unsigned int row,unsigned int column)2788 static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO *bmi,
2789         unsigned int row, unsigned int column)
2790 {
2791     const BITMAPINFOHEADER *h = &bmi->bmiHeader;
2792     unsigned int stride, shift, mask;
2793     const unsigned char *data;
2794     RGBQUAD color;
2795     WORD color16;
2796 
2797     stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
2798     data = bits + row * stride + column * h->biBitCount / 8;
2799     if (h->biBitCount >= 24)
2800         return RGB(data[2], data[1], data[0]);
2801 
2802     if (h->biBitCount == 16)
2803     {
2804         color16 = ((WORD)data[1] << 8) | data[0];
2805         return RGB(((color16 >> 10) & 0x1f) << 3, ((color16 >> 5) & 0x1f) << 3,
2806                 (color16 & 0x1f) << 3);
2807     }
2808     shift = 8 - h->biBitCount - (column * h->biBitCount) % 8;
2809     mask = ~(~0u << h->biBitCount);
2810     color = bmi->bmiColors[(data[0] >> shift) & mask];
2811     return RGB(color.rgbRed, color.rgbGreen, color.rgbBlue);
2812 }
2813 
2814 #define compare_bitmap_bits(a, b, c, d, e, f, g) compare_bitmap_bits_(__LINE__, a, b, c, d, e, f, g)
compare_bitmap_bits_(unsigned int line,HDC hdc,HBITMAP bitmap,BITMAPINFO * bmi,size_t result_bits_size,const unsigned char * expected_bits,unsigned int test_index,BOOL todo)2815 static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BITMAPINFO *bmi,
2816         size_t result_bits_size, const unsigned char *expected_bits, unsigned int test_index, BOOL todo)
2817 {
2818     unsigned char *result_bits;
2819     unsigned int row, column;
2820     int ret;
2821 
2822     result_bits = HeapAlloc(GetProcessHeap(), 0, result_bits_size);
2823     ret = GetDIBits(hdc, bitmap, 0, bmi->bmiHeader.biHeight,
2824             result_bits, bmi, DIB_RGB_COLORS);
2825     ok(ret == bmi->bmiHeader.biHeight, "Unexpected GetDIBits result %d, GetLastError() %u.\n",
2826             ret, GetLastError());
2827     for (row = 0; row < bmi->bmiHeader.biHeight; ++row)
2828         for (column = 0; column < bmi->bmiHeader.biWidth; ++column)
2829         {
2830             COLORREF result, expected;
2831 
2832             result = get_color_from_bits(result_bits, bmi, row, column);
2833             expected = get_color_from_bits(expected_bits, bmi, row, column);
2834 
2835             todo_wine_if(todo)
2836             ok_(__FILE__, line)(result == expected, "Colors do not match, "
2837                     "got 0x%06x, expected 0x%06x, test_index %u, row %u, column %u.\n",
2838                     result, expected, test_index, row, column);
2839         }
2840     HeapFree(GetProcessHeap(), 0, result_bits);
2841 }
2842 
test_Image_StretchMode(void)2843 static void test_Image_StretchMode(void)
2844 {
2845     static const unsigned char test_bits_24[] =
2846     {
2847         0x00, 0xff, 0x00,  0x00, 0xff, 0x00,  0x00, 0xff, 0xff,  0x00, 0xff, 0x00,
2848         0x00, 0xff, 0x00,  0xff, 0xff, 0x00,  0xff, 0xff, 0x00,  0x00, 0xff, 0x00,
2849         0x00, 0xff, 0xff,  0x00, 0xff, 0x00,  0x00, 0xff, 0xff,  0x00, 0xff, 0x00,
2850         0xff, 0xff, 0x00,  0x00, 0xff, 0xff,  0x00, 0xff, 0x00,  0x00, 0xff, 0x00,
2851     };
2852     static const unsigned char expected_bits_24[] =
2853     {
2854         0x3f, 0xff, 0x00,  0x3f, 0xff, 0x3f,  0x00, 0x00,
2855         0x3f, 0xff, 0x7f,  0x00, 0xff, 0x3f,  0x00, 0x00,
2856     };
2857 #define rgb16(r, g, b) ((WORD)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)))
2858     static const WORD test_bits_16[] =
2859     {
2860         rgb16(0x00, 0x20, 0x00), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
2861         rgb16(0x00, 0x60, 0x00), rgb16(0xff, 0x80, 0x00), rgb16(0xff, 0x60, 0x00), rgb16(0x00, 0x80, 0x00),
2862         rgb16(0x00, 0x20, 0xff), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
2863         rgb16(0xff, 0x80, 0x00), rgb16(0x00, 0x60, 0xff), rgb16(0x00, 0x80, 0x00), rgb16(0x00, 0x60, 0x00),
2864     };
2865     static const WORD expected_bits_16[] =
2866     {
2867         rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
2868         rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
2869     };
2870 #undef rgb16
2871     static const unsigned char test_bits_8[] =
2872     {
2873         0x00, 0xff, 0x00, 0xff,
2874         0x00, 0x00, 0x00, 0x00,
2875         0xff, 0x55, 0x00, 0xff,
2876         0x00, 0xff, 0xff, 0x00,
2877     };
2878     static const unsigned char expected_bits_8[] =
2879     {
2880         0xff, 0xff, 0x00, 0x00,
2881         0x55, 0xff, 0x00, 0x00,
2882     };
2883     static const unsigned char test_bits_1[] =
2884     {
2885         0x30, 0x0, 0x0, 0x0,
2886         0x30, 0x0, 0x0, 0x0,
2887         0x40, 0x0, 0x0, 0x0,
2888         0xc0, 0x0, 0x0, 0x0,
2889     };
2890     static const unsigned char expected_bits_1[] =
2891     {
2892         0x40, 0x0, 0x0, 0x0,
2893         0x0,  0x0, 0x0, 0x0,
2894     };
2895     static const RGBQUAD colors_bits_1[] =
2896     {
2897         {0, 0, 0},
2898         {0xff, 0xff, 0xff},
2899     };
2900     static RGBQUAD colors_bits_8[256];
2901 
2902     static const struct
2903     {
2904         LONG width, height, output_width, output_height;
2905         WORD bit_count;
2906         const unsigned char *test_bits, *expected_bits;
2907         size_t test_bits_size, result_bits_size;
2908         const RGBQUAD *bmi_colors;
2909         size_t bmi_colors_size;
2910         BOOL todo;
2911     }
2912     tests[] =
2913     {
2914         {4, 4, 2, 2, 24, test_bits_24, expected_bits_24,
2915                 sizeof(test_bits_24), sizeof(expected_bits_24), NULL, 0, TRUE},
2916         {4, 4, 2, 2, 1, test_bits_1, expected_bits_1,
2917                 sizeof(test_bits_1), sizeof(expected_bits_1), colors_bits_1,
2918                 sizeof(colors_bits_1), FALSE},
2919         {4, 4, 2, 2, 8, test_bits_8, expected_bits_8,
2920                 sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8,
2921                 sizeof(colors_bits_8), FALSE},
2922         {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16,
2923                 sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, FALSE},
2924     };
2925     static const char filename[] = "test.bmp";
2926     BITMAPINFO *bmi, *bmi_output;
2927     HBITMAP bitmap, bitmap_copy;
2928     unsigned int test_index;
2929     unsigned char *bits;
2930     size_t bmi_size;
2931     unsigned int i;
2932     HDC hdc;
2933 
2934     bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
2935     bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
2936     bmi_output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
2937     bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2938     bmi->bmiHeader.biPlanes = 1;
2939     bmi->bmiHeader.biCompression = BI_RGB;
2940 
2941     for (i = 0; i < 256; ++i)
2942         colors_bits_8[i].rgbRed = colors_bits_8[i].rgbGreen = colors_bits_8[i].rgbBlue = i;
2943 
2944     hdc = GetDC(NULL);
2945 
2946     for (test_index = 0; test_index < ARRAY_SIZE(tests); ++test_index)
2947     {
2948         if (tests[test_index].bmi_colors)
2949             memcpy(bmi->bmiColors, tests[test_index].bmi_colors, tests[test_index].bmi_colors_size);
2950         else
2951             memset(bmi->bmiColors, 0, 256 * sizeof(RGBQUAD));
2952 
2953         bmi->bmiHeader.biWidth = tests[test_index].width;
2954         bmi->bmiHeader.biHeight = tests[test_index].height;
2955         bmi->bmiHeader.biBitCount = tests[test_index].bit_count;
2956         memcpy(bmi_output, bmi, bmi_size);
2957         bmi_output->bmiHeader.biWidth = tests[test_index].output_width;
2958         bmi_output->bmiHeader.biHeight = tests[test_index].output_height;
2959 
2960         bitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
2961         ok(bitmap && bits, "CreateDIBSection() failed, result %u.\n", GetLastError());
2962         memcpy(bits, tests[test_index].test_bits, tests[test_index].test_bits_size);
2963 
2964         bitmap_copy = CopyImage(bitmap, IMAGE_BITMAP, tests[test_index].output_width,
2965                 tests[test_index].output_height, LR_CREATEDIBSECTION);
2966         ok(!!bitmap_copy, "CopyImage() failed, result %u.\n", GetLastError());
2967 
2968         compare_bitmap_bits(hdc, bitmap_copy, bmi_output, tests[test_index].result_bits_size,
2969                 tests[test_index].expected_bits, test_index, tests[test_index].todo);
2970         DeleteObject(bitmap);
2971         DeleteObject(bitmap_copy);
2972 
2973         create_bitmap_file(filename, bmi, tests[test_index].test_bits);
2974         bitmap = LoadImageA(NULL, filename, IMAGE_BITMAP, tests[test_index].output_width,
2975                 tests[test_index].output_height, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
2976         ok(!!bitmap, "LoadImageA() failed, result %u.\n", GetLastError());
2977         DeleteFileA(filename);
2978         compare_bitmap_bits(hdc, bitmap, bmi_output, tests[test_index].result_bits_size,
2979                 tests[test_index].expected_bits, test_index, tests[test_index].todo);
2980         DeleteObject(bitmap);
2981     }
2982     ReleaseDC(0, hdc);
2983     HeapFree(GetProcessHeap(), 0, bmi_output);
2984     HeapFree(GetProcessHeap(), 0, bmi);
2985 }
2986 
START_TEST(cursoricon)2987 START_TEST(cursoricon)
2988 {
2989     pGetCursorInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorInfo" );
2990     pGetIconInfoExA = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExA" );
2991     pGetIconInfoExW = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExW" );
2992     pGetCursorFrameInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorFrameInfo" );
2993     test_argc = winetest_get_mainargs(&test_argv);
2994 
2995     if (test_argc >= 3)
2996     {
2997         /* Child process. */
2998         sscanf (test_argv[2], "%x", (unsigned int *) &parent);
2999 
3000         ok(parent != NULL, "Parent not found.\n");
3001         if (parent == NULL)
3002             ExitProcess(1);
3003 
3004         do_child();
3005         return;
3006     }
3007 
3008     test_CopyImage_Bitmap(1);
3009     test_CopyImage_Bitmap(4);
3010     test_CopyImage_Bitmap(8);
3011     test_CopyImage_Bitmap(16);
3012     test_CopyImage_Bitmap(24);
3013     test_CopyImage_Bitmap(32);
3014     test_Image_StretchMode();
3015     test_initial_cursor();
3016     test_CreateIcon();
3017     test_LoadImage();
3018     test_CreateIconFromResource();
3019     test_GetCursorFrameInfo();
3020     test_DrawIcon();
3021     test_DrawIconEx();
3022     test_DrawState();
3023     test_SetCursor();
3024     test_ShowCursor();
3025     test_DestroyCursor();
3026     test_PrivateExtractIcons();
3027     test_monochrome_icon();
3028     do_parent();
3029     test_child_process();
3030     finish_child_process();
3031 }
3032