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