xref: /reactos/win32ss/gdi/ntgdi/bitmaps.c (revision 090ccb3d)
1c2c66affSColin Finck /*
2c2c66affSColin Finck  * COPYRIGHT:        GNU GPL, See COPYING in the top level directory
3c2c66affSColin Finck  * PROJECT:          ReactOS kernel
4c2c66affSColin Finck  * PURPOSE:          Bitmap functions
5c2c66affSColin Finck  * FILE:             win32ss/gdi/ntgdi/bitmaps.c
60aa21c33SKatayama Hirofumi MZ  * PROGRAMERS:       Timo Kreuzer <timo.kreuzer@reactos.org>
70aa21c33SKatayama Hirofumi MZ  *                   Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
8c2c66affSColin Finck  */
9c2c66affSColin Finck 
10c2c66affSColin Finck #include <win32k.h>
11c2c66affSColin Finck 
12c2c66affSColin Finck #define NDEBUG
13c2c66affSColin Finck #include <debug.h>
14c2c66affSColin Finck 
15c2c66affSColin Finck BOOL
16c2c66affSColin Finck NTAPI
GreSetBitmapOwner(_In_ HBITMAP hbmp,_In_ ULONG ulOwner)17c2c66affSColin Finck GreSetBitmapOwner(
18c2c66affSColin Finck     _In_ HBITMAP hbmp,
19c2c66affSColin Finck     _In_ ULONG ulOwner)
20c2c66affSColin Finck {
21c2c66affSColin Finck     /* Check if we have the correct object type */
22c2c66affSColin Finck     if (GDI_HANDLE_GET_TYPE(hbmp) != GDILoObjType_LO_BITMAP_TYPE)
23c2c66affSColin Finck     {
24c2c66affSColin Finck         DPRINT1("Incorrect type for hbmp: %p\n", hbmp);
25c2c66affSColin Finck         return FALSE;
26c2c66affSColin Finck     }
27c2c66affSColin Finck 
28c2c66affSColin Finck     /// FIXME: this is a hack and doesn't handle a race condition properly.
29c2c66affSColin Finck     /// It needs to be done in GDIOBJ_vSetObjectOwner atomically.
30c2c66affSColin Finck 
31c2c66affSColin Finck     /* Check if we set public or none */
32c2c66affSColin Finck     if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) ||
33c2c66affSColin Finck         (ulOwner == GDI_OBJ_HMGR_NONE))
34c2c66affSColin Finck     {
35c2c66affSColin Finck         /* Only allow this for owned objects */
36c2c66affSColin Finck         if (GreGetObjectOwner(hbmp) != GDI_OBJ_HMGR_POWNED)
37c2c66affSColin Finck         {
38c2c66affSColin Finck             DPRINT1("Cannot change owner for non-powned hbmp\n");
39c2c66affSColin Finck             return FALSE;
40c2c66affSColin Finck         }
41c2c66affSColin Finck     }
42c2c66affSColin Finck 
43c2c66affSColin Finck     return GreSetObjectOwner(hbmp, ulOwner);
44c2c66affSColin Finck }
45c2c66affSColin Finck 
460aa21c33SKatayama Hirofumi MZ LONG
47c2c66affSColin Finck NTAPI
UnsafeSetBitmapBits(_Inout_ PSURFACE psurf,_In_ ULONG cjBits,_In_ const VOID * pvBits)48c2c66affSColin Finck UnsafeSetBitmapBits(
49c2c66affSColin Finck     _Inout_ PSURFACE psurf,
50c2c66affSColin Finck     _In_ ULONG cjBits,
51c2c66affSColin Finck     _In_ const VOID *pvBits)
52c2c66affSColin Finck {
53c2c66affSColin Finck     PUCHAR pjDst;
54c2c66affSColin Finck     const UCHAR *pjSrc;
551cd2f543SKatayama Hirofumi MZ     LONG lDeltaDst, lDeltaSrc, lDeltaDstAbs;
560aa21c33SKatayama Hirofumi MZ     ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel;
570aa21c33SKatayama Hirofumi MZ 
58c2c66affSColin Finck     NT_ASSERT(psurf->flags & API_BITMAP);
59c2c66affSColin Finck     NT_ASSERT(psurf->SurfObj.iBitmapFormat <= BMF_32BPP);
60c2c66affSColin Finck 
61c2c66affSColin Finck     nWidth = psurf->SurfObj.sizlBitmap.cx;
6231d616ffSKatayama Hirofumi MZ     nHeight = psurf->SurfObj.sizlBitmap.cy;
63c2c66affSColin Finck     cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
64c2c66affSColin Finck 
65c2c66affSColin Finck     pjDst = psurf->SurfObj.pvScan0;
66c2c66affSColin Finck     pjSrc = pvBits;
67c2c66affSColin Finck     lDeltaDst = psurf->SurfObj.lDelta;
681cd2f543SKatayama Hirofumi MZ     lDeltaDstAbs = labs(lDeltaDst);
69c2c66affSColin Finck     lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
701cd2f543SKatayama Hirofumi MZ     NT_ASSERT(lDeltaSrc <= lDeltaDstAbs);
71c2c66affSColin Finck 
721cd2f543SKatayama Hirofumi MZ     cbDst = lDeltaDstAbs * nHeight;
730aa21c33SKatayama Hirofumi MZ     cbSrc = lDeltaSrc * nHeight;
740aa21c33SKatayama Hirofumi MZ     cjBits = min(cjBits, cbSrc);
75c2c66affSColin Finck 
760aa21c33SKatayama Hirofumi MZ     iSrc = iDst = 0;
770aa21c33SKatayama Hirofumi MZ     for (Y = 0; Y < nHeight; Y++)
78c2c66affSColin Finck     {
791cd2f543SKatayama Hirofumi MZ         if (iSrc + lDeltaSrc > cjBits || iDst + lDeltaDstAbs > cbDst)
800aa21c33SKatayama Hirofumi MZ         {
810aa21c33SKatayama Hirofumi MZ             LONG lDelta = min(cjBits - iSrc, cbDst - iDst);
820aa21c33SKatayama Hirofumi MZ             NT_ASSERT(lDelta >= 0);
830aa21c33SKatayama Hirofumi MZ             RtlCopyMemory(pjDst, pjSrc, lDelta);
840aa21c33SKatayama Hirofumi MZ             iSrc += lDelta;
850aa21c33SKatayama Hirofumi MZ             break;
86c2c66affSColin Finck         }
87c2c66affSColin Finck 
880aa21c33SKatayama Hirofumi MZ         /* Copy one line */
890aa21c33SKatayama Hirofumi MZ         RtlCopyMemory(pjDst, pjSrc, lDeltaSrc);
900aa21c33SKatayama Hirofumi MZ         pjSrc += lDeltaSrc;
910aa21c33SKatayama Hirofumi MZ         pjDst += lDeltaDst;
920aa21c33SKatayama Hirofumi MZ         iSrc += lDeltaSrc;
931cd2f543SKatayama Hirofumi MZ         iDst += lDeltaDstAbs;
940aa21c33SKatayama Hirofumi MZ     }
950aa21c33SKatayama Hirofumi MZ 
960aa21c33SKatayama Hirofumi MZ     return iSrc;
97c2c66affSColin Finck }
98c2c66affSColin Finck 
99c2c66affSColin Finck HBITMAP
100c2c66affSColin Finck NTAPI
GreCreateBitmapEx(_In_ ULONG nWidth,_In_ ULONG nHeight,_In_ ULONG cjWidthBytes,_In_ ULONG iFormat,_In_ USHORT fjBitmap,_In_ ULONG cjSizeImage,_In_opt_ PVOID pvBits,_In_ FLONG flags)101c2c66affSColin Finck GreCreateBitmapEx(
102c2c66affSColin Finck     _In_ ULONG nWidth,
103c2c66affSColin Finck     _In_ ULONG nHeight,
104c2c66affSColin Finck     _In_ ULONG cjWidthBytes,
105c2c66affSColin Finck     _In_ ULONG iFormat,
106c2c66affSColin Finck     _In_ USHORT fjBitmap,
107c2c66affSColin Finck     _In_ ULONG cjSizeImage,
108c2c66affSColin Finck     _In_opt_ PVOID pvBits,
109c2c66affSColin Finck     _In_ FLONG flags)
110c2c66affSColin Finck {
111c2c66affSColin Finck     PSURFACE psurf;
112c2c66affSColin Finck     HBITMAP hbmp;
113c2c66affSColin Finck     PVOID pvCompressedBits = NULL;
114c2c66affSColin Finck 
115c2c66affSColin Finck     /* Verify format */
116c2c66affSColin Finck     if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL;
117c2c66affSColin Finck 
118c2c66affSColin Finck     /* The infamous RLE hack */
119c2c66affSColin Finck     if ((iFormat == BMF_4RLE) || (iFormat == BMF_8RLE))
120c2c66affSColin Finck     {
121c2c66affSColin Finck         pvCompressedBits = pvBits;
122c2c66affSColin Finck         pvBits = NULL;
123c2c66affSColin Finck         iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP;
124c2c66affSColin Finck     }
125c2c66affSColin Finck 
126c2c66affSColin Finck     /* Allocate a surface */
127c2c66affSColin Finck     psurf = SURFACE_AllocSurface(STYPE_BITMAP,
128c2c66affSColin Finck                                  nWidth,
129c2c66affSColin Finck                                  nHeight,
130c2c66affSColin Finck                                  iFormat,
131c2c66affSColin Finck                                  fjBitmap,
132c2c66affSColin Finck                                  cjWidthBytes,
133c2c66affSColin Finck                                  pvCompressedBits ? 0 : cjSizeImage,
134c2c66affSColin Finck                                  pvBits);
135c2c66affSColin Finck     if (!psurf)
136c2c66affSColin Finck     {
137c2c66affSColin Finck         DPRINT1("SURFACE_AllocSurface failed.\n");
138c2c66affSColin Finck         return NULL;
139c2c66affSColin Finck     }
140c2c66affSColin Finck 
141c2c66affSColin Finck     /* The infamous RLE hack */
142c2c66affSColin Finck     if (pvCompressedBits)
143c2c66affSColin Finck     {
144c2c66affSColin Finck         SIZEL sizl;
145c2c66affSColin Finck         LONG lDelta;
146c2c66affSColin Finck 
147c2c66affSColin Finck         sizl.cx = nWidth;
148c2c66affSColin Finck         sizl.cy = nHeight;
149c2c66affSColin Finck         lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]);
150c2c66affSColin Finck 
151c2c66affSColin Finck         pvBits = psurf->SurfObj.pvBits;
152c2c66affSColin Finck         DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat, cjSizeImage);
153c2c66affSColin Finck     }
154c2c66affSColin Finck 
155c2c66affSColin Finck     /* Get the handle for the bitmap */
156c2c66affSColin Finck     hbmp = (HBITMAP)psurf->SurfObj.hsurf;
157c2c66affSColin Finck 
158c2c66affSColin Finck     /* Mark as API bitmap */
159c2c66affSColin Finck     psurf->flags |= (flags | API_BITMAP);
160c2c66affSColin Finck 
161c2c66affSColin Finck     /* Unlock the surface and return */
162c2c66affSColin Finck     SURFACE_UnlockSurface(psurf);
163c2c66affSColin Finck     return hbmp;
164c2c66affSColin Finck }
165c2c66affSColin Finck 
166c2c66affSColin Finck /* Creates a DDB surface,
167c2c66affSColin Finck  * as in CreateCompatibleBitmap or CreateBitmap.
168c2c66affSColin Finck  * Note that each scanline must be 32bit aligned!
169c2c66affSColin Finck  */
170c2c66affSColin Finck HBITMAP
171c2c66affSColin Finck NTAPI
GreCreateBitmap(_In_ ULONG nWidth,_In_ ULONG nHeight,_In_ ULONG cPlanes,_In_ ULONG cBitsPixel,_In_opt_ PVOID pvBits)172c2c66affSColin Finck GreCreateBitmap(
173c2c66affSColin Finck     _In_ ULONG nWidth,
174c2c66affSColin Finck     _In_ ULONG nHeight,
175c2c66affSColin Finck     _In_ ULONG cPlanes,
176c2c66affSColin Finck     _In_ ULONG cBitsPixel,
177c2c66affSColin Finck     _In_opt_ PVOID pvBits)
178c2c66affSColin Finck {
179c2c66affSColin Finck     /* Call the extended function */
180c2c66affSColin Finck     return GreCreateBitmapEx(nWidth,
181c2c66affSColin Finck                              nHeight,
182c2c66affSColin Finck                              0, /* Auto width */
183c2c66affSColin Finck                              BitmapFormat(cBitsPixel * cPlanes, BI_RGB),
184c2c66affSColin Finck                              0, /* No bitmap flags */
185c2c66affSColin Finck                              0, /* Auto size */
186c2c66affSColin Finck                              pvBits,
187c2c66affSColin Finck                              DDB_SURFACE /* DDB */);
188c2c66affSColin Finck }
189c2c66affSColin Finck 
190c2c66affSColin Finck HBITMAP
191c2c66affSColin Finck APIENTRY
NtGdiCreateBitmap(IN INT nWidth,IN INT nHeight,IN UINT cPlanes,IN UINT cBitsPixel,IN OPTIONAL LPBYTE pUnsafeBits)192c2c66affSColin Finck NtGdiCreateBitmap(
193c2c66affSColin Finck     IN INT nWidth,
194c2c66affSColin Finck     IN INT nHeight,
195c2c66affSColin Finck     IN UINT cPlanes,
196c2c66affSColin Finck     IN UINT cBitsPixel,
197c2c66affSColin Finck     IN OPTIONAL LPBYTE pUnsafeBits)
198c2c66affSColin Finck {
199c2c66affSColin Finck     HBITMAP hbmp;
200c2c66affSColin Finck     ULONG cRealBpp, cjWidthBytes, iFormat;
201c2c66affSColin Finck     ULONGLONG cjSize;
202c2c66affSColin Finck     PSURFACE psurf;
203c2c66affSColin Finck 
204c2c66affSColin Finck     /* Calculate bitmap format and real bits per pixel. */
205c2c66affSColin Finck     iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB);
206c2c66affSColin Finck     cRealBpp = gajBitsPerFormat[iFormat];
207c2c66affSColin Finck 
208c2c66affSColin Finck     /* Calculate width and image size in bytes */
209c2c66affSColin Finck     cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp);
210c2c66affSColin Finck     cjSize = (ULONGLONG)cjWidthBytes * nHeight;
211c2c66affSColin Finck 
212c2c66affSColin Finck     /* Check parameters (possible overflow of cjSize!) */
213c2c66affSColin Finck     if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) ||
214c2c66affSColin Finck         (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL))
215c2c66affSColin Finck     {
216c2c66affSColin Finck         DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n",
217c2c66affSColin Finck                 nWidth, nHeight, cBitsPixel, cPlanes);
218c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
219c2c66affSColin Finck         return NULL;
220c2c66affSColin Finck     }
221c2c66affSColin Finck 
222c2c66affSColin Finck     /* Allocate the surface (but don't set the bits) */
223c2c66affSColin Finck     psurf = SURFACE_AllocSurface(STYPE_BITMAP,
224c2c66affSColin Finck                                  nWidth,
225c2c66affSColin Finck                                  nHeight,
226c2c66affSColin Finck                                  iFormat,
227c2c66affSColin Finck                                  0,
228c2c66affSColin Finck                                  0,
229c2c66affSColin Finck                                  0,
230c2c66affSColin Finck                                  NULL);
231c2c66affSColin Finck     if (!psurf)
232c2c66affSColin Finck     {
233c2c66affSColin Finck         DPRINT1("SURFACE_AllocSurface failed.\n");
234c2c66affSColin Finck         return NULL;
235c2c66affSColin Finck     }
236c2c66affSColin Finck 
237c2c66affSColin Finck     /* Mark as API and DDB bitmap */
238c2c66affSColin Finck     psurf->flags |= (API_BITMAP | DDB_SURFACE);
239c2c66affSColin Finck 
240c2c66affSColin Finck     /* Check if we have bits to set */
241c2c66affSColin Finck     if (pUnsafeBits)
242c2c66affSColin Finck     {
243c2c66affSColin Finck         /* Protect with SEH and copy the bits */
244c2c66affSColin Finck         _SEH2_TRY
245c2c66affSColin Finck         {
246c2c66affSColin Finck             ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1);
247c2c66affSColin Finck             UnsafeSetBitmapBits(psurf, cjSize, pUnsafeBits);
248c2c66affSColin Finck         }
249c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
250c2c66affSColin Finck         {
251c2c66affSColin Finck             GDIOBJ_vDeleteObject(&psurf->BaseObject);
252c2c66affSColin Finck             _SEH2_YIELD(return NULL;)
253c2c66affSColin Finck         }
254c2c66affSColin Finck         _SEH2_END
255c2c66affSColin Finck     }
256c2c66affSColin Finck     else
257c2c66affSColin Finck     {
258c2c66affSColin Finck         /* Zero the bits */
259c2c66affSColin Finck         RtlZeroMemory(psurf->SurfObj.pvBits, psurf->SurfObj.cjBits);
260c2c66affSColin Finck     }
261c2c66affSColin Finck 
262c2c66affSColin Finck     /* Get the handle for the bitmap */
263c2c66affSColin Finck     hbmp = (HBITMAP)psurf->SurfObj.hsurf;
264c2c66affSColin Finck 
265c2c66affSColin Finck     /* Unlock the surface */
266c2c66affSColin Finck     SURFACE_UnlockSurface(psurf);
267c2c66affSColin Finck 
268c2c66affSColin Finck     return hbmp;
269c2c66affSColin Finck }
270c2c66affSColin Finck 
271c2c66affSColin Finck 
272c2c66affSColin Finck HBITMAP FASTCALL
IntCreateCompatibleBitmap(PDC Dc,INT Width,INT Height,UINT Planes,UINT Bpp)273c2c66affSColin Finck IntCreateCompatibleBitmap(
274c2c66affSColin Finck     PDC Dc,
275c2c66affSColin Finck     INT Width,
276c2c66affSColin Finck     INT Height,
277c2c66affSColin Finck     UINT Planes,
278c2c66affSColin Finck     UINT Bpp)
279c2c66affSColin Finck {
280c2c66affSColin Finck     HBITMAP Bmp = NULL;
281c2c66affSColin Finck     PPALETTE ppal;
282c2c66affSColin Finck 
283c2c66affSColin Finck     /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
284c2c66affSColin Finck     if (0 == Width || 0 == Height)
285c2c66affSColin Finck     {
286c2c66affSColin Finck         return NtGdiGetStockObject(DEFAULT_BITMAP);
287c2c66affSColin Finck     }
288c2c66affSColin Finck 
2895e93daa9SHermès Bélusca-Maïto     if (Dc->dctype != DCTYPE_MEMORY)
290c2c66affSColin Finck     {
291c2c66affSColin Finck         PSURFACE psurf;
292c2c66affSColin Finck 
293c2c66affSColin Finck         Bmp = GreCreateBitmap(abs(Width),
294c2c66affSColin Finck                               abs(Height),
295c2c66affSColin Finck                               Planes ? Planes : 1,
296c2c66affSColin Finck                               Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel,
297c2c66affSColin Finck                               NULL);
298c2c66affSColin Finck         if (Bmp == NULL)
299c2c66affSColin Finck         {
300c2c66affSColin Finck             DPRINT1("Failed to allocate a bitmap!\n");
301c2c66affSColin Finck             return NULL;
302c2c66affSColin Finck         }
303c2c66affSColin Finck 
304c2c66affSColin Finck         psurf = SURFACE_ShareLockSurface(Bmp);
305c2c66affSColin Finck         ASSERT(psurf);
306c2c66affSColin Finck 
307c2c66affSColin Finck         /* Dereference old palette and set new palette */
308c2c66affSColin Finck         ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault);
309c2c66affSColin Finck         ASSERT(ppal);
310c2c66affSColin Finck         SURFACE_vSetPalette(psurf, ppal);
311c2c66affSColin Finck         PALETTE_ShareUnlockPalette(ppal);
312c2c66affSColin Finck 
313c2c66affSColin Finck         /* Set flags */
314c2c66affSColin Finck         psurf->flags = API_BITMAP;
315c2c66affSColin Finck         psurf->hdc = NULL; // FIXME:
316c2c66affSColin Finck         psurf->SurfObj.hdev = (HDEV)Dc->ppdev;
317c2c66affSColin Finck         SURFACE_ShareUnlockSurface(psurf);
318c2c66affSColin Finck     }
319c2c66affSColin Finck     else
320c2c66affSColin Finck     {
321c2c66affSColin Finck         DIBSECTION dibs;
322c2c66affSColin Finck         INT Count;
323c2c66affSColin Finck         PSURFACE psurf = Dc->dclevel.pSurface;
324c2c66affSColin Finck         if(!psurf) psurf = psurfDefaultBitmap;
325c2c66affSColin Finck         Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs);
326c2c66affSColin Finck 
327c2c66affSColin Finck         if (Count == sizeof(BITMAP))
328c2c66affSColin Finck         {
329c2c66affSColin Finck             PSURFACE psurfBmp;
330c2c66affSColin Finck 
331c2c66affSColin Finck             Bmp = GreCreateBitmap(abs(Width),
332c2c66affSColin Finck                           abs(Height),
333c2c66affSColin Finck                           Planes ? Planes : 1,
334c2c66affSColin Finck                           Bpp ? Bpp : dibs.dsBm.bmBitsPixel,
335c2c66affSColin Finck                           NULL);
336*090ccb3dSTimo Kreuzer             if (Bmp == NULL)
337*090ccb3dSTimo Kreuzer             {
338*090ccb3dSTimo Kreuzer                 DPRINT1("Failed to allocate a bitmap!\n");
339*090ccb3dSTimo Kreuzer                 return NULL;
340*090ccb3dSTimo Kreuzer             }
341c2c66affSColin Finck             psurfBmp = SURFACE_ShareLockSurface(Bmp);
342c2c66affSColin Finck             ASSERT(psurfBmp);
343c2c66affSColin Finck 
344c2c66affSColin Finck             /* Dereference old palette and set new palette */
345c2c66affSColin Finck             SURFACE_vSetPalette(psurfBmp, psurf->ppal);
346c2c66affSColin Finck 
347c2c66affSColin Finck             /* Set flags */
348c2c66affSColin Finck             psurfBmp->flags = API_BITMAP;
349c2c66affSColin Finck             psurfBmp->hdc = NULL; // FIXME:
350*090ccb3dSTimo Kreuzer             psurfBmp->SurfObj.hdev = (HDEV)Dc->ppdev;
351c2c66affSColin Finck             SURFACE_ShareUnlockSurface(psurfBmp);
352c2c66affSColin Finck         }
353c2c66affSColin Finck         else if (Count == sizeof(DIBSECTION))
354c2c66affSColin Finck         {
355c2c66affSColin Finck             /* A DIB section is selected in the DC */
356c2c66affSColin Finck             BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0};
357c2c66affSColin Finck             PVOID Bits;
358c2c66affSColin Finck             BITMAPINFO* bi = (BITMAPINFO*)buf;
359c2c66affSColin Finck 
360c2c66affSColin Finck             bi->bmiHeader.biSize          = sizeof(bi->bmiHeader);
361c2c66affSColin Finck             bi->bmiHeader.biWidth         = Width;
362c2c66affSColin Finck             bi->bmiHeader.biHeight        = Height;
363c2c66affSColin Finck             bi->bmiHeader.biPlanes        = Planes ? Planes : dibs.dsBmih.biPlanes;
364c2c66affSColin Finck             bi->bmiHeader.biBitCount      = Bpp ? Bpp : dibs.dsBmih.biBitCount;
365c2c66affSColin Finck             bi->bmiHeader.biCompression   = dibs.dsBmih.biCompression;
366c2c66affSColin Finck             bi->bmiHeader.biSizeImage     = 0;
367c2c66affSColin Finck             bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter;
368c2c66affSColin Finck             bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter;
369c2c66affSColin Finck             bi->bmiHeader.biClrUsed       = dibs.dsBmih.biClrUsed;
370c2c66affSColin Finck             bi->bmiHeader.biClrImportant  = dibs.dsBmih.biClrImportant;
371c2c66affSColin Finck 
372c2c66affSColin Finck             if (bi->bmiHeader.biCompression == BI_BITFIELDS)
373c2c66affSColin Finck             {
374c2c66affSColin Finck                 /* Copy the color masks */
375c2c66affSColin Finck                 RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD));
376c2c66affSColin Finck             }
377c2c66affSColin Finck             else if (bi->bmiHeader.biBitCount <= 8)
378c2c66affSColin Finck             {
379c2c66affSColin Finck                 /* Copy the color table */
380c2c66affSColin Finck                 UINT Index;
381c2c66affSColin Finck                 PPALETTE PalGDI;
382c2c66affSColin Finck 
383c2c66affSColin Finck                 if (!psurf->ppal)
384c2c66affSColin Finck                 {
385c2c66affSColin Finck                     EngSetLastError(ERROR_INVALID_HANDLE);
386c2c66affSColin Finck                     return 0;
387c2c66affSColin Finck                 }
388c2c66affSColin Finck 
389c2c66affSColin Finck                 PalGDI = psurf->ppal;
390c2c66affSColin Finck 
391c2c66affSColin Finck                 for (Index = 0;
392c2c66affSColin Finck                         Index < 256 && Index < PalGDI->NumColors;
393c2c66affSColin Finck                         Index++)
394c2c66affSColin Finck                 {
395c2c66affSColin Finck                     bi->bmiColors[Index].rgbRed   = PalGDI->IndexedColors[Index].peRed;
396c2c66affSColin Finck                     bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen;
397c2c66affSColin Finck                     bi->bmiColors[Index].rgbBlue  = PalGDI->IndexedColors[Index].peBlue;
398c2c66affSColin Finck                     bi->bmiColors[Index].rgbReserved = 0;
399c2c66affSColin Finck                 }
400c2c66affSColin Finck             }
401c2c66affSColin Finck 
402c2c66affSColin Finck             Bmp = DIB_CreateDIBSection(Dc,
403c2c66affSColin Finck                                        bi,
404c2c66affSColin Finck                                        DIB_RGB_COLORS,
405c2c66affSColin Finck                                        &Bits,
406c2c66affSColin Finck                                        NULL,
407c2c66affSColin Finck                                        0,
408c2c66affSColin Finck                                        0);
409c2c66affSColin Finck             return Bmp;
410c2c66affSColin Finck         }
411c2c66affSColin Finck     }
412c2c66affSColin Finck     return Bmp;
413c2c66affSColin Finck }
414c2c66affSColin Finck 
415c2c66affSColin Finck HBITMAP APIENTRY
NtGdiCreateCompatibleBitmap(HDC hDC,INT Width,INT Height)416c2c66affSColin Finck NtGdiCreateCompatibleBitmap(
417c2c66affSColin Finck     HDC hDC,
418c2c66affSColin Finck     INT Width,
419c2c66affSColin Finck     INT Height)
420c2c66affSColin Finck {
421c2c66affSColin Finck     HBITMAP Bmp;
422c2c66affSColin Finck     PDC Dc;
423c2c66affSColin Finck 
424c2c66affSColin Finck     /* Check parameters */
425c2c66affSColin Finck     if ((Width <= 0) || (Height <= 0) || ((Width * Height) > 0x3FFFFFFF))
426c2c66affSColin Finck     {
427c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_PARAMETER);
428c2c66affSColin Finck         return NULL;
429c2c66affSColin Finck     }
430c2c66affSColin Finck 
431c2c66affSColin Finck     if (!hDC)
432c2c66affSColin Finck         return GreCreateBitmap(Width, Height, 1, 1, 0);
433c2c66affSColin Finck 
434c2c66affSColin Finck     Dc = DC_LockDc(hDC);
435c2c66affSColin Finck 
436c2c66affSColin Finck     DPRINT("NtGdiCreateCompatibleBitmap(%p,%d,%d, bpp:%u) = \n",
437c2c66affSColin Finck            hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel);
438c2c66affSColin Finck 
439c2c66affSColin Finck     if (NULL == Dc)
440c2c66affSColin Finck     {
441c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
442c2c66affSColin Finck         return NULL;
443c2c66affSColin Finck     }
444c2c66affSColin Finck 
445c2c66affSColin Finck     Bmp = IntCreateCompatibleBitmap(Dc, Width, Height, 0, 0);
446c2c66affSColin Finck 
447c2c66affSColin Finck     DC_UnlockDc(Dc);
448c2c66affSColin Finck     return Bmp;
449c2c66affSColin Finck }
450c2c66affSColin Finck 
451c2c66affSColin Finck BOOL
452c2c66affSColin Finck NTAPI
GreGetBitmapDimension(_In_ HBITMAP hBitmap,_Out_ LPSIZE psizDim)453c2c66affSColin Finck GreGetBitmapDimension(
454c2c66affSColin Finck     _In_ HBITMAP hBitmap,
455c2c66affSColin Finck     _Out_ LPSIZE psizDim)
456c2c66affSColin Finck {
457c2c66affSColin Finck     PSURFACE psurfBmp;
458c2c66affSColin Finck 
459c2c66affSColin Finck     if (hBitmap == NULL)
460c2c66affSColin Finck         return FALSE;
461c2c66affSColin Finck 
462c2c66affSColin Finck     /* Lock the bitmap */
463c2c66affSColin Finck     psurfBmp = SURFACE_ShareLockSurface(hBitmap);
464c2c66affSColin Finck     if (psurfBmp == NULL)
465c2c66affSColin Finck     {
466c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
467c2c66affSColin Finck         return FALSE;
468c2c66affSColin Finck     }
469c2c66affSColin Finck 
470c2c66affSColin Finck     *psizDim = psurfBmp->sizlDim;
471c2c66affSColin Finck 
472c2c66affSColin Finck     /* Unlock the bitmap */
473c2c66affSColin Finck     SURFACE_ShareUnlockSurface(psurfBmp);
474c2c66affSColin Finck 
475c2c66affSColin Finck     return TRUE;
476c2c66affSColin Finck }
477c2c66affSColin Finck 
478c2c66affSColin Finck BOOL
479c2c66affSColin Finck APIENTRY
NtGdiGetBitmapDimension(HBITMAP hBitmap,LPSIZE psizDim)480c2c66affSColin Finck NtGdiGetBitmapDimension(
481c2c66affSColin Finck     HBITMAP hBitmap,
482c2c66affSColin Finck     LPSIZE psizDim)
483c2c66affSColin Finck {
484c2c66affSColin Finck     SIZE dim;
485c2c66affSColin Finck 
486c2c66affSColin Finck     if (!GreGetBitmapDimension(hBitmap, &dim))
487c2c66affSColin Finck         return FALSE;
488c2c66affSColin Finck 
489c2c66affSColin Finck     /* Use SEH to copy the data to the caller */
490c2c66affSColin Finck     _SEH2_TRY
491c2c66affSColin Finck     {
492c2c66affSColin Finck         ProbeForWrite(psizDim, sizeof(*psizDim), 1);
493c2c66affSColin Finck         *psizDim = dim;
494c2c66affSColin Finck     }
495c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
496c2c66affSColin Finck     {
497c2c66affSColin Finck         _SEH2_YIELD(return FALSE);
498c2c66affSColin Finck     }
499c2c66affSColin Finck     _SEH2_END
500c2c66affSColin Finck 
501c2c66affSColin Finck     return TRUE;
502c2c66affSColin Finck }
503c2c66affSColin Finck 
504c2c66affSColin Finck 
50529795a2dSKatayama Hirofumi MZ LONG
506c2c66affSColin Finck FASTCALL
UnsafeGetBitmapBits(PSURFACE psurf,DWORD Bytes,OUT PBYTE pvBits)507c2c66affSColin Finck UnsafeGetBitmapBits(
508c2c66affSColin Finck     PSURFACE psurf,
509c2c66affSColin Finck     DWORD Bytes,
510c2c66affSColin Finck     OUT PBYTE pvBits)
511c2c66affSColin Finck {
512c2c66affSColin Finck     PUCHAR pjDst, pjSrc;
5131cd2f543SKatayama Hirofumi MZ     LONG lDeltaDst, lDeltaSrc, lDeltaSrcAbs;
51429795a2dSKatayama Hirofumi MZ     ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel;
515c2c66affSColin Finck 
516c2c66affSColin Finck     nWidth = psurf->SurfObj.sizlBitmap.cx;
51731d616ffSKatayama Hirofumi MZ     nHeight = psurf->SurfObj.sizlBitmap.cy;
518c2c66affSColin Finck     cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
519c2c66affSColin Finck 
520c2c66affSColin Finck     /* Get pointers */
521c2c66affSColin Finck     pjSrc = psurf->SurfObj.pvScan0;
522c2c66affSColin Finck     pjDst = pvBits;
523c2c66affSColin Finck     lDeltaSrc = psurf->SurfObj.lDelta;
5241cd2f543SKatayama Hirofumi MZ     lDeltaSrcAbs = labs(lDeltaSrc);
525c2c66affSColin Finck     lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
5261cd2f543SKatayama Hirofumi MZ     NT_ASSERT(lDeltaSrcAbs >= lDeltaDst);
527c2c66affSColin Finck 
5281cd2f543SKatayama Hirofumi MZ     cbSrc = nHeight * lDeltaSrcAbs;
52929795a2dSKatayama Hirofumi MZ     cbDst = nHeight * lDeltaDst;
53029795a2dSKatayama Hirofumi MZ     Bytes = min(Bytes, cbDst);
53129795a2dSKatayama Hirofumi MZ 
53229795a2dSKatayama Hirofumi MZ     iSrc = iDst = 0;
53329795a2dSKatayama Hirofumi MZ     for (Y = 0; Y < nHeight; Y++)
534c2c66affSColin Finck     {
5351cd2f543SKatayama Hirofumi MZ         if (iSrc + lDeltaSrcAbs > cbSrc || iDst + lDeltaDst > Bytes)
53629795a2dSKatayama Hirofumi MZ         {
53729795a2dSKatayama Hirofumi MZ             LONG lDelta = min(cbSrc - iSrc, Bytes - iDst);
53829795a2dSKatayama Hirofumi MZ             NT_ASSERT(lDelta >= 0);
53929795a2dSKatayama Hirofumi MZ             RtlCopyMemory(pjDst, pjSrc, lDelta);
54029795a2dSKatayama Hirofumi MZ             iDst += lDelta;
54129795a2dSKatayama Hirofumi MZ             break;
54229795a2dSKatayama Hirofumi MZ         }
54329795a2dSKatayama Hirofumi MZ 
544c2c66affSColin Finck         /* Copy one line */
545c2c66affSColin Finck         RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
546c2c66affSColin Finck         pjSrc += lDeltaSrc;
547c2c66affSColin Finck         pjDst += lDeltaDst;
5481cd2f543SKatayama Hirofumi MZ         iSrc += lDeltaSrcAbs;
54929795a2dSKatayama Hirofumi MZ         iDst += lDeltaDst;
550c2c66affSColin Finck     }
55129795a2dSKatayama Hirofumi MZ 
55229795a2dSKatayama Hirofumi MZ     return iDst;
553c2c66affSColin Finck }
554c2c66affSColin Finck 
555c2c66affSColin Finck LONG
556c2c66affSColin Finck APIENTRY
NtGdiGetBitmapBits(HBITMAP hBitmap,ULONG cjBuffer,OUT OPTIONAL PBYTE pUnsafeBits)557c2c66affSColin Finck NtGdiGetBitmapBits(
558c2c66affSColin Finck     HBITMAP hBitmap,
559c2c66affSColin Finck     ULONG cjBuffer,
560c2c66affSColin Finck     OUT OPTIONAL PBYTE pUnsafeBits)
561c2c66affSColin Finck {
562c2c66affSColin Finck     PSURFACE psurf;
563c2c66affSColin Finck     ULONG cjSize;
564c2c66affSColin Finck     LONG ret;
565c2c66affSColin Finck 
566c2c66affSColin Finck     /* Check parameters */
567c2c66affSColin Finck     if (pUnsafeBits != NULL && cjBuffer == 0)
568c2c66affSColin Finck     {
569c2c66affSColin Finck         return 0;
570c2c66affSColin Finck     }
571c2c66affSColin Finck 
572c2c66affSColin Finck     /* Lock the bitmap */
573c2c66affSColin Finck     psurf = SURFACE_ShareLockSurface(hBitmap);
574c2c66affSColin Finck     if (!psurf)
575c2c66affSColin Finck     {
576c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
577c2c66affSColin Finck         return 0;
578c2c66affSColin Finck     }
579c2c66affSColin Finck 
580c2c66affSColin Finck     /* Calculate the size of the bitmap in bytes */
581c2c66affSColin Finck     cjSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx,
582c2c66affSColin Finck                 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
58331d616ffSKatayama Hirofumi MZ                 psurf->SurfObj.sizlBitmap.cy;
584c2c66affSColin Finck 
585c2c66affSColin Finck     /* If the bits vector is null, the function should return the read size */
586c2c66affSColin Finck     if (pUnsafeBits == NULL)
587c2c66affSColin Finck     {
588c2c66affSColin Finck         SURFACE_ShareUnlockSurface(psurf);
589c2c66affSColin Finck         return cjSize;
590c2c66affSColin Finck     }
591c2c66affSColin Finck 
592c2c66affSColin Finck     /* Don't copy more bytes than the buffer has */
593c2c66affSColin Finck     cjBuffer = min(cjBuffer, cjSize);
594c2c66affSColin Finck 
595c2c66affSColin Finck     // FIXME: Use MmSecureVirtualMemory
596c2c66affSColin Finck     _SEH2_TRY
597c2c66affSColin Finck     {
598c2c66affSColin Finck         ProbeForWrite(pUnsafeBits, cjBuffer, 1);
59929795a2dSKatayama Hirofumi MZ         ret = UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
600c2c66affSColin Finck     }
601c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
602c2c66affSColin Finck     {
603c2c66affSColin Finck         ret = 0;
604c2c66affSColin Finck     }
605c2c66affSColin Finck     _SEH2_END
606c2c66affSColin Finck 
607c2c66affSColin Finck     SURFACE_ShareUnlockSurface(psurf);
608c2c66affSColin Finck 
609c2c66affSColin Finck     return ret;
610c2c66affSColin Finck }
611c2c66affSColin Finck 
612c2c66affSColin Finck 
613c2c66affSColin Finck LONG APIENTRY
NtGdiSetBitmapBits(HBITMAP hBitmap,DWORD Bytes,IN PBYTE pUnsafeBits)614c2c66affSColin Finck NtGdiSetBitmapBits(
615c2c66affSColin Finck     HBITMAP hBitmap,
616c2c66affSColin Finck     DWORD Bytes,
617c2c66affSColin Finck     IN PBYTE pUnsafeBits)
618c2c66affSColin Finck {
619c2c66affSColin Finck     LONG ret;
620c2c66affSColin Finck     PSURFACE psurf;
621c2c66affSColin Finck 
622c2c66affSColin Finck     if (pUnsafeBits == NULL || Bytes == 0)
623c2c66affSColin Finck     {
624c2c66affSColin Finck         return 0;
625c2c66affSColin Finck     }
626c2c66affSColin Finck 
627c2c66affSColin Finck     if (GDI_HANDLE_IS_STOCKOBJ(hBitmap))
628c2c66affSColin Finck     {
629c2c66affSColin Finck         return 0;
630c2c66affSColin Finck     }
631c2c66affSColin Finck 
632c2c66affSColin Finck     psurf = SURFACE_ShareLockSurface(hBitmap);
633c2c66affSColin Finck     if (psurf == NULL)
634c2c66affSColin Finck     {
635c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
636c2c66affSColin Finck         return 0;
637c2c66affSColin Finck     }
638c2c66affSColin Finck 
639c2c66affSColin Finck     if (((psurf->flags & API_BITMAP) == 0) ||
640c2c66affSColin Finck         (psurf->SurfObj.iBitmapFormat > BMF_32BPP))
641c2c66affSColin Finck     {
642c2c66affSColin Finck         DPRINT1("Invalid bitmap: iBitmapFormat = %lu, flags = 0x%lx\n",
643c2c66affSColin Finck                 psurf->SurfObj.iBitmapFormat,
644c2c66affSColin Finck                 psurf->flags);
645c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
646c2c66affSColin Finck         SURFACE_ShareUnlockSurface(psurf);
647c2c66affSColin Finck         return 0;
648c2c66affSColin Finck     }
649c2c66affSColin Finck 
650c2c66affSColin Finck     _SEH2_TRY
651c2c66affSColin Finck     {
6526b8f9c0cSKatayama Hirofumi MZ         /* NOTE: Win2k3 doesn't check WORD alignment here. */
653bb336924SKatayama Hirofumi MZ         ProbeForWrite(pUnsafeBits, Bytes, 1);
654c2c66affSColin Finck         ret = UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
655c2c66affSColin Finck     }
656c2c66affSColin Finck     _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
657c2c66affSColin Finck     {
658c2c66affSColin Finck         ret = 0;
659c2c66affSColin Finck     }
660c2c66affSColin Finck     _SEH2_END
661c2c66affSColin Finck 
662c2c66affSColin Finck     SURFACE_ShareUnlockSurface(psurf);
663c2c66affSColin Finck 
664c2c66affSColin Finck     return ret;
665c2c66affSColin Finck }
666c2c66affSColin Finck 
667c2c66affSColin Finck BOOL APIENTRY
NtGdiSetBitmapDimension(HBITMAP hBitmap,INT Width,INT Height,LPSIZE Size)668c2c66affSColin Finck NtGdiSetBitmapDimension(
669c2c66affSColin Finck     HBITMAP hBitmap,
670c2c66affSColin Finck     INT Width,
671c2c66affSColin Finck     INT Height,
672c2c66affSColin Finck     LPSIZE Size)
673c2c66affSColin Finck {
674c2c66affSColin Finck     PSURFACE psurf;
675c2c66affSColin Finck     BOOL Ret = TRUE;
676c2c66affSColin Finck 
677c2c66affSColin Finck     if (hBitmap == NULL)
678c2c66affSColin Finck         return FALSE;
679c2c66affSColin Finck 
680c2c66affSColin Finck     psurf = SURFACE_ShareLockSurface(hBitmap);
681c2c66affSColin Finck     if (psurf == NULL)
682c2c66affSColin Finck     {
683c2c66affSColin Finck         EngSetLastError(ERROR_INVALID_HANDLE);
684c2c66affSColin Finck         return FALSE;
685c2c66affSColin Finck     }
686c2c66affSColin Finck 
687c2c66affSColin Finck     if (Size)
688c2c66affSColin Finck     {
689c2c66affSColin Finck         _SEH2_TRY
690c2c66affSColin Finck         {
691c2c66affSColin Finck             ProbeForWrite(Size, sizeof(SIZE), 1);
692c2c66affSColin Finck             *Size = psurf->sizlDim;
693c2c66affSColin Finck         }
694c2c66affSColin Finck         _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
695c2c66affSColin Finck         {
696c2c66affSColin Finck             Ret = FALSE;
697c2c66affSColin Finck         }
698c2c66affSColin Finck         _SEH2_END
699c2c66affSColin Finck     }
700c2c66affSColin Finck 
701c2c66affSColin Finck     /* The dimension is changed even if writing the old value failed */
702c2c66affSColin Finck     psurf->sizlDim.cx = Width;
703c2c66affSColin Finck     psurf->sizlDim.cy = Height;
704c2c66affSColin Finck 
705c2c66affSColin Finck     SURFACE_ShareUnlockSurface(psurf);
706c2c66affSColin Finck 
707c2c66affSColin Finck     return Ret;
708c2c66affSColin Finck }
709c2c66affSColin Finck 
710c2c66affSColin Finck /*  Internal Functions  */
711c2c66affSColin Finck 
712c2c66affSColin Finck HBITMAP
713c2c66affSColin Finck FASTCALL
BITMAP_CopyBitmap(HBITMAP hBitmap)714c2c66affSColin Finck BITMAP_CopyBitmap(HBITMAP hBitmap)
715c2c66affSColin Finck {
716c2c66affSColin Finck     HBITMAP hbmNew;
717c2c66affSColin Finck     SURFACE *psurfSrc, *psurfNew;
718c2c66affSColin Finck 
719c2c66affSColin Finck     /* Fail, if no source bitmap is given */
720c2c66affSColin Finck     if (hBitmap == NULL) return 0;
721c2c66affSColin Finck 
722c2c66affSColin Finck     /* Lock the source bitmap */
723c2c66affSColin Finck     psurfSrc = SURFACE_ShareLockSurface(hBitmap);
724c2c66affSColin Finck     if (psurfSrc == NULL)
725c2c66affSColin Finck     {
726c2c66affSColin Finck         return 0;
727c2c66affSColin Finck     }
728c2c66affSColin Finck 
729c2c66affSColin Finck     /* Allocate a new bitmap with the same dimensions as the source bmp */
730c2c66affSColin Finck     hbmNew = GreCreateBitmapEx(psurfSrc->SurfObj.sizlBitmap.cx,
731c2c66affSColin Finck                                psurfSrc->SurfObj.sizlBitmap.cy,
732c2c66affSColin Finck                                abs(psurfSrc->SurfObj.lDelta),
733c2c66affSColin Finck                                psurfSrc->SurfObj.iBitmapFormat,
734c2c66affSColin Finck                                psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN,
735c2c66affSColin Finck                                psurfSrc->SurfObj.cjBits,
736c2c66affSColin Finck                                NULL,
737c2c66affSColin Finck                                psurfSrc->flags);
738c2c66affSColin Finck 
739c2c66affSColin Finck     if (hbmNew)
740c2c66affSColin Finck     {
741c2c66affSColin Finck         /* Lock the new bitmap */
742c2c66affSColin Finck         psurfNew = SURFACE_ShareLockSurface(hbmNew);
743c2c66affSColin Finck         if (psurfNew)
744c2c66affSColin Finck         {
745c2c66affSColin Finck             /* Copy the bitmap bits to the new bitmap buffer */
746c2c66affSColin Finck             RtlCopyMemory(psurfNew->SurfObj.pvBits,
747c2c66affSColin Finck                           psurfSrc->SurfObj.pvBits,
748c2c66affSColin Finck                           psurfNew->SurfObj.cjBits);
749c2c66affSColin Finck 
750c2c66affSColin Finck 
751c2c66affSColin Finck             /* Reference the palette of the source bitmap and use it */
752c2c66affSColin Finck             SURFACE_vSetPalette(psurfNew, psurfSrc->ppal);
753c2c66affSColin Finck 
754c2c66affSColin Finck             /* Unlock the new surface */
755c2c66affSColin Finck             SURFACE_ShareUnlockSurface(psurfNew);
756c2c66affSColin Finck         }
757c2c66affSColin Finck         else
758c2c66affSColin Finck         {
759c2c66affSColin Finck             /* Failed to lock the bitmap, shouldn't happen */
760c2c66affSColin Finck             GreDeleteObject(hbmNew);
761c2c66affSColin Finck             hbmNew = NULL;
762c2c66affSColin Finck         }
763c2c66affSColin Finck     }
764c2c66affSColin Finck 
765c2c66affSColin Finck     /* Unlock the source bitmap and return the handle of the new bitmap */
766c2c66affSColin Finck     SURFACE_ShareUnlockSurface(psurfSrc);
767c2c66affSColin Finck     return hbmNew;
768c2c66affSColin Finck }
769c2c66affSColin Finck 
770c2c66affSColin Finck INT APIENTRY
BITMAP_GetObject(SURFACE * psurf,INT Count,LPVOID buffer)771c2c66affSColin Finck BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
772c2c66affSColin Finck {
773c2c66affSColin Finck     PBITMAP pBitmap;
774c2c66affSColin Finck 
775c2c66affSColin Finck     if (!buffer) return sizeof(BITMAP);
776c2c66affSColin Finck     if ((UINT)Count < sizeof(BITMAP)) return 0;
777c2c66affSColin Finck 
778c2c66affSColin Finck     /* Always fill a basic BITMAP structure */
779c2c66affSColin Finck     pBitmap = buffer;
780c2c66affSColin Finck     pBitmap->bmType = 0;
781c2c66affSColin Finck     pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
782c2c66affSColin Finck     pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
783c2c66affSColin Finck     pBitmap->bmPlanes = 1;
784c2c66affSColin Finck     pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
785c2c66affSColin Finck     pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel);
786c2c66affSColin Finck 
787c2c66affSColin Finck     /* Check for DIB section */
788c2c66affSColin Finck     if (psurf->hSecure)
789c2c66affSColin Finck     {
790c2c66affSColin Finck         /* Set bmBits in this case */
791c2c66affSColin Finck         pBitmap->bmBits = psurf->SurfObj.pvBits;
792c2c66affSColin Finck         /* DIBs data are 32 bits aligned */
793c2c66affSColin Finck         pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel);
794c2c66affSColin Finck 
795c2c66affSColin Finck         if (Count >= sizeof(DIBSECTION))
796c2c66affSColin Finck         {
797c2c66affSColin Finck             /* Fill rest of DIBSECTION */
798c2c66affSColin Finck             PDIBSECTION pds = buffer;
799c2c66affSColin Finck 
800c2c66affSColin Finck             pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
801c2c66affSColin Finck             pds->dsBmih.biWidth = pds->dsBm.bmWidth;
802c2c66affSColin Finck             pds->dsBmih.biHeight = pds->dsBm.bmHeight;
803c2c66affSColin Finck             pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
804c2c66affSColin Finck             pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
805c2c66affSColin Finck 
806c2c66affSColin Finck             switch (psurf->SurfObj.iBitmapFormat)
807c2c66affSColin Finck             {
808c2c66affSColin Finck                 case BMF_1BPP:
809c2c66affSColin Finck                 case BMF_4BPP:
810c2c66affSColin Finck                 case BMF_8BPP:
811c2c66affSColin Finck                    pds->dsBmih.biCompression = BI_RGB;
812c2c66affSColin Finck                    break;
813c2c66affSColin Finck 
814c2c66affSColin Finck                 case BMF_16BPP:
815c2c66affSColin Finck                     if (psurf->ppal->flFlags & PAL_RGB16_555)
816c2c66affSColin Finck                         pds->dsBmih.biCompression = BI_RGB;
817c2c66affSColin Finck                     else
818c2c66affSColin Finck                         pds->dsBmih.biCompression = BI_BITFIELDS;
819c2c66affSColin Finck                     break;
820c2c66affSColin Finck 
821c2c66affSColin Finck                 case BMF_24BPP:
822c2c66affSColin Finck                 case BMF_32BPP:
823c2c66affSColin Finck                     /* 24/32bpp BI_RGB is actually BGR format */
824c2c66affSColin Finck                     if (psurf->ppal->flFlags & PAL_BGR)
825c2c66affSColin Finck                         pds->dsBmih.biCompression = BI_RGB;
826c2c66affSColin Finck                     else
827c2c66affSColin Finck                         pds->dsBmih.biCompression = BI_BITFIELDS;
828c2c66affSColin Finck                     break;
829c2c66affSColin Finck 
830c2c66affSColin Finck                 case BMF_4RLE:
831c2c66affSColin Finck                    pds->dsBmih.biCompression = BI_RLE4;
832c2c66affSColin Finck                    break;
833c2c66affSColin Finck                 case BMF_8RLE:
834c2c66affSColin Finck                    pds->dsBmih.biCompression = BI_RLE8;
835c2c66affSColin Finck                    break;
836c2c66affSColin Finck                 case BMF_JPEG:
837c2c66affSColin Finck                    pds->dsBmih.biCompression = BI_JPEG;
838c2c66affSColin Finck                    break;
839c2c66affSColin Finck                 case BMF_PNG:
840c2c66affSColin Finck                    pds->dsBmih.biCompression = BI_PNG;
841c2c66affSColin Finck                    break;
842c2c66affSColin Finck                 default:
843c2c66affSColin Finck                     ASSERT(FALSE); /* This shouldn't happen */
844c2c66affSColin Finck             }
845c2c66affSColin Finck 
846c2c66affSColin Finck             pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
847c2c66affSColin Finck             pds->dsBmih.biXPelsPerMeter = 0;
848c2c66affSColin Finck             pds->dsBmih.biYPelsPerMeter = 0;
849c2c66affSColin Finck             pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
850c2c66affSColin Finck             pds->dsBmih.biClrImportant = psurf->biClrImportant;
851c2c66affSColin Finck             pds->dsBitfields[0] = psurf->ppal->RedMask;
852c2c66affSColin Finck             pds->dsBitfields[1] = psurf->ppal->GreenMask;
853c2c66affSColin Finck             pds->dsBitfields[2] = psurf->ppal->BlueMask;
854c2c66affSColin Finck             pds->dshSection = psurf->hDIBSection;
855c2c66affSColin Finck             pds->dsOffset = psurf->dwOffset;
856c2c66affSColin Finck 
857c2c66affSColin Finck             return sizeof(DIBSECTION);
858c2c66affSColin Finck         }
859c2c66affSColin Finck     }
860c2c66affSColin Finck     else
861c2c66affSColin Finck     {
862c2c66affSColin Finck         /* Not set according to wine test, confirmed in win2k */
863c2c66affSColin Finck         pBitmap->bmBits = NULL;
864c2c66affSColin Finck     }
865c2c66affSColin Finck 
866c2c66affSColin Finck     return sizeof(BITMAP);
867c2c66affSColin Finck }
868c2c66affSColin Finck 
869c2c66affSColin Finck /*
870c2c66affSColin Finck  * @implemented
871c2c66affSColin Finck  */
872c2c66affSColin Finck HDC
873c2c66affSColin Finck APIENTRY
NtGdiGetDCforBitmap(IN HBITMAP hsurf)874c2c66affSColin Finck NtGdiGetDCforBitmap(
875c2c66affSColin Finck     IN HBITMAP hsurf)
876c2c66affSColin Finck {
877c2c66affSColin Finck     HDC hdc = NULL;
878c2c66affSColin Finck     PSURFACE psurf = SURFACE_ShareLockSurface(hsurf);
879c2c66affSColin Finck     if (psurf)
880c2c66affSColin Finck     {
881c2c66affSColin Finck         hdc = psurf->hdc;
882c2c66affSColin Finck         SURFACE_ShareUnlockSurface(psurf);
883c2c66affSColin Finck     }
884c2c66affSColin Finck     return hdc;
885c2c66affSColin Finck }
886c2c66affSColin Finck 
887c2c66affSColin Finck 
888c2c66affSColin Finck /* EOF */
889