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