ReactOS  0.4.14-dev-49-gfb4591c
cursoricon.c
Go to the documentation of this file.
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;
47 
48 typedef struct
49 {
50  WORD idReserved;
51  WORD idType;
52  WORD idCount;
53  CURSORICONFILEDIRENTRY idEntries[1];
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 {
82 } ani_header;
83 
84 typedef struct {
85  BYTE data[32*32*4];
86  BYTE mask_data[32*32/8];
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 */
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 */
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 */
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 */
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 */
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 */
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 
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  {
219  }
220 };
221 
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,
250  }
251 };
252 
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,
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;
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 
311 {
312  switch (msg)
313  {
314  /* Destroy the cursor. */
315  case WM_USER+1:
316  {
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);
332  error = GetLastError();
333  ok(!ret || broken(ret) /* win9x */, "DestroyCursor on the active cursor succeeded.\n");
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 
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 
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. */
387 
388  /* Receive messages. */
389  while ((ret = GetMessageA(&msg, 0, 0, 0)))
390  {
391  ok(ret != -1, "GetMessage failed. Error: %u\n", GetLastError());
394  }
395 }
396 
397 static void do_parent(void)
398 {
399  char path_name[MAX_PATH];
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());
443  }
444 }
445 
446 static void finish_child_process(void)
447 {
448  SendMessageA(child, WM_CLOSE, 0, 0);
451 }
452 
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. */
479 }
480 
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 
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 
539  }
540 }
541 
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 
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 
599 
600  /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
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 
626 
627  /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
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 
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 
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 
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 
693 }
694 
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 
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");
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 
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);
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);
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);
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);
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;
856  ok(hIcon != 0, "CreateIconIndirect failed\n");
857  test_icon_info(hIcon, 16, 16, 16, display_bpp);
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);
873  ok(hIcon != 0, "CreateIconIndirect failed\n");
874  test_icon_info(hIcon, 16, 16, 32, 1);
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);
890  ok(hIcon != 0, "CreateIconIndirect failed\n");
891  test_icon_info(hIcon, 1, i / 2, max(i,1), 1);
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);
922  ok(hIcon != 0, "CreateIconIndirect failed\n");
923  test_icon_info(hIcon, 32, 32, 32, 8);
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);
940  ok(hIcon != 0, "CreateIconIndirect failed\n");
941  test_icon_info(hIcon, 32, 32, 32, 8);
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);
958  ok(hIcon != 0, "CreateIconIndirect failed\n");
959  test_icon_info(hIcon, 32, 32, 32, 8);
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 
1056 #ifndef __REACTOS__
1057 #define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))
1058 #endif
1059 
1060 static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm)
1061 {
1062  BITMAP bm;
1063  BITMAPINFO bmi;
1064  DWORD ret, pixel = 0;
1065  HDC hdc = GetDC(NULL);
1066 
1067  ret = GetObjectA(hbm, sizeof(bm), &bm);
1068  ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
1069 
1070  memset(&bmi, 0, sizeof(bmi));
1071  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1072  bmi.bmiHeader.biWidth = bm.bmWidth;
1073  bmi.bmiHeader.biHeight = bm.bmHeight;
1074  bmi.bmiHeader.biPlanes = 1;
1075  bmi.bmiHeader.biBitCount= 24;
1077  ret = GetDIBits(hdc, hbm, 0, bm.bmHeight, &pixel, &bmi, DIB_RGB_COLORS);
1078  ok(ret == bm.bmHeight, "%s: %d lines were converted, not %d\n", test_desc, ret, bm.bmHeight);
1079 
1080  ok(color_match(pixel, 0x00ffffff), "%s: Pixel is 0x%08x\n", test_desc, pixel);
1081 
1082  ReleaseDC(NULL, hdc);
1083 }
1084 
1085 static void test_LoadImageFile(const char * test_desc, const unsigned char * image_data,
1086  unsigned int image_size, const char * ext, BOOL expect_success)
1087 {
1088  HANDLE handle;
1089  BOOL ret;
1090  DWORD error, bytes_written;
1091  char filename[64];
1092 
1093  strcpy(filename, "test.");
1094  strcat(filename, ext);
1095 
1096  /* Create the test image. */
1099  ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1100  ret = WriteFile(handle, image_data, image_size, &bytes_written, NULL);
1101  ok(ret && bytes_written == image_size, "test file created improperly.\n");
1103 
1104  /* Load as cursor. For all tested formats, this should fail */
1105  SetLastError(0xdeadbeef);
1107  ok(handle == NULL, "%s: IMAGE_CURSOR succeeded incorrectly.\n", test_desc);
1108  error = GetLastError();
1109  ok(error == 0 ||
1110  broken(error == 0xdeadbeef) || /* Win9x */
1111  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1112  "Last error: %u\n", error);
1113  if (handle != NULL) DestroyCursor(handle);
1114 
1115  /* Load as icon. For all tested formats, this should fail */
1116  SetLastError(0xdeadbeef);
1118  ok(handle == NULL, "%s: IMAGE_ICON succeeded incorrectly.\n", test_desc);
1119  error = GetLastError();
1120  ok(error == 0 ||
1121  broken(error == 0xdeadbeef) || /* Win9x */
1122  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1123  "Last error: %u\n", error);
1124  if (handle != NULL) DestroyIcon(handle);
1125 
1126  /* Load as bitmap. Should succeed for correct bmp, fail for everything else */
1127  SetLastError(0xdeadbeef);
1129  error = GetLastError();
1130  ok(error == 0 ||
1131  error == 0xdeadbeef, /* Win9x, WinMe */
1132  "Last error: %u\n", error);
1133 
1134  if (expect_success) {
1135  ok(handle != NULL, "%s: IMAGE_BITMAP failed.\n", test_desc);
1136  if (handle != NULL) test_LoadImageBitmap(test_desc, handle);
1137  }
1138  else ok(handle == NULL, "%s: IMAGE_BITMAP succeeded incorrectly.\n", test_desc);
1139 
1140  if (handle != NULL) DeleteObject(handle);
1142 }
1143 
1144 typedef struct {
1145  unsigned width;
1146  unsigned height;
1149 
1150 static void create_ico_file(const char *filename, const test_icon_entries_t *test_icon_entries, unsigned entry_cnt)
1151 {
1152  CURSORICONFILEDIRENTRY *icon_entry;
1153  BITMAPINFOHEADER *icon_header;
1155  BYTE *buf, *bitmap_ptr;
1156  DWORD bytes_written;
1157  size_t icon_size;
1158  HANDLE file;
1159  unsigned i;
1160  BOOL ret;
1161 
1162  const unsigned icon_bpp = 32;
1163 
1164  icon_size = FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]) + sizeof(BITMAPINFOHEADER)*entry_cnt;
1165  for(i=0; i<entry_cnt; i++)
1166  icon_size += icon_bpp * test_icon_entries[i].width * test_icon_entries[i].height / 8;
1167 
1170 
1171  dir->idReserved = 0;
1172  dir->idType = 1;
1173  dir->idCount = entry_cnt;
1174 
1175  bitmap_ptr = buf + FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]);
1176  for(i=0; i<entry_cnt; i++) {
1177  icon_entry = dir->idEntries+i;
1178  icon_entry->bWidth = test_icon_entries[i].width;
1179  icon_entry->bHeight = test_icon_entries[i].height;
1180  icon_entry->bColorCount = 0;
1181  icon_entry->bReserved = 0;
1182  icon_entry->xHotspot = 1;
1183  icon_entry->yHotspot = 1;
1184  icon_entry->dwDIBSize = sizeof(BITMAPINFOHEADER) + icon_entry->bWidth * icon_entry->bHeight * icon_bpp / 8;
1185  icon_entry->dwDIBOffset = test_icon_entries[i].invalid_offset ? 0xffffffff : bitmap_ptr - buf;
1186 
1187  icon_header = (BITMAPINFOHEADER*)bitmap_ptr;
1188  bitmap_ptr += icon_entry->dwDIBSize;
1189 
1190  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1191  icon_header->biWidth = icon_entry->bWidth;
1192  icon_header->biHeight = icon_entry->bHeight;
1193  icon_header->biPlanes = 1;
1194  icon_header->biBitCount = icon_bpp;
1195  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1196  }
1197 
1198  memset(bitmap_ptr, 0xf0, buf+icon_size-bitmap_ptr);
1199 
1200  /* Create the icon. */
1202  ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1203  ret = WriteFile(file, buf, icon_size, &bytes_written, NULL);
1204  ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
1205  CloseHandle(file);
1206 
1207  HeapFree(GetProcessHeap(), 0, buf);
1208 }
1209 
1210 static void test_LoadImage(void)
1211 {
1212  HANDLE handle;
1213  BOOL ret;
1214  DWORD error;
1215  BITMAPINFOHEADER *bitmap_header;
1216  ICONINFO icon_info;
1217  int i;
1218 
1219 #define ICON_WIDTH 32
1220 #define ICON_HEIGHT 32
1221 #define ICON_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1222 #define ICON_BPP 32
1223 #define ICON_SIZE \
1224  (sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) \
1225  + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1226 
1227  static const test_icon_entries_t icon_desc = {32, 32};
1228 
1229  create_ico_file("icon.ico", &icon_desc, 1);
1230 
1231  /* Test loading an icon as a cursor. */
1232  SetLastError(0xdeadbeef);
1233  handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1234  ok(handle != NULL, "LoadImage() failed.\n");
1235  error = GetLastError();
1236  ok(error == 0 ||
1237  broken(error == 0xdeadbeef) || /* Win9x */
1238  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1239  "Last error: %u\n", error);
1240 
1241  /* Test the icon information. */
1242  SetLastError(0xdeadbeef);
1243  ret = GetIconInfo(handle, &icon_info);
1244  ok(ret, "GetIconInfo() failed.\n");
1245  error = GetLastError();
1246  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1247 
1248  if (ret)
1249  {
1250  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1251  ok(icon_info.xHotspot == 1, "xHotspot is %u.\n", icon_info.xHotspot);
1252  ok(icon_info.yHotspot == 1, "yHotspot is %u.\n", icon_info.yHotspot);
1253  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1254  "No hbmColor!\n");
1255  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1256  }
1257 
1258  if (pGetIconInfoExA)
1259  {
1260  ICONINFOEXA infoex;
1261  infoex.cbSize = sizeof(infoex);
1262  ret = pGetIconInfoExA( handle, &infoex );
1263  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1264  ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1265  ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1266  ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1267  }
1268  else win_skip( "GetIconInfoEx not available\n" );
1269 
1270  /* Clean up. */
1271  SetLastError(0xdeadbeef);
1273  ok(ret, "DestroyCursor() failed.\n");
1274  error = GetLastError();
1275  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1276 
1277  DeleteFileA("icon.ico");
1278 
1279  /* Test a system icon */
1280  handle = LoadIconA( 0, (LPCSTR)IDI_HAND );
1281  ok(handle != NULL, "LoadImage() failed.\n");
1282  if (pGetIconInfoExA)
1283  {
1284  ICONINFOEXA infoexA;
1285  ICONINFOEXW infoexW;
1286  infoexA.cbSize = sizeof(infoexA);
1287  ret = pGetIconInfoExA( handle, &infoexA );
1288  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1289  ok( infoexA.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexA.wResID );
1290  /* the A version is broken on 64-bit, it truncates the string after the first char */
1291  if (is_win64 && infoexA.szModName[0] && infoexA.szModName[1] == 0)
1292  trace( "GetIconInfoExA broken on Win64\n" );
1293  else
1294  ok( GetModuleHandleA(infoexA.szModName) == GetModuleHandleA("user32.dll"),
1295  "GetIconInfoEx wrong module %s\n", infoexA.szModName );
1296  ok( infoexA.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoexA.szResName );
1297  infoexW.cbSize = sizeof(infoexW);
1298  ret = pGetIconInfoExW( handle, &infoexW );
1299  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1300  ok( infoexW.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexW.wResID );
1301  ok( GetModuleHandleW(infoexW.szModName) == GetModuleHandleA("user32.dll"),
1302  "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(infoexW.szModName) );
1303  ok( infoexW.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", wine_dbgstr_w(infoexW.szResName) );
1304  }
1305  SetLastError(0xdeadbeef);
1307 
1308  test_LoadImageFile("BMP", bmpimage, sizeof(bmpimage), "bmp", 1);
1309  test_LoadImageFile("BMP (coreinfo)", bmpcoreimage, sizeof(bmpcoreimage), "bmp", 1);
1310  test_LoadImageFile("GIF", gifimage, sizeof(gifimage), "gif", 0);
1311  test_LoadImageFile("GIF (2x2 pixel)", gif4pixel, sizeof(gif4pixel), "gif", 0);
1312  test_LoadImageFile("JPG", jpgimage, sizeof(jpgimage), "jpg", 0);
1313  test_LoadImageFile("PNG", pngimage, sizeof(pngimage), "png", 0);
1314 
1315  /* Check failure for broken BMP images */
1316  bitmap_header = (BITMAPINFOHEADER *)(bmpimage + sizeof(BITMAPFILEHEADER));
1317 
1318  bitmap_header->biHeight = 65536;
1319  test_LoadImageFile("BMP (too high)", bmpimage, sizeof(bmpimage), "bmp", 0);
1320  bitmap_header->biHeight = 1;
1321 
1322  bitmap_header->biWidth = 65536;
1323  test_LoadImageFile("BMP (too wide)", bmpimage, sizeof(bmpimage), "bmp", 0);
1324  bitmap_header->biWidth = 1;
1325 
1326  for (i = 0; i < ARRAY_SIZE(biSize_tests); i++) {
1327  bitmap_header->biSize = biSize_tests[i];
1328  test_LoadImageFile("BMP (broken biSize)", bmpimage, sizeof(bmpimage), "bmp", 0);
1329  }
1330  bitmap_header->biSize = sizeof(BITMAPINFOHEADER);
1331 
1332  test_LoadImageFile("Cursor (invalid dwDIBOffset)", invalid_dwDIBOffset, sizeof(invalid_dwDIBOffset), "cur", 0);
1333 }
1334 
1335 #undef ARRAY_SIZE
1336 
1338 {
1339  HANDLE handle;
1340  BOOL ret;
1341  DWORD error;
1342  BITMAPINFOHEADER *icon_header;
1343  INT16 *hotspot;
1344  ICONINFO icon_info;
1345 
1346 #define ICON_RES_WIDTH 32
1347 #define ICON_RES_HEIGHT 32
1348 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1349 #define ICON_RES_BPP 32
1350 #define ICON_RES_SIZE \
1351  (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1352 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1353 
1354  /* Set icon data. */
1356 
1357  /* Cursor resources have an extra hotspot, icon resources not. */
1358  hotspot[0] = 3;
1359  hotspot[1] = 3;
1360 
1361  icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1362  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1363  icon_header->biWidth = ICON_WIDTH;
1364  icon_header->biHeight = ICON_HEIGHT*2;
1365  icon_header->biPlanes = 1;
1366  icon_header->biBitCount = ICON_BPP;
1367  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1368 
1369  /* Test creating a cursor. */
1370  SetLastError(0xdeadbeef);
1371  handle = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1372  ok(handle != NULL, "Create cursor failed.\n");
1373 
1374  /* Test the icon information. */
1375  SetLastError(0xdeadbeef);
1376  ret = GetIconInfo(handle, &icon_info);
1377  ok(ret, "GetIconInfo() failed.\n");
1378  error = GetLastError();
1379  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1380 
1381  if (ret)
1382  {
1383  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1384  ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1385  ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1386  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1387  "No hbmColor!\n");
1388  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1389  }
1390 
1391  if (pGetIconInfoExA)
1392  {
1393  ICONINFOEXA infoex;
1394  infoex.cbSize = sizeof(infoex);
1395  ret = pGetIconInfoExA( handle, &infoex );
1396  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1397  ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1398  ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1399  ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1400  }
1401 
1402  /* Clean up. */
1403  SetLastError(0xdeadbeef);
1405  ok(ret, "DestroyCursor() failed.\n");
1406  error = GetLastError();
1407  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1408 
1409  /* Test creating an icon. */
1410  SetLastError(0xdeadbeef);
1412  0x00030000);
1413  ok(handle != NULL, "Create icon failed.\n");
1414 
1415  /* Test the icon information. */
1416  SetLastError(0xdeadbeef);
1417  ret = GetIconInfo(handle, &icon_info);
1418  ok(ret, "GetIconInfo() failed.\n");
1419  error = GetLastError();
1420  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1421 
1422  if (ret)
1423  {
1424  ok(icon_info.fIcon == TRUE, "fIcon != TRUE.\n");
1425  /* Icons always have hotspot in the middle */
1426  ok(icon_info.xHotspot == ICON_WIDTH/2, "xHotspot is %u.\n", icon_info.xHotspot);
1427  ok(icon_info.yHotspot == ICON_HEIGHT/2, "yHotspot is %u.\n", icon_info.yHotspot);
1428  ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
1429  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1430  }
1431 
1432  /* Clean up. */
1433  SetLastError(0xdeadbeef);
1435  ok(ret, "DestroyCursor() failed.\n");
1436  error = GetLastError();
1437  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1438 
1439  /* Rejection of NULL pointer crashes at least on WNT4WSSP6, W2KPROSP4, WXPPROSP3
1440  *
1441  * handle = CreateIconFromResource(NULL, ICON_RES_SIZE, TRUE, 0x00030000);
1442  * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
1443  */
1444  HeapFree(GetProcessHeap(), 0, hotspot);
1445 
1446  /* Test creating an animated cursor. */
1447  empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1451  ok(handle != NULL, "Create cursor failed.\n");
1452 
1453  /* Test the animated cursor's information. */
1454  SetLastError(0xdeadbeef);
1455  ret = GetIconInfo(handle, &icon_info);
1456  ok(ret, "GetIconInfo() failed.\n");
1457  error = GetLastError();
1458  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1459 
1460  if (ret)
1461  {
1462  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1463  ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1464  ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1465  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1466  "No hbmColor!\n");
1467  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1468  }
1469 
1470  /* Clean up. */
1471  SetLastError(0xdeadbeef);
1473  ok(ret, "DestroyCursor() failed.\n");
1474  error = GetLastError();
1475  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1476 }
1477 
1478 static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
1479 {
1480  char *image = NULL;
1481  BITMAPINFO *info;
1482  ICONINFO iinfo;
1483  DWORD ret;
1484  int i;
1485 
1486  ret = GetIconInfo( hCursor, &iinfo );
1487  ok(ret, "GetIconInfo() failed\n");
1488  if (!ret) return 0;
1489  ret = 0;
1490  info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
1491  ok(info != NULL, "HeapAlloc() failed\n");
1492  if (!info) return 0;
1493 
1494  info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1495  info->bmiHeader.biWidth = 32;
1496  info->bmiHeader.biHeight = 32;
1497  info->bmiHeader.biPlanes = 1;
1498  info->bmiHeader.biBitCount = 32;
1499  info->bmiHeader.biCompression = BI_RGB;
1500  info->bmiHeader.biSizeImage = 32 * 32 * 4;
1501  info->bmiHeader.biXPelsPerMeter = 0;
1502  info->bmiHeader.biYPelsPerMeter = 0;
1503  info->bmiHeader.biClrUsed = 0;
1504  info->bmiHeader.biClrImportant = 0;
1505  image = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
1506  ok(image != NULL, "HeapAlloc() failed\n");
1507  if (!image) goto cleanup;
1508  ret = GetDIBits( hdc, iinfo.hbmColor, 0, 32, image, info, DIB_RGB_COLORS );
1509  ok(ret, "GetDIBits() failed\n");
1510  for (i = 0; ret && i < length / sizeof(COLORREF); i++)
1511  {
1512  ret = color_match( ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1513  ok(ret, "%04x: Expected 0x%x, actually 0x%x\n", i, ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1514  }
1515 cleanup:
1516  HeapFree( GetProcessHeap(), 0, image );
1517  HeapFree( GetProcessHeap(), 0, info );
1518  return ret;
1519 }
1520 
1521 static HCURSOR (WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor, DWORD unk1, DWORD istep, DWORD *rate, DWORD *steps);
1522 static void test_GetCursorFrameInfo(void)
1523 {
1524  DWORD frame_identifier[] = { 0x10Ad, 0xc001, 0x1c05 };
1525  HBITMAP bmp = NULL, bmpOld = NULL;
1526  DWORD rate, steps;
1527  BITMAPINFOHEADER *icon_header;
1528  BITMAPINFO bitmapInfo;
1529  HDC hdc = NULL;
1530  void *bits = 0;
1531  INT16 *hotspot;
1532  HANDLE h1, h2;
1533  BOOL ret;
1534  int i;
1535 
1536  if (!pGetCursorFrameInfo)
1537  {
1538  win_skip( "GetCursorFrameInfo not supported, skipping tests.\n" );
1539  return;
1540  }
1541 
1542  hdc = CreateCompatibleDC(0);
1543  ok(hdc != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1544  if (!hdc)
1545  return;
1546 
1547  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1548  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1549  bitmapInfo.bmiHeader.biWidth = 3;
1550  bitmapInfo.bmiHeader.biHeight = 3;
1551  bitmapInfo.bmiHeader.biBitCount = 32;
1552  bitmapInfo.bmiHeader.biPlanes = 1;
1553  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1554  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1555  bmp = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1556  ok (bmp && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1557  if (!bmp || !bits)
1558  goto cleanup;
1559  bmpOld = SelectObject(hdc, bmp);
1560 
1561 #define ICON_RES_WIDTH 32
1562 #define ICON_RES_HEIGHT 32
1563 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1564 #define ICON_RES_BPP 32
1565 #define ICON_RES_SIZE \
1566  (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1567 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1568 
1569  /* Set icon data. */
1571 
1572  /* Cursor resources have an extra hotspot, icon resources not. */
1573  hotspot[0] = 3;
1574  hotspot[1] = 3;
1575 
1576  icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1577  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1578  icon_header->biWidth = ICON_WIDTH;
1579  icon_header->biHeight = ICON_HEIGHT*2;
1580  icon_header->biPlanes = 1;
1581  icon_header->biBitCount = ICON_BPP;
1582  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1583 
1584  /* Creating a static cursor. */
1585  SetLastError(0xdeadbeef);
1586  h1 = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1587  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1588 
1589  /* Check GetCursorFrameInfo behavior on a static cursor */
1590  rate = steps = 0xdead;
1591  h2 = pGetCursorFrameInfo(h1, 0xdead, 0xdead, &rate, &steps);
1592  ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1593  ok(rate == 0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1594  ok(steps == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1595 
1596  /* Clean up static cursor. */
1597  SetLastError(0xdeadbeef);
1598  ret = DestroyCursor(h1);
1599  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1600 
1601  /* Creating a single-frame animated cursor. */
1602  empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1605  memcpy( &empty_anicursor.frames[0].data.bmi_data.data[0], &frame_identifier[0], sizeof(DWORD) );
1606  SetLastError(0xdeadbeef);
1607  h1 = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
1608  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1609 
1610  /* Check GetCursorFrameInfo behavior on a single-frame animated cursor */
1611  rate = steps = 0xdead;
1612  h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1613  ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1614  ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1615  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1616  ok(rate == 0x0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1618  "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1619 
1620  /* Clean up single-frame animated cursor. */
1621  SetLastError(0xdeadbeef);
1622  ret = DestroyCursor(h1);
1623  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1624 
1625  /* Creating a multi-frame animated cursor. */
1627  {
1628  empty_anicursor3.frames[i].data.icon_info.idType = 2; /* type: cursor */
1631  memcpy( &empty_anicursor3.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1632  }
1633  SetLastError(0xdeadbeef);
1634  h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1635  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1636 
1637  /* Check number of steps in multi-frame animated cursor */
1638  i=0;
1639  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1640  i++;
1642  "Unexpected number of steps in cursor (%d != %d)\n",
1644 
1645  /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor */
1647  {
1648  rate = steps = 0xdead;
1649  h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1650  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1651  ret = check_cursor_data( hdc, h2, &frame_identifier[i], sizeof(DWORD) );
1652  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1654  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1657  "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1659  }
1660 
1661  /* Check GetCursorFrameInfo behavior on rate 3 of a multi-frame animated cursor */
1662  rate = steps = 0xdead;
1663  h2 = pGetCursorFrameInfo(h1, 0xdead, 3, &rate, &steps);
1664  ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1665  ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1666  || broken(rate == ~0) /*win2k (sporadic)*/,
1667  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1668  ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1669  || broken(steps == 0) /*win2k (sporadic)*/,
1670  "GetCursorFrameInfo() unexpected param 5 value (0x%x != 0xdead).\n", steps);
1671 
1672  /* Clean up multi-frame animated cursor. */
1673  SetLastError(0xdeadbeef);
1674  ret = DestroyCursor(h1);
1675  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1676 
1677  /* Create a multi-frame animated cursor with num_steps == 1 */
1679  SetLastError(0xdeadbeef);
1680  h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1681  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1682 
1683  /* Check number of steps in multi-frame animated cursor (mismatch between steps and frames) */
1684  i=0;
1685  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1686  i++;
1688  "Unexpected number of steps in cursor (%d != %d)\n",
1690 
1691  /* Check GetCursorFrameInfo behavior on rate 0 for a multi-frame animated cursor (with num_steps == 1) */
1692  rate = steps = 0xdead;
1693  h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1694  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1695  ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1696  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1698  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1700  ok(steps == ~0 || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/,
1701  "GetCursorFrameInfo() unexpected param 5 value (%d != ~0).\n", steps);
1702 
1703  /* Check GetCursorFrameInfo behavior on rate 1 for a multi-frame animated cursor (with num_steps == 1) */
1704  rate = steps = 0xdead;
1705  h2 = pGetCursorFrameInfo(h1, 0xdead, 1, &rate, &steps);
1706  ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1707  ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1708  || broken(rate == ~0) /*win2k (sporadic)*/,
1709  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1710  ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1711  || broken(steps == 0) /*win2k (sporadic)*/,
1712  "GetCursorFrameInfo() unexpected param 5 value (%d != 0xdead).\n", steps);
1713 
1714  /* Clean up multi-frame animated cursor. */
1715  SetLastError(0xdeadbeef);
1716  ret = DestroyCursor(h1);
1717  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1718 
1719  /* Creating a multi-frame animated cursor with rate data. */
1721  {
1722  empty_anicursor3_seq.frames[i].data.icon_info.idType = 2; /* type: cursor */
1725  memcpy( &empty_anicursor3_seq.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1726  }
1727  SetLastError(0xdeadbeef);
1729  ok(h1 != NULL, "Create cursor failed (error = %x).\n", GetLastError());
1730 
1731  /* Check number of steps in multi-frame animated cursor with rate data */
1732  i=0;
1733  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1734  i++;
1736  "Unexpected number of steps in cursor (%d != %d)\n",
1738 
1739  /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor with rate data */
1741  {
1742  int frame_id = empty_anicursor3_seq.seq.order[i];
1743 
1744  rate = steps = 0xdead;
1745  h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1746  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1747  ret = check_cursor_data( hdc, h2, &frame_identifier[frame_id], sizeof(DWORD) );
1748  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1750  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1753  "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1755  }
1756 
1757  /* Clean up multi-frame animated cursor with rate data. */
1758  SetLastError(0xdeadbeef);
1759  ret = DestroyCursor(h1);
1760  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1761 
1762  HeapFree(GetProcessHeap(), 0, hotspot);
1763 cleanup:
1764  if(bmpOld) SelectObject(hdc, bmpOld);
1765  if(bmp) DeleteObject(bmp);
1766  if(hdc) DeleteDC(hdc);
1767 }
1768 
1769 static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
1770  BOOL maskvalue, UINT32 *color, int colorSize)
1771 {
1772  ICONINFO iconInfo;
1773  BITMAPINFO bitmapInfo;
1774  void *buffer = NULL;
1775  UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000;
1776 
1777  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1778  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1779  bitmapInfo.bmiHeader.biWidth = width;
1780  bitmapInfo.bmiHeader.biHeight = height;
1781  bitmapInfo.bmiHeader.biPlanes = 1;
1782  bitmapInfo.bmiHeader.biBitCount = bpp;
1783  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1784  bitmapInfo.bmiHeader.biSizeImage = colorSize;
1785 
1786  iconInfo.fIcon = TRUE;
1787  iconInfo.xHotspot = 0;
1788  iconInfo.yHotspot = 0;
1789 
1790  iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask );
1791  if(!iconInfo.hbmMask) return NULL;
1792 
1793  iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &buffer, NULL, 0);
1794  if(!iconInfo.hbmColor || !buffer)
1795  {
1796  DeleteObject(iconInfo.hbmMask);
1797  return NULL;
1798  }
1799 
1800  memcpy(buffer, color, colorSize);
1801 
1802  return CreateIconIndirect(&iconInfo);
1803 }
1804 
1805 static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
1806 {
1807  HICON hicon;
1808  UINT32 color[2];
1809  COLORREF modern_expected, legacy_expected, result;
1810 
1811  color[0] = 0x00A0B0C0;
1812  color[1] = alpha ? 0xFF000000 : 0x00000000;
1813  modern_expected = alpha ? 0x00FFFFFF : 0x00C0B0A0;
1814  legacy_expected = 0x00C0B0A0;
1815 
1816  hicon = create_test_icon(hdc, 2, 1, bpp, 0, color, sizeof(color));
1817  if (!hicon) return;
1818 
1819  SetPixelV(hdc, 0, 0, 0x00FFFFFF);
1820 
1821  if(drawiconex)
1822  DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL);
1823  else
1824  DrawIcon(hdc, 0, 0, hicon);
1825 
1826  result = GetPixel(hdc, 0, 0);
1827  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1828  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1829  "%s. Expected a close match to %06X (modern) or %06X (legacy) with %s. "
1830  "Got %06X from line %d\n",
1831  alpha ? "Alpha blending" : "Not alpha blending", modern_expected, legacy_expected,
1832  drawiconex ? "DrawIconEx" : "DrawIcon", result, line);
1833 }
1834 
1835 static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
1836  COLORREF modern_expected, COLORREF legacy_expected, int line)
1837 {
1838  COLORREF result;
1839  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1840  if (!hicon) return;
1841  SetPixelV(hdc, 0, 0, background);
1844  DrawIcon(hdc, 0, 0, hicon);
1845  result = GetPixel(hdc, 0, 0);
1846 
1847  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1848  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1849  "Overlaying Mask %d on Color %06X with DrawIcon. "
1850  "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1851  maskvalue, color, modern_expected, legacy_expected, result, line);
1852 
1854 
1855  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1856  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1857  "Overlaying Mask %d on Color %06X with DrawIcon. "
1858  "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1859  maskvalue, color, modern_expected, legacy_expected, result, line);
1860 
1862 
1863  ok (color_match(result, background),
1864  "Overlaying Mask %d on Color %06X with DrawIcon. "
1865  "Expected unchanged background color %06X. Got %06X from line %d\n",
1866  maskvalue, color, background, result, line);
1867 }
1868 
1869 static void test_DrawIcon(void)
1870 {
1871  BITMAPINFO bitmapInfo;
1872  HDC hdcDst = NULL;
1873  HBITMAP bmpDst = NULL;
1874  HBITMAP bmpOld = NULL;
1875  void *bits = 0;
1876 
1878  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1879  if (!hdcDst)
1880  return;
1881 
1882  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
1883  {
1884  skip("Windows will distort DrawIcon colors at 8-bpp and less due to palettizing.\n");
1885  goto cleanup;
1886  }
1887 
1888  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1889  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1890  bitmapInfo.bmiHeader.biWidth = GetSystemMetrics(SM_CXICON)+1;
1891  bitmapInfo.bmiHeader.biHeight = GetSystemMetrics(SM_CYICON)+1;
1892  bitmapInfo.bmiHeader.biBitCount = 32;
1893  bitmapInfo.bmiHeader.biPlanes = 1;
1894  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1895  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1896 
1897  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1898  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1899  if (!bmpDst || !bits)
1900  goto cleanup;
1901  bmpOld = SelectObject(hdcDst, bmpDst);
1902 
1903  /* Mask is only heeded if alpha channel is always zero */
1904  check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1905  check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
1906 
1907  /* Test alpha blending */
1908  /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
1909  check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1910  check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
1911 
1912  check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1913  check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
1914  check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
1915  check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
1916 
1917  check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1918  check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
1919 
1920  /* Test detecting of alpha channel */
1921  /* If a single pixel's alpha channel is non-zero, the icon
1922  will be alpha blended, otherwise it will be draw with
1923  and + xor blts. */
1924  check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__);
1925  check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__);
1926 
1927 cleanup:
1928  if(bmpOld)
1929  SelectObject(hdcDst, bmpOld);
1930  if(bmpDst)
1931  DeleteObject(bmpDst);
1932  if(hdcDst)
1933  DeleteDC(hdcDst);
1934 }
1935 
1936 static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background,
1937  COLORREF modern_expected, COLORREF legacy_expected, int line)
1938 {
1939  COLORREF result;
1940  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1941  if (!hicon) return;
1942  SetPixelV(hdc, 0, 0, background);
1943  DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags);
1944  result = GetPixel(hdc, 0, 0);
1945 
1946  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1947  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1948  "Overlaying Mask %d on Color %06X with DrawIconEx flags %08X. "
1949  "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
1950  maskvalue, color, flags, modern_expected, legacy_expected, result, line);
1951 }
1952 
1953 static void test_DrawIconEx(void)
1954 {
1955  BITMAPINFO bitmapInfo;
1956  HDC hdcDst = NULL;
1957  HBITMAP bmpDst = NULL;
1958  HBITMAP bmpOld = NULL;
1959  void *bits = 0;
1960 
1962  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1963  if (!hdcDst)
1964  return;
1965 
1966  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
1967  {
1968  skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
1969  goto cleanup;
1970  }
1971 
1972  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1973  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1974  bitmapInfo.bmiHeader.biWidth = 1;
1975  bitmapInfo.bmiHeader.biHeight = 1;
1976  bitmapInfo.bmiHeader.biBitCount = 32;
1977  bitmapInfo.bmiHeader.biPlanes = 1;
1978  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1979  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1980  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1981  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1982  if (!bmpDst || !bits)
1983  goto cleanup;
1984  bmpOld = SelectObject(hdcDst, bmpDst);
1985 
1986  /* Test null, image only, and mask only drawing */
1987  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
1988  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
1989 
1990  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00000000, 0x00000000, __LINE__);
1991  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
1992 
1993  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1994  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1995 
1996  /* Test normal drawing */
1997  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
1998  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
1999  check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2000 
2001  /* Test alpha blending */
2002  /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
2003  check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
2004 
2005  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2006  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2007  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
2008  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
2009 
2010  check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2011  check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2012 
2013  /* Test detecting of alpha channel */
2014  /* If a single pixel's alpha channel is non-zero, the icon
2015  will be alpha blended, otherwise it will be draw with
2016  and + xor blts. */
2017  check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
2018  check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
2019 
2020 cleanup:
2021  if(bmpOld)
2022  SelectObject(hdcDst, bmpOld);
2023  if(bmpDst)
2024  DeleteObject(bmpDst);
2025  if(hdcDst)
2026  DeleteDC(hdcDst);
2027 }
2028 
2029 static void check_DrawState_Size(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags, int line)
2030 {
2031  COLORREF result, background;
2032  BOOL passed[2];
2033  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2034  background = 0x00FFFFFF;
2035  /* Set color of the 2 pixels that will be checked afterwards */
2036  SetPixelV(hdc, 0, 0, background);
2037  SetPixelV(hdc, 2, 2, background);
2038 
2039  /* Let DrawState calculate the size of the icon (it's 1x1) */
2040  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, (DST_ICON | flags ));
2041 
2042  result = GetPixel(hdc, 0, 0);
2043  passed[0] = color_match(result, background);
2044  result = GetPixel(hdc, 2, 2);
2045  passed[0] = passed[0] & color_match(result, background);
2046 
2047  /* Check if manually specifying the icon size DOESN'T work */
2048 
2049  /* IMPORTANT: For Icons, DrawState wants the size of the source image, not the
2050  * size in which it should be ultimately drawn. Therefore giving
2051  * width/height 2x2 if the icon is only 1x1 pixels in size should
2052  * result in drawing it with size 1x1. The size parameters must be
2053  * ignored if a Icon has to be drawn! */
2054  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 2, 2, (DST_ICON | flags ));
2055 
2056  result = GetPixel(hdc, 0, 0);
2057  passed[1] = color_match(result, background);
2058  result = GetPixel(hdc, 2, 2);
2059  passed[1] = passed[0] & color_match(result, background);
2060 
2061  if(!passed[0]&&!passed[1])
2062  ok (passed[1],
2063  "DrawState failed to draw a 1x1 Icon in the correct size, independent of the "
2064  "width and height settings passed to it, for Icon with: Overlaying Mask %d on "
2065  "Color %06X with flags %08X. Line %d\n",
2066  maskvalue, color, (DST_ICON | flags), line);
2067  else if(!passed[1])
2068  ok (passed[1],
2069  "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2070  "parameters passed to it are bigger than the real Icon size, for Icon with: Overlaying "
2071  "Mask %d on Color %06X with flags %08X. Line %d\n",
2072  maskvalue, color, (DST_ICON | flags), line);
2073  else
2074  ok (passed[0],
2075  "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2076  "parameters passed to it are 0, for Icon with: Overlaying Mask %d on "
2077  "Color %06X with flags %08X. Line %d\n",
2078  maskvalue, color, (DST_ICON | flags), line);
2079 }
2080 
2081 static void check_DrawState_Color(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags,
2082  COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
2083 {
2084  COLORREF result;
2085  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2086  if (!hicon) return;
2087  /* Set color of the pixel that will be checked afterwards */
2088  SetPixelV(hdc, 1, 1, background);
2089 
2090  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, ( DST_ICON | flags ));
2091 
2092  /* Check the color of the pixel is correct */
2093  result = GetPixel(hdc, 1, 1);
2094 
2095  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
2096  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
2097  "DrawState drawing Icon with Overlaying Mask %d on Color %06X with flags %08X. "
2098  "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
2099  maskvalue, color, (DST_ICON | flags), modern_expected, legacy_expected, result, line);
2100 }
2101 
2102 static void test_DrawState(void)
2103 {
2104  BITMAPINFO bitmapInfo;
2105  HDC hdcDst = NULL;
2106  HBITMAP bmpDst = NULL;
2107  HBITMAP bmpOld = NULL;
2108  void *bits = 0;
2109 
2111  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
2112  if (!hdcDst)
2113  return;
2114 
2115  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2116  {
2117  skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
2118  goto cleanup;
2119  }
2120 
2121  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2122  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2123  bitmapInfo.bmiHeader.biWidth = 3;
2124  bitmapInfo.bmiHeader.biHeight = 3;
2125  bitmapInfo.bmiHeader.biBitCount = 32;
2126  bitmapInfo.bmiHeader.biPlanes = 1;
2127  bitmapInfo.bmiHeader.biCompression = BI_RGB;
2128  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2129  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2130  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2131  if (!bmpDst || !bits)
2132  goto cleanup;
2133  bmpOld = SelectObject(hdcDst, bmpDst);
2134 
2135  /* potential flags to test with DrawState are: */
2136  /* DSS_DISABLED embosses the icon */
2137  /* DSS_MONO draw Icon using a brush as parameter 5 */
2138  /* DSS_NORMAL draw Icon without any modifications */
2139  /* DSS_UNION draw the Icon dithered */
2140 
2141  check_DrawState_Size(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, __LINE__);
2142  check_DrawState_Color(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2143 
2144 cleanup:
2145  if(bmpOld)
2146  SelectObject(hdcDst, bmpOld);
2147  if(bmpDst)
2148  DeleteObject(bmpDst);
2149  if(hdcDst)
2150  DeleteDC(hdcDst);
2151 }
2152 
2154 
2156 {
2157  HCURSOR ret;
2158 
2159  PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE ); /* create a msg queue */
2160  if (parent_id)
2161  {
2163  ok( ret, "AttachThreadInput failed\n" );
2164  }
2165  if (arg) ret = SetCursor( (HCURSOR)arg );
2166  else ret = GetCursor();
2167  return (DWORD_PTR)ret;
2168 }
2169 
2170 static void test_SetCursor(void)
2171 {
2172  static const BYTE bmp_bits[4096];
2173  ICONINFO cursorInfo;
2174  HCURSOR cursor, old_cursor, global_cursor = 0;
2175  DWORD error, id, result;
2176  UINT display_bpp;
2177  HDC hdc;
2178  HANDLE thread;
2179  CURSORINFO info;
2180 
2181  if (pGetCursorInfo)
2182  {
2183  memset( &info, 0, sizeof(info) );
2184  info.cbSize = sizeof(info);
2185  if (!pGetCursorInfo( &info ))
2186  {
2187  win_skip( "GetCursorInfo not working\n" );
2188  pGetCursorInfo = NULL;
2189  }
2190  else global_cursor = info.hCursor;
2191  }
2192  cursor = GetCursor();
2193  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2194  WaitForSingleObject( thread, 1000 );
2196  ok( result == (DWORD_PTR)cursor, "wrong thread cursor %x/%p\n", result, cursor );
2197 
2198  hdc = GetDC(0);
2199  display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2200  ReleaseDC(0, hdc);
2201 
2202  cursorInfo.fIcon = FALSE;
2203  cursorInfo.xHotspot = 0;
2204  cursorInfo.yHotspot = 0;
2205  cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2206  cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2207 
2208  cursor = CreateIconIndirect(&cursorInfo);
2209  ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2210  old_cursor = SetCursor( cursor );
2211 
2212  if (pGetCursorInfo)
2213  {
2214  info.cbSize = sizeof(info);
2215  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2216  /* global cursor doesn't change since we don't have a window */
2217  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2218  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2219  }
2220  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2221  WaitForSingleObject( thread, 1000 );
2223  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2224 
2225  SetCursor( 0 );
2226  ok( GetCursor() == 0, "wrong cursor %p\n", GetCursor() );
2227  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2228  WaitForSingleObject( thread, 1000 );
2230  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2231 
2232  thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2233  WaitForSingleObject( thread, 1000 );
2235  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2236  ok( GetCursor() == 0, "wrong cursor %p/0\n", GetCursor() );
2237 
2239  thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2240  WaitForSingleObject( thread, 1000 );
2242  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2243  ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor );
2244 
2245  if (pGetCursorInfo)
2246  {
2247  info.cbSize = sizeof(info);
2248  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2249  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2250  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2251  }
2252  SetCursor( old_cursor );
2253  DestroyCursor( cursor );
2254 
2255  SetLastError( 0xdeadbeef );
2256  cursor = SetCursor( (HCURSOR)0xbadbad );
2257  error = GetLastError();
2258  ok( cursor == 0, "wrong cursor %p/0\n", cursor );
2259  ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ), /* win9x */
2260  "wrong error %u\n", error );
2261 
2262  if (pGetCursorInfo)
2263  {
2264  info.cbSize = sizeof(info);
2265  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2266  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2267  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2268  }
2269 }
2270 
2272 
2274 {
2275  DWORD count = (DWORD_PTR)arg;
2276  int ret;
2277 
2278  PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE ); /* create a msg queue */
2279  if (parent_id)
2280  {
2282  ok( ret, "AttachThreadInput failed\n" );
2283  }
2284  if (!count) ret = ShowCursor( FALSE );
2285  else while (count--) ret = ShowCursor( TRUE );
2286  SetEvent( event_start );
2288  return ret;
2289 }
2290 
2291 static void test_ShowCursor(void)
2292 {
2293  int count;
2294  DWORD id, result;
2295  HANDLE thread;
2296  CURSORINFO info;
2297 
2298  if (pGetCursorInfo)
2299  {
2300  memset( &info, 0, sizeof(info) );
2301  info.cbSize = sizeof(info);
2302  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2303  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2304  }
2305 
2308 
2309  count = ShowCursor( TRUE );
2310  ok( count == 1, "wrong count %d\n", count );
2311  count = ShowCursor( TRUE );
2312  ok( count == 2, "wrong count %d\n", count );
2313  count = ShowCursor( FALSE );
2314  ok( count == 1, "wrong count %d\n", count );
2315  count = ShowCursor( FALSE );
2316  ok( count == 0, "wrong count %d\n", count );
2317  count = ShowCursor( FALSE );
2318  ok( count == -1, "wrong count %d\n", count );
2319  count = ShowCursor( FALSE );
2320  ok( count == -2, "wrong count %d\n", count );
2321 
2322  if (pGetCursorInfo)
2323  {
2324  info.cbSize = sizeof(info);
2325  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2326  /* global show count is not affected since we don't have a window */
2327  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2328  }
2329 
2330  parent_id = 0;
2331  thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2333  count = ShowCursor( FALSE );
2334  ok( count == -3, "wrong count %d\n", count );
2335  SetEvent( event_next );
2336  WaitForSingleObject( thread, 1000 );
2338  ok( result == -1, "wrong thread count %d\n", result );
2339  count = ShowCursor( FALSE );
2340  ok( count == -4, "wrong count %d\n", count );
2341 
2342  thread = CreateThread( NULL, 0, show_cursor_thread, (void *)1, 0, &id );
2344  count = ShowCursor( TRUE );
2345  ok( count == -3, "wrong count %d\n", count );
2346  SetEvent( event_next );
2347  WaitForSingleObject( thread, 1000 );
2349  ok( result == 1, "wrong thread count %d\n", result );
2350  count = ShowCursor( TRUE );
2351  ok( count == -2, "wrong count %d\n", count );
2352 
2354  thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2356  count = ShowCursor( TRUE );
2357  ok( count == -2, "wrong count %d\n", count );
2358  SetEvent( event_next );
2359  WaitForSingleObject( thread, 1000 );
2361  ok( result == -3, "wrong thread count %d\n", result );
2362  count = ShowCursor( FALSE );
2363  ok( count == -2, "wrong count %d\n", count );
2364 
2365  thread = CreateThread( NULL, 0, show_cursor_thread, (void *)3, 0, &id );
2367  count = ShowCursor( TRUE );
2368  ok( count == 2, "wrong count %d\n", count );
2369  SetEvent( event_next );
2370  WaitForSingleObject( thread, 1000 );
2372  ok( result == 1, "wrong thread count %d\n", result );
2373  count = ShowCursor( FALSE );
2374  ok( count == -2, "wrong count %d\n", count );
2375 
2376  if (pGetCursorInfo)
2377  {
2378  info.cbSize = sizeof(info);
2379  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2380  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2381  }
2382 
2383  count = ShowCursor( TRUE );
2384  ok( count == -1, "wrong count %d\n", count );
2385  count = ShowCursor( TRUE );
2386  ok( count == 0, "wrong count %d\n", count );
2387 
2388  if (pGetCursorInfo)
2389  {
2390  info.cbSize = sizeof(info);
2391  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2392  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2393  }
2394 }
2395 
2396 
2397 static void test_DestroyCursor(void)
2398 {
2399  static const BYTE bmp_bits[4096];
2400  ICONINFO cursorInfo, new_info;
2401  HCURSOR cursor, cursor2, new_cursor;
2402  BOOL ret;
2403  DWORD error;
2404  UINT display_bpp;
2405  HDC hdc;
2406 
2407  hdc = GetDC(0);
2408  display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2409  ReleaseDC(0, hdc);
2410 
2411  cursorInfo.fIcon = FALSE;
2412  cursorInfo.xHotspot = 0;
2413  cursorInfo.yHotspot = 0;
2414  cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2415  cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2416 
2417  cursor = CreateIconIndirect(&cursorInfo);
2418  ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2419  if(!cursor) {
2420  return;
2421  }
2422  SetCursor(cursor);
2423 
2424  SetLastError(0xdeadbeef);
2426  ok(!ret || broken(ret) /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n");
2427  error = GetLastError();
2428  ok(error == 0xdeadbeef, "Last error: %u\n", error);
2429 
2430  new_cursor = GetCursor();
2431  if (ret) /* win9x replaces cursor by another one on destroy */
2432  ok(new_cursor != cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2433  else
2434  ok(new_cursor == cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2435 
2436  SetLastError(0xdeadbeef);
2437  ret = GetIconInfo( cursor, &new_info );
2438  ok( !ret || broken(ret), /* nt4 */ "GetIconInfo succeeded\n" );
2440  broken(GetLastError() == 0xdeadbeef), /* win9x */
2441  "wrong error %u\n", GetLastError() );
2442 
2443  if (ret) /* nt4 delays destruction until cursor changes */
2444  {
2445  DeleteObject( new_info.hbmColor );
2446  DeleteObject( new_info.hbmMask );
2447 
2448  SetLastError(0xdeadbeef);
2449  ret = DestroyCursor( cursor );
2450  ok( !ret, "DestroyCursor succeeded\n" );
2451  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2452  "wrong error %u\n", GetLastError() );
2453 
2454  SetLastError(0xdeadbeef);
2455  cursor2 = SetCursor( cursor );
2456  ok( cursor2 == cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2457  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2458  "wrong error %u\n", GetLastError() );
2459  }
2460  else
2461  {
2462  SetLastError(0xdeadbeef);
2463  cursor2 = CopyCursor( cursor );
2464  ok(!cursor2, "CopyCursor succeeded\n" );
2466  broken(GetLastError() == 0xdeadbeef), /* win9x */
2467  "wrong error %u\n", GetLastError() );
2468 
2469  SetLastError(0xdeadbeef);
2470  ret = DestroyCursor( cursor );
2471  if (new_cursor != cursor) /* win9x */
2472  ok( ret, "DestroyCursor succeeded\n" );
2473  else
2474  ok( !ret, "DestroyCursor succeeded\n" );
2475  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2476  "wrong error %u\n", GetLastError() );
2477 
2478  SetLastError(0xdeadbeef);
2479  cursor2 = SetCursor( cursor );
2480  ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2481  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2482  "wrong error %u\n", GetLastError() );
2483  }
2484 
2485  cursor2 = GetCursor();
2486  ok(cursor2 == new_cursor, "GetCursor returned %p/%p\n", cursor2, new_cursor);
2487 
2488  SetLastError(0xdeadbeef);
2489  cursor2 = SetCursor( 0 );
2490  if (new_cursor != cursor) /* win9x */
2491  ok(cursor2 == new_cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2492  else
2493  ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2494  ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
2495 
2496  cursor2 = GetCursor();
2497  ok(!cursor2, "GetCursor returned %p/%p\n", cursor2, cursor);
2498 
2499  SetLastError(0xdeadbeef);
2501  if (new_cursor != cursor) /* win9x */
2502  ok( ret, "DestroyCursor succeeded\n" );
2503  else
2504  ok( !ret, "DestroyCursor succeeded\n" );
2505  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2506  "wrong error %u\n", GetLastError() );
2507 
2508  DeleteObject(cursorInfo.hbmMask);
2509  DeleteObject(cursorInfo.hbmColor);
2510 
2511  /* Try testing DestroyCursor() now using LoadCursor() cursors. */
2513 
2514  SetLastError(0xdeadbeef);
2516  ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n");
2517  error = GetLastError();
2518  ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2519 
2520  /* Try setting the cursor to a destroyed OEM cursor. */
2521  SetLastError(0xdeadbeef);
2522  SetCursor(cursor);
2523  error = GetLastError();
2524  ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2525 
2526  /* Check if LoadCursor() returns the same handle with the same icon. */
2527  cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2528  ok(cursor2 == cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2529 
2530  /* Check if LoadCursor() returns the same handle with a different icon. */
2531  cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_WAIT);
2532  ok(cursor2 != cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2533 }
2534 
2535 static void test_PrivateExtractIcons(void)
2536 {
2537  HICON icon;
2538  UINT ret;
2539 
2540  static const test_icon_entries_t icon_desc[] = {{0,0,TRUE}, {16,16,TRUE}, {32,32}, {64,64,TRUE}};
2541 
2542  create_ico_file("extract.ico", icon_desc, sizeof(icon_desc)/sizeof(*icon_desc));
2543 
2544  ret = PrivateExtractIconsA("extract.ico", 0, 32, 32, &icon, NULL, 1, 0);
2545  ok(ret == 1, "PrivateExtractIconsA returned %u\n", ret);
2546  ok(icon != NULL, "icon == NULL\n");
2547 
2548  test_icon_info(icon, 32, 32, 32, 32);
2549  DestroyIcon(icon);
2550 
2551  DeleteFileA("extract.ico");
2552 }
2553 
2554 static void test_monochrome_icon(void)
2555 {
2556  HANDLE handle;
2557  BOOL ret;
2558  DWORD bytes_written;
2559  CURSORICONFILEDIR *icon_data;
2560  CURSORICONFILEDIRENTRY *icon_entry;
2561  BITMAPINFO *bitmap_info;
2562  BITMAPCOREINFO *core_info;
2563  ICONINFO icon_info;
2564  ULONG icon_size;
2565  BOOL monochrome, use_core_info;
2566 
2567  icon_data = HeapAlloc(GetProcessHeap(), 0, sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) +
2568  2 * sizeof(RGBQUAD) + sizeof(ULONG));
2569 
2570  for (monochrome = FALSE; monochrome <= TRUE; monochrome++)
2571  for (use_core_info = FALSE; use_core_info <= TRUE; use_core_info++)
2572  {
2573  trace("%s, %s\n",
2574  monochrome ? "monochrome" : "colored",
2575  use_core_info ? "core info" : "bitmap info");
2576 
2577  icon_size = sizeof(CURSORICONFILEDIR) +
2578  (use_core_info ? sizeof(BITMAPCOREHEADER) : sizeof(BITMAPINFOHEADER)) +
2579  /* 2 * sizeof(RGBTRIPLE) + padding comes out the same */
2580  2 * sizeof(RGBQUAD) +
2581  sizeof(ULONG);
2582  ZeroMemory(icon_data, icon_size);
2583  icon_data->idReserved = 0;
2584  icon_data->idType = 1;
2585  icon_data->idCount = 1;
2586 
2587  icon_entry = icon_data->idEntries;
2588  icon_entry->bWidth = 1;
2589  icon_entry->bHeight = 1;
2590  icon_entry->bColorCount = 0;
2591  icon_entry->bReserved = 0;
2592  icon_entry->xHotspot = 0;
2593  icon_entry->yHotspot = 0;
2594  icon_entry->dwDIBSize = icon_size - sizeof(CURSORICONFILEDIR);
2595  icon_entry->dwDIBOffset = sizeof(CURSORICONFILEDIR);
2596 
2597  if (use_core_info)
2598  {
2599  core_info = (BITMAPCOREINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2600  core_info->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
2601  core_info->bmciHeader.bcWidth = 1;
2602  core_info->bmciHeader.bcHeight = 2;
2603  core_info->bmciHeader.bcPlanes = 1;
2604  core_info->bmciHeader.bcBitCount = 1;
2605  core_info->bmciColors[0].rgbtBlue = monochrome ? 0x00 : 0xff;
2606  core_info->bmciColors[0].rgbtGreen = 0x00;
2607  core_info->bmciColors[0].rgbtRed = 0x00;
2608  core_info->bmciColors[1].rgbtBlue = 0xff;
2609  core_info->bmciColors[1].rgbtGreen = 0xff;
2610  core_info->bmciColors[1].rgbtRed = 0xff;
2611  }
2612  else
2613  {
2614  bitmap_info = (BITMAPINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2615  bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2616  bitmap_info->bmiHeader.biWidth = 1;
2617  bitmap_info->bmiHeader.biHeight = 2;
2618  bitmap_info->bmiHeader.biPlanes = 1;
2619  bitmap_info->bmiHeader.biBitCount = 1;
2620  bitmap_info->bmiHeader.biSizeImage = 0; /* Uncompressed bitmap. */
2621  bitmap_info->bmiColors[0].rgbBlue = monochrome ? 0x00 : 0xff;
2622  bitmap_info->bmiColors[0].rgbGreen = 0x00;
2623  bitmap_info->bmiColors[0].rgbRed = 0x00;
2624  bitmap_info->bmiColors[1].rgbBlue = 0xff;
2625  bitmap_info->bmiColors[1].rgbGreen = 0xff;
2626  bitmap_info->bmiColors[1].rgbRed = 0xff;
2627  }
2628 
2629  handle = CreateFileA("icon.ico", GENERIC_WRITE, 0, NULL, CREATE_NEW,
2631  ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
2632  ret = WriteFile(handle, icon_data, icon_size, &bytes_written, NULL);
2633  ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
2635 
2636  handle = LoadImageA(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
2637  ok(handle != NULL ||
2638  broken(use_core_info && handle == NULL), /* Win 8, 10 */
2639  "LoadImage() failed with %u.\n", GetLastError());
2640  if (handle == NULL)
2641  {
2642  skip("Icon failed to load: %s, %s\n",
2643  monochrome ? "monochrome" : "colored",
2644  use_core_info ? "core info" : "bitmap info");
2645  DeleteFileA("icon.ico");
2646  continue;
2647  }
2648 
2649  ret = GetIconInfo(handle, &icon_info);
2650  ok(ret, "GetIconInfo() failed with %u.\n", GetLastError());
2651  if (ret)
2652  {
2653  ok(icon_info.fIcon == TRUE, "fIcon is %u.\n", icon_info.fIcon);
2654  ok(icon_info.xHotspot == 0, "xHotspot is %u.\n", icon_info.xHotspot);
2655  ok(icon_info.yHotspot == 0, "yHotspot is %u.\n", icon_info.yHotspot);
2656  if (monochrome)
2657  ok(icon_info.hbmColor == NULL, "Got hbmColor %p!\n", icon_info.hbmColor);
2658  else
2659  ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
2660  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
2661  }
2662 
2663  ret = DestroyIcon(handle);
2664  ok(ret, "DestroyIcon() failed with %u.\n", GetLastError());
2665  DeleteFileA("icon.ico");
2666  }
2667 
2668  HeapFree(GetProcessHeap(), 0, icon_data);
2669 }
2670 
2671 START_TEST(cursoricon)
2672 {
2673  pGetCursorInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorInfo" );
2674  pGetIconInfoExA = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExA" );
2675  pGetIconInfoExW = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExW" );
2676  pGetCursorFrameInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorFrameInfo" );
2678 
2679  if (test_argc >= 3)
2680  {
2681  /* Child process. */
2682  sscanf (test_argv[2], "%x", (unsigned int *) &parent);
2683 
2684  ok(parent != NULL, "Parent not found.\n");
2685  if (parent == NULL)
2686  ExitProcess(1);
2687 
2688  do_child();
2689  return;
2690  }
2691 
2699  test_CreateIcon();
2700  test_LoadImage();
2703  test_DrawIcon();
2704  test_DrawIconEx();
2705  test_DrawState();
2706  test_SetCursor();
2707  test_ShowCursor();
2711  do_parent();
2714 }
int WINAPI GetObjectA(_In_ HANDLE h, _In_ int c, _Out_writes_bytes_opt_(c) LPVOID pv)
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
static void do_parent(void)
Definition: cursoricon.c:397
DWORD chunk_type
Definition: cursoricon.c:116
static const unsigned char gifimage[35]
Definition: cursoricon.c:971
#define ANI_anih_ID
Definition: cursoricon.c:63
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define BITSPIXEL
Definition: wingdi.h:719
static void test_SetCursor(void)
Definition: cursoricon.c:2170
#define CRSR_RES_SIZE
BYTE rgbtBlue
Definition: wingdi.h:1433
GLint GLint GLsizei width
Definition: gl.h:1546
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
#define max(a, b)
Definition: svc.c:63
BOOL WINAPI TranslateMessage(_In_ const MSG *)
LRESULT WINAPI DispatchMessageA(_In_ const MSG *)
DWORD bpp
Definition: cursoricon.c:78
#define ERROR_INVALID_CURSOR_HANDLE
Definition: winerror.h:883
static HICON
Definition: imagelist.c:84
namespace GUID const ADDRINFOEXW ADDRINFOEXW struct timeval OVERLAPPED LPLOOKUPSERVICE_COMPLETION_ROUTINE HANDLE * handle
Definition: sock.c:82
#define TRUE
Definition: types.h:120
#define CloseHandle
Definition: compat.h:398
DWORD chunk_size
Definition: cursoricon.c:133
#define IMAGE_ICON
Definition: winuser.h:212
BOOL WINAPI DestroyIcon(_In_ HICON hIcon)
Definition: cursoricon.c:2022
static void test_initial_cursor(void)
Definition: cursoricon.c:695
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1471
#define DWORD_PTR
Definition: treelist.c:76
DWORD header_size
Definition: cursoricon.c:73
#define error(str)
Definition: mkdosfs.c:1605
GLint x0
Definition: linetemp.h:95
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
#define DI_MASK
Definition: wingdi.h:71
BOOL WINAPI AttachThreadInput(_In_ DWORD, _In_ DWORD, _In_ BOOL)
HICON WINAPI CreateIcon(_In_opt_ HINSTANCE hInstance, _In_ int nWidth, _In_ int nHeight, _In_ BYTE cPlanes, _In_ BYTE cBitsPixel, _In_ const BYTE *lpbANDbits, _In_ const BYTE *lpbXORbits)
Definition: cursoricon.c:2364
static char ** test_argv
Definition: cursoricon.c:296
#define ANI_ACON_ID
Definition: cursoricon.c:62
HDC WINAPI GetDC(_In_opt_ HWND)
riff_rate3_t rates
Definition: cursoricon.c:149
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
BOOL WINAPI PostMessageA(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
LRESULT WINAPI SendMessageA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
char * wine_dbgstr_w(const wchar_t *wstr)
Definition: atltest.h:87
#define LR_LOADFROMFILE
Definition: winuser.h:1082
DWORD yHotspot
Definition: winuser.h:3099
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
GLuint GLuint GLsizei count
Definition: gl.h:1545
static DWORD DWORD istep
Definition: cursoricon.c:1521
BITMAPINFOHEADER bmi_header
Definition: cursoricon.c:91
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define IMAGE_CURSOR
Definition: winuser.h:213
#define PROC_INIT
Definition: cursoricon.c:302
static void test_CreateIconFromResource(void)
Definition: cursoricon.c:1337
#define CopyCursor(c)
Definition: winuser.h:4136
static HDC
Definition: imagelist.c:92
static void check_DrawState_Size(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags, int line)
Definition: cursoricon.c:2029
#define CALLBACK
Definition: compat.h:27
WCHAR szModName[MAX_PATH]
Definition: winuser.h:3126
WORD wResID
Definition: winuser.h:3112
HANDLE HWND
Definition: compat.h:13
BOOL WINAPI GetMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT)
static void test_LoadImage(void)
Definition: cursoricon.c:1210
#define ANI_FLAG_SEQUENCE
Definition: cursoricon.c:70
HANDLE WINAPI LoadImageA(_In_opt_ HINSTANCE hinst, _In_ LPCSTR lpszName, _In_ UINT uType, _In_ int cxDesired, _In_ int cyDesired, _In_ UINT fuLoad)
Definition: cursoricon.c:2147
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1497
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
BOOL WINAPI DeleteObject(_In_ HGDIOBJ)
GLuint buffer
Definition: glext.h:5915
int startup(int argc, const char *argv[])
Definition: startup.c:430
static const unsigned char invalid_dwDIBOffset[]
Definition: cursoricon.c:1035
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
START_TEST(cursoricon)
Definition: cursoricon.c:2671
CHAR szResName[MAX_PATH]
Definition: winuser.h:3114
static void test_CopyImage_Bitmap(int depth)
Definition: cursoricon.c:542
UINT_PTR WPARAM
Definition: windef.h:207
CURSORICONFILEDIRENTRY idEntries[1]
Definition: olepicture.c:108
HICON HCURSOR
Definition: windef.h:284
BOOL WINAPI PeekMessageA(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
int32_t INT_PTR
Definition: typedefs.h:62
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
const char * filename
Definition: ioapi.h:135
static LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: cursoricon.c:347
static int check_cursor_data(HDC hdc, HCURSOR hCursor, void *data, int length)
Definition: cursoricon.c:1478
riff_cursor3_t empty_anicursor3
Definition: cursoricon.c:222
#define DWORD
Definition: nt_native.h:44
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
int32_t INT
Definition: typedefs.h:56
static const unsigned char pngimage[285]
Definition: cursoricon.c:1000
static HWND child
Definition: cursoricon.c:298
WPARAM wParam
Definition: combotst.c:138
UCHAR rgbBlue
Definition: inbv.c:170
DWORD chunk_size
Definition: cursoricon.c:139
DWORD WINAPI GetVersion(VOID)
Definition: version.c:22
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:651
riff_icon32x32x32_t frames[3]
Definition: cursoricon.c:151
#define PM_NOREMOVE
Definition: winuser.h:1181
HANDLE WINAPI CopyImage(_In_ HANDLE hImage, _In_ UINT uType, _In_ int cxDesired, _In_ int cyDesired, _In_ UINT fuFlags)
Definition: cursoricon.c:1956
struct _test_info info[]
Definition: SetCursorPos.c:19
UCHAR rgbGreen
Definition: inbv.c:171
BOOL WINAPI GetIconInfo(_In_ HICON hIcon, _Out_ PICONINFO piconinfo)
Definition: cursoricon.c:2014
#define sprintf(buf, format,...)
Definition: sprintf.c:55
UCHAR rgbRed
Definition: inbv.c:172
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:540
BITMAPCOREHEADER bmciHeader
Definition: wingdi.h:1448
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static DWORD unk1
Definition: cursoricon.c:1521
#define ICON_HEIGHT
static void test_DrawIconEx(void)
Definition: cursoricon.c:1953
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
DWORD chunk_size
Definition: cursoricon.c:103
GLenum GLint GLuint mask
Definition: glext.h:6028
riff_cursor3_seq_t empty_anicursor3_seq
Definition: cursoricon.c:253
static void test_DrawIcon(void)
Definition: cursoricon.c:1869
unsigned int UINT32
DWORD chunk_id
Definition: cursoricon.c:102
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint color
Definition: glext.h:6243
static DWORD parent_id
Definition: cursoricon.c:2153
CURSORICONFILEDIR icon_info
Definition: cursoricon.c:90
#define GENERIC_WRITE
Definition: nt_native.h:90
HBITMAP hbmMask
Definition: winuser.h:3100
#define EMPTY_ICON32
Definition: cursoricon.c:154
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
static void do_child(void)
Definition: cursoricon.c:358
DWORD biCompression
Definition: amvideo.idl:35
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4216
#define SM_CXICON
Definition: winuser.h:962
static HICON create_test_icon(HDC hdc, int width, int height, int bpp, BOOL maskvalue, UINT32 *color, int colorSize)
Definition: cursoricon.c:1769
#define ICON_BPP
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1521
static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_mask_cy, UINT exp_bpp, int line)
Definition: cursoricon.c:712
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:136
smooth NULL
Definition: ftsmooth.c:416
static HANDLE event_next
Definition: cursoricon.c:2271
char ext[3]
Definition: mkdosfs.c:358
static ICONINFOEXA *static ICONINFOEXW *static const BOOL is_win64
Definition: cursoricon.c:308
#define IDC_WAIT
Definition: winuser.h:684
#define ICON_RES_SIZE
RGBTRIPLE bmciColors[1]
Definition: wingdi.h:1449
LONG_PTR LPARAM
Definition: windef.h:208
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
Definition: parser.c:48
HBITMAP hbmColor
Definition: winuser.h:3101
#define ANI_seq__ID
Definition: cursoricon.c:64
HCURSOR WINAPI LoadCursorA(_In_opt_ HINSTANCE hInstance, _In_ LPCSTR lpCursorName)
Definition: cursoricon.c:2059
static unsigned char bmpimage[70]
Definition: cursoricon.c:1012
static HANDLE child_process
Definition: cursoricon.c:300
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
static void 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)
Definition: cursoricon.c:2081
unsigned int dir
Definition: maze.c:112
const char * LPCSTR
Definition: xmlstorage.h:183
static DWORD CALLBACK show_cursor_thread(void *arg)
Definition: cursoricon.c:2273
#define STARTF_USESHOWWINDOW
Definition: winbase.h:472
DWORD height
Definition: cursoricon.c:77
static void test_LoadImageBitmap(const char *test_desc, HBITMAP hbm)
Definition: cursoricon.c:1060
riff_header_t header
Definition: cursoricon.c:117
ani_data32x32x32 bmi_data
Definition: cursoricon.c:92
DWORD WINAPI GetCurrentThreadId(VOID)
Definition: thread.c:458
#define WM_DESTROY
Definition: winuser.h:1591
DWORD chunk_size
Definition: cursoricon.c:97
static void create_ico_file(const char *filename, const test_icon_entries_t *test_icon_entries, unsigned entry_cnt)
Definition: cursoricon.c:1150
DWORD num_planes
Definition: cursoricon.c:79
static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight, INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
Definition: cursoricon.c:489
DWORD order[3]
Definition: cursoricon.c:140
HICON WINAPI LoadIconA(_In_opt_ HINSTANCE hInstance, _In_ LPCSTR lpIconName)
Definition: cursoricon.c:2029
static const unsigned char gif4pixel[42]
Definition: cursoricon.c:1028
BYTE data[32 *32 *4]
Definition: cursoricon.c:85
Definition: uimain.c:88
struct tagRGBQUAD RGBQUAD
int WINAPI ShowCursor(_In_ BOOL bShow)
Definition: cursoricon.c:2642
BOOL fIcon
Definition: winuser.h:3097
static void test_LoadImageFile(const char *test_desc, const unsigned char *image_data, unsigned int image_size, const char *ext, BOOL expect_success)
Definition: cursoricon.c:1085
static void test_GetCursorFrameInfo(void)
Definition: cursoricon.c:1522
WORD wResID
Definition: winuser.h:3125
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
DWORD chunk_size
Definition: cursoricon.c:115
riff_list_t frame_list
Definition: cursoricon.c:150
#define ANI_RIFF_ID
Definition: cursoricon.c:60
static int test_argc
Definition: cursoricon.c:297
static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
Definition: cursoricon.c:1936
#define GetProcessHeap()
Definition: compat.h:395
#define trace
Definition: atltest.h:70
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
riff_seq3_t seq
Definition: cursoricon.c:148
static const unsigned char bmpcoreimage[38]
Definition: cursoricon.c:1021
RGBQUAD bmiColors[1]
Definition: wingdi.h:1472
GLenum GLuint GLenum GLsizei length
Definition: glext.h:5579
static char * path_name(DOS_FILE *file)
Definition: check.c:208
#define CURSOR_SHOWING
Definition: winuser.h:2633
DWORD COLORREF
Definition: windef.h:285
DWORD xHotspot
Definition: winuser.h:3098
#define WM_CLOSE
Definition: winuser.h:1603
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation)
Definition: proc.c:4742
static HWND parent
Definition: cursoricon.c:299
#define CS_GLOBALCLASS
Definition: winuser.h:647
static void test_DrawState(void)
Definition: cursoricon.c:2102
static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: cursoricon.c:310
#define MAX_PATH
Definition: compat.h:26
DWORD num_steps
Definition: cursoricon.c:75
#define WINAPI
Definition: msvc.h:8
const char file[]
Definition: icontest.c:11
struct tagBITMAPCOREHEADER BITMAPCOREHEADER
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
static const DWORD biSize_tests[]
Definition: cursoricon.c:1040
unsigned long DWORD
Definition: ntddk_ex.h:95
DWORD chunk_id
Definition: cursoricon.c:138
DWORD biSizeImage
Definition: amvideo.idl:36
#define SetLastError(x)
Definition: compat.h:409
DWORD cbSize
Definition: winuser.h:3119
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
BITMAP bmp
Definition: alphablend.c:62
int winetest_get_mainargs(char ***pargv)
riff_header_t header
Definition: cursoricon.c:147
GLbitfield flags
Definition: glext.h:7161
HICON WINAPI CreateIconIndirect(_In_ PICONINFO piconinfo)
Definition: cursoricon.c:2546
riff_icon32x32x32_t frames[1]
Definition: cursoricon.c:119
static HANDLE thread
Definition: service.c:33
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
int ret
#define SM_CYICON
Definition: winuser.h:963
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:126
DWORD chunk_id
Definition: cursoricon.c:132
static const WCHAR L[]
Definition: oid.c:1250
#define todo_wine
Definition: test.h:154
DWORD rate[3]
Definition: cursoricon.c:134
CHAR szModName[MAX_PATH]
Definition: winuser.h:3113
HDC hdc
Definition: main.c:9
DWORD chunk_type
Definition: cursoricon.c:104
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define DI_NORMAL
Definition: wingdi.h:72
riff_header_t header
Definition: cursoricon.c:126
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:821
unsigned char BYTE
Definition: mem.h:68
static DWORD CALLBACK set_cursor_thread(void *arg)
Definition: cursoricon.c:2155
#define GENERIC_READ
Definition: compat.h:124
HICON WINAPI CreateIconFromResource(_In_ PBYTE presbits, _In_ DWORD dwResSize, _In_ BOOL fIcon, _In_ DWORD dwVer)
Definition: cursoricon.c:2402
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
DWORD flags
Definition: cursoricon.c:81
uint32_t DWORD_PTR
Definition: typedefs.h:63
#define WM_USER
Definition: winuser.h:1877
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
#define broken(x)
Definition: _sntprintf.h:21
ani_frame32x32x32 data
Definition: cursoricon.c:110
#define ARRAY_SIZE(a)
Definition: cursoricon.c:1057
#define ANI_FLAG_ICON
Definition: cursoricon.c:69
void winetest_wait_child_process(HANDLE process)
#define LR_MONOCHROME
Definition: winuser.h:1078
riff_cursor1_t empty_anicursor
Definition: cursoricon.c:193
static DWORD DWORD DWORD * rate
Definition: cursoricon.c:1521
BOOL WINAPI DrawIcon(_In_ HDC hDC, _In_ int X, _In_ int Y, _In_ HICON hIcon)
Definition: cursoricon.c:1987
DWORD chunk_type
Definition: cursoricon.c:125
UINT WINAPI PrivateExtractIconsA(_In_reads_(MAX_PATH) LPCSTR szFileName, _In_ int nIconIndex, _In_ int cxIcon, _In_ int cyIcon, _Out_writes_opt_(nIcons) HICON *phicon, _Out_writes_opt_(nIcons) UINT *piconid, _In_ UINT nIcons, _In_ UINT flags)
#define SW_SHOWNORMAL
Definition: winuser.h:764
static HDC hdcDst
Definition: xlate.c:32
DWORD display_rate
Definition: cursoricon.c:80
const char cursor[]
Definition: icontest.c:13
static void test_CreateIcon(void)
Definition: cursoricon.c:795
BOOL WINAPI DeleteDC(_In_ HDC)
static void test_DestroyCursor(void)
Definition: cursoricon.c:2397
HCURSOR WINAPI SetCursor(_In_opt_ HCURSOR)
HICON hIcon
Definition: msconfig.c:44
HCURSOR WINAPI GetCursor(void)
Definition: cursoricon.c:2649
DWORD num_frames
Definition: cursoricon.c:74
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:197
#define ANI_fram_ID
Definition: cursoricon.c:65
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
#define ok(value,...)
Definition: atltest.h:57
Definition: bl.h:1331
#define LR_CREATEDIBSECTION
Definition: winuser.h:1088
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define test_icon_info(a, b, c, d, e)
Definition: cursoricon.c:793
static BOOL(WINAPI *pGetCursorInfo)(CURSORINFO *)
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
#define WS_POPUP
Definition: pedump.c:616
BYTE rgbtRed
Definition: wingdi.h:1435
unsigned int UINT
Definition: ndis.h:50
#define IMAGE_BITMAP
Definition: winuser.h:211
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
static const BYTE dib[]
Definition: ole2.c:201
#define ANI_rate_ID
Definition: cursoricon.c:67
static BOOL color_match(COLORREF a, COLORREF b)
Definition: cursoricon.c:481
#define skip(...)
Definition: atltest.h:64
DWORD cbSize
Definition: winuser.h:3106
#define ERROR_DESTROY_OBJECT_OF_OTHER_THREAD
Definition: winerror.h:916
#define msg(x)
Definition: auth_time.c:54
#define IDC_ARROW
Definition: winuser.h:682
int WINAPI GetDIBits(_In_ HDC hdc, _In_ HBITMAP hbm, _In_ UINT start, _In_ UINT cLines, _Out_opt_ LPVOID lpvBits, _At_((LPBITMAPINFOHEADER) lpbmi, _Inout_) LPBITMAPINFO lpbmi, _In_ UINT usage)
BOOL WINAPI DrawStateA(_In_ HDC, _In_opt_ HBRUSH, _In_opt_ DRAWSTATEPROC, _In_ LPARAM, _In_ WPARAM, _In_ int, _In_ int, _In_ int, _In_ int, _In_ UINT)
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define DSS_NORMAL
Definition: winuser.h:517
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:847
BOOL WINAPI DestroyCursor(_In_ HCURSOR hCursor)
Definition: cursoricon.c:2654
char * cleanup(char *str)
Definition: wpickclick.c:99
#define GetProcAddress(x, y)
Definition: compat.h:410
DWORD bpp
Definition: surface.c:181
DWORD width
Definition: cursoricon.c:76
static void test_child_process(void)
Definition: cursoricon.c:453
static void finish_child_process(void)
Definition: cursoricon.c:446
#define CREATE_NEW
Definition: disk.h:69
static HBITMAP
Definition: button.c:44
BYTE rgbtGreen
Definition: wingdi.h:1434
static const unsigned char jpgimage[285]
Definition: cursoricon.c:978
#define DST_ICON
Definition: winuser.h:515
static void test_ShowCursor(void)
Definition: cursoricon.c:2291
DWORD chunk_id
Definition: cursoricon.c:96
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:399
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
BOOL WINAPI SetPixelV(_In_ HDC, _In_ int, _In_ int, _In_ COLORREF)
WCHAR szResName[MAX_PATH]
Definition: winuser.h:3127
static void test_PrivateExtractIcons(void)
Definition: cursoricon.c:2535
LONG_PTR LRESULT
Definition: windef.h:209
#define DIB_RGB_COLORS
Definition: wingdi.h:366
#define ANI_LIST_ID
Definition: cursoricon.c:61
#define WS_VISIBLE
Definition: pedump.c:620
static HANDLE event_start
Definition: cursoricon.c:2271
ani_header header
Definition: cursoricon.c:98
GLuint64EXT * result
Definition: glext.h:11304
#define memset(x, y, z)
Definition: compat.h:39
static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
Definition: cursoricon.c:1805
#define ERROR_BAD_PATHNAME
Definition: winerror.h:233
#define win_skip
Definition: test.h:141
BYTE * PBYTE
Definition: pedump.c:66
#define BI_RGB
Definition: precomp.h:34
LPARAM lParam
Definition: combotst.c:139
static HCURSOR(WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor
DWORD chunk_size
Definition: cursoricon.c:124
#define ICON_WIDTH
riff_list_t frame_list
Definition: cursoricon.c:127
#define HeapFree(x, y, z)
Definition: compat.h:394
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
__analysis_noreturn void WINAPI PostQuitMessage(_In_ int)
#define IDI_HAND
Definition: winuser.h:700
static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
Definition: cursoricon.c:1835
riff_list_t frame_list
Definition: cursoricon.c:118
#define DI_IMAGE
Definition: wingdi.h:70
BOOL WINAPI DrawIconEx(_In_ HDC hdc, _In_ int xLeft, _In_ int yTop, _In_ HICON hIcon, _In_ int cxWidth, _In_ int cyWidth, _In_ UINT istepIfAniCur, _In_opt_ HBRUSH hbrFlickerFreeDraw, _In_ UINT diFlags)
Definition: cursoricon.c:1997
static void test_monochrome_icon(void)
Definition: cursoricon.c:2554
riff_icon32x32x32_t frames[3]
Definition: cursoricon.c:128
#define ok_(x1, x2)
Definition: atltest.h:61
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
Definition: mipmap.c:4856
iconPos iconPos icon_size
Definition: startmenu.cpp:1416
HBITMAP WINAPI CreateBitmap(_In_ INT cx, _In_ INT cy, _In_ UINT cPlanes, _In_ UINT cBitsPerPel, _In_opt_ const VOID *pvBits)
Definition: fci.c:126
signed short INT16