ReactOS 0.4.15-dev-8393-g61b7fb9
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
36typedef 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
48typedef 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
72typedef struct {
83
84typedef struct {
85 BYTE data[32*32*4];
86 BYTE mask_data[32*32/8];
88
89typedef 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
95typedef struct {
96 DWORD chunk_id; /* ANI_anih_ID */
97 DWORD chunk_size; /* actual size of data */
98 ani_header header; /* animated cursor header */
100
101typedef struct {
102 DWORD chunk_id; /* ANI_LIST_ID */
103 DWORD chunk_size; /* actual size of data */
104 DWORD chunk_type; /* ANI_fram_ID */
106
107typedef struct {
108 DWORD chunk_id; /* ANI_icon_ID */
109 DWORD chunk_size; /* actual size of data */
110 ani_frame32x32x32 data; /* animated cursor frame */
112
113typedef 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
122typedef 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
131typedef struct {
132 DWORD chunk_id; /* ANI_rate_ID */
133 DWORD chunk_size; /* actual size of data */
134 DWORD rate[3]; /* animated cursor rate data */
136
137typedef struct {
138 DWORD chunk_id; /* ANI_seq__ID */
139 DWORD chunk_size; /* actual size of data */
140 DWORD order[3]; /* animated cursor sequence data */
142
143typedef 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
195 sizeof(empty_anicursor) - sizeof(DWORD)*2,
197 {
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 {
214 sizeof(riff_icon32x32x32_t)*(1 /*frames*/) + sizeof(DWORD),
216 },
217 {
219 }
220};
221
224 sizeof(empty_anicursor3) - sizeof(DWORD)*2,
226 {
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 {
243 sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD),
245 },
246 {
250 }
251};
252
255 sizeof(empty_anicursor3_seq) - sizeof(DWORD)*2,
257 {
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 */
270 }
271 },
272 {
274 sizeof(riff_seq3_t) - sizeof(DWORD)*2,
275 { 2, 0, 1} /* show frames in a uniquely identifiable order */
276 },
277 {
279 sizeof(riff_rate3_t) - sizeof(DWORD)*2,
280 { 0xc0de, 0xcafe, 0xbabe}
281 },
282 {
284 sizeof(riff_icon32x32x32_t)*(3 /*frames*/) + sizeof(DWORD),
286 },
287 {
291 }
292};
293
294#include "poppack.h"
295
296static char **test_argv;
297static int test_argc;
298static HWND child = 0;
299static HWND parent = 0;
301
302#define PROC_INIT (WM_USER+1)
303
304static BOOL (WINAPI *pGetCursorInfo)(CURSORINFO *);
305static BOOL (WINAPI *pGetIconInfoExA)(HICON,ICONINFOEXA *);
306static BOOL (WINAPI *pGetIconInfoExW)(HICON,ICONINFOEXW *);
307
308static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
309
311{
312 switch (msg)
313 {
314 /* Destroy the cursor. */
315 case WM_USER+1:
316 {
319 BOOL ret;
320 DWORD error;
321
322 memset(&info, 0, sizeof(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);
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:
341 return 0;
342 }
343
345}
346
348{
349 if (msg == PROC_INIT)
350 {
351 child = (HWND) wParam;
352 return TRUE;
353 }
354
356}
357
358static 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
397static 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);
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
446static void finish_child_process(void)
447{
451}
452
453static void test_child_process(void)
454{
455 static const BYTE bmp_bits[4096];
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
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
489static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
490 INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
491{
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
543{
544 HBITMAP ddb, dib;
545 HDC screenDC;
547 VOID * bits;
548 int screen_depth;
549 unsigned int i;
550
551 /* Create a device-independent bitmap (DIB) */
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
621
626
627 /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
632
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);
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);
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);
689 }
690 }
691
693}
694
695static 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 }
709 ok(error == 0xdeadbeef, "Last error: 0x%08x\n", error);
710}
711
712static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_mask_cy, UINT exp_bpp, int line)
713{
715 DWORD ret;
716 BITMAP bmMask, bmColor;
717
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
795static void test_CreateIcon(void)
796{
797 static const BYTE bmp_bits[1024];
798 HICON hIcon;
799 HBITMAP hbmMask, hbmColor;
800 BITMAPINFO *bmpinfo;
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 */
971static const unsigned char gifimage[35] = {
9720x47,0x49,0x46,0x38,0x37,0x61,0x01,0x00,0x01,0x00,0x80,0x00,0x00,0xff,0xff,0xff,
9730xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x02,0x02,0x44,
9740x01,0x00,0x3b
975};
976
977/* 1x1 pixel jpg */
978static const unsigned char jpgimage[285] = {
9790xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x01,0x2c,
9800x01,0x2c,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x05,0x03,0x04,0x04,0x04,0x03,0x05,
9810x04,0x04,0x04,0x05,0x05,0x05,0x06,0x07,0x0c,0x08,0x07,0x07,0x07,0x07,0x0f,0x0b,
9820x0b,0x09,0x0c,0x11,0x0f,0x12,0x12,0x11,0x0f,0x11,0x11,0x13,0x16,0x1c,0x17,0x13,
9830x14,0x1a,0x15,0x11,0x11,0x18,0x21,0x18,0x1a,0x1d,0x1d,0x1f,0x1f,0x1f,0x13,0x17,
9840x22,0x24,0x22,0x1e,0x24,0x1c,0x1e,0x1f,0x1e,0xff,0xdb,0x00,0x43,0x01,0x05,0x05,
9850x05,0x07,0x06,0x07,0x0e,0x08,0x08,0x0e,0x1e,0x14,0x11,0x14,0x1e,0x1e,0x1e,0x1e,
9860x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
9870x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,
9880x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0xff,0xc0,
9890x00,0x11,0x08,0x00,0x01,0x00,0x01,0x03,0x01,0x22,0x00,0x02,0x11,0x01,0x03,0x11,
9900x01,0xff,0xc4,0x00,0x15,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
9910x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0xff,0xc4,0x00,0x14,0x10,0x01,0x00,0x00,
9920x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xc4,
9930x00,0x14,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
9940x00,0x00,0x00,0x00,0xff,0xc4,0x00,0x14,0x11,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
9950x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xda,0x00,0x0c,0x03,0x01,
9960x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0xb2,0xc0,0x07,0xff,0xd9
997};
998
999/* 1x1 pixel png */
1000static const unsigned char pngimage[285] = {
10010x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52,
10020x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x08,0x02,0x00,0x00,0x00,0x90,0x77,0x53,
10030xde,0x00,0x00,0x00,0x09,0x70,0x48,0x59,0x73,0x00,0x00,0x0b,0x13,0x00,0x00,0x0b,
10040x13,0x01,0x00,0x9a,0x9c,0x18,0x00,0x00,0x00,0x07,0x74,0x49,0x4d,0x45,0x07,0xd5,
10050x06,0x03,0x0f,0x07,0x2d,0x12,0x10,0xf0,0xfd,0x00,0x00,0x00,0x0c,0x49,0x44,0x41,
10060x54,0x08,0xd7,0x63,0xf8,0xff,0xff,0x3f,0x00,0x05,0xfe,0x02,0xfe,0xdc,0xcc,0x59,
10070xe7,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. */
1012static unsigned char bmpimage[70] = {
10130x42,0x4d,0x46,0x00,0x00,0x00,0xDE,0xAD,0xBE,0xEF,0x42,0x00,0x00,0x00,0x28,0x00,
10140x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x00,0x00,
10150x00,0x00,0x04,0x00,0x00,0x00,0x12,0x0b,0x00,0x00,0x12,0x0b,0x00,0x00,0x02,0x00,
10160x00,0x00,0x02,0x00,0x00,0x00,0xff,0xff,0xff,0x00,0x55,0x55,0x55,0x00,0xFF,0xFF,
10170xFF,0xFF,0x00,0x00,0x00,0x00
1018};
1019
1020/* 1x1 pixel bmp using BITMAPCOREHEADER */
1021static const unsigned char bmpcoreimage[38] = {
10220x42,0x4d,0x26,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x0c,0x00,
10230x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xff,0xff,0xff,0x00,0x55,0x55,
10240x55,0x00,0x00,0x00,0x00,0x00
1025};
1026
1027/* 2x2 pixel gif */
1028static const unsigned char gif4pixel[42] = {
10290x47,0x49,0x46,0x38,0x37,0x61,0x02,0x00,0x02,0x00,0xa1,0x00,0x00,0x00,0x00,0x00,
10300x39,0x62,0xfc,0xff,0x1a,0xe5,0xff,0xff,0xff,0x2c,0x00,0x00,0x00,0x00,0x02,0x00,
10310x02,0x00,0x00,0x02,0x03,0x14,0x16,0x05,0x00,0x3b
1032};
1033
1034/* An invalid cursor with an invalid dwDIBOffset */
1035static 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
1040static 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
1056static 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
1081static 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.");
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);
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
1140typedef struct {
1141 unsigned width;
1142 unsigned height;
1145
1146static 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");
1202
1204}
1205
1206static 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);
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
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
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);
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
1326static 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 */
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
1595static int check_cursor_data( HDC hdc, HCURSOR hCursor, void *data, int length)
1596{
1597 char *image = NULL;
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 }
1632cleanup:
1633 HeapFree( GetProcessHeap(), 0, image );
1634 HeapFree( GetProcessHeap(), 0, info );
1635 return ret;
1636}
1637
1638static HCURSOR (WINAPI *pGetCursorFrameInfo)(HCURSOR hCursor, DWORD unk1, DWORD istep, DWORD *rate, DWORD *steps);
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
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);
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);
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);
1880cleanup:
1881 if(bmpOld) SelectObject(hdc, bmpOld);
1882 if(bmp) DeleteObject(bmp);
1883 if(hdc) DeleteDC(hdc);
1884}
1885
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
1922static 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
1952static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background,
1953 COLORREF modern_expected, COLORREF legacy_expected, int line)
1954{
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
1986static 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);
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
2044cleanup:
2045 if(bmpOld)
2046 SelectObject(hdcDst, bmpOld);
2047 if(bmpDst)
2048 DeleteObject(bmpDst);
2049 if(hdcDst)
2051}
2052
2053static 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{
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
2070static 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
2137cleanup:
2138 if(bmpOld)
2139 SelectObject(hdcDst, bmpOld);
2140 if(bmpDst)
2141 DeleteObject(bmpDst);
2142 if(hdcDst)
2144}
2145
2146static 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
2198static 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{
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
2219static 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
2261cleanup:
2262 if(bmpOld)
2263 SelectObject(hdcDst, bmpOld);
2264 if(bmpDst)
2265 DeleteObject(bmpDst);
2266 if(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
2287static 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;
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
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
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 );
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{
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 );
2405 return ret;
2406}
2407
2408static void test_ShowCursor(void)
2409{
2410 int count;
2411 DWORD id, result;
2412 HANDLE thread;
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;
2450 count = ShowCursor( FALSE );
2451 ok( count == -3, "wrong count %d\n", count );
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 );
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
2473 count = ShowCursor( TRUE );
2474 ok( count == -2, "wrong count %d\n", count );
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 );
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
2514static 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 }
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);
2567 ok( !ret, "DestroyCursor succeeded\n" );
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);
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);
2588 if (new_cursor != cursor) /* win9x */
2589 ok( ret, "DestroyCursor succeeded\n" );
2590 else
2591 ok( !ret, "DestroyCursor succeeded\n" );
2593 "wrong error %u\n", GetLastError() );
2594
2595 SetLastError(0xdeadbeef);
2596 cursor2 = SetCursor( cursor );
2597 ok(!cursor2, "SetCursor returned %p/%p\n", cursor2, cursor);
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" );
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);
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
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
2671static 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;
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
2781 ok(ret, "DestroyIcon() failed with %u.\n", GetLastError());
2782 DeleteFileA("icon.ico");
2783 }
2784
2785 HeapFree(GetProcessHeap(), 0, icon_data);
2786}
2787
2788static 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)
2815static 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);
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
2843static 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
2987START_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
3020 test_DrawIcon();
3028 do_parent();
3031}
signed short INT16
unsigned int UINT32
#define broken(x)
Definition: _sntprintf.h:21
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
static void startup(void)
unsigned int dir
Definition: maze.c:112
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
#define ARRAY_SIZE(A)
Definition: main.h:33
INT copy(TCHAR source[MAX_PATH], TCHAR dest[MAX_PATH], INT append, DWORD lpdwFlags, BOOL bTouch)
Definition: copy.c:51
static HANDLE thread
Definition: service.c:33
DWORD GetPixel(LPDIRECTDRAWSURFACE7 Surface, UINT x, UINT y)
Definition: blt.cpp:2
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DWORD bpp
Definition: surface.c:185
#define CloseHandle
Definition: compat.h:739
#define GetProcessHeap()
Definition: compat.h:736
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
HANDLE HWND
Definition: compat.h:19
#define GetProcAddress(x, y)
Definition: compat.h:753
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define HeapAlloc
Definition: compat.h:733
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define CALLBACK
Definition: compat.h:35
#define GetEnvironmentVariableA(x, y, z)
Definition: compat.h:754
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static const WCHAR *const ext[]
Definition: module.c:53
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
DWORD WINAPI GetModuleFileNameA(HINSTANCE hModule, LPSTR lpFilename, DWORD nSize)
Definition: loader.c:539
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
VOID WINAPI ExitProcess(IN UINT uExitCode)
Definition: proc.c:1487
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:4741
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:137
BOOL WINAPI GetExitCodeThread(IN HANDLE hThread, OUT LPDWORD lpExitCode)
Definition: thread.c:541
struct png_info_def *typedef unsigned char **typedef struct png_info_def *typedef struct png_info_def *typedef struct png_info_def *typedef unsigned char ** row
Definition: typeof.h:78
#define BI_RGB
Definition: precomp.h:56
#define RGB(r, g, b)
Definition: precomp.h:71
ULONG RGBQUAD
Definition: precomp.h:59
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
static char * path_name(DOS_FILE *file)
Definition: check.c:208
pKey DeleteObject()
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLclampf GLclampf GLclampf alpha
Definition: gl.h:1740
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
GLsizei stride
Definition: glext.h:5848
GLuint buffer
Definition: glext.h:5915
GLuint color
Definition: glext.h:6243
GLenum GLint GLuint mask
Definition: glext.h:6028
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint64EXT * result
Definition: glext.h:11304
GLuint id
Definition: glext.h:5910
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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
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
const char cursor[]
Definition: icontest.c:13
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define bits
Definition: infblock.c:15
const char * filename
Definition: ioapi.h:137
char hdr[14]
Definition: iptest.cpp:33
#define wine_dbgstr_w
Definition: kernel32.h:34
static GLint image_size(GLint width, GLint height, GLenum format, GLenum type)
Definition: mipmap.c:4858
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define CREATE_NEW
Definition: disk.h:69
static struct test_info tests[]
#define sprintf(buf, format,...)
Definition: sprintf.c:55
BITMAP bmp
Definition: alphablend.c:62
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static HICON
Definition: imagelist.c:84
BOOL todo
Definition: filedlg.c:313
BOOL expected
Definition: store.c:2063
#define todo_wine_if(is_todo)
Definition: custom.c:76
#define todo_wine
Definition: custom.c:79
static const BYTE dib[]
Definition: ole2.c:201
static void test_SetCursor(void)
Definition: cursoricon.c:2287
#define ANI_FLAG_SEQUENCE
Definition: cursoricon.c:70
static LRESULT CALLBACK callback_parent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
Definition: cursoricon.c:347
static DWORD DWORD DWORD DWORD * steps
Definition: cursoricon.c:1638
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
static DWORD unk1
Definition: cursoricon.c:1638
riff_cursor3_t empty_anicursor3
Definition: cursoricon.c:222
static DWORD DWORD DWORD * rate
Definition: cursoricon.c:1638
static DWORD parent_id
Definition: cursoricon.c:2270
static void do_child(void)
Definition: cursoricon.c:358
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
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
static void test_GetCursorFrameInfo(void)
Definition: cursoricon.c:1639
static void finish_child_process(void)
Definition: cursoricon.c:446
#define ICON_RES_SIZE
#define EMPTY_ICON32
Definition: cursoricon.c:154
static void test_ShowCursor(void)
Definition: cursoricon.c:2408
static char ** test_argv
Definition: cursoricon.c:296
static HANDLE event_next
Definition: cursoricon.c:2388
static void test_DrawIcon(void)
Definition: cursoricon.c:1986
static HANDLE event_start
Definition: cursoricon.c:2388
static void test_initial_cursor(void)
Definition: cursoricon.c:695
static const unsigned char bmpcoreimage[38]
Definition: cursoricon.c:1021
static void test_LoadImage(void)
Definition: cursoricon.c:1326
#define compare_bitmap_bits(a, b, c, d, e, f, g)
Definition: cursoricon.c:2814
#define ANI_fram_ID
Definition: cursoricon.c:65
#define ANI_RIFF_ID
Definition: cursoricon.c:60
#define rgb16(r, g, b)
static DWORD CALLBACK set_cursor_thread(void *arg)
Definition: cursoricon.c:2272
#define PROC_INIT
Definition: cursoricon.c:302
#define ANI_LIST_ID
Definition: cursoricon.c:61
static void check_alpha_draw(HDC hdc, BOOL drawiconex, BOOL alpha, int bpp, int line)
Definition: cursoricon.c:1922
static void test_child_process(void)
Definition: cursoricon.c:453
#define CRSR_RES_SIZE
static const unsigned char gifimage[35]
Definition: cursoricon.c:971
#define ICON_WIDTH
static unsigned char bmpimage[70]
Definition: cursoricon.c:1012
static BOOL color_match(COLORREF a, COLORREF b)
Definition: cursoricon.c:481
static HICON create_test_icon(HDC hdc, int width, int height, int bpp, BOOL maskvalue, UINT32 *color, int colorSize)
Definition: cursoricon.c:1886
static void test_LoadImageBitmap(const char *test_desc, HBITMAP hbm)
Definition: cursoricon.c:1056
riff_cursor1_t empty_anicursor
Definition: cursoricon.c:193
static HANDLE child_process
Definition: cursoricon.c:300
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
#define test_icon_info(a, b, c, d, e)
Definition: cursoricon.c:793
static void create_ico_file(const char *filename, const test_icon_entries_t *test_icon_entries, unsigned entry_cnt)
Definition: cursoricon.c:1146
riff_cursor3_seq_t empty_anicursor3_seq
Definition: cursoricon.c:253
static ICONINFOEXA *static ICONINFOEXW *static const BOOL is_win64
Definition: cursoricon.c:308
static void test_DrawIconEx(void)
Definition: cursoricon.c:2070
static HWND parent
Definition: cursoricon.c:299
static void test_monochrome_icon(void)
Definition: cursoricon.c:2671
static void test_CopyImage_Bitmap(int depth)
Definition: cursoricon.c:542
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
#define ANI_ACON_ID
Definition: cursoricon.c:62
static void test_DrawState(void)
Definition: cursoricon.c:2219
#define ICON_HEIGHT
static void test_LoadImage_working_directory(void)
Definition: cursoricon.c:1282
static void test_LoadImage_working_directory_run(char *path)
Definition: cursoricon.c:1240
static void create_bitmap_file(const char *filename, const BITMAPINFO *bmi, const unsigned char *bits)
Definition: cursoricon.c:1206
static void test_DestroyCursor(void)
Definition: cursoricon.c:2514
static void test_CreateIcon(void)
Definition: cursoricon.c:795
#define ANI_FLAG_ICON
Definition: cursoricon.c:69
static void check_DrawIcon(HDC hdc, BOOL maskvalue, UINT32 color, int bpp, COLORREF background, COLORREF modern_expected, COLORREF legacy_expected, int line)
Definition: cursoricon.c:1952
static void test_CreateIconFromResource(void)
Definition: cursoricon.c:1454
static HWND child
Definition: cursoricon.c:298
static DWORD CALLBACK show_cursor_thread(void *arg)
Definition: cursoricon.c:2390
static int check_cursor_data(HDC hdc, HCURSOR hCursor, void *data, int length)
Definition: cursoricon.c:1595
static int test_argc
Definition: cursoricon.c:297
static void test_PrivateExtractIcons(void)
Definition: