- Merge aicom-network-fixes up to r36740
[reactos.git] / reactos / subsystems / win32 / 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
21 #include <w32k.h>
22
23 #define NDEBUG
24 #include <debug.h>
25
26 #define IN_RECT(r,x,y) \
27 ( \
28 (x) >= (r).left && \
29 (y) >= (r).top && \
30 (x) < (r).right && \
31 (y) < (r).bottom \
32 )
33
34 HBITMAP STDCALL
35 IntGdiCreateBitmap(
36 INT Width,
37 INT Height,
38 UINT Planes,
39 UINT BitsPixel,
40 IN OPTIONAL LPBYTE pBits)
41 {
42 HBITMAP hBitmap;
43 SIZEL Size;
44 LONG WidthBytes;
45
46 /* NOTE: Windows also doesn't store nr. of planes separately! */
47 BitsPixel = BITMAPOBJ_GetRealBitsPixel(BitsPixel * Planes);
48
49 /* Check parameters */
50 if (BitsPixel == 0 || Width <= 0 || Width >= 0x8000000 || Height == 0)
51 {
52 DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", Width, Height, BitsPixel);
53 SetLastWin32Error(ERROR_INVALID_PARAMETER);
54 return 0;
55 }
56
57 WidthBytes = BITMAPOBJ_GetWidthBytes(Width, BitsPixel);
58
59 Size.cx = Width;
60 Size.cy = abs(Height);
61
62 /* Make sure that cjBits will not overflow */
63 if ((ULONGLONG)WidthBytes * Size.cy >= 0x100000000ULL)
64 {
65 DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", Width, Height, BitsPixel);
66 SetLastWin32Error(ERROR_INVALID_PARAMETER);
67 return 0;
68 }
69
70 /* Create the bitmap object. */
71 hBitmap = IntCreateBitmap(Size, WidthBytes,
72 BitmapFormat(BitsPixel, BI_RGB),
73 (Height < 0 ? BMF_TOPDOWN : 0) |
74 (NULL == pBits ? 0 : BMF_NOZEROINIT), NULL);
75 if (!hBitmap)
76 {
77 DPRINT("IntGdiCreateBitmap: returned 0\n");
78 return 0;
79 }
80
81 PBITMAPOBJ bmp = BITMAPOBJ_LockBitmap( hBitmap );
82 if (bmp == NULL)
83 {
84 NtGdiDeleteObject(hBitmap);
85 return NULL;
86 }
87
88 bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
89 bmp->hDC = NULL; // Fixme
90
91 if (NULL != pBits)
92 {
93 IntSetBitmapBits(bmp, bmp->SurfObj.cjBits, pBits);
94 }
95
96 BITMAPOBJ_UnlockBitmap( bmp );
97
98 DPRINT("IntGdiCreateBitmap : %dx%d, %d BPP colors, topdown %d, returning %08x\n",
99 Size.cx, Size.cy, BitsPixel, (Height < 0 ? 1 : 0), hBitmap);
100
101 return hBitmap;
102 }
103
104
105 HBITMAP STDCALL
106 NtGdiCreateBitmap(
107 INT Width,
108 INT Height,
109 UINT Planes,
110 UINT BitsPixel,
111 IN OPTIONAL LPBYTE pUnsafeBits)
112 {
113 HBITMAP hBitmap;
114
115 _SEH_TRY
116 {
117 if (pUnsafeBits)
118 {
119 UINT cjBits = BITMAPOBJ_GetWidthBytes(Width, BitsPixel) * abs(Height);
120 ProbeForRead(pUnsafeBits, cjBits, 1);
121 }
122
123 hBitmap = IntGdiCreateBitmap(Width, Height, Planes, BitsPixel, pUnsafeBits);
124
125 }
126 _SEH_HANDLE
127 {
128 hBitmap = 0;
129 }
130 _SEH_END
131
132 return hBitmap;
133 }
134
135 BOOL INTERNAL_CALL
136 BITMAP_Cleanup(PVOID ObjectBody)
137 {
138 PBITMAPOBJ pBmp = (PBITMAPOBJ)ObjectBody;
139 if (pBmp->SurfObj.pvBits != NULL &&
140 (pBmp->flFlags & BITMAPOBJ_IS_APIBITMAP))
141 {
142 if (pBmp->dib == NULL)
143 {
144 ExFreePool(pBmp->SurfObj.pvBits);
145 }
146 else
147 {
148 EngFreeUserMem(pBmp->SurfObj.pvBits);
149 }
150 if (pBmp->hDIBPalette != NULL)
151 {
152 NtGdiDeleteObject(pBmp->hDIBPalette);
153 }
154 }
155
156 if (NULL != pBmp->BitsLock)
157 {
158 ExFreePoolWithTag(pBmp->BitsLock, TAG_BITMAPOBJ);
159 pBmp->BitsLock = NULL;
160 }
161
162 if (pBmp->dib)
163 ExFreePoolWithTag(pBmp->dib, TAG_DIB);
164
165 return TRUE;
166 }
167
168
169 HBITMAP FASTCALL
170 IntCreateCompatibleBitmap(
171 PDC Dc,
172 INT Width,
173 INT Height)
174 {
175 HBITMAP Bmp;
176
177 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */
178 if (0 == Width || 0 == Height)
179 {
180 Bmp = NtGdiGetStockObject(DEFAULT_BITMAP);
181 }
182 else
183 {
184 Bmp = IntGdiCreateBitmap(abs(Width), abs(Height), 1, Dc->w.bitsPerPixel, NULL);
185 }
186
187 return Bmp;
188 }
189
190 HBITMAP STDCALL
191 NtGdiCreateCompatibleBitmap(
192 HDC hDC,
193 INT Width,
194 INT Height)
195 {
196 HBITMAP Bmp;
197 PDC Dc;
198
199 Dc = DC_LockDc(hDC);
200
201 DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, Dc->w.bitsPerPixel);
202
203 if (NULL == Dc)
204 {
205 SetLastWin32Error(ERROR_INVALID_HANDLE);
206 return NULL;
207 }
208
209 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height);
210
211 DPRINT ("\t\t%04x\n", Bmp);
212 DC_UnlockDc(Dc);
213 return Bmp;
214 }
215
216 BOOL STDCALL
217 NtGdiGetBitmapDimension(
218 HBITMAP hBitmap,
219 LPSIZE Dimension)
220 {
221 PBITMAPOBJ bmp;
222 BOOL Ret = TRUE;
223
224 if (hBitmap == NULL)
225 return FALSE;
226
227 bmp = BITMAPOBJ_LockBitmap(hBitmap);
228 if (bmp == NULL)
229 {
230 SetLastWin32Error(ERROR_INVALID_HANDLE);
231 return FALSE;
232 }
233
234 _SEH_TRY
235 {
236 ProbeForWrite(Dimension, sizeof(SIZE), 1);
237 *Dimension = bmp->dimension;
238 }
239 _SEH_HANDLE
240 {
241 Ret = FALSE;
242 }
243 _SEH_END
244
245 BITMAPOBJ_UnlockBitmap(bmp);
246
247 return Ret;
248 }
249
250 COLORREF STDCALL
251 NtGdiGetPixel(HDC hDC, INT XPos, INT YPos)
252 {
253 PDC dc = NULL;
254 COLORREF Result = (COLORREF)CLR_INVALID; // default to failure
255 BOOL bInRect = FALSE;
256 BITMAPOBJ *BitmapObject;
257 SURFOBJ *SurfaceObject;
258 HPALETTE Pal = 0;
259 XLATEOBJ *XlateObj;
260 HBITMAP hBmpTmp;
261
262 dc = DC_LockDc (hDC);
263
264 if ( !dc )
265 {
266 SetLastWin32Error(ERROR_INVALID_HANDLE);
267 return Result;
268 }
269 if (dc->DC_Type == DC_TYPE_INFO)
270 {
271 DC_UnlockDc(dc);
272 return Result;
273 }
274 XPos += dc->ptlDCOrig.x;
275 YPos += dc->ptlDCOrig.y;
276 if ( IN_RECT(dc->CombinedClip->rclBounds,XPos,YPos) )
277 {
278 bInRect = TRUE;
279 BitmapObject = BITMAPOBJ_LockBitmap(dc->w.hBitmap);
280 SurfaceObject = &BitmapObject->SurfObj;
281 if ( BitmapObject )
282 {
283 Pal = BitmapObject->hDIBPalette;
284 if (!Pal) Pal = pPrimarySurface->DevInfo.hpalDefault;
285
286 /* FIXME: Verify if it shouldn't be PAL_BGR! */
287 XlateObj = (XLATEOBJ*)IntEngCreateXlate ( PAL_RGB, 0, NULL, Pal );
288 if ( XlateObj )
289 {
290 // check if this DC has a DIB behind it...
291 if ( SurfaceObject->pvScan0 ) // STYPE_BITMAP == SurfaceObject->iType
292 {
293 ASSERT ( SurfaceObject->lDelta );
294 Result = XLATEOBJ_iXlate(XlateObj,
295 DibFunctionsForBitmapFormat[SurfaceObject->iBitmapFormat].DIB_GetPixel ( SurfaceObject, XPos, YPos ) );
296 }
297 EngDeleteXlate(XlateObj);
298 }
299 BITMAPOBJ_UnlockBitmap(BitmapObject);
300 }
301 }
302 DC_UnlockDc(dc);
303
304 // if Result is still CLR_INVALID, then the "quick" method above didn't work
305 if ( bInRect && Result == CLR_INVALID )
306 {
307 // FIXME: create a 1x1 32BPP DIB, and blit to it
308 HDC hDCTmp = NtGdiCreateCompatibleDC(hDC);
309 if ( hDCTmp )
310 {
311 static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 };
312 BITMAPINFO bi;
313 RtlMoveMemory ( &(bi.bmiHeader), &bih, sizeof(bih) );
314 hBmpTmp = NtGdiCreateDIBitmapInternal(hDC,
315 bi.bmiHeader.biWidth,
316 bi.bmiHeader.biHeight,
317 0,
318 NULL,
319 &bi,
320 DIB_RGB_COLORS,
321 bi.bmiHeader.biBitCount,
322 bi.bmiHeader.biSizeImage,
323 0,
324 0);
325
326 //HBITMAP hBmpTmp = IntGdiCreateBitmap ( 1, 1, 1, 32, NULL);
327 if ( hBmpTmp )
328 {
329 HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap ( hDCTmp, hBmpTmp );
330 if ( hBmpOld )
331 {
332 PBITMAPOBJ bmpobj;
333
334 NtGdiBitBlt ( hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0 );
335 NtGdiSelectBitmap ( hDCTmp, hBmpOld );
336
337 // our bitmap is no longer selected, so we can access it's stuff...
338 bmpobj = BITMAPOBJ_LockBitmap ( hBmpTmp );
339 if ( bmpobj )
340 {
341 Result = *(COLORREF*)bmpobj->SurfObj.pvScan0;
342 BITMAPOBJ_UnlockBitmap ( bmpobj );
343 }
344 }
345 NtGdiDeleteObject ( hBmpTmp );
346 }
347 NtGdiDeleteObjectApp ( hDCTmp );
348 }
349 }
350
351 return Result;
352 }
353
354
355 LONG STDCALL
356 IntGetBitmapBits(
357 PBITMAPOBJ bmp,
358 DWORD Bytes,
359 OUT PBYTE Bits)
360 {
361 LONG ret;
362
363 ASSERT(Bits);
364
365 /* Don't copy more bytes than the buffer has */
366 Bytes = min(Bytes, bmp->SurfObj.cjBits);
367
368 #if 0
369 /* FIXME: Call DDI CopyBits here if available */
370 if(bmp->DDBitmap)
371 {
372 DPRINT("Calling device specific BitmapBits\n");
373 if(bmp->DDBitmap->funcs->pBitmapBits)
374 {
375 ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count, DDB_GET);
376 }
377 else
378 {
379 ERR_(bitmap)("BitmapBits == NULL??\n");
380 ret = 0;
381 }
382 }
383 else
384 #endif
385 {
386 RtlCopyMemory(Bits, bmp->SurfObj.pvBits, Bytes);
387 ret = Bytes;
388 }
389 return ret;
390 }
391
392 LONG STDCALL
393 NtGdiGetBitmapBits(HBITMAP hBitmap,
394 ULONG Bytes,
395 OUT OPTIONAL PBYTE pUnsafeBits)
396 {
397 PBITMAPOBJ bmp;
398 LONG ret;
399
400 if (pUnsafeBits != NULL && Bytes == 0)
401 {
402 return 0;
403 }
404
405 bmp = BITMAPOBJ_LockBitmap (hBitmap);
406 if (!bmp)
407 {
408 SetLastWin32Error(ERROR_INVALID_HANDLE);
409 return 0;
410 }
411
412 /* If the bits vector is null, the function should return the read size */
413 if (pUnsafeBits == NULL)
414 {
415 ret = bmp->SurfObj.cjBits;
416 BITMAPOBJ_UnlockBitmap (bmp);
417 return ret;
418 }
419
420 /* Don't copy more bytes than the buffer has */
421 Bytes = min(Bytes, bmp->SurfObj.cjBits);
422
423 _SEH_TRY
424 {
425 ProbeForWrite(pUnsafeBits, Bytes, 1);
426 ret = IntGetBitmapBits(bmp, Bytes, pUnsafeBits);
427 }
428 _SEH_HANDLE
429 {
430 ret = 0;
431 }
432 _SEH_END
433
434 BITMAPOBJ_UnlockBitmap (bmp);
435
436 return ret;
437 }
438
439
440 LONG STDCALL
441 IntSetBitmapBits(
442 PBITMAPOBJ bmp,
443 DWORD Bytes,
444 IN PBYTE Bits)
445 {
446 LONG ret;
447
448 /* Don't copy more bytes than the buffer has */
449 Bytes = min(Bytes, bmp->SurfObj.cjBits);
450
451 #if 0
452 /* FIXME: call DDI specific function here if available */
453 if(bmp->DDBitmap)
454 {
455 DPRINT ("Calling device specific BitmapBits\n");
456 if (bmp->DDBitmap->funcs->pBitmapBits)
457 {
458 ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes, DDB_SET);
459 }
460 else
461 {
462 DPRINT ("BitmapBits == NULL??\n");
463 ret = 0;
464 }
465 }
466 else
467 #endif
468 {
469 RtlCopyMemory(bmp->SurfObj.pvBits, Bits, Bytes);
470 ret = Bytes;
471 }
472
473 return ret;
474 }
475
476
477 LONG STDCALL
478 NtGdiSetBitmapBits(
479 HBITMAP hBitmap,
480 DWORD Bytes,
481 IN PBYTE pUnsafeBits)
482 {
483 LONG ret;
484 PBITMAPOBJ bmp;
485
486 if (pUnsafeBits == NULL || Bytes == 0)
487 {
488 return 0;
489 }
490
491 bmp = BITMAPOBJ_LockBitmap(hBitmap);
492 if (bmp == NULL)
493 {
494 SetLastWin32Error(ERROR_INVALID_HANDLE);
495 return 0;
496 }
497
498 _SEH_TRY
499 {
500 ProbeForRead(pUnsafeBits, Bytes, 1);
501 ret = IntSetBitmapBits(bmp, Bytes, pUnsafeBits);
502 }
503 _SEH_HANDLE
504 {
505 ret = 0;
506 }
507 _SEH_END
508
509 BITMAPOBJ_UnlockBitmap(bmp);
510
511 return ret;
512 }
513
514 BOOL STDCALL
515 NtGdiSetBitmapDimension(
516 HBITMAP hBitmap,
517 INT Width,
518 INT Height,
519 LPSIZE Size)
520 {
521 PBITMAPOBJ bmp;
522 BOOL Ret = TRUE;
523
524 if (hBitmap == NULL)
525 return FALSE;
526
527 bmp = BITMAPOBJ_LockBitmap(hBitmap);
528 if (bmp == NULL)
529 {
530 SetLastWin32Error(ERROR_INVALID_HANDLE);
531 return FALSE;
532 }
533
534 if (Size)
535 {
536 _SEH_TRY
537 {
538 ProbeForWrite(Size, sizeof(SIZE), 1);
539 *Size = bmp->dimension;
540 }
541 _SEH_HANDLE
542 {
543 Ret = FALSE;
544 }
545 _SEH_END
546 }
547
548 /* The dimension is changed even if writing the old value failed */
549 bmp->dimension.cx = Width;
550 bmp->dimension.cy = Height;
551
552 BITMAPOBJ_UnlockBitmap (bmp);
553
554 return Ret;
555 }
556
557 BOOL STDCALL
558 GdiSetPixelV(
559 HDC hDC,
560 INT X,
561 INT Y,
562 COLORREF Color)
563 {
564 HBRUSH NewBrush = NtGdiCreateSolidBrush(Color, NULL);
565 HGDIOBJ OldBrush;
566
567 if (NewBrush == NULL)
568 return(FALSE);
569 OldBrush = NtGdiSelectBrush(hDC, NewBrush);
570 if (OldBrush == NULL)
571 {
572 NtGdiDeleteObject(NewBrush);
573 return(FALSE);
574 }
575 NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY);
576 NtGdiSelectBrush(hDC, OldBrush);
577 NtGdiDeleteObject(NewBrush);
578 return TRUE;
579 }
580
581 COLORREF STDCALL
582 NtGdiSetPixel(
583 HDC hDC,
584 INT X,
585 INT Y,
586 COLORREF Color)
587 {
588 DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
589
590 if (GdiSetPixelV(hDC,X,Y,Color))
591 {
592 Color = NtGdiGetPixel(hDC,X,Y);
593 DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
594 return Color;
595 }
596
597 Color = ((COLORREF) CLR_INVALID);
598 DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n",X,Y,Color);
599 return Color;
600 }
601
602
603 /* Internal Functions */
604
605 UINT FASTCALL
606 BITMAPOBJ_GetRealBitsPixel(UINT nBitsPixel)
607 {
608 if (nBitsPixel <= 1)
609 return 1;
610 if (nBitsPixel <= 4)
611 return 4;
612 if (nBitsPixel <= 8)
613 return 8;
614 if (nBitsPixel <= 16)
615 return 16;
616 if (nBitsPixel <= 24)
617 return 24;
618 if (nBitsPixel <= 32)
619 return 32;
620
621 return 0;
622 }
623
624 INT FASTCALL
625 BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp)
626 {
627 #if 0
628 switch(bpp)
629 {
630 case 1:
631 return 2 * ((bmWidth+15) >> 4);
632
633 case 24:
634 bmWidth *= 3; /* fall through */
635 case 8:
636 return bmWidth + (bmWidth & 1);
637
638 case 32:
639 return bmWidth * 4;
640
641 case 16:
642 case 15:
643 return bmWidth * 2;
644
645 case 4:
646 return 2 * ((bmWidth+3) >> 2);
647
648 default:
649 DPRINT ("stub");
650 }
651
652 return -1;
653 #endif
654
655 return ((bmWidth * bpp + 15) & ~15) >> 3;
656 }
657
658 HBITMAP FASTCALL
659 BITMAPOBJ_CopyBitmap(HBITMAP hBitmap)
660 {
661 HBITMAP res;
662 BITMAP bm;
663 BITMAPOBJ *Bitmap, *resBitmap;
664 SIZEL Size;
665
666 if (hBitmap == NULL)
667 {
668 return 0;
669 }
670
671 Bitmap = GDIOBJ_LockObj(hBitmap, GDI_OBJECT_TYPE_BITMAP);
672 if (Bitmap == NULL)
673 {
674 return 0;
675 }
676
677 BITMAP_GetObject(Bitmap, sizeof(BITMAP), &bm);
678 bm.bmBits = NULL;
679 if (Bitmap->SurfObj.lDelta >= 0)
680 bm.bmHeight = -bm.bmHeight;
681
682 Size.cx = abs(bm.bmWidth);
683 Size.cy = abs(bm.bmHeight);
684 res = IntCreateBitmap(Size,
685 bm.bmWidthBytes,
686 BitmapFormat(bm.bmBitsPixel * bm.bmPlanes, BI_RGB),
687 (bm.bmHeight < 0 ? BMF_TOPDOWN : 0) | BMF_NOZEROINIT,
688 NULL);
689
690 if(res)
691 {
692 PBYTE buf;
693
694 resBitmap = GDIOBJ_LockObj(res, GDI_OBJECT_TYPE_BITMAP);
695 if (resBitmap)
696 {
697 buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight), TAG_BITMAP);
698 if (buf == NULL)
699 {
700 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
701 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
702 NtGdiDeleteObject(res);
703 return 0;
704 }
705 IntGetBitmapBits (Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
706 IntSetBitmapBits (resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
707 ExFreePool (buf);
708 resBitmap->flFlags = Bitmap->flFlags;
709 GDIOBJ_UnlockObjByPtr((POBJ)resBitmap);
710 }
711 else
712 {
713 NtGdiDeleteObject(res);
714 res = NULL;
715 }
716 }
717
718 GDIOBJ_UnlockObjByPtr((POBJ)Bitmap);
719
720 return res;
721 }
722
723 INT STDCALL
724 BITMAP_GetObject(BITMAPOBJ * bmp, INT Count, LPVOID buffer)
725 {
726 if ((UINT)Count < sizeof(BITMAP)) return 0;
727
728 if(bmp->dib)
729 {
730 if((UINT)Count < sizeof(DIBSECTION))
731 {
732 Count = sizeof(BITMAP);
733 }
734 else
735 {
736 Count = sizeof(DIBSECTION);
737 }
738 if (buffer)
739 {
740 memcpy(buffer, bmp->dib, Count);
741 }
742 return Count;
743 }
744 else
745 {
746 Count = sizeof(BITMAP);
747 if (buffer)
748 {
749 BITMAP Bitmap;
750
751 Count = sizeof(BITMAP);
752 Bitmap.bmType = 0;
753 Bitmap.bmWidth = bmp->SurfObj.sizlBitmap.cx;
754 Bitmap.bmHeight = bmp->SurfObj.sizlBitmap.cy;
755 Bitmap.bmWidthBytes = abs(bmp->SurfObj.lDelta);
756 Bitmap.bmPlanes = 1;
757 Bitmap.bmBitsPixel = BitsPerFormat(bmp->SurfObj.iBitmapFormat);
758 Bitmap.bmBits = NULL; /* not set according to wine test, confirmed in win2k */
759 memcpy(buffer, &Bitmap, Count);
760 }
761 return Count;
762 }
763 }
764
765 /*
766 * @implemented
767 */
768 HDC
769 APIENTRY
770 NtGdiGetDCforBitmap(
771 IN HBITMAP hsurf)
772 {
773 HDC hDC = NULL;
774 PBITMAPOBJ bmp = BITMAPOBJ_LockBitmap( hsurf );
775 if (bmp)
776 {
777 hDC = bmp->hDC;
778 BITMAPOBJ_UnlockBitmap( bmp );
779 }
780 return hDC;
781 }
782
783
784 /* EOF */