[GDI32] Allow functions to access printing support.
[reactos.git] / 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 /*
248 * @implemented
249 */
250 HBITMAP
251 WINAPI
252 CreateBitmap(
253 INT Width,
254 INT Height,
255 UINT Planes,
256 UINT BitsPixel,
257 CONST VOID* pUnsafeBits)
258 {
259 if (Width && Height)
260 {
261 return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
262 }
263 else
264 {
265 /* Return 1x1 bitmap */
266 return GetStockObject(DEFAULT_BITMAP);
267 }
268 }
269
270 /*
271 * @implemented
272 */
273 HBITMAP
274 WINAPI
275 CreateBitmapIndirect(
276 const BITMAP *pbm)
277 {
278 HBITMAP bitmap = NULL;
279
280 /* Note windows xp/2003 does not check if pbm is NULL or not */
281 if ((pbm->bmWidthBytes != 0) && (!(pbm->bmWidthBytes & 1)))
282
283 {
284 bitmap = CreateBitmap(pbm->bmWidth, pbm->bmHeight, pbm->bmPlanes, pbm->bmBitsPixel,
285 pbm->bmBits);
286 }
287 else
288 {
289 SetLastError(ERROR_INVALID_PARAMETER);
290 }
291
292 return bitmap;
293 }
294
295 HBITMAP
296 WINAPI
297 CreateDiscardableBitmap(
298 HDC hDC,
299 INT Width,
300 INT Height)
301 {
302 return CreateCompatibleBitmap(hDC, Width, Height);
303 }
304
305 HBITMAP
306 WINAPI
307 CreateCompatibleBitmap(
308 HDC hDC,
309 INT Width,
310 INT Height)
311 {
312 PDC_ATTR pDc_Attr;
313
314 if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
315 return NULL;
316
317 if (!Width || !Height)
318 return GetStockObject(DEFAULT_BITMAP);
319
320 if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
321 {
322 return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
323 }
324 else
325 {
326 HBITMAP hBmp = NULL;
327 struct
328 {
329 BITMAP bitmap;
330 BITMAPINFOHEADER bmih;
331 RGBQUAD rgbquad[256];
332 } buffer;
333 DIBSECTION* pDIBs = (DIBSECTION*) &buffer;
334 BITMAPINFO* pbmi = (BITMAPINFO*) &buffer.bmih;
335
336 hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
337
338 if (GetObjectA(hBmp, sizeof(DIBSECTION), pDIBs) != sizeof(DIBSECTION))
339 return NULL;
340
341 if (pDIBs->dsBm.bmBitsPixel <= 8)
342 GetDIBColorTable(hDC, 0, 256, buffer.rgbquad);
343
344 pDIBs->dsBmih.biWidth = Width;
345 pDIBs->dsBmih.biHeight = Height;
346
347 return CreateDIBSection(hDC, pbmi, DIB_RGB_COLORS, NULL, NULL, 0);
348 }
349 return NULL;
350 }
351
352 INT
353 WINAPI
354 GetDIBits(
355 HDC hDC,
356 HBITMAP hbmp,
357 UINT uStartScan,
358 UINT cScanLines,
359 LPVOID lpvBits,
360 LPBITMAPINFO lpbmi,
361 UINT uUsage)
362 {
363 UINT cjBmpScanSize;
364 UINT cjInfoSize;
365
366 if (!hDC || !GdiValidateHandle((HGDIOBJ) hDC) || !lpbmi)
367 {
368 GdiSetLastError(ERROR_INVALID_PARAMETER);
369 return 0;
370 }
371
372 cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
373 /* Caller must provide maximum size possible */
374 cjInfoSize = DIB_BitmapInfoSize(lpbmi, uUsage, TRUE);
375
376 if (lpvBits)
377 {
378 if (lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
379 {
380 if (lpbmi->bmiHeader.biCompression == BI_JPEG
381 || lpbmi->bmiHeader.biCompression == BI_PNG)
382 {
383 SetLastError(ERROR_INVALID_PARAMETER);
384 return 0;
385 }
386 }
387 }
388
389 return NtGdiGetDIBitsInternal(hDC, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, uUsage,
390 cjBmpScanSize, cjInfoSize);
391 }
392
393 /*
394 * @implemented
395 */
396 HBITMAP
397 WINAPI
398 CreateDIBitmap(
399 HDC hDC,
400 const BITMAPINFOHEADER *Header,
401 DWORD Init,
402 LPCVOID Bits,
403 const BITMAPINFO *Data,
404 UINT ColorUse)
405 {
406 LONG Width, Height, Compression, DibSize;
407 WORD Planes, BitsPerPixel;
408 // PDC_ATTR pDc_Attr;
409 UINT cjBmpScanSize = 0;
410 HBITMAP hBitmap = NULL;
411 PBITMAPINFO pbmiConverted;
412 UINT cjInfoSize;
413
414 /* Convert the BITMAPINFO if it is a COREINFO */
415 pbmiConverted = ConvertBitmapInfo(Data, ColorUse, &cjInfoSize, FALSE);
416
417 /* Check for CBM_CREATDIB */
418 if (Init & CBM_CREATDIB)
419 {
420 if (cjInfoSize == 0)
421 {
422 goto Exit;
423 }
424 else if (Init & CBM_INIT)
425 {
426 if (Bits == NULL)
427 {
428 goto Exit;
429 }
430 }
431 else
432 {
433 Bits = NULL;
434 }
435
436 /* CBM_CREATDIB needs Data. */
437 if (pbmiConverted == NULL)
438 {
439 DPRINT1("CBM_CREATDIB needs a BITMAPINFO!\n");
440 goto Exit;
441 }
442
443 /* It only works with PAL or RGB */
444 if (ColorUse > DIB_PAL_COLORS)
445 {
446 DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
447 GdiSetLastError(ERROR_INVALID_PARAMETER);
448 goto Exit;
449 }
450
451 /* Use the header from the data */
452 Header = &Data->bmiHeader;
453 }
454 else
455 {
456 if (Init & CBM_INIT)
457 {
458 if (Bits != NULL)
459 {
460 if (cjInfoSize == 0)
461 {
462 goto Exit;
463 }
464 }
465 else
466 {
467 Init &= ~CBM_INIT;
468 }
469 }
470 }
471
472 /* Header is required */
473 if (!Header)
474 {
475 DPRINT1("Header is NULL\n");
476 GdiSetLastError(ERROR_INVALID_PARAMETER);
477 goto Exit;
478 }
479
480 /* Get the bitmap format and dimensions */
481 if (DIB_GetBitmapInfo(Header, &Width, &Height, &Planes, &BitsPerPixel, &Compression, &DibSize) == -1)
482 {
483 DPRINT1("DIB_GetBitmapInfo failed!\n");
484 GdiSetLastError(ERROR_INVALID_PARAMETER);
485 goto Exit;
486 }
487
488 /* Check if the Compr is incompatible */
489 if ((Compression == BI_JPEG) || (Compression == BI_PNG) || (Compression == BI_BITFIELDS))
490 {
491 DPRINT1("Invalid compression: %lu!\n", Compression);
492 goto Exit;
493 }
494
495 /* Only DIB_RGB_COLORS (0), DIB_PAL_COLORS (1) and 2 are valid. */
496 if (ColorUse > DIB_PAL_COLORS + 1)
497 {
498 DPRINT1("Invalid compression: %lu!\n", Compression);
499 GdiSetLastError(ERROR_INVALID_PARAMETER);
500 goto Exit;
501 }
502
503 /* If some Bits are given, only DIB_PAL_COLORS and DIB_RGB_COLORS are valid */
504 if (Bits && (ColorUse > DIB_PAL_COLORS))
505 {
506 DPRINT1("Invalid ColorUse: %lu\n", ColorUse);
507 GdiSetLastError(ERROR_INVALID_PARAMETER);
508 goto Exit;
509 }
510
511 /* Negative width is not allowed */
512 if (Width < 0)
513 {
514 DPRINT1("Negative width: %li\n", Width);
515 goto Exit;
516 }
517
518 /* Top-down DIBs have a negative height. */
519 Height = abs(Height);
520
521 // For Icm support.
522 // GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
523
524 cjBmpScanSize = GdiGetBitmapBitsSize(pbmiConverted);
525
526 DPRINT("pBMI %p, Size bpp %u, dibsize %d, Conv %u, BSS %u\n",
527 Data, BitsPerPixel, DibSize, cjInfoSize, cjBmpScanSize);
528
529 if (!Width || !Height)
530 {
531 hBitmap = GetStockObject(DEFAULT_BITMAP);
532 }
533 else
534 {
535 hBitmap = NtGdiCreateDIBitmapInternal(hDC,
536 Width,
537 Height,
538 Init,
539 (LPBYTE)Bits,
540 (LPBITMAPINFO)pbmiConverted,
541 ColorUse,
542 cjInfoSize,
543 cjBmpScanSize,
544 0, 0);
545 }
546
547 Exit:
548 /* Cleanup converted BITMAPINFO */
549 if ((pbmiConverted != NULL) && (pbmiConverted != Data))
550 {
551 RtlFreeHeap(RtlGetProcessHeap(), 0, pbmiConverted);
552 }
553
554 return hBitmap;
555 }
556
557 /*
558 * @implemented
559 */
560 INT
561 WINAPI
562 SetDIBits(
563 HDC hDC,
564 HBITMAP hBitmap,
565 UINT uStartScan,
566 UINT cScanLines,
567 CONST VOID *lpvBits,
568 CONST BITMAPINFO *lpbmi,
569 UINT fuColorUse)
570 {
571 HDC hDCc, SavehDC, nhDC;
572 DWORD dwWidth, dwHeight;
573 HGDIOBJ hOldBitmap;
574 HPALETTE hPal = NULL;
575 INT LinesCopied = 0;
576 BOOL newDC = FALSE;
577
578 if (!lpvBits || (GDI_HANDLE_GET_TYPE(hBitmap) != GDI_OBJECT_TYPE_BITMAP))
579 return 0;
580
581 if (lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER))
582 {
583 if (lpbmi->bmiHeader.biCompression == BI_JPEG
584 || lpbmi->bmiHeader.biCompression == BI_PNG)
585 {
586 SetLastError(ERROR_INVALID_PARAMETER);
587 return 0;
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, FALSE);
675 if (!pConvertedInfo)
676 return 0;
677
678 HANDLE_METADC(INT,
679 SetDIBitsToDevice,
680 0,
681 hdc,
682 XDest,
683 YDest,
684 Width,
685 Height,
686 XSrc,
687 YSrc,
688 StartScan,
689 ScanLines,
690 Bits,
691 lpbmi,
692 ColorUse);
693
694 // Handle the "Special Case"!
695 {
696 PLDC pldc;
697 ULONG hType = GDI_HANDLE_GET_TYPE(hdc);
698 if (hType != GDILoObjType_LO_DC_TYPE && hType != GDILoObjType_LO_METADC16_TYPE)
699 {
700 pldc = GdiGetLDC(hdc);
701 if (pldc)
702 {
703 if (pldc->Flags & LDC_STARTPAGE) StartPage(hdc);
704
705 if (pldc->Flags & LDC_SAPCALLBACK) GdiSAPCallback(pldc);
706
707 if (pldc->Flags & LDC_KILL_DOCUMENT)
708 {
709 LinesCopied = 0;
710 goto Exit;
711 }
712 }
713 else
714 {
715 SetLastError(ERROR_INVALID_HANDLE);
716 LinesCopied = 0;
717 goto Exit;
718 }
719 }
720 }
721
722 if ((pConvertedInfo->bmiHeader.biCompression == BI_RLE8) ||
723 (pConvertedInfo->bmiHeader.biCompression == BI_RLE4))
724 {
725 /* For compressed data, we must set the whole thing */
726 StartScan = 0;
727 ScanLines = pConvertedInfo->bmiHeader.biHeight;
728 }
729
730 cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO) lpbmi, ScanLines);
731
732 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
733 if (pvSafeBits)
734 {
735 _SEH2_TRY
736 {
737 RtlCopyMemory(pvSafeBits, Bits, cjBmpScanSize);
738 }
739 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
740 {
741 Hit = TRUE;
742 }
743 _SEH2_END
744
745 if (Hit)
746 {
747 // We don't die, we continue on with a allocated safe pointer to kernel
748 // space.....
749 DPRINT1("SetDIBitsToDevice fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
750 pConvertedInfo, Bits, cjBmpScanSize);
751 }
752 DPRINT("SetDIBitsToDevice Allocate Bits %u!!!\n", cjBmpScanSize);
753 }
754
755 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
756 {
757 SetLastError(ERROR_INVALID_PARAMETER);
758 return 0;
759 }
760 /*
761 if ( !pDc_Attr || // DC is Public
762 ColorUse == DIB_PAL_COLORS ||
763 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
764 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
765 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
766 {
767 LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc,
768 StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse,
769 cjBmpScanSize, ConvertedInfoSize,
770 TRUE,
771 NULL);
772 }
773 Exit:
774 if (Bits != pvSafeBits)
775 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
776 if (lpbmi != pConvertedInfo)
777 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
778
779 return LinesCopied;
780 }
781
782 /*
783 * @unimplemented
784 */
785 int
786 WINAPI
787 StretchDIBits(
788 HDC hdc,
789 int XDest,
790 int YDest,
791 int nDestWidth,
792 int nDestHeight,
793 int XSrc,
794 int YSrc,
795 int nSrcWidth,
796 int nSrcHeight,
797 CONST VOID *lpBits,
798 CONST BITMAPINFO *lpBitsInfo,
799 UINT iUsage,
800 DWORD dwRop)
801
802 {
803 PDC_ATTR pDc_Attr;
804 PBITMAPINFO pConvertedInfo = NULL;
805 UINT ConvertedInfoSize = 0;
806 INT LinesCopied = 0;
807 UINT cjBmpScanSize = 0;
808 PVOID pvSafeBits = NULL;
809 BOOL Hit = FALSE;
810
811 DPRINT("StretchDIBits %p : %p : %u\n", lpBits, lpBitsInfo, iUsage);
812 #if 0
813 // Handle something other than a normal dc object.
814 if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
815 {
816 if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
817 return MFDRV_StretchBlt( hdc,
818 XDest,
819 YDest,
820 nDestWidth,
821 nDestHeight,
822 XSrc,
823 YSrc,
824 nSrcWidth,
825 nSrcHeight,
826 lpBits,
827 lpBitsInfo,
828 iUsage,
829 dwRop);
830 else
831 {
832 PLDC pLDC = GdiGetLDC(hdc);
833 if ( !pLDC )
834 {
835 SetLastError(ERROR_INVALID_HANDLE);
836 return 0;
837 }
838 if (pLDC->iType == LDC_EMFLDC)
839 {
840 return EMFDRV_StretchBlt(hdc,
841 XDest,
842 YDest,
843 nDestWidth,
844 nDestHeight,
845 XSrc,
846 YSrc,
847 nSrcWidth,
848 nSrcHeight,
849 lpBits,
850 lpBitsInfo,
851 iUsage,
852 dwRop);
853 }
854 return 0;
855 }
856 }
857 #endif
858
859 if ( GdiConvertAndCheckDC(hdc) == NULL ) return 0;
860
861 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, &ConvertedInfoSize,
862 FALSE);
863 if (!pConvertedInfo)
864 {
865 return 0;
866 }
867
868 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) pConvertedInfo);
869
870 if (lpBits)
871 {
872 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
873 if (pvSafeBits)
874 {
875 _SEH2_TRY
876 {
877 RtlCopyMemory(pvSafeBits, lpBits, cjBmpScanSize);
878 }
879 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
880 {
881 Hit = TRUE;
882 }
883 _SEH2_END
884
885 if (Hit)
886 {
887 // We don't die, we continue on with a allocated safe pointer to kernel
888 // space.....
889 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n",
890 pConvertedInfo, lpBits, cjBmpScanSize);
891 }
892 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize);
893 }
894 }
895
896 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr))
897 {
898 SetLastError(ERROR_INVALID_PARAMETER);
899 return 0;
900 }
901 /*
902 if ( !pDc_Attr ||
903 iUsage == DIB_PAL_COLORS ||
904 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
905 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
906 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
907 {
908 LinesCopied = NtGdiStretchDIBitsInternal(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc,
909 YSrc, nSrcWidth, nSrcHeight, pvSafeBits, pConvertedInfo, (DWORD) iUsage, dwRop,
910 ConvertedInfoSize, cjBmpScanSize,
911 NULL);
912 }
913 if (pvSafeBits)
914 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
915 if (lpBitsInfo != pConvertedInfo)
916 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
917
918 return LinesCopied;
919 }
920
921 /*
922 * @unimplemented
923 */
924 DWORD
925 WINAPI
926 GetBitmapAttributes(HBITMAP hbm)
927 {
928 UNIMPLEMENTED;
929 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
930 return 0;
931 }
932
933 /*
934 * @unimplemented
935 */
936 HBITMAP
937 WINAPI
938 SetBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
939 {
940 UNIMPLEMENTED;
941 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
942 return 0;
943 }
944
945 /*
946 * @unimplemented
947 */
948 HBITMAP
949 WINAPI
950 ClearBitmapAttributes(HBITMAP hbm, DWORD dwFlags)
951 {
952 UNIMPLEMENTED;
953 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
954 return 0;
955 }
956
957 /*
958 * @unimplemented
959 *
960 */
961 HBITMAP
962 WINAPI
963 GdiConvertBitmapV5(
964 HBITMAP in_format_BitMap,
965 HBITMAP src_BitMap,
966 INT bpp,
967 INT unuse)
968 {
969 /* FIXME guessing the prototypes */
970
971 /*
972 * it have create a new bitmap with desired in format,
973 * then convert it src_bitmap to new format
974 * and return it as HBITMAP
975 */
976
977 return FALSE;
978 }
979