[SHELL32]
[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: 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 APIENTRY
434 NtGdiGetBitmapDimension(
435 HBITMAP hBitmap,
436 LPSIZE psizDim)
437 {
438 PSURFACE psurfBmp;
439 BOOL bResult = TRUE;
440
441 if (hBitmap == NULL)
442 return FALSE;
443
444 /* Lock the bitmap */
445 psurfBmp = SURFACE_ShareLockSurface(hBitmap);
446 if (psurfBmp == NULL)
447 {
448 EngSetLastError(ERROR_INVALID_HANDLE);
449 return FALSE;
450 }
451
452 /* Use SEH to copy the data to the caller */
453 _SEH2_TRY
454 {
455 ProbeForWrite(psizDim, sizeof(SIZE), 1);
456 *psizDim = psurfBmp->sizlDim;
457 }
458 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
459 {
460 bResult = FALSE;
461 }
462 _SEH2_END
463
464 /* Unlock the bitmap */
465 SURFACE_ShareUnlockSurface(psurfBmp);
466
467 return bResult;
468 }
469
470
471 VOID
472 FASTCALL
473 UnsafeGetBitmapBits(
474 PSURFACE psurf,
475 DWORD Bytes,
476 OUT PBYTE pvBits)
477 {
478 PUCHAR pjDst, pjSrc;
479 LONG lDeltaDst, lDeltaSrc;
480 ULONG nWidth, nHeight, cBitsPixel;
481
482 nWidth = psurf->SurfObj.sizlBitmap.cx;
483 nHeight = psurf->SurfObj.sizlBitmap.cy;
484 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
485
486 /* Get pointers */
487 pjSrc = psurf->SurfObj.pvScan0;
488 pjDst = pvBits;
489 lDeltaSrc = psurf->SurfObj.lDelta;
490 lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel);
491
492 while (nHeight--)
493 {
494 /* Copy one line */
495 RtlCopyMemory(pjDst, pjSrc, lDeltaDst);
496 pjSrc += lDeltaSrc;
497 pjDst += lDeltaDst;
498 }
499 }
500
501 LONG
502 APIENTRY
503 NtGdiGetBitmapBits(
504 HBITMAP hBitmap,
505 ULONG cjBuffer,
506 OUT OPTIONAL PBYTE pUnsafeBits)
507 {
508 PSURFACE psurf;
509 ULONG cjSize;
510 LONG ret;
511
512 /* Check parameters */
513 if (pUnsafeBits != NULL && cjBuffer == 0)
514 {
515 return 0;
516 }
517
518 /* Lock the bitmap */
519 psurf = SURFACE_ShareLockSurface(hBitmap);
520 if (!psurf)
521 {
522 EngSetLastError(ERROR_INVALID_HANDLE);
523 return 0;
524 }
525
526 /* Calculate the size of the bitmap in bytes */
527 cjSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx,
528 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) *
529 abs(psurf->SurfObj.sizlBitmap.cy);
530
531 /* If the bits vector is null, the function should return the read size */
532 if (pUnsafeBits == NULL)
533 {
534 SURFACE_ShareUnlockSurface(psurf);
535 return cjSize;
536 }
537
538 /* Don't copy more bytes than the buffer has */
539 cjBuffer = min(cjBuffer, cjSize);
540
541 // FIXME: Use MmSecureVirtualMemory
542 _SEH2_TRY
543 {
544 ProbeForWrite(pUnsafeBits, cjBuffer, 1);
545 UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits);
546 ret = cjBuffer;
547 }
548 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
549 {
550 ret = 0;
551 }
552 _SEH2_END
553
554 SURFACE_ShareUnlockSurface(psurf);
555
556 return ret;
557 }
558
559
560 LONG APIENTRY
561 NtGdiSetBitmapBits(
562 HBITMAP hBitmap,
563 DWORD Bytes,
564 IN PBYTE pUnsafeBits)
565 {
566 LONG ret;
567 PSURFACE psurf;
568
569 if (pUnsafeBits == NULL || Bytes == 0)
570 {
571 return 0;
572 }
573
574 if (GDI_HANDLE_IS_STOCKOBJ(hBitmap))
575 {
576 return 0;
577 }
578
579 psurf = SURFACE_ShareLockSurface(hBitmap);
580 if (psurf == NULL)
581 {
582 EngSetLastError(ERROR_INVALID_HANDLE);
583 return 0;
584 }
585
586 if (((psurf->flags & API_BITMAP) == 0) ||
587 (psurf->SurfObj.iBitmapFormat > BMF_32BPP))
588 {
589 DPRINT1("Invalid bitmap: iBitmapFormat = %lu, flags = 0x%lx\n",
590 psurf->SurfObj.iBitmapFormat,
591 psurf->flags);
592 EngSetLastError(ERROR_INVALID_HANDLE);
593 SURFACE_ShareUnlockSurface(psurf);
594 return 0;
595 }
596
597 _SEH2_TRY
598 {
599 ProbeForRead(pUnsafeBits, Bytes, sizeof(WORD));
600 ret = UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits);
601 }
602 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
603 {
604 ret = 0;
605 }
606 _SEH2_END
607
608 SURFACE_ShareUnlockSurface(psurf);
609
610 return ret;
611 }
612
613 BOOL APIENTRY
614 NtGdiSetBitmapDimension(
615 HBITMAP hBitmap,
616 INT Width,
617 INT Height,
618 LPSIZE Size)
619 {
620 PSURFACE psurf;
621 BOOL Ret = TRUE;
622
623 if (hBitmap == NULL)
624 return FALSE;
625
626 psurf = SURFACE_ShareLockSurface(hBitmap);
627 if (psurf == NULL)
628 {
629 EngSetLastError(ERROR_INVALID_HANDLE);
630 return FALSE;
631 }
632
633 if (Size)
634 {
635 _SEH2_TRY
636 {
637 ProbeForWrite(Size, sizeof(SIZE), 1);
638 *Size = psurf->sizlDim;
639 }
640 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
641 {
642 Ret = FALSE;
643 }
644 _SEH2_END
645 }
646
647 /* The dimension is changed even if writing the old value failed */
648 psurf->sizlDim.cx = Width;
649 psurf->sizlDim.cy = Height;
650
651 SURFACE_ShareUnlockSurface(psurf);
652
653 return Ret;
654 }
655
656 /* Internal Functions */
657
658 HBITMAP
659 FASTCALL
660 BITMAP_CopyBitmap(HBITMAP hBitmap)
661 {
662 HBITMAP hbmNew;
663 SURFACE *psurfSrc, *psurfNew;
664
665 /* Fail, if no source bitmap is given */
666 if (hBitmap == NULL) return 0;
667
668 /* Lock the source bitmap */
669 psurfSrc = SURFACE_ShareLockSurface(hBitmap);
670 if (psurfSrc == NULL)
671 {
672 return 0;
673 }
674
675 /* Allocate a new bitmap with the same dimensions as the source bmp */
676 hbmNew = GreCreateBitmapEx(psurfSrc->SurfObj.sizlBitmap.cx,
677 psurfSrc->SurfObj.sizlBitmap.cy,
678 abs(psurfSrc->SurfObj.lDelta),
679 psurfSrc->SurfObj.iBitmapFormat,
680 psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN,
681 psurfSrc->SurfObj.cjBits,
682 NULL,
683 psurfSrc->flags);
684
685 if (hbmNew)
686 {
687 /* Lock the new bitmap */
688 psurfNew = SURFACE_ShareLockSurface(hbmNew);
689 if (psurfNew)
690 {
691 /* Copy the bitmap bits to the new bitmap buffer */
692 RtlCopyMemory(psurfNew->SurfObj.pvBits,
693 psurfSrc->SurfObj.pvBits,
694 psurfNew->SurfObj.cjBits);
695
696
697 /* Reference the palette of the source bitmap and use it */
698 SURFACE_vSetPalette(psurfNew, psurfSrc->ppal);
699
700 /* Unlock the new surface */
701 SURFACE_ShareUnlockSurface(psurfNew);
702 }
703 else
704 {
705 /* Failed to lock the bitmap, shouldn't happen */
706 GreDeleteObject(hbmNew);
707 hbmNew = NULL;
708 }
709 }
710
711 /* Unlock the source bitmap and return the handle of the new bitmap */
712 SURFACE_ShareUnlockSurface(psurfSrc);
713 return hbmNew;
714 }
715
716 INT APIENTRY
717 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer)
718 {
719 PBITMAP pBitmap;
720
721 if (!buffer) return sizeof(BITMAP);
722 if ((UINT)Count < sizeof(BITMAP)) return 0;
723
724 /* Always fill a basic BITMAP structure */
725 pBitmap = buffer;
726 pBitmap->bmType = 0;
727 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx;
728 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy;
729 pBitmap->bmPlanes = 1;
730 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat);
731 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel);
732
733 /* Check for DIB section */
734 if (psurf->hSecure)
735 {
736 /* Set bmBits in this case */
737 pBitmap->bmBits = psurf->SurfObj.pvBits;
738 /* DIBs data are 32 bits aligned */
739 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel);
740
741 if (Count >= sizeof(DIBSECTION))
742 {
743 /* Fill rest of DIBSECTION */
744 PDIBSECTION pds = buffer;
745
746 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER);
747 pds->dsBmih.biWidth = pds->dsBm.bmWidth;
748 pds->dsBmih.biHeight = pds->dsBm.bmHeight;
749 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes;
750 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel;
751
752 switch (psurf->SurfObj.iBitmapFormat)
753 {
754 case BMF_1BPP:
755 case BMF_4BPP:
756 case BMF_8BPP:
757 pds->dsBmih.biCompression = BI_RGB;
758 break;
759
760 case BMF_16BPP:
761 if (psurf->ppal->flFlags & PAL_RGB16_555)
762 pds->dsBmih.biCompression = BI_RGB;
763 else
764 pds->dsBmih.biCompression = BI_BITFIELDS;
765 break;
766
767 case BMF_24BPP:
768 case BMF_32BPP:
769 /* 24/32bpp BI_RGB is actually BGR format */
770 if (psurf->ppal->flFlags & PAL_BGR)
771 pds->dsBmih.biCompression = BI_RGB;
772 else
773 pds->dsBmih.biCompression = BI_BITFIELDS;
774 break;
775
776 case BMF_4RLE:
777 pds->dsBmih.biCompression = BI_RLE4;
778 break;
779 case BMF_8RLE:
780 pds->dsBmih.biCompression = BI_RLE8;
781 break;
782 case BMF_JPEG:
783 pds->dsBmih.biCompression = BI_JPEG;
784 break;
785 case BMF_PNG:
786 pds->dsBmih.biCompression = BI_PNG;
787 break;
788 default:
789 ASSERT(FALSE); /* This shouldn't happen */
790 }
791
792 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits;
793 pds->dsBmih.biXPelsPerMeter = 0;
794 pds->dsBmih.biYPelsPerMeter = 0;
795 pds->dsBmih.biClrUsed = psurf->ppal->NumColors;
796 pds->dsBmih.biClrImportant = psurf->biClrImportant;
797 pds->dsBitfields[0] = psurf->ppal->RedMask;
798 pds->dsBitfields[1] = psurf->ppal->GreenMask;
799 pds->dsBitfields[2] = psurf->ppal->BlueMask;
800 pds->dshSection = psurf->hDIBSection;
801 pds->dsOffset = psurf->dwOffset;
802
803 return sizeof(DIBSECTION);
804 }
805 }
806 else
807 {
808 /* Not set according to wine test, confirmed in win2k */
809 pBitmap->bmBits = NULL;
810 }
811
812 return sizeof(BITMAP);
813 }
814
815 /*
816 * @implemented
817 */
818 HDC
819 APIENTRY
820 NtGdiGetDCforBitmap(
821 IN HBITMAP hsurf)
822 {
823 HDC hdc = NULL;
824 PSURFACE psurf = SURFACE_ShareLockSurface(hsurf);
825 if (psurf)
826 {
827 hdc = psurf->hdc;
828 SURFACE_ShareUnlockSurface(psurf);
829 }
830 return hdc;
831 }
832
833
834 /* EOF */