ReactOS  0.4.14-dev-593-g1793dcc
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 static void test_LoadImageBitmap(const char * test_desc, HBITMAP hbm)
1057 {
1058  BITMAP bm;
1059  BITMAPINFO bmi;
1060  DWORD ret, pixel = 0;
1061  HDC hdc = GetDC(NULL);
1062 
1063  ret = GetObjectA(hbm, sizeof(bm), &bm);
1064  ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
1065 
1066  memset(&bmi, 0, sizeof(bmi));
1067  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
1068  bmi.bmiHeader.biWidth = bm.bmWidth;
1069  bmi.bmiHeader.biHeight = bm.bmHeight;
1070  bmi.bmiHeader.biPlanes = 1;
1071  bmi.bmiHeader.biBitCount= 24;
1073  ret = GetDIBits(hdc, hbm, 0, bm.bmHeight, &pixel, &bmi, DIB_RGB_COLORS);
1074  ok(ret == bm.bmHeight, "%s: %d lines were converted, not %d\n", test_desc, ret, bm.bmHeight);
1075 
1076  ok(color_match(pixel, 0x00ffffff), "%s: Pixel is 0x%08x\n", test_desc, pixel);
1077 
1078  ReleaseDC(NULL, hdc);
1079 }
1080 
1081 static void test_LoadImageFile(const char * test_desc, const unsigned char * image_data,
1082  unsigned int image_size, const char * ext, BOOL expect_success)
1083 {
1084  HANDLE handle;
1085  BOOL ret;
1086  DWORD error, bytes_written;
1087  char filename[64];
1088 
1089  strcpy(filename, "test.");
1090  strcat(filename, ext);
1091 
1092  /* Create the test image. */
1095  ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1096  ret = WriteFile(handle, image_data, image_size, &bytes_written, NULL);
1097  ok(ret && bytes_written == image_size, "test file created improperly.\n");
1099 
1100  /* Load as cursor. For all tested formats, this should fail */
1101  SetLastError(0xdeadbeef);
1103  ok(handle == NULL, "%s: IMAGE_CURSOR succeeded incorrectly.\n", test_desc);
1104  error = GetLastError();
1105  ok(error == 0 ||
1106  broken(error == 0xdeadbeef) || /* Win9x */
1107  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1108  "Last error: %u\n", error);
1109  if (handle != NULL) DestroyCursor(handle);
1110 
1111  /* Load as icon. For all tested formats, this should fail */
1112  SetLastError(0xdeadbeef);
1114  ok(handle == NULL, "%s: IMAGE_ICON succeeded incorrectly.\n", test_desc);
1115  error = GetLastError();
1116  ok(error == 0 ||
1117  broken(error == 0xdeadbeef) || /* Win9x */
1118  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1119  "Last error: %u\n", error);
1120  if (handle != NULL) DestroyIcon(handle);
1121 
1122  /* Load as bitmap. Should succeed for correct bmp, fail for everything else */
1123  SetLastError(0xdeadbeef);
1125  error = GetLastError();
1126  ok(error == 0 ||
1127  error == 0xdeadbeef, /* Win9x, WinMe */
1128  "Last error: %u\n", error);
1129 
1130  if (expect_success) {
1131  ok(handle != NULL, "%s: IMAGE_BITMAP failed.\n", test_desc);
1132  if (handle != NULL) test_LoadImageBitmap(test_desc, handle);
1133  }
1134  else ok(handle == NULL, "%s: IMAGE_BITMAP succeeded incorrectly.\n", test_desc);
1135 
1136  if (handle != NULL) DeleteObject(handle);
1138 }
1139 
1140 typedef struct {
1141  unsigned width;
1142  unsigned height;
1145 
1146 static void create_ico_file(const char *filename, const test_icon_entries_t *test_icon_entries, unsigned entry_cnt)
1147 {
1148  CURSORICONFILEDIRENTRY *icon_entry;
1149  BITMAPINFOHEADER *icon_header;
1151  BYTE *buf, *bitmap_ptr;
1152  DWORD bytes_written;
1153  size_t icon_size;
1154  HANDLE file;
1155  unsigned i;
1156  BOOL ret;
1157 
1158  const unsigned icon_bpp = 32;
1159 
1160  icon_size = FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]) + sizeof(BITMAPINFOHEADER)*entry_cnt;
1161  for(i=0; i<entry_cnt; i++)
1162  icon_size += icon_bpp * test_icon_entries[i].width * test_icon_entries[i].height / 8;
1163 
1166 
1167  dir->idReserved = 0;
1168  dir->idType = 1;
1169  dir->idCount = entry_cnt;
1170 
1171  bitmap_ptr = buf + FIELD_OFFSET(CURSORICONFILEDIR, idEntries[entry_cnt]);
1172  for(i=0; i<entry_cnt; i++) {
1173  icon_entry = dir->idEntries+i;
1174  icon_entry->bWidth = test_icon_entries[i].width;
1175  icon_entry->bHeight = test_icon_entries[i].height;
1176  icon_entry->bColorCount = 0;
1177  icon_entry->bReserved = 0;
1178  icon_entry->xHotspot = 1;
1179  icon_entry->yHotspot = 1;
1180  icon_entry->dwDIBSize = sizeof(BITMAPINFOHEADER) + icon_entry->bWidth * icon_entry->bHeight * icon_bpp / 8;
1181  icon_entry->dwDIBOffset = test_icon_entries[i].invalid_offset ? 0xffffffff : bitmap_ptr - buf;
1182 
1183  icon_header = (BITMAPINFOHEADER*)bitmap_ptr;
1184  bitmap_ptr += icon_entry->dwDIBSize;
1185 
1186  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1187  icon_header->biWidth = icon_entry->bWidth;
1188  icon_header->biHeight = icon_entry->bHeight;
1189  icon_header->biPlanes = 1;
1190  icon_header->biBitCount = icon_bpp;
1191  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1192  }
1193 
1194  memset(bitmap_ptr, 0xf0, buf+icon_size-bitmap_ptr);
1195 
1196  /* Create the icon. */
1198  ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
1199  ret = WriteFile(file, buf, icon_size, &bytes_written, NULL);
1200  ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
1201  CloseHandle(file);
1202 
1203  HeapFree(GetProcessHeap(), 0, buf);
1204 }
1205 
1206 static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits)
1207 {
1208  unsigned int clr_used, bmi_size, bits_size, stride;
1209  const BITMAPINFOHEADER *h = &bmi->bmiHeader;
1211  DWORD bytes_written;
1212  HANDLE file;
1213  BOOL ret;
1214 
1215  clr_used = h->biBitCount <= 8 ? 1u << h->biBitCount : 0;
1216  stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
1217  bits_size = h->biHeight * stride;
1218  bmi_size = h->biSize + clr_used * sizeof(RGBQUAD);
1219 
1220  hdr.bfType = 0x4d42;
1221  hdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + bmi_size;
1222  hdr.bfSize = hdr.bfOffBits + bits_size;
1223  hdr.bfReserved1 = 0;
1224  hdr.bfReserved2 = 0;
1225 
1227  ok(file != INVALID_HANDLE_VALUE, "CreateFileA failed, result %u.\n", GetLastError());
1228  ret = WriteFile(file, &hdr, sizeof(hdr), &bytes_written, NULL);
1229  ok(ret && bytes_written == sizeof(hdr), "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1230  ret, bytes_written);
1231  ret = WriteFile(file, bmi, bmi_size, &bytes_written, NULL);
1232  ok(ret && bytes_written == bmi_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1233  ret, bytes_written);
1234  ret = WriteFile(file, bits, bits_size, &bytes_written, NULL);
1235  ok(ret && bytes_written == bits_size, "Unexpected WriteFile() result, ret %#x, bytes_written %u.\n",
1236  ret, bytes_written);
1237  CloseHandle(file);
1238 }
1239 
1241 {
1242  DWORD bytes_written;
1243  HANDLE handle;
1244  BOOL ret;
1245  char path_icon[MAX_PATH];
1246  char path_image[MAX_PATH];
1247  static const test_icon_entries_t icon_desc = {32, 32};
1248 
1249  sprintf(path_icon, "%s\\icon.ico", path);
1250  sprintf(path_image, "%s\\test.bmp", path);
1251 
1252  /* Create Files */
1253  create_ico_file(path_icon, &icon_desc, 1);
1254 
1256  ok(handle != INVALID_HANDLE_VALUE, "run %s: CreateFileA failed. %u\n", path, GetLastError());
1257  ret = WriteFile(handle, bmpimage, sizeof(bmpimage), &bytes_written, NULL);
1258  ok(ret && bytes_written == sizeof(bmpimage), "run %s: Test file created improperly.\n", path);
1260 
1261  /* Test cursor */
1262  handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1263  ok(handle != NULL, "run %s: LoadImage() failed.\n", path);
1264 
1265  ret = DestroyIcon(handle);
1266  ok(ret, "run %s: DestroyIcon failed: %d\n", path, GetLastError());
1267 
1268  /* Test image */
1269  handle = LoadImageA(NULL, "test.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
1270  ok(handle != NULL, "run %s: LoadImageA failed.\n", path);
1271 
1272  ret = DeleteObject(handle);
1273  ok(ret, "run %s: DeleteObject failed: %d\n", path, GetLastError());
1274 
1275  /* Cleanup */
1276  ret = DeleteFileA(path_image);
1277  ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
1278  ret = DeleteFileA(path_icon);
1279  ok(ret, "run %s: DeleteFileA failed: %d\n", path, GetLastError());
1280 }
1281 
1283 {
1284  char old_working_dir[MAX_PATH];
1285  char temp_dir_current[MAX_PATH];
1286  char temp_dir_PATH[MAX_PATH];
1287  char executable_path[MAX_PATH];
1288  int pos_slash;
1289  char old_PATH[10000];
1290  char new_PATH[10000];
1291  BOOL ret;
1292 
1293  GetCurrentDirectoryA(ARRAY_SIZE(old_working_dir), old_working_dir);
1294 
1295  GetTempPathA(ARRAY_SIZE(temp_dir_current), temp_dir_current);
1296  strcat(temp_dir_current, "wine-test-dir-current\\");
1297  GetTempPathA(ARRAY_SIZE(temp_dir_PATH), temp_dir_PATH);
1298  strcat(temp_dir_PATH, "wine-test-dir-path\\");
1299 
1300  GetModuleFileNameA(NULL, executable_path, ARRAY_SIZE(executable_path));
1301  pos_slash = strrchr(executable_path, '\\') - executable_path;
1302  executable_path[pos_slash + 1] = 0;
1303 
1304  CreateDirectoryA(temp_dir_current, NULL);
1305  CreateDirectoryA(temp_dir_PATH, NULL);
1306 
1307  SetCurrentDirectoryA(temp_dir_current);
1308 
1309  GetEnvironmentVariableA("PATH", old_PATH, ARRAY_SIZE(old_PATH));
1310  sprintf(new_PATH, "%s;%s", old_PATH, temp_dir_PATH);
1311  SetEnvironmentVariableA("PATH", new_PATH);
1312 
1313  test_LoadImage_working_directory_run(temp_dir_current);
1314  test_LoadImage_working_directory_run(executable_path);
1315  test_LoadImage_working_directory_run(temp_dir_PATH);
1316 
1317  SetCurrentDirectoryA(old_working_dir);
1318  SetEnvironmentVariableA("PATH", old_PATH);
1319 
1320  ret = RemoveDirectoryA(temp_dir_current);
1321  ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
1322  ret = RemoveDirectoryA(temp_dir_PATH);
1323  ok(ret, "RemoveDirectoryA failed: %d\n", GetLastError());
1324 }
1325 
1326 static void test_LoadImage(void)
1327 {
1328  HANDLE handle;
1329  BOOL ret;
1330  DWORD error;
1331  BITMAPINFOHEADER *bitmap_header;
1332  ICONINFO icon_info;
1333  int i;
1334 
1335 #define ICON_WIDTH 32
1336 #define ICON_HEIGHT 32
1337 #define ICON_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1338 #define ICON_BPP 32
1339 #define ICON_SIZE \
1340  (sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) \
1341  + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1342 
1343  static const test_icon_entries_t icon_desc = {32, 32};
1344 
1345  create_ico_file("icon.ico", &icon_desc, 1);
1346 
1347  /* Test loading an icon as a cursor. */
1348  SetLastError(0xdeadbeef);
1349  handle = LoadImageA(NULL, "icon.ico", IMAGE_CURSOR, 0, 0, LR_LOADFROMFILE);
1350  ok(handle != NULL, "LoadImage() failed.\n");
1351  error = GetLastError();
1352  ok(error == 0 ||
1353  broken(error == 0xdeadbeef) || /* Win9x */
1354  broken(error == ERROR_BAD_PATHNAME), /* Win98, WinMe */
1355  "Last error: %u\n", error);
1356 
1357  /* Test the icon information. */
1358  SetLastError(0xdeadbeef);
1359  ret = GetIconInfo(handle, &icon_info);
1360  ok(ret, "GetIconInfo() failed.\n");
1361  error = GetLastError();
1362  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1363 
1364  if (ret)
1365  {
1366  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1367  ok(icon_info.xHotspot == 1, "xHotspot is %u.\n", icon_info.xHotspot);
1368  ok(icon_info.yHotspot == 1, "yHotspot is %u.\n", icon_info.yHotspot);
1369  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1370  "No hbmColor!\n");
1371  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1372  }
1373 
1374  if (pGetIconInfoExA)
1375  {
1376  ICONINFOEXA infoex;
1377  infoex.cbSize = sizeof(infoex);
1378  ret = pGetIconInfoExA( handle, &infoex );
1379  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1380  ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1381  ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1382  ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1383  }
1384  else win_skip( "GetIconInfoEx not available\n" );
1385 
1386  /* Clean up. */
1387  SetLastError(0xdeadbeef);
1389  ok(ret, "DestroyCursor() failed.\n");
1390  error = GetLastError();
1391  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1392 
1393  DeleteFileA("icon.ico");
1394 
1395  /* Test a system icon */
1396  handle = LoadIconA( 0, (LPCSTR)IDI_HAND );
1397  ok(handle != NULL, "LoadImage() failed.\n");
1398  if (pGetIconInfoExA)
1399  {
1400  ICONINFOEXA infoexA;
1401  ICONINFOEXW infoexW;
1402  infoexA.cbSize = sizeof(infoexA);
1403  ret = pGetIconInfoExA( handle, &infoexA );
1404  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1405  ok( infoexA.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexA.wResID );
1406  /* the A version is broken on 64-bit, it truncates the string after the first char */
1407  if (is_win64 && infoexA.szModName[0] && infoexA.szModName[1] == 0)
1408  trace( "GetIconInfoExA broken on Win64\n" );
1409  else
1410  ok( GetModuleHandleA(infoexA.szModName) == GetModuleHandleA("user32.dll"),
1411  "GetIconInfoEx wrong module %s\n", infoexA.szModName );
1412  ok( infoexA.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoexA.szResName );
1413  infoexW.cbSize = sizeof(infoexW);
1414  ret = pGetIconInfoExW( handle, &infoexW );
1415  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1416  ok( infoexW.wResID == (UINT_PTR)IDI_HAND, "GetIconInfoEx wrong resid %x\n", infoexW.wResID );
1417  ok( GetModuleHandleW(infoexW.szModName) == GetModuleHandleA("user32.dll"),
1418  "GetIconInfoEx wrong module %s\n", wine_dbgstr_w(infoexW.szModName) );
1419  ok( infoexW.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", wine_dbgstr_w(infoexW.szResName) );
1420  }
1421  SetLastError(0xdeadbeef);
1423 
1424  test_LoadImageFile("BMP", bmpimage, sizeof(bmpimage), "bmp", 1);
1425  test_LoadImageFile("BMP (coreinfo)", bmpcoreimage, sizeof(bmpcoreimage), "bmp", 1);
1426  test_LoadImageFile("GIF", gifimage, sizeof(gifimage), "gif", 0);
1427  test_LoadImageFile("GIF (2x2 pixel)", gif4pixel, sizeof(gif4pixel), "gif", 0);
1428  test_LoadImageFile("JPG", jpgimage, sizeof(jpgimage), "jpg", 0);
1429  test_LoadImageFile("PNG", pngimage, sizeof(pngimage), "png", 0);
1430 
1431  /* Check failure for broken BMP images */
1432  bitmap_header = (BITMAPINFOHEADER *)(bmpimage + sizeof(BITMAPFILEHEADER));
1433 
1434  bitmap_header->biHeight = 65536;
1435  test_LoadImageFile("BMP (too high)", bmpimage, sizeof(bmpimage), "bmp", 0);
1436  bitmap_header->biHeight = 1;
1437 
1438  bitmap_header->biWidth = 65536;
1439  test_LoadImageFile("BMP (too wide)", bmpimage, sizeof(bmpimage), "bmp", 0);
1440  bitmap_header->biWidth = 1;
1441 
1442  for (i = 0; i < ARRAY_SIZE(biSize_tests); i++) {
1443  bitmap_header->biSize = biSize_tests[i];
1444  test_LoadImageFile("BMP (broken biSize)", bmpimage, sizeof(bmpimage), "bmp", 0);
1445  }
1446  bitmap_header->biSize = sizeof(BITMAPINFOHEADER);
1447 
1448  test_LoadImageFile("Cursor (invalid dwDIBOffset)", invalid_dwDIBOffset, sizeof(invalid_dwDIBOffset), "cur", 0);
1449 
1450  /* Test in which paths images with a relative path can be found */
1452 }
1453 
1455 {
1456  HANDLE handle;
1457  BOOL ret;
1458  DWORD error;
1459  BITMAPINFOHEADER *icon_header;
1460  INT16 *hotspot;
1461  ICONINFO icon_info;
1462 
1463 #define ICON_RES_WIDTH 32
1464 #define ICON_RES_HEIGHT 32
1465 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1466 #define ICON_RES_BPP 32
1467 #define ICON_RES_SIZE \
1468  (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1469 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1470 
1471  /* Set icon data. */
1473 
1474  /* Cursor resources have an extra hotspot, icon resources not. */
1475  hotspot[0] = 3;
1476  hotspot[1] = 3;
1477 
1478  icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1479  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1480  icon_header->biWidth = ICON_WIDTH;
1481  icon_header->biHeight = ICON_HEIGHT*2;
1482  icon_header->biPlanes = 1;
1483  icon_header->biBitCount = ICON_BPP;
1484  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1485 
1486  /* Test creating a cursor. */
1487  SetLastError(0xdeadbeef);
1488  handle = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1489  ok(handle != NULL, "Create cursor failed.\n");
1490 
1491  /* Test the icon information. */
1492  SetLastError(0xdeadbeef);
1493  ret = GetIconInfo(handle, &icon_info);
1494  ok(ret, "GetIconInfo() failed.\n");
1495  error = GetLastError();
1496  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1497 
1498  if (ret)
1499  {
1500  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1501  ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1502  ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1503  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1504  "No hbmColor!\n");
1505  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1506  }
1507 
1508  if (pGetIconInfoExA)
1509  {
1510  ICONINFOEXA infoex;
1511  infoex.cbSize = sizeof(infoex);
1512  ret = pGetIconInfoExA( handle, &infoex );
1513  ok( ret, "GetIconInfoEx failed err %d\n", GetLastError() );
1514  ok( infoex.wResID == 0, "GetIconInfoEx wrong resid %x\n", infoex.wResID );
1515  ok( infoex.szModName[0] == 0, "GetIconInfoEx wrong module %s\n", infoex.szModName );
1516  ok( infoex.szResName[0] == 0, "GetIconInfoEx wrong name %s\n", infoex.szResName );
1517  }
1518 
1519  /* Clean up. */
1520  SetLastError(0xdeadbeef);
1522  ok(ret, "DestroyCursor() failed.\n");
1523  error = GetLastError();
1524  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1525 
1526  /* Test creating an icon. */
1527  SetLastError(0xdeadbeef);
1529  0x00030000);
1530  ok(handle != NULL, "Create icon failed.\n");
1531 
1532  /* Test the icon information. */
1533  SetLastError(0xdeadbeef);
1534  ret = GetIconInfo(handle, &icon_info);
1535  ok(ret, "GetIconInfo() failed.\n");
1536  error = GetLastError();
1537  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1538 
1539  if (ret)
1540  {
1541  ok(icon_info.fIcon == TRUE, "fIcon != TRUE.\n");
1542  /* Icons always have hotspot in the middle */
1543  ok(icon_info.xHotspot == ICON_WIDTH/2, "xHotspot is %u.\n", icon_info.xHotspot);
1544  ok(icon_info.yHotspot == ICON_HEIGHT/2, "yHotspot is %u.\n", icon_info.yHotspot);
1545  ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
1546  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1547  }
1548 
1549  /* Clean up. */
1550  SetLastError(0xdeadbeef);
1552  ok(ret, "DestroyCursor() failed.\n");
1553  error = GetLastError();
1554  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1555 
1556  /* Rejection of NULL pointer crashes at least on WNT4WSSP6, W2KPROSP4, WXPPROSP3
1557  *
1558  * handle = CreateIconFromResource(NULL, ICON_RES_SIZE, TRUE, 0x00030000);
1559  * ok(handle == NULL, "Invalid pointer accepted (%p)\n", handle);
1560  */
1561  HeapFree(GetProcessHeap(), 0, hotspot);
1562 
1563  /* Test creating an animated cursor. */
1564  empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1568  ok(handle != NULL, "Create cursor failed.\n");
1569 
1570  /* Test the animated cursor's information. */
1571  SetLastError(0xdeadbeef);
1572  ret = GetIconInfo(handle, &icon_info);
1573  ok(ret, "GetIconInfo() failed.\n");
1574  error = GetLastError();
1575  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1576 
1577  if (ret)
1578  {
1579  ok(icon_info.fIcon == FALSE, "fIcon != FALSE.\n");
1580  ok(icon_info.xHotspot == 3, "xHotspot is %u.\n", icon_info.xHotspot);
1581  ok(icon_info.yHotspot == 3, "yHotspot is %u.\n", icon_info.yHotspot);
1582  ok(icon_info.hbmColor != NULL || broken(!icon_info.hbmColor) /* no color cursor support */,
1583  "No hbmColor!\n");
1584  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
1585  }
1586 
1587  /* Clean up. */
1588  SetLastError(0xdeadbeef);
1590  ok(ret, "DestroyCursor() failed.\n");
1591  error = GetLastError();
1592  ok(error == 0xdeadbeef, "Last error: %u\n", error);
1593 }
1594 
1595 static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
1596 {
1597  char *image = NULL;
1598  BITMAPINFO *info;
1599  ICONINFO iinfo;
1600  DWORD ret;
1601  int i;
1602 
1603  ret = GetIconInfo( hCursor, &iinfo );
1604  ok(ret, "GetIconInfo() failed\n");
1605  if (!ret) return 0;
1606  ret = 0;
1607  info = HeapAlloc( GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
1608  ok(info != NULL, "HeapAlloc() failed\n");
1609  if (!info) return 0;
1610 
1611  info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1612  info->bmiHeader.biWidth = 32;
1613  info->bmiHeader.biHeight = 32;
1614  info->bmiHeader.biPlanes = 1;
1615  info->bmiHeader.biBitCount = 32;
1616  info->bmiHeader.biCompression = BI_RGB;
1617  info->bmiHeader.biSizeImage = 32 * 32 * 4;
1618  info->bmiHeader.biXPelsPerMeter = 0;
1619  info->bmiHeader.biYPelsPerMeter = 0;
1620  info->bmiHeader.biClrUsed = 0;
1621  info->bmiHeader.biClrImportant = 0;
1622  image = HeapAlloc( GetProcessHeap(), 0, info->bmiHeader.biSizeImage );
1623  ok(image != NULL, "HeapAlloc() failed\n");
1624  if (!image) goto cleanup;
1625  ret = GetDIBits( hdc, iinfo.hbmColor, 0, 32, image, info, DIB_RGB_COLORS );
1626  ok(ret, "GetDIBits() failed\n");
1627  for (i = 0; ret && i < length / sizeof(COLORREF); i++)
1628  {
1629  ret = color_match( ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1630  ok(ret, "%04x: Expected 0x%x, actually 0x%x\n", i, ((COLORREF *)data)[i], ((COLORREF *)image)[i] );
1631  }
1632 cleanup:
1633  HeapFree( GetProcessHeap(), 0, image );
1634  HeapFree( GetProcessHeap(), 0, info );
1635  return ret;
1636 }
1637 
1638 static HCURSOR (WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor, DWORD unk1, DWORD istep, DWORD *rate, DWORD *steps);
1639 static void test_GetCursorFrameInfo(void)
1640 {
1641  DWORD frame_identifier[] = { 0x10Ad, 0xc001, 0x1c05 };
1642  HBITMAP bmp = NULL, bmpOld = NULL;
1643  DWORD rate, steps;
1644  BITMAPINFOHEADER *icon_header;
1645  BITMAPINFO bitmapInfo;
1646  HDC hdc = NULL;
1647  void *bits = 0;
1648  INT16 *hotspot;
1649  HANDLE h1, h2;
1650  BOOL ret;
1651  int i;
1652 
1653  if (!pGetCursorFrameInfo)
1654  {
1655  win_skip( "GetCursorFrameInfo not supported, skipping tests.\n" );
1656  return;
1657  }
1658 
1659  hdc = CreateCompatibleDC(0);
1660  ok(hdc != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1661  if (!hdc)
1662  return;
1663 
1664  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1665  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1666  bitmapInfo.bmiHeader.biWidth = 3;
1667  bitmapInfo.bmiHeader.biHeight = 3;
1668  bitmapInfo.bmiHeader.biBitCount = 32;
1669  bitmapInfo.bmiHeader.biPlanes = 1;
1670  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1671  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
1672  bmp = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
1673  ok (bmp && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
1674  if (!bmp || !bits)
1675  goto cleanup;
1676  bmpOld = SelectObject(hdc, bmp);
1677 
1678 #define ICON_RES_WIDTH 32
1679 #define ICON_RES_HEIGHT 32
1680 #define ICON_RES_AND_SIZE (ICON_WIDTH*ICON_HEIGHT/8)
1681 #define ICON_RES_BPP 32
1682 #define ICON_RES_SIZE \
1683  (sizeof(BITMAPINFOHEADER) + ICON_AND_SIZE + ICON_AND_SIZE*ICON_BPP)
1684 #define CRSR_RES_SIZE (2*sizeof(INT16) + ICON_RES_SIZE)
1685 
1686  /* Set icon data. */
1688 
1689  /* Cursor resources have an extra hotspot, icon resources not. */
1690  hotspot[0] = 3;
1691  hotspot[1] = 3;
1692 
1693  icon_header = (BITMAPINFOHEADER *) (hotspot + 2);
1694  icon_header->biSize = sizeof(BITMAPINFOHEADER);
1695  icon_header->biWidth = ICON_WIDTH;
1696  icon_header->biHeight = ICON_HEIGHT*2;
1697  icon_header->biPlanes = 1;
1698  icon_header->biBitCount = ICON_BPP;
1699  icon_header->biSizeImage = 0; /* Uncompressed bitmap. */
1700 
1701  /* Creating a static cursor. */
1702  SetLastError(0xdeadbeef);
1703  h1 = CreateIconFromResource((PBYTE) hotspot, CRSR_RES_SIZE, FALSE, 0x00030000);
1704  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1705 
1706  /* Check GetCursorFrameInfo behavior on a static cursor */
1707  rate = steps = 0xdead;
1708  h2 = pGetCursorFrameInfo(h1, 0xdead, 0xdead, &rate, &steps);
1709  ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1710  ok(rate == 0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1711  ok(steps == 1, "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1712 
1713  /* Clean up static cursor. */
1714  SetLastError(0xdeadbeef);
1715  ret = DestroyCursor(h1);
1716  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1717 
1718  /* Creating a single-frame animated cursor. */
1719  empty_anicursor.frames[0].data.icon_info.idType = 2; /* type: cursor */
1722  memcpy( &empty_anicursor.frames[0].data.bmi_data.data[0], &frame_identifier[0], sizeof(DWORD) );
1723  SetLastError(0xdeadbeef);
1724  h1 = CreateIconFromResource((PBYTE) &empty_anicursor, sizeof(empty_anicursor), FALSE, 0x00030000);
1725  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1726 
1727  /* Check GetCursorFrameInfo behavior on a single-frame animated cursor */
1728  rate = steps = 0xdead;
1729  h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1730  ok(h1 == h2, "GetCursorFrameInfo() failed: (%p != %p).\n", h1, h2);
1731  ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1732  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1733  ok(rate == 0x0, "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x0).\n", rate);
1735  "GetCursorFrameInfo() unexpected param 5 value (%d != 1).\n", steps);
1736 
1737  /* Clean up single-frame animated cursor. */
1738  SetLastError(0xdeadbeef);
1739  ret = DestroyCursor(h1);
1740  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1741 
1742  /* Creating a multi-frame animated cursor. */
1744  {
1745  empty_anicursor3.frames[i].data.icon_info.idType = 2; /* type: cursor */
1748  memcpy( &empty_anicursor3.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1749  }
1750  SetLastError(0xdeadbeef);
1751  h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1752  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1753 
1754  /* Check number of steps in multi-frame animated cursor */
1755  i=0;
1756  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1757  i++;
1759  "Unexpected number of steps in cursor (%d != %d)\n",
1761 
1762  /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor */
1764  {
1765  rate = steps = 0xdead;
1766  h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1767  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1768  ret = check_cursor_data( hdc, h2, &frame_identifier[i], sizeof(DWORD) );
1769  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1771  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1774  "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1776  }
1777 
1778  /* Check GetCursorFrameInfo behavior on rate 3 of a multi-frame animated cursor */
1779  rate = steps = 0xdead;
1780  h2 = pGetCursorFrameInfo(h1, 0xdead, 3, &rate, &steps);
1781  ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1782  ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1783  || broken(rate == ~0) /*win2k (sporadic)*/,
1784  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1785  ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1786  || broken(steps == 0) /*win2k (sporadic)*/,
1787  "GetCursorFrameInfo() unexpected param 5 value (0x%x != 0xdead).\n", steps);
1788 
1789  /* Clean up multi-frame animated cursor. */
1790  SetLastError(0xdeadbeef);
1791  ret = DestroyCursor(h1);
1792  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1793 
1794  /* Create a multi-frame animated cursor with num_steps == 1 */
1796  SetLastError(0xdeadbeef);
1797  h1 = CreateIconFromResource((PBYTE) &empty_anicursor3, sizeof(empty_anicursor3), FALSE, 0x00030000);
1798  ok(h1 != NULL, "Create cursor failed (error = %d).\n", GetLastError());
1799 
1800  /* Check number of steps in multi-frame animated cursor (mismatch between steps and frames) */
1801  i=0;
1802  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1803  i++;
1805  "Unexpected number of steps in cursor (%d != %d)\n",
1807 
1808  /* Check GetCursorFrameInfo behavior on rate 0 for a multi-frame animated cursor (with num_steps == 1) */
1809  rate = steps = 0xdead;
1810  h2 = pGetCursorFrameInfo(h1, 0xdead, 0, &rate, &steps);
1811  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1812  ret = check_cursor_data( hdc, h2, &frame_identifier[0], sizeof(DWORD) );
1813  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame 0.\n");
1815  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1817  ok(steps == ~0 || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/,
1818  "GetCursorFrameInfo() unexpected param 5 value (%d != ~0).\n", steps);
1819 
1820  /* Check GetCursorFrameInfo behavior on rate 1 for a multi-frame animated cursor (with num_steps == 1) */
1821  rate = steps = 0xdead;
1822  h2 = pGetCursorFrameInfo(h1, 0xdead, 1, &rate, &steps);
1823  ok(h2 == 0, "GetCursorFrameInfo() failed for cursor %p: (%p != 0).\n", h1, h2);
1824  ok(rate == 0xdead || broken(rate == empty_anicursor3.header.header.display_rate) /*win2k*/
1825  || broken(rate == ~0) /*win2k (sporadic)*/,
1826  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0xdead).\n", rate);
1827  ok(steps == 0xdead || broken(steps == empty_anicursor3.header.header.num_steps) /*win2k*/
1828  || broken(steps == 0) /*win2k (sporadic)*/,
1829  "GetCursorFrameInfo() unexpected param 5 value (%d != 0xdead).\n", steps);
1830 
1831  /* Clean up multi-frame animated cursor. */
1832  SetLastError(0xdeadbeef);
1833  ret = DestroyCursor(h1);
1834  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1835 
1836  /* Creating a multi-frame animated cursor with rate data. */
1838  {
1839  empty_anicursor3_seq.frames[i].data.icon_info.idType = 2; /* type: cursor */
1842  memcpy( &empty_anicursor3_seq.frames[i].data.bmi_data.data[0], &frame_identifier[i], sizeof(DWORD) );
1843  }
1844  SetLastError(0xdeadbeef);
1846  ok(h1 != NULL, "Create cursor failed (error = %x).\n", GetLastError());
1847 
1848  /* Check number of steps in multi-frame animated cursor with rate data */
1849  i=0;
1850  while (DrawIconEx(hdc, 0, 0, h1, 32, 32, i, NULL, DI_NORMAL))
1851  i++;
1853  "Unexpected number of steps in cursor (%d != %d)\n",
1855 
1856  /* Check GetCursorFrameInfo behavior on a multi-frame animated cursor with rate data */
1858  {
1859  int frame_id = empty_anicursor3_seq.seq.order[i];
1860 
1861  rate = steps = 0xdead;
1862  h2 = pGetCursorFrameInfo(h1, 0xdead, i, &rate, &steps);
1863  ok(h1 != h2 && h2 != 0, "GetCursorFrameInfo() failed for cursor %p: (%p, %p).\n", h1, h1, h2);
1864  ret = check_cursor_data( hdc, h2, &frame_identifier[frame_id], sizeof(DWORD) );
1865  ok(ret, "GetCursorFrameInfo() returned wrong cursor data for frame %d.\n", i);
1867  "GetCursorFrameInfo() unexpected param 4 value (0x%x != 0x%x).\n",
1870  "GetCursorFrameInfo() unexpected param 5 value (%d != %d).\n",
1872  }
1873 
1874  /* Clean up multi-frame animated cursor with rate data. */
1875  SetLastError(0xdeadbeef);
1876  ret = DestroyCursor(h1);
1877  ok(ret, "DestroyCursor() failed (error = %d).\n", GetLastError());
1878 
1879  HeapFree(GetProcessHeap(), 0, hotspot);
1880 cleanup:
1881  if(bmpOld) SelectObject(hdc, bmpOld);
1882  if(bmp) DeleteObject(bmp);
1883  if(hdc) DeleteDC(hdc);
1884 }
1885 
1886 static HICON create_test_icon(HDC hdc, int width, int height, int bpp,
1887  BOOL maskvalue, UINT32 *color, int colorSize)
1888 {
1889  ICONINFO iconInfo;
1890  BITMAPINFO bitmapInfo;
1891  void *buffer = NULL;
1892  UINT32 mask = maskvalue ? 0xFFFFFFFF : 0x00000000;
1893 
1894  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
1895  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1896  bitmapInfo.bmiHeader.biWidth = width;
1897  bitmapInfo.bmiHeader.biHeight = height;
1898  bitmapInfo.bmiHeader.biPlanes = 1;
1899  bitmapInfo.bmiHeader.biBitCount = bpp;
1900  bitmapInfo.bmiHeader.biCompression = BI_RGB;
1901  bitmapInfo.bmiHeader.biSizeImage = colorSize;
1902 
1903  iconInfo.fIcon = TRUE;
1904  iconInfo.xHotspot = 0;
1905  iconInfo.yHotspot = 0;
1906 
1907  iconInfo.hbmMask = CreateBitmap( width, height, 1, 1, &mask );
1908  if(!iconInfo.hbmMask) return NULL;
1909 
1910  iconInfo.hbmColor = CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &buffer, NULL, 0);
1911  if(!iconInfo.hbmColor || !buffer)
1912  {
1913  DeleteObject(iconInfo.hbmMask);
1914  return NULL;
1915  }
1916 
1917  memcpy(buffer, color, colorSize);
1918 
1919  return CreateIconIndirect(&iconInfo);
1920 }
1921 
1922 static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
1923 {
1924  HICON hicon;
1925  UINT32 color[2];
1926  COLORREF modern_expected, legacy_expected, result;
1927 
1928  color[0] = 0x00A0B0C0;
1929  color[1] = alpha ? 0xFF000000 : 0x00000000;
1930  modern_expected = alpha ? 0x00FFFFFF : 0x00C0B0A0;
1931  legacy_expected = 0x00C0B0A0;
1932 
1933  hicon = create_test_icon(hdc, 2, 1, bpp, 0, color, sizeof(color));
1934  if (!hicon) return;
1935 
1936  SetPixelV(hdc, 0, 0, 0x00FFFFFF);
1937 
1938  if(drawiconex)
1939  DrawIconEx(hdc, 0, 0, hicon, 2, 1, 0, NULL, DI_NORMAL);
1940  else
1941  DrawIcon(hdc, 0, 0, hicon);
1942 
1943  result = GetPixel(hdc, 0, 0);
1944  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1945  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1946  "%s. Expected a close match to %06X (modern) or %06X (legacy) with %s. "
1947  "Got %06X from line %d\n",
1948  alpha ? "Alpha blending" : "Not alpha blending", modern_expected, legacy_expected,
1949  drawiconex ? "DrawIconEx" : "DrawIcon", result, line);
1950 }
1951 
1952 static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
1953  COLORREF modern_expected, COLORREF legacy_expected, int line)
1954 {
1955  COLORREF result;
1956  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
1957  if (!hicon) return;
1958  SetPixelV(hdc, 0, 0, background);
1961  DrawIcon(hdc, 0, 0, hicon);
1962  result = GetPixel(hdc, 0, 0);
1963 
1964  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1965  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1966  "Overlaying Mask %d on Color %06X with DrawIcon. "
1967  "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1968  maskvalue, color, modern_expected, legacy_expected, result, line);
1969 
1971 
1972  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
1973  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
1974  "Overlaying Mask %d on Color %06X with DrawIcon. "
1975  "Expected a close match to %06X (modern), or %06X (legacy). Got %06X from line %d\n",
1976  maskvalue, color, modern_expected, legacy_expected, result, line);
1977 
1979 
1980  ok (color_match(result, background),
1981  "Overlaying Mask %d on Color %06X with DrawIcon. "
1982  "Expected unchanged background color %06X. Got %06X from line %d\n",
1983  maskvalue, color, background, result, line);
1984 }
1985 
1986 static void test_DrawIcon(void)
1987 {
1988  BITMAPINFO bitmapInfo;
1989  HDC hdcDst = NULL;
1990  HBITMAP bmpDst = NULL;
1991  HBITMAP bmpOld = NULL;
1992  void *bits = 0;
1993 
1995  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
1996  if (!hdcDst)
1997  return;
1998 
1999  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2000  {
2001  skip("Windows will distort DrawIcon colors at 8-bpp and less due to palettizing.\n");
2002  goto cleanup;
2003  }
2004 
2005  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2006  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2007  bitmapInfo.bmiHeader.biWidth = GetSystemMetrics(SM_CXICON)+1;
2008  bitmapInfo.bmiHeader.biHeight = GetSystemMetrics(SM_CYICON)+1;
2009  bitmapInfo.bmiHeader.biBitCount = 32;
2010  bitmapInfo.bmiHeader.biPlanes = 1;
2011  bitmapInfo.bmiHeader.biCompression = BI_RGB;
2012  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2013 
2014  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2015  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2016  if (!bmpDst || !bits)
2017  goto cleanup;
2018  bmpOld = SelectObject(hdcDst, bmpDst);
2019 
2020  /* Mask is only heeded if alpha channel is always zero */
2021  check_DrawIcon(hdcDst, FALSE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2022  check_DrawIcon(hdcDst, TRUE, 0x00A0B0C0, 32, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
2023 
2024  /* Test alpha blending */
2025  /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
2026  check_DrawIcon(hdcDst, FALSE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2027  check_DrawIcon(hdcDst, TRUE, 0xFFA0B0C0, 32, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
2028 
2029  check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2030  check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2031  check_DrawIcon(hdcDst, FALSE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
2032  check_DrawIcon(hdcDst, TRUE, 0x80A0B0C0, 32, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
2033 
2034  check_DrawIcon(hdcDst, FALSE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2035  check_DrawIcon(hdcDst, TRUE, 0x01FFFFFF, 32, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2036 
2037  /* Test detecting of alpha channel */
2038  /* If a single pixel's alpha channel is non-zero, the icon
2039  will be alpha blended, otherwise it will be draw with
2040  and + xor blts. */
2041  check_alpha_draw(hdcDst, FALSE, FALSE, 32, __LINE__);
2042  check_alpha_draw(hdcDst, FALSE, TRUE, 32, __LINE__);
2043 
2044 cleanup:
2045  if(bmpOld)
2046  SelectObject(hdcDst, bmpOld);
2047  if(bmpDst)
2048  DeleteObject(bmpDst);
2049  if(hdcDst)
2050  DeleteDC(hdcDst);
2051 }
2052 
2053 static void check_DrawIconEx(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, UINT flags, COLORREF background,
2054  COLORREF modern_expected, COLORREF legacy_expected, int line)
2055 {
2056  COLORREF result;
2057  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2058  if (!hicon) return;
2059  SetPixelV(hdc, 0, 0, background);
2060  DrawIconEx(hdc, 0, 0, hicon, 1, 1, 0, NULL, flags);
2061  result = GetPixel(hdc, 0, 0);
2062 
2063  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
2064  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
2065  "Overlaying Mask %d on Color %06X with DrawIconEx flags %08X. "
2066  "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
2067  maskvalue, color, flags, modern_expected, legacy_expected, result, line);
2068 }
2069 
2070 static void test_DrawIconEx(void)
2071 {
2072  BITMAPINFO bitmapInfo;
2073  HDC hdcDst = NULL;
2074  HBITMAP bmpDst = NULL;
2075  HBITMAP bmpOld = NULL;
2076  void *bits = 0;
2077 
2079  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
2080  if (!hdcDst)
2081  return;
2082 
2083  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2084  {
2085  skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
2086  goto cleanup;
2087  }
2088 
2089  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2090  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2091  bitmapInfo.bmiHeader.biWidth = 1;
2092  bitmapInfo.bmiHeader.biHeight = 1;
2093  bitmapInfo.bmiHeader.biBitCount = 32;
2094  bitmapInfo.bmiHeader.biPlanes = 1;
2095  bitmapInfo.bmiHeader.biCompression = BI_RGB;
2096  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2097  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2098  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2099  if (!bmpDst || !bits)
2100  goto cleanup;
2101  bmpOld = SelectObject(hdcDst, bmpDst);
2102 
2103  /* Test null, image only, and mask only drawing */
2104  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
2105  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, 0, 0x00102030, 0x00102030, 0x00102030, __LINE__);
2106 
2107  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00000000, 0x00000000, __LINE__);
2108  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_MASK, 0x00123456, 0x00FFFFFF, 0x00FFFFFF, __LINE__);
2109 
2110  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2111  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_IMAGE, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2112 
2113  /* Test normal drawing */
2114  check_DrawIconEx(hdcDst, FALSE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2115  check_DrawIconEx(hdcDst, TRUE, 0x00A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x003F4F5F, 0x003F4F5F, __LINE__);
2116  check_DrawIconEx(hdcDst, FALSE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2117 
2118  /* Test alpha blending */
2119  /* Windows 2000 and up will alpha blend, earlier Windows versions will not */
2120  check_DrawIconEx(hdcDst, TRUE, 0xFFA0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x003F4F5F, __LINE__);
2121 
2122  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2123  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00000000, 0x00605850, 0x00C0B0A0, __LINE__);
2124  check_DrawIconEx(hdcDst, FALSE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x00C0B0A0, __LINE__);
2125  check_DrawIconEx(hdcDst, TRUE, 0x80A0B0C0, 32, DI_NORMAL, 0x00FFFFFF, 0x00DFD7CF, 0x003F4F5F, __LINE__);
2126 
2127  check_DrawIconEx(hdcDst, FALSE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2128  check_DrawIconEx(hdcDst, TRUE, 0x01FFFFFF, 32, DI_NORMAL, 0x00000000, 0x00010101, 0x00FFFFFF, __LINE__);
2129 
2130  /* Test detecting of alpha channel */
2131  /* If a single pixel's alpha channel is non-zero, the icon
2132  will be alpha blended, otherwise it will be draw with
2133  and + xor blts. */
2134  check_alpha_draw(hdcDst, TRUE, FALSE, 32, __LINE__);
2135  check_alpha_draw(hdcDst, TRUE, TRUE, 32, __LINE__);
2136 
2137 cleanup:
2138  if(bmpOld)
2139  SelectObject(hdcDst, bmpOld);
2140  if(bmpDst)
2141  DeleteObject(bmpDst);
2142  if(hdcDst)
2143  DeleteDC(hdcDst);
2144 }
2145 
2146 static void check_DrawState_Size(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags, int line)
2147 {
2148  COLORREF result, background;
2149  BOOL passed[2];
2150  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2151  background = 0x00FFFFFF;
2152  /* Set color of the 2 pixels that will be checked afterwards */
2153  SetPixelV(hdc, 0, 0, background);
2154  SetPixelV(hdc, 2, 2, background);
2155 
2156  /* Let DrawState calculate the size of the icon (it's 1x1) */
2157  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, (DST_ICON | flags ));
2158 
2159  result = GetPixel(hdc, 0, 0);
2160  passed[0] = color_match(result, background);
2161  result = GetPixel(hdc, 2, 2);
2162  passed[0] = passed[0] & color_match(result, background);
2163 
2164  /* Check if manually specifying the icon size DOESN'T work */
2165 
2166  /* IMPORTANT: For Icons, DrawState wants the size of the source image, not the
2167  * size in which it should be ultimately drawn. Therefore giving
2168  * width/height 2x2 if the icon is only 1x1 pixels in size should
2169  * result in drawing it with size 1x1. The size parameters must be
2170  * ignored if a Icon has to be drawn! */
2171  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 2, 2, (DST_ICON | flags ));
2172 
2173  result = GetPixel(hdc, 0, 0);
2174  passed[1] = color_match(result, background);
2175  result = GetPixel(hdc, 2, 2);
2176  passed[1] = passed[0] & color_match(result, background);
2177 
2178  if(!passed[0]&&!passed[1])
2179  ok (passed[1],
2180  "DrawState failed to draw a 1x1 Icon in the correct size, independent of the "
2181  "width and height settings passed to it, for Icon with: Overlaying Mask %d on "
2182  "Color %06X with flags %08X. Line %d\n",
2183  maskvalue, color, (DST_ICON | flags), line);
2184  else if(!passed[1])
2185  ok (passed[1],
2186  "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2187  "parameters passed to it are bigger than the real Icon size, for Icon with: Overlaying "
2188  "Mask %d on Color %06X with flags %08X. Line %d\n",
2189  maskvalue, color, (DST_ICON | flags), line);
2190  else
2191  ok (passed[0],
2192  "DrawState failed to draw a 1x1 Icon in the correct size, if the width and height "
2193  "parameters passed to it are 0, for Icon with: Overlaying Mask %d on "
2194  "Color %06X with flags %08X. Line %d\n",
2195  maskvalue, color, (DST_ICON | flags), line);
2196 }
2197 
2198 static void check_DrawState_Color(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, HBRUSH hbr, UINT flags,
2199  COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
2200 {
2201  COLORREF result;
2202  HICON hicon = create_test_icon(hdc, 1, 1, bpp, maskvalue, &color, sizeof(color));
2203  if (!hicon) return;
2204  /* Set color of the pixel that will be checked afterwards */
2205  SetPixelV(hdc, 1, 1, background);
2206 
2207  DrawStateA(hdc, hbr, NULL, (LPARAM) hicon, 0, 1, 1, 0, 0, ( DST_ICON | flags ));
2208 
2209  /* Check the color of the pixel is correct */
2210  result = GetPixel(hdc, 1, 1);
2211 
2212  ok (color_match(result, modern_expected) || /* Windows 2000 and up */
2213  broken(color_match(result, legacy_expected)), /* Windows NT 4.0, 9X and below */
2214  "DrawState drawing Icon with Overlaying Mask %d on Color %06X with flags %08X. "
2215  "Expected a close match to %06X (modern) or %06X (legacy). Got %06X from line %d\n",
2216  maskvalue, color, (DST_ICON | flags), modern_expected, legacy_expected, result, line);
2217 }
2218 
2219 static void test_DrawState(void)
2220 {
2221  BITMAPINFO bitmapInfo;
2222  HDC hdcDst = NULL;
2223  HBITMAP bmpDst = NULL;
2224  HBITMAP bmpOld = NULL;
2225  void *bits = 0;
2226 
2228  ok(hdcDst != 0, "CreateCompatibleDC(0) failed to return a valid DC\n");
2229  if (!hdcDst)
2230  return;
2231 
2232  if(GetDeviceCaps(hdcDst, BITSPIXEL) <= 8)
2233  {
2234  skip("Windows will distort DrawIconEx colors at 8-bpp and less due to palettizing.\n");
2235  goto cleanup;
2236  }
2237 
2238  memset(&bitmapInfo, 0, sizeof(bitmapInfo));
2239  bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2240  bitmapInfo.bmiHeader.biWidth = 3;
2241  bitmapInfo.bmiHeader.biHeight = 3;
2242  bitmapInfo.bmiHeader.biBitCount = 32;
2243  bitmapInfo.bmiHeader.biPlanes = 1;
2244  bitmapInfo.bmiHeader.biCompression = BI_RGB;
2245  bitmapInfo.bmiHeader.biSizeImage = sizeof(UINT32);
2246  bmpDst = CreateDIBSection(hdcDst, &bitmapInfo, DIB_RGB_COLORS, &bits, NULL, 0);
2247  ok (bmpDst && bits, "CreateDIBSection failed to return a valid bitmap and buffer\n");
2248  if (!bmpDst || !bits)
2249  goto cleanup;
2250  bmpOld = SelectObject(hdcDst, bmpDst);
2251 
2252  /* potential flags to test with DrawState are: */
2253  /* DSS_DISABLED embosses the icon */
2254  /* DSS_MONO draw Icon using a brush as parameter 5 */
2255  /* DSS_NORMAL draw Icon without any modifications */
2256  /* DSS_UNION draw the Icon dithered */
2257 
2258  check_DrawState_Size(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, __LINE__);
2259  check_DrawState_Color(hdcDst, FALSE, 0x00A0B0C0, 32, 0, DSS_NORMAL, 0x00FFFFFF, 0x00C0B0A0, 0x00C0B0A0, __LINE__);
2260 
2261 cleanup:
2262  if(bmpOld)
2263  SelectObject(hdcDst, bmpOld);
2264  if(bmpDst)
2265  DeleteObject(bmpDst);
2266  if(hdcDst)
2267  DeleteDC(hdcDst);
2268 }
2269 
2271 
2273 {
2274  HCURSOR ret;
2275 
2276  PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE ); /* create a msg queue */
2277  if (parent_id)
2278  {
2280  ok( ret, "AttachThreadInput failed\n" );
2281  }
2282  if (arg) ret = SetCursor( (HCURSOR)arg );
2283  else ret = GetCursor();
2284  return (DWORD_PTR)ret;
2285 }
2286 
2287 static void test_SetCursor(void)
2288 {
2289  static const BYTE bmp_bits[4096];
2290  ICONINFO cursorInfo;
2291  HCURSOR cursor, old_cursor, global_cursor = 0;
2292  DWORD error, id, result;
2293  UINT display_bpp;
2294  HDC hdc;
2295  HANDLE thread;
2296  CURSORINFO info;
2297 
2298  if (pGetCursorInfo)
2299  {
2300  memset( &info, 0, sizeof(info) );
2301  info.cbSize = sizeof(info);
2302  if (!pGetCursorInfo( &info ))
2303  {
2304  win_skip( "GetCursorInfo not working\n" );
2305  pGetCursorInfo = NULL;
2306  }
2307  else global_cursor = info.hCursor;
2308  }
2309  cursor = GetCursor();
2310  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2311  WaitForSingleObject( thread, 1000 );
2313  ok( result == (DWORD_PTR)cursor, "wrong thread cursor %x/%p\n", result, cursor );
2314 
2315  hdc = GetDC(0);
2316  display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2317  ReleaseDC(0, hdc);
2318 
2319  cursorInfo.fIcon = FALSE;
2320  cursorInfo.xHotspot = 0;
2321  cursorInfo.yHotspot = 0;
2322  cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2323  cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2324 
2325  cursor = CreateIconIndirect(&cursorInfo);
2326  ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2327  old_cursor = SetCursor( cursor );
2328 
2329  if (pGetCursorInfo)
2330  {
2331  info.cbSize = sizeof(info);
2332  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2333  /* global cursor doesn't change since we don't have a window */
2334  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2335  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2336  }
2337  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2338  WaitForSingleObject( thread, 1000 );
2340  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2341 
2342  SetCursor( 0 );
2343  ok( GetCursor() == 0, "wrong cursor %p\n", GetCursor() );
2344  thread = CreateThread( NULL, 0, set_cursor_thread, 0, 0, &id );
2345  WaitForSingleObject( thread, 1000 );
2347  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2348 
2349  thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2350  WaitForSingleObject( thread, 1000 );
2352  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2353  ok( GetCursor() == 0, "wrong cursor %p/0\n", GetCursor() );
2354 
2356  thread = CreateThread( NULL, 0, set_cursor_thread, cursor, 0, &id );
2357  WaitForSingleObject( thread, 1000 );
2359  ok( result == (DWORD_PTR)old_cursor, "wrong thread cursor %x/%p\n", result, old_cursor );
2360  ok( GetCursor() == cursor, "wrong cursor %p/0\n", cursor );
2361 
2362  if (pGetCursorInfo)
2363  {
2364  info.cbSize = sizeof(info);
2365  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2366  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2367  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2368  }
2369  SetCursor( old_cursor );
2370  DestroyCursor( cursor );
2371 
2372  SetLastError( 0xdeadbeef );
2373  cursor = SetCursor( (HCURSOR)0xbadbad );
2374  error = GetLastError();
2375  ok( cursor == 0, "wrong cursor %p/0\n", cursor );
2376  ok( error == ERROR_INVALID_CURSOR_HANDLE || broken( error == 0xdeadbeef ), /* win9x */
2377  "wrong error %u\n", error );
2378 
2379  if (pGetCursorInfo)
2380  {
2381  info.cbSize = sizeof(info);
2382  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2383  ok( info.hCursor == global_cursor || broken(info.hCursor != cursor), /* win9x */
2384  "wrong info cursor %p/%p\n", info.hCursor, global_cursor );
2385  }
2386 }
2387 
2389 
2391 {
2392  DWORD count = (DWORD_PTR)arg;
2393  int ret;
2394 
2395  PeekMessageA( 0, 0, 0, 0, PM_NOREMOVE ); /* create a msg queue */
2396  if (parent_id)
2397  {
2399  ok( ret, "AttachThreadInput failed\n" );
2400  }
2401  if (!count) ret = ShowCursor( FALSE );
2402  else while (count--) ret = ShowCursor( TRUE );
2403  SetEvent( event_start );
2405  return ret;
2406 }
2407 
2408 static void test_ShowCursor(void)
2409 {
2410  int count;
2411  DWORD id, result;
2412  HANDLE thread;
2413  CURSORINFO info;
2414 
2415  if (pGetCursorInfo)
2416  {
2417  memset( &info, 0, sizeof(info) );
2418  info.cbSize = sizeof(info);
2419  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2420  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2421  }
2422 
2425 
2426  count = ShowCursor( TRUE );
2427  ok( count == 1, "wrong count %d\n", count );
2428  count = ShowCursor( TRUE );
2429  ok( count == 2, "wrong count %d\n", count );
2430  count = ShowCursor( FALSE );
2431  ok( count == 1, "wrong count %d\n", count );
2432  count = ShowCursor( FALSE );
2433  ok( count == 0, "wrong count %d\n", count );
2434  count = ShowCursor( FALSE );
2435  ok( count == -1, "wrong count %d\n", count );
2436  count = ShowCursor( FALSE );
2437  ok( count == -2, "wrong count %d\n", count );
2438 
2439  if (pGetCursorInfo)
2440  {
2441  info.cbSize = sizeof(info);
2442  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2443  /* global show count is not affected since we don't have a window */
2444  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2445  }
2446 
2447  parent_id = 0;
2448  thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2450  count = ShowCursor( FALSE );
2451  ok( count == -3, "wrong count %d\n", count );
2452  SetEvent( event_next );
2453  WaitForSingleObject( thread, 1000 );
2455  ok( result == -1, "wrong thread count %d\n", result );
2456  count = ShowCursor( FALSE );
2457  ok( count == -4, "wrong count %d\n", count );
2458 
2459  thread = CreateThread( NULL, 0, show_cursor_thread, (void *)1, 0, &id );
2461  count = ShowCursor( TRUE );
2462  ok( count == -3, "wrong count %d\n", count );
2463  SetEvent( event_next );
2464  WaitForSingleObject( thread, 1000 );
2466  ok( result == 1, "wrong thread count %d\n", result );
2467  count = ShowCursor( TRUE );
2468  ok( count == -2, "wrong count %d\n", count );
2469 
2471  thread = CreateThread( NULL, 0, show_cursor_thread, NULL, 0, &id );
2473  count = ShowCursor( TRUE );
2474  ok( count == -2, "wrong count %d\n", count );
2475  SetEvent( event_next );
2476  WaitForSingleObject( thread, 1000 );
2478  ok( result == -3, "wrong thread count %d\n", result );
2479  count = ShowCursor( FALSE );
2480  ok( count == -2, "wrong count %d\n", count );
2481 
2482  thread = CreateThread( NULL, 0, show_cursor_thread, (void *)3, 0, &id );
2484  count = ShowCursor( TRUE );
2485  ok( count == 2, "wrong count %d\n", count );
2486  SetEvent( event_next );
2487  WaitForSingleObject( thread, 1000 );
2489  ok( result == 1, "wrong thread count %d\n", result );
2490  count = ShowCursor( FALSE );
2491  ok( count == -2, "wrong count %d\n", count );
2492 
2493  if (pGetCursorInfo)
2494  {
2495  info.cbSize = sizeof(info);
2496  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2497  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2498  }
2499 
2500  count = ShowCursor( TRUE );
2501  ok( count == -1, "wrong count %d\n", count );
2502  count = ShowCursor( TRUE );
2503  ok( count == 0, "wrong count %d\n", count );
2504 
2505  if (pGetCursorInfo)
2506  {
2507  info.cbSize = sizeof(info);
2508  ok( pGetCursorInfo( &info ), "GetCursorInfo failed\n" );
2509  ok( info.flags & CURSOR_SHOWING, "cursor not shown in info\n" );
2510  }
2511 }
2512 
2513 
2514 static void test_DestroyCursor(void)
2515 {
2516  static const BYTE bmp_bits[4096];
2517  ICONINFO cursorInfo, new_info;
2518  HCURSOR cursor, cursor2, new_cursor;
2519  BOOL ret;
2520  DWORD error;
2521  UINT display_bpp;
2522  HDC hdc;
2523 
2524  hdc = GetDC(0);
2525  display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
2526  ReleaseDC(0, hdc);
2527 
2528  cursorInfo.fIcon = FALSE;
2529  cursorInfo.xHotspot = 0;
2530  cursorInfo.yHotspot = 0;
2531  cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
2532  cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
2533 
2534  cursor = CreateIconIndirect(&cursorInfo);
2535  ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
2536  if(!cursor) {
2537  return;
2538  }
2539  SetCursor(cursor);
2540 
2541  SetLastError(0xdeadbeef);
2543  ok(!ret || broken(ret) /* succeeds on win9x */, "DestroyCursor on the active cursor succeeded\n");
2544  error = GetLastError();
2545  ok(error == 0xdeadbeef, "Last error: %u\n", error);
2546 
2547  new_cursor = GetCursor();
2548  if (ret) /* win9x replaces cursor by another one on destroy */
2549  ok(new_cursor != cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2550  else
2551  ok(new_cursor == cursor, "GetCursor returned %p/%p\n", new_cursor, cursor);
2552 
2553  SetLastError(0xdeadbeef);
2554  ret = GetIconInfo( cursor, &new_info );
2555  ok( !ret || broken(ret), /* nt4 */ "GetIconInfo succeeded\n" );
2557  broken(GetLastError() == 0xdeadbeef), /* win9x */
2558  "wrong error %u\n", GetLastError() );
2559 
2560  if (ret) /* nt4 delays destruction until cursor changes */
2561  {
2562  DeleteObject( new_info.hbmColor );
2563  DeleteObject( new_info.hbmMask );
2564 
2565  SetLastError(0xdeadbeef);
2566  ret = DestroyCursor( cursor );
2567  ok( !ret, "DestroyCursor succeeded\n" );
2568  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2569  "wrong error %u\n", GetLastError() );
2570 
2571  SetLastError(0xdeadbeef);
2572  cursor2 = SetCursor( cursor );
2573  ok( cursor2 == cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2574  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2575  "wrong error %u\n", GetLastError() );
2576  }
2577  else
2578  {
2579  SetLastError(0xdeadbeef);
2580  cursor2 = CopyCursor( cursor );
2581  ok(!cursor2, "CopyCursor succeeded\n" );
2583  broken(GetLastError() == 0xdeadbeef), /* win9x */
2584  "wrong error %u\n", GetLastError() );
2585 
2586  SetLastError(0xdeadbeef);
2587  ret = DestroyCursor( cursor );
2588  if (new_cursor != cursor) /* win9x */
2589  ok( ret, "DestroyCursor succeeded\n" );
2590  else
2591  ok( !ret, "DestroyCursor succeeded\n" );
2592  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2593  "wrong error %u\n", GetLastError() );
2594 
2595  SetLastError(0xdeadbeef);
2596  cursor2 = SetCursor( cursor );
2597  ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2598  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2599  "wrong error %u\n", GetLastError() );
2600  }
2601 
2602  cursor2 = GetCursor();
2603  ok(cursor2 == new_cursor, "GetCursor returned %p/%p\n", cursor2, new_cursor);
2604 
2605  SetLastError(0xdeadbeef);
2606  cursor2 = SetCursor( 0 );
2607  if (new_cursor != cursor) /* win9x */
2608  ok(cursor2 == new_cursor, "SetCursor returned %p/%p\n", cursor2, cursor);
2609  else
2610  ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
2611  ok( GetLastError() == 0xdeadbeef, "wrong error %u\n", GetLastError() );
2612 
2613  cursor2 = GetCursor();
2614  ok(!cursor2, "GetCursor returned %p/%p\n", cursor2, cursor);
2615 
2616  SetLastError(0xdeadbeef);
2618  if (new_cursor != cursor) /* win9x */
2619  ok( ret, "DestroyCursor succeeded\n" );
2620  else
2621  ok( !ret, "DestroyCursor succeeded\n" );
2622  ok( GetLastError() == ERROR_INVALID_CURSOR_HANDLE || GetLastError() == 0xdeadbeef,
2623  "wrong error %u\n", GetLastError() );
2624 
2625  DeleteObject(cursorInfo.hbmMask);
2626  DeleteObject(cursorInfo.hbmColor);
2627 
2628  /* Try testing DestroyCursor() now using LoadCursor() cursors. */
2630 
2631  SetLastError(0xdeadbeef);
2633  ok(ret || broken(!ret) /* fails on win9x */, "DestroyCursor on the active cursor failed.\n");
2634  error = GetLastError();
2635  ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2636 
2637  /* Try setting the cursor to a destroyed OEM cursor. */
2638  SetLastError(0xdeadbeef);
2639  SetCursor(cursor);
2640  error = GetLastError();
2641  ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
2642 
2643  /* Check if LoadCursor() returns the same handle with the same icon. */
2644  cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_ARROW);
2645  ok(cursor2 == cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2646 
2647  /* Check if LoadCursor() returns the same handle with a different icon. */
2648  cursor2 = LoadCursorA(NULL, (LPCSTR)IDC_WAIT);
2649  ok(cursor2 != cursor, "cursor == %p, cursor2 == %p\n", cursor, cursor2);
2650 }
2651 
2652 static void test_PrivateExtractIcons(void)
2653 {
2654  HICON icon;
2655  UINT ret;
2656 
2657  static const test_icon_entries_t icon_desc[] = {{0,0,TRUE}, {16,16,TRUE}, {32,32}, {64,64,TRUE}};
2658 
2659  create_ico_file("extract.ico", icon_desc, ARRAY_SIZE(icon_desc));
2660 
2661  ret = PrivateExtractIconsA("extract.ico", 0, 32, 32, &icon, NULL, 1, 0);
2662  ok(ret == 1, "PrivateExtractIconsA returned %u\n", ret);
2663  ok(icon != NULL, "icon == NULL\n");
2664 
2665  test_icon_info(icon, 32, 32, 32, 32);
2666  DestroyIcon(icon);
2667 
2668  DeleteFileA("extract.ico");
2669 }
2670 
2671 static void test_monochrome_icon(void)
2672 {
2673  HANDLE handle;
2674  BOOL ret;
2675  DWORD bytes_written;
2676  CURSORICONFILEDIR *icon_data;
2677  CURSORICONFILEDIRENTRY *icon_entry;
2678  BITMAPINFO *bitmap_info;
2679  BITMAPCOREINFO *core_info;
2680  ICONINFO icon_info;
2681  ULONG icon_size;
2682  BOOL monochrome, use_core_info;
2683 
2684  icon_data = HeapAlloc(GetProcessHeap(), 0, sizeof(CURSORICONFILEDIR) + sizeof(BITMAPINFOHEADER) +
2685  2 * sizeof(RGBQUAD) + sizeof(ULONG));
2686 
2687  for (monochrome = FALSE; monochrome <= TRUE; monochrome++)
2688  for (use_core_info = FALSE; use_core_info <= TRUE; use_core_info++)
2689  {
2690  trace("%s, %s\n",
2691  monochrome ? "monochrome" : "colored",
2692  use_core_info ? "core info" : "bitmap info");
2693 
2694  icon_size = sizeof(CURSORICONFILEDIR) +
2695  (use_core_info ? sizeof(BITMAPCOREHEADER) : sizeof(BITMAPINFOHEADER)) +
2696  /* 2 * sizeof(RGBTRIPLE) + padding comes out the same */
2697  2 * sizeof(RGBQUAD) +
2698  sizeof(ULONG);
2699  ZeroMemory(icon_data, icon_size);
2700  icon_data->idReserved = 0;
2701  icon_data->idType = 1;
2702  icon_data->idCount = 1;
2703 
2704  icon_entry = icon_data->idEntries;
2705  icon_entry->bWidth = 1;
2706  icon_entry->bHeight = 1;
2707  icon_entry->bColorCount = 0;
2708  icon_entry->bReserved = 0;
2709  icon_entry->xHotspot = 0;
2710  icon_entry->yHotspot = 0;
2711  icon_entry->dwDIBSize = icon_size - sizeof(CURSORICONFILEDIR);
2712  icon_entry->dwDIBOffset = sizeof(CURSORICONFILEDIR);
2713 
2714  if (use_core_info)
2715  {
2716  core_info = (BITMAPCOREINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2717  core_info->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
2718  core_info->bmciHeader.bcWidth = 1;
2719  core_info->bmciHeader.bcHeight = 2;
2720  core_info->bmciHeader.bcPlanes = 1;
2721  core_info->bmciHeader.bcBitCount = 1;
2722  core_info->bmciColors[0].rgbtBlue = monochrome ? 0x00 : 0xff;
2723  core_info->bmciColors[0].rgbtGreen = 0x00;
2724  core_info->bmciColors[0].rgbtRed = 0x00;
2725  core_info->bmciColors[1].rgbtBlue = 0xff;
2726  core_info->bmciColors[1].rgbtGreen = 0xff;
2727  core_info->bmciColors[1].rgbtRed = 0xff;
2728  }
2729  else
2730  {
2731  bitmap_info = (BITMAPINFO *) ((BYTE *) icon_data + icon_entry->dwDIBOffset);
2732  bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2733  bitmap_info->bmiHeader.biWidth = 1;
2734  bitmap_info->bmiHeader.biHeight = 2;
2735  bitmap_info->bmiHeader.biPlanes = 1;
2736  bitmap_info->bmiHeader.biBitCount = 1;
2737  bitmap_info->bmiHeader.biSizeImage = 0; /* Uncompressed bitmap. */
2738  bitmap_info->bmiColors[0].rgbBlue = monochrome ? 0x00 : 0xff;
2739  bitmap_info->bmiColors[0].rgbGreen = 0x00;
2740  bitmap_info->bmiColors[0].rgbRed = 0x00;
2741  bitmap_info->bmiColors[1].rgbBlue = 0xff;
2742  bitmap_info->bmiColors[1].rgbGreen = 0xff;
2743  bitmap_info->bmiColors[1].rgbRed = 0xff;
2744  }
2745 
2746  handle = CreateFileA("icon.ico", GENERIC_WRITE, 0, NULL, CREATE_NEW,
2748  ok(handle != INVALID_HANDLE_VALUE, "CreateFileA failed. %u\n", GetLastError());
2749  ret = WriteFile(handle, icon_data, icon_size, &bytes_written, NULL);
2750  ok(ret && bytes_written == icon_size, "icon.ico created improperly.\n");
2752 
2753  handle = LoadImageA(NULL, "icon.ico", IMAGE_ICON, 0, 0, LR_LOADFROMFILE);
2754  ok(handle != NULL ||
2755  broken(use_core_info && handle == NULL), /* Win 8, 10 */
2756  "LoadImage() failed with %u.\n", GetLastError());
2757  if (handle == NULL)
2758  {
2759  skip("Icon failed to load: %s, %s\n",
2760  monochrome ? "monochrome" : "colored",
2761  use_core_info ? "core info" : "bitmap info");
2762  DeleteFileA("icon.ico");
2763  continue;
2764  }
2765 
2766  ret = GetIconInfo(handle, &icon_info);
2767  ok(ret, "GetIconInfo() failed with %u.\n", GetLastError());
2768  if (ret)
2769  {
2770  ok(icon_info.fIcon == TRUE, "fIcon is %u.\n", icon_info.fIcon);
2771  ok(icon_info.xHotspot == 0, "xHotspot is %u.\n", icon_info.xHotspot);
2772  ok(icon_info.yHotspot == 0, "yHotspot is %u.\n", icon_info.yHotspot);
2773  if (monochrome)
2774  ok(icon_info.hbmColor == NULL, "Got hbmColor %p!\n", icon_info.hbmColor);
2775  else
2776  ok(icon_info.hbmColor != NULL, "No hbmColor!\n");
2777  ok(icon_info.hbmMask != NULL, "No hbmMask!\n");
2778  }
2779 
2780  ret = DestroyIcon(handle);
2781  ok(ret, "DestroyIcon() failed with %u.\n", GetLastError());
2782  DeleteFileA("icon.ico");
2783  }
2784 
2785  HeapFree(GetProcessHeap(), 0, icon_data);
2786 }
2787 
2788 static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO *bmi,
2789  unsigned int row, unsigned int column)
2790 {
2791  const BITMAPINFOHEADER *h = &bmi->bmiHeader;
2792  unsigned int stride, shift, mask;
2793  const unsigned char *data;
2794  RGBQUAD color;
2795  WORD color16;
2796 
2797  stride = ((h->biBitCount * h->biWidth + 7) / 8 + 3) & ~3;
2798  data = bits + row * stride + column * h->biBitCount / 8;
2799  if (h->biBitCount >= 24)
2800  return RGB(data[2], data[1], data[0]);
2801 
2802  if (h->biBitCount == 16)
2803  {
2804  color16 = ((WORD)data[1] << 8) | data[0];
2805  return RGB(((color16 >> 10) & 0x1f) << 3, ((color16 >> 5) & 0x1f) << 3,
2806  (color16 & 0x1f) << 3);
2807  }
2808  shift = 8 - h->biBitCount - (column * h->biBitCount) % 8;
2809  mask = ~(~0u << h->biBitCount);
2810  color = bmi->bmiColors[(data[0] >> shift) & mask];
2811  return RGB(color.rgbRed, color.rgbGreen, color.rgbBlue);
2812 }
2813 
2814 #define compare_bitmap_bits(a, b, c, d, e, f, g) compare_bitmap_bits_(__LINE__, a, b, c, d, e, f, g)
2815 static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BITMAPINFO *bmi,
2816  size_t result_bits_size, const unsigned char *expected_bits, unsigned int test_index, BOOL todo)
2817 {
2818  unsigned char *result_bits;
2819  unsigned int row, column;
2820  int ret;
2821 
2822  result_bits = HeapAlloc(GetProcessHeap(), 0, result_bits_size);
2823  ret = GetDIBits(hdc, bitmap, 0, bmi->bmiHeader.biHeight,
2824  result_bits, bmi, DIB_RGB_COLORS);
2825  ok(ret == bmi->bmiHeader.biHeight, "Unexpected GetDIBits result %d, GetLastError() %u.\n",
2826  ret, GetLastError());
2827  for (row = 0; row < bmi->bmiHeader.biHeight; ++row)
2828  for (column = 0; column < bmi->bmiHeader.biWidth; ++column)
2829  {
2831 
2832  result = get_color_from_bits(result_bits, bmi, row, column);
2833  expected = get_color_from_bits(expected_bits, bmi, row, column);
2834 
2836  ok_(__FILE__, line)(result == expected, "Colors do not match, "
2837  "got 0x%06x, expected 0x%06x, test_index %u, row %u, column %u.\n",
2838  result, expected, test_index, row, column);
2839  }
2840  HeapFree(GetProcessHeap(), 0, result_bits);
2841 }
2842 
2843 static void test_Image_StretchMode(void)
2844 {
2845  static const unsigned char test_bits_24[] =
2846  {
2847  0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
2848  0x00, 0xff, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff, 0x00, 0x00, 0xff, 0x00,
2849  0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00,
2850  0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00,
2851  };
2852  static const unsigned char expected_bits_24[] =
2853  {
2854  0x3f, 0xff, 0x00, 0x3f, 0xff, 0x3f, 0x00, 0x00,
2855  0x3f, 0xff, 0x7f, 0x00, 0xff, 0x3f, 0x00, 0x00,
2856  };
2857 #define rgb16(r, g, b) ((WORD)(((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3)))
2858  static const WORD test_bits_16[] =
2859  {
2860  rgb16(0x00, 0x20, 0x00), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
2861  rgb16(0x00, 0x60, 0x00), rgb16(0xff, 0x80, 0x00), rgb16(0xff, 0x60, 0x00), rgb16(0x00, 0x80, 0x00),
2862  rgb16(0x00, 0x20, 0xff), rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x40, 0xff), rgb16(0x00, 0x20, 0x00),
2863  rgb16(0xff, 0x80, 0x00), rgb16(0x00, 0x60, 0xff), rgb16(0x00, 0x80, 0x00), rgb16(0x00, 0x60, 0x00),
2864  };
2865  static const WORD expected_bits_16[] =
2866  {
2867  rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
2868  rgb16(0x00, 0x40, 0x00), rgb16(0x00, 0x20, 0x00),
2869  };
2870 #undef rgb16
2871  static const unsigned char test_bits_8[] =
2872  {
2873  0x00, 0xff, 0x00, 0xff,
2874  0x00, 0x00, 0x00, 0x00,
2875  0xff, 0x55, 0x00, 0xff,
2876  0x00, 0xff, 0xff, 0x00,
2877  };
2878  static const unsigned char expected_bits_8[] =
2879  {
2880  0xff, 0xff, 0x00, 0x00,
2881  0x55, 0xff, 0x00, 0x00,
2882  };
2883  static const unsigned char test_bits_1[] =
2884  {
2885  0x30, 0x0, 0x0, 0x0,
2886  0x30, 0x0, 0x0, 0x0,
2887  0x40, 0x0, 0x0, 0x0,
2888  0xc0, 0x0, 0x0, 0x0,
2889  };
2890  static const unsigned char expected_bits_1[] =
2891  {
2892  0x40, 0x0, 0x0, 0x0,
2893  0x0, 0x0, 0x0, 0x0,
2894  };
2895  static const RGBQUAD colors_bits_1[] =
2896  {
2897  {0, 0, 0},
2898  {0xff, 0xff, 0xff},
2899  };
2900  static RGBQUAD colors_bits_8[256];
2901 
2902  static const struct
2903  {
2904  LONG width, height, output_width, output_height;
2905  WORD bit_count;
2906  const unsigned char *test_bits, *expected_bits;
2907  size_t test_bits_size, result_bits_size;
2908  const RGBQUAD *bmi_colors;
2909  size_t bmi_colors_size;
2910  BOOL todo;
2911  }
2912  tests[] =
2913  {
2914  {4, 4, 2, 2, 24, test_bits_24, expected_bits_24,
2915  sizeof(test_bits_24), sizeof(expected_bits_24), NULL, 0, TRUE},
2916  {4, 4, 2, 2, 1, test_bits_1, expected_bits_1,
2917  sizeof(test_bits_1), sizeof(expected_bits_1), colors_bits_1,
2918  sizeof(colors_bits_1), FALSE},
2919  {4, 4, 2, 2, 8, test_bits_8, expected_bits_8,
2920  sizeof(test_bits_8), sizeof(expected_bits_8), colors_bits_8,
2921  sizeof(colors_bits_8), FALSE},
2922  {4, 4, 2, 2, 16, (const unsigned char *)test_bits_16, (const unsigned char *)expected_bits_16,
2923  sizeof(test_bits_16), sizeof(expected_bits_16), NULL, 0, FALSE},
2924  };
2925  static const char filename[] = "test.bmp";
2926  BITMAPINFO *bmi, *bmi_output;
2927  HBITMAP bitmap, bitmap_copy;
2928  unsigned int test_index;
2929  unsigned char *bits;
2930  size_t bmi_size;
2931  unsigned int i;
2932  HDC hdc;
2933 
2934  bmi_size = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
2935  bmi = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
2936  bmi_output = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bmi_size);
2937  bmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2938  bmi->bmiHeader.biPlanes = 1;
2940 
2941  for (i = 0; i < 256; ++i)
2942  colors_bits_8[i].rgbRed = colors_bits_8[i].rgbGreen = colors_bits_8[i].rgbBlue = i;
2943 
2944  hdc = GetDC(NULL);
2945 
2946  for (test_index = 0; test_index < ARRAY_SIZE(tests); ++test_index)
2947  {
2948  if (tests[test_index].bmi_colors)
2949  memcpy(bmi->bmiColors, tests[test_index].bmi_colors, tests[test_index].bmi_colors_size);
2950  else
2951  memset(bmi->bmiColors, 0, 256 * sizeof(RGBQUAD));
2952 
2953  bmi->bmiHeader.biWidth = tests[test_index].width;
2954  bmi->bmiHeader.biHeight = tests[test_index].height;
2955  bmi->bmiHeader.biBitCount = tests[test_index].bit_count;
2956  memcpy(bmi_output, bmi, bmi_size);
2957  bmi_output->bmiHeader.biWidth = tests[test_index].output_width;
2958  bmi_output->bmiHeader.biHeight = tests[test_index].output_height;
2959 
2960  bitmap = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, (void **)&bits, NULL, 0);
2961  ok(bitmap && bits, "CreateDIBSection() failed, result %u.\n", GetLastError());
2962  memcpy(bits, tests[test_index].test_bits, tests[test_index].test_bits_size);
2963 
2964  bitmap_copy = CopyImage(bitmap, IMAGE_BITMAP, tests[test_index].output_width,
2965  tests[test_index].output_height, LR_CREATEDIBSECTION);
2966  ok(!!bitmap_copy, "CopyImage() failed, result %u.\n", GetLastError());
2967 
2968  compare_bitmap_bits(hdc, bitmap_copy, bmi_output, tests[test_index].result_bits_size,
2969  tests[test_index].expected_bits, test_index, tests[test_index].todo);
2971  DeleteObject(bitmap_copy);
2972 
2973  create_bitmap_file(filename, bmi, tests[test_index].test_bits);
2974  bitmap = LoadImageA(NULL, filename, IMAGE_BITMAP, tests[test_index].output_width,
2975  tests[test_index].output_height, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
2976  ok(!!bitmap, "LoadImageA() failed, result %u.\n", GetLastError());
2978  compare_bitmap_bits(hdc, bitmap, bmi_output, tests[test_index].result_bits_size,
2979  tests[test_index].expected_bits, test_index, tests[test_index].todo);
2981  }
2982  ReleaseDC(0, hdc);
2983  HeapFree(GetProcessHeap(), 0, bmi_output);
2984  HeapFree(GetProcessHeap(), 0, bmi);
2985 }
2986 
2987 START_TEST(cursoricon)
2988 {
2989  pGetCursorInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorInfo" );
2990  pGetIconInfoExA = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExA" );
2991  pGetIconInfoExW = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetIconInfoExW" );
2992  pGetCursorFrameInfo = (void *)GetProcAddress( GetModuleHandleA("user32.dll"), "GetCursorFrameInfo" );
2994 
2995  if (test_argc >= 3)
2996  {
2997  /* Child process. */
2998  sscanf (test_argv[2], "%x", (unsigned int *) &parent);
2999 
3000  ok(parent != NULL, "Parent not found.\n");
3001  if (parent == NULL)
3002  ExitProcess(1);
3003 
3004  do_child();
3005  return;
3006  }
3007 
3016  test_CreateIcon();
3017  test_LoadImage();
3020  test_DrawIcon();
3021  test_DrawIconEx();
3022  test_DrawState();
3023  test_SetCursor();
3024  test_ShowCursor();
3028  do_parent();
3031 }
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 * u
Definition: glfuncs.h:240
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:2287
#define CRSR_RES_SIZE
struct param_test tests[]
BYTE rgbtBlue
Definition: wingdi.h:1437
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:406
#define shift
Definition: input.c:1761
char hdr[14]
Definition: iptest.cpp:33
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:1475
#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
static COLORREF get_color_from_bits(const unsigned char *bits, const BITMAPINFO *bmi, unsigned int row, unsigned int column)
Definition: cursoricon.c:2788
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:3100
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
GLuint GLuint GLsizei count
Definition: gl.h:1545
static DWORD DWORD istep
Definition: cursoricon.c:1638
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:1454
#define CopyCursor(c)
Definition: winuser.h:4210
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:2146
#define CALLBACK
Definition: compat.h:27
WCHAR szModName[MAX_PATH]
Definition: winuser.h:3127
BOOL todo
Definition: filedlg.c:313
WORD wResID
Definition: winuser.h:3113
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:1326
#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:399
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:1642
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:2987
CHAR szResName[MAX_PATH]
Definition: winuser.h:3115
static void test_CopyImage_Bitmap(int depth)
Definition: cursoricon.c:542
UINT_PTR WPARAM
Definition: windef.h:207
_Check_return_ _CRTIMP _CONST_RETURN char *__cdecl strrchr(_In_z_ const char *_Str, _In_ int _Ch)
CURSORICONFILEDIRENTRY idEntries[1]
Definition: olepicture.c:100
HICON HCURSOR
Definition: windef.h:299
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:1595
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
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:548
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
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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:1452
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
static DWORD unk1
Definition: cursoricon.c:1638
#define ICON_HEIGHT
static void test_DrawIconEx(void)
Definition: cursoricon.c:2070
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:1986
unsigned int UINT32
DWORD chunk_id
Definition: cursoricon.c:102
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
GLuint color
Definition: glext.h:6243
static DWORD parent_id
Definition: cursoricon.c:2270
CURSORICONFILEDIR icon_info
Definition: cursoricon.c:90
#define GENERIC_WRITE
Definition: nt_native.h:90
HBITMAP hbmMask
Definition: winuser.h:3101
#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:4290
#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:1886
#define ICON_BPP
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
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
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
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:2388
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:1453
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:3102
#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:2198
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:2390
#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:1056
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:1146
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
#define rgb16(r, g, b)
static const unsigned char gif4pixel[42]
Definition: cursoricon.c:1028
BYTE data[32 *32 *4]
Definition: cursoricon.c:85
#define todo_wine_if(is_todo)
Definition: test.h:164
static void test_LoadImage_working_directory_run(char *path)
Definition: cursoricon.c:1240
Definition: uimain.c:88
struct tagRGBQUAD RGBQUAD
int WINAPI ShowCursor(_In_ BOOL bShow)
Definition: cursoricon.c:2642
BOOL fIcon
Definition: winuser.h:3098
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:1081
static void test_GetCursorFrameInfo(void)
Definition: cursoricon.c:1639
WORD wResID
Definition: winuser.h:3126
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
DWORD chunk_size
Definition: cursoricon.c:115
GLsizei stride
Definition: glext.h:5848
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:2053
#define GetProcessHeap()
Definition: compat.h:403
#define trace
Definition: atltest.h:70
PVOID WINAPI HeapAlloc(HANDLE, DWORD, SIZE_T)
#define GetEnvironmentVariableA(x, y, z)
Definition: compat.h:419
riff_seq3_t seq
Definition: cursoricon.c:148
static const unsigned char bmpcoreimage[38]
Definition: cursoricon.c:1021
RGBQUAD bmiColors[1]
Definition: wingdi.h:1476
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:300
DWORD xHotspot
Definition: winuser.h:3099
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
#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:2219
static LRESULT CALLBACK callback_child(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: cursoricon.c:310
#define RGB(r, g, b)
Definition: wingdi.h:2939
#define MAX_PATH
Definition: compat.h:26
DWORD num_steps
Definition: cursoricon.c:75
#define WINAPI
Definition: msvc.h:6
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:417
DWORD cbSize
Definition: winuser.h:3120
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
static void compare_bitmap_bits_(unsigned int line, HDC hdc, HBITMAP bitmap, BITMAPINFO *bmi, size_t result_bits_size, const unsigned char *expected_bits, unsigned int test_index, BOOL todo)
Definition: cursoricon.c:2815
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:163
DWORD rate[3]
Definition: cursoricon.c:134
static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits)
Definition: cursoricon.c:1206
CHAR szModName[MAX_PATH]
Definition: winuser.h:3114
HDC hdc
Definition: main.c:9
DWORD chunk_type
Definition: cursoricon.c:104
int WINAPI GetDeviceCaps(_In_opt_ HDC, _In_ int)
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2205
#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:2272
#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
static void test_Image_StretchMode(void)
Definition: cursoricon.c:2843
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 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:1638
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)
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2053
static void test_DestroyCursor(void)
Definition: cursoricon.c:2514
HCURSOR WINAPI SetCursor(_In_opt_ HCURSOR)
HICON hIcon
Definition: msconfig.c:44
#define ARRAY_SIZE(a)
Definition: main.h:24
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
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2145
#define LR_CREATEDIBSECTION
Definition: winuser.h:1088
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
#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:1439
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