shell32/tests: Add verification of FOLDERID_ProgramFilesX64 and FOLDERID_ProgramFiles...
[wine] / dlls / gdi32 / dib.c
1 /*
2  * GDI device-independent bitmaps
3  *
4  * Copyright 1993,1994  Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 /*
22   Important information:
23   
24   * Current Windows versions support two different DIB structures:
25
26     - BITMAPCOREINFO / BITMAPCOREHEADER (legacy structures; used in OS/2)
27     - BITMAPINFO / BITMAPINFOHEADER
28   
29     Most Windows API functions taking a BITMAPINFO* / BITMAPINFOHEADER* also
30     accept the old "core" structures, and so must WINE.
31     You can distinguish them by looking at the first member (bcSize/biSize).
32
33     
34   * The palettes are stored in different formats:
35
36     - BITMAPCOREINFO: Array of RGBTRIPLE
37     - BITMAPINFO:     Array of RGBQUAD
38
39     
40   * There are even more DIB headers, but they all extend BITMAPINFOHEADER:
41     
42     - BITMAPV4HEADER: Introduced in Windows 95 / NT 4.0
43     - BITMAPV5HEADER: Introduced in Windows 98 / 2000
44     
45     If biCompression is BI_BITFIELDS, the color masks are at the same position
46     in all the headers (they start at bmiColors of BITMAPINFOHEADER), because
47     the new headers have structure members for the masks.
48
49
50   * You should never access the color table using the bmiColors member,
51     because the passed structure may have one of the extended headers
52     mentioned above. Use this to calculate the location:
53     
54     BITMAPINFO* info;
55     void* colorPtr = (LPBYTE) info + (WORD) info->bmiHeader.biSize;
56
57     
58   * More information:
59     Search for "Bitmap Structures" in MSDN
60 */
61
62 #include <stdarg.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <assert.h>
66
67 #include "windef.h"
68 #include "winbase.h"
69 #include "gdi_private.h"
70 #include "wine/debug.h"
71
72 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
73
74
75 /***********************************************************************
76  *           bitmap_info_size
77  *
78  * Return the size of the bitmap info structure including color table.
79  */
80 int bitmap_info_size( const BITMAPINFO * info, WORD coloruse )
81 {
82     unsigned int colors, size, masks = 0;
83
84     if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
85     {
86         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
87         colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
88         return sizeof(BITMAPCOREHEADER) + colors *
89              ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
90     }
91     else  /* assume BITMAPINFOHEADER */
92     {
93         colors = get_dib_num_of_colors( info );
94         if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
95         size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
96         return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
97     }
98 }
99
100 /*******************************************************************************************
101  *  Fill out a true BITMAPINFOHEADER from a variable sized BITMAPINFOHEADER / BITMAPCOREHEADER.
102  */
103 static BOOL bitmapinfoheader_from_user_bitmapinfo( BITMAPINFOHEADER *dst, const BITMAPINFOHEADER *info )
104 {
105     if (!info) return FALSE;
106
107     if (info->biSize == sizeof(BITMAPCOREHEADER))
108     {
109         const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
110         dst->biWidth         = core->bcWidth;
111         dst->biHeight        = core->bcHeight;
112         dst->biPlanes        = core->bcPlanes;
113         dst->biBitCount      = core->bcBitCount;
114         dst->biCompression   = BI_RGB;
115         dst->biXPelsPerMeter = 0;
116         dst->biYPelsPerMeter = 0;
117         dst->biClrUsed       = 0;
118         dst->biClrImportant  = 0;
119     }
120     else if (info->biSize >= sizeof(BITMAPINFOHEADER)) /* assume BITMAPINFOHEADER */
121     {
122         *dst = *info;
123     }
124     else
125     {
126         WARN( "(%u): unknown/wrong size for header\n", info->biSize );
127         return FALSE;
128     }
129
130     dst->biSize = sizeof(*dst);
131     if (dst->biCompression == BI_RGB || dst->biCompression == BI_BITFIELDS)
132         dst->biSizeImage = get_dib_image_size( (BITMAPINFO *)dst );
133     return TRUE;
134 }
135
136 /*******************************************************************************************
137  *  Fill out a true BITMAPINFO from a variable sized BITMAPINFO / BITMAPCOREINFO.
138  */
139 static BOOL bitmapinfo_from_user_bitmapinfo( BITMAPINFO *dst, const BITMAPINFO *info, UINT coloruse )
140 {
141     void *src_colors;
142     unsigned int colors;
143
144     if (!bitmapinfoheader_from_user_bitmapinfo( &dst->bmiHeader, &info->bmiHeader )) return FALSE;
145
146     src_colors = (char *)info + info->bmiHeader.biSize;
147     colors = get_dib_num_of_colors( dst );
148
149     if (info->bmiHeader.biCompression == BI_BITFIELDS)
150     {
151         /* bitfields are always at bmiColors even in larger structures */
152         memcpy( dst->bmiColors, info->bmiColors, 3 * sizeof(DWORD) );
153     }
154     else if (colors)
155     {
156         if (coloruse == DIB_PAL_COLORS)
157             memcpy( dst->bmiColors, src_colors, colors * sizeof(WORD) );
158         else if (info->bmiHeader.biSize != sizeof(BITMAPCOREHEADER))
159             memcpy( dst->bmiColors, src_colors, colors * sizeof(RGBQUAD) );
160         else
161         {
162             unsigned int i;
163             RGBTRIPLE *triple = (RGBTRIPLE *)src_colors;
164             for (i = 0; i < colors; i++)
165             {
166                 dst->bmiColors[i].rgbRed      = triple[i].rgbtRed;
167                 dst->bmiColors[i].rgbGreen    = triple[i].rgbtGreen;
168                 dst->bmiColors[i].rgbBlue     = triple[i].rgbtBlue;
169                 dst->bmiColors[i].rgbReserved = 0;
170             }
171         }
172     }
173     return TRUE;
174 }
175
176 static int fill_color_table_from_palette( BITMAPINFO *info, DC *dc )
177 {
178     PALETTEENTRY palEntry[256];
179     int i, colors = get_dib_num_of_colors( info );
180
181     if (!colors) return 0;
182
183     memset( palEntry, 0, sizeof(palEntry) );
184     if (!GetPaletteEntries( dc->hPalette, 0, colors, palEntry ))
185         return 0;
186
187     for (i = 0; i < colors; i++)
188     {
189         info->bmiColors[i].rgbRed      = palEntry[i].peRed;
190         info->bmiColors[i].rgbGreen    = palEntry[i].peGreen;
191         info->bmiColors[i].rgbBlue     = palEntry[i].peBlue;
192         info->bmiColors[i].rgbReserved = 0;
193     }
194
195     return colors;
196 }
197
198 static void *get_pixel_ptr( const BITMAPINFO *info, void *bits, int x, int y )
199 {
200     const int width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
201     const int bpp = info->bmiHeader.biBitCount;
202
203     if (height > 0)
204         return (char *)bits + (height - y - 1) * get_dib_stride( width, bpp ) + x * bpp / 8;
205     else
206         return (char *)bits + y * get_dib_stride( width, bpp ) + x * bpp / 8;
207 }
208
209 static BOOL build_rle_bitmap( const BITMAPINFO *info, struct gdi_image_bits *bits, HRGN *clip )
210 {
211     int i = 0;
212     int left, right;
213     int x, y, width = info->bmiHeader.biWidth, height = info->bmiHeader.biHeight;
214     HRGN run = NULL;
215     BYTE skip, num, data;
216     BYTE *out_bits, *in_bits = bits->ptr;
217
218     *clip = NULL;
219
220     assert( info->bmiHeader.biBitCount == 4 || info->bmiHeader.biBitCount == 8 );
221
222     out_bits = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ) );
223     *clip = CreateRectRgn( 0, 0, 0, 0 );
224     run   = CreateRectRgn( 0, 0, 0, 0 );
225     if (!out_bits || !*clip || !run) goto fail;
226
227     x = left = right = 0;
228     y = height - 1;
229
230     while (i < info->bmiHeader.biSizeImage - 1)
231     {
232         num = in_bits[i];
233         data = in_bits[i + 1];
234         i += 2;
235
236         if (num)
237         {
238             if (x + num > width) num = width - x;
239             if (num)
240             {
241                 BYTE s = data, *out_ptr = get_pixel_ptr( info, out_bits, x, y );
242                 if (info->bmiHeader.biBitCount == 8)
243                     memset( out_ptr, s, num );
244                 else
245                 {
246                     if(x & 1)
247                     {
248                         s = ((s >> 4) & 0x0f) | ((s << 4) & 0xf0);
249                         *out_ptr = (*out_ptr & 0xf0) | (s & 0x0f);
250                         out_ptr++;
251                         x++;
252                         num--;
253                     }
254                     /* this will write one too many if num is odd, but that doesn't matter */
255                     if (num) memset( out_ptr, s, (num + 1) / 2 );
256                 }
257             }
258             x += num;
259             right = x;
260         }
261         else
262         {
263             if (data < 3)
264             {
265                 if(left != right)
266                 {
267                     SetRectRgn( run, left, y, right, y + 1 );
268                     CombineRgn( *clip, run, *clip, RGN_OR );
269                 }
270                 switch (data)
271                 {
272                 case 0: /* eol */
273                     left = right = x = 0;
274                     y--;
275                     if(y < 0) goto done;
276                     break;
277
278                 case 1: /* eod */
279                     goto done;
280
281                 case 2: /* delta */
282                     if (i >= info->bmiHeader.biSizeImage - 1) goto done;
283                     x += in_bits[i];
284                     if (x > width) x = width;
285                     left = right = x;
286                     y -= in_bits[i + 1];
287                     if(y < 0) goto done;
288                     i += 2;
289                 }
290             }
291             else /* data bytes of data */
292             {
293                 num = data;
294                 skip = (num * info->bmiHeader.biBitCount + 7) / 8;
295                 if (skip > info->bmiHeader.biSizeImage - i) goto done;
296                 skip = (skip + 1) & ~1;
297                 if (x + num > width) num = width - x;
298                 if (num)
299                 {
300                     BYTE *out_ptr = get_pixel_ptr( info, out_bits, x, y );
301                     if (info->bmiHeader.biBitCount == 8)
302                         memcpy( out_ptr, in_bits + i, num );
303                     else
304                     {
305                         if(x & 1)
306                         {
307                             const BYTE *in_ptr = in_bits + i;
308                             for ( ; num; num--, x++)
309                             {
310                                 if (x & 1)
311                                 {
312                                     *out_ptr = (*out_ptr & 0xf0) | ((*in_ptr >> 4) & 0x0f);
313                                     out_ptr++;
314                                 }
315                                 else
316                                     *out_ptr = (*in_ptr++ << 4) & 0xf0;
317                             }
318                         }
319                         else
320                             memcpy( out_ptr, in_bits + i, (num + 1) / 2);
321                     }
322                 }
323                 x += num;
324                 right = x;
325                 i += skip;
326             }
327         }
328     }
329
330 done:
331     DeleteObject( run );
332     if (bits->free) bits->free( bits );
333
334     bits->ptr     = out_bits;
335     bits->is_copy = TRUE;
336     bits->free    = free_heap_bits;
337
338     return TRUE;
339
340 fail:
341     if (run) DeleteObject( run );
342     if (*clip) DeleteObject( *clip );
343     HeapFree( GetProcessHeap(), 0, out_bits );
344     return FALSE;
345 }
346
347
348
349 /* nulldrv fallback implementation using SetDIBits/StretchBlt */
350 INT nulldrv_StretchDIBits( PHYSDEV dev, INT xDst, INT yDst, INT widthDst, INT heightDst,
351                            INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
352                            const BITMAPINFO *info, UINT coloruse, DWORD rop )
353 {
354     DC *dc = get_nulldrv_dc( dev );
355     INT ret;
356     LONG height;
357     HBITMAP hBitmap;
358     HDC hdcMem;
359
360     /* make sure we have a real implementation for StretchBlt and PutImage */
361     if (GET_DC_PHYSDEV( dc, pStretchBlt ) == dev || GET_DC_PHYSDEV( dc, pPutImage ) == dev)
362         return 0;
363
364     if (info->bmiHeader.biWidth < 0) return 0;
365     height = info->bmiHeader.biHeight;
366
367     if (xSrc == 0 && ySrc == 0 && widthDst == widthSrc && heightDst == heightSrc &&
368         info->bmiHeader.biCompression == BI_RGB)
369     {
370         /* Windows appears to have a fast case optimization
371          * that uses the wrong origin for top-down DIBs */
372         if (height < 0 && heightSrc < abs(height)) ySrc = abs(height) - heightSrc;
373
374         if (xDst == 0 && yDst == 0 && info->bmiHeader.biCompression == BI_RGB && rop == SRCCOPY)
375         {
376             BITMAP bm;
377             hBitmap = GetCurrentObject( dev->hdc, OBJ_BITMAP );
378             if (GetObjectW( hBitmap, sizeof(bm), &bm ) &&
379                 bm.bmWidth == widthSrc && bm.bmHeight == heightSrc &&
380                 bm.bmBitsPixel == info->bmiHeader.biBitCount && bm.bmPlanes == 1)
381             {
382                 /* fast path */
383                 return SetDIBits( dev->hdc, hBitmap, 0, abs( height ), bits, info, coloruse );
384             }
385         }
386     }
387
388     hdcMem = CreateCompatibleDC( dev->hdc );
389     hBitmap = CreateCompatibleBitmap( dev->hdc, info->bmiHeader.biWidth, height );
390     SelectObject( hdcMem, hBitmap );
391     if (coloruse == DIB_PAL_COLORS)
392         SelectPalette( hdcMem, GetCurrentObject( dev->hdc, OBJ_PAL ), FALSE );
393
394     if (info->bmiHeader.biCompression == BI_RLE4 || info->bmiHeader.biCompression == BI_RLE8)
395     {
396         /* when RLE compression is used, there may be some gaps (ie the DIB doesn't
397          * contain all the rectangle described in bmiHeader, but only part of it.
398          * This mean that those undescribed pixels must be left untouched.
399          * So, we first copy on a memory bitmap the current content of the
400          * destination rectangle, blit the DIB bits on top of it - hence leaving
401          * the gaps untouched -, and blitting the rectangle back.
402          * This insure that gaps are untouched on the destination rectangle
403          */
404         StretchBlt( hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc,
405                     dev->hdc, xDst, yDst, widthDst, heightDst, rop );
406     }
407     ret = SetDIBits( hdcMem, hBitmap, 0, abs( height ), bits, info, coloruse );
408     if (ret) StretchBlt( dev->hdc, xDst, yDst, widthDst, heightDst,
409                          hdcMem, xSrc, abs(height) - heightSrc - ySrc, widthSrc, heightSrc, rop );
410     DeleteDC( hdcMem );
411     DeleteObject( hBitmap );
412     return ret;
413 }
414
415 /***********************************************************************
416  *           StretchDIBits   (GDI32.@)
417  */
418 INT WINAPI StretchDIBits(HDC hdc, INT xDst, INT yDst, INT widthDst, INT heightDst,
419                          INT xSrc, INT ySrc, INT widthSrc, INT heightSrc, const void *bits,
420                          const BITMAPINFO *bmi, UINT coloruse, DWORD rop )
421 {
422     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
423     BITMAPINFO *info = (BITMAPINFO *)buffer;
424     DC *dc;
425     INT ret = 0;
426
427     if (!bits) return 0;
428     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse )) return 0;
429
430     if ((dc = get_dc_ptr( hdc )))
431     {
432         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pStretchDIBits );
433         update_dc( dc );
434         ret = physdev->funcs->pStretchDIBits( physdev, xDst, yDst, widthDst, heightDst,
435                                               xSrc, ySrc, widthSrc, heightSrc, bits, info, coloruse, rop );
436         release_dc_ptr( dc );
437     }
438     return ret;
439 }
440
441
442 /******************************************************************************
443  * SetDIBits [GDI32.@]
444  *
445  * Sets pixels in a bitmap using colors from DIB.
446  *
447  * PARAMS
448  *    hdc       [I] Handle to device context
449  *    hbitmap   [I] Handle to bitmap
450  *    startscan [I] Starting scan line
451  *    lines     [I] Number of scan lines
452  *    bits      [I] Array of bitmap bits
453  *    info      [I] Address of structure with data
454  *    coloruse  [I] Type of color indexes to use
455  *
456  * RETURNS
457  *    Success: Number of scan lines copied
458  *    Failure: 0
459  */
460 INT WINAPI SetDIBits( HDC hdc, HBITMAP hbitmap, UINT startscan,
461                       UINT lines, LPCVOID bits, const BITMAPINFO *info,
462                       UINT coloruse )
463 {
464     DC *dc = get_dc_ptr( hdc );
465     BOOL delete_hdc = FALSE;
466     PHYSDEV physdev;
467     BITMAPOBJ *bitmap;
468     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
469     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
470     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
471     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
472     INT result = 0;
473     DWORD err;
474     struct gdi_image_bits src_bits;
475     struct bitblt_coords src, dst;
476     INT src_to_dst_offset;
477     HRGN clip = 0;
478     const struct gdi_dc_funcs *funcs;
479
480     src_bits.ptr = (void *)bits;
481     src_bits.is_copy = FALSE;
482     src_bits.free = NULL;
483     src_bits.param = NULL;
484
485     if (coloruse == DIB_RGB_COLORS && !dc)
486     {
487         hdc = CreateCompatibleDC(0);
488         dc = get_dc_ptr( hdc );
489         delete_hdc = TRUE;
490     }
491
492     if (!dc) return 0;
493
494     update_dc( dc );
495
496     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
497     {
498         release_dc_ptr( dc );
499         if (delete_hdc) DeleteDC(hdc);
500         return 0;
501     }
502
503     if (!bitmapinfo_from_user_bitmapinfo( src_info, info, coloruse )) goto done;
504
505     if (coloruse == DIB_PAL_COLORS)
506         if (!fill_color_table_from_palette( src_info, dc )) goto done;
507
508     if (src_info->bmiHeader.biCompression == BI_RLE4 || src_info->bmiHeader.biCompression == BI_RLE8)
509     {
510         if ( src_info->bmiHeader.biHeight < 0 ||
511             (src_info->bmiHeader.biCompression == BI_RLE4 && src_info->bmiHeader.biBitCount != 4) ||
512             (src_info->bmiHeader.biCompression == BI_RLE8 && src_info->bmiHeader.biBitCount != 8) )
513         {
514             SetLastError( ERROR_INVALID_PARAMETER );
515             goto done;
516         }
517
518         if (lines == 0) goto done;
519         else lines = src_info->bmiHeader.biHeight;
520         startscan = 0;
521
522         if (!build_rle_bitmap( src_info, &src_bits, &clip )) goto done;
523     }
524
525     dst.visrect.left   = 0;
526     dst.visrect.top    = 0;
527     dst.visrect.right  = bitmap->bitmap.bmWidth;
528     dst.visrect.bottom = bitmap->bitmap.bmHeight;
529
530     src.visrect.left   = 0;
531     src.visrect.top    = 0;
532     src.visrect.right  = src_info->bmiHeader.biWidth;
533     src.visrect.bottom = abs( src_info->bmiHeader.biHeight );
534
535     if (src_info->bmiHeader.biHeight > 0)
536     {
537         src_to_dst_offset = -startscan;
538         lines = min( lines, src.visrect.bottom - startscan );
539         if (lines < src.visrect.bottom) src.visrect.top = src.visrect.bottom - lines;
540     }
541     else
542     {
543         src_to_dst_offset = src.visrect.bottom - lines - startscan;
544         /* Unlike the bottom-up case, Windows doesn't limit lines. */
545         if (lines < src.visrect.bottom) src.visrect.bottom = lines;
546     }
547
548     /* Hack to ensure we don't get the nulldrv if the bmp hasn't been selected
549        into a dc yet */
550     physdev = GET_DC_PHYSDEV( dc, pCreateBitmap );
551     if (!BITMAP_SetOwnerDC( hbitmap, physdev )) goto done;
552
553     funcs = bitmap->funcs;
554     if (bitmap->dib) funcs = dc->dibdrv.dev.funcs;
555
556     result = lines;
557
558     offset_rect( &src.visrect, 0, src_to_dst_offset );
559     if (!intersect_rect( &dst.visrect, &src.visrect, &dst.visrect )) goto done;
560     src.visrect = dst.visrect;
561     offset_rect( &src.visrect, 0, -src_to_dst_offset );
562
563     src.x      = src.visrect.left;
564     src.y      = src.visrect.top;
565     src.width  = src.visrect.right - src.visrect.left;
566     src.height = src.visrect.bottom - src.visrect.top;
567
568     dst.x      = dst.visrect.left;
569     dst.y      = dst.visrect.top;
570     dst.width  = dst.visrect.right - dst.visrect.left;
571     dst.height = dst.visrect.bottom - dst.visrect.top;
572
573     memcpy( dst_info, src_info, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ));
574
575     err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
576     if (err == ERROR_BAD_FORMAT)
577     {
578         void *ptr;
579
580         dst_info->bmiHeader.biWidth = dst.width;
581         ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( dst_info ));
582         if (ptr)
583         {
584             err = convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, ptr );
585             {
586                 if (src_bits.free) src_bits.free( &src_bits );
587                 src_bits.ptr = ptr;
588                 src_bits.is_copy = TRUE;
589                 src_bits.free = free_heap_bits;
590                 if (!err)
591                     err = funcs->pPutImage( NULL, hbitmap, clip, dst_info, &src_bits, &src, &dst, 0 );
592             }
593         }
594         else err = ERROR_OUTOFMEMORY;
595     }
596     if(err) result = 0;
597
598 done:
599     if (src_bits.free) src_bits.free( &src_bits );
600     if (clip) DeleteObject( clip );
601     GDI_ReleaseObj( hbitmap );
602     release_dc_ptr( dc );
603     if (delete_hdc) DeleteDC(hdc);
604     return result;
605 }
606
607
608 /***********************************************************************
609  *           SetDIBitsToDevice   (GDI32.@)
610  */
611 INT WINAPI SetDIBitsToDevice(HDC hdc, INT xDest, INT yDest, DWORD cx,
612                            DWORD cy, INT xSrc, INT ySrc, UINT startscan,
613                            UINT lines, LPCVOID bits, const BITMAPINFO *bmi,
614                            UINT coloruse )
615 {
616     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
617     BITMAPINFO *info = (BITMAPINFO *)buffer;
618     INT ret = 0;
619     DC *dc;
620
621     if (!bits) return 0;
622     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, coloruse )) return 0;
623
624     if ((dc = get_dc_ptr( hdc )))
625     {
626         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBitsToDevice );
627         update_dc( dc );
628         ret = physdev->funcs->pSetDIBitsToDevice( physdev, xDest, yDest, cx, cy, xSrc,
629                                                   ySrc, startscan, lines, bits, info, coloruse );
630         release_dc_ptr( dc );
631     }
632     return ret;
633 }
634
635 /***********************************************************************
636  *           SetDIBColorTable    (GDI32.@)
637  */
638 UINT WINAPI SetDIBColorTable( HDC hdc, UINT startpos, UINT entries, CONST RGBQUAD *colors )
639 {
640     DC * dc;
641     UINT result = 0;
642     BITMAPOBJ * bitmap;
643
644     if (!(dc = get_dc_ptr( hdc ))) return 0;
645
646     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
647     {
648         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetDIBColorTable );
649
650         /* Check if currently selected bitmap is a DIB */
651         if (bitmap->color_table)
652         {
653             if (startpos < bitmap->nb_colors)
654             {
655                 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
656                 memcpy(bitmap->color_table + startpos, colors, entries * sizeof(RGBQUAD));
657                 result = entries;
658             }
659         }
660         GDI_ReleaseObj( dc->hBitmap );
661         physdev->funcs->pSetDIBColorTable( physdev, startpos, entries, colors );
662     }
663     release_dc_ptr( dc );
664     return result;
665 }
666
667
668 /***********************************************************************
669  *           GetDIBColorTable    (GDI32.@)
670  */
671 UINT WINAPI GetDIBColorTable( HDC hdc, UINT startpos, UINT entries, RGBQUAD *colors )
672 {
673     DC * dc;
674     BITMAPOBJ *bitmap;
675     UINT result = 0;
676
677     if (!(dc = get_dc_ptr( hdc ))) return 0;
678
679     if ((bitmap = GDI_GetObjPtr( dc->hBitmap, OBJ_BITMAP )))
680     {
681         /* Check if currently selected bitmap is a DIB */
682         if (bitmap->color_table)
683         {
684             if (startpos < bitmap->nb_colors)
685             {
686                 if (startpos + entries > bitmap->nb_colors) entries = bitmap->nb_colors - startpos;
687                 memcpy(colors, bitmap->color_table + startpos, entries * sizeof(RGBQUAD));
688                 result = entries;
689             }
690         }
691         GDI_ReleaseObj( dc->hBitmap );
692     }
693     release_dc_ptr( dc );
694     return result;
695 }
696
697 static const RGBQUAD DefLogPaletteQuads[20] = { /* Copy of Default Logical Palette */
698 /* rgbBlue, rgbGreen, rgbRed, rgbReserved */
699     { 0x00, 0x00, 0x00, 0x00 },
700     { 0x00, 0x00, 0x80, 0x00 },
701     { 0x00, 0x80, 0x00, 0x00 },
702     { 0x00, 0x80, 0x80, 0x00 },
703     { 0x80, 0x00, 0x00, 0x00 },
704     { 0x80, 0x00, 0x80, 0x00 },
705     { 0x80, 0x80, 0x00, 0x00 },
706     { 0xc0, 0xc0, 0xc0, 0x00 },
707     { 0xc0, 0xdc, 0xc0, 0x00 },
708     { 0xf0, 0xca, 0xa6, 0x00 },
709     { 0xf0, 0xfb, 0xff, 0x00 },
710     { 0xa4, 0xa0, 0xa0, 0x00 },
711     { 0x80, 0x80, 0x80, 0x00 },
712     { 0x00, 0x00, 0xff, 0x00 },
713     { 0x00, 0xff, 0x00, 0x00 },
714     { 0x00, 0xff, 0xff, 0x00 },
715     { 0xff, 0x00, 0x00, 0x00 },
716     { 0xff, 0x00, 0xff, 0x00 },
717     { 0xff, 0xff, 0x00, 0x00 },
718     { 0xff, 0xff, 0xff, 0x00 }
719 };
720
721 static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff};
722 static const DWORD bit_fields_565[3] = {0xf800, 0x07e0, 0x001f};
723 static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f};
724
725 static int fill_query_info( BITMAPINFO *info, BITMAPOBJ *bmp )
726 {
727     BITMAPINFOHEADER header;
728
729     header.biSize   = info->bmiHeader.biSize; /* Ensure we don't overwrite the original size when we copy back */
730     header.biWidth  = bmp->bitmap.bmWidth;
731     header.biHeight = bmp->bitmap.bmHeight;
732     header.biPlanes = 1;
733
734     if (bmp->dib)
735     {
736         header.biBitCount = bmp->dib->dsBm.bmBitsPixel;
737         switch (bmp->dib->dsBm.bmBitsPixel)
738         {
739         case 16:
740         case 32:
741             header.biCompression = BI_BITFIELDS;
742             break;
743         default:
744             header.biCompression = BI_RGB;
745             break;
746         }
747     }
748     else
749     {
750         header.biCompression = (bmp->bitmap.bmBitsPixel > 8) ? BI_BITFIELDS : BI_RGB;
751         header.biBitCount = bmp->bitmap.bmBitsPixel;
752     }
753
754     header.biSizeImage = get_dib_image_size( (BITMAPINFO *)&header );
755     header.biXPelsPerMeter = 0;
756     header.biYPelsPerMeter = 0;
757     header.biClrUsed       = 0;
758     header.biClrImportant  = 0;
759
760     if ( info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER) )
761     {
762         BITMAPCOREHEADER *coreheader = (BITMAPCOREHEADER *)info;
763
764         coreheader->bcWidth    = header.biWidth;
765         coreheader->bcHeight   = header.biHeight;
766         coreheader->bcPlanes   = header.biPlanes;
767         coreheader->bcBitCount = header.biBitCount;
768     }
769     else
770         info->bmiHeader = header;
771
772     return abs(bmp->bitmap.bmHeight);
773 }
774
775 /************************************************************************
776  *      copy_color_info
777  *
778  * Copy BITMAPINFO color information where dst may be a BITMAPCOREINFO.
779  */
780 static void copy_color_info(BITMAPINFO *dst, const BITMAPINFO *src, UINT coloruse)
781 {
782     unsigned int colors = get_dib_num_of_colors( src );
783     RGBQUAD *src_colors = (RGBQUAD *)((char *)src + src->bmiHeader.biSize);
784
785     assert( src->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) );
786
787     if (dst->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
788     {
789         BITMAPCOREINFO *core = (BITMAPCOREINFO *)dst;
790         if (coloruse == DIB_PAL_COLORS)
791             memcpy( core->bmciColors, src_colors, colors * sizeof(WORD) );
792         else
793         {
794             unsigned int i;
795             for (i = 0; i < colors; i++)
796             {
797                 core->bmciColors[i].rgbtRed   = src_colors[i].rgbRed;
798                 core->bmciColors[i].rgbtGreen = src_colors[i].rgbGreen;
799                 core->bmciColors[i].rgbtBlue  = src_colors[i].rgbBlue;
800             }
801         }
802     }
803     else
804     {
805         dst->bmiHeader.biClrUsed   = src->bmiHeader.biClrUsed;
806         dst->bmiHeader.biSizeImage = src->bmiHeader.biSizeImage;
807
808         if (src->bmiHeader.biCompression == BI_BITFIELDS)
809             /* bitfields are always at bmiColors even in larger structures */
810             memcpy( dst->bmiColors, src->bmiColors, 3 * sizeof(DWORD) );
811         else if (colors)
812         {
813             void *colorptr = (char *)dst + dst->bmiHeader.biSize;
814             unsigned int size;
815
816             if (coloruse == DIB_PAL_COLORS)
817                 size = colors * sizeof(WORD);
818             else
819                 size = colors * sizeof(RGBQUAD);
820             memcpy( colorptr, src_colors, size );
821         }
822     }
823 }
824
825 static void fill_default_color_table( BITMAPINFO *info )
826 {
827     int i;
828
829     switch (info->bmiHeader.biBitCount)
830     {
831     case 1:
832         info->bmiColors[0].rgbRed = info->bmiColors[0].rgbGreen = info->bmiColors[0].rgbBlue = 0;
833         info->bmiColors[0].rgbReserved = 0;
834         info->bmiColors[1].rgbRed = info->bmiColors[1].rgbGreen = info->bmiColors[1].rgbBlue = 0xff;
835         info->bmiColors[1].rgbReserved = 0;
836         break;
837
838     case 4:
839         /* The EGA palette is the first and last 8 colours of the default palette
840            with the innermost pair swapped */
841         memcpy(info->bmiColors,     DefLogPaletteQuads,      7 * sizeof(RGBQUAD));
842         memcpy(info->bmiColors + 7, DefLogPaletteQuads + 12, 1 * sizeof(RGBQUAD));
843         memcpy(info->bmiColors + 8, DefLogPaletteQuads +  7, 1 * sizeof(RGBQUAD));
844         memcpy(info->bmiColors + 9, DefLogPaletteQuads + 13, 7 * sizeof(RGBQUAD));
845         break;
846
847     case 8:
848         memcpy(info->bmiColors, DefLogPaletteQuads, 10 * sizeof(RGBQUAD));
849         memcpy(info->bmiColors + 246, DefLogPaletteQuads + 10, 10 * sizeof(RGBQUAD));
850         for (i = 10; i < 246; i++)
851         {
852             info->bmiColors[i].rgbRed      = (i & 0x07) << 5;
853             info->bmiColors[i].rgbGreen    = (i & 0x38) << 2;
854             info->bmiColors[i].rgbBlue     =  i & 0xc0;
855             info->bmiColors[i].rgbReserved = 0;
856         }
857         break;
858
859     default:
860         ERR("called with bitcount %d\n", info->bmiHeader.biBitCount);
861     }
862 }
863
864 /******************************************************************************
865  * GetDIBits [GDI32.@]
866  *
867  * Retrieves bits of bitmap and copies to buffer.
868  *
869  * RETURNS
870  *    Success: Number of scan lines copied from bitmap
871  *    Failure: 0
872  */
873 INT WINAPI GetDIBits(
874     HDC hdc,         /* [in]  Handle to device context */
875     HBITMAP hbitmap, /* [in]  Handle to bitmap */
876     UINT startscan,  /* [in]  First scan line to set in dest bitmap */
877     UINT lines,      /* [in]  Number of scan lines to copy */
878     LPVOID bits,       /* [out] Address of array for bitmap bits */
879     BITMAPINFO * info, /* [out] Address of structure with bitmap data */
880     UINT coloruse)   /* [in]  RGB or palette index */
881 {
882     DC * dc;
883     BITMAPOBJ * bmp;
884     int i, dst_to_src_offset, ret = 0;
885     DWORD err;
886     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
887     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
888     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
889     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
890     const struct gdi_dc_funcs *funcs;
891     struct gdi_image_bits src_bits;
892     struct bitblt_coords src, dst;
893     BOOL empty_rect = FALSE;
894
895     /* Since info may be a BITMAPCOREINFO or any of the larger BITMAPINFO structures, we'll use our
896        own copy and transfer the colour info back at the end */
897     if (!bitmapinfoheader_from_user_bitmapinfo( &dst_info->bmiHeader, &info->bmiHeader )) return 0;
898     dst_info->bmiHeader.biClrUsed = 0;
899     dst_info->bmiHeader.biClrImportant = 0;
900
901     if (!(dc = get_dc_ptr( hdc )))
902     {
903         SetLastError( ERROR_INVALID_PARAMETER );
904         return 0;
905     }
906     update_dc( dc );
907     if (!(bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP )))
908     {
909         release_dc_ptr( dc );
910         return 0;
911     }
912
913     funcs = bmp->funcs;
914     if (bmp->dib) funcs = dc->dibdrv.dev.funcs;
915
916     if (dst_info->bmiHeader.biBitCount == 0) /* query bitmap info only */
917     {
918         ret = fill_query_info( info, bmp );
919         goto done;
920     }
921
922     src.visrect.left   = 0;
923     src.visrect.top    = 0;
924     src.visrect.right  = bmp->bitmap.bmWidth;
925     src.visrect.bottom = bmp->bitmap.bmHeight;
926
927     dst.visrect.left   = 0;
928     dst.visrect.top    = 0;
929     dst.visrect.right  = dst_info->bmiHeader.biWidth;
930     dst.visrect.bottom = abs( dst_info->bmiHeader.biHeight );
931
932     if (lines == 0 || startscan >= dst.visrect.bottom)
933         bits = NULL;
934
935     if (bits)
936     {
937         if (dst_info->bmiHeader.biHeight > 0)
938         {
939             dst_to_src_offset = -startscan;
940             lines = min( lines, dst.visrect.bottom - startscan );
941             if (lines < dst.visrect.bottom) dst.visrect.top = dst.visrect.bottom - lines;
942         }
943         else
944         {
945             dst_to_src_offset = dst.visrect.bottom - lines - startscan;
946             if (dst_to_src_offset < 0)
947             {
948                 dst_to_src_offset = 0;
949                 lines = dst.visrect.bottom - startscan;
950             }
951             if (lines < dst.visrect.bottom) dst.visrect.bottom = lines;
952         }
953
954         offset_rect( &dst.visrect, 0, dst_to_src_offset );
955         empty_rect = !intersect_rect( &src.visrect, &src.visrect, &dst.visrect );
956         dst.visrect = src.visrect;
957         offset_rect( &dst.visrect, 0, -dst_to_src_offset );
958
959         if (dst_info->bmiHeader.biHeight > 0)
960         {
961             if (dst.visrect.bottom < dst_info->bmiHeader.biHeight)
962             {
963                 int pad_lines = min( dst_info->bmiHeader.biHeight - dst.visrect.bottom, lines );
964                 int pad_bytes = pad_lines * get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
965                 memset( bits, 0, pad_bytes );
966                 bits = (char *)bits + pad_bytes;
967             }
968         }
969         else
970         {
971             if (dst.visrect.bottom < lines)
972             {
973                 int pad_lines = lines - dst.visrect.bottom;
974                 int stride = get_dib_stride( dst_info->bmiHeader.biWidth, dst_info->bmiHeader.biBitCount );
975                 int pad_bytes = pad_lines * stride;
976                 memset( (char *)bits + dst.visrect.bottom * stride, 0, pad_bytes );
977             }
978         }
979
980         if (empty_rect) bits = NULL;
981
982         src.x      = src.visrect.left;
983         src.y      = src.visrect.top;
984         src.width  = src.visrect.right - src.visrect.left;
985         src.height = src.visrect.bottom - src.visrect.top;
986
987         lines = src.height;
988     }
989
990     err = funcs->pGetImage( NULL, hbitmap, src_info, bits ? &src_bits : NULL, bits ? &src : NULL );
991
992     if (err) goto done;
993
994     /* fill out the src colour table, if it needs one */
995     if (src_info->bmiHeader.biBitCount <= 8 && src_info->bmiHeader.biClrUsed == 0)
996     {
997         fill_default_color_table( src_info );
998         src_info->bmiHeader.biClrUsed = 1 << src_info->bmiHeader.biBitCount;
999     }
1000
1001     /* if the src and dst are the same depth, copy the colour info across */
1002     if (dst_info->bmiHeader.biBitCount == src_info->bmiHeader.biBitCount && coloruse == DIB_RGB_COLORS )
1003     {
1004         switch (src_info->bmiHeader.biBitCount)
1005         {
1006         case 16:
1007             if (src_info->bmiHeader.biCompression == BI_RGB)
1008             {
1009                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1010                 memcpy( src_info->bmiColors, bit_fields_555, sizeof(bit_fields_555) );
1011             }
1012             break;
1013         case 32:
1014             if (src_info->bmiHeader.biCompression == BI_RGB)
1015             {
1016                 src_info->bmiHeader.biCompression = BI_BITFIELDS;
1017                 memcpy( src_info->bmiColors, bit_fields_888, sizeof(bit_fields_888) );
1018             }
1019             break;
1020         }
1021         src_info->bmiHeader.biSizeImage = get_dib_image_size( dst_info );
1022         copy_color_info( dst_info, src_info, coloruse );
1023     }
1024     else if (dst_info->bmiHeader.biBitCount <= 8) /* otherwise construct a default colour table for the dst, if needed */
1025     {
1026         if( coloruse == DIB_PAL_COLORS )
1027         {
1028             if (!fill_color_table_from_palette( dst_info, dc )) goto done;
1029         }
1030         else
1031         {
1032             fill_default_color_table( dst_info );
1033         }
1034     }
1035
1036     if (bits)
1037     {
1038         if(dst_info->bmiHeader.biHeight > 0)
1039             dst_info->bmiHeader.biHeight = src.height;
1040         else
1041             dst_info->bmiHeader.biHeight = -src.height;
1042
1043         convert_bitmapinfo( src_info, src_bits.ptr, &src, dst_info, bits );
1044         if (src_bits.free) src_bits.free( &src_bits );
1045         ret = lines;
1046     }
1047     else
1048         ret = empty_rect ? FALSE : TRUE;
1049
1050     if (coloruse == DIB_PAL_COLORS)
1051     {
1052         WORD *index = (WORD *)dst_info->bmiColors;
1053         int colors = get_dib_num_of_colors( dst_info );
1054         for (i = 0; i < colors; i++, index++)
1055             *index = i;
1056     }
1057
1058     copy_color_info( info, dst_info, coloruse );
1059
1060 done:
1061     release_dc_ptr( dc );
1062     GDI_ReleaseObj( hbitmap );
1063     return ret;
1064 }
1065
1066
1067 /***********************************************************************
1068  *           CreateDIBitmap    (GDI32.@)
1069  *
1070  * Creates a DDB (device dependent bitmap) from a DIB.
1071  * The DDB will have the same color depth as the reference DC.
1072  */
1073 HBITMAP WINAPI CreateDIBitmap( HDC hdc, const BITMAPINFOHEADER *header,
1074                             DWORD init, LPCVOID bits, const BITMAPINFO *data,
1075                             UINT coloruse )
1076 {
1077     BITMAPINFOHEADER info;
1078     HBITMAP handle;
1079     LONG height;
1080
1081     if (!bitmapinfoheader_from_user_bitmapinfo( &info, header )) return 0;
1082     if (info.biWidth < 0) return 0;
1083
1084     /* Top-down DIBs have a negative height */
1085     height = abs( info.biHeight );
1086
1087     TRACE("hdc=%p, header=%p, init=%u, bits=%p, data=%p, coloruse=%u (bitmap: width=%d, height=%d, bpp=%u, compr=%u)\n",
1088           hdc, header, init, bits, data, coloruse, info.biWidth, info.biHeight,
1089           info.biBitCount, info.biCompression);
1090
1091     if (hdc == NULL)
1092         handle = CreateBitmap( info.biWidth, height, 1, 1, NULL );
1093     else
1094         handle = CreateCompatibleBitmap( hdc, info.biWidth, height );
1095
1096     if (handle)
1097     {
1098         if (init & CBM_INIT)
1099         {
1100             if (SetDIBits( hdc, handle, 0, height, bits, data, coloruse ) == 0)
1101             {
1102                 DeleteObject( handle );
1103                 handle = 0;
1104             }
1105         }
1106     }
1107
1108     return handle;
1109 }
1110
1111 /* Copy/synthesize RGB palette from BITMAPINFO */
1112 static void DIB_CopyColorTable( DC *dc, BITMAPOBJ *bmp, WORD coloruse, const BITMAPINFO *info )
1113 {
1114     unsigned int colors, i;
1115
1116     colors = get_dib_num_of_colors( info );
1117     if (!(bmp->color_table = HeapAlloc(GetProcessHeap(), 0, colors * sizeof(RGBQUAD) ))) return;
1118     bmp->nb_colors = colors;
1119
1120     if (coloruse == DIB_RGB_COLORS)
1121     {
1122         memcpy( bmp->color_table, info->bmiColors, colors * sizeof(RGBQUAD));
1123     }
1124     else
1125     {
1126         PALETTEENTRY entries[256];
1127         const WORD *index = (const WORD *)info->bmiColors;
1128         UINT count = GetPaletteEntries( dc->hPalette, 0, colors, entries );
1129
1130         for (i = 0; i < colors; i++, index++)
1131         {
1132             PALETTEENTRY *entry = &entries[*index % count];
1133             bmp->color_table[i].rgbRed = entry->peRed;
1134             bmp->color_table[i].rgbGreen = entry->peGreen;
1135             bmp->color_table[i].rgbBlue = entry->peBlue;
1136             bmp->color_table[i].rgbReserved = 0;
1137         }
1138     }
1139 }
1140
1141 /***********************************************************************
1142  *           CreateDIBSection    (GDI32.@)
1143  */
1144 HBITMAP WINAPI CreateDIBSection(HDC hdc, CONST BITMAPINFO *bmi, UINT usage,
1145                                 VOID **bits, HANDLE section, DWORD offset)
1146 {
1147     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1148     BITMAPINFO *info = (BITMAPINFO *)buffer;
1149     HBITMAP ret = 0;
1150     DC *dc;
1151     BOOL bDesktopDC = FALSE;
1152     DIBSECTION *dib;
1153     BITMAPOBJ *bmp;
1154     void *mapBits = NULL;
1155
1156     if (bits) *bits = NULL;
1157     if (!bitmapinfo_from_user_bitmapinfo( info, bmi, usage )) return 0;
1158
1159     switch (info->bmiHeader.biBitCount)
1160     {
1161     case 16:
1162     case 32:
1163         if (info->bmiHeader.biCompression == BI_BITFIELDS) break;
1164         /* fall through */
1165     case 1:
1166     case 4:
1167     case 8:
1168     case 24:
1169         if (info->bmiHeader.biCompression == BI_RGB) break;
1170         /* fall through */
1171     default:
1172         WARN( "invalid %u bpp compression %u\n",
1173               info->bmiHeader.biBitCount, info->bmiHeader.biCompression );
1174         return 0;
1175     }
1176
1177     if (!(dib = HeapAlloc( GetProcessHeap(), 0, sizeof(*dib) ))) return 0;
1178
1179     TRACE("format (%d,%d), planes %d, bpp %d, %s, size %d %s\n",
1180           info->bmiHeader.biWidth, info->bmiHeader.biHeight,
1181           info->bmiHeader.biPlanes, info->bmiHeader.biBitCount,
1182           info->bmiHeader.biCompression == BI_BITFIELDS? "BI_BITFIELDS" : "BI_RGB",
1183           info->bmiHeader.biSizeImage, usage == DIB_PAL_COLORS? "PAL" : "RGB");
1184
1185     dib->dsBm.bmType       = 0;
1186     dib->dsBm.bmWidth      = info->bmiHeader.biWidth;
1187     dib->dsBm.bmHeight     = abs( info->bmiHeader.biHeight );
1188     dib->dsBm.bmWidthBytes = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
1189     dib->dsBm.bmPlanes     = info->bmiHeader.biPlanes;
1190     dib->dsBm.bmBitsPixel  = info->bmiHeader.biBitCount;
1191     dib->dsBm.bmBits       = NULL;
1192     dib->dsBmih            = info->bmiHeader;
1193
1194     /* set number of entries in bmi.bmiColors table */
1195     if( info->bmiHeader.biBitCount <= 8 )
1196         dib->dsBmih.biClrUsed = 1 << info->bmiHeader.biBitCount;
1197
1198     /* set dsBitfields values */
1199     dib->dsBitfields[0] = dib->dsBitfields[1] = dib->dsBitfields[2] = 0;
1200
1201     if (info->bmiHeader.biBitCount == 16 && info->bmiHeader.biCompression == BI_RGB)
1202     {
1203         /* In this case Windows changes biCompression to BI_BITFIELDS,
1204            however for now we won't do this, as there are a lot
1205            of places where BI_BITFIELDS is currently unsupported. */
1206
1207         /* dib->dsBmih.biCompression = compression = BI_BITFIELDS;*/
1208         dib->dsBitfields[0] = 0x7c00;
1209         dib->dsBitfields[1] = 0x03e0;
1210         dib->dsBitfields[2] = 0x001f;
1211     }
1212     else if (info->bmiHeader.biCompression == BI_BITFIELDS)
1213     {
1214         dib->dsBitfields[0] =  *(const DWORD *)bmi->bmiColors;
1215         dib->dsBitfields[1] =  *((const DWORD *)bmi->bmiColors + 1);
1216         dib->dsBitfields[2] =  *((const DWORD *)bmi->bmiColors + 2);
1217     }
1218
1219     /* get storage location for DIB bits */
1220
1221     if (section)
1222     {
1223         SYSTEM_INFO SystemInfo;
1224         DWORD mapOffset;
1225         INT mapSize;
1226
1227         GetSystemInfo( &SystemInfo );
1228         mapOffset = offset - (offset % SystemInfo.dwAllocationGranularity);
1229         mapSize = dib->dsBmih.biSizeImage + (offset - mapOffset);
1230         mapBits = MapViewOfFile( section, FILE_MAP_ALL_ACCESS, 0, mapOffset, mapSize );
1231         if (mapBits) dib->dsBm.bmBits = (char *)mapBits + (offset - mapOffset);
1232     }
1233     else
1234     {
1235         offset = 0;
1236         dib->dsBm.bmBits = VirtualAlloc( NULL, dib->dsBmih.biSizeImage,
1237                                          MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE );
1238     }
1239     dib->dshSection = section;
1240     dib->dsOffset = offset;
1241
1242     if (!dib->dsBm.bmBits)
1243     {
1244         HeapFree( GetProcessHeap(), 0, dib );
1245         return 0;
1246     }
1247
1248     /* If the reference hdc is null, take the desktop dc */
1249     if (hdc == 0)
1250     {
1251         hdc = CreateCompatibleDC(0);
1252         bDesktopDC = TRUE;
1253     }
1254
1255     if (!(dc = get_dc_ptr( hdc ))) goto error;
1256
1257     /* create Device Dependent Bitmap and add DIB pointer */
1258     ret = CreateBitmap( dib->dsBm.bmWidth, dib->dsBm.bmHeight, 1,
1259                         (info->bmiHeader.biBitCount == 1) ? 1 : GetDeviceCaps(hdc, BITSPIXEL), NULL );
1260
1261     if (ret && ((bmp = GDI_GetObjPtr(ret, OBJ_BITMAP))))
1262     {
1263         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pCreateDIBSection );
1264         bmp->dib = dib;
1265         bmp->funcs = physdev->funcs;
1266         /* create local copy of DIB palette */
1267         if (info->bmiHeader.biBitCount <= 8) DIB_CopyColorTable( dc, bmp, usage, info );
1268         GDI_ReleaseObj( ret );
1269
1270         if (!physdev->funcs->pCreateDIBSection( physdev, ret, info, usage ))
1271         {
1272             DeleteObject( ret );
1273             ret = 0;
1274         }
1275     }
1276
1277     release_dc_ptr( dc );
1278     if (bDesktopDC) DeleteDC( hdc );
1279     if (ret && bits) *bits = dib->dsBm.bmBits;
1280     return ret;
1281
1282 error:
1283     if (bDesktopDC) DeleteDC( hdc );
1284     if (section) UnmapViewOfFile( mapBits );
1285     else if (!offset) VirtualFree( dib->dsBm.bmBits, 0, MEM_RELEASE );
1286     HeapFree( GetProcessHeap(), 0, dib );
1287     return 0;
1288 }