Copy msimg32
[reactos.git] / reactos / subsys / win32k / objects / bitmaps.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$ */
20 #include <w32k.h>
21
22 #define IN_RECT(r,x,y) \
23 ( \
24 (x) >= (r).left && \
25 (y) >= (r).top && \
26 (x) < (r).right && \
27 (y) < (r).bottom \
28 )
29
30 BOOL STDCALL
31 NtGdiBitBlt(
32 HDC hDCDest,
33 INT XDest,
34 INT YDest,
35 INT Width,
36 INT Height,
37 HDC hDCSrc,
38 INT XSrc,
39 INT YSrc,
40 DWORD ROP)
41 {
42 PDC DCDest = NULL;
43 PDC DCSrc = NULL;
44 BITMAPOBJ *BitmapDest, *BitmapSrc;
45 RECTL DestRect;
46 POINTL SourcePoint, BrushOrigin;
47 BOOL Status;
48 XLATEOBJ *XlateObj = NULL;
49 HPALETTE SourcePalette = 0, DestPalette = 0;
50 PGDIBRUSHOBJ BrushObj;
51 GDIBRUSHINST BrushInst;
52 BOOL UsesSource = ROP_USES_SOURCE(ROP);
53 BOOL UsesPattern = ROP_USES_PATTERN(ROP);
54
55 DCDest = DC_LockDc(hDCDest);
56 if (NULL == DCDest)
57 {
58 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCDest);
59 SetLastWin32Error(ERROR_INVALID_HANDLE);
60 return FALSE;
61 }
62
63 if (UsesSource)
64 {
65 if (hDCSrc != hDCDest)
66 {
67 DCSrc = DC_LockDc(hDCSrc);
68 if (NULL == DCSrc)
69 {
70 DC_UnlockDc(hDCDest);
71 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiBitBlt\n", hDCSrc);
72 SetLastWin32Error(ERROR_INVALID_HANDLE);
73 return FALSE;
74 }
75 }
76 else
77 {
78 DCSrc = DCDest;
79 }
80 }
81 else
82 {
83 DCSrc = NULL;
84 }
85
86 /* Offset the destination and source by the origin of their DCs. */
87 XDest += DCDest->w.DCOrgX;
88 YDest += DCDest->w.DCOrgY;
89 if (UsesSource)
90 {
91 XSrc += DCSrc->w.DCOrgX;
92 YSrc += DCSrc->w.DCOrgY;
93 }
94
95 DestRect.left = XDest;
96 DestRect.top = YDest;
97 DestRect.right = XDest+Width;
98 DestRect.bottom = YDest+Height;
99
100 SourcePoint.x = XSrc;
101 SourcePoint.y = YSrc;
102
103 BrushOrigin.x = 0;
104 BrushOrigin.y = 0;
105
106 /* Determine surfaces to be used in the bitblt */
107 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
108 if (UsesSource)
109 {
110 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
111 BitmapSrc = BitmapDest;
112 else
113 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
114 }
115 else
116 {
117 BitmapSrc = NULL;
118 }
119
120 if (UsesPattern)
121 {
122 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
123 if (NULL == BrushObj)
124 {
125 if (UsesSource && hDCSrc != hDCDest)
126 {
127 DC_UnlockDc(hDCSrc);
128 }
129 if(BitmapDest != NULL)
130 {
131 BITMAPOBJ_UnlockBitmap(DCDest->w.hBitmap);
132 }
133 if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
134 {
135 BITMAPOBJ_UnlockBitmap(DCSrc->w.hBitmap);
136 }
137 DC_UnlockDc(hDCDest);
138 SetLastWin32Error(ERROR_INVALID_HANDLE);
139 return FALSE;
140 }
141 BrushOrigin = BrushObj->ptOrigin;
142 IntGdiInitBrushInstance(&BrushInst, BrushObj, DCDest->XlateBrush);
143 }
144 else
145 {
146 BrushObj = NULL;
147 }
148
149 /* Create the XLATEOBJ. */
150 if (UsesSource)
151 {
152 if (DCDest->w.hPalette != 0)
153 DestPalette = DCDest->w.hPalette;
154
155 if (DCSrc->w.hPalette != 0)
156 SourcePalette = DCSrc->w.hPalette;
157
158 /* KB41464 details how to convert between mono and color */
159 if (DCDest->w.bitsPerPixel == 1 && DCSrc->w.bitsPerPixel == 1)
160 {
161 XlateObj = NULL;
162 }
163 else
164 {
165 if (DCDest->w.bitsPerPixel == 1)
166 {
167 XlateObj = IntEngCreateMonoXlate(0, DestPalette, SourcePalette, DCSrc->w.backgroundColor);
168 }
169 else if (DCSrc->w.bitsPerPixel == 1)
170 {
171 XlateObj = IntEngCreateSrcMonoXlate(DestPalette, DCSrc->w.backgroundColor, DCSrc->w.textColor);
172 }
173 else
174 {
175 XlateObj = IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
176 }
177 if (NULL == XlateObj)
178 {
179 if (UsesSource && hDCSrc != hDCDest)
180 {
181 DC_UnlockDc(hDCSrc);
182 }
183 DC_UnlockDc(hDCDest);
184 if(BitmapDest != NULL)
185 {
186 BITMAPOBJ_UnlockBitmap(DCDest->w.hBitmap);
187 }
188 if(BitmapSrc != NULL && BitmapSrc != BitmapDest)
189 {
190 BITMAPOBJ_UnlockBitmap(DCSrc->w.hBitmap);
191 }
192 if(BrushObj != NULL)
193 {
194 BRUSHOBJ_UnlockBrush(DCDest->w.hBrush);
195 }
196 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
197 return FALSE;
198 }
199 }
200 }
201
202 /* Perform the bitblt operation */
203 Status = IntEngBitBlt(BitmapDest, BitmapSrc, NULL, DCDest->CombinedClip, XlateObj,
204 &DestRect, &SourcePoint, NULL, BrushObj ? &BrushInst.BrushObject : NULL, &BrushOrigin, ROP);
205
206 if (UsesSource && XlateObj != NULL)
207 EngDeleteXlate(XlateObj);
208
209 if(BitmapDest != NULL)
210 {
211 BITMAPOBJ_UnlockBitmap(DCDest->w.hBitmap);
212 }
213 if (UsesSource && BitmapSrc != BitmapDest)
214 {
215 BITMAPOBJ_UnlockBitmap(DCSrc->w.hBitmap);
216 }
217 if (BrushObj != NULL)
218 {
219 BRUSHOBJ_UnlockBrush(DCDest->w.hBrush);
220 }
221 if (UsesSource && hDCSrc != hDCDest)
222 {
223 DC_UnlockDc(hDCSrc);
224 }
225 DC_UnlockDc(hDCDest);
226
227 return Status;
228 }
229
230 BOOL STDCALL
231 NtGdiTransparentBlt(
232 HDC hdcDst,
233 INT xDst,
234 INT yDst,
235 INT cxDst,
236 INT cyDst,
237 HDC hdcSrc,
238 INT xSrc,
239 INT ySrc,
240 INT cxSrc,
241 INT cySrc,
242 COLORREF TransColor)
243 {
244 PDC DCDest, DCSrc;
245 RECTL rcDest, rcSrc;
246 BITMAPOBJ *BitmapDest, *BitmapSrc;
247 XLATEOBJ *XlateObj;
248 HPALETTE SourcePalette = 0, DestPalette = 0;
249 PPALGDI PalDestGDI, PalSourceGDI;
250 USHORT PalDestMode, PalSrcMode;
251 ULONG TransparentColor = 0;
252 BOOL Ret = FALSE;
253
254 if(!(DCDest = DC_LockDc(hdcDst)))
255 {
256 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcDst);
257 SetLastWin32Error(ERROR_INVALID_HANDLE);
258 return FALSE;
259 }
260
261 if((hdcDst != hdcSrc) && !(DCSrc = DC_LockDc(hdcSrc)))
262 {
263 DC_UnlockDc(hdcDst);
264 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiTransparentBlt\n", hdcSrc);
265 SetLastWin32Error(ERROR_INVALID_HANDLE);
266 return FALSE;
267 }
268 if(hdcDst == hdcSrc)
269 {
270 DCSrc = DCDest;
271 }
272
273 /* Offset positions */
274 xDst += DCDest->w.DCOrgX;
275 yDst += DCDest->w.DCOrgY;
276 xSrc += DCSrc->w.DCOrgX;
277 ySrc += DCSrc->w.DCOrgY;
278
279 if(DCDest->w.hPalette)
280 DestPalette = DCDest->w.hPalette;
281
282 if(DCSrc->w.hPalette)
283 SourcePalette = DCSrc->w.hPalette;
284
285 if(!(PalSourceGDI = PALETTE_LockPalette(SourcePalette)))
286 {
287 DC_UnlockDc(hdcSrc);
288 DC_UnlockDc(hdcDst);
289 SetLastWin32Error(ERROR_INVALID_HANDLE);
290 return FALSE;
291 }
292 if((DestPalette != SourcePalette) && !(PalDestGDI = PALETTE_LockPalette(DestPalette)))
293 {
294 PALETTE_UnlockPalette(SourcePalette);
295 DC_UnlockDc(hdcSrc);
296 DC_UnlockDc(hdcDst);
297 SetLastWin32Error(ERROR_INVALID_HANDLE);
298 return FALSE;
299 }
300 if(DestPalette != SourcePalette)
301 {
302 PalDestMode = PalDestGDI->Mode;
303 PalSrcMode = PalSourceGDI->Mode;
304 PALETTE_UnlockPalette(DestPalette);
305 }
306 else
307 {
308 PalDestMode = PalSrcMode = PalSourceGDI->Mode;
309 }
310 PALETTE_UnlockPalette(SourcePalette);
311
312 /* Translate Transparent (RGB) Color to the source palette */
313 if((XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalSrcMode, PAL_RGB, SourcePalette, NULL)))
314 {
315 TransparentColor = XLATEOBJ_iXlate(XlateObj, (ULONG)TransColor);
316 EngDeleteXlate(XlateObj);
317 }
318
319 /* Create the XLATE object to convert colors between source and destination */
320 XlateObj = (XLATEOBJ*)IntEngCreateXlate(PalDestMode, PalSrcMode, DestPalette, SourcePalette);
321
322 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
323 /* FIXME - BitmapDest can be NULL!!!! Don't assert here! */
324 ASSERT(BitmapDest);
325 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
326 /* FIXME - BitmapSrc can be NULL!!!! Don't assert here! */
327 ASSERT(BitmapSrc);
328
329 rcDest.left = xDst;
330 rcDest.top = yDst;
331 rcDest.right = rcDest.left + cxDst;
332 rcDest.bottom = rcDest.top + cyDst;
333 rcSrc.left = xSrc;
334 rcSrc.top = ySrc;
335 rcSrc.right = rcSrc.left + cxSrc;
336 rcSrc.bottom = rcSrc.top + cySrc;
337
338 if((cxDst != cxSrc) || (cyDst != cySrc))
339 {
340 DPRINT1("TransparentBlt() does not support stretching at the moment!\n");
341 goto done;
342 }
343
344 Ret = IntEngTransparentBlt(BitmapDest, BitmapSrc, DCDest->CombinedClip, XlateObj, &rcDest, &rcSrc,
345 TransparentColor, 0);
346
347 done:
348 BITMAPOBJ_UnlockBitmap(DCDest->w.hBitmap);
349 BITMAPOBJ_UnlockBitmap(DCSrc->w.hBitmap);
350 DC_UnlockDc(hdcSrc);
351 if(hdcDst != hdcSrc)
352 {
353 DC_UnlockDc(hdcDst);
354 }
355 if(XlateObj)
356 {
357 EngDeleteXlate(XlateObj);
358 }
359 return Ret;
360 }
361
362 HBITMAP STDCALL
363 NtGdiCreateBitmap(
364 INT Width,
365 INT Height,
366 UINT Planes,
367 UINT BitsPerPel,
368 CONST VOID *Bits)
369 {
370 PBITMAPOBJ bmp;
371 HBITMAP hBitmap;
372 SIZEL Size;
373
374 /* NOTE: Windows also doesn't store nr. of planes separately! */
375 BitsPerPel = (BYTE)BitsPerPel * (BYTE)Planes;
376
377 /* Check parameters */
378 if (!Height || !Width)
379 {
380 Size.cx = Size.cy = 1;
381 }
382 else
383 {
384 Size.cx = abs(Width);
385 Size.cy = abs(Height);
386 }
387
388 /* Create the bitmap object. */
389 hBitmap = IntCreateBitmap(Size, BITMAPOBJ_GetWidthBytes(Width, BitsPerPel),
390 BitmapFormat(BitsPerPel, BI_RGB),
391 (Height < 0 ? BMF_TOPDOWN : 0) |
392 (Bits == NULL ? 0 : BMF_NOZEROINIT), NULL);
393 if (!hBitmap)
394 {
395 DPRINT("NtGdiCreateBitmap: IntCreateBitmap returned 0\n");
396 return 0;
397 }
398
399 DPRINT("NtGdiCreateBitmap:%dx%d, %d BPP colors returning %08x\n",
400 Size.cx, Size.cy, BitsPerPel, hBitmap);
401
402 bmp = BITMAPOBJ_LockBitmap( hBitmap );
403 /* FIXME - bmp can be NULL!!!!!! */
404 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
405 BITMAPOBJ_UnlockBitmap( hBitmap );
406
407 /*
408 * NOTE: It's ugly practice, but we are using the object even
409 * after unlocking. Since the handle is currently known only
410 * to us it should be safe.
411 */
412
413 if (Bits != NULL)
414 {
415 NtGdiSetBitmapBits(hBitmap, bmp->SurfObj.cjBits, Bits);
416 }
417
418 return hBitmap;
419 }
420
421 BOOL INTERNAL_CALL
422 BITMAP_Cleanup(PVOID ObjectBody)
423 {
424 PBITMAPOBJ pBmp = (PBITMAPOBJ)ObjectBody;
425 if (pBmp->SurfObj.pvBits != NULL &&
426 (pBmp->flFlags & BITMAPOBJ_IS_APIBITMAP))
427 {
428 if (pBmp->dib == NULL)
429 {
430 ExFreePool(pBmp->SurfObj.pvBits);
431 }
432 else
433 {
434 EngFreeUserMem(pBmp->SurfObj.pvBits);
435 }
436 }
437
438 return TRUE;
439 }
440
441
442 HBITMAP FASTCALL
443 IntCreateCompatibleBitmap(
444 PDC Dc,
445 INT Width,
446 INT Height)
447 {
448 HBITMAP Bmp;
449
450 Bmp = NULL;
451
452 if ((Width >= 0x10000) || (Height >= 0x10000))
453 {
454 DPRINT1("got bad width %d or height %d, please look for reason\n", Width, Height);
455 return NULL;
456 }
457
458 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
459 if (0 == Width || 0 == Height)
460 {
461 Bmp = NtGdiCreateBitmap (1, 1, 1, 1, NULL);
462 }
463 else
464 {
465 Bmp = NtGdiCreateBitmap(Width, Height, 1, Dc->w.bitsPerPixel, NULL);
466 }
467
468 return Bmp;
469 }
470
471 HBITMAP STDCALL
472 NtGdiCreateCompatibleBitmap(
473 HDC hDC,
474 INT Width,
475 INT Height)
476 {
477 HBITMAP Bmp;
478 PDC Dc;
479
480 Dc = DC_LockDc(hDC);
481
482 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, Dc->w.bitsPerPixel);
483
484 if (NULL == Dc)
485 {
486 SetLastWin32Error(ERROR_INVALID_HANDLE);
487 return NULL;
488 }
489
490 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
491
492 DPRINT ("\t\t%04x\n", Bmp);
493 DC_UnlockDc(hDC);
494 return Bmp;
495 }
496
497 HBITMAP STDCALL
498 NtGdiCreateBitmapIndirect(CONST BITMAP *BM)
499 {
500 return NtGdiCreateBitmap (BM->bmWidth,
501 BM->bmHeight,
502 BM->bmPlanes,
503 BM->bmBitsPixel,
504 BM->bmBits);
505 }
506
507 HBITMAP STDCALL
508 NtGdiCreateDiscardableBitmap(
509 HDC hDC,
510 INT Width,
511 INT Height)
512 {
513 /* FIXME: this probably should do something else */
514 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
515 }
516
517 BOOL STDCALL
518 NtGdiExtFloodFill(
519 HDC hDC,
520 INT XStart,
521 INT YStart,
522 COLORREF Color,
523 UINT FillType)
524 {
525 UNIMPLEMENTED;
526 return FALSE;
527 }
528
529 BOOL STDCALL
530 NtGdiFloodFill(
531 HDC hDC,
532 INT XStart,
533 INT YStart,
534 COLORREF Fill)
535 {
536 return NtGdiExtFloodFill(hDC, XStart, YStart, Fill, FLOODFILLBORDER );
537 }
538
539 BOOL STDCALL
540 NtGdiGetBitmapDimensionEx(
541 HBITMAP hBitmap,
542 LPSIZE Dimension)
543 {
544 PBITMAPOBJ bmp;
545
546 bmp = BITMAPOBJ_LockBitmap(hBitmap);
547 if (bmp == NULL)
548 {
549 return FALSE;
550 }
551
552 *Dimension = bmp->dimension;
553
554 BITMAPOBJ_UnlockBitmap(hBitmap);
555
556 return TRUE;
557 }
558
559 COLORREF STDCALL
560 NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
561 {
562 PDC dc = NULL;
563 COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
564 BOOL bInRect = FALSE;
565 BITMAPOBJ *BitmapObject;
566 SURFOBJ *SurfaceObject;
567 HPALETTE Pal = 0;
568 XLATEOBJ *XlateObj;
569
570 dc = DC_LockDc (hDC);
571
572 if ( !dc )
573 {
574 SetLastWin32Error(ERROR_INVALID_HANDLE);
575 return Result;
576 }
577 XPos += dc->w.DCOrgX;
578 YPos += dc->w.DCOrgY;
579 if ( IN_RECT(dc->CombinedClip->rclBounds,XPos,YPos) )
580 {
581 bInRect = TRUE;
582 BitmapObject = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
583 SurfaceObject = &BitmapObject->SurfObj;
584 if ( BitmapObject )
585 {
586 if ( dc->w.hPalette != 0 )
587 Pal = dc->w.hPalette;
588 /* FIXME: Verify if it shouldn't be PAL_BGR! */
589 XlateObj = (XLATEOBJ*)IntEngCreateXlate ( PAL_RGB, 0, NULL, Pal );
590 if ( XlateObj )
591 {
592 // check if this DC has a DIB behind it...
593 if ( SurfaceObject->pvScan0 ) // STYPE_BITMAP == SurfaceObject->iType
594 {
595 ASSERT ( SurfaceObject->lDelta );
596 Result = XLATEOBJ_iXlate(XlateObj,
597 DibFunctionsForBitmapFormat[SurfaceObject->iBitmapFormat].DIB_GetPixel ( SurfaceObject, XPos, YPos ) );
598 }
599 EngDeleteXlate(XlateObj);
600 }
601 BITMAPOBJ_UnlockBitmap(dc->w.hBitmap);
602 }
603 }
604 DC_UnlockDc(hDC);
605
606 // if Result is still CLR_INVALID, then the "quick" method above didn't work
607 if ( bInRect && Result == CLR_INVALID )
608 {
609 // FIXME: create a 1x1 32BPP DIB, and blit to it
610 HDC hDCTmp = NtGdiCreateCompatableDC(hDC);
611 if ( hDCTmp )
612 {
613 static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
614 BITMAPINFO bi;
615 RtlMoveMemory ( &(bi.bmiHeader), &bih, sizeof(bih) );
616 HBITMAP hBmpTmp = NtGdiCreateDIBitmap ( hDC, &bi.bmiHeader, 0, NULL, &bi, DIB_RGB_COLORS );
617 //HBITMAP hBmpTmp = NtGdiCreateBitmap ( 1, 1, 1, 32, NULL);
618 if ( hBmpTmp )
619 {
620 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectObject ( hDCTmp, hBmpTmp );
621 if ( hBmpOld )
622 {
623 PBITMAPOBJ bmpobj;
624
625 NtGdiBitBlt ( hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY );
626 NtGdiSelectObject ( hDCTmp, hBmpOld );
627
628 // our bitmap is no longer selected, so we can access it's stuff...
629 bmpobj = BITMAPOBJ_LockBitmap ( hBmpTmp );
630 if ( bmpobj )
631 {
632 Result = *(COLORREF*)bmpobj->SurfObj.pvScan0;
633 BITMAPOBJ_UnlockBitmap ( hBmpTmp );
634 }
635 }
636 NtGdiDeleteObject ( hBmpTmp );
637 }
638 NtGdiDeleteDC ( hDCTmp );
639 }
640 }
641
642 return Result;
643 }
644
645 /***********************************************************************
646 * MaskBlt
647 * Ported from WINE by sedwards 11-4-03
648 *
649 * Someone thought it would be faster to do it here and then switch back
650 * to GDI32. I dunno. Write a test and let me know.
651 */
652
653 static inline BYTE
654 SwapROP3_SrcDst(BYTE bRop3)
655 {
656 return (bRop3 & 0x99) | ((bRop3 & 0x22) << 1) | ((bRop3 & 0x44) >> 1);
657 }
658
659 #define FRGND_ROP3(ROP4) ((ROP4) & 0x00FFFFFF)
660 #define BKGND_ROP3(ROP4) (ROP3Table[(SwapROP3_SrcDst((ROP4)>>24)) & 0xFF])
661 #define DSTCOPY 0x00AA0029
662 #define DSTERASE 0x00220326 /* dest = dest & (~src) : DSna */
663
664 BOOL STDCALL
665 NtGdiMaskBlt (
666 HDC hdcDest, INT nXDest, INT nYDest,
667 INT nWidth, INT nHeight, HDC hdcSrc,
668 INT nXSrc, INT nYSrc, HBITMAP hbmMask,
669 INT xMask, INT yMask, DWORD dwRop)
670 {
671 HBITMAP hOldMaskBitmap, hBitmap2, hOldBitmap2, hBitmap3, hOldBitmap3;
672 HDC hDCMask, hDC1, hDC2;
673 static const DWORD ROP3Table[256] =
674 {
675 0x00000042, 0x00010289,
676 0x00020C89, 0x000300AA,
677 0x00040C88, 0x000500A9,
678 0x00060865, 0x000702C5,
679 0x00080F08, 0x00090245,
680 0x000A0329, 0x000B0B2A,
681 0x000C0324, 0x000D0B25,
682 0x000E08A5, 0x000F0001,
683 0x00100C85, 0x001100A6,
684 0x00120868, 0x001302C8,
685 0x00140869, 0x001502C9,
686 0x00165CCA, 0x00171D54,
687 0x00180D59, 0x00191CC8,
688 0x001A06C5, 0x001B0768,
689 0x001C06CA, 0x001D0766,
690 0x001E01A5, 0x001F0385,
691 0x00200F09, 0x00210248,
692 0x00220326, 0x00230B24,
693 0x00240D55, 0x00251CC5,
694 0x002606C8, 0x00271868,
695 0x00280369, 0x002916CA,
696 0x002A0CC9, 0x002B1D58,
697 0x002C0784, 0x002D060A,
698 0x002E064A, 0x002F0E2A,
699 0x0030032A, 0x00310B28,
700 0x00320688, 0x00330008,
701 0x003406C4, 0x00351864,
702 0x003601A8, 0x00370388,
703 0x0038078A, 0x00390604,
704 0x003A0644, 0x003B0E24,
705 0x003C004A, 0x003D18A4,
706 0x003E1B24, 0x003F00EA,
707 0x00400F0A, 0x00410249,
708 0x00420D5D, 0x00431CC4,
709 0x00440328, 0x00450B29,
710 0x004606C6, 0x0047076A,
711 0x00480368, 0x004916C5,
712 0x004A0789, 0x004B0605,
713 0x004C0CC8, 0x004D1954,
714 0x004E0645, 0x004F0E25,
715 0x00500325, 0x00510B26,
716 0x005206C9, 0x00530764,
717 0x005408A9, 0x00550009,
718 0x005601A9, 0x00570389,
719 0x00580785, 0x00590609,
720 0x005A0049, 0x005B18A9,
721 0x005C0649, 0x005D0E29,
722 0x005E1B29, 0x005F00E9,
723 0x00600365, 0x006116C6,
724 0x00620786, 0x00630608,
725 0x00640788, 0x00650606,
726 0x00660046, 0x006718A8,
727 0x006858A6, 0x00690145,
728 0x006A01E9, 0x006B178A,
729 0x006C01E8, 0x006D1785,
730 0x006E1E28, 0x006F0C65,
731 0x00700CC5, 0x00711D5C,
732 0x00720648, 0x00730E28,
733 0x00740646, 0x00750E26,
734 0x00761B28, 0x007700E6,
735 0x007801E5, 0x00791786,
736 0x007A1E29, 0x007B0C68,
737 0x007C1E24, 0x007D0C69,
738 0x007E0955, 0x007F03C9,
739 0x008003E9, 0x00810975,
740 0x00820C49, 0x00831E04,
741 0x00840C48, 0x00851E05,
742 0x008617A6, 0x008701C5,
743 0x008800C6, 0x00891B08,
744 0x008A0E06, 0x008B0666,
745 0x008C0E08, 0x008D0668,
746 0x008E1D7C, 0x008F0CE5,
747 0x00900C45, 0x00911E08,
748 0x009217A9, 0x009301C4,
749 0x009417AA, 0x009501C9,
750 0x00960169, 0x0097588A,
751 0x00981888, 0x00990066,
752 0x009A0709, 0x009B07A8,
753 0x009C0704, 0x009D07A6,
754 0x009E16E6, 0x009F0345,
755 0x00A000C9, 0x00A11B05,
756 0x00A20E09, 0x00A30669,
757 0x00A41885, 0x00A50065,
758 0x00A60706, 0x00A707A5,
759 0x00A803A9, 0x00A90189,
760 0x00AA0029, 0x00AB0889,
761 0x00AC0744, 0x00AD06E9,
762 0x00AE0B06, 0x00AF0229,
763 0x00B00E05, 0x00B10665,
764 0x00B21974, 0x00B30CE8,
765 0x00B4070A, 0x00B507A9,
766 0x00B616E9, 0x00B70348,
767 0x00B8074A, 0x00B906E6,
768 0x00BA0B09, 0x00BB0226,
769 0x00BC1CE4, 0x00BD0D7D,
770 0x00BE0269, 0x00BF08C9,
771 0x00C000CA, 0x00C11B04,
772 0x00C21884, 0x00C3006A,
773 0x00C40E04, 0x00C50664,
774 0x00C60708, 0x00C707AA,
775 0x00C803A8, 0x00C90184,
776 0x00CA0749, 0x00CB06E4,
777 0x00CC0020, 0x00CD0888,
778 0x00CE0B08, 0x00CF0224,
779 0x00D00E0A, 0x00D1066A,
780 0x00D20705, 0x00D307A4,
781 0x00D41D78, 0x00D50CE9,
782 0x00D616EA, 0x00D70349,
783 0x00D80745, 0x00D906E8,
784 0x00DA1CE9, 0x00DB0D75,
785 0x00DC0B04, 0x00DD0228,
786 0x00DE0268, 0x00DF08C8,
787 0x00E003A5, 0x00E10185,
788 0x00E20746, 0x00E306EA,
789 0x00E40748, 0x00E506E5,
790 0x00E61CE8, 0x00E70D79,
791 0x00E81D74, 0x00E95CE6,
792 0x00EA02E9, 0x00EB0849,
793 0x00EC02E8, 0x00ED0848,
794 0x00EE0086, 0x00EF0A08,
795 0x00F00021, 0x00F10885,
796 0x00F20B05, 0x00F3022A,
797 0x00F40B0A, 0x00F50225,
798 0x00F60265, 0x00F708C5,
799 0x00F802E5, 0x00F90845,
800 0x00FA0089, 0x00FB0A09,
801 0x00FC008A, 0x00FD0A0A,
802 0x00FE02A9, 0x00FF0062,
803 };
804
805 if (!hbmMask)
806 return NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
807
808 /* 1. make mask bitmap's dc */
809 hDCMask = NtGdiCreateCompatableDC(hdcDest);
810 hOldMaskBitmap = (HBITMAP)NtGdiSelectObject(hDCMask, hbmMask);
811
812 /* 2. make masked Background bitmap */
813
814 /* 2.1 make bitmap */
815 hDC1 = NtGdiCreateCompatableDC(hdcDest);
816 hBitmap2 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
817 hOldBitmap2 = (HBITMAP)NtGdiSelectObject(hDC1, hBitmap2);
818
819 /* 2.2 draw dest bitmap and mask */
820 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, SRCCOPY);
821 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, BKGND_ROP3(dwRop));
822 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, DSTERASE);
823
824 /* 3. make masked Foreground bitmap */
825
826 /* 3.1 make bitmap */
827 hDC2 = NtGdiCreateCompatableDC(hdcDest);
828 hBitmap3 = NtGdiCreateCompatibleBitmap(hdcDest, nWidth, nHeight);
829 hOldBitmap3 = (HBITMAP)NtGdiSelectObject(hDC2, hBitmap3);
830
831 /* 3.2 draw src bitmap and mask */
832 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcDest, nXDest, nYDest, SRCCOPY);
833 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hdcSrc, nXSrc, nYSrc, FRGND_ROP3(dwRop));
834 NtGdiBitBlt(hDC2, 0, 0, nWidth, nHeight, hDCMask, xMask, yMask, SRCAND);
835
836 /* 4. combine two bitmap and copy it to hdcDest */
837 NtGdiBitBlt(hDC1, 0, 0, nWidth, nHeight, hDC2, 0, 0, SRCPAINT);
838 NtGdiBitBlt(hdcDest, nXDest, nYDest, nWidth, nHeight, hDC1, 0, 0, SRCCOPY);
839
840 /* 5. restore all object */
841 NtGdiSelectObject(hDCMask, hOldMaskBitmap);
842 NtGdiSelectObject(hDC1, hOldBitmap2);
843 NtGdiSelectObject(hDC2, hOldBitmap3);
844
845 /* 6. delete all temp object */
846 NtGdiDeleteObject(hBitmap2);
847 NtGdiDeleteObject(hBitmap3);
848
849 NtGdiDeleteDC(hDC1);
850 NtGdiDeleteDC(hDC2);
851 NtGdiDeleteDC(hDCMask);
852
853 return TRUE;
854 }
855
856 BOOL STDCALL
857 NtGdiPlgBlt(
858 HDC hDCDest,
859 CONST POINT *Point,
860 HDC hDCSrc,
861 INT XSrc,
862 INT YSrc,
863 INT Width,
864 INT Height,
865 HBITMAP hMaskBitmap,
866 INT xMask,
867 INT yMask)
868 {
869 UNIMPLEMENTED;
870 return FALSE;
871 }
872
873 LONG STDCALL
874 NtGdiSetBitmapBits(
875 HBITMAP hBitmap,
876 DWORD Bytes,
877 CONST VOID *Bits)
878 {
879 LONG height, ret;
880 PBITMAPOBJ bmp;
881
882 bmp = BITMAPOBJ_LockBitmap(hBitmap);
883 if (bmp == NULL || Bits == NULL)
884 {
885 return 0;
886 }
887
888 if (Bytes < 0)
889 {
890 DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes );
891 Bytes = -Bytes;
892 }
893
894 /* Only get entire lines */
895 height = Bytes / abs(bmp->SurfObj.lDelta);
896 if (height > bmp->SurfObj.sizlBitmap.cy)
897 {
898 height = bmp->SurfObj.sizlBitmap.cy;
899 }
900 Bytes = height * abs(bmp->SurfObj.lDelta);
901 DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
902 hBitmap,
903 Bytes,
904 Bits,
905 bmp->SurfObj.sizlBitmap.cx,
906 bmp->SurfObj.sizlBitmap.cy,
907 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat),
908 height);
909
910 #if 0
911 /* FIXME: call DDI specific function here if available */
912 if(bmp->DDBitmap)
913 {
914 DPRINT ("Calling device specific BitmapBits\n");
915 if (bmp->DDBitmap->funcs->pBitmapBits)
916 {
917 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
918 }
919 else
920 {
921 DPRINT ("BitmapBits == NULL??\n");
922 ret = 0;
923 }
924 }
925 else
926 #endif
927 {
928 memcpy(bmp->SurfObj.pvBits, Bits, Bytes);
929 ret = Bytes;
930 }
931
932 BITMAPOBJ_UnlockBitmap(hBitmap);
933
934 return ret;
935 }
936
937 BOOL STDCALL
938 NtGdiSetBitmapDimensionEx(
939 HBITMAP hBitmap,
940 INT Width,
941 INT Height,
942 LPSIZE Size)
943 {
944 PBITMAPOBJ bmp;
945
946 bmp = BITMAPOBJ_LockBitmap(hBitmap);
947 if (bmp == NULL)
948 {
949 return FALSE;
950 }
951
952 if (Size)
953 {
954 *Size = bmp->dimension;
955 }
956 bmp->dimension.cx = Width;
957 bmp->dimension.cy = Height;
958
959 BITMAPOBJ_UnlockBitmap (hBitmap);
960
961 return TRUE;
962 }
963
964 COLORREF STDCALL
965 NtGdiSetPixel(
966 HDC hDC,
967 INT X,
968 INT Y,
969 COLORREF Color)
970 {
971 COLORREF cr = NtGdiGetPixel(hDC,X,Y);
972 if(cr != CLR_INVALID && NtGdiSetPixelV(hDC,X,Y,Color))
973 {
974 return(cr);
975 }
976 return ((COLORREF) -1);
977 }
978
979 BOOL STDCALL
980 NtGdiSetPixelV(
981 HDC hDC,
982 INT X,
983 INT Y,
984 COLORREF Color)
985 {
986 HBRUSH NewBrush = NtGdiCreateSolidBrush(Color);
987 HGDIOBJ OldBrush;
988
989 if (NewBrush == NULL)
990 return(FALSE);
991 OldBrush = NtGdiSelectObject(hDC, NewBrush);
992 if (OldBrush == NULL)
993 {
994 NtGdiDeleteObject(NewBrush);
995 return(FALSE);
996 }
997 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
998 NtGdiSelectObject(hDC, OldBrush);
999 NtGdiDeleteObject(NewBrush);
1000 return TRUE;
1001 }
1002
1003 BOOL STDCALL
1004 NtGdiStretchBlt(
1005 HDC hDCDest,
1006 INT XOriginDest,
1007 INT YOriginDest,
1008 INT WidthDest,
1009 INT HeightDest,
1010 HDC hDCSrc,
1011 INT XOriginSrc,
1012 INT YOriginSrc,
1013 INT WidthSrc,
1014 INT HeightSrc,
1015 DWORD ROP)
1016 {
1017 PDC DCDest = NULL;
1018 PDC DCSrc = NULL;
1019 BITMAPOBJ *BitmapDest, *BitmapSrc;
1020 RECTL DestRect;
1021 RECTL SourceRect;
1022 BOOL Status;
1023 XLATEOBJ *XlateObj = NULL;
1024 HPALETTE SourcePalette = 0, DestPalette = 0;
1025 PGDIBRUSHOBJ BrushObj;
1026 BOOL UsesSource = ((ROP & 0xCC0000) >> 2) != (ROP & 0x330000);
1027 BOOL UsesPattern = ((ROP & 0xF00000) >> 4) != (ROP & 0x0F0000);
1028
1029 if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc)
1030 {
1031 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1032 return FALSE;
1033 }
1034 DCDest = DC_LockDc(hDCDest);
1035 if (NULL == DCDest)
1036 {
1037 DPRINT1("Invalid destination dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCDest);
1038 SetLastWin32Error(ERROR_INVALID_HANDLE);
1039 return FALSE;
1040 }
1041
1042 if (UsesSource)
1043 {
1044 if (hDCSrc != hDCDest)
1045 {
1046 DCSrc = DC_LockDc(hDCSrc);
1047 if (NULL == DCSrc)
1048 {
1049 DC_UnlockDc(hDCDest);
1050 DPRINT1("Invalid source dc handle (0x%08x) passed to NtGdiStretchBlt\n", hDCSrc);
1051 SetLastWin32Error(ERROR_INVALID_HANDLE);
1052 return FALSE;
1053 }
1054 }
1055 else
1056 {
1057 DCSrc = DCDest;
1058 }
1059 }
1060 else
1061 {
1062 DCSrc = NULL;
1063 }
1064
1065 /* Offset the destination and source by the origin of their DCs. */
1066 XOriginDest += DCDest->w.DCOrgX;
1067 YOriginDest += DCDest->w.DCOrgY;
1068 if (UsesSource)
1069 {
1070 XOriginSrc += DCSrc->w.DCOrgX;
1071 YOriginSrc += DCSrc->w.DCOrgY;
1072 }
1073
1074 DestRect.left = XOriginDest;
1075 DestRect.top = YOriginDest;
1076 DestRect.right = XOriginDest+WidthDest;
1077 DestRect.bottom = YOriginDest+HeightDest;
1078
1079 SourceRect.left = XOriginSrc;
1080 SourceRect.top = YOriginSrc;
1081 SourceRect.right = XOriginSrc+WidthSrc;
1082 SourceRect.bottom = YOriginSrc+HeightSrc;
1083
1084 /* Determine surfaces to be used in the bitblt */
1085 BitmapDest = BITMAPOBJ_LockBitmap(DCDest->w.hBitmap);
1086 if (UsesSource)
1087 {
1088 if (DCSrc->w.hBitmap == DCDest->w.hBitmap)
1089 BitmapSrc = BitmapDest;
1090 else
1091 BitmapSrc = BITMAPOBJ_LockBitmap(DCSrc->w.hBitmap);
1092 }
1093 else
1094 {
1095 BitmapSrc = NULL;
1096 }
1097
1098 if ( UsesSource )
1099 {
1100 int sw = BitmapSrc->SurfObj.sizlBitmap.cx;
1101 int sh = BitmapSrc->SurfObj.sizlBitmap.cy;
1102 if ( SourceRect.left < 0 )
1103 {
1104 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right)/abs(SourceRect.right-SourceRect.left);
1105 SourceRect.left = 0;
1106 }
1107 if ( SourceRect.top < 0 )
1108 {
1109 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom)/abs(SourceRect.bottom-SourceRect.top);
1110 SourceRect.top = 0;
1111 }
1112 if ( SourceRect.right < -1 )
1113 {
1114 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * (-1-SourceRect.left)/abs(SourceRect.right-SourceRect.left);
1115 SourceRect.right = -1;
1116 }
1117 if ( SourceRect.bottom < -1 )
1118 {
1119 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * (-1-SourceRect.top)/abs(SourceRect.bottom-SourceRect.top);
1120 SourceRect.bottom = -1;
1121 }
1122 if ( SourceRect.right > sw )
1123 {
1124 DestRect.right = DestRect.left + (DestRect.right-DestRect.left) * abs(sw-SourceRect.left) / abs(SourceRect.right-SourceRect.left);
1125 SourceRect.right = sw;
1126 }
1127 if ( SourceRect.bottom > sh )
1128 {
1129 DestRect.bottom = DestRect.top + (DestRect.bottom-DestRect.top) * abs(sh-SourceRect.top) / abs(SourceRect.bottom-SourceRect.top);
1130 SourceRect.bottom = sh;
1131 }
1132 sw--;
1133 sh--;
1134 if ( SourceRect.left > sw )
1135 {
1136 DestRect.left = DestRect.right - (DestRect.right-DestRect.left) * (SourceRect.right-sw) / abs(SourceRect.right-SourceRect.left);
1137 SourceRect.left = 0;
1138 }
1139 if ( SourceRect.top > sh )
1140 {
1141 DestRect.top = DestRect.bottom - (DestRect.bottom-DestRect.top) * (SourceRect.bottom-sh) / abs(SourceRect.bottom-SourceRect.top);
1142 SourceRect.top = 0;
1143 }
1144 if (0 == (DestRect.right-DestRect.left) || 0 == (DestRect.bottom-DestRect.top) || 0 == (SourceRect.right-SourceRect.left) || 0 == (SourceRect.bottom-SourceRect.top))
1145 {
1146 SetLastWin32Error(ERROR_INVALID_PARAMETER);
1147 Status = FALSE;
1148 goto failed;
1149 }
1150 }
1151
1152 if (UsesPattern)
1153 {
1154 BrushObj = BRUSHOBJ_LockBrush(DCDest->w.hBrush);
1155 if (NULL == BrushObj)
1156 {
1157 if (UsesSource && hDCSrc != hDCDest)
1158 {
1159 DC_UnlockDc(hDCSrc);
1160 }
1161 DC_UnlockDc(hDCDest);
1162 SetLastWin32Error(ERROR_INVALID_HANDLE);
1163 return FALSE;
1164 }
1165 }
1166 else
1167 {
1168 BrushObj = NULL;
1169 }
1170
1171 /* Create the XLATEOBJ. */
1172 if (UsesSource)
1173 {
1174 if (DCDest->w.hPalette != 0)
1175 DestPalette = DCDest->w.hPalette;
1176
1177 if (DCSrc->w.hPalette != 0)
1178 SourcePalette = DCSrc->w.hPalette;
1179
1180 /* FIXME: Use the same logic for create XLATEOBJ as in NtGdiBitBlt. */
1181 XlateObj = (XLATEOBJ*)IntEngCreateXlate(0, 0, DestPalette, SourcePalette);
1182 if (NULL == XlateObj)
1183 {
1184 if (UsesSource && hDCSrc != hDCDest)
1185 {
1186 DC_UnlockDc(hDCSrc);
1187 }
1188 DC_UnlockDc(hDCDest);
1189 SetLastWin32Error(ERROR_NO_SYSTEM_RESOURCES);
1190 return FALSE;
1191 }
1192 }
1193
1194 /* Perform the bitblt operation */
1195 Status = IntEngStretchBlt(BitmapDest, BitmapSrc, NULL, DCDest->CombinedClip,
1196 XlateObj, &DestRect, &SourceRect, NULL, NULL, NULL, COLORONCOLOR);
1197
1198 if (UsesSource)
1199 EngDeleteXlate(XlateObj);
1200 if (UsesPattern)
1201 {
1202 BRUSHOBJ_UnlockBrush(DCDest->w.hBrush);
1203 }
1204 failed:
1205 if (UsesSource && DCSrc->w.hBitmap != DCDest->w.hBitmap)
1206 {
1207 BITMAPOBJ_UnlockBitmap(DCSrc->w.hBitmap);
1208 }
1209 BITMAPOBJ_UnlockBitmap(DCDest->w.hBitmap);
1210 if (UsesSource && hDCSrc != hDCDest)
1211 {
1212 DC_UnlockDc(hDCSrc);
1213 }
1214 DC_UnlockDc(hDCDest);
1215
1216 return Status;
1217 }
1218
1219 /* Internal Functions */
1220
1221 INT FASTCALL
1222 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
1223 {
1224 #if 0
1225 switch(bpp)
1226 {
1227 case 1:
1228 return 2 * ((bmWidth+15) >> 4);
1229
1230 case 24:
1231 bmWidth *= 3; /* fall through */
1232 case 8:
1233 return bmWidth + (bmWidth & 1);
1234
1235 case 32:
1236 return bmWidth * 4;
1237
1238 case 16:
1239 case 15:
1240 return bmWidth * 2;
1241
1242 case 4:
1243 return 2 * ((bmWidth+3) >> 2);
1244
1245 default:
1246 DPRINT ("stub");
1247 }
1248
1249 return -1;
1250 #endif
1251
1252 return ((bmWidth * bpp + 15) & ~15) >> 3;
1253 }
1254
1255 HBITMAP FASTCALL
1256 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
1257 {
1258 HBITMAP res;
1259 BITMAP bm;
1260 BITMAPOBJ *Bitmap;
1261
1262 if (hBitmap == NULL)
1263 return 0;
1264
1265 Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
1266 if (Bitmap == NULL)
1267 return 0;
1268
1269 BITMAP_GetObject(Bitmap, sizeof(BITMAP), &bm);
1270 bm.bmBits = NULL;
1271 if (Bitmap->SurfObj.lDelta >= 0)
1272 bm.bmHeight = -bm.bmHeight;
1273
1274 res = NtGdiCreateBitmapIndirect(&bm);
1275 if(res)
1276 {
1277 char *buf;
1278
1279 buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight), TAG_BITMAP);
1280 NtGdiGetBitmapBits (hBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1281 NtGdiSetBitmapBits (res, bm.bmWidthBytes * abs(bm.bmHeight), buf);
1282 ExFreePool (buf);
1283 }
1284
1285 GDIOBJ_UnlockObj(hBitmap);
1286
1287 return res;
1288 }
1289
1290 INT STDCALL
1291 BITMAP_GetObject(BITMAPOBJ * bmp, INT count, LPVOID buffer)
1292 {
1293 if(bmp->dib)
1294 {
1295 if(count < (INT) sizeof(DIBSECTION))
1296 {
1297 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
1298 }
1299 else
1300 {
1301 if (count > (INT) sizeof(DIBSECTION)) count = sizeof(DIBSECTION);
1302 }
1303 memcpy(buffer, bmp->dib, count);
1304 return count;
1305 }
1306 else
1307 {
1308 BITMAP Bitmap;
1309 if (count > (INT) sizeof(BITMAP)) count = sizeof(BITMAP);
1310 Bitmap.bmType = 0;
1311 Bitmap.bmWidth = bmp->SurfObj.sizlBitmap.cx;
1312 Bitmap.bmHeight = bmp->SurfObj.sizlBitmap.cy;
1313 Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta);
1314 Bitmap.bmPlanes = 1;
1315 Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat);
1316 Bitmap.bmBits = bmp->SurfObj.pvBits;
1317 memcpy(buffer, &Bitmap, count);
1318 return count;
1319 }
1320 }
1321 /* EOF */