gdi/tests: Win64 printf format warning fixes.
[wine] / dlls / gdi / tests / bitmap.c
1 /*
2  * Unit test suite for bitmaps
3  *
4  * Copyright 2004 Huw Davies
5  * Copyright 2006 Dmitry Timoshkov
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <assert.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "mmsystem.h"
31
32 #include "wine/test.h"
33
34 static BOOL is_win9x;
35
36 static INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
37 {
38     switch(bpp)
39     {
40     case 1:
41         return 2 * ((bmWidth+15) >> 4);
42
43     case 24:
44         bmWidth *= 3; /* fall through */
45     case 8:
46         return bmWidth + (bmWidth & 1);
47
48     case 32:
49         return bmWidth * 4;
50
51     case 16:
52     case 15:
53         return bmWidth * 2;
54
55     case 4:
56         return 2 * ((bmWidth+3) >> 2);
57
58     default:
59         trace("Unknown depth %d, please report.\n", bpp );
60         assert(0);
61     }
62     return -1;
63 }
64
65 static void test_bitmap_info(HBITMAP hbm, INT expected_depth, const BITMAPINFOHEADER *bmih)
66 {
67     BITMAP bm;
68     INT ret, width_bytes;
69     char buf[512], buf_cmp[512];
70
71     ret = GetObject(hbm, sizeof(bm), &bm);
72     ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
73
74     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
75     ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
76     ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
77     width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
78     ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes);
79     ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
80     ok(bm.bmBitsPixel == expected_depth, "wrong bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, expected_depth);
81     ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
82
83     assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
84     assert(sizeof(buf) == sizeof(buf_cmp));
85
86     ret = GetBitmapBits(hbm, 0, NULL);
87     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
88
89     memset(buf_cmp, 0xAA, sizeof(buf_cmp));
90     memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
91
92     memset(buf, 0xAA, sizeof(buf));
93     ret = GetBitmapBits(hbm, sizeof(buf), buf);
94     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
95     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
96
97     /* test various buffer sizes for GetObject */
98     ret = GetObject(hbm, 0, NULL);
99     ok(ret == sizeof(bm), "wrong size %d\n", ret);
100
101     ret = GetObject(hbm, sizeof(bm) * 2, &bm);
102     ok(ret == sizeof(bm), "wrong size %d\n", ret);
103
104     ret = GetObject(hbm, sizeof(bm) / 2, &bm);
105     ok(ret == 0, "%d != 0\n", ret);
106
107     ret = GetObject(hbm, 0, &bm);
108     ok(ret == 0, "%d != 0\n", ret);
109
110     ret = GetObject(hbm, 1, &bm);
111     ok(ret == 0, "%d != 0\n", ret);
112 }
113
114 static void test_createdibitmap(void)
115 {
116     HDC hdc, hdcmem;
117     BITMAPINFOHEADER bmih;
118     HBITMAP hbm, hbm_colour, hbm_old;
119     INT screen_depth;
120
121     hdc = GetDC(0);
122     screen_depth = GetDeviceCaps(hdc, BITSPIXEL);
123     memset(&bmih, 0, sizeof(bmih));
124     bmih.biSize = sizeof(bmih);
125     bmih.biWidth = 10;
126     bmih.biHeight = 10;
127     bmih.biPlanes = 1;
128     bmih.biBitCount = 32;
129     bmih.biCompression = BI_RGB;
130  
131     /* First create an un-initialised bitmap.  The depth of the bitmap
132        should match that of the hdc and not that supplied in bmih.
133     */
134
135     /* First try 32 bits */
136     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
137     ok(hbm != NULL, "CreateDIBitmap failed\n");
138     test_bitmap_info(hbm, screen_depth, &bmih);
139     DeleteObject(hbm);
140     
141     /* Then 16 */
142     bmih.biBitCount = 16;
143     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
144     ok(hbm != NULL, "CreateDIBitmap failed\n");
145     test_bitmap_info(hbm, screen_depth, &bmih);
146     DeleteObject(hbm);
147
148     /* Then 1 */
149     bmih.biBitCount = 1;
150     hbm = CreateDIBitmap(hdc, &bmih, 0, NULL, NULL, 0);
151     ok(hbm != NULL, "CreateDIBitmap failed\n");
152     test_bitmap_info(hbm, screen_depth, &bmih);
153     DeleteObject(hbm);
154
155     /* Now with a monochrome dc we expect a monochrome bitmap */
156     hdcmem = CreateCompatibleDC(hdc);
157
158     /* First try 32 bits */
159     bmih.biBitCount = 32;
160     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
161     ok(hbm != NULL, "CreateDIBitmap failed\n");
162     test_bitmap_info(hbm, 1, &bmih);
163     DeleteObject(hbm);
164     
165     /* Then 16 */
166     bmih.biBitCount = 16;
167     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
168     ok(hbm != NULL, "CreateDIBitmap failed\n");
169     test_bitmap_info(hbm, 1, &bmih);
170     DeleteObject(hbm);
171     
172     /* Then 1 */
173     bmih.biBitCount = 1;
174     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
175     ok(hbm != NULL, "CreateDIBitmap failed\n");
176     test_bitmap_info(hbm, 1, &bmih);
177     DeleteObject(hbm);
178
179     /* Now select a polychrome bitmap into the dc and we expect
180        screen_depth bitmaps again */
181     hbm_colour = CreateCompatibleBitmap(hdc, 1, 1);
182     hbm_old = SelectObject(hdcmem, hbm_colour);
183
184     /* First try 32 bits */
185     bmih.biBitCount = 32;
186     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
187     ok(hbm != NULL, "CreateDIBitmap failed\n");
188     test_bitmap_info(hbm, screen_depth, &bmih);
189     DeleteObject(hbm);
190     
191     /* Then 16 */
192     bmih.biBitCount = 16;
193     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
194     ok(hbm != NULL, "CreateDIBitmap failed\n");
195     test_bitmap_info(hbm, screen_depth, &bmih);
196     DeleteObject(hbm);
197     
198     /* Then 1 */
199     bmih.biBitCount = 1;
200     hbm = CreateDIBitmap(hdcmem, &bmih, 0, NULL, NULL, 0);
201     ok(hbm != NULL, "CreateDIBitmap failed\n");
202     test_bitmap_info(hbm, screen_depth, &bmih);
203     DeleteObject(hbm);
204
205     SelectObject(hdcmem, hbm_old);
206     DeleteObject(hbm_colour);
207     DeleteDC(hdcmem);
208
209     /* If hdc == 0 then we get a 1 bpp bitmap */
210     if (!is_win9x) {
211         bmih.biBitCount = 32;
212         hbm = CreateDIBitmap(0, &bmih, 0, NULL, NULL, 0);
213         ok(hbm != NULL, "CreateDIBitmap failed\n");
214         test_bitmap_info(hbm, 1, &bmih);
215         DeleteObject(hbm);
216     }
217     
218     ReleaseDC(0, hdc);
219 }
220
221 static INT DIB_GetWidthBytes( int width, int bpp )
222 {
223     int words;
224
225     switch (bpp)
226     {
227         case 1:  words = (width + 31) / 32; break;
228         case 4:  words = (width + 7) / 8; break;
229         case 8:  words = (width + 3) / 4; break;
230         case 15:
231         case 16: words = (width + 1) / 2; break;
232         case 24: words = (width * 3 + 3)/4; break;
233         case 32: words = width; break;
234
235         default:
236             words=0;
237             trace("Unknown depth %d, please report.\n", bpp );
238             assert(0);
239             break;
240     }
241     return 4 * words;
242 }
243
244 static void test_dib_info(HBITMAP hbm, const void *bits, const BITMAPINFOHEADER *bmih)
245 {
246     BITMAP bm;
247     DIBSECTION ds;
248     INT ret, width_bytes;
249     BYTE *buf;
250
251     ret = GetObject(hbm, sizeof(bm), &bm);
252     ok(ret == sizeof(bm), "GetObject returned %d\n", ret);
253
254     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
255     ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
256     ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
257     width_bytes = DIB_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
258     ok(bm.bmWidthBytes == width_bytes, "wrong bm.bmWidthBytes %d != %d\n", bm.bmWidthBytes, width_bytes);
259     ok(bm.bmPlanes == bmih->biPlanes, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
260     ok(bm.bmBitsPixel == bmih->biBitCount, "bm.bmBitsPixel %d != %d\n", bm.bmBitsPixel, bmih->biBitCount);
261     ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
262
263     buf = HeapAlloc(GetProcessHeap(), 0, bm.bmWidthBytes * bm.bmHeight + 4096);
264
265     width_bytes = BITMAP_GetWidthBytes(bm.bmWidth, bm.bmBitsPixel);
266
267     /* GetBitmapBits returns not 32-bit aligned data */
268     ret = GetBitmapBits(hbm, 0, NULL);
269     ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight);
270
271     memset(buf, 0xAA, bm.bmWidthBytes * bm.bmHeight + 4096);
272     ret = GetBitmapBits(hbm, bm.bmWidthBytes * bm.bmHeight + 4096, buf);
273     ok(ret == width_bytes * bm.bmHeight, "%d != %d\n", ret, width_bytes * bm.bmHeight);
274
275     HeapFree(GetProcessHeap(), 0, buf);
276
277     /* test various buffer sizes for GetObject */
278     memset(&ds, 0xAA, sizeof(ds));
279     ret = GetObject(hbm, sizeof(bm) * 2, &bm);
280     ok(ret == sizeof(bm), "wrong size %d\n", ret);
281     ok(bm.bmWidth == bmih->biWidth, "wrong bm.bmWidth %d\n", bm.bmWidth);
282     ok(bm.bmHeight == bmih->biHeight, "wrong bm.bmHeight %d\n", bm.bmHeight);
283     ok(bm.bmBits == bits, "wrong bm.bmBits %p != %p\n", bm.bmBits, bits);
284
285     ret = GetObject(hbm, sizeof(bm) / 2, &bm);
286     ok(ret == 0, "%d != 0\n", ret);
287
288     ret = GetObject(hbm, 0, &bm);
289     ok(ret == 0, "%d != 0\n", ret);
290
291     ret = GetObject(hbm, 1, &bm);
292     ok(ret == 0, "%d != 0\n", ret);
293
294     /* test various buffer sizes for GetObject */
295     ret = GetObject(hbm, 0, NULL);
296     ok(ret == sizeof(bm), "wrong size %d\n", ret);
297
298     memset(&ds, 0xAA, sizeof(ds));
299     ret = GetObject(hbm, sizeof(ds) * 2, &ds);
300     ok(ret == sizeof(ds), "wrong size %d\n", ret);
301
302     ok(ds.dsBm.bmBits == bits, "wrong bm.bmBits %p != %p\n", ds.dsBm.bmBits, bits);
303     ok(ds.dsBmih.biSizeImage == ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight, "%u != %u\n",
304        ds.dsBmih.biSizeImage, ds.dsBm.bmWidthBytes * ds.dsBm.bmHeight);
305     ok(bmih->biSizeImage == 0, "%u != 0\n", bmih->biSizeImage);
306     ds.dsBmih.biSizeImage = 0;
307
308     ok(ds.dsBmih.biSize == bmih->biSize, "%u != %u\n", ds.dsBmih.biSize, bmih->biSize);
309     ok(ds.dsBmih.biWidth == bmih->biWidth, "%u != %u\n", ds.dsBmih.biWidth, bmih->biWidth);
310     ok(ds.dsBmih.biHeight == bmih->biHeight, "%u != %u\n", ds.dsBmih.biHeight, bmih->biHeight);
311     ok(ds.dsBmih.biPlanes == bmih->biPlanes, "%u != %u\n", ds.dsBmih.biPlanes, bmih->biPlanes);
312     ok(ds.dsBmih.biBitCount == bmih->biBitCount, "%u != %u\n", ds.dsBmih.biBitCount, bmih->biBitCount);
313     ok(ds.dsBmih.biCompression == bmih->biCompression, "%u != %u\n", ds.dsBmih.biCompression, bmih->biCompression);
314     ok(ds.dsBmih.biSizeImage == bmih->biSizeImage, "%u != %u\n", ds.dsBmih.biSizeImage, bmih->biSizeImage);
315     ok(ds.dsBmih.biXPelsPerMeter == bmih->biXPelsPerMeter, "%u != %u\n", ds.dsBmih.biXPelsPerMeter, bmih->biXPelsPerMeter);
316     ok(ds.dsBmih.biYPelsPerMeter == bmih->biYPelsPerMeter, "%u != %u\n", ds.dsBmih.biYPelsPerMeter, bmih->biYPelsPerMeter);
317
318     memset(&ds, 0xAA, sizeof(ds));
319     ret = GetObject(hbm, sizeof(ds) - 4, &ds);
320     ok(ret == sizeof(ds.dsBm), "wrong size %d\n", ret);
321     ok(ds.dsBm.bmWidth == bmih->biWidth, "%u != %u\n", ds.dsBmih.biWidth, bmih->biWidth);
322     ok(ds.dsBm.bmHeight == bmih->biHeight, "%u != %u\n", ds.dsBmih.biHeight, bmih->biHeight);
323     ok(ds.dsBm.bmBits == bits, "%p != %p\n", ds.dsBm.bmBits, bits);
324
325     ret = GetObject(hbm, 0, &ds);
326     ok(ret == 0, "%d != 0\n", ret);
327
328     ret = GetObject(hbm, 1, &ds);
329     ok(ret == 0, "%d != 0\n", ret);
330 }
331
332 #define test_color_todo(got, exp, txt, todo) \
333     if (!todo && got != exp && screen_depth < 24) { \
334       todo_wine ok(0, #txt " failed at %d-bit screen depth: got 0x%06x expected 0x%06x - skipping DIB tests\n", \
335                    screen_depth, (UINT)got, (UINT)exp); \
336       return; \
337     } else if (todo) todo_wine { ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp); } \
338     else ok(got == exp, #txt " failed: got 0x%06x expected 0x%06x\n", (UINT)got, (UINT)exp) \
339
340 #define test_color(hdc, color, exp, todo_setp, todo_getp) \
341 { \
342     COLORREF c; \
343     c = SetPixel(hdc, 0, 0, color); \
344     if (!is_win9x) { test_color_todo(c, exp, SetPixel, todo_setp); } \
345     c = GetPixel(hdc, 0, 0); \
346     test_color_todo(c, exp, GetPixel, todo_getp); \
347 }
348
349 static void test_dibsections(void)
350 {
351     HDC hdc, hdcmem, hdcmem2;
352     HBITMAP hdib, oldbm, hdib2, oldbm2;
353     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
354     char bcibuf[sizeof(BITMAPCOREINFO) + 256 * sizeof(RGBTRIPLE)];
355     BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
356     BITMAPCOREINFO *pbci = (BITMAPCOREINFO *)bcibuf;
357     HBITMAP hcoredib;
358     char coreBits[256];
359     BYTE *bits;
360     RGBQUAD rgb[256];
361     int ret;
362     char logpalbuf[sizeof(LOGPALETTE) + 256 * sizeof(PALETTEENTRY)];
363     LOGPALETTE *plogpal = (LOGPALETTE*)logpalbuf;
364     WORD *index;
365     DWORD *bits32;
366     HPALETTE hpal, oldpal;
367     DIBSECTION dibsec;
368     COLORREF c0, c1;
369     int i;
370     int screen_depth;
371     MEMORY_BASIC_INFORMATION info;
372
373     hdc = GetDC(0);
374     screen_depth = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
375
376     memset(pbmi, 0, sizeof(bmibuf));
377     pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
378     pbmi->bmiHeader.biHeight = 100;
379     pbmi->bmiHeader.biWidth = 512;
380     pbmi->bmiHeader.biBitCount = 24;
381     pbmi->bmiHeader.biPlanes = 1;
382     pbmi->bmiHeader.biCompression = BI_RGB;
383
384     SetLastError(0xdeadbeef);
385     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
386     ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
387     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
388     ok(dibsec.dsBm.bmBits == bits, "dibsec.dsBits %p != bits %p\n", dibsec.dsBm.bmBits, bits);
389
390     /* test the DIB memory */
391     ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
392         "VirtualQuery failed\n");
393     ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
394     ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
395     ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
396     ok(info.RegionSize == 0x26000, "0x%lx != 0x26000\n", info.RegionSize);
397     ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
398     ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
399     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
400
401     test_dib_info(hdib, bits, &pbmi->bmiHeader);
402     DeleteObject(hdib);
403
404     pbmi->bmiHeader.biBitCount = 8;
405     pbmi->bmiHeader.biCompression = BI_RLE8;
406     SetLastError(0xdeadbeef);
407     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
408     ok(hdib == NULL, "CreateDIBSection should fail when asked to create a compressed DIB section\n");
409     ok(GetLastError() == 0xdeadbeef, "wrong error %d\n", GetLastError());
410
411     pbmi->bmiHeader.biBitCount = 16;
412     pbmi->bmiHeader.biCompression = BI_BITFIELDS;
413     ((PDWORD)pbmi->bmiColors)[0] = 0xf800;
414     ((PDWORD)pbmi->bmiColors)[1] = 0x07e0;
415     ((PDWORD)pbmi->bmiColors)[2] = 0x001f;
416     SetLastError(0xdeadbeef);
417     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
418     ok(hdib != NULL, "CreateDIBSection error %d\n", GetLastError());
419
420     /* test the DIB memory */
421     ok(VirtualQuery(bits, &info, sizeof(info)) == sizeof(info),
422         "VirtualQuery failed\n");
423     ok(info.BaseAddress == bits, "%p != %p\n", info.BaseAddress, bits);
424     ok(info.AllocationBase == bits, "%p != %p\n", info.AllocationBase, bits);
425     ok(info.AllocationProtect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.AllocationProtect);
426     ok(info.RegionSize == 0x19000, "0x%lx != 0x19000\n", info.RegionSize);
427     ok(info.State == MEM_COMMIT, "%x != MEM_COMMIT\n", info.State);
428     ok(info.Protect == PAGE_READWRITE, "%x != PAGE_READWRITE\n", info.Protect);
429     ok(info.Type == MEM_PRIVATE, "%x != MEM_PRIVATE\n", info.Type);
430
431     test_dib_info(hdib, bits, &pbmi->bmiHeader);
432     DeleteObject(hdib);
433
434     memset(pbmi, 0, sizeof(bmibuf));
435     pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
436     pbmi->bmiHeader.biHeight = 16;
437     pbmi->bmiHeader.biWidth = 16;
438     pbmi->bmiHeader.biBitCount = 1;
439     pbmi->bmiHeader.biPlanes = 1;
440     pbmi->bmiHeader.biCompression = BI_RGB;
441     pbmi->bmiColors[0].rgbRed = 0xff;
442     pbmi->bmiColors[0].rgbGreen = 0;
443     pbmi->bmiColors[0].rgbBlue = 0;
444     pbmi->bmiColors[1].rgbRed = 0;
445     pbmi->bmiColors[1].rgbGreen = 0;
446     pbmi->bmiColors[1].rgbBlue = 0xff;
447
448     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
449     ok(hdib != NULL, "CreateDIBSection failed\n");
450     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIBSection\n");
451     ok(dibsec.dsBmih.biClrUsed == 2,
452         "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
453
454     /* Test if the old BITMAPCOREINFO structure is supported */    
455         
456     pbci->bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
457     pbci->bmciHeader.bcBitCount = 0;
458
459     if (!is_win9x) {
460         ret = GetDIBits(hdc, hdib, 0, 16, NULL, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
461         ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
462         ok((pbci->bmciHeader.bcWidth == 16) && (pbci->bmciHeader.bcHeight == 16)
463             && (pbci->bmciHeader.bcBitCount == 1) && (pbci->bmciHeader.bcPlanes == 1),
464         "GetDIBits did't fill in the BITMAPCOREHEADER structure properly\n");
465
466         ret = GetDIBits(hdc, hdib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
467         ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
468         ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
469             (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
470             (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
471             "The color table has not been translated to the old BITMAPCOREINFO format\n");
472
473         hcoredib = CreateDIBSection(hdc, (BITMAPINFO*) pbci, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
474         ok(hcoredib != NULL, "CreateDIBSection failed with a BITMAPCOREINFO\n");
475
476         ZeroMemory(pbci->bmciColors, 256 * sizeof(RGBTRIPLE));
477         ret = GetDIBits(hdc, hcoredib, 0, 16, &coreBits, (BITMAPINFO*) pbci, DIB_RGB_COLORS);
478         ok(ret, "GetDIBits doesn't work with a BITMAPCOREHEADER\n");
479         ok((pbci->bmciColors[0].rgbtRed == 0xff) && (pbci->bmciColors[0].rgbtGreen == 0) &&
480             (pbci->bmciColors[0].rgbtBlue == 0) && (pbci->bmciColors[1].rgbtRed == 0) &&
481             (pbci->bmciColors[1].rgbtGreen == 0) && (pbci->bmciColors[1].rgbtBlue == 0xff),
482             "The color table has not been translated to the old BITMAPCOREINFO format\n");
483
484         DeleteObject(hcoredib);
485     }
486
487     hdcmem = CreateCompatibleDC(hdc);
488     oldbm = SelectObject(hdcmem, hdib);
489
490     ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
491     ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
492     ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
493        "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
494        rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
495        rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
496
497     c0 = RGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen, pbmi->bmiColors[0].rgbBlue);
498     c1 = RGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen, pbmi->bmiColors[1].rgbBlue);
499
500     test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
501     test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
502     test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
503     test_color(hdcmem, PALETTEINDEX(0), c0, 1, 1);
504     test_color(hdcmem, PALETTEINDEX(1), c0, 1, 1);
505     test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
506     test_color(hdcmem, PALETTERGB(pbmi->bmiColors[0].rgbRed, pbmi->bmiColors[0].rgbGreen,
507         pbmi->bmiColors[0].rgbBlue), c0, 1, 1);
508     test_color(hdcmem, PALETTERGB(pbmi->bmiColors[1].rgbRed, pbmi->bmiColors[1].rgbGreen,
509         pbmi->bmiColors[1].rgbBlue), c1, 1, 1);
510     test_color(hdcmem, PALETTERGB(0, 0, 0), c0, 1, 1);
511     test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
512     test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c1, 1, 1);
513
514     SelectObject(hdcmem, oldbm);
515     DeleteObject(hdib);
516
517     pbmi->bmiColors[0].rgbRed = 0xff;
518     pbmi->bmiColors[0].rgbGreen = 0xff;
519     pbmi->bmiColors[0].rgbBlue = 0xff;
520     pbmi->bmiColors[1].rgbRed = 0;
521     pbmi->bmiColors[1].rgbGreen = 0;
522     pbmi->bmiColors[1].rgbBlue = 0;
523
524     hdib = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
525     ok(hdib != NULL, "CreateDIBSection failed\n");
526
527     test_dib_info(hdib, bits, &pbmi->bmiHeader);
528
529     oldbm = SelectObject(hdcmem, hdib);
530
531     ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
532     ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
533     ok(!memcmp(rgb, pbmi->bmiColors, 2 * sizeof(RGBQUAD)),
534        "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
535        rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
536        rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
537
538     SelectObject(hdcmem, oldbm);
539     test_dib_info(hdib, bits, &pbmi->bmiHeader);
540     DeleteObject(hdib);
541
542     pbmi->bmiHeader.biBitCount = 4;
543     for (i = 0; i < 16; i++) {
544         pbmi->bmiColors[i].rgbRed = i;
545         pbmi->bmiColors[i].rgbGreen = 16-i;
546         pbmi->bmiColors[i].rgbBlue = 0;
547     }
548     hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
549     ok(hdib != NULL, "CreateDIBSection failed\n");
550     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
551     ok(dibsec.dsBmih.biClrUsed == 16,
552        "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 16);
553     test_dib_info(hdib, bits, &pbmi->bmiHeader);
554     DeleteObject(hdib);
555
556     pbmi->bmiHeader.biBitCount = 8;
557
558     for (i = 0; i < 128; i++) {
559         pbmi->bmiColors[i].rgbRed = 255 - i * 2;
560         pbmi->bmiColors[i].rgbGreen = i * 2;
561         pbmi->bmiColors[i].rgbBlue = 0;
562         pbmi->bmiColors[255 - i].rgbRed = 0;
563         pbmi->bmiColors[255 - i].rgbGreen = i * 2;
564         pbmi->bmiColors[255 - i].rgbBlue = 255 - i * 2;
565     }
566     hdib = CreateDIBSection(hdcmem, pbmi, DIB_RGB_COLORS, (void**)&bits, NULL, 0);
567     ok(hdib != NULL, "CreateDIBSection failed\n");
568     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
569     ok(dibsec.dsBmih.biClrUsed == 256,
570         "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
571
572     oldbm = SelectObject(hdcmem, hdib);
573
574     for (i = 0; i < 256; i++) {
575         test_color(hdcmem, DIBINDEX(i), 
576             RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
577         test_color(hdcmem, PALETTERGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 
578             RGB(pbmi->bmiColors[i].rgbRed, pbmi->bmiColors[i].rgbGreen, pbmi->bmiColors[i].rgbBlue), 0, 0);
579     }
580
581     SelectObject(hdcmem, oldbm);
582     test_dib_info(hdib, bits, &pbmi->bmiHeader);
583     DeleteObject(hdib);
584
585     pbmi->bmiHeader.biBitCount = 1;
586
587     /* Now create a palette and a palette indexed dib section */
588     memset(plogpal, 0, sizeof(logpalbuf));
589     plogpal->palVersion = 0x300;
590     plogpal->palNumEntries = 2;
591     plogpal->palPalEntry[0].peRed = 0xff;
592     plogpal->palPalEntry[0].peBlue = 0xff;
593     plogpal->palPalEntry[1].peGreen = 0xff;
594
595     index = (WORD*)pbmi->bmiColors;
596     *index++ = 0;
597     *index = 1;
598     hpal = CreatePalette(plogpal);
599     ok(hpal != NULL, "CreatePalette failed\n");
600     oldpal = SelectPalette(hdc, hpal, TRUE);
601     hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
602     ok(hdib != NULL, "CreateDIBSection failed\n");
603     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
604     ok(dibsec.dsBmih.biClrUsed == 2,
605         "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 2);
606
607     /* The colour table has already been grabbed from the dc, so we select back the
608        old palette */
609
610     SelectPalette(hdc, oldpal, TRUE);
611     oldbm = SelectObject(hdcmem, hdib);
612     oldpal = SelectPalette(hdcmem, hpal, TRUE);
613
614     ret = GetDIBColorTable(hdcmem, 0, 2, rgb);
615     ok(ret == 2, "GetDIBColorTable returned %d\n", ret);
616     ok(rgb[0].rgbRed == 0xff && rgb[0].rgbBlue == 0xff && rgb[0].rgbGreen == 0 &&
617        rgb[1].rgbRed == 0    && rgb[1].rgbBlue == 0    && rgb[1].rgbGreen == 0xff,
618        "GetDIBColorTable returns table 0: r%02x g%02x b%02x res%02x 1: r%02x g%02x b%02x res%02x\n",
619        rgb[0].rgbRed, rgb[0].rgbGreen, rgb[0].rgbBlue, rgb[0].rgbReserved,
620        rgb[1].rgbRed, rgb[1].rgbGreen, rgb[1].rgbBlue, rgb[1].rgbReserved);
621
622     c0 = RGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen, plogpal->palPalEntry[0].peBlue);
623     c1 = RGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen, plogpal->palPalEntry[1].peBlue);
624
625     test_color(hdcmem, DIBINDEX(0), c0, 0, 1);
626     test_color(hdcmem, DIBINDEX(1), c1, 0, 1);
627     test_color(hdcmem, DIBINDEX(2), c0, 1, 1);
628     test_color(hdcmem, PALETTEINDEX(0), c0, 0, 1);
629     test_color(hdcmem, PALETTEINDEX(1), c1, 0, 1);
630     test_color(hdcmem, PALETTEINDEX(2), c0, 1, 1);
631     test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[0].peRed, plogpal->palPalEntry[0].peGreen,
632         plogpal->palPalEntry[0].peBlue), c0, 1, 1);
633     test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[1].peRed, plogpal->palPalEntry[1].peGreen,
634         plogpal->palPalEntry[1].peBlue), c1, 1, 1);
635     test_color(hdcmem, PALETTERGB(0, 0, 0), c1, 1, 1);
636     test_color(hdcmem, PALETTERGB(0xff, 0xff, 0xff), c0, 1, 1);
637     test_color(hdcmem, PALETTERGB(0, 0, 0xfe), c0, 1, 1);
638     test_color(hdcmem, PALETTERGB(0, 1, 0), c1, 1, 1);
639     test_color(hdcmem, PALETTERGB(0x3f, 0, 0x3f), c1, 1, 1);
640     test_color(hdcmem, PALETTERGB(0x40, 0, 0x40), c0, 1, 1);
641
642     /* Bottom and 2nd row from top green, everything else magenta */
643     bits[0] = bits[1] = 0xff;
644     bits[13 * 4] = bits[13*4 + 1] = 0xff;
645
646     test_dib_info(hdib, bits, &pbmi->bmiHeader);
647
648     pbmi->bmiHeader.biBitCount = 32;
649
650     hdib2 = CreateDIBSection(NULL, pbmi, DIB_RGB_COLORS, (void **)&bits32, NULL, 0);
651     ok(hdib2 != NULL, "CreateDIBSection failed\n");
652     hdcmem2 = CreateCompatibleDC(hdc);
653     oldbm2 = SelectObject(hdcmem2, hdib2);
654
655     BitBlt(hdcmem2, 0, 0, 16,16, hdcmem, 0, 0, SRCCOPY);
656
657     ok(bits32[0] == 0xff00, "lower left pixel is %08x\n", bits32[0]);
658     ok(bits32[17] == 0xff00ff, "bottom but one, left pixel is %08x\n", bits32[17]);
659
660     SelectObject(hdcmem2, oldbm2);
661     test_dib_info(hdib2, bits32, &pbmi->bmiHeader);
662     DeleteObject(hdib2);
663
664     SelectObject(hdcmem, oldbm);
665     SelectObject(hdcmem, oldpal);
666     DeleteObject(hdib);
667     DeleteObject(hpal);
668
669
670     pbmi->bmiHeader.biBitCount = 8;
671
672     memset(plogpal, 0, sizeof(logpalbuf));
673     plogpal->palVersion = 0x300;
674     plogpal->palNumEntries = 256;
675
676     for (i = 0; i < 128; i++) {
677         plogpal->palPalEntry[i].peRed = 255 - i * 2;
678         plogpal->palPalEntry[i].peBlue = i * 2;
679         plogpal->palPalEntry[i].peGreen = 0;
680         plogpal->palPalEntry[255 - i].peRed = 0;
681         plogpal->palPalEntry[255 - i].peGreen = i * 2;
682         plogpal->palPalEntry[255 - i].peBlue = 255 - i * 2;
683     }
684
685     index = (WORD*)pbmi->bmiColors;
686     for (i = 0; i < 256; i++) {
687         *index++ = i;
688     }
689
690     hpal = CreatePalette(plogpal);
691     ok(hpal != NULL, "CreatePalette failed\n");
692     oldpal = SelectPalette(hdc, hpal, TRUE);
693     hdib = CreateDIBSection(hdc, pbmi, DIB_PAL_COLORS, (void**)&bits, NULL, 0);
694     ok(hdib != NULL, "CreateDIBSection failed\n");
695     ok(GetObject(hdib, sizeof(DIBSECTION), &dibsec) != 0, "GetObject failed for DIB Section\n");
696     ok(dibsec.dsBmih.biClrUsed == 256,
697         "created DIBSection: wrong biClrUsed field: %u, should be: %u\n", dibsec.dsBmih.biClrUsed, 256);
698
699     test_dib_info(hdib, bits, &pbmi->bmiHeader);
700
701     SelectPalette(hdc, oldpal, TRUE);
702     oldbm = SelectObject(hdcmem, hdib);
703     oldpal = SelectPalette(hdcmem, hpal, TRUE);
704
705     ret = GetDIBColorTable(hdcmem, 0, 256, rgb);
706     ok(ret == 256, "GetDIBColorTable returned %d\n", ret);
707     for (i = 0; i < 256; i++) {
708         ok(rgb[i].rgbRed == plogpal->palPalEntry[i].peRed && 
709             rgb[i].rgbBlue == plogpal->palPalEntry[i].peBlue && 
710             rgb[i].rgbGreen == plogpal->palPalEntry[i].peGreen, 
711             "GetDIBColorTable returns table %d: r%02x g%02x b%02x res%02x\n",
712             i, rgb[i].rgbRed, rgb[i].rgbGreen, rgb[i].rgbBlue, rgb[i].rgbReserved);
713     }
714
715     for (i = 0; i < 256; i++) {
716         test_color(hdcmem, DIBINDEX(i), 
717             RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
718         test_color(hdcmem, PALETTEINDEX(i), 
719             RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
720         test_color(hdcmem, PALETTERGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 
721             RGB(plogpal->palPalEntry[i].peRed, plogpal->palPalEntry[i].peGreen, plogpal->palPalEntry[i].peBlue), 0, 0);
722     }
723
724     SelectPalette(hdcmem, oldpal, TRUE);
725     SelectObject(hdcmem, oldbm);
726     DeleteObject(hdib);
727     DeleteObject(hpal);
728
729
730     DeleteDC(hdcmem);
731     ReleaseDC(0, hdc);
732 }    
733
734 void test_mono_dibsection(void)
735 {
736     HDC hdc, memdc;
737     HBITMAP old_bm, mono_ds;
738     char bmibuf[sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)];
739     BITMAPINFO *pbmi = (BITMAPINFO *)bmibuf;
740     BYTE bits[10 * 4];
741     BYTE *ds_bits;
742     int num;
743
744     hdc = GetDC(0);
745
746     memdc = CreateCompatibleDC(hdc);
747
748     memset(pbmi, 0, sizeof(bmibuf));
749     pbmi->bmiHeader.biSize = sizeof(pbmi->bmiHeader);
750     pbmi->bmiHeader.biHeight = 10;
751     pbmi->bmiHeader.biWidth = 10;
752     pbmi->bmiHeader.biBitCount = 1;
753     pbmi->bmiHeader.biPlanes = 1;
754     pbmi->bmiHeader.biCompression = BI_RGB;
755     pbmi->bmiColors[0].rgbRed = 0xff;
756     pbmi->bmiColors[0].rgbGreen = 0xff;
757     pbmi->bmiColors[0].rgbBlue = 0xff;
758     pbmi->bmiColors[1].rgbRed = 0x0;
759     pbmi->bmiColors[1].rgbGreen = 0x0;
760     pbmi->bmiColors[1].rgbBlue = 0x0;
761
762     /*
763      * First dib section is 'inverted' ie color[0] is white, color[1] is black
764      */
765
766     mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
767     ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
768     old_bm = SelectObject(memdc, mono_ds);
769
770     /* black border, white interior */
771     Rectangle(memdc, 0, 0, 10, 10);
772     ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
773     ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
774
775     /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
776
777     memset(bits, 0, sizeof(bits));
778     bits[0] = 0xaa;
779
780     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
781     ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
782
783     /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
784
785     pbmi->bmiColors[0].rgbRed = 0x0;
786     pbmi->bmiColors[0].rgbGreen = 0x0;
787     pbmi->bmiColors[0].rgbBlue = 0x0;
788     pbmi->bmiColors[1].rgbRed = 0xff;
789     pbmi->bmiColors[1].rgbGreen = 0xff;
790     pbmi->bmiColors[1].rgbBlue = 0xff;
791
792     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
793     ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
794
795     SelectObject(memdc, old_bm);
796     DeleteObject(mono_ds);
797
798     /*
799      * Next dib section is 'normal' ie color[0] is black, color[1] is white
800      */
801
802     pbmi->bmiColors[0].rgbRed = 0x0;
803     pbmi->bmiColors[0].rgbGreen = 0x0;
804     pbmi->bmiColors[0].rgbBlue = 0x0;
805     pbmi->bmiColors[1].rgbRed = 0xff;
806     pbmi->bmiColors[1].rgbGreen = 0xff;
807     pbmi->bmiColors[1].rgbBlue = 0xff;
808
809     mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
810     ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
811     old_bm = SelectObject(memdc, mono_ds);
812
813     /* black border, white interior */
814     Rectangle(memdc, 0, 0, 10, 10);
815     ok(ds_bits[0] == 0x00, "out_bits %02x\n", ds_bits[0]);
816     ok(ds_bits[4] == 0x7f, "out_bits %02x\n", ds_bits[4]);
817
818     /* SetDIBitsToDevice with a normal bmi -> normal dib section */
819
820     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
821     ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
822
823     /* SetDIBitsToDevice with a inverted bmi -> normal dib section */
824
825     pbmi->bmiColors[0].rgbRed = 0xff;
826     pbmi->bmiColors[0].rgbGreen = 0xff;
827     pbmi->bmiColors[0].rgbBlue = 0xff;
828     pbmi->bmiColors[1].rgbRed = 0x0;
829     pbmi->bmiColors[1].rgbGreen = 0x0;
830     pbmi->bmiColors[1].rgbBlue = 0x0;
831
832     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
833     ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
834
835     /*
836      * Take that 'normal' dibsection and change its colour table to an 'inverted' one
837      */
838
839     pbmi->bmiColors[0].rgbRed = 0xff;
840     pbmi->bmiColors[0].rgbGreen = 0xff;
841     pbmi->bmiColors[0].rgbBlue = 0xff;
842     pbmi->bmiColors[1].rgbRed = 0x0;
843     pbmi->bmiColors[1].rgbGreen = 0x0;
844     pbmi->bmiColors[1].rgbBlue = 0x0;
845     num = SetDIBColorTable(memdc, 0, 2, pbmi->bmiColors);
846     ok(num == 2, "num = %d\n", num);
847
848     /* black border, white interior */
849     Rectangle(memdc, 0, 0, 10, 10);
850 todo_wine {
851     ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
852     ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
853  }
854     /* SetDIBitsToDevice with an inverted bmi -> inverted dib section */
855
856     memset(bits, 0, sizeof(bits));
857     bits[0] = 0xaa;
858
859     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
860     ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
861
862     /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
863
864     pbmi->bmiColors[0].rgbRed = 0x0;
865     pbmi->bmiColors[0].rgbGreen = 0x0;
866     pbmi->bmiColors[0].rgbBlue = 0x0;
867     pbmi->bmiColors[1].rgbRed = 0xff;
868     pbmi->bmiColors[1].rgbGreen = 0xff;
869     pbmi->bmiColors[1].rgbBlue = 0xff;
870
871     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
872     ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
873
874     SelectObject(memdc, old_bm);
875     DeleteObject(mono_ds);
876
877     /*
878      * Now a dib section with a strange colour map just for fun.  This behaves just like an inverted one.
879      */
880  
881     pbmi->bmiColors[0].rgbRed = 0xff;
882     pbmi->bmiColors[0].rgbGreen = 0x0;
883     pbmi->bmiColors[0].rgbBlue = 0x0;
884     pbmi->bmiColors[1].rgbRed = 0xfe;
885     pbmi->bmiColors[1].rgbGreen = 0x0;
886     pbmi->bmiColors[1].rgbBlue = 0x0;
887
888     mono_ds = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, (void**)&ds_bits, NULL, 0);
889     ok(mono_ds != NULL, "CreateDIBSection rets NULL\n");
890     old_bm = SelectObject(memdc, mono_ds);
891
892     /* black border, white interior */
893     Rectangle(memdc, 0, 0, 10, 10);
894     ok(ds_bits[0] == 0xff, "out_bits %02x\n", ds_bits[0]);
895     ok(ds_bits[4] == 0x80, "out_bits %02x\n", ds_bits[4]);
896
897     /* SetDIBitsToDevice with a normal bmi -> inverted dib section */
898
899     pbmi->bmiColors[0].rgbRed = 0x0;
900     pbmi->bmiColors[0].rgbGreen = 0x0;
901     pbmi->bmiColors[0].rgbBlue = 0x0;
902     pbmi->bmiColors[1].rgbRed = 0xff;
903     pbmi->bmiColors[1].rgbGreen = 0xff;
904     pbmi->bmiColors[1].rgbBlue = 0xff;
905
906     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
907     ok(ds_bits[0] == 0x55, "out_bits %02x\n", ds_bits[0]);
908
909     /* SetDIBitsToDevice with a inverted bmi -> inverted dib section */
910
911     pbmi->bmiColors[0].rgbRed = 0xff;
912     pbmi->bmiColors[0].rgbGreen = 0xff;
913     pbmi->bmiColors[0].rgbBlue = 0xff;
914     pbmi->bmiColors[1].rgbRed = 0x0;
915     pbmi->bmiColors[1].rgbGreen = 0x0;
916     pbmi->bmiColors[1].rgbBlue = 0x0;
917
918     SetDIBitsToDevice(memdc, 0, 0, 10, 10, 0, 0, 0, 10, bits, pbmi, DIB_RGB_COLORS);
919     ok(ds_bits[0] == 0xaa, "out_bits %02x\n", ds_bits[0]);
920
921     SelectObject(memdc, old_bm);
922     DeleteObject(mono_ds);
923
924     DeleteDC(memdc);
925     ReleaseDC(0, hdc);
926 }
927
928 static void test_bitmap(void)
929 {
930     char buf[256], buf_cmp[256];
931     HBITMAP hbmp, hbmp_old;
932     HDC hdc;
933     BITMAP bm;
934     INT ret;
935
936     hdc = CreateCompatibleDC(0);
937     assert(hdc != 0);
938
939     hbmp = CreateBitmap(15, 15, 1, 1, NULL);
940     assert(hbmp != NULL);
941
942     ret = GetObject(hbmp, sizeof(bm), &bm);
943     ok(ret == sizeof(bm), "wrong size %d\n", ret);
944
945     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
946     ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
947     ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
948     ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
949     ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
950     ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
951     ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
952
953     assert(sizeof(buf) >= bm.bmWidthBytes * bm.bmHeight);
954     assert(sizeof(buf) == sizeof(buf_cmp));
955
956     ret = GetBitmapBits(hbmp, 0, NULL);
957     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
958
959     memset(buf_cmp, 0xAA, sizeof(buf_cmp));
960     memset(buf_cmp, 0, bm.bmWidthBytes * bm.bmHeight);
961
962     memset(buf, 0xAA, sizeof(buf));
963     ret = GetBitmapBits(hbmp, sizeof(buf), buf);
964     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
965     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
966
967     hbmp_old = SelectObject(hdc, hbmp);
968
969     ret = GetObject(hbmp, sizeof(bm), &bm);
970     ok(ret == sizeof(bm), "wrong size %d\n", ret);
971
972     ok(bm.bmType == 0, "wrong bm.bmType %d\n", bm.bmType);
973     ok(bm.bmWidth == 15, "wrong bm.bmWidth %d\n", bm.bmWidth);
974     ok(bm.bmHeight == 15, "wrong bm.bmHeight %d\n", bm.bmHeight);
975     ok(bm.bmWidthBytes == 2, "wrong bm.bmWidthBytes %d\n", bm.bmWidthBytes);
976     ok(bm.bmPlanes == 1, "wrong bm.bmPlanes %d\n", bm.bmPlanes);
977     ok(bm.bmBitsPixel == 1, "wrong bm.bmBitsPixel %d\n", bm.bmBitsPixel);
978     ok(bm.bmBits == NULL, "wrong bm.bmBits %p\n", bm.bmBits);
979
980     memset(buf, 0xAA, sizeof(buf));
981     ret = GetBitmapBits(hbmp, sizeof(buf), buf);
982     ok(ret == bm.bmWidthBytes * bm.bmHeight, "%d != %d\n", ret, bm.bmWidthBytes * bm.bmHeight);
983     ok(!memcmp(buf, buf_cmp, sizeof(buf)), "buffers do not match\n");
984
985     hbmp_old = SelectObject(hdc, hbmp_old);
986     ok(hbmp_old == hbmp, "wrong old bitmap %p\n", hbmp_old);
987
988     /* test various buffer sizes for GetObject */
989     ret = GetObject(hbmp, sizeof(bm) * 2, &bm);
990     ok(ret == sizeof(bm), "wrong size %d\n", ret);
991
992     ret = GetObject(hbmp, sizeof(bm) / 2, &bm);
993     ok(ret == 0, "%d != 0\n", ret);
994
995     ret = GetObject(hbmp, 0, &bm);
996     ok(ret == 0, "%d != 0\n", ret);
997
998     ret = GetObject(hbmp, 1, &bm);
999     ok(ret == 0, "%d != 0\n", ret);
1000
1001     DeleteObject(hbmp);
1002     DeleteDC(hdc);
1003 }
1004
1005 static void test_bmBits(void)
1006 {
1007     BYTE bits[4];
1008     HBITMAP hbmp;
1009     BITMAP bmp;
1010
1011     memset(bits, 0, sizeof(bits));
1012     hbmp = CreateBitmap(2, 2, 1, 4, bits);
1013     ok(hbmp != NULL, "CreateBitmap failed\n");
1014
1015     memset(&bmp, 0xFF, sizeof(bmp));
1016     ok(GetObject(hbmp, sizeof(bmp), &bmp) == sizeof(bmp),
1017        "GetObject failed or returned a wrong structure size\n");
1018     ok(!bmp.bmBits, "bmBits must be NULL for device-dependent bitmaps\n");
1019
1020     DeleteObject(hbmp);
1021 }
1022
1023 static void test_GetDIBits_selected_DIB(UINT bpp)
1024 {
1025     HBITMAP dib;
1026     BITMAPINFO * info;
1027     BITMAPINFO * info2;
1028     void * bits;
1029     void * bits2;
1030     UINT dib_size;
1031     HDC dib_dc, dc;
1032     HBITMAP old_bmp;
1033     BOOL equalContents;
1034     UINT i;
1035     int res;
1036
1037     /* Create a DIB section with a color table */
1038
1039     info  = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1040     info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + (1 << bpp) * sizeof(RGBQUAD));
1041     assert(info);
1042     assert(info2);
1043
1044     info->bmiHeader.biSize = sizeof(info->bmiHeader);
1045
1046     /* Choose width and height such that the row length (in bytes)
1047        is a multiple of 4 (makes things easier) */
1048     info->bmiHeader.biWidth = 32;
1049     info->bmiHeader.biHeight = 32;
1050     info->bmiHeader.biPlanes = 1;
1051     info->bmiHeader.biBitCount = bpp;
1052     info->bmiHeader.biCompression = BI_RGB;
1053
1054     for (i=0; i < (1 << bpp); i++)
1055     {
1056         BYTE c = i * (1 << (8 - bpp));
1057         info->bmiColors[i].rgbRed = c;
1058         info->bmiColors[i].rgbGreen = c;
1059         info->bmiColors[i].rgbBlue = c;
1060         info->bmiColors[i].rgbReserved = 0;
1061     }
1062
1063     dib = CreateDIBSection(NULL, info, DIB_RGB_COLORS, &bits, NULL, 0);
1064     assert(dib);
1065     dib_size = bpp * (info->bmiHeader.biWidth * info->bmiHeader.biHeight) / 8;
1066
1067     /* Set the bits of the DIB section */
1068     for (i=0; i < dib_size; i++)
1069     {
1070         ((BYTE *)bits)[i] = i % 256;
1071     }
1072
1073     /* Select the DIB into a DC */
1074     dib_dc = CreateCompatibleDC(NULL);
1075     old_bmp = (HBITMAP) SelectObject(dib_dc, dib);
1076     dc = CreateCompatibleDC(NULL);
1077     bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dib_size);
1078     assert(bits2);
1079
1080     /* Copy the DIB attributes but not the color table */
1081     memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1082
1083     res = GetDIBits(dc, dib, 0, info->bmiHeader.biHeight, bits2, info2, DIB_RGB_COLORS);
1084     ok(res, "GetDIBits failed\n");
1085
1086     /* Compare the color table and the bits */
1087     equalContents = TRUE;
1088     for (i=0; i < (1 << bpp); i++)
1089     {
1090         if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1091             || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1092             || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1093             || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1094         {
1095             equalContents = FALSE;
1096             break;
1097         }
1098     }
1099     todo_wine
1100     {
1101         ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB color table\n");
1102     }
1103
1104     equalContents = TRUE;
1105     for (i=0; i < dib_size / sizeof(DWORD); i++)
1106     {
1107         if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1108         {
1109             equalContents = FALSE;
1110             break;
1111         }
1112     }
1113     todo_wine
1114     {
1115         ok(equalContents, "GetDIBits with DIB selected in DC: Invalid DIB bits\n");
1116     }
1117
1118     HeapFree(GetProcessHeap(), 0, bits2);
1119     DeleteDC(dc);
1120
1121     SelectObject(dib_dc, old_bmp);
1122     DeleteDC(dib_dc);
1123     DeleteObject(dib);
1124
1125     HeapFree(GetProcessHeap(), 0, info2);
1126     HeapFree(GetProcessHeap(), 0, info);
1127 }
1128
1129 static void test_GetDIBits_selected_DDB(BOOL monochrome)
1130 {
1131     HBITMAP ddb;
1132     BITMAPINFO * info;
1133     BITMAPINFO * info2;
1134     void * bits;
1135     void * bits2;
1136     HDC ddb_dc, dc;
1137     HBITMAP old_bmp;
1138     BOOL equalContents;
1139     UINT width, height;
1140     UINT bpp;
1141     UINT i, j;
1142     int res;
1143
1144     width = height = 16;
1145
1146     /* Create a DDB (device-dependent bitmap) */
1147     if (monochrome)
1148     {
1149         bpp = 1;
1150         ddb = CreateBitmap(width, height, 1, 1, NULL);
1151     }
1152     else
1153     {
1154         HDC screen_dc = GetDC(NULL);
1155         bpp = GetDeviceCaps(screen_dc, BITSPIXEL) * GetDeviceCaps(screen_dc, PLANES);
1156         ddb = CreateCompatibleBitmap(screen_dc, width, height);
1157         ReleaseDC(NULL, screen_dc);
1158     }
1159
1160     /* Set the pixels */
1161     ddb_dc = CreateCompatibleDC(NULL);
1162     old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
1163     for (i = 0; i < width; i++)
1164     {
1165         for (j=0; j < height; j++)
1166         {
1167             BYTE c = (i * width + j) % 256;
1168             SetPixelV(ddb_dc, i, j, RGB(c, c, c));
1169         }
1170     }
1171     SelectObject(ddb_dc, old_bmp);
1172
1173     info  = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1174     info2 = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
1175     assert(info);
1176     assert(info2);
1177
1178     info->bmiHeader.biSize = sizeof(info->bmiHeader);
1179     info->bmiHeader.biWidth = width;
1180     info->bmiHeader.biHeight = height;
1181     info->bmiHeader.biPlanes = 1;
1182     info->bmiHeader.biBitCount = bpp;
1183     info->bmiHeader.biCompression = BI_RGB;
1184
1185     dc = CreateCompatibleDC(NULL);
1186
1187     /* Fill in biSizeImage */
1188     GetDIBits(dc, ddb, 0, height, NULL, info, DIB_RGB_COLORS);
1189     ok(info->bmiHeader.biSizeImage != 0, "GetDIBits failed to get the DIB attributes\n");
1190
1191     bits = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1192     bits2 = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, info->bmiHeader.biSizeImage);
1193     assert(bits);
1194     assert(bits2);
1195
1196     /* Get the bits */
1197     res = GetDIBits(dc, ddb, 0, height, bits, info, DIB_RGB_COLORS);
1198     ok(res, "GetDIBits failed\n");
1199
1200     /* Copy the DIB attributes but not the color table */
1201     memcpy(info2, info, sizeof(BITMAPINFOHEADER));
1202
1203     /* Select the DDB into another DC */
1204     old_bmp = (HBITMAP) SelectObject(ddb_dc, ddb);
1205
1206     /* Get the bits */
1207     res = GetDIBits(dc, ddb, 0, height, bits2, info2, DIB_RGB_COLORS);
1208     ok(res, "GetDIBits failed\n");
1209
1210     /* Compare the color table and the bits */
1211     if (bpp <= 8)
1212     {
1213         equalContents = TRUE;
1214         for (i=0; i < (1 << bpp); i++)
1215         {
1216             if ((info->bmiColors[i].rgbRed != info2->bmiColors[i].rgbRed)
1217                 || (info->bmiColors[i].rgbGreen != info2->bmiColors[i].rgbGreen)
1218                 || (info->bmiColors[i].rgbBlue != info2->bmiColors[i].rgbBlue)
1219                 || (info->bmiColors[i].rgbReserved != info2->bmiColors[i].rgbReserved))
1220             {
1221                 equalContents = FALSE;
1222                 break;
1223             }
1224         }
1225         ok(equalContents, "GetDIBits with DDB selected in DC: Got a different color table\n");
1226     }
1227
1228     equalContents = TRUE;
1229     for (i=0; i < info->bmiHeader.biSizeImage / sizeof(DWORD); i++)
1230     {
1231         if (((DWORD *)bits)[i] != ((DWORD *)bits2)[i])
1232         {
1233             equalContents = FALSE;
1234         }
1235     }
1236     ok(equalContents, "GetDIBits with DDB selected in DC: Got different DIB bits\n");
1237
1238     HeapFree(GetProcessHeap(), 0, bits2);
1239     HeapFree(GetProcessHeap(), 0, bits);
1240     DeleteDC(dc);
1241
1242     SelectObject(ddb_dc, old_bmp);
1243     DeleteDC(ddb_dc);
1244     DeleteObject(ddb);
1245
1246     HeapFree(GetProcessHeap(), 0, info2);
1247     HeapFree(GetProcessHeap(), 0, info);
1248 }
1249
1250 START_TEST(bitmap)
1251 {
1252     is_win9x = GetWindowLongPtrW(GetDesktopWindow(), GWLP_WNDPROC) == 0;
1253
1254     test_createdibitmap();
1255     test_dibsections();
1256     test_mono_dibsection();
1257     test_bitmap();
1258     test_bmBits();
1259     test_GetDIBits_selected_DIB(1);
1260     test_GetDIBits_selected_DIB(4);
1261     test_GetDIBits_selected_DIB(8);
1262     test_GetDIBits_selected_DDB(TRUE);
1263     test_GetDIBits_selected_DDB(FALSE);
1264 }