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