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