[GDI32/WIN32K]
[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)
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 = 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("(%ld): 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 0,
204 0,
205 0,
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 char buffer[sizeof(DIBSECTION) + 256*sizeof(RGBQUAD)];
366 DIBSECTION* pDIBs = (DIBSECTION*)buffer;
367
368 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
369
370 if ( GetObjectA(hBmp, sizeof(DIBSECTION), pDIBs) != sizeof(DIBSECTION) )
371 return NULL;
372
373 if ( pDIBs->dsBm.bmBitsPixel <= 8 )
374 GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&pDIBs->dsBitfields[0]);
375
376 pDIBs->dsBmih.biWidth = Width;
377 pDIBs->dsBmih.biHeight = Height;
378
379 return CreateDIBSection(hDC, (CONST BITMAPINFO *)&pDIBs->dsBmih, 0, NULL, NULL, 0);
380 }
381 return NULL;
382 }
383
384
385 INT
386 WINAPI
387 GetDIBits(
388 HDC hDC,
389 HBITMAP hbmp,
390 UINT uStartScan,
391 UINT cScanLines,
392 LPVOID lpvBits,
393 LPBITMAPINFO lpbmi,
394 UINT uUsage)
395 {
396 UINT cjBmpScanSize;
397 UINT cjInfoSize;
398
399 if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC) || !lpbmi)
400 {
401 GdiSetLastError(ERROR_INVALID_PARAMETER);
402 return 0;
403 }
404
405 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
406 cjInfoSize = DIB_BitmapInfoSize(lpbmi, uUsage);
407
408 if ( lpvBits )
409 {
410 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
411 {
412 if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
413 lpbmi->bmiHeader.biCompression == BI_PNG )
414 {
415 SetLastError(ERROR_INVALID_PARAMETER);
416 return 0;
417 }
418 }
419 }
420
421 return NtGdiGetDIBitsInternal(hDC,
422 hbmp,
423 uStartScan,
424 cScanLines,
425 lpvBits,
426 lpbmi,
427 uUsage,
428 cjBmpScanSize,
429 cjInfoSize);
430 }
431
432 /*
433 * @implemented
434 */
435 HBITMAP
436 WINAPI
437 CreateDIBitmap( HDC hDC,
438 const BITMAPINFOHEADER *Header,
439 DWORD Init,
440 LPCVOID Bits,
441 const BITMAPINFO *Data,
442 UINT ColorUse)
443 {
444 LONG width, height, compr, dibsize;
445 WORD planes, bpp;
446 // PDC_ATTR pDc_Attr;
447 UINT InfoSize = 0;
448 UINT cjBmpScanSize = 0;
449 HBITMAP hBmp;
450 NTSTATUS Status = STATUS_SUCCESS;
451
452 if (!Header) return 0;
453
454 if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
455 {
456 GdiSetLastError(ERROR_INVALID_PARAMETER);
457 return NULL;
458 }
459
460 // For Icm support.
461 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
462
463 if(Data)
464 {
465 _SEH2_TRY
466 {
467 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)Data);
468 CalculateColorTableSize(&Data->bmiHeader, &ColorUse, &InfoSize);
469 InfoSize += Data->bmiHeader.biSize;
470 }
471 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
472 {
473 Status = _SEH2_GetExceptionCode();
474 }
475 _SEH2_END
476 }
477
478 if(!NT_SUCCESS(Status))
479 {
480 GdiSetLastError(ERROR_INVALID_PARAMETER);
481 return NULL;
482 }
483
484 DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", Data,bpp,dibsize,InfoSize,cjBmpScanSize);
485
486 if ( !width || !height )
487 hBmp = GetStockObject(DEFAULT_BITMAP);
488 else
489 {
490 hBmp = NtGdiCreateDIBitmapInternal(hDC,
491 width,
492 height,
493 Init,
494 (LPBYTE)Bits,
495 (LPBITMAPINFO)Data,
496 ColorUse,
497 InfoSize,
498 cjBmpScanSize,
499 0,
500 0);
501 }
502 return hBmp;
503 }
504
505 /*
506 * @implemented
507 */
508 INT
509 WINAPI
510 SetDIBits(HDC hDC,
511 HBITMAP hBitmap,
512 UINT uStartScan,
513 UINT cScanLines,
514 CONST VOID *lpvBits,
515 CONST BITMAPINFO *lpbmi,
516 UINT fuColorUse)
517 {
518 HDC hDCc, SavehDC, nhDC;
519 DWORD dwWidth, dwHeight;
520 HGDIOBJ hOldBitmap;
521 HPALETTE hPal = NULL;
522 INT LinesCopied = 0;
523 BOOL newDC = FALSE;
524
525 if ( !lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP) )
526 return 0;
527
528 if ( lpbmi )
529 {
530 if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
531 {
532 if ( lpbmi->bmiHeader.biCompression == BI_JPEG || lpbmi->bmiHeader.biCompression == BI_PNG )
533 {
534 SetLastError(ERROR_INVALID_PARAMETER);
535 return 0;
536 }
537 }
538 }
539
540 hDCc = NtGdiGetDCforBitmap(hBitmap); // hDC can be NULL, so, get it from the bitmap.
541 SavehDC = hDCc;
542 if ( !hDCc ) // No DC associated with bitmap, Clone or Create one.
543 {
544 nhDC = CreateCompatibleDC(hDC);
545 if ( !nhDC ) return 0;
546 newDC = TRUE;
547 SavehDC = nhDC;
548 }
549 else if ( !SaveDC(hDCc) )
550 return 0;
551
552 hOldBitmap = SelectObject(SavehDC, hBitmap);
553
554 if ( hOldBitmap )
555 {
556 if ( hDC )
557 hPal = SelectPalette(SavehDC, (HPALETTE)GetCurrentObject(hDC, OBJ_PAL), FALSE);
558
559 if ( lpbmi->bmiHeader.biSize < sizeof(BITMAPINFOHEADER))
560 {
561 PBITMAPCOREINFO pbci = (PBITMAPCOREINFO) lpbmi;
562 dwWidth = pbci->bmciHeader.bcWidth;
563 dwHeight = pbci->bmciHeader.bcHeight;
564 }
565 else
566 {
567 dwWidth = lpbmi->bmiHeader.biWidth;
568 dwHeight = abs(lpbmi->bmiHeader.biHeight);
569 }
570
571 LinesCopied = SetDIBitsToDevice(SavehDC,
572 0,
573 0,
574 dwWidth,
575 dwHeight,
576 0,
577 0,
578 uStartScan,
579 cScanLines,
580 (void *)lpvBits,
581 (LPBITMAPINFO)lpbmi,
582 fuColorUse);
583
584 if ( hDC ) SelectPalette(SavehDC, hPal, FALSE);
585
586 SelectObject(SavehDC, hOldBitmap);
587 }
588
589 if ( newDC )
590 DeleteDC(SavehDC);
591 else
592 RestoreDC(SavehDC, -1);
593
594 return LinesCopied;
595 }
596
597 /*
598 * @implemented
599 *
600 */
601 INT
602 WINAPI
603 SetDIBitsToDevice(
604 HDC hdc,
605 int XDest,
606 int YDest,
607 DWORD Width,
608 DWORD Height,
609 int XSrc,
610 int YSrc,
611 UINT StartScan,
612 UINT ScanLines,
613 CONST VOID *Bits,
614 CONST BITMAPINFO *lpbmi,
615 UINT ColorUse)
616 {
617 PDC_ATTR pDc_Attr;
618 PBITMAPINFO pConvertedInfo;
619 UINT ConvertedInfoSize;
620 INT LinesCopied = 0;
621 UINT cjBmpScanSize = 0;
622 BOOL Hit = FALSE;
623 PVOID pvSafeBits = (PVOID)Bits;
624
625 if ( !ScanLines || !lpbmi || !Bits )
626 return 0;
627
628 if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
629 return 0;
630
631 pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
632 &ConvertedInfoSize, FALSE);
633 if (!pConvertedInfo)
634 return 0;
635
636 #if 0
637 // Handle something other than a normal dc object.
638 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
639 {
640 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
641 return MFDRV_SetDIBitsToDevice( hdc,
642 XDest,
643 YDest,
644 Width,
645 Height,
646 XSrc,
647 YSrc,
648 StartScan,
649 ScanLines,
650 Bits,
651 lpbmi,
652 ColorUse);
653 else
654 {
655 PLDC pLDC = GdiGetLDC(hdc);
656 if ( !pLDC )
657 {
658 SetLastError(ERROR_INVALID_HANDLE);
659 return 0;
660 }
661 if (pLDC->iType == LDC_EMFLDC)
662 {
663 return EMFDRV_SetDIBitsToDevice(hdc,
664 XDest,
665 YDest,
666 Width,
667 Height,
668 XSrc,
669 YSrc,
670 StartScan,
671 ScanLines,
672 Bits,
673 lpbmi,
674 ColorUse);
675 }
676 return 0;
677 }
678 }
679 #endif
680 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
681
682 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
683 if (pvSafeBits)
684 {
685 _SEH2_TRY
686 {
687 RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
688 }
689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
690 {
691 Hit = TRUE;
692 }
693 _SEH2_END
694
695 if (Hit)
696 {
697 // We don't die, we continue on with a allocated safe pointer to kernel
698 // space.....
699 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,Bits,cjBmpScanSize);
700 }
701 DPRINT("SetDIBitsToDevice Allocate Bits %d!!!\n", cjBmpScanSize);
702 }
703
704 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
705 {
706 SetLastError(ERROR_INVALID_PARAMETER);
707 return 0;
708 }
709 /*
710 if ( !pDc_Attr || // DC is Public
711 ColorUse == DIB_PAL_COLORS ||
712 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
713 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
714 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
715 {
716 LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
717 XDest,
718 YDest,
719 Width,
720 Height,
721 XSrc,
722 YSrc,
723 StartScan,
724 ScanLines,
725 (LPBYTE)pvSafeBits,
726 (LPBITMAPINFO)pConvertedInfo,
727 ColorUse,
728 cjBmpScanSize,
729 ConvertedInfoSize,
730 TRUE,
731 NULL);
732 }
733 if ( Bits != pvSafeBits)
734 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
735 if (lpbmi != pConvertedInfo)
736 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
737
738 return LinesCopied;
739 }
740
741
742 /*
743 * @unimplemented
744 */
745 int
746 WINAPI
747 StretchDIBits(HDC hdc,
748 int XDest,
749 int YDest,
750 int nDestWidth,
751 int nDestHeight,
752 int XSrc,
753 int YSrc,
754 int nSrcWidth,
755 int nSrcHeight,
756 CONST VOID *lpBits,
757 CONST BITMAPINFO *lpBitsInfo,
758 UINT iUsage,
759 DWORD dwRop)
760
761 {
762 PDC_ATTR pDc_Attr;
763 PBITMAPINFO pConvertedInfo = NULL;
764 UINT ConvertedInfoSize = 0;
765 INT LinesCopied = 0;
766 UINT cjBmpScanSize = 0;
767 PVOID pvSafeBits = NULL;
768 BOOL Hit = FALSE;
769
770 DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
771 #if 0
772 // Handle something other than a normal dc object.
773 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
774 {
775 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
776 return MFDRV_StretchBlt( hdc,
777 XDest,
778 YDest,
779 nDestWidth,
780 nDestHeight,
781 XSrc,
782 YSrc,
783 nSrcWidth,
784 nSrcHeight,
785 lpBits,
786 lpBitsInfo,
787 iUsage,
788 dwRop);
789 else
790 {
791 PLDC pLDC = GdiGetLDC(hdc);
792 if ( !pLDC )
793 {
794 SetLastError(ERROR_INVALID_HANDLE);
795 return 0;
796 }
797 if (pLDC->iType == LDC_EMFLDC)
798 {
799 return EMFDRV_StretchBlt(hdc,
800 XDest,
801 YDest,
802 nDestWidth,
803 nDestHeight,
804 XSrc,
805 YSrc,
806 nSrcWidth,
807 nSrcHeight,
808 lpBits,
809 lpBitsInfo,
810 iUsage,
811 dwRop);
812 }
813 return 0;
814 }
815 }
816 #endif
817 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
818 &ConvertedInfoSize, FALSE);
819 if (!pConvertedInfo)
820 {
821 return 0;
822 }
823
824 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *)pConvertedInfo);
825
826 if ( lpBits )
827 {
828 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
829 if (pvSafeBits)
830 {
831 _SEH2_TRY
832 {
833 RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
834 }
835 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
836 {
837 Hit = TRUE;
838 }
839 _SEH2_END
840
841 if (Hit)
842 {
843 // We don't die, we continue on with a allocated safe pointer to kernel
844 // space.....
845 DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
846 }
847 DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
848 }
849 }
850
851 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
852 {
853 SetLastError(ERROR_INVALID_PARAMETER);
854 return 0;
855 }
856 /*
857 if ( !pDc_Attr ||
858 iUsage == DIB_PAL_COLORS ||
859 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
860 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
861 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
862 {
863 LinesCopied = NtGdiStretchDIBitsInternal( hdc,
864 XDest,
865 YDest,
866 nDestWidth,
867 nDestHeight,
868 XSrc,
869 YSrc,
870 nSrcWidth,
871 nSrcHeight,
872 pvSafeBits,
873 pConvertedInfo,
874 (DWORD)iUsage,
875 dwRop,
876 ConvertedInfoSize,
877 cjBmpScanSize,
878 NULL);
879 }
880 if ( pvSafeBits )
881 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
882 if (lpBitsInfo != pConvertedInfo)
883 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
884
885 return LinesCopied;
886 }
887