ddraw: Check the validy of IDirectDrawSurface::BltFast parameters.
[wine] / dlls / user32 / tests / cursoricon.c
1 /*
2  * Unit test suite for cursors and icons.
3  *
4  * Copyright 2006 Michael Kaufmann
5  * Copyright 2007 Dmitry Timoshkov
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <assert.h>
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 static void test_CopyImage_Check(HBITMAP bitmap, UINT flags, INT copyWidth, INT copyHeight,
35                                   INT expectedWidth, INT expectedHeight, WORD expectedDepth, BOOL dibExpected)
36 {
37     HBITMAP copy;
38     BITMAP origBitmap;
39     BITMAP copyBitmap;
40     BOOL orig_is_dib;
41     BOOL copy_is_dib;
42
43     copy = (HBITMAP) CopyImage(bitmap, IMAGE_BITMAP, copyWidth, copyHeight, flags);
44     ok(copy != NULL, "CopyImage() failed\n");
45     if (copy != NULL)
46     {
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);
51
52         if (copy_is_dib && dibExpected
53             && copyBitmap.bmBitsPixel == 24
54             && (expectedDepth == 16 || expectedDepth == 32))
55         {
56             /* Windows 95 doesn't create DIBs with a depth of 16 or 32 bit */
57             if (GetVersion() & 0x80000000)
58             {
59                 expectedDepth = 24;
60             }
61         }
62
63         if (copy_is_dib && !dibExpected && !(flags & LR_CREATEDIBSECTION))
64         {
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;
71         }
72
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);
82
83         DeleteObject(copy);
84     }
85 }
86
87 static void test_CopyImage_Bitmap(int depth)
88 {
89     HBITMAP ddb, dib;
90     HDC screenDC;
91     BITMAPINFO * info;
92     VOID * bits;
93     int screen_depth;
94     unsigned int i;
95
96     /* Create a device-independent bitmap (DIB) */
97     info = (BITMAPINFO *) 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;
104
105     for (i=0; i < 256; i++)
106     {
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;
111     }
112
113     dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
114
115     /* Create a device-dependent bitmap (DDB) */
116     screenDC = GetDC(NULL);
117     screen_depth = GetDeviceCaps(screenDC, BITSPIXEL);
118     if (depth == 1 || depth == screen_depth)
119     {
120         ddb = CreateBitmap(2, 2, 1, depth, NULL);
121     }
122     else
123     {
124         ddb = NULL;
125     }
126     ReleaseDC(NULL, screenDC);
127
128     if (ddb != NULL)
129     {
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);
134
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);
139
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);
144
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);
150
151         DeleteObject(ddb);
152     }
153
154     if (depth != 1)
155     {
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);
160     }
161
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);
166
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);
171
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);
177
178     DeleteObject(dib);
179
180     if (depth == 1)
181     {
182         /* Special case: A monochrome DIB is converted to a monochrome DDB if
183            the colors in the color table are black and white.
184
185            Skip this test on Windows 95, it always creates a monochrome DDB
186            in this case */
187
188         if (!(GetVersion() & 0x80000000))
189         {
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;
197
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);
204
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;
212
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);
219
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;
227
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);
234         }
235     }
236
237     HeapFree(GetProcessHeap(), 0, info);
238 }
239
240 static void test_icon_info_dbg(HICON hIcon, UINT exp_cx, UINT exp_cy, UINT exp_bpp, int line)
241 {
242     ICONINFO info;
243     DWORD ret;
244     BITMAP bmMask, bmColor;
245
246     ret = GetIconInfo(hIcon, &info);
247     ok_(__FILE__, line)(ret, "GetIconInfo failed\n");
248
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");
253
254     ret = GetObject(info.hbmMask, sizeof(bmMask), &bmMask);
255     ok_(__FILE__, line)(ret == sizeof(bmMask), "GetObject(info.hbmMask) failed, ret %u\n", ret);
256
257     if (exp_bpp == 1)
258         ok_(__FILE__, line)(info.hbmColor == 0, "info.hbmColor should be NULL\n");
259
260     if (info.hbmColor)
261     {
262         HDC hdc;
263         UINT display_bpp;
264
265         hdc = GetDC(0);
266         display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
267         ReleaseDC(0, hdc);
268
269         ret = GetObject(info.hbmColor, sizeof(bmColor), &bmColor);
270         ok_(__FILE__, line)(ret == sizeof(bmColor), "GetObject(info.hbmColor) failed, ret %u\n", ret);
271
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);
277
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);
281     }
282     else
283     {
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);
287     }
288 }
289
290 #define test_icon_info(a,b,c,d) test_icon_info_dbg((a),(b),(c),(d),__LINE__)
291
292 static void test_CreateIcon(void)
293 {
294     static const BYTE bmp_bits[1024];
295     HICON hIcon;
296     HBITMAP hbmMask, hbmColor;
297     ICONINFO info;
298     HDC hdc;
299     UINT display_bpp;
300
301     hdc = GetDC(0);
302     display_bpp = GetDeviceCaps(hdc, BITSPIXEL);
303     ReleaseDC(0, hdc);
304
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);
308     */
309
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);
314
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);
319
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");
324
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());
334
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());
344
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);
354
355     DeleteObject(hbmMask);
356     DeleteObject(hbmColor);
357
358     hbmMask = CreateBitmap(16, 32, 1, 1, bmp_bits);
359     ok(hbmMask != 0, "CreateBitmap failed\n");
360
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);
371
372     DeleteObject(hbmMask);
373     DeleteObject(hbmColor);
374 }
375
376 START_TEST(cursoricon)
377 {
378     test_CopyImage_Bitmap(1);
379     test_CopyImage_Bitmap(4);
380     test_CopyImage_Bitmap(8);
381     test_CopyImage_Bitmap(16);
382     test_CopyImage_Bitmap(24);
383     test_CopyImage_Bitmap(32);
384     test_CreateIcon();
385 }