[GDI32]
[reactos.git] / reactos / dll / win32 / gdi32 / objects / bitmap.c
1 #include "precomp.h"
2
3 #define NDEBUG
4 #include <debug.h>
5
6 /*
7 * DIB_BitmapInfoSize
8 *
9 * Return the size of the bitmap info structure including color table.
10 * 11/16/1999 (RJJ) lifted from wine
11 */
12
13 INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
14 {
15 unsigned int colors, size, masks = 0;
16
17 if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
18 {
19 const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
20 colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
21 return sizeof(BITMAPCOREHEADER) + colors *
22 ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
23 }
24 else /* assume BITMAPINFOHEADER */
25 {
26 colors = info->bmiHeader.biClrUsed;
27 if (colors > 256) colors = 256;
28 if (!colors && (info->bmiHeader.biBitCount <= 8))
29 colors = 1 << info->bmiHeader.biBitCount;
30 if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
31 size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
32 return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
33 }
34 }
35
36 /*
37 * Return the full scan size for a bitmap.
38 *
39 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
40 */
41 UINT
42 FASTCALL
43 DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines )
44 {
45 UINT MaxBits = 0;
46
47 if (!Info) return 0;
48
49 if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
50 {
51 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
52 MaxBits = Core->bcBitCount * Core->bcPlanes * Core->bcWidth;
53 }
54 else /* assume BITMAPINFOHEADER */
55 {
56 if ((Info->bmiHeader.biCompression) && (Info->bmiHeader.biCompression != BI_BITFIELDS))
57 return Info->bmiHeader.biSizeImage;
58 // Planes are over looked by Yuan. I guess assumed always 1.
59 MaxBits = Info->bmiHeader.biBitCount * Info->bmiHeader.biPlanes * Info->bmiHeader.biWidth;
60 }
61 MaxBits = ((MaxBits + 31) & ~31 ) / 8; // From Yuan, ScanLineSize = (Width * bitcount + 31)/32
62 return (MaxBits * ScanLines); // ret the full Size.
63 }
64
65 UINT
66 FASTCALL
67 DIB_BitmapBitsSize( CONST BITMAPINFO* Info )
68 {
69 UINT Ret;
70
71 if (!Info) return 0;
72
73 if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
74 {
75 PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
76 Ret = Core->bcHeight *
77 ((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8;
78 }
79 else /* assume BITMAPINFOHEADER */
80 {
81 if ((Info->bmiHeader.biCompression) &&
82 (Info->bmiHeader.biCompression != BI_BITFIELDS))
83 return Info->bmiHeader.biSizeImage;
84 // Make Height positive always....
85 Ret = abs(Info->bmiHeader.biHeight) *
86 ((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
87 }
88 return Ret;
89 }
90
91
92 /*
93 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
94 * from file dib.c from gdi32.dll or orginal version
95 * did not calc the info right for some headers.
96 */
97 INT
98 WINAPI
99 DIB_GetBitmapInfo(const BITMAPINFOHEADER *header,
100 PLONG width,
101 PLONG height,
102 PWORD planes,
103 PWORD bpp,
104 PLONG compr,
105 PLONG size )
106 {
107 if (header->biSize == sizeof(BITMAPCOREHEADER))
108 {
109 BITMAPCOREHEADER *core = (BITMAPCOREHEADER *)header;
110 *width = core->bcWidth;
111 *height = core->bcHeight;
112 *planes = core->bcPlanes;
113 *bpp = core->bcBitCount;
114 *compr = 0;
115 *size = 0;
116 return 0;
117 }
118
119 if (header->biSize == sizeof(BITMAPINFOHEADER))
120 {
121 *width = header->biWidth;
122 *height = header->biHeight;
123 *planes = header->biPlanes;
124 *bpp = header->biBitCount;
125 *compr = header->biCompression;
126 *size = header->biSizeImage;
127 return 1;
128 }
129
130 if (header->biSize == sizeof(BITMAPV4HEADER))
131 {
132 BITMAPV4HEADER *v4hdr = (BITMAPV4HEADER *)header;
133 *width = v4hdr->bV4Width;
134 *height = v4hdr->bV4Height;
135 *planes = v4hdr->bV4Planes;
136 *bpp = v4hdr->bV4BitCount;
137 *compr = v4hdr->bV4V4Compression;
138 *size = v4hdr->bV4SizeImage;
139 return 4;
140 }
141
142 if (header->biSize == sizeof(BITMAPV5HEADER))
143 {
144 BITMAPV5HEADER *v5hdr = (BITMAPV5HEADER *)header;
145 *width = v5hdr->bV5Width;
146 *height = v5hdr->bV5Height;
147 *planes = v5hdr->bV5Planes;
148 *bpp = v5hdr->bV5BitCount;
149 *compr = v5hdr->bV5Compression;
150 *size = v5hdr->bV5SizeImage;
151 return 5;
152 }
153 DPRINT("(%ld): wrong size for header\n", header->biSize );
154 return -1;
155 }
156
157 /*
158 * @implemented
159 */
160 int
161 WINAPI
162 GdiGetBitmapBitsSize(BITMAPINFO *lpbmi)
163 {
164 int retSize;
165
166 if (lpbmi->bmiHeader.biSize == FIELD_OFFSET(BITMAPINFOHEADER, biPlanes))
167 {
168 /* Calc the bits Size and align it*/
169 retSize = HIWORD(lpbmi->bmiHeader.biWidth) * ((LOWORD(lpbmi->bmiHeader.biWidth) *
170 LOWORD(lpbmi->bmiHeader.biHeight) * HIWORD(lpbmi->bmiHeader.biHeight) + 31)
171 & -32) / 8;
172 }
173 else
174 {
175 if ( (lpbmi->bmiHeader.biCompression == BI_BITFIELDS) ||
176 (lpbmi->bmiHeader.biCompression == BI_RGB))
177 {
178 if (lpbmi->bmiHeader.biHeight >=0 )
179 {
180 /* Calc the bits Size and align it*/
181 retSize = lpbmi->bmiHeader.biHeight * ((lpbmi->bmiHeader.biWidth *
182 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
183 }
184 else
185 {
186 /* Make height postiive if it negitve then calc the bits Size and align it*/
187 retSize = (-lpbmi->bmiHeader.biHeight) * ((lpbmi->bmiHeader.biWidth *
188 lpbmi->bmiHeader.biPlanes * lpbmi->bmiHeader.biBitCount + 31) & -32) / 8;
189 }
190 }
191 else
192 {
193 retSize = lpbmi->bmiHeader.biSizeImage;
194 }
195 }
196 return retSize;
197 }
198
199 /*
200 * @implemented
201 */
202 HBITMAP WINAPI
203 CreateDIBSection(
204 HDC hDC,
205 CONST BITMAPINFO *BitmapInfo,
206 UINT Usage,
207 VOID **Bits,
208 HANDLE hSection,
209 DWORD dwOffset)
210 {
211 PBITMAPINFO pConvertedInfo;
212 UINT ConvertedInfoSize;
213 HBITMAP hBitmap = NULL;
214 PVOID bmBits = NULL;
215
216 pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage,
217 &ConvertedInfoSize, FALSE);
218 if (pConvertedInfo)
219 {
220 // Verify header due to converted may == info.
221 if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
222 {
223 if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
224 pConvertedInfo->bmiHeader.biCompression == BI_PNG )
225 {
226 SetLastError(ERROR_INVALID_PARAMETER);
227 return NULL;
228 }
229 }
230 bmBits = Bits;
231 hBitmap = NtGdiCreateDIBSection( hDC,
232 hSection,
233 dwOffset,
234 pConvertedInfo,
235 Usage,
236 0,
237 0,
238 0,
239 &bmBits);
240 if (BitmapInfo != pConvertedInfo)
241 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
242
243 if (!hBitmap)
244 {
245 bmBits = NULL;
246 }
247 }
248
249 if (Bits) *Bits = bmBits;
250
251 return hBitmap;
252 }
253
254
255 /*
256 * @implemented
257 */
258 BOOL
259 WINAPI
260 BitBlt(HDC hdcDest, /* handle to destination DC */
261 int nXOriginDest, /* x-coord of destination upper-left corner */
262 int nYOriginDest, /* y-coord of destination upper-left corner */
263 int nWidthDest, /* width of destination rectangle */
264 int nHeightDest, /* height of destination rectangle */
265 HDC hdcSrc, /* handle to source DC */
266 int nXSrc, /* x-coordinate of source upper-left corner */
267 int nYSrc, /* y-coordinate of source upper-left corner */
268 DWORD dwRop) /* raster operation code */
269 {
270 /* use patBlt for no source blt Like windows does */
271 if (!ROP_USES_SOURCE(dwRop))
272 {
273 return PatBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, dwRop);
274 }
275
276 return NtGdiBitBlt(hdcDest,
277 nXOriginDest,
278 nYOriginDest,
279 nWidthDest,
280 nHeightDest,
281 hdcSrc,
282 nXSrc,
283 nYSrc,
284 dwRop,
285 0,
286 0);
287 }
288
289 /*
290 * @implemented
291 */
292 BOOL WINAPI
293 StretchBlt(
294 HDC hdcDest, /* handle to destination DC */
295 int nXOriginDest, /* x-coord of destination upper-left corner */
296 int nYOriginDest, /* y-coord of destination upper-left corner */
297 int nWidthDest, /* width of destination rectangle */
298 int nHeightDest, /* height of destination rectangle */
299 HDC hdcSrc, /* handle to source DC */
300 int nXOriginSrc, /* x-coord of source upper-left corner */
301 int nYOriginSrc, /* y-coord of source upper-left corner */
302 int nWidthSrc, /* width of source rectangle */
303 int nHeightSrc, /* height of source rectangle */
304 DWORD dwRop) /* raster operation code */
305
306 {
307 if ((nWidthDest != nWidthSrc) || (nHeightDest != nHeightSrc))
308 {
309 return NtGdiStretchBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
310 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc,
311 nWidthSrc, nHeightSrc, dwRop, 0);
312 }
313
314 return NtGdiBitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest,
315 nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0);
316 }
317
318 /*
319 * @unimplemented
320 */
321 HBITMAP WINAPI
322 CreateBitmap(INT Width,
323 INT Height,
324 UINT Planes,
325 UINT BitsPixel,
326 CONST VOID* pUnsafeBits)
327 {
328 /* FIXME some part should be done in user mode */
329 if (Width && Height)
330 {
331 return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
332 }
333 else
334 {
335 /* Return 1x1 bitmap */
336 return GetStockObject(DEFAULT_BITMAP);
337 }
338 }
339
340 /*
341 * @implemented
342 */
343 HBITMAP WINAPI
344 CreateBitmapIndirect(const BITMAP *pbm)
345 {
346 HBITMAP bitmap = NULL;
347
348 /* Note windows xp/2003 does not check if pbm is NULL or not */
349 if ( (pbm->bmWidthBytes != 0) &&
350 (!(pbm->bmWidthBytes & 1)) )
351
352 {
353
354 bitmap = CreateBitmap(pbm->bmWidth,
355 pbm->bmHeight,
356 pbm->bmPlanes,
357 pbm->bmBitsPixel,
358 pbm->bmBits);
359 }
360 else
361 {
362 SetLastError(ERROR_INVALID_PARAMETER);
363 }
364
365 return bitmap;
366 }
367
368 HBITMAP WINAPI
369 CreateDiscardableBitmap(
370 HDC hDC,
371 INT Width,
372 INT Height)
373 {
374 return CreateCompatibleBitmap(hDC, Width, Height);
375 }
376
377
378 HBITMAP WINAPI
379 CreateCompatibleBitmap(
380 HDC hDC,
381 INT Width,
382 INT Height)
383 {
384 PDC_ATTR pDc_Attr;
385 HBITMAP hBmp = NULL;
386 DIBSECTION dibs;
387
388 if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
389 return NULL;
390
391 if ( !Width || !Height )
392 return GetStockObject(DEFAULT_BITMAP);
393
394 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
395 {
396 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
397 }
398
399 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
400
401 if ( GetObjectA(hBmp, sizeof(DIBSECTION), &dibs) != sizeof(DIBSECTION) )
402 return NULL;
403
404 if ( dibs.dsBm.bmBitsPixel <= 8 )
405 GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&dibs.dsBitfields);
406
407 dibs.dsBmih.biWidth = Width;
408 dibs.dsBmih.biHeight = Height;
409
410 return CreateDIBSection(hDC, (CONST BITMAPINFO *)&dibs.dsBmih, 0, NULL, NULL, 0);
411 }
412
413
414 INT
415 WINAPI
416 GetDIBits(
417 HDC hDC,
418 HBITMAP hbmp,
419 UINT uStartScan,
420 UINT cScanLines,
421 LPVOID lpvBits,
422 LPBITMAPINFO lpbmi,
423 UINT uUsage)
424 {
425 UINT cjBmpScanSize;
426 UINT cjInfoSize;
427
428 if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC) || !lpbmi)
429 {
430 GdiSetLastError(ERROR_INVALID_PARAMETER);
431 return 0;
432 }
433
434 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
435 cjInfoSize = DIB_BitmapInfoSize(lpbmi, uUsage);
436
437 if ( lpvBits )
438 {
439 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
440 {
441 if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
442 lpbmi->bmiHeader.biCompression == BI_PNG )
443 {
444 SetLastError(ERROR_INVALID_PARAMETER);
445 return 0;
446 }
447 }
448 }
449
450 return NtGdiGetDIBitsInternal(hDC,
451 hbmp,
452 uStartScan,
453 cScanLines,
454 lpvBits,
455 lpbmi,
456 uUsage,
457 cjBmpScanSize,
458 cjInfoSize);
459 }
460
461 /*
462 * @implemented
463 */
464 HBITMAP
465 WINAPI
466 CreateDIBitmap( HDC hDC,
467 const BITMAPINFOHEADER *Header,
468 DWORD Init,
469 LPCVOID Bits,
470 const BITMAPINFO *Data,
471 UINT ColorUse)
472 {
473 LONG width, height, compr, dibsize;
474 WORD planes, bpp;
475 // PDC_ATTR pDc_Attr;
476 UINT InfoSize = 0;
477 UINT cjBmpScanSize = 0;
478 HBITMAP hBmp;
479 NTSTATUS Status = STATUS_SUCCESS;
480
481 if (!Header) return 0;
482
483 if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
484 {
485 GdiSetLastError(ERROR_INVALID_PARAMETER);
486 return NULL;
487 }
488
489 // For Icm support.
490 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
491
492 if(Data)
493 {
494 _SEH2_TRY
495 {
496 cjBmpScanSize = DIB_BitmapBitsSize(Data);
497 CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
498 InfoSize += Data->bmiHeader.biSize;
499 }
500 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
501 {
502 Status = _SEH2_GetExceptionCode();
503 }
504 _SEH2_END
505 }
506
507 if(!NT_SUCCESS(Status))
508 {
509 GdiSetLastError(ERROR_INVALID_PARAMETER);
510 return NULL;
511 }
512
513 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
514
515 if ( !width || !height )
516 hBmp = GetStockObject(DEFAULT_BITMAP);
517 else
518 {
519 hBmp = NtGdiCreateDIBitmapInternal(hDC,
520 width,
521 height,
522 Init,
523 (LPBYTE)Bits,
524 (LPBITMAPINFO)Data,
525 ColorUse,
526 InfoSize,
527 cjBmpScanSize,
528 0,
529 0);
530 }
531 return hBmp;
532 }
533
534 /*
535 * @implemented
536 */
537 INT
538 WINAPI
539 SetDIBits(HDC hDC,
540 HBITMAP hBitmap,
541 UINT uStartScan,
542 UINT cScanLines,
543 CONST VOID *lpvBits,
544 CONST BITMAPINFO *lpbmi,
545 UINT fuColorUse)
546 {
547 HDC hDCc, SavehDC, nhDC;
548 DWORD dwWidth, dwHeight;
549 HGDIOBJ hOldBitmap;
550 HPALETTE hPal = NULL;
551 INT LinesCopied = 0;
552 BOOL newDC = FALSE;
553
554 if ( !lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP) )
555 return 0;
556
557 if ( lpbmi )
558 {
559 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
560 {
561 if ( lpbmi->bmiHeader.biCompression == BI_JPEG || lpbmi->bmiHeader.biCompression == BI_PNG )
562 {
563 SetLastError(ERROR_INVALID_PARAMETER);
564 return 0;
565 }
566 }
567 }
568
569 hDCc = NtGdiGetDCforBitmap(hBitmap);
570 SavehDC = hDCc;
571 if ( !hDCc )
572 {
573 nhDC = CreateCompatibleDC(hDC);
574 if ( !nhDC ) return 0;
575 newDC = TRUE;
576 SavehDC = nhDC;
577 }
578 else if ( !SaveDC(hDCc) )
579 return 0;
580
581 hOldBitmap = SelectObject(SavehDC, hBitmap);
582
583 if ( hOldBitmap )
584 {
585 if ( hDC )
586 hPal = SelectPalette(SavehDC, (HPALETTE)GetDCObject(hDC, GDI_OBJECT_TYPE_PALETTE), FALSE);
587
588 if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
589 {
590 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
591 dwWidth = pbci->bmciHeader.bcWidth;
592 dwHeight = pbci->bmciHeader.bcHeight;
593 }
594 else
595 {
596 dwWidth = lpbmi->bmiHeader.biWidth;
597 dwHeight = abs(lpbmi->bmiHeader.biHeight);
598 }
599
600 LinesCopied = SetDIBitsToDevice(SavehDC,
601 0,
602 0,
603 dwWidth,
604 dwHeight,
605 0,
606 0,
607 uStartScan,
608 cScanLines,
609 (void *)lpvBits,
610 (LPBITMAPINFO)lpbmi,
611 fuColorUse);
612
613 if ( hDC ) SelectPalette(SavehDC, hPal, FALSE);
614
615 SelectObject(SavehDC, hOldBitmap);
616 }
617
618 if ( newDC )
619 DeleteDC(SavehDC);
620 else
621 RestoreDC(SavehDC, -1);
622
623 return LinesCopied;
624 }
625
626 /*
627 * @implemented
628 *
629 */
630 INT
631 WINAPI
632 SetDIBitsToDevice(
633 HDC hdc,
634 int XDest,
635 int YDest,
636 DWORD Width,
637 DWORD Height,
638 int XSrc,
639 int YSrc,
640 UINT StartScan,
641 UINT ScanLines,
642 CONST VOID *Bits,
643 CONST BITMAPINFO *lpbmi,
644 UINT ColorUse)
645 {
646 PDC_ATTR pDc_Attr;
647 PBITMAPINFO pConvertedInfo;
648 UINT ConvertedInfoSize;
649 INT LinesCopied = 0;
650 UINT cjBmpScanSize = 0;
651 PVOID pvSafeBits = (PVOID)Bits;
652
653 if ( !ScanLines || !lpbmi || !Bits )
654 return 0;
655
656 if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
657 return 0;
658
659 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
660 &ConvertedInfoSize, FALSE);
661 if (!pConvertedInfo)
662 return 0;
663
664 #if 0
665 // Handle something other than a normal dc object.
666 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
667 {
668 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
669 return MFDRV_SetDIBitsToDevice( hdc,
670 XDest,
671 YDest,
672 Width,
673 Height,
674 XSrc,
675 YSrc,
676 StartScan,
677 ScanLines,
678 Bits,
679 lpbmi,
680 ColorUse);
681 else
682 {
683 PLDC pLDC = GdiGetLDC(hdc);
684 if ( !pLDC )
685 {
686 SetLastError(ERROR_INVALID_HANDLE);
687 return 0;
688 }
689 if (pLDC->iType == LDC_EMFLDC)
690 {
691 return EMFDRV_SetDIBitsToDevice(hdc,
692 XDest,
693 YDest,
694 Width,
695 Height,
696 XSrc,
697 YSrc,
698 StartScan,
699 ScanLines,
700 Bits,
701 lpbmi,
702 ColorUse);
703 }
704 return 0;
705 }
706 }
707 #endif
708 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
709
710 if ( Bits )
711 {
712 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
713 if (pvSafeBits)
714 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
715 }
716
717 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
718 {
719 SetLastError(ERROR_INVALID_PARAMETER);
720 return 0;
721 }
722 /*
723 if ( !pDc_Attr ||
724 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
725 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
726 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
727 {
728 LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
729 XDest,
730 YDest,
731 Width,
732 Height,
733 XSrc,
734 YSrc,
735 StartScan,
736 ScanLines,
737 (LPBYTE)pvSafeBits,
738 (LPBITMAPINFO)pConvertedInfo,
739 ColorUse,
740 cjBmpScanSize,
741 ConvertedInfoSize,
742 TRUE,
743 NULL);
744 }
745 if ( Bits != pvSafeBits)
746 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
747 if (lpbmi != pConvertedInfo)
748 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
749
750 return LinesCopied;
751 }
752
753
754 /*
755 * @unimplemented
756 */
757 int
758 WINAPI
759 StretchDIBits(HDC hdc,
760 int XDest,
761 int YDest,
762 int nDestWidth,
763 int nDestHeight,
764 int XSrc,
765 int YSrc,
766 int nSrcWidth,
767 int nSrcHeight,
768 CONST VOID *lpBits,
769 CONST BITMAPINFO *lpBitsInfo,
770 UINT iUsage,
771 DWORD dwRop)
772
773 {
774 PDC_ATTR pDc_Attr;
775 PBITMAPINFO pConvertedInfo = NULL;
776 UINT ConvertedInfoSize = 0;
777 INT LinesCopied = 0;
778 UINT cjBmpScanSize = 0;
779 PVOID pvSafeBits = NULL;
780 BOOL Hit = FALSE;
781
782 DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
783 #if 0
784 // Handle something other than a normal dc object.
785 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
786 {
787 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
788 return MFDRV_StretchBlt( hdc,
789 XDest,
790 YDest,
791 nDestWidth,
792 nDestHeight,
793 XSrc,
794 YSrc,
795 nSrcWidth,
796 nSrcHeight,
797 lpBits,
798 lpBitsInfo,
799 iUsage,
800 dwRop);
801 else
802 {
803 PLDC pLDC = GdiGetLDC(hdc);
804 if ( !pLDC )
805 {
806 SetLastError(ERROR_INVALID_HANDLE);
807 return 0;
808 }
809 if (pLDC->iType == LDC_EMFLDC)
810 {
811 return EMFDRV_StretchBlt(hdc,
812 XDest,
813 YDest,
814 nDestWidth,
815 nDestHeight,
816 XSrc,
817 YSrc,
818 nSrcWidth,
819 nSrcHeight,
820 lpBits,
821 lpBitsInfo,
822 iUsage,
823 dwRop);
824 }
825 return 0;
826 }
827 }
828 #endif
829 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
830 &ConvertedInfoSize, FALSE);
831 if (!pConvertedInfo)
832 {
833 return 0;
834 }
835
836 cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
837
838 if ( lpBits )
839 {
840 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
841 if (pvSafeBits)
842 {
843 _SEH2_TRY
844 {
845 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
846 }
847 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
848 {
849 Hit = TRUE;
850 }
851 _SEH2_END
852
853 if (Hit)
854 {
855 // We don't die, we continue on with a allocated safe pointer to kernel
856 // space.....
857 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
858 }
859 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
860 }
861 }
862
863 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
864 {
865 SetLastError(ERROR_INVALID_PARAMETER);
866 return 0;
867 }
868 /*
869 if ( !pDc_Attr ||
870 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
871 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
872 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
873 {
874 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
875 XDest,
876 YDest,
877 nDestWidth,
878 nDestHeight,
879 XSrc,
880 YSrc,
881 nSrcWidth,
882 nSrcHeight,
883 pvSafeBits,
884 pConvertedInfo,
885 (DWORD)iUsage,
886 dwRop,
887 ConvertedInfoSize,
888 cjBmpScanSize,
889 NULL);
890 }
891 if ( pvSafeBits )
892 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
893 if (lpBitsInfo != pConvertedInfo)
894 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
895
896 return LinesCopied;
897 }
898