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