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 SetLastError(ERROR_INVALID_PARAMETER); 760 return 0; 761 } 762 /* 763 if ( !pDc_Attr || // DC is Public 764 ColorUse == DIB_PAL_COLORS || 765 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && 766 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 767 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ 768 { 769 LinesCopied = NtGdiSetDIBitsToDeviceInternal(hdc, XDest, YDest, Width, Height, XSrc, YSrc, 770 StartScan, ScanLines, (LPBYTE) pvSafeBits, (LPBITMAPINFO) pConvertedInfo, ColorUse, 771 cjBmpScanSize, ConvertedInfoSize, 772 TRUE, 773 NULL); 774 } 775 Exit: 776 if (Bits != pvSafeBits) 777 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); 778 if (lpbmi != pConvertedInfo) 779 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); 780 781 return LinesCopied; 782 } 783 784 /* 785 * @unimplemented 786 */ 787 int 788 WINAPI 789 StretchDIBits( 790 HDC hdc, 791 int XDest, 792 int YDest, 793 int nDestWidth, 794 int nDestHeight, 795 int XSrc, 796 int YSrc, 797 int nSrcWidth, 798 int nSrcHeight, 799 CONST VOID *lpBits, 800 CONST BITMAPINFO *lpBitsInfo, 801 UINT iUsage, 802 DWORD dwRop) 803 804 { 805 PDC_ATTR pDc_Attr; 806 PBITMAPINFO pConvertedInfo = NULL; 807 UINT ConvertedInfoSize = 0; 808 INT LinesCopied = 0; 809 UINT cjBmpScanSize = 0; 810 PVOID pvSafeBits = NULL; 811 BOOL Hit = FALSE; 812 813 DPRINT("StretchDIBits %p : %p : %u\n", lpBits, lpBitsInfo, iUsage); 814 815 HANDLE_METADC( int, 816 StretchDIBits, 817 0, 818 hdc, 819 XDest, 820 YDest, 821 nDestWidth, 822 nDestHeight, 823 XSrc, 824 YSrc, 825 nSrcWidth, 826 nSrcHeight, 827 lpBits, 828 lpBitsInfo, 829 iUsage, 830 dwRop ); 831 832 if ( GdiConvertAndCheckDC(hdc) == NULL ) return 0; 833 834 pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage, &ConvertedInfoSize, FALSE); 835 if (!pConvertedInfo) 836 { 837 return 0; 838 } 839 840 cjBmpScanSize = GdiGetBitmapBitsSize((BITMAPINFO *) pConvertedInfo); 841 842 if (lpBits) 843 { 844 pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize); 845 if (pvSafeBits) 846 { 847 _SEH2_TRY 848 { 849 RtlCopyMemory(pvSafeBits, lpBits, cjBmpScanSize); 850 } 851 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 852 { 853 Hit = TRUE; 854 } 855 _SEH2_END 856 857 if (Hit) 858 { 859 // We don't die, we continue on with a allocated safe pointer to kernel 860 // space..... 861 DPRINT1("StretchDIBits fail to read BitMapInfo: %p or Bits: %p & Size: %u\n", 862 pConvertedInfo, lpBits, cjBmpScanSize); 863 } 864 DPRINT("StretchDIBits Allocate Bits %u!!!\n", cjBmpScanSize); 865 } 866 } 867 868 if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID) & pDc_Attr)) 869 { 870 SetLastError(ERROR_INVALID_PARAMETER); 871 return 0; 872 } 873 /* 874 if ( !pDc_Attr || 875 iUsage == DIB_PAL_COLORS || 876 ((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) && 877 (pConvertedInfo->bmiHeader.biCompression == BI_JPEG || 878 pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/ 879 { 880 LinesCopied = NtGdiStretchDIBitsInternal( hdc, 881 XDest, 882 YDest, 883 nDestWidth, 884 nDestHeight, 885 XSrc, 886 YSrc, 887 nSrcWidth, 888 nSrcHeight, 889 pvSafeBits, 890 pConvertedInfo, 891 (DWORD) iUsage, 892 dwRop, 893 ConvertedInfoSize, 894 cjBmpScanSize, 895 NULL ); 896 } 897 if (pvSafeBits) 898 RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits); 899 if (lpBitsInfo != pConvertedInfo) 900 RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); 901 902 return LinesCopied; 903 } 904 905 /* 906 * @implemented 907 */ 908 DWORD 909 WINAPI 910 GetBitmapAttributes(HBITMAP hbm) 911 { 912 if ( GDI_HANDLE_IS_STOCKOBJ(hbm) ) 913 { 914 return SC_BB_STOCKOBJ; 915 } 916 return 0; 917 } 918 919 /* 920 * @implemented 921 */ 922 HBITMAP 923 WINAPI 924 SetBitmapAttributes(HBITMAP hbm, DWORD dwFlags) 925 { 926 if ( dwFlags & ~SC_BB_STOCKOBJ ) 927 { 928 return NULL; 929 } 930 return NtGdiSetBitmapAttributes( hbm, dwFlags ); 931 } 932 933 /* 934 * @implemented 935 */ 936 HBITMAP 937 WINAPI 938 ClearBitmapAttributes(HBITMAP hbm, DWORD dwFlags) 939 { 940 if ( dwFlags & ~SC_BB_STOCKOBJ ) 941 { 942 return NULL; 943 } 944 return NtGdiClearBitmapAttributes( hbm, dwFlags );; 945 } 946 947 948