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