Fixed CreateCompatibleBitmap when called with 0 width or height.
[wine] / objects / bitmap.c
1 /*
2  * GDI bitmap objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1998 Huw D M Davies
6  */
7
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include "wine/winbase16.h"
12 #include "gdi.h"
13 #include "dc.h"
14 #include "bitmap.h"
15 #include "heap.h"
16 #include "global.h"
17 #include "cursoricon.h"
18 #include "debugtools.h"
19 #include "monitor.h"
20 #include "wine/winuser16.h"
21
22 DECLARE_DEBUG_CHANNEL(bitmap)
23 DECLARE_DEBUG_CHANNEL(resource)
24
25 BITMAP_DRIVER *BITMAP_Driver = NULL;
26
27
28 /***********************************************************************
29  *           BITMAP_GetWidthBytes
30  *
31  * Return number of bytes taken by a scanline of 16-bit aligned Windows DDB
32  * data.
33  */
34 INT BITMAP_GetWidthBytes( INT bmWidth, INT bpp )
35 {
36     switch(bpp)
37     {
38     case 1:
39         return 2 * ((bmWidth+15) >> 4);
40
41     case 24:
42         bmWidth *= 3; /* fall through */
43     case 8:
44         return bmWidth + (bmWidth & 1);
45
46     case 32:
47         return bmWidth * 4;
48
49     case 16:
50     case 15:
51         return bmWidth * 2;
52
53     case 4:
54         return 2 * ((bmWidth+3) >> 2);
55
56     default:
57         WARN_(bitmap)("Unknown depth %d, please report.\n", bpp );
58     }
59     return -1;
60 }
61
62 /***********************************************************************
63  *           CreateUserBitmap16    (GDI.407)
64  */
65 HBITMAP16 WINAPI CreateUserBitmap16( INT16 width, INT16 height, UINT16 planes,
66                                      UINT16 bpp, LPCVOID bits )
67 {
68     return CreateBitmap16( width, height, planes, bpp, bits );
69 }
70
71 /***********************************************************************
72  *           CreateUserDiscardableBitmap16    (GDI.409)
73  */
74 HBITMAP16 WINAPI CreateUserDiscardableBitmap16( WORD dummy, 
75                                                 INT16 width, INT16 height )
76 {
77     return CreateUserBitmap16( width, height, 1, MONITOR_GetDepth(&MONITOR_PrimaryMonitor), NULL );
78 }
79
80
81 /***********************************************************************
82  *           CreateBitmap16    (GDI.48)
83  */
84 HBITMAP16 WINAPI CreateBitmap16( INT16 width, INT16 height, UINT16 planes,
85                                  UINT16 bpp, LPCVOID bits )
86 {
87     return CreateBitmap( width, height, planes, bpp, bits );
88 }
89
90
91 /******************************************************************************
92  * CreateBitmap32 [GDI32.25]  Creates a bitmap with the specified info
93  *
94  * PARAMS
95  *    width  [I] bitmap width
96  *    height [I] bitmap height
97  *    planes [I] Number of color planes
98  *    bpp    [I] Number of bits to identify a color
99  *    bits   [I] Pointer to array containing color data
100  *
101  * RETURNS
102  *    Success: Handle to bitmap
103  *    Failure: 0
104  */
105 HBITMAP WINAPI CreateBitmap( INT width, INT height, UINT planes,
106                                  UINT bpp, LPCVOID bits )
107 {
108     BITMAPOBJ *bmp;
109     HBITMAP hbitmap;
110
111     planes = (BYTE)planes;
112     bpp    = (BYTE)bpp;
113
114
115       /* Check parameters */
116     if (!height || !width) return 0;
117     if (planes != 1) {
118         FIXME_(bitmap)("planes = %d\n", planes);
119         return 0;
120     }
121     if (height < 0) height = -height;
122     if (width < 0) width = -width;
123
124       /* Create the BITMAPOBJ */
125     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
126     if (!hbitmap) return 0;
127
128     TRACE_(bitmap)("%dx%d, %d colors returning %08x\n", width, height,
129           1 << (planes*bpp), hbitmap);
130
131     bmp = (BITMAPOBJ *) GDI_HEAP_LOCK( hbitmap );
132
133     bmp->size.cx = 0;
134     bmp->size.cy = 0;
135     bmp->bitmap.bmType = 0;
136     bmp->bitmap.bmWidth = width;
137     bmp->bitmap.bmHeight = height;
138     bmp->bitmap.bmPlanes = planes;
139     bmp->bitmap.bmBitsPixel = bpp;
140     bmp->bitmap.bmWidthBytes = BITMAP_GetWidthBytes( width, bpp );
141     bmp->bitmap.bmBits = NULL;
142
143     bmp->DDBitmap = NULL;
144     bmp->dib = NULL;
145
146     if (bits) /* Set bitmap bits */
147         SetBitmapBits( hbitmap, height * bmp->bitmap.bmWidthBytes,
148                          bits );
149     GDI_HEAP_UNLOCK( hbitmap );
150     return hbitmap;
151 }
152
153
154 /***********************************************************************
155  *           CreateCompatibleBitmap16    (GDI.51)
156  */
157 HBITMAP16 WINAPI CreateCompatibleBitmap16(HDC16 hdc, INT16 width, INT16 height)
158 {
159     return CreateCompatibleBitmap( hdc, width, height );
160 }
161
162
163 /******************************************************************************
164  * CreateCompatibleBitmap32 [GDI32.30]  Creates a bitmap compatible with the DC
165  *
166  * PARAMS
167  *    hdc    [I] Handle to device context
168  *    width  [I] Width of bitmap
169  *    height [I] Height of bitmap
170  *
171  * RETURNS
172  *    Success: Handle to bitmap
173  *    Failure: 0
174  */
175 HBITMAP WINAPI CreateCompatibleBitmap( HDC hdc, INT width, INT height)
176 {
177     HBITMAP hbmpRet = 0;
178     DC *dc;
179
180     TRACE_(bitmap)("(%04x,%d,%d) = \n", hdc, width, height );
181     if (!(dc = DC_GetDCPtr( hdc ))) return 0;
182     if ((width >= 0x10000) || (height >= 0x10000)) {
183         FIXME_(bitmap)("got bad width %d or height %d, please look for reason\n",
184               width, height );
185     } else {
186         /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
187         if (!width || !height) 
188            hbmpRet = CreateBitmap( 1, 1, 1, 1, NULL );
189         else 
190            hbmpRet = CreateBitmap( width, height, 1, dc->w.bitsPerPixel, NULL );
191         if(dc->funcs->pCreateBitmap)
192             dc->funcs->pCreateBitmap( hbmpRet );
193     }
194     TRACE_(bitmap)("\t\t%04x\n", hbmpRet);
195     GDI_HEAP_UNLOCK(hdc);
196     return hbmpRet;
197 }
198
199
200 /***********************************************************************
201  *           CreateBitmapIndirect16    (GDI.49)
202  */
203 HBITMAP16 WINAPI CreateBitmapIndirect16( const BITMAP16 * bmp )
204 {
205     return CreateBitmap16( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
206                            bmp->bmBitsPixel, PTR_SEG_TO_LIN( bmp->bmBits ) );
207 }
208
209
210 /******************************************************************************
211  * CreateBitmapIndirect32 [GDI32.26]  Creates a bitmap with the specifies info
212  *
213  * RETURNS
214  *    Success: Handle to bitmap
215  *    Failure: NULL
216  */
217 HBITMAP WINAPI CreateBitmapIndirect(
218     const BITMAP * bmp) /* [in] Pointer to the bitmap data */
219 {
220     return CreateBitmap( bmp->bmWidth, bmp->bmHeight, bmp->bmPlanes,
221                            bmp->bmBitsPixel, bmp->bmBits );
222 }
223
224
225 /***********************************************************************
226  *           GetBitmapBits16    (GDI.74)
227  */
228 LONG WINAPI GetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPVOID buffer )
229 {
230     return GetBitmapBits( hbitmap, count, buffer );
231 }
232
233
234 /***********************************************************************
235  * GetBitmapBits32 [GDI32.143]  Copies bitmap bits of bitmap to buffer
236  * 
237  * RETURNS
238  *    Success: Number of bytes copied
239  *    Failure: 0
240  */
241 LONG WINAPI GetBitmapBits(
242     HBITMAP hbitmap, /* [in]  Handle to bitmap */
243     LONG count,        /* [in]  Number of bytes to copy */
244     LPVOID bits)       /* [out] Pointer to buffer to receive bits */
245 {
246     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
247     LONG height, ret;
248     
249     if (!bmp) return 0;
250     
251     /* If the bits vector is null, the function should return the read size */
252     if(bits == NULL)
253         return bmp->bitmap.bmWidthBytes * bmp->bitmap.bmHeight;
254
255     if (count < 0) {
256         WARN_(bitmap)("(%ld): Negative number of bytes passed???\n", count );
257         count = -count;
258     }
259
260     /* Only get entire lines */
261     height = count / bmp->bitmap.bmWidthBytes;
262     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
263     count = height * bmp->bitmap.bmWidthBytes;
264     if (count == 0)
265       {
266         WARN_(bitmap)("Less then one entire line requested\n");
267         GDI_HEAP_UNLOCK( hbitmap );
268         return 0;
269       }
270
271
272     TRACE_(bitmap)("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
273             hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
274             1 << bmp->bitmap.bmBitsPixel, height );
275
276     if(bmp->DDBitmap) { 
277
278         TRACE_(bitmap)("Calling device specific BitmapBits\n");
279         if(bmp->DDBitmap->funcs->pBitmapBits)
280             ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
281                                                     DDB_GET);
282         else {
283             ERR_(bitmap)("BitmapBits == NULL??\n");
284             ret = 0;
285         }       
286
287     } else {
288
289         if(!bmp->bitmap.bmBits) {
290             WARN_(bitmap)("Bitmap is empty\n");
291             ret = 0;
292         } else {
293             memcpy(bits, bmp->bitmap.bmBits, count);
294             ret = count;
295         }
296
297     }
298
299     GDI_HEAP_UNLOCK( hbitmap );
300     return ret;
301 }
302
303
304 /***********************************************************************
305  *           SetBitmapBits16    (GDI.106)
306  */
307 LONG WINAPI SetBitmapBits16( HBITMAP16 hbitmap, LONG count, LPCVOID buffer )
308 {
309     return SetBitmapBits( hbitmap, count, buffer );
310 }
311
312
313 /******************************************************************************
314  * SetBitmapBits32 [GDI32.303]  Sets bits of color data for a bitmap
315  *
316  * RETURNS
317  *    Success: Number of bytes used in setting the bitmap bits
318  *    Failure: 0
319  */
320 LONG WINAPI SetBitmapBits(
321     HBITMAP hbitmap, /* [in] Handle to bitmap */
322     LONG count,        /* [in] Number of bytes in bitmap array */
323     LPCVOID bits)      /* [in] Address of array with bitmap bits */
324 {
325     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
326     LONG height, ret;
327     
328     if ((!bmp) || (!bits))
329         return 0;
330
331     if (count < 0) {
332         WARN_(bitmap)("(%ld): Negative number of bytes passed???\n", count );
333         count = -count;
334     }
335
336     /* Only get entire lines */
337     height = count / bmp->bitmap.bmWidthBytes;
338     if (height > bmp->bitmap.bmHeight) height = bmp->bitmap.bmHeight;
339     count = height * bmp->bitmap.bmWidthBytes;
340
341     TRACE_(bitmap)("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
342             hbitmap, count, bits, bmp->bitmap.bmWidth, bmp->bitmap.bmHeight,
343             1 << bmp->bitmap.bmBitsPixel, height );
344
345     if(bmp->DDBitmap) {
346
347         TRACE_(bitmap)("Calling device specific BitmapBits\n");
348         if(bmp->DDBitmap->funcs->pBitmapBits)
349             ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, (void *) bits,
350                                                     count, DDB_SET);
351         else {
352             ERR_(bitmap)("BitmapBits == NULL??\n");
353             ret = 0;
354         }
355         
356     } else {
357
358         if(!bmp->bitmap.bmBits) /* Alloc enough for entire bitmap */
359             bmp->bitmap.bmBits = HeapAlloc( GetProcessHeap(), 0, count );
360         if(!bmp->bitmap.bmBits) {
361             WARN_(bitmap)("Unable to allocate bit buffer\n");
362             ret = 0;
363         } else {
364             memcpy(bmp->bitmap.bmBits, bits, count);
365             ret = count;
366         }
367     }
368
369     GDI_HEAP_UNLOCK( hbitmap );
370     return ret;
371 }
372
373 /***********************************************************************
374  * LoadImage16 [USER.389]
375  *
376  */
377 HANDLE16 WINAPI LoadImage16( HINSTANCE16 hinst, LPCSTR name, UINT16 type,
378                              INT16 desiredx, INT16 desiredy, UINT16 loadflags)
379 {
380     LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
381     return LoadImageA( hinst, nameStr, type, 
382                        desiredx, desiredy, loadflags );
383 }
384
385 /**********************************************************************
386  *          LoadImageA    (USER32.365)
387  * 
388  * FIXME: implementation lacks some features, see LR_ defines in windows.h
389  */
390
391 HANDLE WINAPI LoadImageA( HINSTANCE hinst, LPCSTR name, UINT type,
392                               INT desiredx, INT desiredy, UINT loadflags)
393 {
394     HANDLE res;
395     LPWSTR u_name;
396
397     if (HIWORD(name)) u_name = HEAP_strdupAtoW(GetProcessHeap(), 0, name);
398     else u_name=(LPWSTR)name;
399     res = LoadImageW(hinst, u_name, type, desiredx, desiredy, loadflags);
400     if (HIWORD(name)) HeapFree(GetProcessHeap(), 0, u_name);
401     return res;
402 }
403
404
405 /******************************************************************************
406  * LoadImageW [USER32.366]  Loads an icon, cursor, or bitmap
407  *
408  * PARAMS
409  *    hinst     [I] Handle of instance that contains image
410  *    name      [I] Name of image
411  *    type      [I] Type of image
412  *    desiredx  [I] Desired width
413  *    desiredy  [I] Desired height
414  *    loadflags [I] Load flags
415  *
416  * RETURNS
417  *    Success: Handle to newly loaded image
418  *    Failure: NULL
419  *
420  * FIXME: Implementation lacks some features, see LR_ defines in windows.h
421  */
422 HANDLE WINAPI LoadImageW( HINSTANCE hinst, LPCWSTR name, UINT type,
423                 INT desiredx, INT desiredy, UINT loadflags )
424 {
425     if (HIWORD(name)) {
426         TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
427               hinst,name,type,desiredx,desiredy,loadflags);
428     } else {
429         TRACE_(resource)("(0x%04x,%p,%d,%d,%d,0x%08x)\n",
430               hinst,name,type,desiredx,desiredy,loadflags);
431     }
432     if (loadflags & LR_DEFAULTSIZE) {
433         if (type == IMAGE_ICON) {
434             if (!desiredx) desiredx = GetSystemMetrics(SM_CXICON);
435             if (!desiredy) desiredy = GetSystemMetrics(SM_CYICON);
436         } else if (type == IMAGE_CURSOR) {
437             if (!desiredx) desiredx = GetSystemMetrics(SM_CXCURSOR);
438             if (!desiredy) desiredy = GetSystemMetrics(SM_CYCURSOR);
439         }
440     }
441     if (loadflags & LR_LOADFROMFILE) loadflags &= ~LR_SHARED;
442     switch (type) {
443     case IMAGE_BITMAP:
444         return BITMAP_Load( hinst, name, loadflags );
445
446     case IMAGE_ICON:
447         {
448         HDC hdc = GetDC(0);
449         UINT palEnts = GetSystemPaletteEntries(hdc, 0, 0, NULL);
450         if (palEnts == 0)
451             palEnts = 256;
452         ReleaseDC(0, hdc);
453
454         return CURSORICON_Load(hinst, name, desiredx, desiredy,
455                                  palEnts, FALSE, loadflags);
456         }
457
458     case IMAGE_CURSOR:
459         return CURSORICON_Load(hinst, name, desiredx, desiredy,
460                                  1, TRUE, loadflags);
461     }
462     return 0;
463 }
464
465
466 /**********************************************************************
467  *              BITMAP_CopyBitmap
468  *
469  */
470 HBITMAP BITMAP_CopyBitmap(HBITMAP hbitmap)
471 {
472     BITMAPOBJ *bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
473     HBITMAP res = 0;
474     BITMAP bm;
475
476     if(!bmp) return 0;
477
478     bm = bmp->bitmap;
479     bm.bmBits = NULL;
480     res = CreateBitmapIndirect(&bm);
481
482     if(res) {
483         char *buf = HeapAlloc( GetProcessHeap(), 0, bm.bmWidthBytes *
484                                bm.bmHeight );
485         GetBitmapBits (hbitmap, bm.bmWidthBytes * bm.bmHeight, buf);
486         SetBitmapBits (res, bm.bmWidthBytes * bm.bmHeight, buf);
487         HeapFree( GetProcessHeap(), 0, buf );
488     }
489
490     GDI_HEAP_UNLOCK( hbitmap );
491     return res;
492 }
493
494 /******************************************************************************
495  * CopyImage16 [USER.390]  Creates new image and copies attributes to it
496  *
497  */
498 HICON16 WINAPI CopyImage16( HANDLE16 hnd, UINT16 type, INT16 desiredx,
499                              INT16 desiredy, UINT16 flags )
500 {
501     return (HICON16)CopyImage((HANDLE)hnd, (UINT)type, (INT)desiredx,
502                                 (INT)desiredy, (UINT)flags);
503 }
504
505 /******************************************************************************
506  * CopyImage32 [USER32.61]  Creates new image and copies attributes to it
507  *
508  * PARAMS
509  *    hnd      [I] Handle to image to copy
510  *    type     [I] Type of image to copy
511  *    desiredx [I] Desired width of new image
512  *    desiredy [I] Desired height of new image
513  *    flags    [I] Copy flags
514  *
515  * RETURNS
516  *    Success: Handle to newly created image
517  *    Failure: NULL
518  *
519  * FIXME: implementation still lacks nearly all features, see LR_*
520  * defines in windows.h
521  */
522 HICON WINAPI CopyImage( HANDLE hnd, UINT type, INT desiredx,
523                              INT desiredy, UINT flags )
524 {
525     switch (type)
526     {
527         case IMAGE_BITMAP:
528                 return BITMAP_CopyBitmap(hnd);
529         case IMAGE_ICON:
530                 return CopyIcon(hnd);
531         case IMAGE_CURSOR:
532                 return CopyCursor(hnd);
533     }
534     return 0;
535 }
536
537 /**********************************************************************
538  *       BITMAP_Load
539  */
540 HBITMAP BITMAP_Load( HINSTANCE instance,LPCWSTR name, UINT loadflags )
541 {
542     HBITMAP hbitmap = 0;
543     HDC hdc;
544     HRSRC hRsrc;
545     HGLOBAL handle;
546     char *ptr = NULL;
547     BITMAPINFO *info, *fix_info=NULL;
548     HGLOBAL hFix;
549     int size;
550
551     if (!(loadflags & LR_LOADFROMFILE)) {
552       if (!instance)  /* OEM bitmap */
553       {
554           HDC hdc;
555           DC *dc;
556
557           if (HIWORD((int)name)) return 0;
558           hdc = CreateDCA( "DISPLAY", NULL, NULL, NULL );
559           dc = DC_GetDCPtr( hdc );
560           if(dc->funcs->pLoadOEMResource)
561               hbitmap = dc->funcs->pLoadOEMResource( LOWORD((int)name), 
562                                                      OEM_BITMAP );
563           GDI_HEAP_UNLOCK( hdc );
564           DeleteDC( hdc );
565           return hbitmap;
566       }
567
568       if (!(hRsrc = FindResourceW( instance, name, RT_BITMAPW ))) return 0;
569       if (!(handle = LoadResource( instance, hRsrc ))) return 0;
570
571       if ((info = (BITMAPINFO *)LockResource( handle )) == NULL) return 0;
572     }
573     else
574     {
575         if (!(ptr = (char *)VIRTUAL_MapFileW( name ))) return 0;
576         info = (BITMAPINFO *)(ptr + sizeof(BITMAPFILEHEADER));
577     }
578     size = DIB_BitmapInfoSize(info, DIB_RGB_COLORS);
579     if ((hFix = GlobalAlloc(0, size))) fix_info=GlobalLock(hFix);
580     if (fix_info) {
581       BYTE pix;
582
583       memcpy(fix_info, info, size);
584       pix = *((LPBYTE)info+DIB_BitmapInfoSize(info, DIB_RGB_COLORS));
585       DIB_FixColorsToLoadflags(fix_info, loadflags, pix);
586       if ((hdc = GetDC(0)) != 0) {
587         char *bits = (char *)info + size;
588         if (loadflags & LR_CREATEDIBSECTION) {
589           DIBSECTION dib;
590           hbitmap = CreateDIBSection(hdc, fix_info, DIB_RGB_COLORS, NULL, 0, 0);
591           GetObjectA(hbitmap, sizeof(DIBSECTION), &dib);
592           SetDIBits(hdc, hbitmap, 0, dib.dsBm.bmHeight, bits, info, 
593                     DIB_RGB_COLORS);
594         }
595         else {
596           hbitmap = CreateDIBitmap( hdc, &fix_info->bmiHeader, CBM_INIT,
597                                       bits, fix_info, DIB_RGB_COLORS );
598         }
599         ReleaseDC( 0, hdc );
600       }
601       GlobalUnlock(hFix);
602       GlobalFree(hFix);
603     }
604     if (loadflags & LR_LOADFROMFILE) UnmapViewOfFile( ptr );
605     return hbitmap;
606 }
607
608
609 /******************************************************************************
610  * LoadBitmapW [USER32.358]  Loads bitmap from the executable file
611  *
612  * RETURNS
613  *    Success: Handle to specified bitmap
614  *    Failure: NULL
615  */
616 HBITMAP WINAPI LoadBitmapW(
617     HINSTANCE instance, /* [in] Handle to application instance */
618     LPCWSTR name)         /* [in] Address of bitmap resource name */
619 {
620     return LoadImageW( instance, name, IMAGE_BITMAP, 0, 0, 0 );
621 }
622
623 /**********************************************************************
624  *          LoadBitmapA   (USER32.357)
625  */
626 HBITMAP WINAPI LoadBitmapA( HINSTANCE instance, LPCSTR name )
627 {
628     return LoadImageA( instance, name, IMAGE_BITMAP, 0, 0, 0 );
629 }
630
631 /**********************************************************************
632  *          LoadBitmap16    (USER.175)
633  */
634 HBITMAP16 WINAPI LoadBitmap16( HINSTANCE16 instance, SEGPTR name )
635 {
636     LPCSTR nameStr = HIWORD(name)? PTR_SEG_TO_LIN(name) : (LPCSTR)name;
637     return LoadBitmapA( instance, nameStr );
638 }
639
640
641
642 /***********************************************************************
643  *           BITMAP_DeleteObject
644  */
645 BOOL BITMAP_DeleteObject( HBITMAP16 hbitmap, BITMAPOBJ * bmp )
646 {
647     if( bmp->DDBitmap ) {
648         if( bmp->DDBitmap->funcs->pDeleteObject )
649             bmp->DDBitmap->funcs->pDeleteObject( hbitmap );
650     }
651
652     if( bmp->bitmap.bmBits )
653         HeapFree( GetProcessHeap(), 0, bmp->bitmap.bmBits );
654
655     DIB_DeleteDIBSection( bmp );
656
657     return GDI_FreeObject( hbitmap );
658 }
659
660         
661 /***********************************************************************
662  *           BITMAP_GetObject16
663  */
664 INT16 BITMAP_GetObject16( BITMAPOBJ * bmp, INT16 count, LPVOID buffer )
665 {
666     if (bmp->dib)
667     {
668         if ( count <= sizeof(BITMAP16) )
669         {
670             BITMAP *bmp32 = &bmp->dib->dsBm;
671             BITMAP16 bmp16;
672             bmp16.bmType       = bmp32->bmType;
673             bmp16.bmWidth      = bmp32->bmWidth;
674             bmp16.bmHeight     = bmp32->bmHeight;
675             bmp16.bmWidthBytes = bmp32->bmWidthBytes;
676             bmp16.bmPlanes     = bmp32->bmPlanes;
677             bmp16.bmBitsPixel  = bmp32->bmBitsPixel;
678             bmp16.bmBits       = (SEGPTR)0;
679             memcpy( buffer, &bmp16, count );
680             return count;
681         }
682         else
683         {
684             FIXME_(bitmap)("not implemented for DIBs: count %d\n", count);
685             return 0;
686         }
687     }
688     else
689     {
690         BITMAP16 bmp16;
691         bmp16.bmType       = bmp->bitmap.bmType;
692         bmp16.bmWidth      = bmp->bitmap.bmWidth;
693         bmp16.bmHeight     = bmp->bitmap.bmHeight;
694         bmp16.bmWidthBytes = bmp->bitmap.bmWidthBytes;
695         bmp16.bmPlanes     = bmp->bitmap.bmPlanes;
696         bmp16.bmBitsPixel  = bmp->bitmap.bmBitsPixel;
697         bmp16.bmBits       = (SEGPTR)0;
698         if (count > sizeof(bmp16)) count = sizeof(bmp16);
699         memcpy( buffer, &bmp16, count );
700         return count;
701     }
702 }
703     
704
705 /***********************************************************************
706  *           BITMAP_GetObject32
707  */
708 INT BITMAP_GetObject( BITMAPOBJ * bmp, INT count, LPVOID buffer )
709 {
710     if (bmp->dib)
711     {
712         if (count < sizeof(DIBSECTION))
713         {
714             if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
715         }
716         else
717         {
718             if (count > sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
719         }
720
721         memcpy( buffer, bmp->dib, count );
722         return count;
723     }
724     else
725     {
726         if (count > sizeof(BITMAP)) count = sizeof(BITMAP);
727         memcpy( buffer, &bmp->bitmap, count );
728         return count;
729     }
730 }
731     
732
733 /***********************************************************************
734  *           CreateDiscardableBitmap16    (GDI.156)
735  */
736 HBITMAP16 WINAPI CreateDiscardableBitmap16( HDC16 hdc, INT16 width,
737                                             INT16 height )
738 {
739     return CreateCompatibleBitmap16( hdc, width, height );
740 }
741
742
743 /******************************************************************************
744  * CreateDiscardableBitmap32 [GDI32.38]  Creates a discardable bitmap
745  *
746  * RETURNS
747  *    Success: Handle to bitmap
748  *    Failure: NULL
749  */
750 HBITMAP WINAPI CreateDiscardableBitmap(
751     HDC hdc,    /* [in] Handle to device context */
752     INT width,  /* [in] Bitmap width */
753     INT height) /* [in] Bitmap height */
754 {
755     return CreateCompatibleBitmap( hdc, width, height );
756 }
757
758
759 /***********************************************************************
760  *           GetBitmapDimensionEx16    (GDI.468)
761  *
762  * NOTES
763  *    Can this call GetBitmapDimensionEx32?
764  */
765 BOOL16 WINAPI GetBitmapDimensionEx16( HBITMAP16 hbitmap, LPSIZE16 size )
766 {
767     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
768     if (!bmp) return FALSE;
769     CONV_SIZE32TO16( &bmp->size, size );
770     GDI_HEAP_UNLOCK( hbitmap );
771     return TRUE;
772 }
773
774
775 /******************************************************************************
776  * GetBitmapDimensionEx32 [GDI32.144]  Retrieves dimensions of a bitmap
777  *
778  * RETURNS
779  *    Success: TRUE
780  *    Failure: FALSE
781  */
782 BOOL WINAPI GetBitmapDimensionEx(
783     HBITMAP hbitmap, /* [in]  Handle to bitmap */
784     LPSIZE size)     /* [out] Address of struct receiving dimensions */
785 {
786     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
787     if (!bmp) return FALSE;
788     *size = bmp->size;
789     GDI_HEAP_UNLOCK( hbitmap );
790     return TRUE;
791 }
792
793
794 /***********************************************************************
795  *           GetBitmapDimension    (GDI.162)
796  */
797 DWORD WINAPI GetBitmapDimension16( HBITMAP16 hbitmap )
798 {
799     SIZE16 size;
800     if (!GetBitmapDimensionEx16( hbitmap, &size )) return 0;
801     return MAKELONG( size.cx, size.cy );
802 }
803
804
805 /***********************************************************************
806  *           SetBitmapDimensionEx16    (GDI.478)
807  */
808 BOOL16 WINAPI SetBitmapDimensionEx16( HBITMAP16 hbitmap, INT16 x, INT16 y,
809                                       LPSIZE16 prevSize )
810 {
811     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
812     if (!bmp) return FALSE;
813     if (prevSize) CONV_SIZE32TO16( &bmp->size, prevSize );
814     bmp->size.cx = x;
815     bmp->size.cy = y;
816     GDI_HEAP_UNLOCK( hbitmap );
817     return TRUE;
818 }
819
820
821 /******************************************************************************
822  * SetBitmapDimensionEx32 [GDI32.304]  Assignes dimensions to a bitmap
823  *
824  * RETURNS
825  *    Success: TRUE
826  *    Failure: FALSE
827  */
828 BOOL WINAPI SetBitmapDimensionEx(
829     HBITMAP hbitmap, /* [in]  Handle to bitmap */
830     INT x,           /* [in]  Bitmap width */
831     INT y,           /* [in]  Bitmap height */
832     LPSIZE prevSize) /* [out] Address of structure for orig dims */
833 {
834     BITMAPOBJ * bmp = (BITMAPOBJ *) GDI_GetObjPtr( hbitmap, BITMAP_MAGIC );
835     if (!bmp) return FALSE;
836     if (prevSize) *prevSize = bmp->size;
837     bmp->size.cx = x;
838     bmp->size.cy = y;
839     GDI_HEAP_UNLOCK( hbitmap );
840     return TRUE;
841 }
842
843
844 /***********************************************************************
845  *           SetBitmapDimension    (GDI.163)
846  */
847 DWORD WINAPI SetBitmapDimension16( HBITMAP16 hbitmap, INT16 x, INT16 y )
848 {
849     SIZE16 size;
850     if (!SetBitmapDimensionEx16( hbitmap, x, y, &size )) return 0;
851     return MAKELONG( size.cx, size.cy );
852 }
853