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