push 22b3e00525a9a3743634eb8f21ffe1bf98bf885e
[wine/hacks.git] / dlls / gdi32 / tests / bitmap.c
blobbfbeee05670a51fb4faa88bf348b47bbc3f4d314
1 /*
2 * Unit test suite for bitmaps
4 * Copyright 2004 Huw Davies
5 * Copyright 2006 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 <stdarg.h>
23 #include <assert.h>
24 #include <string.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winerror.h"
29 #include "wingdi.h"
30 #include "winuser.h"
31 #include "mmsystem.h"
33 #include "wine/test.h"
35 static BOOL (WINAPI *pGdiAlphaBlend)(HDC,int,int,int,int,HDC,int,int,int,int,BLENDFUNCTION);
37 #define expect_eq(expr, value, type, format) { type ret = (expr); ok((value) == ret, #expr " expected " format " got " format "\n", value, ret); }
39 static BOOL is_win9x;
41 static INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
43 switch(bpp)
45 case 1:
46 return 2 * ((bmWidth+15) >> 4);
48 case 24:
49 bmWidth *= 3; /* fall through */
50 case 8:
51 return bmWidth + (bmWidth & 1);
53 case 32:
54 return bmWidth * 4;
56 case 16:
57 case 15:
58 return bmWidth * 2;
60 case 4:
61 return 2 * ((bmWidth+3) >> 2);
63 default:
64 trace("Unknown depth %d, please report.\n", bpp );
65 assert(0);
67 return -1;
70 static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih)
72 BITMAP bm;
73 BITMAP bma[2];
74 INT ret, width_bytes;
75 BYTE buf[512], buf_cmp[512];
76 DWORD gle;
78 ret = GetObject(hbm, sizeof(bm), &bm);
79 ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
81 ok(bm.bmType == 0 || broken(bm.bmType == 21072 /* Win9x */), "wrong bm.bmType %d\n", bm.bmType);
82 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
83 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
84 width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
85 ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes);
86 ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
87 ok(bm.bmBitsPixel == expected_depth, "wrong bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, expected_depth);
88 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
90 assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
91 assert(sizeof(buf) == sizeof(buf_cmp));
93 SetLastError(0xdeadbeef);
94 ret = GetBitmapBits(hbm, 0, NULL);
95 gle=GetLastError();
96 ok(ret == bm.bmWidthBytes * bm.bmHeight || (ret == 0 && gle == ERROR_INVALID_PARAMETER /* Win9x */), "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
98 memset(buf_cmp, 0xAA, sizeof(buf_cmp));
99 memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
101 memset(buf, 0xAA, sizeof(buf));
102 ret = GetBitmapBits(hbm, sizeof(buf), buf);
103 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
104 ok(!memcmp(buf, buf_cmp, sizeof(buf)) ||
105 broken(memcmp(buf, buf_cmp, sizeof(buf))), /* win9x doesn't init the bitmap bits */
106 "buffers do not match, depth %d\n", bmih->biBitCount);
108 /* test various buffer sizes for GetObject */
109 ret = GetObject(hbm, sizeof(*bma) * 2, bma);
110 ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret);
112 ret = GetObject(hbm, sizeof(bm) / 2, &bm);
113 ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
115 ret = GetObject(hbm, 0, &bm);
116 ok(ret == 0, "%d != 0\n", ret);
118 ret = GetObject(hbm, 1, &bm);
119 ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
121 /* Don't trust Win9x not to try to write to NULL */
122 if (ret == 0)
124 ret = GetObject(hbm, 0, NULL);
125 ok(ret == sizeof(bm), "wrong size %d\n", ret);
129 static void test_createdibitmap(void)
131 HDC hdc, hdcmem;
132 BITMAPINFOHEADER bmih;
133 BITMAPINFO bm;
134 HBITMAP hbm, hbm_colour, hbm_old;
135 INT screen_depth;
136 DWORD pixel;
138 hdc = GetDC(0);
139 screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
140 memset(&bmih, 0, sizeof(bmih));
141 bmih.biSize = sizeof(bmih);
142 bmih.biWidth = 10;
143 bmih.biHeight = 10;
144 bmih.biPlanes = 1;
145 bmih.biBitCount = 32;
146 bmih.biCompression = BI_RGB;
148 /* First create an un-initialised bitmap. The depth of the bitmap
149 should match that of the hdc and not that supplied in bmih.
152 /* First try 32 bits */
153 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
154 ok(hbm != NULL, "CreateDIBitmap failed\n");
155 test_bitmap_info(hbm, screen_depth, &bmih);
156 DeleteObject(hbm);
158 /* Then 16 */
159 bmih.biBitCount = 16;
160 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
161 ok(hbm != NULL, "CreateDIBitmap failed\n");
162 test_bitmap_info(hbm, screen_depth, &bmih);
163 DeleteObject(hbm);
165 /* Then 1 */
166 bmih.biBitCount = 1;
167 hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
168 ok(hbm != NULL, "CreateDIBitmap failed\n");
169 test_bitmap_info(hbm, screen_depth, &bmih);
170 DeleteObject(hbm);
172 /* Now with a monochrome dc we expect a monochrome bitmap */
173 hdcmem = CreateCompatibleDC(hdc);
175 /* First try 32 bits */
176 bmih.biBitCount = 32;
177 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
178 ok(hbm != NULL, "CreateDIBitmap failed\n");
179 test_bitmap_info(hbm, 1, &bmih);
180 DeleteObject(hbm);
182 /* Then 16 */
183 bmih.biBitCount = 16;
184 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
185 ok(hbm != NULL, "CreateDIBitmap failed\n");
186 test_bitmap_info(hbm, 1, &bmih);
187 DeleteObject(hbm);
189 /* Then 1 */
190 bmih.biBitCount = 1;
191 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
192 ok(hbm != NULL, "CreateDIBitmap failed\n");
193 test_bitmap_info(hbm, 1, &bmih);
194 DeleteObject(hbm);
196 /* Now select a polychrome bitmap into the dc and we expect
197 screen_depth bitmaps again */
198 hbm_colour = CreateCompatibleBitmap(hdc, bmih.biWidth, bmih.biHeight);
199 test_bitmap_info(hbm_colour, screen_depth, &bmih);
200 hbm_old = SelectObject(hdcmem, hbm_colour);
202 /* First try 32 bits */
203 bmih.biBitCount = 32;
204 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
205 ok(hbm != NULL, "CreateDIBitmap failed\n");
206 test_bitmap_info(hbm, screen_depth, &bmih);
207 DeleteObject(hbm);
209 /* Then 16 */
210 bmih.biBitCount = 16;
211 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
212 ok(hbm != NULL, "CreateDIBitmap failed\n");
213 test_bitmap_info(hbm, screen_depth, &bmih);
214 DeleteObject(hbm);
216 /* Then 1 */
217 bmih.biBitCount = 1;
218 hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
219 ok(hbm != NULL, "CreateDIBitmap failed\n");
220 test_bitmap_info(hbm, screen_depth, &bmih);
221 DeleteObject(hbm);
223 SelectObject(hdcmem, hbm_old);
224 DeleteObject(hbm_colour);
225 DeleteDC(hdcmem);
227 /* If hdc == 0 then we get a 1 bpp bitmap */
228 if (!is_win9x) {
229 bmih.biBitCount = 32;
230 hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0);
231 ok(hbm != NULL, "CreateDIBitmap failed\n");
232 test_bitmap_info(hbm, 1, &bmih);
233 DeleteObject(hbm);
236 /* Test how formats are converted */
237 pixel = 0xffffffff;
238 bmih.biBitCount = 1;
239 bmih.biWidth = 1;
240 bmih.biHeight = 1;
242 memset(&bm, 0, sizeof(bm));
243 bm.bmiHeader.biSize = sizeof(bm.bmiHeader);
244 bm.bmiHeader.biWidth = 1;
245 bm.bmiHeader.biHeight = 1;
246 bm.bmiHeader.biPlanes = 1;
247 bm.bmiHeader.biBitCount= 24;
248 bm.bmiHeader.biCompression= BI_RGB;
249 bm.bmiHeader.biSizeImage = 0;
250 hbm = CreateDIBitmap(hdc, &bmih, CBM_INIT, &pixel, &bm, DIB_RGB_COLORS);
251 ok(hbm != NULL, "CreateDIBitmap failed\n");
253 pixel = 0xdeadbeef;
254 bm.bmiHeader.biBitCount= 32;
255 GetDIBits(hdc, hbm, 0, 1, &pixel, &bm, DIB_RGB_COLORS);
256 ok(pixel == 0x00ffffff, "Reading a 32 bit pixel from a DDB returned %08x\n", pixel);
257 DeleteObject(hbm);
259 ReleaseDC(0, hdc);
262 static INT DIB_GetWidthBytes( int width, int bpp )
264 int words;
266 switch (bpp)
268 case 1: words = (width + 31) / 32; break;
269 case 4: words = (width + 7) / 8; break;
270 case 8: words = (width + 3) / 4; break;
271 case 15:
272 case 16: words = (width + 1) / 2; break;
273 case 24: words = (width * 3 + 3)/4; break;
274 case 32: words = width; break;
276 default:
277 words=0;
278 trace("Unknown depth %d, please report.\n", bpp );
279 assert(0);
280 break;
282 return 4 * words;
285 static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih)
287 BITMAP bm;
288 BITMAP bma[2];
289 DIBSECTION ds;
290 DIBSECTION dsa[2];
291 INT ret, bm_width_bytes, dib_width_bytes;
292 BYTE *buf;
294 ret = GetObject(hbm, sizeof(bm), &bm);
295 ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
297 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
298 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
299 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
300 dib_width_bytes = DIB_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
301 bm_width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
302 if (bm.bmWidthBytes != dib_width_bytes) /* Win2k bug */
303 ok(bm.bmWidthBytes == bm_width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, bm_width_bytes);
304 else
305 ok(bm.bmWidthBytes == dib_width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, dib_width_bytes);
306 ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
307 ok(bm.bmBitsPixel == bmih->biBitCount, "bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, bmih->biBitCount);
308 ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
310 buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096);
312 /* GetBitmapBits returns not 32-bit aligned data */
313 SetLastError(0xdeadbeef);
314 ret = GetBitmapBits(hbm, 0, NULL);
315 ok(ret == bm_width_bytes * bm.bmHeight ||
316 broken(ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER), /* Win9x */
317 "%d != %d\n", ret, bm_width_bytes * bm.bmHeight);
319 memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096);
320 ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf);
321 ok(ret == bm_width_bytes * bm.bmHeight, "%d != %d\n", ret, bm_width_bytes * bm.bmHeight);
323 HeapFree(GetProcessHeap(), 0, buf);
325 /* test various buffer sizes for GetObject */
326 memset(&ds, 0xAA, sizeof(ds));
327 ret = GetObject(hbm, sizeof(*bma) * 2, bma);
328 ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret);
329 ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
330 ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
331 ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
333 ret = GetObject(hbm, sizeof(bm) / 2, &bm);
334 ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
336 ret = GetObject(hbm, 0, &bm);
337 ok(ret == 0, "%d != 0\n", ret);
339 ret = GetObject(hbm, 1, &bm);
340 ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
342 /* test various buffer sizes for GetObject */
343 ret = GetObject(hbm, 0, NULL);
344 ok(ret == sizeof(bm) || broken(ret == sizeof(DIBSECTION) /* Win9x */), "wrong size %d\n", ret);
346 ret = GetObject(hbm, sizeof(*dsa) * 2, dsa);
347 ok(ret == sizeof(*dsa) || broken(ret == sizeof(*dsa) * 2 /* Win9x */), "wrong size %d\n", ret);
349 memset(&ds, 0xAA, sizeof(ds));
350 ret = GetObject(hbm, sizeof(ds), &ds);
351 ok(ret == sizeof(ds), "wrong size %d\n", ret);
353 ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits, bits);
354 if (ds.dsBm.bmWidthBytes != bm_width_bytes) /* Win2k bug */
355 ok(ds.dsBmih.biSizeImage == ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight, "%u != %u\n",
356 ds.dsBmih.biSizeImage, ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight);
357 ok(bmih->biSizeImage == 0, "%u != 0\n", bmih->biSizeImage);
358 ds.dsBmih.biSizeImage = 0;
360 ok(ds.dsBmih.biSize == bmih->biSize, "%u != %u\n", ds.dsBmih.biSize, bmih->biSize);
361 ok(ds.dsBmih.biWidth == bmih->biWidth, "%u != %u\n", ds.dsBmih.biWidth, bmih->biWidth);
362 ok(ds.dsBmih.biHeight == bmih->biHeight, "%u != %u\n", ds.dsBmih.biHeight, bmih->biHeight);
363 ok(ds.dsBmih.biPlanes == bmih->biPlanes, "%u != %u\n", ds.dsBmih.biPlanes, bmih->biPlanes);
364 ok(ds.dsBmih.biBitCount == bmih->biBitCount, "%u != %u\n", ds.dsBmih.biBitCount, bmih->biBitCount);
365 ok(ds.dsBmih.biCompression == bmih->biCompression, "%u != %u\n", ds.dsBmih.biCompression, bmih->biCompression);
366 ok(ds.dsBmih.biSizeImage == bmih->biSizeImage, "%u != %u\n", ds.dsBmih.biSizeImage, bmih->biSizeImage);
367 ok(ds.dsBmih.biXPelsPerMeter == bmih->biXPelsPerMeter, "%u != %u\n", ds.dsBmih.biXPelsPerMeter, bmih->biXPelsPerMeter);
368 ok(ds.dsBmih.biYPelsPerMeter == bmih->biYPelsPerMeter, "%u != %u\n", ds.dsBmih.biYPelsPerMeter, bmih->biYPelsPerMeter);
370 memset(&ds, 0xAA, sizeof(ds));
371 ret = GetObject(hbm, sizeof(ds) - 4, &ds);
372 ok(ret == sizeof(ds.dsBm) || broken(ret == (sizeof(ds) - 4) /* Win9x */), "wrong size %d\n", ret);
373 ok(ds.dsBm.bmWidth == bmih->biWidth, "%u != %u\n", ds.dsBmih.biWidth, bmih->biWidth);
374 ok(ds.dsBm.bmHeight == bmih->biHeight, "%u != %u\n", ds.dsBmih.biHeight, bmih->biHeight);
375 ok(ds.dsBm.bmBits == bits, "%p != %p\n", ds.dsBm.bmBits, bits);
377 ret = GetObject(hbm, 0, &ds);
378 ok(ret == 0, "%d != 0\n", ret);
380 ret = GetObject(hbm, 1, &ds);
381 ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
384 #define test_color_todo(got, exp, txt, todo) \
385 if (!todo && got != exp && screen_depth < 24) { \
386 todo_wine ok(0, #txt " failed at %d-bit screen depth: got 0x%06x expected 0x%06x - skipping DIB tests\n", \
387 screen_depth, (UINT)got, (UINT)exp); \
388 return; \
389 } else if (todo) todo_wine { ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp); } \
390 else ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp) \
392 #define test_color(hdc, color, exp, todo_setp, todo_getp) \
394 COLORREF c; \
395 c = SetPixel(hdc, 0, 0, color); \
396 if (!is_win9x) { test_color_todo(c, exp, SetPixel, todo_setp); } \
397 c = GetPixel(hdc, 0, 0); \
398 test_color_todo(c, exp, GetPixel, todo_getp); \
401 static void test_dib_bits_access( HBITMAP hdib, void *bits )
403 MEMORY_BASIC_INFORMATION info;
404 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
405 DWORD data[256];
406 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
407 HDC hdc = GetDC(0);
408 char filename[MAX_PATH];
409 HANDLE file;
410 DWORD written;
411 INT ret;
413 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
414 "VirtualQuery failed\n");
415 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
416 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
417 ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
418 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
419 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
420 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
422 memset( pbmi, 0, sizeof(bmibuf) );
423 memset( data, 0xcc, sizeof(data) );
424 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
425 pbmi->bmiHeader.biHeight = 16;
426 pbmi->bmiHeader.biWidth = 16;
427 pbmi->bmiHeader.biBitCount = 32;
428 pbmi->bmiHeader.biPlanes = 1;
429 pbmi->bmiHeader.biCompression = BI_RGB;
431 ret = SetDIBits( hdc, hdib, 0, 16, data, pbmi, DIB_RGB_COLORS );
432 ok(ret == 16 ||
433 broken(ret == 0), /* win9x */
434 "SetDIBits failed: expected 16 got %d\n", ret);
436 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
437 "VirtualQuery failed\n");
438 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
439 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
440 ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
441 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
442 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
443 /* it has been protected now */
444 todo_wine ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
446 /* try writing protected bits to a file */
448 GetTempFileNameA( ".", "dib", 0, filename );
449 file = CreateFileA( filename, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
450 CREATE_ALWAYS, 0, 0 );
451 ok( file != INVALID_HANDLE_VALUE, "failed to open %s error %u\n", filename, GetLastError() );
452 ret = WriteFile( file, bits, 8192, &written, NULL );
453 ok( ret, "WriteFile failed error %u\n", GetLastError() );
454 if (ret) ok( written == 8192, "only wrote %u bytes\n", written );
455 CloseHandle( file );
456 DeleteFileA( filename );
459 static void test_dibsections(void)
461 HDC hdc, hdcmem, hdcmem2;
462 HBITMAP hdib, oldbm, hdib2, oldbm2;
463 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
464 char bcibuf[sizeof(BITMAPCOREINFO) + 256 * sizeof(RGBTRIPLE)];
465 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
466 BITMAPCOREINFO *pbci = (BITMAPCOREINFO *)bcibuf;
467 HBITMAP hcoredib;
468 char coreBits[256];
469 BYTE *bits;
470 RGBQUAD rgb[256];
471 int ret;
472 char logpalbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
473 LOGPALETTE *plogpal = (LOGPALETTE*)logpalbuf;
474 WORD *index;
475 DWORD *bits32;
476 HPALETTE hpal, oldpal;
477 DIBSECTION dibsec;
478 COLORREF c0, c1;
479 int i;
480 int screen_depth;
481 MEMORY_BASIC_INFORMATION info;
483 hdc = GetDC(0);
484 screen_depth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
486 memset(pbmi, 0, sizeof(bmibuf));
487 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
488 pbmi->bmiHeader.biHeight = 100;
489 pbmi->bmiHeader.biWidth = 512;
490 pbmi->bmiHeader.biBitCount = 24;
491 pbmi->bmiHeader.biPlanes = 1;
492 pbmi->bmiHeader.biCompression = BI_RGB;
494 SetLastError(0xdeadbeef);
496 /* invalid pointer for BITMAPINFO
497 (*bits should be NULL on error) */
498 bits = (BYTE*)0xdeadbeef;
499 hdib = CreateDIBSection(hdc, NULL, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
500 ok(hdib == NULL && bits == NULL, "CreateDIBSection failed for invalid parameter: bmi == 0x0\n");
502 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
503 ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
504 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
505 ok(dibsec.dsBm.bmBits == bits, "dibsec.dsBits %p != bits %p\n", dibsec.dsBm.bmBits, bits);
507 /* test the DIB memory */
508 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
509 "VirtualQuery failed\n");
510 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
511 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
512 ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
513 ok(info.RegionSize == 0x26000, "0x%lx != 0x26000\n", info.RegionSize);
514 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
515 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
516 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
518 test_dib_bits_access( hdib, bits );
520 test_dib_info(hdib, bits, &pbmi->bmiHeader);
521 DeleteObject(hdib);
523 pbmi->bmiHeader.biBitCount = 8;
524 pbmi->bmiHeader.biCompression = BI_RLE8;
525 SetLastError(0xdeadbeef);
526 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
527 ok(hdib == NULL, "CreateDIBSection should fail when asked to create a compressed DIB section\n");
528 ok(GetLastError() == 0xdeadbeef, "wrong error %d\n", GetLastError());
530 pbmi->bmiHeader.biBitCount = 16;
531 pbmi->bmiHeader.biCompression = BI_BITFIELDS;
532 ((PDWORD)pbmi->bmiColors)[0] = 0xf800;
533 ((PDWORD)pbmi->bmiColors)[1] = 0x07e0;
534 ((PDWORD)pbmi->bmiColors)[2] = 0x001f;
535 SetLastError(0xdeadbeef);
536 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
537 ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
539 /* test the DIB memory */
540 ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
541 "VirtualQuery failed\n");
542 ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
543 ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
544 ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
545 ok(info.RegionSize == 0x19000, "0x%lx != 0x19000\n", info.RegionSize);
546 ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
547 ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
548 ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
550 test_dib_info(hdib, bits, &pbmi->bmiHeader);
551 DeleteObject(hdib);
553 memset(pbmi, 0, sizeof(bmibuf));
554 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
555 pbmi->bmiHeader.biHeight = 16;
556 pbmi->bmiHeader.biWidth = 16;
557 pbmi->bmiHeader.biBitCount = 1;
558 pbmi->bmiHeader.biPlanes = 1;
559 pbmi->bmiHeader.biCompression = BI_RGB;
560 pbmi->bmiColors[0].rgbRed = 0xff;
561 pbmi->bmiColors[0].rgbGreen = 0;
562 pbmi->bmiColors[0].rgbBlue = 0;
563 pbmi->bmiColors[1].rgbRed = 0;
564 pbmi->bmiColors[1].rgbGreen = 0;
565 pbmi->bmiColors[1].rgbBlue = 0xff;
567 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
568 ok(hdib != NULL, "CreateDIBSection failed\n");
569 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
570 ok(dibsec.dsBmih.biClrUsed == 2,
571 "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
573 /* Test if the old BITMAPCOREINFO structure is supported */
575 pbci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
576 pbci->bmciHeader.bcBitCount = 0;
578 if (!is_win9x) {
579 ret = GetDIBits(hdc, hdib, 0, 16, NULL, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
580 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
581 ok((pbci->bmciHeader.bcWidth == 16) && (pbci->bmciHeader.bcHeight == 16)
582 && (pbci->bmciHeader.bcBitCount == 1) && (pbci->bmciHeader.bcPlanes == 1),
583 "GetDIBits did't fill in the BITMAPCOREHEADER structure properly\n");
585 ret = GetDIBits(hdc, hdib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
586 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
587 ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
588 (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
589 (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
590 "The color table has not been translated to the old BITMAPCOREINFO format\n");
592 hcoredib = CreateDIBSection(hdc, (BITMAPINFO*) pbci, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
593 ok(hcoredib != NULL, "CreateDIBSection failed with a BITMAPCOREINFO\n");
595 ZeroMemory(pbci->bmciColors, 256 * sizeof(RGBTRIPLE));
596 ret = GetDIBits(hdc, hcoredib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
597 ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
598 ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
599 (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
600 (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
601 "The color table has not been translated to the old BITMAPCOREINFO format\n");
603 DeleteObject(hcoredib);
606 hdcmem = CreateCompatibleDC(hdc);
607 oldbm = SelectObject(hdcmem, hdib);
609 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
610 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
611 ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
612 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
613 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
614 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
616 c0 = RGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen, pbmi->bmiColors[0].rgbBlue);
617 c1 = RGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen, pbmi->bmiColors[1].rgbBlue);
619 test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
620 test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
621 test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
622 test_color(hdcmem, PALETTEINDEX(0), c0, 1, 1);
623 test_color(hdcmem, PALETTEINDEX(1), c0, 1, 1);
624 test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
625 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen,
626 pbmi->bmiColors[0].rgbBlue), c0, 1, 1);
627 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen,
628 pbmi->bmiColors[1].rgbBlue), c1, 1, 1);
629 test_color(hdcmem, PALETTERGB(0, 0, 0), c0, 1, 1);
630 test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
631 test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c1, 1, 1);
633 SelectObject(hdcmem, oldbm);
634 DeleteObject(hdib);
636 pbmi->bmiColors[0].rgbRed = 0xff;
637 pbmi->bmiColors[0].rgbGreen = 0xff;
638 pbmi->bmiColors[0].rgbBlue = 0xff;
639 pbmi->bmiColors[1].rgbRed = 0;
640 pbmi->bmiColors[1].rgbGreen = 0;
641 pbmi->bmiColors[1].rgbBlue = 0;
643 hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
644 ok(hdib != NULL, "CreateDIBSection failed\n");
646 test_dib_info(hdib, bits, &pbmi->bmiHeader);
648 oldbm = SelectObject(hdcmem, hdib);
650 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
651 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
652 ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
653 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
654 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
655 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
657 SelectObject(hdcmem, oldbm);
658 test_dib_info(hdib, bits, &pbmi->bmiHeader);
659 DeleteObject(hdib);
661 pbmi->bmiHeader.biBitCount = 4;
662 for (i = 0; i < 16; i++) {
663 pbmi->bmiColors[i].rgbRed = i;
664 pbmi->bmiColors[i].rgbGreen = 16-i;
665 pbmi->bmiColors[i].rgbBlue = 0;
667 hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
668 ok(hdib != NULL, "CreateDIBSection failed\n");
669 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
670 ok(dibsec.dsBmih.biClrUsed == 16,
671 "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 16);
672 test_dib_info(hdib, bits, &pbmi->bmiHeader);
673 DeleteObject(hdib);
675 pbmi->bmiHeader.biBitCount = 8;
677 for (i = 0; i < 128; i++) {
678 pbmi->bmiColors[i].rgbRed = 255 - i * 2;
679 pbmi->bmiColors[i].rgbGreen = i * 2;
680 pbmi->bmiColors[i].rgbBlue = 0;
681 pbmi->bmiColors[255 - i].rgbRed = 0;
682 pbmi->bmiColors[255 - i].rgbGreen = i * 2;
683 pbmi->bmiColors[255 - i].rgbBlue = 255 - i * 2;
685 hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
686 ok(hdib != NULL, "CreateDIBSection failed\n");
687 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
688 ok(dibsec.dsBmih.biClrUsed == 256,
689 "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
691 oldbm = SelectObject(hdcmem, hdib);
693 for (i = 0; i < 256; i++) {
694 test_color(hdcmem, DIBINDEX(i),
695 RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
696 test_color(hdcmem, PALETTERGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue),
697 RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
700 SelectObject(hdcmem, oldbm);
701 test_dib_info(hdib, bits, &pbmi->bmiHeader);
702 DeleteObject(hdib);
704 pbmi->bmiHeader.biBitCount = 1;
706 /* Now create a palette and a palette indexed dib section */
707 memset(plogpal, 0, sizeof(logpalbuf));
708 plogpal->palVersion = 0x300;
709 plogpal->palNumEntries = 2;
710 plogpal->palPalEntry[0].peRed = 0xff;
711 plogpal->palPalEntry[0].peBlue = 0xff;
712 plogpal->palPalEntry[1].peGreen = 0xff;
714 index = (WORD*)pbmi->bmiColors;
715 *index++ = 0;
716 *index = 1;
717 hpal = CreatePalette(plogpal);
718 ok(hpal != NULL, "CreatePalette failed\n");
719 oldpal = SelectPalette(hdc, hpal, TRUE);
720 hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
721 ok(hdib != NULL, "CreateDIBSection failed\n");
722 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
723 ok(dibsec.dsBmih.biClrUsed == 2 ||
724 broken(dibsec.dsBmih.biClrUsed == 0), /* win9x */
725 "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
727 /* The colour table has already been grabbed from the dc, so we select back the
728 old palette */
730 SelectPalette(hdc, oldpal, TRUE);
731 oldbm = SelectObject(hdcmem, hdib);
732 oldpal = SelectPalette(hdcmem, hpal, TRUE);
734 ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
735 ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
736 ok(rgb[0].rgbRed == 0xff && rgb[0].rgbBlue == 0xff && rgb[0].rgbGreen == 0 &&
737 rgb[1].rgbRed == 0 && rgb[1].rgbBlue == 0 && rgb[1].rgbGreen == 0xff,
738 "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
739 rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
740 rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
742 c0 = RGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen, plogpal->palPalEntry[0].peBlue);
743 c1 = RGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen, plogpal->palPalEntry[1].peBlue);
745 test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
746 test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
747 test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
748 test_color(hdcmem, PALETTEINDEX(0), c0, 0, 1);
749 test_color(hdcmem, PALETTEINDEX(1), c1, 0, 1);
750 test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
751 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen,
752 plogpal->palPalEntry[0].peBlue), c0, 1, 1);
753 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen,
754 plogpal->palPalEntry[1].peBlue), c1, 1, 1);
755 test_color(hdcmem, PALETTERGB(0, 0, 0), c1, 1, 1);
756 test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
757 test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c0, 1, 1);
758 test_color(hdcmem, PALETTERGB(0, 1, 0), c1, 1, 1);
759 test_color(hdcmem, PALETTERGB(0x3f, 0, 0x3f), c1, 1, 1);
760 test_color(hdcmem, PALETTERGB(0x40, 0, 0x40), c0, 1, 1);
762 /* Bottom and 2nd row from top green, everything else magenta */
763 bits[0] = bits[1] = 0xff;
764 bits[13 * 4] = bits[13*4 + 1] = 0xff;
766 test_dib_info(hdib, bits, &pbmi->bmiHeader);
768 pbmi->bmiHeader.biBitCount = 32;
770 hdib2 = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, (void **)&bits32, NULL, 0);
771 ok(hdib2 != NULL, "CreateDIBSection failed\n");
772 hdcmem2 = CreateCompatibleDC(hdc);
773 oldbm2 = SelectObject(hdcmem2, hdib2);
775 BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY);
777 ok(bits32[0] == 0xff00, "lower left pixel is %08x\n", bits32[0]);
778 ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08x\n", bits32[17]);
780 SelectObject(hdcmem2, oldbm2);
781 test_dib_info(hdib2, bits32, &pbmi->bmiHeader);
782 DeleteObject(hdib2);
784 SelectObject(hdcmem, oldbm);
785 SelectObject(hdcmem, oldpal);
786 DeleteObject(hdib);
787 DeleteObject(hpal);
790 pbmi->bmiHeader.biBitCount = 8;
792 memset(plogpal, 0, sizeof(logpalbuf));
793 plogpal->palVersion = 0x300;
794 plogpal->palNumEntries = 256;
796 for (i = 0; i < 128; i++) {
797 plogpal->palPalEntry[i].peRed = 255 - i * 2;
798 plogpal->palPalEntry[i].peBlue = i * 2;
799 plogpal->palPalEntry[i].peGreen = 0;
800 plogpal->palPalEntry[255 - i].peRed = 0;
801 plogpal->palPalEntry[255 - i].peGreen = i * 2;
802 plogpal->palPalEntry[255 - i].peBlue = 255 - i * 2;
805 index = (WORD*)pbmi->bmiColors;
806 for (i = 0; i < 256; i++) {
807 *index++ = i;
810 hpal = CreatePalette(plogpal);
811 ok(hpal != NULL, "CreatePalette failed\n");
812 oldpal = SelectPalette(hdc, hpal, TRUE);
813 hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
814 ok(hdib != NULL, "CreateDIBSection failed\n");
815 ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
816 ok(dibsec.dsBmih.biClrUsed == 256 ||
817 broken(dibsec.dsBmih.biClrUsed == 0), /* win9x */
818 "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
820 test_dib_info(hdib, bits, &pbmi->bmiHeader);
822 SelectPalette(hdc, oldpal, TRUE);
823 oldbm = SelectObject(hdcmem, hdib);
824 oldpal = SelectPalette(hdcmem, hpal, TRUE);
826 ret = GetDIBColorTable(hdcmem, 0, 256, rgb);
827 ok(ret == 256, "GetDIBColorTable returned %d\n", ret);
828 for (i = 0; i < 256; i++) {
829 ok(rgb[i].rgbRed == plogpal->palPalEntry[i].peRed &&
830 rgb[i].rgbBlue == plogpal->palPalEntry[i].peBlue &&
831 rgb[i].rgbGreen == plogpal->palPalEntry[i].peGreen,
832 "GetDIBColorTable returns table %d: r%02x g%02x b%02x res%02x\n",
833 i, rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue, rgb[i].rgbReserved);
836 for (i = 0; i < 256; i++) {
837 test_color(hdcmem, DIBINDEX(i),
838 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
839 test_color(hdcmem, PALETTEINDEX(i),
840 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
841 test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue),
842 RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
845 SelectPalette(hdcmem, oldpal, TRUE);
846 SelectObject(hdcmem, oldbm);
847 DeleteObject(hdib);
848 DeleteObject(hpal);
851 DeleteDC(hdcmem);
852 ReleaseDC(0, hdc);
855 static void test_mono_dibsection(void)
857 HDC hdc, memdc;
858 HBITMAP old_bm, mono_ds;
859 char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
860 BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
861 BYTE bits[10 * 4];
862 BYTE *ds_bits;
863 int num;
865 hdc = GetDC(0);
867 memdc = CreateCompatibleDC(hdc);
869 memset(pbmi, 0, sizeof(bmibuf));
870 pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
871 pbmi->bmiHeader.biHeight = 10;
872 pbmi->bmiHeader.biWidth = 10;
873 pbmi->bmiHeader.biBitCount = 1;
874 pbmi->bmiHeader.biPlanes = 1;
875 pbmi->bmiHeader.biCompression = BI_RGB;
876 pbmi->bmiColors[0].rgbRed = 0xff;
877 pbmi->bmiColors[0].rgbGreen = 0xff;
878 pbmi->bmiColors[0].rgbBlue = 0xff;
879 pbmi->bmiColors[1].rgbRed = 0x0;
880 pbmi->bmiColors[1].rgbGreen = 0x0;
881 pbmi->bmiColors[1].rgbBlue = 0x0;
884 * First dib section is 'inverted' ie color[0] is white, color[1] is black
887 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
888 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
889 old_bm = SelectObject(memdc, mono_ds);
891 /* black border, white interior */
892 Rectangle(memdc, 0, 0, 10, 10);
893 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
894 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
896 /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
898 memset(bits, 0, sizeof(bits));
899 bits[0] = 0xaa;
901 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
902 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
904 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
906 pbmi->bmiColors[0].rgbRed = 0x0;
907 pbmi->bmiColors[0].rgbGreen = 0x0;
908 pbmi->bmiColors[0].rgbBlue = 0x0;
909 pbmi->bmiColors[1].rgbRed = 0xff;
910 pbmi->bmiColors[1].rgbGreen = 0xff;
911 pbmi->bmiColors[1].rgbBlue = 0xff;
913 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
914 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
916 SelectObject(memdc, old_bm);
917 DeleteObject(mono_ds);
920 * Next dib section is 'normal' ie color[0] is black, color[1] is white
923 pbmi->bmiColors[0].rgbRed = 0x0;
924 pbmi->bmiColors[0].rgbGreen = 0x0;
925 pbmi->bmiColors[0].rgbBlue = 0x0;
926 pbmi->bmiColors[1].rgbRed = 0xff;
927 pbmi->bmiColors[1].rgbGreen = 0xff;
928 pbmi->bmiColors[1].rgbBlue = 0xff;
930 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
931 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
932 old_bm = SelectObject(memdc, mono_ds);
934 /* black border, white interior */
935 Rectangle(memdc, 0, 0, 10, 10);
936 ok(ds_bits[0] == 0x00, "out_bits %02x\n", ds_bits[0]);
937 ok(ds_bits[4] == 0x7f, "out_bits %02x\n", ds_bits[4]);
939 /* SetDIBitsToDevice with a normal bmi -> normal dib section */
941 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
942 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
944 /* SetDIBitsToDevice with a inverted bmi -> normal dib section */
946 pbmi->bmiColors[0].rgbRed = 0xff;
947 pbmi->bmiColors[0].rgbGreen = 0xff;
948 pbmi->bmiColors[0].rgbBlue = 0xff;
949 pbmi->bmiColors[1].rgbRed = 0x0;
950 pbmi->bmiColors[1].rgbGreen = 0x0;
951 pbmi->bmiColors[1].rgbBlue = 0x0;
953 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
954 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
957 * Take that 'normal' dibsection and change its colour table to an 'inverted' one
960 pbmi->bmiColors[0].rgbRed = 0xff;
961 pbmi->bmiColors[0].rgbGreen = 0xff;
962 pbmi->bmiColors[0].rgbBlue = 0xff;
963 pbmi->bmiColors[1].rgbRed = 0x0;
964 pbmi->bmiColors[1].rgbGreen = 0x0;
965 pbmi->bmiColors[1].rgbBlue = 0x0;
966 num = SetDIBColorTable(memdc, 0, 2, pbmi->bmiColors);
967 ok(num == 2, "num = %d\n", num);
969 /* black border, white interior */
970 Rectangle(memdc, 0, 0, 10, 10);
971 todo_wine {
972 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
973 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
975 /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
977 memset(bits, 0, sizeof(bits));
978 bits[0] = 0xaa;
980 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
981 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
983 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
985 pbmi->bmiColors[0].rgbRed = 0x0;
986 pbmi->bmiColors[0].rgbGreen = 0x0;
987 pbmi->bmiColors[0].rgbBlue = 0x0;
988 pbmi->bmiColors[1].rgbRed = 0xff;
989 pbmi->bmiColors[1].rgbGreen = 0xff;
990 pbmi->bmiColors[1].rgbBlue = 0xff;
992 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
993 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
995 SelectObject(memdc, old_bm);
996 DeleteObject(mono_ds);
999 * Now a dib section with a strange colour map just for fun. This behaves just like an inverted one.
1002 pbmi->bmiColors[0].rgbRed = 0xff;
1003 pbmi->bmiColors[0].rgbGreen = 0x0;
1004 pbmi->bmiColors[0].rgbBlue = 0x0;
1005 pbmi->bmiColors[1].rgbRed = 0xfe;
1006 pbmi->bmiColors[1].rgbGreen = 0x0;
1007 pbmi->bmiColors[1].rgbBlue = 0x0;
1009 mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
1010 ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
1011 old_bm = SelectObject(memdc, mono_ds);
1013 /* black border, white interior */
1014 Rectangle(memdc, 0, 0, 10, 10);
1015 ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
1016 ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
1018 /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
1020 pbmi->bmiColors[0].rgbRed = 0x0;
1021 pbmi->bmiColors[0].rgbGreen = 0x0;
1022 pbmi->bmiColors[0].rgbBlue = 0x0;
1023 pbmi->bmiColors[1].rgbRed = 0xff;
1024 pbmi->bmiColors[1].rgbGreen = 0xff;
1025 pbmi->bmiColors[1].rgbBlue = 0xff;
1027 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
1028 ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
1030 /* SetDIBitsToDevice with a inverted bmi -> inverted dib section */
1032 pbmi->bmiColors[0].rgbRed = 0xff;
1033 pbmi->bmiColors[0].rgbGreen = 0xff;
1034 pbmi->bmiColors[0].rgbBlue = 0xff;
1035 pbmi->bmiColors[1].rgbRed = 0x0;
1036 pbmi->bmiColors[1].rgbGreen = 0x0;
1037 pbmi->bmiColors[1].rgbBlue = 0x0;
1039 SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
1040 ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
1042 SelectObject(memdc, old_bm);
1043 DeleteObject(mono_ds);
1045 DeleteDC(memdc);
1046 ReleaseDC(0, hdc);
1049 static void test_bitmap(void)
1051 char buf[256], buf_cmp[256];
1052 HBITMAP hbmp, hbmp_old;
1053 HDC hdc;
1054 BITMAP bm;
1055 BITMAP bma[2];
1056 INT ret;
1058 hdc = CreateCompatibleDC(0);
1059 assert(hdc != 0);
1061 SetLastError(0xdeadbeef);
1062 hbmp = CreateBitmap(0x7ffffff, 1, 1, 1, NULL);
1063 if (!hbmp)
1065 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY /* XP */ ||
1066 GetLastError() == ERROR_INVALID_PARAMETER /* Win2k */,
1067 "expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1069 else
1070 DeleteObject(hbmp);
1072 SetLastError(0xdeadbeef);
1073 hbmp = CreateBitmap(0x7ffffff, 9, 1, 1, NULL);
1074 if (!hbmp)
1076 ok(GetLastError() == ERROR_NOT_ENOUGH_MEMORY /* XP */ ||
1077 GetLastError() == ERROR_INVALID_PARAMETER /* Win2k */,
1078 "expected ERROR_NOT_ENOUGH_MEMORY, got %u\n", GetLastError());
1080 else
1081 DeleteObject(hbmp);
1083 SetLastError(0xdeadbeef);
1084 hbmp = CreateBitmap(0x7ffffff + 1, 1, 1, 1, NULL);
1085 ok(!hbmp || broken(hbmp != NULL /* Win9x */), "CreateBitmap should fail\n");
1086 if (!hbmp)
1087 ok(GetLastError() == ERROR_INVALID_PARAMETER,
1088 "expected ERROR_INVALID_PARAMETER, got %u\n", GetLastError());
1089 else
1090 DeleteObject(hbmp);
1092 hbmp = CreateBitmap(15, 15, 1, 1, NULL);
1093 assert(hbmp != NULL);
1095 ret = GetObject(hbmp, sizeof(bm), &bm);
1096 ok(ret == sizeof(bm), "wrong size %d\n", ret);
1098 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
1099 ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
1100 ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
1101 ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
1102 ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
1103 ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
1104 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
1106 assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
1107 assert(sizeof(buf) == sizeof(buf_cmp));
1109 ret = GetBitmapBits(hbmp, 0, NULL);
1110 ok(ret == bm.bmWidthBytes * bm.bmHeight || broken(ret == 0 /* Win9x */),
1111 "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
1113 memset(buf_cmp, 0xAA, sizeof(buf_cmp));
1114 memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
1116 memset(buf, 0xAA, sizeof(buf));
1117 ret = GetBitmapBits(hbmp, sizeof(buf), buf);
1118 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
1119 ok(!memcmp(buf, buf_cmp, sizeof(buf)) ||
1120 broken(memcmp(buf, buf_cmp, sizeof(buf))), /* win9x doesn't init the bitmap bits */
1121 "buffers do not match\n");
1123 hbmp_old = SelectObject(hdc, hbmp);
1125 ret = GetObject(hbmp, sizeof(bm), &bm);
1126 ok(ret == sizeof(bm), "wrong size %d\n", ret);
1128 ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
1129 ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
1130 ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
1131 ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
1132 ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
1133 ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
1134 ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
1136 memset(buf, 0xAA, sizeof(buf));
1137 ret = GetBitmapBits(hbmp, sizeof(buf), buf);
1138 ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
1139 ok(!memcmp(buf, buf_cmp, sizeof(buf)) ||
1140 broken(memcmp(buf, buf_cmp, sizeof(buf))), /* win9x doesn't init the bitmap bits */
1141 "buffers do not match\n");
1143 hbmp_old = SelectObject(hdc, hbmp_old);
1144 ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
1146 /* test various buffer sizes for GetObject */
1147 ret = GetObject(hbmp, sizeof(*bma) * 2, bma);
1148 ok(ret == sizeof(*bma) || broken(ret == sizeof(*bma) * 2 /* Win9x */), "wrong size %d\n", ret);
1150 ret = GetObject(hbmp, sizeof(bm) / 2, &bm);
1151 ok(ret == 0 || broken(ret == sizeof(bm) / 2 /* Win9x */), "%d != 0\n", ret);
1153 ret = GetObject(hbmp, 0, &bm);
1154 ok(ret == 0, "%d != 0\n", ret);
1156 ret = GetObject(hbmp, 1, &bm);
1157 ok(ret == 0 || broken(ret == 1 /* Win9x */), "%d != 0\n", ret);
1159 DeleteObject(hbmp);
1160 DeleteDC(hdc);
1163 static void test_bmBits(void)
1165 BYTE bits[4];
1166 HBITMAP hbmp;
1167 BITMAP bmp;
1169 memset(bits, 0, sizeof(bits));
1170 hbmp = CreateBitmap(2, 2, 1, 4, bits);
1171 ok(hbmp != NULL, "CreateBitmap failed\n");
1173 memset(&bmp, 0xFF, sizeof(bmp));
1174 ok(GetObject(hbmp, sizeof(bmp), &bmp) == sizeof(bmp),
1175 "GetObject failed or returned a wrong structure size\n");
1176 ok(!bmp.bmBits, "bmBits must be NULL for device-dependent bitmaps\n");
1178 DeleteObject(hbmp);
1181 static void test_GetDIBits_selected_DIB(UINT bpp)
1183 HBITMAP dib;
1184 BITMAPINFO * info;
1185 BITMAPINFO * info2;
1186 void * bits;
1187 void * bits2;
1188 UINT dib_size;
1189 HDC dib_dc, dc;
1190 HBITMAP old_bmp;
1191 BOOL equalContents;
1192 UINT i;
1193 int res;
1195 /* Create a DIB section with a color table */
1197 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1198 info2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1199 assert(info);
1200 assert(info2);
1202 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1204 /* Choose width and height such that the row length (in bytes)
1205 is a multiple of 4 (makes things easier) */
1206 info->bmiHeader.biWidth = 32;
1207 info->bmiHeader.biHeight = 32;
1208 info->bmiHeader.biPlanes = 1;
1209 info->bmiHeader.biBitCount = bpp;
1210 info->bmiHeader.biCompression = BI_RGB;
1212 for (i=0; i < (1u << bpp); i++)
1214 BYTE c = i * (1 << (8 - bpp));
1215 info->bmiColors[i].rgbRed = c;
1216 info->bmiColors[i].rgbGreen = c;
1217 info->bmiColors[i].rgbBlue = c;
1218 info->bmiColors[i].rgbReserved = 0;
1221 dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
1222 assert(dib);
1223 dib_size = bpp * (info->bmiHeader.biWidth * info->bmiHeader.biHeight) / 8;
1225 /* Set the bits of the DIB section */
1226 for (i=0; i < dib_size; i++)
1228 ((BYTE *)bits)[i] = i % 256;
1231 /* Select the DIB into a DC */
1232 dib_dc = CreateCompatibleDC(NULL);
1233 old_bmp = SelectObject(dib_dc, dib);
1234 dc = CreateCompatibleDC(NULL);
1235 bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size);
1236 assert(bits2);
1238 /* Copy the DIB attributes but not the color table */
1239 memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1241 res = GetDIBits(dc, dib, 0, info->bmiHeader.biHeight, bits2, info2, DIB_RGB_COLORS);
1242 ok(res, "GetDIBits failed\n");
1244 /* Compare the color table and the bits */
1245 equalContents = TRUE;
1246 for (i=0; i < (1u << bpp); i++)
1248 if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1249 || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1250 || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1251 || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1253 equalContents = FALSE;
1254 break;
1257 ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n");
1259 equalContents = TRUE;
1260 for (i=0; i < dib_size / sizeof(DWORD); i++)
1262 if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1264 equalContents = FALSE;
1265 break;
1268 ok(equalContents, "GetDIBits with %d bpp DIB selected in DC: Invalid DIB bits\n",bpp);
1270 HeapFree(GetProcessHeap(), 0, bits2);
1271 DeleteDC(dc);
1273 SelectObject(dib_dc, old_bmp);
1274 DeleteDC(dib_dc);
1275 DeleteObject(dib);
1277 HeapFree(GetProcessHeap(), 0, info2);
1278 HeapFree(GetProcessHeap(), 0, info);
1281 static void test_GetDIBits_selected_DDB(BOOL monochrome)
1283 HBITMAP ddb;
1284 BITMAPINFO * info;
1285 BITMAPINFO * info2;
1286 void * bits;
1287 void * bits2;
1288 HDC ddb_dc, dc;
1289 HBITMAP old_bmp;
1290 BOOL equalContents;
1291 UINT width, height;
1292 UINT bpp;
1293 UINT i, j;
1294 int res;
1296 width = height = 16;
1298 /* Create a DDB (device-dependent bitmap) */
1299 if (monochrome)
1301 bpp = 1;
1302 ddb = CreateBitmap(width, height, 1, 1, NULL);
1304 else
1306 HDC screen_dc = GetDC(NULL);
1307 bpp = GetDeviceCaps(screen_dc, BITSPIXEL) * GetDeviceCaps(screen_dc, PLANES);
1308 ddb = CreateCompatibleBitmap(screen_dc, width, height);
1309 ReleaseDC(NULL, screen_dc);
1312 /* Set the pixels */
1313 ddb_dc = CreateCompatibleDC(NULL);
1314 old_bmp = SelectObject(ddb_dc, ddb);
1315 for (i = 0; i < width; i++)
1317 for (j=0; j < height; j++)
1319 BYTE c = (i * width + j) % 256;
1320 SetPixelV(ddb_dc, i, j, RGB(c, c, c));
1323 SelectObject(ddb_dc, old_bmp);
1325 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1326 info2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1327 assert(info);
1328 assert(info2);
1330 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1331 info->bmiHeader.biWidth = width;
1332 info->bmiHeader.biHeight = height;
1333 info->bmiHeader.biPlanes = 1;
1334 info->bmiHeader.biBitCount = bpp;
1335 info->bmiHeader.biCompression = BI_RGB;
1337 dc = CreateCompatibleDC(NULL);
1339 /* Fill in biSizeImage */
1340 GetDIBits(dc, ddb, 0, height, NULL, info, DIB_RGB_COLORS);
1341 ok(info->bmiHeader.biSizeImage != 0, "GetDIBits failed to get the DIB attributes\n");
1343 bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1344 bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1345 assert(bits);
1346 assert(bits2);
1348 /* Get the bits */
1349 res = GetDIBits(dc, ddb, 0, height, bits, info, DIB_RGB_COLORS);
1350 ok(res, "GetDIBits failed\n");
1352 /* Copy the DIB attributes but not the color table */
1353 memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1355 /* Select the DDB into another DC */
1356 old_bmp = SelectObject(ddb_dc, ddb);
1358 /* Get the bits */
1359 res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS);
1360 ok(res, "GetDIBits failed\n");
1362 /* Compare the color table and the bits */
1363 if (bpp <= 8)
1365 equalContents = TRUE;
1366 for (i=0; i < (1u << bpp); i++)
1368 if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1369 || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1370 || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1371 || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1373 equalContents = FALSE;
1374 break;
1377 ok(equalContents, "GetDIBits with DDB selected in DC: Got a different color table\n");
1380 equalContents = TRUE;
1381 for (i=0; i < info->bmiHeader.biSizeImage / sizeof(DWORD); i++)
1383 if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1385 equalContents = FALSE;
1388 ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB bits\n");
1390 /* Test the palette */
1391 equalContents = TRUE;
1392 if (info2->bmiHeader.biBitCount <= 8)
1394 WORD *colors = (WORD*)info2->bmiColors;
1396 /* Get the palette indices */
1397 res = GetDIBits(dc, ddb, 0, 0, NULL, info2, DIB_PAL_COLORS);
1398 if (res == 0 && GetLastError() == ERROR_INVALID_PARAMETER) /* Win9x */
1399 res = GetDIBits(dc, ddb, 0, height, NULL, info2, DIB_PAL_COLORS);
1400 ok(res, "GetDIBits failed\n");
1402 for (i=0;i < 1 << info->bmiHeader.biSizeImage; i++)
1404 if (colors[i] != i)
1406 equalContents = FALSE;
1407 break;
1412 ok(equalContents, "GetDIBits with DDB selected in DC: non 1:1 palette indices\n");
1414 HeapFree(GetProcessHeap(), 0, bits2);
1415 HeapFree(GetProcessHeap(), 0, bits);
1416 DeleteDC(dc);
1418 SelectObject(ddb_dc, old_bmp);
1419 DeleteDC(ddb_dc);
1420 DeleteObject(ddb);
1422 HeapFree(GetProcessHeap(), 0, info2);
1423 HeapFree(GetProcessHeap(), 0, info);
1426 static void test_GetDIBits(void)
1428 /* 2-bytes aligned 1-bit bitmap data: 16x16 */
1429 static const BYTE bmp_bits_1[16 * 2] =
1431 0xff,0xff, 0,0, 0xff,0xff, 0,0,
1432 0xff,0xff, 0,0, 0xff,0xff, 0,0,
1433 0xff,0xff, 0,0, 0xff,0xff, 0,0,
1434 0xff,0xff, 0,0, 0xff,0xff, 0,0
1436 /* 4-bytes aligned 1-bit DIB data: 16x16 */
1437 static const BYTE dib_bits_1[16 * 4] =
1439 0,0,0,0, 0xff,0xff,0,0, 0,0,0,0, 0xff,0xff,0,0,
1440 0,0,0,0, 0xff,0xff,0,0, 0,0,0,0, 0xff,0xff,0,0,
1441 0,0,0,0, 0xff,0xff,0,0, 0,0,0,0, 0xff,0xff,0,0,
1442 0,0,0,0, 0xff,0xff,0,0, 0,0,0,0, 0xff,0xff,0,0
1444 static const BYTE dib_bits_1_9x[16 * 4] =
1446 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa, 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa,
1447 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa, 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa,
1448 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa, 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa,
1449 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa, 0,0,0xaa,0xaa, 0xff,0xff,0xaa,0xaa
1451 /* 2-bytes aligned 24-bit bitmap data: 16x16 */
1452 static const BYTE bmp_bits_24[16 * 16*3] =
1454 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1455 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1456 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1457 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1458 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1459 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1460 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1461 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1462 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1463 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1464 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1465 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1466 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1467 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1468 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1469 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1470 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1471 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1472 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1473 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1474 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1475 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1476 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1477 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1478 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1479 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1480 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1481 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1482 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1483 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1484 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1485 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1487 /* 4-bytes aligned 24-bit DIB data: 16x16 */
1488 static const BYTE dib_bits_24[16 * 16*3] =
1490 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1491 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1492 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1493 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1494 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1495 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1496 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1497 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1498 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1499 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1500 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1501 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1502 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1503 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1504 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1505 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1506 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1507 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1508 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1509 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1510 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1511 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1512 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1513 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1514 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1515 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1516 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1517 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1518 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1519 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1520 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
1521 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
1523 HBITMAP hbmp;
1524 BITMAP bm;
1525 HDC hdc;
1526 int i, bytes, lines;
1527 BYTE buf[1024];
1528 char bi_buf[sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256];
1529 BITMAPINFO *bi = (BITMAPINFO *)bi_buf;
1531 hdc = GetDC(0);
1533 /* 1-bit source bitmap data */
1534 hbmp = CreateBitmap(16, 16, 1, 1, bmp_bits_1);
1535 ok(hbmp != 0, "CreateBitmap failed\n");
1537 memset(&bm, 0xAA, sizeof(bm));
1538 bytes = GetObject(hbmp, sizeof(bm), &bm);
1539 ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes);
1540 ok(bm.bmType == 0, "wrong bmType %d\n", bm.bmType);
1541 ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth);
1542 ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight);
1543 ok(bm.bmWidthBytes == 2, "wrong bmWidthBytes %d\n", bm.bmWidthBytes);
1544 ok(bm.bmPlanes == 1, "wrong bmPlanes %u\n", bm.bmPlanes);
1545 ok(bm.bmBitsPixel == 1, "wrong bmBitsPixel %d\n", bm.bmBitsPixel);
1546 ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
1548 bytes = GetBitmapBits(hbmp, 0, NULL);
1549 ok(bytes == sizeof(bmp_bits_1) || broken(bytes == 0 /* Win9x */), "expected 16*2 got %d bytes\n", bytes);
1550 bytes = GetBitmapBits(hbmp, sizeof(buf), buf);
1551 ok(bytes == sizeof(bmp_bits_1), "expected 16*2 got %d bytes\n", bytes);
1552 ok(!memcmp(buf, bmp_bits_1, sizeof(bmp_bits_1)), "bitmap bits don't match\n");
1554 /* retrieve 1-bit DIB data */
1555 memset(bi, 0, sizeof(*bi));
1556 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1557 bi->bmiHeader.biWidth = bm.bmWidth;
1558 bi->bmiHeader.biHeight = bm.bmHeight;
1559 bi->bmiHeader.biPlanes = 1;
1560 bi->bmiHeader.biBitCount = 1;
1561 bi->bmiHeader.biCompression = BI_RGB;
1562 bi->bmiHeader.biSizeImage = 0;
1563 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1564 SetLastError(0xdeadbeef);
1565 lines = GetDIBits(0, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
1566 ok(lines == 0, "GetDIBits copied %d lines with hdc = 0\n", lines);
1567 ok(GetLastError() == ERROR_INVALID_PARAMETER ||
1568 broken(GetLastError() == 0xdeadbeef), /* winnt */
1569 "wrong error %u\n", GetLastError());
1570 ok(bi->bmiHeader.biSizeImage == 0, "expected 0, got %u\n", bi->bmiHeader.biSizeImage);
1572 memset(buf, 0xAA, sizeof(buf));
1573 SetLastError(0xdeadbeef);
1574 lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
1575 ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
1576 lines, bm.bmHeight, GetLastError());
1577 ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1) ||
1578 broken(bi->bmiHeader.biSizeImage == 0), /* win9x */
1579 "expected 16*4, got %u\n", bi->bmiHeader.biSizeImage);
1581 /* the color table consists of black and white */
1582 ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0 &&
1583 bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0,
1584 "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n",
1585 bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen,
1586 bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved);
1587 ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff &&
1588 bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved == 0,
1589 "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n",
1590 bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen,
1591 bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved);
1592 for (i = 2; i < 256; i++)
1594 ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA &&
1595 bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA,
1596 "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
1597 bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
1598 bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
1601 /* returned bits are DWORD aligned and upside down */
1602 ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)) ||
1603 broken(!memcmp(buf, dib_bits_1_9x, sizeof(dib_bits_1_9x))), /* Win9x, WinME */
1604 "DIB bits don't match\n");
1606 /* Test the palette indices */
1607 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1608 SetLastError(0xdeadbeef);
1609 lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS);
1610 if (lines == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
1611 win_skip("Win9x/WinMe doesn't handle 0 for the number of scan lines\n");
1612 else
1614 ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n", ((WORD*)bi->bmiColors)[0]);
1615 ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n", ((WORD*)bi->bmiColors)[1]);
1617 for (i = 2; i < 256; i++)
1618 ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i, ((WORD*)bi->bmiColors)[1]);
1620 /* retrieve 24-bit DIB data */
1621 memset(bi, 0, sizeof(*bi));
1622 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1623 bi->bmiHeader.biWidth = bm.bmWidth;
1624 bi->bmiHeader.biHeight = bm.bmHeight;
1625 bi->bmiHeader.biPlanes = 1;
1626 bi->bmiHeader.biBitCount = 24;
1627 bi->bmiHeader.biCompression = BI_RGB;
1628 bi->bmiHeader.biSizeImage = 0;
1629 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1630 memset(buf, 0xAA, sizeof(buf));
1631 SetLastError(0xdeadbeef);
1632 lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
1633 ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
1634 lines, bm.bmHeight, GetLastError());
1635 ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24) ||
1636 broken(bi->bmiHeader.biSizeImage == 0), /* win9x */
1637 "expected 16*16*3, got %u\n", bi->bmiHeader.biSizeImage);
1639 /* the color table doesn't exist for 24-bit images */
1640 for (i = 0; i < 256; i++)
1642 ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA &&
1643 bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA,
1644 "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
1645 bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
1646 bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
1649 /* returned bits are DWORD aligned and upside down */
1650 ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't match\n");
1651 DeleteObject(hbmp);
1653 /* 24-bit source bitmap data */
1654 hbmp = CreateCompatibleBitmap(hdc, 16, 16);
1655 ok(hbmp != 0, "CreateBitmap failed\n");
1656 SetLastError(0xdeadbeef);
1657 bi->bmiHeader.biHeight = -bm.bmHeight; /* indicate bottom-up data */
1658 lines = SetDIBits(hdc, hbmp, 0, bm.bmHeight, bmp_bits_24, bi, DIB_RGB_COLORS);
1659 ok(lines == bm.bmHeight, "SetDIBits copied %d lines of %d, error %u\n",
1660 lines, bm.bmHeight, GetLastError());
1662 memset(&bm, 0xAA, sizeof(bm));
1663 bytes = GetObject(hbmp, sizeof(bm), &bm);
1664 ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes);
1665 ok(bm.bmType == 0 ||
1666 broken(bm.bmType == 21072), /* win9x */
1667 "wrong bmType %d\n", bm.bmType);
1668 ok(bm.bmWidth == 16, "wrong bmWidth %d\n", bm.bmWidth);
1669 ok(bm.bmHeight == 16, "wrong bmHeight %d\n", bm.bmHeight);
1670 ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes);
1671 ok(bm.bmPlanes == GetDeviceCaps(hdc, PLANES), "wrong bmPlanes %u\n", bm.bmPlanes);
1672 ok(bm.bmBitsPixel == GetDeviceCaps(hdc, BITSPIXEL), "wrong bmBitsPixel %d\n", bm.bmBitsPixel);
1673 ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
1675 bytes = GetBitmapBits(hbmp, 0, NULL);
1676 ok(bytes == bm.bmWidthBytes * bm.bmHeight ||
1677 broken(bytes == 0), /* win9x */
1678 "expected %d got %d bytes\n", bm.bmWidthBytes * bm.bmHeight, bytes);
1679 bytes = GetBitmapBits(hbmp, sizeof(buf), buf);
1680 ok(bytes == bm.bmWidthBytes * bm.bmHeight, "expected %d got %d bytes\n",
1681 bm.bmWidthBytes * bm.bmHeight, bytes);
1683 /* retrieve 1-bit DIB data */
1684 memset(bi, 0, sizeof(*bi));
1685 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1686 bi->bmiHeader.biWidth = bm.bmWidth;
1687 bi->bmiHeader.biHeight = bm.bmHeight;
1688 bi->bmiHeader.biPlanes = 1;
1689 bi->bmiHeader.biBitCount = 1;
1690 bi->bmiHeader.biCompression = BI_RGB;
1691 bi->bmiHeader.biSizeImage = 0;
1692 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1693 memset(buf, 0xAA, sizeof(buf));
1694 SetLastError(0xdeadbeef);
1695 lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
1696 ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
1697 lines, bm.bmHeight, GetLastError());
1698 ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_1) ||
1699 broken(bi->bmiHeader.biSizeImage == 0), /* win9x */
1700 "expected 16*4, got %u\n", bi->bmiHeader.biSizeImage);
1702 /* the color table consists of black and white */
1703 ok(bi->bmiColors[0].rgbRed == 0 && bi->bmiColors[0].rgbGreen == 0 &&
1704 bi->bmiColors[0].rgbBlue == 0 && bi->bmiColors[0].rgbReserved == 0,
1705 "expected bmiColors[0] 0,0,0,0 - got %x %x %x %x\n",
1706 bi->bmiColors[0].rgbRed, bi->bmiColors[0].rgbGreen,
1707 bi->bmiColors[0].rgbBlue, bi->bmiColors[0].rgbReserved);
1708 ok(bi->bmiColors[1].rgbRed == 0xff && bi->bmiColors[1].rgbGreen == 0xff &&
1709 bi->bmiColors[1].rgbBlue == 0xff && bi->bmiColors[1].rgbReserved == 0,
1710 "expected bmiColors[0] 0xff,0xff,0xff,0 - got %x %x %x %x\n",
1711 bi->bmiColors[1].rgbRed, bi->bmiColors[1].rgbGreen,
1712 bi->bmiColors[1].rgbBlue, bi->bmiColors[1].rgbReserved);
1713 for (i = 2; i < 256; i++)
1715 ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA &&
1716 bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA,
1717 "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
1718 bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
1719 bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
1722 /* returned bits are DWORD aligned and upside down */
1723 todo_wine
1724 ok(!memcmp(buf, dib_bits_1, sizeof(dib_bits_1)) ||
1725 broken(!memcmp(buf, dib_bits_1_9x, sizeof(dib_bits_1_9x))), /* Win9x, WinME */
1726 "DIB bits don't match\n");
1728 /* Test the palette indices */
1729 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1730 SetLastError(0xdeadbeef);
1731 lines = GetDIBits(hdc, hbmp, 0, 0, NULL, bi, DIB_PAL_COLORS);
1732 if (lines == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
1733 win_skip("Win9x/WinMe doesn't handle 0 for the number of scan lines\n");
1734 else
1736 ok(((WORD*)bi->bmiColors)[0] == 0, "Color 0 is %d\n", ((WORD*)bi->bmiColors)[0]);
1737 ok(((WORD*)bi->bmiColors)[1] == 1, "Color 1 is %d\n", ((WORD*)bi->bmiColors)[1]);
1739 for (i = 2; i < 256; i++)
1740 ok(((WORD*)bi->bmiColors)[i] == 0xAAAA, "Color %d is %d\n", i, ((WORD*)bi->bmiColors)[i]);
1742 /* retrieve 24-bit DIB data */
1743 memset(bi, 0, sizeof(*bi));
1744 bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1745 bi->bmiHeader.biWidth = bm.bmWidth;
1746 bi->bmiHeader.biHeight = bm.bmHeight;
1747 bi->bmiHeader.biPlanes = 1;
1748 bi->bmiHeader.biBitCount = 24;
1749 bi->bmiHeader.biCompression = BI_RGB;
1750 bi->bmiHeader.biSizeImage = 0;
1751 memset(bi->bmiColors, 0xAA, sizeof(RGBQUAD) * 256);
1752 memset(buf, 0xAA, sizeof(buf));
1753 SetLastError(0xdeadbeef);
1754 lines = GetDIBits(hdc, hbmp, 0, bm.bmHeight, buf, bi, DIB_RGB_COLORS);
1755 ok(lines == bm.bmHeight, "GetDIBits copied %d lines of %d, error %u\n",
1756 lines, bm.bmHeight, GetLastError());
1757 ok(bi->bmiHeader.biSizeImage == sizeof(dib_bits_24) ||
1758 broken(bi->bmiHeader.biSizeImage == 0), /* win9x */
1759 "expected 16*16*3, got %u\n", bi->bmiHeader.biSizeImage);
1761 /* the color table doesn't exist for 24-bit images */
1762 for (i = 0; i < 256; i++)
1764 ok(bi->bmiColors[i].rgbRed == 0xAA && bi->bmiColors[i].rgbGreen == 0xAA &&
1765 bi->bmiColors[i].rgbBlue == 0xAA && bi->bmiColors[i].rgbReserved == 0xAA,
1766 "expected bmiColors[%d] 0xAA,0xAA,0xAA,0xAA - got %x %x %x %x\n", i,
1767 bi->bmiColors[i].rgbRed, bi->bmiColors[i].rgbGreen,
1768 bi->bmiColors[i].rgbBlue, bi->bmiColors[i].rgbReserved);
1771 /* returned bits are DWORD aligned and upside down */
1772 ok(!memcmp(buf, dib_bits_24, sizeof(dib_bits_24)), "DIB bits don't match\n");
1773 DeleteObject(hbmp);
1775 ReleaseDC(0, hdc);
1778 static void test_GetDIBits_BI_BITFIELDS(void)
1780 /* Try a screen resolution detection technique
1781 * from the September 1999 issue of Windows Developer's Journal
1782 * which seems to be in widespread use.
1783 * http://www.lesher.ws/highcolor.html
1784 * http://www.lesher.ws/vidfmt.c
1785 * It hinges on being able to retrieve the bitmaps
1786 * for the three primary colors in non-paletted 16 bit mode.
1788 char dibinfo_buf[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)];
1789 DWORD bits[32];
1790 LPBITMAPINFO dibinfo = (LPBITMAPINFO) dibinfo_buf;
1791 HDC hdc;
1792 HBITMAP hbm;
1793 int ret;
1795 memset(dibinfo, 0, sizeof(dibinfo_buf));
1796 dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1798 hdc = GetDC(NULL);
1799 ok(hdc != NULL, "GetDC failed?\n");
1800 hbm = CreateCompatibleBitmap(hdc, 1, 1);
1801 ok(hbm != NULL, "CreateCompatibleBitmap failed?\n");
1803 /* Call GetDIBits to fill in bmiHeader. */
1804 ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
1805 ok(ret == 1, "GetDIBits failed\n");
1806 if (dibinfo->bmiHeader.biBitCount > 8)
1808 DWORD *bitmasks = (DWORD *)dibinfo->bmiColors;
1810 ok( dibinfo->bmiHeader.biCompression == BI_BITFIELDS,
1811 "compression is %u\n", dibinfo->bmiHeader.biCompression );
1813 ok( !bitmasks[0], "red mask is set\n" );
1814 ok( !bitmasks[1], "green mask is set\n" );
1815 ok( !bitmasks[2], "blue mask is set\n" );
1817 /* test with NULL bits pointer and correct bpp */
1818 dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
1819 ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
1820 ok(ret == 1, "GetDIBits failed\n");
1822 ok( bitmasks[0] != 0, "red mask is not set\n" );
1823 ok( bitmasks[1] != 0, "green mask is not set\n" );
1824 ok( bitmasks[2] != 0, "blue mask is not set\n" );
1825 ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
1827 /* test with valid bits pointer */
1828 memset(dibinfo, 0, sizeof(dibinfo_buf));
1829 dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1830 ret = GetDIBits(hdc, hbm, 0, 1, NULL, dibinfo, DIB_RGB_COLORS);
1831 ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
1832 dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
1833 ret = GetDIBits(hdc, hbm, 0, 1, bits, dibinfo, DIB_RGB_COLORS);
1834 ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
1836 ok( bitmasks[0] != 0, "red mask is not set\n" );
1837 ok( bitmasks[1] != 0, "green mask is not set\n" );
1838 ok( bitmasks[2] != 0, "blue mask is not set\n" );
1839 ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef ||
1840 broken(dibinfo->bmiHeader.biSizeImage == 0xdeadbeef), /* win9x */
1841 "size image not set\n" );
1843 /* now with bits and 0 lines */
1844 memset(dibinfo, 0, sizeof(dibinfo_buf));
1845 dibinfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1846 dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
1847 SetLastError(0xdeadbeef);
1848 ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
1849 if (ret == 0 && GetLastError() == ERROR_INVALID_PARAMETER)
1850 win_skip("Win9x/WinMe doesn't handle 0 for the number of scan lines\n");
1851 else
1853 ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
1855 ok( !bitmasks[0], "red mask is set\n" );
1856 ok( !bitmasks[1], "green mask is set\n" );
1857 ok( !bitmasks[2], "blue mask is set\n" );
1858 ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
1860 memset(bitmasks, 0, 3*sizeof(DWORD));
1861 dibinfo->bmiHeader.biSizeImage = 0xdeadbeef;
1862 ret = GetDIBits(hdc, hbm, 0, 0, bits, dibinfo, DIB_RGB_COLORS);
1863 ok(ret == 1, "GetDIBits failed ret %u err %u\n",ret,GetLastError());
1865 ok( bitmasks[0] != 0, "red mask is not set\n" );
1866 ok( bitmasks[1] != 0, "green mask is not set\n" );
1867 ok( bitmasks[2] != 0, "blue mask is not set\n" );
1868 ok( dibinfo->bmiHeader.biSizeImage != 0xdeadbeef, "size image not set\n" );
1871 else skip("not in 16 bpp BI_BITFIELDS mode, skipping that test\n");
1873 DeleteObject(hbm);
1874 ReleaseDC(NULL, hdc);
1877 static void test_select_object(void)
1879 HDC hdc;
1880 HBITMAP hbm, hbm_old;
1881 INT planes, bpp, i;
1882 DWORD depths[] = {8, 15, 16, 24, 32};
1883 BITMAP bm;
1884 DWORD bytes;
1886 hdc = GetDC(0);
1887 ok(hdc != 0, "GetDC(0) failed\n");
1888 hbm = CreateCompatibleBitmap(hdc, 10, 10);
1889 ok(hbm != 0, "CreateCompatibleBitmap failed\n");
1891 hbm_old = SelectObject(hdc, hbm);
1892 ok(hbm_old == 0, "SelectObject should fail\n");
1894 DeleteObject(hbm);
1895 ReleaseDC(0, hdc);
1897 hdc = CreateCompatibleDC(0);
1898 ok(hdc != 0, "GetDC(0) failed\n");
1899 hbm = CreateCompatibleBitmap(hdc, 10, 10);
1900 ok(hbm != 0, "CreateCompatibleBitmap failed\n");
1902 hbm_old = SelectObject(hdc, hbm);
1903 ok(hbm_old != 0, "SelectObject failed\n");
1904 hbm_old = SelectObject(hdc, hbm_old);
1905 ok(hbm_old == hbm, "SelectObject failed\n");
1907 DeleteObject(hbm);
1909 /* test an 1-bpp bitmap */
1910 planes = GetDeviceCaps(hdc, PLANES);
1911 bpp = 1;
1913 hbm = CreateBitmap(10, 10, planes, bpp, NULL);
1914 ok(hbm != 0, "CreateBitmap failed\n");
1916 hbm_old = SelectObject(hdc, hbm);
1917 ok(hbm_old != 0, "SelectObject failed\n");
1918 hbm_old = SelectObject(hdc, hbm_old);
1919 ok(hbm_old == hbm, "SelectObject failed\n");
1921 DeleteObject(hbm);
1923 for(i = 0; i < sizeof(depths)/sizeof(depths[0]); i++) {
1924 /* test a color bitmap to dc bpp matching */
1925 planes = GetDeviceCaps(hdc, PLANES);
1926 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1928 hbm = CreateBitmap(10, 10, planes, depths[i], NULL);
1929 ok(hbm != 0, "CreateBitmap failed\n");
1931 hbm_old = SelectObject(hdc, hbm);
1932 if(depths[i] == bpp ||
1933 (bpp == 16 && depths[i] == 15) /* 16 and 15 bpp are compatible */
1935 ok(hbm_old != 0, "SelectObject failed, BITSPIXEL: %d, created depth: %d\n", bpp, depths[i]);
1936 SelectObject(hdc, hbm_old);
1937 } else {
1938 ok(hbm_old == 0, "SelectObject should fail. BITSPIXELS: %d, created depth: %d\n", bpp, depths[i]);
1941 memset(&bm, 0xAA, sizeof(bm));
1942 bytes = GetObject(hbm, sizeof(bm), &bm);
1943 ok(bytes == sizeof(bm), "GetObject returned %d\n", bytes);
1944 ok(bm.bmType == 0 ||
1945 broken(bm.bmType == 21072), /* win9x */
1946 "wrong bmType %d\n", bm.bmType);
1947 ok(bm.bmWidth == 10, "wrong bmWidth %d\n", bm.bmWidth);
1948 ok(bm.bmHeight == 10, "wrong bmHeight %d\n", bm.bmHeight);
1949 ok(bm.bmWidthBytes == BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel), "wrong bmWidthBytes %d\n", bm.bmWidthBytes);
1950 ok(bm.bmPlanes == planes, "wrong bmPlanes %u\n", bm.bmPlanes);
1951 if(depths[i] == 15) {
1952 ok(bm.bmBitsPixel == 16, "wrong bmBitsPixel %d(15 bpp special)\n", bm.bmBitsPixel);
1953 } else {
1954 ok(bm.bmBitsPixel == depths[i], "wrong bmBitsPixel %d\n", bm.bmBitsPixel);
1956 ok(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
1958 DeleteObject(hbm);
1961 DeleteDC(hdc);
1964 static void test_mono_1x1_bmp_dbg(HBITMAP hbmp, int line)
1966 INT ret;
1967 BITMAP bm;
1969 ret = GetObjectType(hbmp);
1970 ok_(__FILE__, line)(ret == OBJ_BITMAP, "the object %p is not bitmap\n", hbmp);
1972 ret = GetObject(hbmp, 0, 0);
1973 ok_(__FILE__, line)(ret == sizeof(BITMAP) /* XP */ ||
1974 ret == sizeof(DIBSECTION) /* Win9x */, "object size %d\n", ret);
1976 memset(&bm, 0xDA, sizeof(bm));
1977 SetLastError(0xdeadbeef);
1978 ret = GetObject(hbmp, sizeof(bm), &bm);
1979 if (!ret) /* XP, only for curObj2 */ return;
1980 ok_(__FILE__, line)(ret == sizeof(BITMAP) ||
1981 ret == sizeof(DIBSECTION) /* Win9x, only for curObj2 */,
1982 "GetObject returned %d, error %u\n", ret, GetLastError());
1983 ok_(__FILE__, line)(bm.bmType == 0, "wrong bmType, expected 0 got %d\n", bm.bmType);
1984 ok_(__FILE__, line)(bm.bmWidth == 1, "wrong bmWidth, expected 1 got %d\n", bm.bmWidth);
1985 ok_(__FILE__, line)(bm.bmHeight == 1, "wrong bmHeight, expected 1 got %d\n", bm.bmHeight);
1986 ok_(__FILE__, line)(bm.bmWidthBytes == 2, "wrong bmWidthBytes, expected 2 got %d\n", bm.bmWidthBytes);
1987 ok_(__FILE__, line)(bm.bmPlanes == 1, "wrong bmPlanes, expected 1 got %u\n", bm.bmPlanes);
1988 ok_(__FILE__, line)(bm.bmBitsPixel == 1, "wrong bmBitsPixel, expected 1 got %d\n", bm.bmBitsPixel);
1989 ok_(__FILE__, line)(!bm.bmBits, "wrong bmBits %p\n", bm.bmBits);
1992 #define test_mono_1x1_bmp(a) test_mono_1x1_bmp_dbg((a), __LINE__)
1994 static void test_CreateBitmap(void)
1996 BITMAP bmp;
1997 HDC screenDC = GetDC(0);
1998 HDC hdc = CreateCompatibleDC(screenDC);
1999 UINT i, expect = 0;
2001 /* all of these are the stock monochrome bitmap */
2002 HBITMAP bm = CreateCompatibleBitmap(hdc, 0, 0);
2003 HBITMAP bm1 = CreateCompatibleBitmap(screenDC, 0, 0);
2004 HBITMAP bm4 = CreateBitmap(0, 1, 0, 0, 0);
2005 HBITMAP bm5 = CreateDiscardableBitmap(hdc, 0, 0);
2006 HBITMAP curObj1 = GetCurrentObject(hdc, OBJ_BITMAP);
2007 HBITMAP curObj2 = GetCurrentObject(screenDC, OBJ_BITMAP);
2009 /* these 2 are not the stock monochrome bitmap */
2010 HBITMAP bm2 = CreateCompatibleBitmap(hdc, 1, 1);
2011 HBITMAP bm3 = CreateBitmap(1, 1, 1, 1, 0);
2013 HBITMAP old1 = SelectObject(hdc, bm2);
2014 HBITMAP old2 = SelectObject(screenDC, bm3);
2015 SelectObject(hdc, old1);
2016 SelectObject(screenDC, old2);
2018 ok(bm == bm1 && bm == bm4 && bm == bm5 && bm == curObj1 && bm == old1,
2019 "0: %p, 1: %p, 4: %p, 5: %p, curObj1 %p, old1 %p\n",
2020 bm, bm1, bm4, bm5, curObj1, old1);
2021 ok(bm != bm2 && bm != bm3, "0: %p, 2: %p, 3: %p\n", bm, bm2, bm3);
2022 todo_wine
2023 ok(bm != curObj2 || /* WinXP */
2024 broken(bm == curObj2) /* Win9x */,
2025 "0: %p, curObj2 %p\n", bm, curObj2);
2026 ok(old2 == 0, "old2 %p\n", old2);
2028 test_mono_1x1_bmp(bm);
2029 test_mono_1x1_bmp(bm1);
2030 test_mono_1x1_bmp(bm2);
2031 test_mono_1x1_bmp(bm3);
2032 test_mono_1x1_bmp(bm4);
2033 test_mono_1x1_bmp(bm5);
2034 test_mono_1x1_bmp(old1);
2035 test_mono_1x1_bmp(curObj1);
2037 DeleteObject(bm);
2038 DeleteObject(bm1);
2039 DeleteObject(bm2);
2040 DeleteObject(bm3);
2041 DeleteObject(bm4);
2042 DeleteObject(bm5);
2044 DeleteDC(hdc);
2045 ReleaseDC(0, screenDC);
2047 /* show that Windows ignores the provided bm.bmWidthBytes */
2048 bmp.bmType = 0;
2049 bmp.bmWidth = 1;
2050 bmp.bmHeight = 1;
2051 bmp.bmWidthBytes = 28;
2052 bmp.bmPlanes = 1;
2053 bmp.bmBitsPixel = 1;
2054 bmp.bmBits = NULL;
2055 bm = CreateBitmapIndirect(&bmp);
2056 ok(bm != 0, "CreateBitmapIndirect error %u\n", GetLastError());
2057 test_mono_1x1_bmp(bm);
2058 DeleteObject(bm);
2060 /* Test how the bmBitsPixel field is treated */
2061 for(i = 1; i <= 33; i++) {
2062 bmp.bmType = 0;
2063 bmp.bmWidth = 1;
2064 bmp.bmHeight = 1;
2065 bmp.bmWidthBytes = 28;
2066 bmp.bmPlanes = 1;
2067 bmp.bmBitsPixel = i;
2068 bmp.bmBits = NULL;
2069 SetLastError(0xdeadbeef);
2070 bm = CreateBitmapIndirect(&bmp);
2071 if(i > 32) {
2072 DWORD error = GetLastError();
2073 ok(bm == 0 ||
2074 broken(bm != 0), /* Win9x and WinMe */
2075 "CreateBitmapIndirect for %d bpp succeeded\n", i);
2076 ok(error == ERROR_INVALID_PARAMETER ||
2077 broken(error == 0xdeadbeef), /* Win9x and WinME */
2078 "Got error %d, expected ERROR_INVALID_PARAMETER\n", error);
2079 DeleteObject(bm);
2080 continue;
2082 ok(bm != 0, "CreateBitmapIndirect error %u\n", GetLastError());
2083 GetObject(bm, sizeof(bmp), &bmp);
2084 if(i == 1) {
2085 expect = 1;
2086 } else if(i <= 4) {
2087 expect = 4;
2088 } else if(i <= 8) {
2089 expect = 8;
2090 } else if(i <= 16) {
2091 expect = 16;
2092 } else if(i <= 24) {
2093 expect = 24;
2094 } else if(i <= 32) {
2095 expect = 32;
2097 ok(bmp.bmBitsPixel == expect ||
2098 broken(bmp.bmBitsPixel == i), /* Win9x and WinMe */
2099 "CreateBitmapIndirect for a %d bpp bitmap created a %d bpp bitmap, expected %d\n",
2100 i, bmp.bmBitsPixel, expect);
2101 DeleteObject(bm);
2105 static void test_bitmapinfoheadersize(void)
2107 HBITMAP hdib;
2108 BITMAPINFO bmi;
2109 BITMAPCOREINFO bci;
2110 HDC hdc = GetDC(0);
2112 memset(&bmi, 0, sizeof(BITMAPINFO));
2113 bmi.bmiHeader.biHeight = 100;
2114 bmi.bmiHeader.biWidth = 512;
2115 bmi.bmiHeader.biBitCount = 24;
2116 bmi.bmiHeader.biPlanes = 1;
2118 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER) - 1;
2120 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2121 ok(hdib == NULL, "CreateDIBSection succeeded\n");
2123 bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2125 SetLastError(0xdeadbeef);
2126 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2127 ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
2128 DeleteObject(hdib);
2130 bmi.bmiHeader.biSize++;
2132 SetLastError(0xdeadbeef);
2133 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2134 ok(hdib != NULL ||
2135 broken(!hdib), /* Win98, WinMe */
2136 "CreateDIBSection error %d\n", GetLastError());
2137 DeleteObject(hdib);
2139 bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
2141 SetLastError(0xdeadbeef);
2142 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2143 ok(hdib != NULL ||
2144 broken(!hdib), /* Win98, WinMe */
2145 "CreateDIBSection error %d\n", GetLastError());
2146 DeleteObject(hdib);
2148 bmi.bmiHeader.biSize++;
2150 SetLastError(0xdeadbeef);
2151 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2152 ok(hdib != NULL ||
2153 broken(!hdib), /* Win98, WinMe */
2154 "CreateDIBSection error %d\n", GetLastError());
2155 DeleteObject(hdib);
2157 bmi.bmiHeader.biSize = sizeof(BITMAPV4HEADER);
2159 SetLastError(0xdeadbeef);
2160 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2161 ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
2162 DeleteObject(hdib);
2164 bmi.bmiHeader.biSize = sizeof(BITMAPV5HEADER);
2166 SetLastError(0xdeadbeef);
2167 hdib = CreateDIBSection(hdc, &bmi, 0, NULL, NULL, 0);
2168 ok(hdib != NULL ||
2169 broken(!hdib), /* Win95 */
2170 "CreateDIBSection error %d\n", GetLastError());
2171 DeleteObject(hdib);
2173 memset(&bci, 0, sizeof(BITMAPCOREINFO));
2174 bci.bmciHeader.bcHeight = 100;
2175 bci.bmciHeader.bcWidth = 512;
2176 bci.bmciHeader.bcBitCount = 24;
2177 bci.bmciHeader.bcPlanes = 1;
2179 bci.bmciHeader.bcSize = sizeof(BITMAPCOREHEADER) - 1;
2181 hdib = CreateDIBSection(hdc, (BITMAPINFO *)&bci, 0, NULL, NULL, 0);
2182 ok(hdib == NULL, "CreateDIBSection succeeded\n");
2184 bci.bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
2186 SetLastError(0xdeadbeef);
2187 hdib = CreateDIBSection(hdc, (BITMAPINFO *)&bci, 0, NULL, NULL, 0);
2188 ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
2189 DeleteObject(hdib);
2191 bci.bmciHeader.bcSize++;
2193 hdib = CreateDIBSection(hdc, (BITMAPINFO *)&bci, 0, NULL, NULL, 0);
2194 ok(hdib == NULL, "CreateDIBSection succeeded\n");
2196 bci.bmciHeader.bcSize = sizeof(BITMAPCOREINFO);
2198 hdib = CreateDIBSection(hdc, (BITMAPINFO *)&bci, 0, NULL, NULL, 0);
2199 ok(hdib == NULL, "CreateDIBSection succeeded\n");
2201 ReleaseDC(0, hdc);
2204 static void test_get16dibits(void)
2206 BYTE bits[4 * (16 / sizeof(BYTE))];
2207 HBITMAP hbmp;
2208 HDC screen_dc = GetDC(NULL);
2209 int ret;
2210 BITMAPINFO * info;
2211 int info_len = sizeof(BITMAPINFOHEADER) + 1024;
2212 BYTE *p;
2213 int overwritten_bytes = 0;
2215 memset(bits, 0, sizeof(bits));
2216 hbmp = CreateBitmap(2, 2, 1, 16, bits);
2217 ok(hbmp != NULL, "CreateBitmap failed\n");
2219 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info_len);
2220 assert(info);
2222 memset(info, '!', info_len);
2223 memset(info, 0, sizeof(info->bmiHeader));
2225 info->bmiHeader.biSize = sizeof(info->bmiHeader);
2226 info->bmiHeader.biWidth = 2;
2227 info->bmiHeader.biHeight = 2;
2228 info->bmiHeader.biPlanes = 1;
2229 info->bmiHeader.biCompression = BI_RGB;
2231 ret = GetDIBits(screen_dc, hbmp, 0, 0, NULL, info, 0);
2232 ok(ret != 0 ||
2233 broken(ret == 0), /* win9x */
2234 "GetDIBits failed got %d\n", ret);
2236 for (p = ((BYTE *) info) + sizeof(info->bmiHeader); (p - ((BYTE *) info)) < info_len; p++)
2237 if (*p != '!')
2238 overwritten_bytes++;
2239 ok(overwritten_bytes == 0, "GetDIBits wrote past the buffer given\n");
2241 HeapFree(GetProcessHeap(), 0, info);
2242 DeleteObject(hbmp);
2243 ReleaseDC(NULL, screen_dc);
2246 static void test_GdiAlphaBlend(void)
2248 /* test out-of-bound parameters for GdiAlphaBlend */
2249 HDC hdcNull;
2251 HDC hdcDst;
2252 HBITMAP bmpDst;
2253 HBITMAP oldDst;
2255 BITMAPINFO bmi;
2256 HDC hdcSrc;
2257 HBITMAP bmpSrc;
2258 HBITMAP oldSrc;
2259 LPVOID bits;
2261 BLENDFUNCTION blend;
2263 if (!pGdiAlphaBlend)
2265 win_skip("GdiAlphaBlend() is not implemented\n");
2266 return;
2269 hdcNull = GetDC(NULL);
2270 hdcDst = CreateCompatibleDC(hdcNull);
2271 bmpDst = CreateCompatibleBitmap(hdcNull, 100, 100);
2272 hdcSrc = CreateCompatibleDC(hdcNull);
2274 memset(&bmi, 0, sizeof(bmi)); /* as of Wine 0.9.44 we require the src to be a DIB section */
2275 bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
2276 bmi.bmiHeader.biHeight = 20;
2277 bmi.bmiHeader.biWidth = 20;
2278 bmi.bmiHeader.biBitCount = 32;
2279 bmi.bmiHeader.biPlanes = 1;
2280 bmi.bmiHeader.biCompression = BI_RGB;
2281 bmpSrc = CreateDIBSection(hdcDst, &bmi, DIB_RGB_COLORS, &bits, NULL, 0);
2282 ok(bmpSrc != NULL, "Couldn't create source bitmap\n");
2284 oldDst = SelectObject(hdcDst, bmpDst);
2285 oldSrc = SelectObject(hdcSrc, bmpSrc);
2287 blend.BlendOp = AC_SRC_OVER;
2288 blend.BlendFlags = 0;
2289 blend.SourceConstantAlpha = 128;
2290 blend.AlphaFormat = 0;
2292 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, 0, 20, 20, blend), TRUE, BOOL, "%d");
2293 SetLastError(0xdeadbeef);
2294 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, -1, 0, 10, 10, blend), FALSE, BOOL, "%d");
2295 expect_eq(GetLastError(), ERROR_INVALID_PARAMETER, int, "%d");
2296 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, -1, 10, 10, blend), FALSE, BOOL, "%d");
2297 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 15, 0, 10, 10, blend), FALSE, BOOL, "%d");
2298 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 10, 10, -2, 3, blend), FALSE, BOOL, "%d");
2299 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 10, 10, -2, 3, blend), FALSE, BOOL, "%d");
2301 SetWindowOrgEx(hdcSrc, -10, -10, NULL);
2302 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, -1, 0, 10, 10, blend), TRUE, BOOL, "%d");
2303 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, -1, 10, 10, blend), TRUE, BOOL, "%d");
2304 SetMapMode(hdcSrc, MM_ANISOTROPIC);
2305 ScaleWindowExtEx(hdcSrc, 10, 1, 10, 1, NULL);
2306 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, -1, 0, 30, 30, blend), TRUE, BOOL, "%d");
2307 expect_eq(pGdiAlphaBlend(hdcDst, 0, 0, 20, 20, hdcSrc, 0, -1, 30, 30, blend), TRUE, BOOL, "%d");
2309 SelectObject(hdcDst, oldDst);
2310 SelectObject(hdcSrc, oldSrc);
2311 DeleteObject(bmpSrc);
2312 DeleteObject(bmpDst);
2313 DeleteDC(hdcDst);
2314 DeleteDC(hdcSrc);
2316 ReleaseDC(NULL, hdcNull);
2320 static void test_clipping(void)
2322 HBITMAP bmpDst;
2323 HBITMAP oldDst;
2324 HBITMAP bmpSrc;
2325 HBITMAP oldSrc;
2326 HRGN hRgn;
2327 LPVOID bits;
2328 BOOL result;
2330 HDC hdcDst = CreateCompatibleDC( NULL );
2331 HDC hdcSrc = CreateCompatibleDC( NULL );
2333 BITMAPINFO bmpinfo={{0}};
2334 bmpinfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
2335 bmpinfo.bmiHeader.biWidth = 100;
2336 bmpinfo.bmiHeader.biHeight = 100;
2337 bmpinfo.bmiHeader.biPlanes = 1;
2338 bmpinfo.bmiHeader.biBitCount = GetDeviceCaps( hdcDst, BITSPIXEL );
2339 bmpinfo.bmiHeader.biCompression = BI_RGB;
2341 bmpDst = CreateDIBSection( hdcDst, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
2342 ok(bmpDst != NULL, "Couldn't create destination bitmap\n");
2343 oldDst = SelectObject( hdcDst, bmpDst );
2345 bmpSrc = CreateDIBSection( hdcSrc, &bmpinfo, DIB_RGB_COLORS, &bits, NULL, 0 );
2346 ok(bmpSrc != NULL, "Couldn't create source bitmap\n");
2347 oldSrc = SelectObject( hdcSrc, bmpSrc );
2349 result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 100, 100, SRCCOPY );
2350 ok(result, "BitBlt failed\n");
2352 hRgn = CreateRectRgn( 0,0,0,0 );
2353 SelectClipRgn( hdcDst, hRgn );
2355 result = BitBlt( hdcDst, 0, 0, 100, 100, hdcSrc, 0, 0, SRCCOPY );
2356 ok(result, "BitBlt failed\n");
2358 DeleteObject( bmpDst );
2359 DeleteObject( bmpSrc );
2360 DeleteObject( hRgn );
2361 DeleteDC( hdcDst );
2362 DeleteDC( hdcSrc );
2365 START_TEST(bitmap)
2367 HMODULE hdll;
2368 is_win9x = GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC) == 0;
2370 hdll = GetModuleHandle("gdi32.dll");
2371 pGdiAlphaBlend = (void*)GetProcAddress(hdll, "GdiAlphaBlend");
2373 test_createdibitmap();
2374 test_dibsections();
2375 test_mono_dibsection();
2376 test_bitmap();
2377 test_bmBits();
2378 test_GetDIBits_selected_DIB(1);
2379 test_GetDIBits_selected_DIB(4);
2380 test_GetDIBits_selected_DIB(8);
2381 test_GetDIBits_selected_DDB(TRUE);
2382 test_GetDIBits_selected_DDB(FALSE);
2383 test_GetDIBits();
2384 test_GetDIBits_BI_BITFIELDS();
2385 test_select_object();
2386 test_CreateBitmap();
2387 test_GdiAlphaBlend();
2388 test_bitmapinfoheadersize();
2389 test_get16dibits();
2390 test_clipping();