advapi32: Implement CredMarshalCredential and CredUnmarshalCredential.
[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 BOOL nulldrv_CopyBitmap( HBITMAP src, HBITMAP dst )
69 {
70     BOOL ret = TRUE;
71     BITMAPOBJ *src_bmp = GDI_GetObjPtr( src, OBJ_BITMAP );
72
73     if (!src_bmp) return FALSE;
74     if (src_bmp->dib.dsBm.bmBits)
75     {
76         BITMAPOBJ *dst_bmp = GDI_GetObjPtr( dst, OBJ_BITMAP );
77         int stride = get_dib_stride( dst_bmp->dib.dsBm.bmWidth, dst_bmp->dib.dsBm.bmBitsPixel );
78         dst_bmp->dib.dsBm.bmBits = HeapAlloc( GetProcessHeap(), 0, dst_bmp->dib.dsBm.bmHeight * stride );
79         if (dst_bmp->dib.dsBm.bmBits)
80             memcpy( dst_bmp->dib.dsBm.bmBits, src_bmp->dib.dsBm.bmBits, dst_bmp->dib.dsBm.bmHeight * stride );
81         else
82             ret = FALSE;
83         GDI_ReleaseObj( dst );
84     }
85     GDI_ReleaseObj( src );
86     return ret;
87 }
88
89
90 /******************************************************************************
91  * CreateBitmap [GDI32.@]
92  *
93  * Creates a bitmap with the specified info.
94  *
95  * PARAMS
96  *    width  [I] bitmap width
97  *    height [I] bitmap height
98  *    planes [I] Number of color planes
99  *    bpp    [I] Number of bits to identify a color
100  *    bits   [I] Pointer to array containing color data
101  *
102  * RETURNS
103  *    Success: Handle to bitmap
104  *    Failure: 0
105  */
106 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
107                              UINT bpp, LPCVOID bits )
108 {
109     BITMAP bm;
110
111     bm.bmType = 0;
112     bm.bmWidth = width;
113     bm.bmHeight = height;
114     bm.bmWidthBytes = get_bitmap_stride( width, bpp );
115     bm.bmPlanes = planes;
116     bm.bmBitsPixel = bpp;
117     bm.bmBits = (LPVOID)bits;
118
119     return CreateBitmapIndirect( &bm );
120 }
121
122 /******************************************************************************
123  * CreateCompatibleBitmap [GDI32.@]
124  *
125  * Creates a bitmap compatible with the DC.
126  *
127  * PARAMS
128  *    hdc    [I] Handle to device context
129  *    width  [I] Width of bitmap
130  *    height [I] Height of bitmap
131  *
132  * RETURNS
133  *    Success: Handle to bitmap
134  *    Failure: 0
135  */
136 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
137 {
138     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
139     BITMAPINFO *bi = (BITMAPINFO *)buffer;
140     DIBSECTION dib;
141
142     TRACE("(%p,%d,%d)\n", hdc, width, height);
143
144     if (GetObjectType( hdc ) != OBJ_MEMDC)
145         return CreateBitmap( width, height,
146                              GetDeviceCaps(hdc, PLANES), GetDeviceCaps(hdc, BITSPIXEL), NULL );
147
148     switch (GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(dib), &dib ))
149     {
150     case sizeof(BITMAP): /* A device-dependent bitmap is selected in the DC */
151         return CreateBitmap( width, height, dib.dsBm.bmPlanes, dib.dsBm.bmBitsPixel, NULL );
152
153     case sizeof(DIBSECTION): /* A DIB section is selected in the DC */
154         bi->bmiHeader = dib.dsBmih;
155         bi->bmiHeader.biWidth  = width;
156         bi->bmiHeader.biHeight = height;
157         if (dib.dsBmih.biCompression == BI_BITFIELDS)  /* copy the color masks */
158             memcpy(bi->bmiColors, dib.dsBitfields, sizeof(dib.dsBitfields));
159         else if (dib.dsBmih.biBitCount <= 8)  /* copy the color table */
160             GetDIBColorTable(hdc, 0, 256, bi->bmiColors);
161         return CreateDIBSection( hdc, bi, DIB_RGB_COLORS, NULL, NULL, 0 );
162
163     default:
164         return 0;
165     }
166 }
167
168
169 /******************************************************************************
170  * CreateBitmapIndirect [GDI32.@]
171  *
172  * Creates a bitmap with the specified info.
173  *
174  * PARAMS
175  *  bmp [I] Pointer to the bitmap info describing the bitmap
176  *
177  * RETURNS
178  *    Success: Handle to bitmap
179  *    Failure: NULL. Use GetLastError() to determine the cause.
180  *
181  * NOTES
182  *  If a width or height of 0 are given, a 1x1 monochrome bitmap is returned.
183  */
184 HBITMAP WINAPI CreateBitmapIndirect( const BITMAP *bmp )
185 {
186     BITMAP bm;
187     BITMAPOBJ *bmpobj;
188     HBITMAP hbitmap;
189
190     if (!bmp || bmp->bmType)
191     {
192         SetLastError( ERROR_INVALID_PARAMETER );
193         return NULL;
194     }
195
196     if (bmp->bmWidth > 0x7ffffff || bmp->bmHeight > 0x7ffffff)
197     {
198         SetLastError( ERROR_INVALID_PARAMETER );
199         return 0;
200     }
201
202     bm = *bmp;
203
204     if (!bm.bmWidth || !bm.bmHeight)
205     {
206         return GetStockObject( DEFAULT_BITMAP );
207     }
208     else
209     {
210         if (bm.bmHeight < 0)
211             bm.bmHeight = -bm.bmHeight;
212         if (bm.bmWidth < 0)
213             bm.bmWidth = -bm.bmWidth;
214     }
215
216     if (bm.bmPlanes != 1)
217     {
218         FIXME("planes = %d\n", bm.bmPlanes);
219         SetLastError( ERROR_INVALID_PARAMETER );
220         return NULL;
221     }
222
223     /* Windows only uses 1, 4, 8, 16, 24 and 32 bpp */
224     if(bm.bmBitsPixel == 1)         bm.bmBitsPixel = 1;
225     else if(bm.bmBitsPixel <= 4)    bm.bmBitsPixel = 4;
226     else if(bm.bmBitsPixel <= 8)    bm.bmBitsPixel = 8;
227     else if(bm.bmBitsPixel <= 16)   bm.bmBitsPixel = 16;
228     else if(bm.bmBitsPixel <= 24)   bm.bmBitsPixel = 24;
229     else if(bm.bmBitsPixel <= 32)   bm.bmBitsPixel = 32;
230     else {
231         WARN("Invalid bmBitsPixel %d, returning ERROR_INVALID_PARAMETER\n", bm.bmBitsPixel);
232         SetLastError(ERROR_INVALID_PARAMETER);
233         return NULL;
234     }
235
236     /* Windows ignores the provided bm.bmWidthBytes */
237     bm.bmWidthBytes = get_bitmap_stride( bm.bmWidth, bm.bmBitsPixel );
238     /* XP doesn't allow to create bitmaps larger than 128 Mb */
239     if (bm.bmHeight > 128 * 1024 * 1024 / bm.bmWidthBytes)
240     {
241         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
242         return 0;
243     }
244
245     /* Create the BITMAPOBJ */
246     if (!(bmpobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*bmpobj) )))
247     {
248         SetLastError( ERROR_NOT_ENOUGH_MEMORY );
249         return 0;
250     }
251
252     bmpobj->dib.dsBm = bm;
253     bmpobj->dib.dsBm.bmBits = NULL;
254     bmpobj->funcs = &null_driver;
255
256     if (!(hbitmap = alloc_gdi_handle( &bmpobj->header, OBJ_BITMAP, &bitmap_funcs )))
257     {
258         HeapFree( GetProcessHeap(), 0, bmpobj );
259         return 0;
260     }
261
262     if (bm.bmBits)
263         SetBitmapBits( hbitmap, bm.bmHeight * bm.bmWidthBytes, bm.bmBits );
264
265     TRACE("%dx%d, bpp %d planes %d: returning %p\n", bm.bmWidth, bm.bmHeight,
266           bm.bmBitsPixel, bm.bmPlanes, hbitmap);
267
268     return hbitmap;
269 }
270
271
272 /***********************************************************************
273  * GetBitmapBits [GDI32.@]
274  *
275  * Copies bitmap bits of bitmap to buffer.
276  *
277  * RETURNS
278  *    Success: Number of bytes copied
279  *    Failure: 0
280  */
281 LONG WINAPI GetBitmapBits(
282     HBITMAP hbitmap, /* [in]  Handle to bitmap */
283     LONG count,        /* [in]  Number of bytes to copy */
284     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
285 {
286     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
287     BITMAPINFO *info = (BITMAPINFO *)buffer;
288     struct gdi_image_bits src_bits;
289     struct bitblt_coords src;
290     int dst_stride, max, ret;
291     BITMAPOBJ *bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
292
293     if (!bmp) return 0;
294
295     dst_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
296     ret = max = dst_stride * bmp->dib.dsBm.bmHeight;
297     if (!bits) goto done;
298     if (count > max) count = max;
299     ret = count;
300
301     src.visrect.left = 0;
302     src.visrect.right = bmp->dib.dsBm.bmWidth;
303     src.visrect.top = 0;
304     src.visrect.bottom = (count + dst_stride - 1) / dst_stride;
305     src.x = src.y = 0;
306     src.width = src.visrect.right - src.visrect.left;
307     src.height = src.visrect.bottom - src.visrect.top;
308
309     if (!bmp->funcs->pGetImage( NULL, hbitmap, info, &src_bits, &src ))
310     {
311         const char *src_ptr = src_bits.ptr;
312         int src_stride = get_dib_stride( info->bmiHeader.biWidth, info->bmiHeader.biBitCount );
313
314         /* GetBitmapBits returns 16-bit aligned data */
315
316         if (info->bmiHeader.biHeight > 0)
317         {
318             src_ptr += (info->bmiHeader.biHeight - 1) * src_stride;
319             src_stride = -src_stride;
320         }
321         src_ptr += src.visrect.top * src_stride;
322
323         if (src_stride == dst_stride) memcpy( bits, src_ptr, count );
324         else while (count > 0)
325         {
326             memcpy( bits, src_ptr, min( count, dst_stride ) );
327             src_ptr += src_stride;
328             bits = (char *)bits + dst_stride;
329             count -= dst_stride;
330         }
331         if (src_bits.free) src_bits.free( &src_bits );
332     }
333     else ret = 0;
334
335 done:
336     GDI_ReleaseObj( hbitmap );
337     return ret;
338 }
339
340
341 /******************************************************************************
342  * SetBitmapBits [GDI32.@]
343  *
344  * Sets bits of color data for a bitmap.
345  *
346  * RETURNS
347  *    Success: Number of bytes used in setting the bitmap bits
348  *    Failure: 0
349  */
350 LONG WINAPI SetBitmapBits(
351     HBITMAP hbitmap, /* [in] Handle to bitmap */
352     LONG count,        /* [in] Number of bytes in bitmap array */
353     LPCVOID bits)      /* [in] Address of array with bitmap bits */
354 {
355     char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
356     BITMAPINFO *info = (BITMAPINFO *)buffer;
357     BITMAPOBJ *bmp;
358     DWORD err;
359     int i, src_stride, dst_stride;
360     struct bitblt_coords src, dst;
361     struct gdi_image_bits src_bits;
362     HRGN clip = NULL;
363
364     if (!bits) return 0;
365
366     bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
367     if (!bmp) return 0;
368
369     if (count < 0) {
370         WARN("(%d): Negative number of bytes passed???\n", count );
371         count = -count;
372     }
373
374     src_stride = get_bitmap_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
375     count = min( count, src_stride * bmp->dib.dsBm.bmHeight );
376
377     dst_stride = get_dib_stride( bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmBitsPixel );
378
379     src.visrect.left   = src.x = 0;
380     src.visrect.top    = src.y = 0;
381     src.visrect.right  = src.width = bmp->dib.dsBm.bmWidth;
382     src.visrect.bottom = src.height = (count + src_stride - 1 ) / src_stride;
383     dst = src;
384
385     if (count % src_stride)
386     {
387         HRGN last_row;
388         int extra_pixels = ((count % src_stride) << 3) / bmp->dib.dsBm.bmBitsPixel;
389
390         if ((count % src_stride << 3) % bmp->dib.dsBm.bmBitsPixel)
391             FIXME( "Unhandled partial pixel\n" );
392         clip = CreateRectRgn( src.visrect.left, src.visrect.top,
393                               src.visrect.right, src.visrect.bottom - 1 );
394         last_row = CreateRectRgn( src.visrect.left, src.visrect.bottom - 1,
395                                   src.visrect.left + extra_pixels, src.visrect.bottom );
396         CombineRgn( clip, clip, last_row, RGN_OR );
397         DeleteObject( last_row );
398     }
399
400     TRACE("(%p, %d, %p) %dx%d %d bpp fetched height: %d\n",
401           hbitmap, count, bits, bmp->dib.dsBm.bmWidth, bmp->dib.dsBm.bmHeight,
402           bmp->dib.dsBm.bmBitsPixel, src.height );
403
404     if (src_stride == dst_stride)
405     {
406         src_bits.ptr = (void *)bits;
407         src_bits.is_copy = FALSE;
408         src_bits.free = NULL;
409     }
410     else
411     {
412         if (!(src_bits.ptr = HeapAlloc( GetProcessHeap(), 0, dst.height * dst_stride )))
413         {
414             GDI_ReleaseObj( hbitmap );
415             return 0;
416         }
417         src_bits.is_copy = TRUE;
418         src_bits.free = free_heap_bits;
419         for (i = 0; i < count / src_stride; i++)
420             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, src_stride );
421         if (count % src_stride)
422             memcpy( (char *)src_bits.ptr + i * dst_stride, (char *)bits + i * src_stride, count % src_stride );
423     }
424
425     /* query the color info */
426     info->bmiHeader.biSize          = sizeof(info->bmiHeader);
427     info->bmiHeader.biPlanes        = 1;
428     info->bmiHeader.biBitCount      = bmp->dib.dsBm.bmBitsPixel;
429     info->bmiHeader.biCompression   = BI_RGB;
430     info->bmiHeader.biXPelsPerMeter = 0;
431     info->bmiHeader.biYPelsPerMeter = 0;
432     info->bmiHeader.biClrUsed       = 0;
433     info->bmiHeader.biClrImportant  = 0;
434     info->bmiHeader.biWidth         = 0;
435     info->bmiHeader.biHeight        = 0;
436     info->bmiHeader.biSizeImage     = 0;
437     err = bmp->funcs->pPutImage( NULL, hbitmap, 0, info, NULL, NULL, NULL, SRCCOPY );
438
439     if (!err || err == ERROR_BAD_FORMAT)
440     {
441         info->bmiHeader.biWidth     = bmp->dib.dsBm.bmWidth;
442         info->bmiHeader.biHeight    = -dst.height;
443         info->bmiHeader.biSizeImage = dst.height * dst_stride;
444         err = bmp->funcs->pPutImage( NULL, hbitmap, clip, info, &src_bits, &src, &dst, SRCCOPY );
445     }
446     if (err) count = 0;
447
448     if (clip) DeleteObject( clip );
449     if (src_bits.free) src_bits.free( &src_bits );
450     GDI_ReleaseObj( hbitmap );
451     return count;
452 }
453
454
455 static void set_initial_bitmap_bits( HBITMAP hbitmap, BITMAPOBJ *bmp )
456 {
457     char src_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
458     BITMAPINFO *src_info = (BITMAPINFO *)src_bmibuf;
459     char dst_bmibuf[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
460     BITMAPINFO *dst_info = (BITMAPINFO *)dst_bmibuf;
461     DWORD err;
462     struct gdi_image_bits bits;
463     struct bitblt_coords src, dst;
464
465     if (!bmp->dib.dsBm.bmBits) return;
466     if (bmp->funcs->pPutImage == nulldrv_PutImage) return;
467
468     get_ddb_bitmapinfo( bmp, src_info );
469
470     bits.ptr = bmp->dib.dsBm.bmBits;
471     bits.is_copy = FALSE;
472     bits.free = NULL;
473     bits.param = NULL;
474
475     src.x      = 0;
476     src.y      = 0;
477     src.width  = bmp->dib.dsBm.bmWidth;
478     src.height = bmp->dib.dsBm.bmHeight;
479     src.visrect.left   = 0;
480     src.visrect.top    = 0;
481     src.visrect.right  = bmp->dib.dsBm.bmWidth;
482     src.visrect.bottom = bmp->dib.dsBm.bmHeight;
483     dst = src;
484
485     copy_bitmapinfo( dst_info, src_info );
486
487     err = bmp->funcs->pPutImage( NULL, hbitmap, 0, dst_info, &bits, &src, &dst, 0 );
488     if (err == ERROR_BAD_FORMAT)
489     {
490         err = convert_bits( src_info, &src, dst_info, &bits, FALSE );
491         if (!err) err = bmp->funcs->pPutImage( NULL, hbitmap, 0, dst_info, &bits, &src, &dst, 0 );
492         if (bits.free) bits.free( &bits );
493     }
494 }
495
496 /***********************************************************************
497  *           BITMAP_SetOwnerDC
498  *
499  * Set the type of DC that owns the bitmap. This is used when the
500  * bitmap is selected into a device to initialize the bitmap function
501  * table.
502  */
503 static BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
504 {
505     BITMAPOBJ *bitmap;
506     BOOL ret = TRUE;
507
508     /* never set the owner of the stock bitmap since it can be selected in multiple DCs */
509     if (hbitmap == GetStockObject(DEFAULT_BITMAP)) return TRUE;
510
511     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
512
513     if (bitmap->funcs != physdev->funcs)
514     {
515         /* we can only change from the null driver to some other driver */
516         if (bitmap->funcs == &null_driver)
517         {
518             if (physdev->funcs->pCreateBitmap)
519             {
520                 ret = physdev->funcs->pCreateBitmap( physdev, hbitmap );
521                 if (ret)
522                 {
523                     bitmap->funcs = physdev->funcs;
524                     set_initial_bitmap_bits( hbitmap, bitmap );
525                 }
526             }
527             else bitmap->funcs = &dib_driver;  /* use the DIB driver to emulate DDB support */
528         }
529         else
530         {
531             FIXME( "Trying to select bitmap %p in different DC type\n", hbitmap );
532             ret = FALSE;
533         }
534     }
535     GDI_ReleaseObj( hbitmap );
536     return ret;
537 }
538
539
540 /***********************************************************************
541  *           BITMAP_SelectObject
542  */
543 static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
544 {
545     HGDIOBJ ret;
546     BITMAPOBJ *bitmap;
547     DC *dc;
548     PHYSDEV physdev = NULL, old_physdev = NULL, pathdev = NULL;
549
550     if (!(dc = get_dc_ptr( hdc ))) return 0;
551
552     if (GetObjectType( hdc ) != OBJ_MEMDC)
553     {
554         ret = 0;
555         goto done;
556     }
557     ret = dc->hBitmap;
558     if (handle == dc->hBitmap) goto done;  /* nothing to do */
559
560     if (!(bitmap = GDI_GetObjPtr( handle, OBJ_BITMAP )))
561     {
562         ret = 0;
563         goto done;
564     }
565
566     if (bitmap->header.selcount && (handle != GetStockObject(DEFAULT_BITMAP)))
567     {
568         WARN( "Bitmap already selected in another DC\n" );
569         GDI_ReleaseObj( handle );
570         ret = 0;
571         goto done;
572     }
573
574     if (dc->physDev->funcs == &path_driver) pathdev = pop_dc_driver( &dc->physDev );
575
576     old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
577     if(old_physdev == dc->dibdrv)
578         old_physdev = pop_dc_driver( &dc->physDev );
579
580     physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
581     if (physdev->funcs == &null_driver)
582     {
583         physdev = dc->dibdrv;
584         if (physdev) push_dc_driver( &dc->physDev, physdev, physdev->funcs );
585         else
586         {
587             if (!dib_driver.pCreateDC( &dc->physDev, NULL, NULL, NULL, NULL )) goto done;
588             dc->dibdrv = physdev = dc->physDev;
589         }
590     }
591
592     if (!BITMAP_SetOwnerDC( handle, physdev ))
593     {
594         GDI_ReleaseObj( handle );
595         ret = 0;
596         goto done;
597     }
598     if (!physdev->funcs->pSelectBitmap( physdev, handle ))
599     {
600         GDI_ReleaseObj( handle );
601         ret = 0;
602     }
603     else
604     {
605         dc->hBitmap = handle;
606         GDI_inc_ref_count( handle );
607         dc->dirty = 0;
608         dc->vis_rect.left   = 0;
609         dc->vis_rect.top    = 0;
610         dc->vis_rect.right  = bitmap->dib.dsBm.bmWidth;
611         dc->vis_rect.bottom = bitmap->dib.dsBm.bmHeight;
612         GDI_ReleaseObj( handle );
613         DC_InitDC( dc );
614         GDI_dec_ref_count( ret );
615     }
616
617  done:
618     if(!ret)
619     {
620         if (physdev && physdev == dc->dibdrv)
621             pop_dc_driver( &dc->physDev );
622         if (old_physdev && old_physdev == dc->dibdrv)
623             push_dc_driver( &dc->physDev, old_physdev, old_physdev->funcs );
624     }
625     if (pathdev) push_dc_driver( &dc->physDev, pathdev, pathdev->funcs );
626     release_dc_ptr( dc );
627     return ret;
628 }
629
630
631 /***********************************************************************
632  *           BITMAP_DeleteObject
633  */
634 static BOOL BITMAP_DeleteObject( HGDIOBJ handle )
635 {
636     const struct gdi_dc_funcs *funcs;
637     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
638
639     if (!bmp) return FALSE;
640     funcs = bmp->funcs;
641     GDI_ReleaseObj( handle );
642
643     funcs->pDeleteBitmap( handle );
644
645     if (!(bmp = free_gdi_handle( handle ))) return FALSE;
646
647     HeapFree( GetProcessHeap(), 0, bmp->dib.dsBm.bmBits );
648     return HeapFree( GetProcessHeap(), 0, bmp );
649 }
650
651
652 /***********************************************************************
653  *           BITMAP_GetObject
654  */
655 static INT BITMAP_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
656 {
657     INT ret = 0;
658     BITMAPOBJ *bmp = GDI_GetObjPtr( handle, OBJ_BITMAP );
659
660     if (!bmp) return 0;
661
662     if (!buffer) ret = sizeof(BITMAP);
663     else if (count >= sizeof(BITMAP))
664     {
665         BITMAP *bitmap = buffer;
666         *bitmap = bmp->dib.dsBm;
667         bitmap->bmBits = NULL;
668         ret = sizeof(BITMAP);
669     }
670     GDI_ReleaseObj( handle );
671     return ret;
672 }
673
674
675 /******************************************************************************
676  * CreateDiscardableBitmap [GDI32.@]
677  *
678  * Creates a discardable bitmap.
679  *
680  * RETURNS
681  *    Success: Handle to bitmap
682  *    Failure: NULL
683  */
684 HBITMAP WINAPI CreateDiscardableBitmap(
685     HDC hdc,    /* [in] Handle to device context */
686     INT width,  /* [in] Bitmap width */
687     INT height) /* [in] Bitmap height */
688 {
689     return CreateCompatibleBitmap( hdc, width, height );
690 }
691
692
693 /******************************************************************************
694  * GetBitmapDimensionEx [GDI32.@]
695  *
696  * Retrieves dimensions of a bitmap.
697  *
698  * RETURNS
699  *    Success: TRUE
700  *    Failure: FALSE
701  */
702 BOOL WINAPI GetBitmapDimensionEx(
703     HBITMAP hbitmap, /* [in]  Handle to bitmap */
704     LPSIZE size)     /* [out] Address of struct receiving dimensions */
705 {
706     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
707     if (!bmp) return FALSE;
708     *size = bmp->size;
709     GDI_ReleaseObj( hbitmap );
710     return TRUE;
711 }
712
713
714 /******************************************************************************
715  * SetBitmapDimensionEx [GDI32.@]
716  *
717  * Assigns dimensions to a bitmap.
718  * MSDN says that this function will fail if hbitmap is a handle created by
719  * CreateDIBSection, but that's not true on Windows 2000.
720  *
721  * RETURNS
722  *    Success: TRUE
723  *    Failure: FALSE
724  */
725 BOOL WINAPI SetBitmapDimensionEx(
726     HBITMAP hbitmap, /* [in]  Handle to bitmap */
727     INT x,           /* [in]  Bitmap width */
728     INT y,           /* [in]  Bitmap height */
729     LPSIZE prevSize) /* [out] Address of structure for orig dims */
730 {
731     BITMAPOBJ * bmp = GDI_GetObjPtr( hbitmap, OBJ_BITMAP );
732     if (!bmp) return FALSE;
733     if (prevSize) *prevSize = bmp->size;
734     bmp->size.cx = x;
735     bmp->size.cy = y;
736     GDI_ReleaseObj( hbitmap );
737     return TRUE;
738 }