gdi32: Emulate DDB support using the DIB driver when the graphics driver doesn't...
[wine] / dlls / gdi32 / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1998 Huw D M Davies
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "gdi_private.h"
30 #include "wine/debug.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(bitmap);
33
34
35 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc );
36 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
37 static BOOL BITMAP_DeleteObject( HGDIOBJ handle );
38
39 static const struct gdi_obj_funcs bitmap_funcs =
40 {
41     BITMAP_SelectObject,  /* pSelectObject */
42     BITMAP_GetObject,     /* pGetObjectA */
43     BITMAP_GetObject,     /* pGetObjectW */
44     NULL,                 /* pUnrealizeObject */
45     BITMAP_DeleteObject   /* pDeleteObject */
46 };
47
48
49 /***********************************************************************
50  *           null driver fallback implementations
51  */
52
53 DWORD nulldrv_GetImage( PHYSDEV dev, HBITMAP hbitmap, BITMAPINFO *info,
54                         struct gdi_image_bits *bits, struct bitblt_coords *src )
55 {
56     if (!hbitmap) return ERROR_NOT_SUPPORTED;
57     return dib_driver.pGetImage( 0, hbitmap, info, bits, src );
58 }
59
60 DWORD nulldrv_PutImage( PHYSDEV dev, HBITMAP hbitmap, HRGN clip, BITMAPINFO *info,
61                         const struct gdi_image_bits *bits, struct bitblt_coords *src,
62                         struct bitblt_coords *dst, DWORD rop )
63 {
64     if (!hbitmap) return ERROR_SUCCESS;
65     return dib_driver.pPutImage( NULL, hbitmap, clip, info, bits, src, dst, rop );
66 }
67
68
69 /******************************************************************************
70  * CreateBitmap [GDI32.@]
71  *
72  * Creates a bitmap with the specified info.
73  *
74  * PARAMS
75  *    width  [I] bitmap width
76  *    height [I] bitmap height
77  *    planes [I] Number of color planes
78  *    bpp    [I] Number of bits to identify a color
79  *    bits   [I] Pointer to array containing color data
80  *
81  * RETURNS
82  *    Success: Handle to bitmap
83  *    Failure: 0
84  */
85 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
86                              UINT bpp, LPCVOID bits )
87 {
88     BITMAP bm;
89
90     bm.bmType = 0;
91     bm.bmWidth = width;
92     bm.bmHeight = height;
93     bm.bmWidthBytes = get_bitmap_stride( width, bpp );
94     bm.bmPlanes = planes;
95     bm.bmBitsPixel = bpp;
96     bm.bmBits = (LPVOID)bits;
97
98     return CreateBitmapIndirect( &bm );
99 }
100
101 /******************************************************************************
102  * CreateCompatibleBitmap [GDI32.@]
103  *
104  * Creates a bitmap compatible with the DC.
105  *
106  * PARAMS
107  *    hdc    [I] Handle to device context
108  *    width  [I] Width of bitmap
109  *    height [I] Height of bitmap
110  *
111  * RETURNS
112  *    Success: Handle to bitmap
113  *    Failure: 0
114  */
115 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
116 {
117     HBITMAP hbmpRet = 0;
118
119     TRACE("(%p,%d,%d) =\n", hdc, width, height);
120
121     if (GetObjectType( hdc ) != OBJ_MEMDC)
122     {
123         hbmpRet = CreateBitmap(width, height,
124                                GetDeviceCaps(hdc, PLANES),
125                                GetDeviceCaps(hdc, BITSPIXEL),
126                                NULL);
127     }
128     else  /* Memory DC */
129     {
130         DIBSECTION dib;
131         HBITMAP bitmap = GetCurrentObject( hdc, OBJ_BITMAP );
132         INT size = GetObjectW( bitmap, sizeof(dib), &dib );
133
134         if (!size) return 0;
135
136         if (size == sizeof(BITMAP))
137         {
138             /* A device-dependent bitmap is selected in the DC */
139             hbmpRet = CreateBitmap(width, height,
140                                    dib.dsBm.bmPlanes,
141                                    dib.dsBm.bmBitsPixel,
142                                    NULL);
143         }
144         else
145         {
146             /* A DIB section is selected in the DC */
147             BITMAPINFO *bi;
148             void *bits;
149
150             /* Allocate memory for a BITMAPINFOHEADER structure and a
151                color table. The maximum number of colors in a color table
152                is 256 which corresponds to a bitmap with depth 8.
153                Bitmaps with higher depths don't have color tables. */
154             bi = HeapAlloc(GetProcessHeap(), 0, sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
155
156             if (bi)
157             {
158                 bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
159                 bi->bmiHeader.biWidth         = width;
160                 bi->bmiHeader.biHeight        = height;
161                 bi->bmiHeader.biPlanes        = dib.dsBmih.biPlanes;
162                 bi->bmiHeader.biBitCount      = dib.dsBmih.biBitCount;
163                 bi->bmiHeader.biCompression   = dib.dsBmih.biCompression;
164                 bi->bmiHeader.biSizeImage     = 0;
165                 bi->bmiHeader.biXPelsPerMeter = dib.dsBmih.biXPelsPerMeter;
166                 bi->bmiHeader.biYPelsPerMeter = dib.dsBmih.biYPelsPerMeter;
167                 bi->bmiHeader.biClrUsed       = dib.dsBmih.biClrUsed;
168                 bi->bmiHeader.biClrImportant  = dib.dsBmih.biClrImportant;
169
170                 if (bi->bmiHeader.biCompression == BI_BITFIELDS)
171                 {
172                     /* Copy the color masks */
173                     CopyMemory(bi->bmiColors, dib.dsBitfields, 3 * sizeof(DWORD));
174                 }
175                 else if (bi->bmiHeader.biBitCount <= 8)
176                 {
177                     /* Copy the color table */
178                     GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
179                 }
180
181                 hbmpRet = CreateDIBSection(hdc, bi, DIB_RGB_COLORS, &bits, NULL, 0);
182                 HeapFree(GetProcessHeap(), 0, bi);
183             }
184         }
185     }
186
187     TRACE("\t\t%p\n", hbmpRet);
188     return hbmpRet;
189 }
190
191
192 /******************************************************************************
193  * CreateBitmapIndirect [GDI32.@]
194  *
195  * Creates a bitmap with the specified info.
196  *
197  * PARAMS
198  *  bmp [I] Pointer to the bitmap info describing the bitmap
199  *
200  * RETURNS
201  *    Success: Handle to bitmap
202  *    Failure: NULL. Use GetLastError() to determine the cause.
203  *
204  * NOTES
205  *  If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
206  */
207 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
208 {
209     BITMAP bm;
210     BITMAPOBJ *bmpobj;
211     HBITMAP hbitmap;
212
213     if (!bmp || bmp->bmType)
214     {
215         SetLastError( ERROR_INVALID_PARAMETER );
216         return NULL;
217     }
218
219     if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
220     {
221         SetLastError( ERROR_INVALID_PARAMETER );
222         return 0;
223     }
224
225     bm = *bmp;
226
227     if (!bm.bmWidth || !bm.bmHeight)
228     {
229         return GetStockObject( DEFAULT_BITMAP );
230     }
231     else
232     {
233         if (bm.bmHeight < 0)
234             bm.bmHeight = -bm.bmHeight;
235         if (bm.bmWidth < 0)
236             bm.bmWidth = -bm.bmWidth;
237     }
238
239     if (bm.bmPlanes != 1)
240     {
241         FIXME("planes = %d\n", bm.bmPlanes);
242         SetLastError( ERROR_INVALID_PARAMETER );
243         return NULL;
244     }
245
246     /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
247     if(bm.bmBitsPixel == 1)         bm.bmBitsPixel = 1;
248     else if(bm.bmBitsPixel <= 4)    bm.bmBitsPixel = 4;
249     else if(bm.bmBitsPixel <= 8)    bm.bmBitsPixel = 8;
250     else if(bm.bmBitsPixel <= 16)   bm.bmBitsPixel = 16;
251     else if(bm.bmBitsPixel <= 24)   bm.bmBitsPixel = 24;
252     else if(bm.bmBitsPixel <= 32)   bm.bmBitsPixel = 32;
253     else {
254         WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
255         SetLastError(ERROR_INVALID_PARAMETER);
256         return NULL;
257     }
258
259     /* Windows ignores the provided bm.bmWidthBytes */
260     bm.bmWidthBytes = get_bitmap_stride( bm.bmWidth, bm.bmBitsPixel );
261     /* XP doesn't allow to create bitmaps larger than 128 Mb */
262     if (bm.bmHeight > 128 * 1024 * 1024 / bm.bmWidthBytes)
263     {
264         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
265         return 0;
266     }
267
268     /* Create the BITMAPOBJ */
269     if (!(bmpobj = HeapAlloc( GetProcessHeap(), 0, sizeof(*bmpobj) )))
270     {
271         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
272         return 0;
273     }
274
275     bmpobj->size.cx = 0;
276     bmpobj->size.cy = 0;
277     bmpobj->bitmap = bm;
278     bmpobj->bitmap.bmBits = NULL;
279     bmpobj->funcs = &null_driver;
280     bmpobj->dib = NULL;
281     bmpobj->color_table = NULL;
282     bmpobj->nb_colors = 0;
283
284     if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
285     {
286         HeapFree( GetProcessHeap(), 0, bmpobj );
287         return 0;
288     }
289
290     if (bm.bmBits)
291         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
292
293     TRACE("%dx%d, bpp %d planes %d: returning %p\n", bm.bmWidth, bm.bmHeight,
294           bm.bmBitsPixel, bm.bmPlanes, hbitmap);
295
296     return hbitmap;
297 }
298
299
300 /* convenience wrapper for GetImage to retrieve the full contents of a bitmap */
301 BOOL get_bitmap_image( HBITMAP hbitmap, BITMAPINFO *info, struct gdi_image_bits *bits )
302 {
303     struct bitblt_coords src;
304     BOOL ret = FALSE;
305     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
306
307     if (bmp)
308     {
309         const struct gdi_dc_funcs *funcs = get_bitmap_funcs( bmp );
310         src.visrect.left   = src.x = 0;
311         src.visrect.top    = src.y = 0;
312         src.visrect.right  = src.width = bmp->bitmap.bmWidth;
313         src.visrect.bottom = src.height = bmp->bitmap.bmHeight;
314         ret = !funcs->pGetImage( NULL, hbitmap, info, bits, &src );
315         GDI_ReleaseObj( hbitmap );
316     }
317     return ret;
318 }
319
320
321 /***********************************************************************
322  * GetBitmapBits [GDI32.@]
323  *
324  * Copies bitmap bits of bitmap to buffer.
325  *
326  * RETURNS
327  *    Success: Number of bytes copied
328  *    Failure: 0
329  */
330 LONG WINAPI GetBitmapBits(
331     HBITMAP hbitmap, /* [in]  Handle to bitmap */
332     LONG count,        /* [in]  Number of bytes to copy */
333     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
334 {
335     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
336     BITMAPINFO *info = (BITMAPINFO *)buffer;
337     struct gdi_image_bits src_bits;
338     struct bitblt_coords src;
339     int dst_stride, max, ret;
340     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
341     const struct gdi_dc_funcs *funcs;
342
343     if (!bmp) return 0;
344     funcs = get_bitmap_funcs( bmp );
345
346     if (bmp->dib) dst_stride = get_bitmap_stride( bmp->dib->dsBmih.biWidth, bmp->dib->dsBmih.biBitCount );
347     else dst_stride = get_bitmap_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
348
349     ret = max = dst_stride * bmp->bitmap.bmHeight;
350     if (!bits) goto done;
351     if (count > max) count = max;
352     ret = count;
353
354     src.visrect.left = 0;
355     src.visrect.right = bmp->bitmap.bmWidth;
356     src.visrect.top = 0;
357     src.visrect.bottom = (count + dst_stride - 1) / dst_stride;
358     src.x = src.y = 0;
359     src.width = src.visrect.right - src.visrect.left;
360     src.height = src.visrect.bottom - src.visrect.top;
361
362     if (!funcs->pGetImage( NULL, hbitmap, info, &src_bits, &src ))
363     {
364         const char *src_ptr = src_bits.ptr;
365         int src_stride = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
366
367         /* GetBitmapBits returns 16-bit aligned data */
368
369         if (info->bmiHeader.biHeight > 0)
370         {
371             src_ptr += (info->bmiHeader.biHeight - 1) * src_stride;
372             src_stride = -src_stride;
373         }
374         src_ptr += src.visrect.top * src_stride;
375
376         if (src_stride == dst_stride) memcpy( bits, src_ptr, count );
377         else while (count > 0)
378         {
379             memcpy( bits, src_ptr, min( count, dst_stride ) );
380             src_ptr += src_stride;
381             bits = (char *)bits + dst_stride;
382             count -= dst_stride;
383         }
384         if (src_bits.free) src_bits.free( &src_bits );
385     }
386     else ret = 0;
387
388 done:
389     GDI_ReleaseObj( hbitmap );
390     return ret;
391 }
392
393
394 /******************************************************************************
395  * SetBitmapBits [GDI32.@]
396  *
397  * Sets bits of color data for a bitmap.
398  *
399  * RETURNS
400  *    Success: Number of bytes used in setting the bitmap bits
401  *    Failure: 0
402  */
403 LONG WINAPI SetBitmapBits(
404     HBITMAP hbitmap, /* [in] Handle to bitmap */
405     LONG count,        /* [in] Number of bytes in bitmap array */
406     LPCVOID bits)      /* [in] Address of array with bitmap bits */
407 {
408     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
409     BITMAPINFO *info = (BITMAPINFO *)buffer;
410     BITMAPOBJ *bmp;
411     DWORD err;
412     int i, src_stride, dst_stride;
413     struct bitblt_coords src, dst;
414     struct gdi_image_bits src_bits;
415     HRGN clip = NULL;
416     const struct gdi_dc_funcs *funcs;
417
418     if (!bits) return 0;
419
420     bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
421     if (!bmp) return 0;
422
423     funcs = get_bitmap_funcs( bmp );
424
425     if (count < 0) {
426         WARN("(%d): Negative number of bytes passed???\n", count );
427         count = -count;
428     }
429
430     if (bmp->dib) src_stride = get_bitmap_stride( bmp->dib->dsBmih.biWidth, bmp->dib->dsBmih.biBitCount );
431     else src_stride = get_bitmap_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
432     count = min( count, src_stride * bmp->bitmap.bmHeight );
433
434     dst_stride = get_dib_stride( bmp->bitmap.bmWidth, bmp->bitmap.bmBitsPixel );
435
436     src.visrect.left   = src.x = 0;
437     src.visrect.top    = src.y = 0;
438     src.visrect.right  = src.width = bmp->bitmap.bmWidth;
439     src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride;
440     dst = src;
441
442     if (count % src_stride)
443     {
444         HRGN last_row;
445         int extra_pixels = ((count % src_stride) << 3) / bmp->bitmap.bmBitsPixel;
446
447         if ((count % src_stride << 3) % bmp->bitmap.bmBitsPixel)
448             FIXME( "Unhandled partial pixel\n" );
449         clip = CreateRectRgn( src.visrect.left, src.visrect.top,
450                               src.visrect.right, src.visrect.bottom - 1 );
451         last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1,
452                                   src.visrect.left + extra_pixels, src.visrect.bottom );
453         CombineRgn( clip, clip, last_row, RGN_OR );
454         DeleteObject( last_row );
455     }
456
457     TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
458           hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
459           bmp->bitmap.bmBitsPixel, src.height );
460
461     if (src_stride == dst_stride)
462     {
463         src_bits.ptr = (void *)bits;
464         src_bits.is_copy = FALSE;
465         src_bits.free = NULL;
466     }
467     else
468     {
469         if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride )))
470         {
471             GDI_ReleaseObj( hbitmap );
472             return 0;
473         }
474         src_bits.is_copy = TRUE;
475         src_bits.free = free_heap_bits;
476         for (i = 0; i < count / src_stride; i++)
477             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride );
478         if (count % src_stride)
479             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride );
480     }
481
482     /* query the color info */
483     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
484     info->bmiHeader.biPlanes        = 1;
485     info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
486     info->bmiHeader.biCompression   = BI_RGB;
487     info->bmiHeader.biXPelsPerMeter = 0;
488     info->bmiHeader.biYPelsPerMeter = 0;
489     info->bmiHeader.biClrUsed       = 0;
490     info->bmiHeader.biClrImportant  = 0;
491     info->bmiHeader.biWidth         = 0;
492     info->bmiHeader.biHeight        = 0;
493     info->bmiHeader.biSizeImage     = 0;
494     err = funcs->pPutImage( NULL, hbitmap, 0, info, NULL, NULL, NULL, SRCCOPY );
495
496     if (!err || err == ERROR_BAD_FORMAT)
497     {
498         info->bmiHeader.biPlanes        = 1;
499         info->bmiHeader.biBitCount      = bmp->bitmap.bmBitsPixel;
500         info->bmiHeader.biWidth         = bmp->bitmap.bmWidth;
501         info->bmiHeader.biHeight        = -dst.height;
502         info->bmiHeader.biSizeImage     = dst.height * dst_stride;
503         err = funcs->pPutImage( NULL, hbitmap, clip, info, &src_bits, &src, &dst, SRCCOPY );
504     }
505     if (err) count = 0;
506
507     if (clip) DeleteObject( clip );
508     if (src_bits.free) src_bits.free( &src_bits );
509     GDI_ReleaseObj( hbitmap );
510     return count;
511 }
512
513 /**********************************************************************
514  *              BITMAP_CopyBitmap
515  *
516  */
517 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
518 {
519     HBITMAP res;
520     DIBSECTION dib;
521     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
522
523     if (!bmp) return 0;
524     if (bmp->dib)
525     {
526         void *bits;
527         BITMAPINFO *bi;
528         HDC dc;
529
530         dib = *bmp->dib;
531         GDI_ReleaseObj( hbitmap );
532         dc = CreateCompatibleDC( NULL );
533
534         if (!dc) return 0;
535         if (!(bi = HeapAlloc(GetProcessHeap(), 0, FIELD_OFFSET( BITMAPINFO, bmiColors[256] ))))
536         {
537             DeleteDC( dc );
538             return 0;
539         }
540         bi->bmiHeader = dib.dsBmih;
541
542         /* Get the color table or the color masks */
543         GetDIBits( dc, hbitmap, 0, 0, NULL, bi, DIB_RGB_COLORS );
544         bi->bmiHeader.biHeight = dib.dsBmih.biHeight;
545
546         res = CreateDIBSection( dc, bi, DIB_RGB_COLORS, &bits, NULL, 0 );
547         if (res) SetDIBits( dc, res, 0, dib.dsBm.bmHeight, dib.dsBm.bmBits, bi, DIB_RGB_COLORS );
548         HeapFree( GetProcessHeap(), 0, bi );
549         DeleteDC( dc );
550         return res;
551     }
552     dib.dsBm = bmp->bitmap;
553     dib.dsBm.bmBits = NULL;
554     GDI_ReleaseObj( hbitmap );
555
556     res = CreateBitmapIndirect( &dib.dsBm );
557     if(res) {
558         char *buf = HeapAlloc( GetProcessHeap(), 0, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight );
559         GetBitmapBits (hbitmap, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
560         SetBitmapBits (res, dib.dsBm.bmWidthBytes * dib.dsBm.bmHeight, buf);
561         HeapFree( GetProcessHeap(), 0, buf );
562     }
563     return res;
564 }
565
566
567 static void set_initial_bitmap_bits( HBITMAP hbitmap, BITMAPOBJ *bmp )
568 {
569     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
570     BITMAPINFO *info = (BITMAPINFO *)buffer;
571
572     if (!bmp->bitmap.bmBits) return;
573     if (bmp->funcs->pPutImage == nulldrv_PutImage) return;
574
575     get_ddb_bitmapinfo( bmp, info );
576     SetDIBits( 0, hbitmap, 0, bmp->bitmap.bmHeight, bmp->bitmap.bmBits, info, DIB_RGB_COLORS );
577     HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
578     bmp->bitmap.bmBits = NULL;
579 }
580
581 /***********************************************************************
582  *           BITMAP_SetOwnerDC
583  *
584  * Set the type of DC that owns the bitmap. This is used when the
585  * bitmap is selected into a device to initialize the bitmap function
586  * table.
587  */
588 BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
589 {
590     BITMAPOBJ *bitmap;
591     BOOL ret = TRUE;
592
593     /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
594     if (hbitmap == GetStockObject(DEFAULT_BITMAP)) return TRUE;
595
596     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
597
598     if (!bitmap->dib && bitmap->funcs != physdev->funcs)
599     {
600         /* we can only change from the null driver to some other driver */
601         if (bitmap->funcs == &null_driver)
602         {
603             if (physdev->funcs->pCreateBitmap)
604             {
605                 ret = physdev->funcs->pCreateBitmap( physdev, hbitmap );
606                 if (ret)
607                 {
608                     bitmap->funcs = physdev->funcs;
609                     set_initial_bitmap_bits( hbitmap, bitmap );
610                 }
611             }
612             else bitmap->funcs = &dib_driver;  /* use the DIB driver to emulate DDB support */
613         }
614         else
615         {
616             FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap );
617             ret = FALSE;
618         }
619     }
620     GDI_ReleaseObj( hbitmap );
621     return ret;
622 }
623
624
625 /***********************************************************************
626  *           BITMAP_SelectObject
627  */
628 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
629 {
630     HGDIOBJ ret;
631     BITMAPOBJ *bitmap;
632     DC *dc;
633     PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
634
635     if (!(dc = get_dc_ptr( hdc ))) return 0;
636
637     if (GetObjectType( hdc ) != OBJ_MEMDC)
638     {
639         ret = 0;
640         goto done;
641     }
642     ret = dc->hBitmap;
643     if (handle == dc->hBitmap) goto done;  /* nothing to do */
644
645     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
646     {
647         ret = 0;
648         goto done;
649     }
650
651     if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP)))
652     {
653         WARN( "Bitmap already selected in another DC\n" );
654         GDI_ReleaseObj( handle );
655         ret = 0;
656         goto done;
657     }
658
659     if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
660
661     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
662     if(old_physdev == dc->dibdrv)
663         old_physdev = pop_dc_driver( &dc->physDev );
664
665     physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
666     if (bitmap->dib || physdev->funcs == &null_driver)
667     {
668         physdev = dc->dibdrv;
669         if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
670         else
671         {
672             if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
673             dc->dibdrv = physdev = dc->physDev;
674         }
675     }
676
677     if (!BITMAP_SetOwnerDC( handle, physdev ))
678     {
679         GDI_ReleaseObj( handle );
680         ret = 0;
681         goto done;
682     }
683     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
684     {
685         GDI_ReleaseObj( handle );
686         ret = 0;
687     }
688     else
689     {
690         dc->hBitmap = handle;
691         GDI_inc_ref_count( handle );
692         dc->dirty = 0;
693         dc->vis_rect.left   = 0;
694         dc->vis_rect.top    = 0;
695         dc->vis_rect.right  = bitmap->bitmap.bmWidth;
696         dc->vis_rect.bottom = bitmap->bitmap.bmHeight;
697         SetRectRgn( dc->hVisRgn, 0, 0, bitmap->bitmap.bmWidth, bitmap->bitmap.bmHeight);
698         GDI_ReleaseObj( handle );
699         DC_InitDC( dc );
700         GDI_dec_ref_count( ret );
701     }
702
703  done:
704     if(!ret)
705     {
706         if (physdev && physdev == dc->dibdrv)
707             pop_dc_driver( &dc->physDev );
708         if (old_physdev && old_physdev == dc->dibdrv)
709             push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs );
710     }
711     if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
712     release_dc_ptr( dc );
713     return ret;
714 }
715
716
717 /***********************************************************************
718  *           BITMAP_DeleteObject
719  */
720 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
721 {
722     const struct gdi_dc_funcs *funcs;
723     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
724
725     if (!bmp) return FALSE;
726     funcs = bmp->funcs;
727     GDI_ReleaseObj( handle );
728
729     funcs->pDeleteBitmap( handle );
730
731     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
732
733     HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
734
735     if (bmp->dib)
736     {
737         DIBSECTION *dib = bmp->dib;
738
739         if (dib->dsBm.bmBits)
740         {
741             if (dib->dshSection)
742             {
743                 SYSTEM_INFO SystemInfo;
744                 GetSystemInfo( &SystemInfo );
745                 UnmapViewOfFile( (char *)dib->dsBm.bmBits -
746                                  (dib->dsOffset % SystemInfo.dwAllocationGranularity) );
747             }
748             else if (!dib->dsOffset)
749                 VirtualFree(dib->dsBm.bmBits, 0L, MEM_RELEASE );
750         }
751         HeapFree(GetProcessHeap(), 0, dib);
752         HeapFree(GetProcessHeap(), 0, bmp->color_table);
753     }
754     return HeapFree( GetProcessHeap(), 0, bmp );
755 }
756
757
758 /***********************************************************************
759  *           BITMAP_GetObject
760  */
761 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
762 {
763     INT ret;
764     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
765
766     if (!bmp) return 0;
767
768     if (!buffer) ret = sizeof(BITMAP);
769     else if (count < sizeof(BITMAP)) ret = 0;
770     else if (bmp->dib)
771     {
772         if (count >= sizeof(DIBSECTION))
773         {
774             DIBSECTION *dib = buffer;
775             *dib = *bmp->dib;
776             dib->dsBmih.biHeight = abs( dib->dsBmih.biHeight );
777             ret = sizeof(DIBSECTION);
778         }
779         else /* if (count >= sizeof(BITMAP)) */
780         {
781             DIBSECTION *dib = bmp->dib;
782             memcpy( buffer, &dib->dsBm, sizeof(BITMAP) );
783             ret = sizeof(BITMAP);
784         }
785     }
786     else
787     {
788         memcpy( buffer, &bmp->bitmap, sizeof(BITMAP) );
789         ((BITMAP *) buffer)->bmBits = NULL;
790         ret = sizeof(BITMAP);
791     }
792     GDI_ReleaseObj( handle );
793     return ret;
794 }
795
796
797 /******************************************************************************
798  * CreateDiscardableBitmap [GDI32.@]
799  *
800  * Creates a discardable bitmap.
801  *
802  * RETURNS
803  *    Success: Handle to bitmap
804  *    Failure: NULL
805  */
806 HBITMAP WINAPI CreateDiscardableBitmap(
807     HDC hdc,    /* [in] Handle to device context */
808     INT width,  /* [in] Bitmap width */
809     INT height) /* [in] Bitmap height */
810 {
811     return CreateCompatibleBitmap( hdc, width, height );
812 }
813
814
815 /******************************************************************************
816  * GetBitmapDimensionEx [GDI32.@]
817  *
818  * Retrieves dimensions of a bitmap.
819  *
820  * RETURNS
821  *    Success: TRUE
822  *    Failure: FALSE
823  */
824 BOOL WINAPI GetBitmapDimensionEx(
825     HBITMAP hbitmap, /* [in]  Handle to bitmap */
826     LPSIZE size)     /* [out] Address of struct receiving dimensions */
827 {
828     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
829     if (!bmp) return FALSE;
830     *size = bmp->size;
831     GDI_ReleaseObj( hbitmap );
832     return TRUE;
833 }
834
835
836 /******************************************************************************
837  * SetBitmapDimensionEx [GDI32.@]
838  *
839  * Assigns dimensions to a bitmap.
840  * MSDN says that this function will fail if hbitmap is a handle created by
841  * CreateDIBSection, but that's not true on Windows 2000.
842  *
843  * RETURNS
844  *    Success: TRUE
845  *    Failure: FALSE
846  */
847 BOOL WINAPI SetBitmapDimensionEx(
848     HBITMAP hbitmap, /* [in]  Handle to bitmap */
849     INT x,           /* [in]  Bitmap width */
850     INT y,           /* [in]  Bitmap height */
851     LPSIZE prevSize) /* [out] Address of structure for orig dims */
852 {
853     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
854     if (!bmp) return FALSE;
855     if (prevSize) *prevSize = bmp->size;
856     bmp->size.cx = x;
857     bmp->size.cy = y;
858     GDI_ReleaseObj( hbitmap );
859     return TRUE;
860 }