push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / user32 / tests / cursoricon.c
blob9858e327f7b999706e639a3c9a732312413a7595
1 /*
2 * Unit test suite for cursors and icons.
4 * Copyright 2006 Michael Kaufmann
5 * Copyright 2007 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <assert.h>
23 #include <stdlib.h>
24 #include <stdarg.h>
25 #include <stdio.h>
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"
34 static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
35 INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
37 HBITMAP copy;
38 BITMAP origBitmap;
39 BITMAP copyBitmap;
40 BOOL orig_is_dib;
41 BOOL copy_is_dib;
43 copy = (HBITMAP) CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags);
44 ok(copy != NULL, "CopyImage() failed\n");
45 if (copy != NULL)
47 GetObject(bitmap, sizeof(origBitmap), &origBitmap);
48 GetObject(copy, sizeof(copyBitmap), &copyBitmap);
49 orig_is_dib = (origBitmap.bmBits != NULL);
50 copy_is_dib = (copyBitmap.bmBits != NULL);
52 if (copy_is_dib && dibExpected
53 && copyBitmap.bmBitsPixel == 24
54 && (expectedDepth == 16 || expectedDepth == 32))
56 /* Windows 95 doesn't create DIBs with a depth of 16 or 32 bit */
57 if (GetVersion() & 0x80000000)
59 expectedDepth = 24;
63 if (copy_is_dib && !dibExpected && !(flags & LR_CREATEDIBSECTION))
65 /* It's not forbidden to create a DIB section if the flag
66 LR_CREATEDIBSECTION is absent.
67 Windows 9x does this if the bitmap has a depth that doesn't
68 match the screen depth, Windows NT doesn't */
69 dibExpected = TRUE;
70 expectedDepth = origBitmap.bmBitsPixel;
73 ok((!(dibExpected ^ copy_is_dib)
74 && (copyBitmap.bmWidth == expectedWidth)
75 && (copyBitmap.bmHeight == expectedHeight)
76 && (copyBitmap.bmBitsPixel == expectedDepth)),
77 "CopyImage ((%s, %dx%d, %u bpp), %d, %d, %#x): Expected (%s, %dx%d, %u bpp), got (%s, %dx%d, %u bpp)\n",
78 orig_is_dib ? "DIB" : "DDB", origBitmap.bmWidth, origBitmap.bmHeight, origBitmap.bmBitsPixel,
79 copyWidth, copyHeight, flags,
80 dibExpected ? "DIB" : "DDB", expectedWidth, expectedHeight, expectedDepth,
81 copy_is_dib ? "DIB" : "DDB", copyBitmap.bmWidth, copyBitmap.bmHeight, copyBitmap.bmBitsPixel);
83 DeleteObject(copy);
87 static void test_CopyImage_Bitmap(int depth)
89 HBITMAP ddb, dib;
90 HDC screenDC;
91 BITMAPINFO * info;
92 VOID * bits;
93 int screen_depth;
94 unsigned int i;
96 /* Create a device-independent bitmap (DIB) */
97 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
98 info->bmiHeader.biSize = sizeof(info->bmiHeader);
99 info->bmiHeader.biWidth = 2;
100 info->bmiHeader.biHeight = 2;
101 info->bmiHeader.biPlanes = 1;
102 info->bmiHeader.biBitCount = depth;
103 info->bmiHeader.biCompression = BI_RGB;
105 for (i=0; i < 256; i++)
107 info->bmiColors[i].rgbRed = i;
108 info->bmiColors[i].rgbGreen = i;
109 info->bmiColors[i].rgbBlue = 255 - i;
110 info->bmiColors[i].rgbReserved = 0;
113 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
115 /* Create a device-dependent bitmap (DDB) */
116 screenDC = GetDC(NULL);
117 screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
118 if (depth == 1 || depth == screen_depth)
120 ddb = CreateBitmap(2, 2, 1, depth, NULL);
122 else
124 ddb = NULL;
126 ReleaseDC(NULL, screenDC);
128 if (ddb != NULL)
130 test_CopyImage_Check(ddb, 0, 0, 0, 2, 2, depth == 1 ? 1 : screen_depth, FALSE);
131 test_CopyImage_Check(ddb, 0, 0, 5, 2, 5, depth == 1 ? 1 : screen_depth, FALSE);
132 test_CopyImage_Check(ddb, 0, 5, 0, 5, 2, depth == 1 ? 1 : screen_depth, FALSE);
133 test_CopyImage_Check(ddb, 0, 5, 5, 5, 5, depth == 1 ? 1 : screen_depth, FALSE);
135 test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
136 test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
137 test_CopyImage_Check(ddb, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
138 test_CopyImage_Check(ddb, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
140 test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
141 test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
142 test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
143 test_CopyImage_Check(ddb, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
145 /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
146 test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
147 test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
148 test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
149 test_CopyImage_Check(ddb, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
151 DeleteObject(ddb);
154 if (depth != 1)
156 test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
157 test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
158 test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
159 test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
162 test_CopyImage_Check(dib, LR_MONOCHROME, 0, 0, 2, 2, 1, FALSE);
163 test_CopyImage_Check(dib, LR_MONOCHROME, 5, 0, 5, 2, 1, FALSE);
164 test_CopyImage_Check(dib, LR_MONOCHROME, 0, 5, 2, 5, 1, FALSE);
165 test_CopyImage_Check(dib, LR_MONOCHROME, 5, 5, 5, 5, 1, FALSE);
167 test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
168 test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
169 test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
170 test_CopyImage_Check(dib, LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
172 /* LR_MONOCHROME is ignored if LR_CREATEDIBSECTION is present */
173 test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 0, 2, 2, depth, TRUE);
174 test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 0, 5, 2, depth, TRUE);
175 test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 0, 5, 2, 5, depth, TRUE);
176 test_CopyImage_Check(dib, LR_MONOCHROME | LR_CREATEDIBSECTION, 5, 5, 5, 5, depth, TRUE);
178 DeleteObject(dib);
180 if (depth == 1)
182 /* Special case: A monochrome DIB is converted to a monochrome DDB if
183 the colors in the color table are black and white.
185 Skip this test on Windows 95, it always creates a monochrome DDB
186 in this case */
188 if (!(GetVersion() & 0x80000000))
190 info->bmiHeader.biBitCount = 1;
191 info->bmiColors[0].rgbRed = 0xFF;
192 info->bmiColors[0].rgbGreen = 0;
193 info->bmiColors[0].rgbBlue = 0;
194 info->bmiColors[1].rgbRed = 0;
195 info->bmiColors[1].rgbGreen = 0xFF;
196 info->bmiColors[1].rgbBlue = 0;
198 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
199 test_CopyImage_Check(dib, 0, 0, 0, 2, 2, screen_depth, FALSE);
200 test_CopyImage_Check(dib, 0, 5, 0, 5, 2, screen_depth, FALSE);
201 test_CopyImage_Check(dib, 0, 0, 5, 2, 5, screen_depth, FALSE);
202 test_CopyImage_Check(dib, 0, 5, 5, 5, 5, screen_depth, FALSE);
203 DeleteObject(dib);
205 info->bmiHeader.biBitCount = 1;
206 info->bmiColors[0].rgbRed = 0;
207 info->bmiColors[0].rgbGreen = 0;
208 info->bmiColors[0].rgbBlue = 0;
209 info->bmiColors[1].rgbRed = 0xFF;
210 info->bmiColors[1].rgbGreen = 0xFF;
211 info->bmiColors[1].rgbBlue = 0xFF;
213 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
214 test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
215 test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
216 test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
217 test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
218 DeleteObject(dib);
220 info->bmiHeader.biBitCount = 1;
221 info->bmiColors[0].rgbRed = 0xFF;
222 info->bmiColors[0].rgbGreen = 0xFF;
223 info->bmiColors[0].rgbBlue = 0xFF;
224 info->bmiColors[1].rgbRed = 0;
225 info->bmiColors[1].rgbGreen = 0;
226 info->bmiColors[1].rgbBlue = 0;
228 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
229 test_CopyImage_Check(dib, 0, 0, 0, 2, 2, 1, FALSE);
230 test_CopyImage_Check(dib, 0, 5, 0, 5, 2, 1, FALSE);
231 test_CopyImage_Check(dib, 0, 0, 5, 2, 5, 1, FALSE);
232 test_CopyImage_Check(dib, 0, 5, 5, 5, 5, 1, FALSE);
233 DeleteObject(dib);
237 HeapFree(GetProcessHeap(), 0, info);
240 static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_bpp, int line)
242 ICONINFO info;
243 DWORD ret;
244 BITMAP bmMask, bmColor;
246 ret = GetIconInfo(hIcon, &info);
247 ok_(__FILE__, line)(ret, "GetIconInfo failed\n");
249 /* CreateIcon under XP causes info.fIcon to be 0 */
250 ok_(__FILE__, line)(info.xHotspot == exp_cx/2, "info.xHotspot = %u\n", info.xHotspot);
251 ok_(__FILE__, line)(info.yHotspot == exp_cy/2, "info.yHotspot = %u\n", info.yHotspot);
252 ok_(__FILE__, line)(info.hbmMask != 0, "info.hbmMask is NULL\n");
254 ret = GetObject(info.hbmMask, sizeof(bmMask), &bmMask);
255 ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
257 if (exp_bpp == 1)
258 ok_(__FILE__, line)(info.hbmColor == 0, "info.hbmColor should be NULL\n");
260 if (info.hbmColor)
262 HDC hdc;
263 UINT display_bpp;
265 hdc = GetDC(0);
266 display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
267 ReleaseDC(0, hdc);
269 ret = GetObject(info.hbmColor, sizeof(bmColor), &bmColor);
270 ok_(__FILE__, line)(ret == sizeof(bmColor), "GetObject(info.hbmColor) failed, ret %u\n", ret);
272 ok_(__FILE__, line)(bmColor.bmBitsPixel == display_bpp /* XP */ ||
273 bmColor.bmBitsPixel == exp_bpp /* Win98 */,
274 "bmColor.bmBitsPixel = %d\n", bmColor.bmBitsPixel);
275 ok_(__FILE__, line)(bmColor.bmWidth == exp_cx, "bmColor.bmWidth = %d\n", bmColor.bmWidth);
276 ok_(__FILE__, line)(bmColor.bmHeight == exp_cy, "bmColor.bmHeight = %d\n", bmColor.bmHeight);
278 ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
279 ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
280 ok_(__FILE__, line)(bmMask.bmHeight == exp_cy, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
282 else
284 ok_(__FILE__, line)(bmMask.bmBitsPixel == 1, "bmMask.bmBitsPixel = %d\n", bmMask.bmBitsPixel);
285 ok_(__FILE__, line)(bmMask.bmWidth == exp_cx, "bmMask.bmWidth = %d\n", bmMask.bmWidth);
286 ok_(__FILE__, line)(bmMask.bmHeight == exp_cy * 2, "bmMask.bmHeight = %d\n", bmMask.bmHeight);
290 #define test_icon_info(a,b,c,d) test_icon_info_dbg((a),(b),(c),(d),__LINE__)
292 static void test_CreateIcon(void)
294 static const BYTE bmp_bits[1024];
295 HICON hIcon;
296 HBITMAP hbmMask, hbmColor;
297 ICONINFO info;
298 HDC hdc;
299 UINT display_bpp;
301 hdc = GetDC(0);
302 display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
303 ReleaseDC(0, hdc);
305 /* these crash under XP
306 hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, NULL);
307 hIcon = CreateIcon(0, 16, 16, 1, 1, NULL, bmp_bits);
310 hIcon = CreateIcon(0, 16, 16, 1, 1, bmp_bits, bmp_bits);
311 ok(hIcon != 0, "CreateIcon failed\n");
312 test_icon_info(hIcon, 16, 16, 1);
313 DestroyIcon(hIcon);
315 hIcon = CreateIcon(0, 16, 16, 1, display_bpp, bmp_bits, bmp_bits);
316 ok(hIcon != 0, "CreateIcon failed\n");
317 test_icon_info(hIcon, 16, 16, display_bpp);
318 DestroyIcon(hIcon);
320 hbmMask = CreateBitmap(16, 16, 1, 1, bmp_bits);
321 ok(hbmMask != 0, "CreateBitmap failed\n");
322 hbmColor = CreateBitmap(16, 16, 1, display_bpp, bmp_bits);
323 ok(hbmColor != 0, "CreateBitmap failed\n");
325 info.fIcon = TRUE;
326 info.xHotspot = 8;
327 info.yHotspot = 8;
328 info.hbmMask = 0;
329 info.hbmColor = 0;
330 SetLastError(0xdeadbeaf);
331 hIcon = CreateIconIndirect(&info);
332 ok(!hIcon, "CreateIconIndirect should fail\n");
333 ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
335 info.fIcon = TRUE;
336 info.xHotspot = 8;
337 info.yHotspot = 8;
338 info.hbmMask = 0;
339 info.hbmColor = hbmColor;
340 SetLastError(0xdeadbeaf);
341 hIcon = CreateIconIndirect(&info);
342 ok(!hIcon, "CreateIconIndirect should fail\n");
343 ok(GetLastError() == 0xdeadbeaf, "wrong error %u\n", GetLastError());
345 info.fIcon = TRUE;
346 info.xHotspot = 8;
347 info.yHotspot = 8;
348 info.hbmMask = hbmMask;
349 info.hbmColor = hbmColor;
350 hIcon = CreateIconIndirect(&info);
351 ok(hIcon != 0, "CreateIconIndirect failed\n");
352 test_icon_info(hIcon, 16, 16, display_bpp);
353 DestroyIcon(hIcon);
355 DeleteObject(hbmMask);
356 DeleteObject(hbmColor);
358 hbmMask = CreateBitmap(16, 32, 1, 1, bmp_bits);
359 ok(hbmMask != 0, "CreateBitmap failed\n");
361 info.fIcon = TRUE;
362 info.xHotspot = 8;
363 info.yHotspot = 8;
364 info.hbmMask = hbmMask;
365 info.hbmColor = 0;
366 SetLastError(0xdeadbeaf);
367 hIcon = CreateIconIndirect(&info);
368 ok(hIcon != 0, "CreateIconIndirect failed\n");
369 test_icon_info(hIcon, 16, 16, 1);
370 DestroyIcon(hIcon);
372 DeleteObject(hbmMask);
373 DeleteObject(hbmColor);
376 static void test_DestroyCursor(void)
378 static const BYTE bmp_bits[4096];
379 ICONINFO cursorInfo;
380 HCURSOR cursor, cursor2;
381 BOOL ret;
382 DWORD error;
383 UINT display_bpp;
384 HDC hdc;
386 hdc = GetDC(0);
387 display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
388 ReleaseDC(0, hdc);
390 cursorInfo.fIcon = FALSE;
391 cursorInfo.xHotspot = 0;
392 cursorInfo.yHotspot = 0;
393 cursorInfo.hbmMask = CreateBitmap(32, 32, 1, 1, bmp_bits);
394 cursorInfo.hbmColor = CreateBitmap(32, 32, 1, display_bpp, bmp_bits);
396 cursor = CreateIconIndirect(&cursorInfo);
397 ok(cursor != NULL, "CreateIconIndirect returned %p\n", cursor);
398 if(!cursor) {
399 return;
401 SetCursor(cursor);
403 SetLastError(0xdeadbeef);
404 ret = DestroyCursor(cursor);
405 ok(!ret, "DestroyCursor on the active cursor succeeded\n");
406 error = GetLastError();
407 ok(error == 0xdeadbeef, "Last error: %u\n", error);
409 cursor2 = GetCursor();
410 ok(cursor2 == cursor, "Active was set to %p when trying to destroy it\n", cursor2);
412 SetCursor(NULL);
414 /* Trying to destroy the cursor properly fails now for some reason with ERROR_INVALID_CURSOR_HANDLE */
415 ret = DestroyCursor(cursor);
416 /* ok(ret, "DestroyCursor failed, GetLastError=%d\n", GetLastError()); */
418 DeleteObject(cursorInfo.hbmMask);
419 DeleteObject(cursorInfo.hbmColor);
422 START_TEST(cursoricon)
424 test_CopyImage_Bitmap(1);
425 test_CopyImage_Bitmap(4);
426 test_CopyImage_Bitmap(8);
427 test_CopyImage_Bitmap(16);
428 test_CopyImage_Bitmap(24);
429 test_CopyImage_Bitmap(32);
430 test_CreateIcon();
431 test_DestroyCursor();