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