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