1 /* 2 * COPYRIGHT: GNU GPL, See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Bitmap functions 5 * FILE: win32ss/gdi/ntgdi/bitmaps.c 6 * PROGRAMERS: Timo Kreuzer <timo.kreuzer@reactos.org> 7 * Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 8 */ 9 10 #include <win32k.h> 11 12 #define NDEBUG 13 #include <debug.h> 14 15 BOOL 16 NTAPI 17 GreSetBitmapOwner( 18 _In_ HBITMAP hbmp, 19 _In_ ULONG ulOwner) 20 { 21 /* Check if we have the correct object type */ 22 if (GDI_HANDLE_GET_TYPE(hbmp) != GDILoObjType_LO_BITMAP_TYPE) 23 { 24 DPRINT1("Incorrect type for hbmp: %p\n", hbmp); 25 return FALSE; 26 } 27 28 /// FIXME: this is a hack and doesn't handle a race condition properly. 29 /// It needs to be done in GDIOBJ_vSetObjectOwner atomically. 30 31 /* Check if we set public or none */ 32 if ((ulOwner == GDI_OBJ_HMGR_PUBLIC) || 33 (ulOwner == GDI_OBJ_HMGR_NONE)) 34 { 35 /* Only allow this for owned objects */ 36 if (GreGetObjectOwner(hbmp) != GDI_OBJ_HMGR_POWNED) 37 { 38 DPRINT1("Cannot change owner for non-powned hbmp\n"); 39 return FALSE; 40 } 41 } 42 43 return GreSetObjectOwner(hbmp, ulOwner); 44 } 45 46 LONG 47 NTAPI 48 UnsafeSetBitmapBits( 49 _Inout_ PSURFACE psurf, 50 _In_ ULONG cjBits, 51 _In_ const VOID *pvBits) 52 { 53 PUCHAR pjDst; 54 const UCHAR *pjSrc; 55 LONG lDeltaDst, lDeltaSrc, lDeltaDstAbs; 56 ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel; 57 58 NT_ASSERT(psurf->flags & API_BITMAP); 59 NT_ASSERT(psurf->SurfObj.iBitmapFormat <= BMF_32BPP); 60 61 nWidth = psurf->SurfObj.sizlBitmap.cx; 62 nHeight = psurf->SurfObj.sizlBitmap.cy; 63 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 64 65 pjDst = psurf->SurfObj.pvScan0; 66 pjSrc = pvBits; 67 lDeltaDst = psurf->SurfObj.lDelta; 68 lDeltaDstAbs = labs(lDeltaDst); 69 lDeltaSrc = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel); 70 NT_ASSERT(lDeltaSrc <= lDeltaDstAbs); 71 72 cbDst = lDeltaDstAbs * nHeight; 73 cbSrc = lDeltaSrc * nHeight; 74 cjBits = min(cjBits, cbSrc); 75 76 iSrc = iDst = 0; 77 for (Y = 0; Y < nHeight; Y++) 78 { 79 if (iSrc + lDeltaSrc > cjBits || iDst + lDeltaDstAbs > cbDst) 80 { 81 LONG lDelta = min(cjBits - iSrc, cbDst - iDst); 82 NT_ASSERT(lDelta >= 0); 83 RtlCopyMemory(pjDst, pjSrc, lDelta); 84 iSrc += lDelta; 85 break; 86 } 87 88 /* Copy one line */ 89 RtlCopyMemory(pjDst, pjSrc, lDeltaSrc); 90 pjSrc += lDeltaSrc; 91 pjDst += lDeltaDst; 92 iSrc += lDeltaSrc; 93 iDst += lDeltaDstAbs; 94 } 95 96 return iSrc; 97 } 98 99 HBITMAP 100 NTAPI 101 GreCreateBitmapEx( 102 _In_ ULONG nWidth, 103 _In_ ULONG nHeight, 104 _In_ ULONG cjWidthBytes, 105 _In_ ULONG iFormat, 106 _In_ USHORT fjBitmap, 107 _In_ ULONG cjSizeImage, 108 _In_opt_ PVOID pvBits, 109 _In_ FLONG flags) 110 { 111 PSURFACE psurf; 112 HBITMAP hbmp; 113 PVOID pvCompressedBits = NULL; 114 115 /* Verify format */ 116 if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL; 117 118 /* The infamous RLE hack */ 119 if ((iFormat == BMF_4RLE) || (iFormat == BMF_8RLE)) 120 { 121 pvCompressedBits = pvBits; 122 pvBits = NULL; 123 iFormat = (iFormat == BMF_4RLE) ? BMF_4BPP : BMF_8BPP; 124 } 125 126 /* Allocate a surface */ 127 psurf = SURFACE_AllocSurface(STYPE_BITMAP, 128 nWidth, 129 nHeight, 130 iFormat, 131 fjBitmap, 132 cjWidthBytes, 133 pvCompressedBits ? 0 : cjSizeImage, 134 pvBits); 135 if (!psurf) 136 { 137 DPRINT1("SURFACE_AllocSurface failed.\n"); 138 return NULL; 139 } 140 141 /* The infamous RLE hack */ 142 if (pvCompressedBits) 143 { 144 SIZEL sizl; 145 LONG lDelta; 146 147 sizl.cx = nWidth; 148 sizl.cy = nHeight; 149 lDelta = WIDTH_BYTES_ALIGN32(nWidth, gajBitsPerFormat[iFormat]); 150 151 pvBits = psurf->SurfObj.pvBits; 152 DecompressBitmap(sizl, pvCompressedBits, pvBits, lDelta, iFormat, cjSizeImage); 153 } 154 155 /* Get the handle for the bitmap */ 156 hbmp = (HBITMAP)psurf->SurfObj.hsurf; 157 158 /* Mark as API bitmap */ 159 psurf->flags |= (flags | API_BITMAP); 160 161 /* Unlock the surface and return */ 162 SURFACE_UnlockSurface(psurf); 163 return hbmp; 164 } 165 166 /* Creates a DDB surface, 167 * as in CreateCompatibleBitmap or CreateBitmap. 168 * Note that each scanline must be 32bit aligned! 169 */ 170 HBITMAP 171 NTAPI 172 GreCreateBitmap( 173 _In_ ULONG nWidth, 174 _In_ ULONG nHeight, 175 _In_ ULONG cPlanes, 176 _In_ ULONG cBitsPixel, 177 _In_opt_ PVOID pvBits) 178 { 179 /* Call the extended function */ 180 return GreCreateBitmapEx(nWidth, 181 nHeight, 182 0, /* Auto width */ 183 BitmapFormat(cBitsPixel * cPlanes, BI_RGB), 184 0, /* No bitmap flags */ 185 0, /* Auto size */ 186 pvBits, 187 DDB_SURFACE /* DDB */); 188 } 189 190 HBITMAP 191 APIENTRY 192 NtGdiCreateBitmap( 193 IN INT nWidth, 194 IN INT nHeight, 195 IN UINT cPlanes, 196 IN UINT cBitsPixel, 197 IN OPTIONAL LPBYTE pUnsafeBits) 198 { 199 HBITMAP hbmp; 200 ULONG cRealBpp, cjWidthBytes, iFormat; 201 ULONGLONG cjSize; 202 PSURFACE psurf; 203 204 /* Calculate bitmap format and real bits per pixel. */ 205 iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB); 206 cRealBpp = gajBitsPerFormat[iFormat]; 207 208 /* Calculate width and image size in bytes */ 209 cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp); 210 cjSize = (ULONGLONG)cjWidthBytes * nHeight; 211 212 /* Check parameters (possible overflow of cjSize!) */ 213 if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) || 214 (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL)) 215 { 216 DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n", 217 nWidth, nHeight, cBitsPixel, cPlanes); 218 EngSetLastError(ERROR_INVALID_PARAMETER); 219 return NULL; 220 } 221 222 /* Allocate the surface (but don't set the bits) */ 223 psurf = SURFACE_AllocSurface(STYPE_BITMAP, 224 nWidth, 225 nHeight, 226 iFormat, 227 0, 228 0, 229 0, 230 NULL); 231 if (!psurf) 232 { 233 DPRINT1("SURFACE_AllocSurface failed.\n"); 234 return NULL; 235 } 236 237 /* Mark as API and DDB bitmap */ 238 psurf->flags |= (API_BITMAP | DDB_SURFACE); 239 240 /* Check if we have bits to set */ 241 if (pUnsafeBits) 242 { 243 /* Protect with SEH and copy the bits */ 244 _SEH2_TRY 245 { 246 ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1); 247 UnsafeSetBitmapBits(psurf, cjSize, pUnsafeBits); 248 } 249 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 250 { 251 GDIOBJ_vDeleteObject(&psurf->BaseObject); 252 _SEH2_YIELD(return NULL;) 253 } 254 _SEH2_END 255 } 256 else 257 { 258 /* Zero the bits */ 259 RtlZeroMemory(psurf->SurfObj.pvBits, psurf->SurfObj.cjBits); 260 } 261 262 /* Get the handle for the bitmap */ 263 hbmp = (HBITMAP)psurf->SurfObj.hsurf; 264 265 /* Unlock the surface */ 266 SURFACE_UnlockSurface(psurf); 267 268 return hbmp; 269 } 270 271 272 HBITMAP FASTCALL 273 IntCreateCompatibleBitmap( 274 PDC Dc, 275 INT Width, 276 INT Height, 277 UINT Planes, 278 UINT Bpp) 279 { 280 HBITMAP Bmp = NULL; 281 PPALETTE ppal; 282 283 /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */ 284 if (0 == Width || 0 == Height) 285 { 286 return NtGdiGetStockObject(DEFAULT_BITMAP); 287 } 288 289 if (Dc->dctype != DCTYPE_MEMORY) 290 { 291 PSURFACE psurf; 292 293 Bmp = GreCreateBitmap(abs(Width), 294 abs(Height), 295 Planes ? Planes : 1, 296 Bpp ? Bpp : Dc->ppdev->gdiinfo.cBitsPixel, 297 NULL); 298 if (Bmp == NULL) 299 { 300 DPRINT1("Failed to allocate a bitmap!\n"); 301 return NULL; 302 } 303 304 psurf = SURFACE_ShareLockSurface(Bmp); 305 ASSERT(psurf); 306 307 /* Dereference old palette and set new palette */ 308 ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault); 309 ASSERT(ppal); 310 SURFACE_vSetPalette(psurf, ppal); 311 PALETTE_ShareUnlockPalette(ppal); 312 313 /* Set flags */ 314 psurf->flags = API_BITMAP; 315 psurf->hdc = NULL; // FIXME: 316 psurf->SurfObj.hdev = (HDEV)Dc->ppdev; 317 SURFACE_ShareUnlockSurface(psurf); 318 } 319 else 320 { 321 DIBSECTION dibs; 322 INT Count; 323 PSURFACE psurf = Dc->dclevel.pSurface; 324 if(!psurf) psurf = psurfDefaultBitmap; 325 Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs); 326 327 if (Count == sizeof(BITMAP)) 328 { 329 PSURFACE psurfBmp; 330 331 Bmp = GreCreateBitmap(abs(Width), 332 abs(Height), 333 Planes ? Planes : 1, 334 Bpp ? Bpp : dibs.dsBm.bmBitsPixel, 335 NULL); 336 if (Bmp == NULL) 337 { 338 DPRINT1("Failed to allocate a bitmap!\n"); 339 return NULL; 340 } 341 psurfBmp = SURFACE_ShareLockSurface(Bmp); 342 ASSERT(psurfBmp); 343 344 /* Dereference old palette and set new palette */ 345 SURFACE_vSetPalette(psurfBmp, psurf->ppal); 346 347 /* Set flags */ 348 psurfBmp->flags = API_BITMAP; 349 psurfBmp->hdc = NULL; // FIXME: 350 psurfBmp->SurfObj.hdev = (HDEV)Dc->ppdev; 351 SURFACE_ShareUnlockSurface(psurfBmp); 352 } 353 else if (Count == sizeof(DIBSECTION)) 354 { 355 /* A DIB section is selected in the DC */ 356 BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0}; 357 PVOID Bits; 358 BITMAPINFO* bi = (BITMAPINFO*)buf; 359 360 bi->bmiHeader.biSize = sizeof(bi->bmiHeader); 361 bi->bmiHeader.biWidth = Width; 362 bi->bmiHeader.biHeight = Height; 363 bi->bmiHeader.biPlanes = Planes ? Planes : dibs.dsBmih.biPlanes; 364 bi->bmiHeader.biBitCount = Bpp ? Bpp : dibs.dsBmih.biBitCount; 365 bi->bmiHeader.biCompression = dibs.dsBmih.biCompression; 366 bi->bmiHeader.biSizeImage = 0; 367 bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter; 368 bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter; 369 bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed; 370 bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant; 371 372 if (bi->bmiHeader.biCompression == BI_BITFIELDS) 373 { 374 /* Copy the color masks */ 375 RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD)); 376 } 377 else if (bi->bmiHeader.biBitCount <= 8) 378 { 379 /* Copy the color table */ 380 UINT Index; 381 PPALETTE PalGDI; 382 383 if (!psurf->ppal) 384 { 385 EngSetLastError(ERROR_INVALID_HANDLE); 386 return 0; 387 } 388 389 PalGDI = psurf->ppal; 390 391 for (Index = 0; 392 Index < 256 && Index < PalGDI->NumColors; 393 Index++) 394 { 395 bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed; 396 bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen; 397 bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue; 398 bi->bmiColors[Index].rgbReserved = 0; 399 } 400 } 401 402 Bmp = DIB_CreateDIBSection(Dc, 403 bi, 404 DIB_RGB_COLORS, 405 &Bits, 406 NULL, 407 0, 408 0); 409 return Bmp; 410 } 411 } 412 return Bmp; 413 } 414 415 HBITMAP APIENTRY 416 NtGdiCreateCompatibleBitmap( 417 HDC hDC, 418 INT Width, 419 INT Height) 420 { 421 HBITMAP Bmp; 422 PDC Dc; 423 424 /* Check parameters */ 425 if ((Width <= 0) || (Height <= 0) || ((Width * Height) > 0x3FFFFFFF)) 426 { 427 EngSetLastError(ERROR_INVALID_PARAMETER); 428 return NULL; 429 } 430 431 if (!hDC) 432 return GreCreateBitmap(Width, Height, 1, 1, 0); 433 434 Dc = DC_LockDc(hDC); 435 436 DPRINT("NtGdiCreateCompatibleBitmap(%p,%d,%d, bpp:%u) = \n", 437 hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel); 438 439 if (NULL == Dc) 440 { 441 EngSetLastError(ERROR_INVALID_HANDLE); 442 return NULL; 443 } 444 445 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height, 0, 0); 446 447 DC_UnlockDc(Dc); 448 return Bmp; 449 } 450 451 BOOL 452 NTAPI 453 GreGetBitmapDimension( 454 _In_ HBITMAP hBitmap, 455 _Out_ LPSIZE psizDim) 456 { 457 PSURFACE psurfBmp; 458 459 if (hBitmap == NULL) 460 return FALSE; 461 462 /* Lock the bitmap */ 463 psurfBmp = SURFACE_ShareLockSurface(hBitmap); 464 if (psurfBmp == NULL) 465 { 466 EngSetLastError(ERROR_INVALID_HANDLE); 467 return FALSE; 468 } 469 470 *psizDim = psurfBmp->sizlDim; 471 472 /* Unlock the bitmap */ 473 SURFACE_ShareUnlockSurface(psurfBmp); 474 475 return TRUE; 476 } 477 478 BOOL 479 APIENTRY 480 NtGdiGetBitmapDimension( 481 HBITMAP hBitmap, 482 LPSIZE psizDim) 483 { 484 SIZE dim; 485 486 if (!GreGetBitmapDimension(hBitmap, &dim)) 487 return FALSE; 488 489 /* Use SEH to copy the data to the caller */ 490 _SEH2_TRY 491 { 492 ProbeForWrite(psizDim, sizeof(*psizDim), 1); 493 *psizDim = dim; 494 } 495 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 496 { 497 _SEH2_YIELD(return FALSE); 498 } 499 _SEH2_END 500 501 return TRUE; 502 } 503 504 505 LONG 506 FASTCALL 507 UnsafeGetBitmapBits( 508 PSURFACE psurf, 509 DWORD Bytes, 510 OUT PBYTE pvBits) 511 { 512 PUCHAR pjDst, pjSrc; 513 LONG lDeltaDst, lDeltaSrc, lDeltaSrcAbs; 514 ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel; 515 516 nWidth = psurf->SurfObj.sizlBitmap.cx; 517 nHeight = psurf->SurfObj.sizlBitmap.cy; 518 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 519 520 /* Get pointers */ 521 pjSrc = psurf->SurfObj.pvScan0; 522 pjDst = pvBits; 523 lDeltaSrc = psurf->SurfObj.lDelta; 524 lDeltaSrcAbs = labs(lDeltaSrc); 525 lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel); 526 NT_ASSERT(lDeltaSrcAbs >= lDeltaDst); 527 528 cbSrc = nHeight * lDeltaSrcAbs; 529 cbDst = nHeight * lDeltaDst; 530 Bytes = min(Bytes, cbDst); 531 532 iSrc = iDst = 0; 533 for (Y = 0; Y < nHeight; Y++) 534 { 535 if (iSrc + lDeltaSrcAbs > cbSrc || iDst + lDeltaDst > Bytes) 536 { 537 LONG lDelta = min(cbSrc - iSrc, Bytes - iDst); 538 NT_ASSERT(lDelta >= 0); 539 RtlCopyMemory(pjDst, pjSrc, lDelta); 540 iDst += lDelta; 541 break; 542 } 543 544 /* Copy one line */ 545 RtlCopyMemory(pjDst, pjSrc, lDeltaDst); 546 pjSrc += lDeltaSrc; 547 pjDst += lDeltaDst; 548 iSrc += lDeltaSrcAbs; 549 iDst += lDeltaDst; 550 } 551 552 return iDst; 553 } 554 555 LONG 556 APIENTRY 557 NtGdiGetBitmapBits( 558 HBITMAP hBitmap, 559 ULONG cjBuffer, 560 OUT OPTIONAL PBYTE pUnsafeBits) 561 { 562 PSURFACE psurf; 563 ULONG cjSize; 564 LONG ret; 565 566 /* Check parameters */ 567 if (pUnsafeBits != NULL && cjBuffer == 0) 568 { 569 return 0; 570 } 571 572 /* Lock the bitmap */ 573 psurf = SURFACE_ShareLockSurface(hBitmap); 574 if (!psurf) 575 { 576 EngSetLastError(ERROR_INVALID_HANDLE); 577 return 0; 578 } 579 580 /* Calculate the size of the bitmap in bytes */ 581 cjSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx, 582 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) * 583 psurf->SurfObj.sizlBitmap.cy; 584 585 /* If the bits vector is null, the function should return the read size */ 586 if (pUnsafeBits == NULL) 587 { 588 SURFACE_ShareUnlockSurface(psurf); 589 return cjSize; 590 } 591 592 /* Don't copy more bytes than the buffer has */ 593 cjBuffer = min(cjBuffer, cjSize); 594 595 // FIXME: Use MmSecureVirtualMemory 596 _SEH2_TRY 597 { 598 ProbeForWrite(pUnsafeBits, cjBuffer, 1); 599 ret = UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits); 600 } 601 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 602 { 603 ret = 0; 604 } 605 _SEH2_END 606 607 SURFACE_ShareUnlockSurface(psurf); 608 609 return ret; 610 } 611 612 613 LONG APIENTRY 614 NtGdiSetBitmapBits( 615 HBITMAP hBitmap, 616 DWORD Bytes, 617 IN PBYTE pUnsafeBits) 618 { 619 LONG ret; 620 PSURFACE psurf; 621 622 if (pUnsafeBits == NULL || Bytes == 0) 623 { 624 return 0; 625 } 626 627 if (GDI_HANDLE_IS_STOCKOBJ(hBitmap)) 628 { 629 return 0; 630 } 631 632 psurf = SURFACE_ShareLockSurface(hBitmap); 633 if (psurf == NULL) 634 { 635 EngSetLastError(ERROR_INVALID_HANDLE); 636 return 0; 637 } 638 639 if (((psurf->flags & API_BITMAP) == 0) || 640 (psurf->SurfObj.iBitmapFormat > BMF_32BPP)) 641 { 642 DPRINT1("Invalid bitmap: iBitmapFormat = %lu, flags = 0x%lx\n", 643 psurf->SurfObj.iBitmapFormat, 644 psurf->flags); 645 EngSetLastError(ERROR_INVALID_HANDLE); 646 SURFACE_ShareUnlockSurface(psurf); 647 return 0; 648 } 649 650 _SEH2_TRY 651 { 652 /* NOTE: Win2k3 doesn't check WORD alignment here. */ 653 ProbeForWrite(pUnsafeBits, Bytes, 1); 654 ret = UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits); 655 } 656 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 657 { 658 ret = 0; 659 } 660 _SEH2_END 661 662 SURFACE_ShareUnlockSurface(psurf); 663 664 return ret; 665 } 666 667 BOOL APIENTRY 668 NtGdiSetBitmapDimension( 669 HBITMAP hBitmap, 670 INT Width, 671 INT Height, 672 LPSIZE Size) 673 { 674 PSURFACE psurf; 675 BOOL Ret = TRUE; 676 677 if (hBitmap == NULL) 678 return FALSE; 679 680 psurf = SURFACE_ShareLockSurface(hBitmap); 681 if (psurf == NULL) 682 { 683 EngSetLastError(ERROR_INVALID_HANDLE); 684 return FALSE; 685 } 686 687 if (Size) 688 { 689 _SEH2_TRY 690 { 691 ProbeForWrite(Size, sizeof(SIZE), 1); 692 *Size = psurf->sizlDim; 693 } 694 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 695 { 696 Ret = FALSE; 697 } 698 _SEH2_END 699 } 700 701 /* The dimension is changed even if writing the old value failed */ 702 psurf->sizlDim.cx = Width; 703 psurf->sizlDim.cy = Height; 704 705 SURFACE_ShareUnlockSurface(psurf); 706 707 return Ret; 708 } 709 710 /* Internal Functions */ 711 712 HBITMAP 713 FASTCALL 714 BITMAP_CopyBitmap(HBITMAP hBitmap) 715 { 716 HBITMAP hbmNew; 717 SURFACE *psurfSrc, *psurfNew; 718 719 /* Fail, if no source bitmap is given */ 720 if (hBitmap == NULL) return 0; 721 722 /* Lock the source bitmap */ 723 psurfSrc = SURFACE_ShareLockSurface(hBitmap); 724 if (psurfSrc == NULL) 725 { 726 return 0; 727 } 728 729 /* Allocate a new bitmap with the same dimensions as the source bmp */ 730 hbmNew = GreCreateBitmapEx(psurfSrc->SurfObj.sizlBitmap.cx, 731 psurfSrc->SurfObj.sizlBitmap.cy, 732 abs(psurfSrc->SurfObj.lDelta), 733 psurfSrc->SurfObj.iBitmapFormat, 734 psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN, 735 psurfSrc->SurfObj.cjBits, 736 NULL, 737 psurfSrc->flags); 738 739 if (hbmNew) 740 { 741 /* Lock the new bitmap */ 742 psurfNew = SURFACE_ShareLockSurface(hbmNew); 743 if (psurfNew) 744 { 745 /* Copy the bitmap bits to the new bitmap buffer */ 746 RtlCopyMemory(psurfNew->SurfObj.pvBits, 747 psurfSrc->SurfObj.pvBits, 748 psurfNew->SurfObj.cjBits); 749 750 751 /* Reference the palette of the source bitmap and use it */ 752 SURFACE_vSetPalette(psurfNew, psurfSrc->ppal); 753 754 /* Unlock the new surface */ 755 SURFACE_ShareUnlockSurface(psurfNew); 756 } 757 else 758 { 759 /* Failed to lock the bitmap, shouldn't happen */ 760 GreDeleteObject(hbmNew); 761 hbmNew = NULL; 762 } 763 } 764 765 /* Unlock the source bitmap and return the handle of the new bitmap */ 766 SURFACE_ShareUnlockSurface(psurfSrc); 767 return hbmNew; 768 } 769 770 INT APIENTRY 771 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer) 772 { 773 PBITMAP pBitmap; 774 775 if (!buffer) return sizeof(BITMAP); 776 if ((UINT)Count < sizeof(BITMAP)) return 0; 777 778 /* Always fill a basic BITMAP structure */ 779 pBitmap = buffer; 780 pBitmap->bmType = 0; 781 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx; 782 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy; 783 pBitmap->bmPlanes = 1; 784 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 785 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel); 786 787 /* Check for DIB section */ 788 if (psurf->hSecure) 789 { 790 /* Set bmBits in this case */ 791 pBitmap->bmBits = psurf->SurfObj.pvBits; 792 /* DIBs data are 32 bits aligned */ 793 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel); 794 795 if (Count >= sizeof(DIBSECTION)) 796 { 797 /* Fill rest of DIBSECTION */ 798 PDIBSECTION pds = buffer; 799 800 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER); 801 pds->dsBmih.biWidth = pds->dsBm.bmWidth; 802 pds->dsBmih.biHeight = pds->dsBm.bmHeight; 803 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes; 804 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel; 805 806 switch (psurf->SurfObj.iBitmapFormat) 807 { 808 case BMF_1BPP: 809 case BMF_4BPP: 810 case BMF_8BPP: 811 pds->dsBmih.biCompression = BI_RGB; 812 break; 813 814 case BMF_16BPP: 815 if (psurf->ppal->flFlags & PAL_RGB16_555) 816 pds->dsBmih.biCompression = BI_RGB; 817 else 818 pds->dsBmih.biCompression = BI_BITFIELDS; 819 break; 820 821 case BMF_24BPP: 822 case BMF_32BPP: 823 /* 24/32bpp BI_RGB is actually BGR format */ 824 if (psurf->ppal->flFlags & PAL_BGR) 825 pds->dsBmih.biCompression = BI_RGB; 826 else 827 pds->dsBmih.biCompression = BI_BITFIELDS; 828 break; 829 830 case BMF_4RLE: 831 pds->dsBmih.biCompression = BI_RLE4; 832 break; 833 case BMF_8RLE: 834 pds->dsBmih.biCompression = BI_RLE8; 835 break; 836 case BMF_JPEG: 837 pds->dsBmih.biCompression = BI_JPEG; 838 break; 839 case BMF_PNG: 840 pds->dsBmih.biCompression = BI_PNG; 841 break; 842 default: 843 ASSERT(FALSE); /* This shouldn't happen */ 844 } 845 846 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits; 847 pds->dsBmih.biXPelsPerMeter = 0; 848 pds->dsBmih.biYPelsPerMeter = 0; 849 pds->dsBmih.biClrUsed = psurf->ppal->NumColors; 850 pds->dsBmih.biClrImportant = psurf->biClrImportant; 851 pds->dsBitfields[0] = psurf->ppal->RedMask; 852 pds->dsBitfields[1] = psurf->ppal->GreenMask; 853 pds->dsBitfields[2] = psurf->ppal->BlueMask; 854 pds->dshSection = psurf->hDIBSection; 855 pds->dsOffset = psurf->dwOffset; 856 857 return sizeof(DIBSECTION); 858 } 859 } 860 else 861 { 862 /* Not set according to wine test, confirmed in win2k */ 863 pBitmap->bmBits = NULL; 864 } 865 866 return sizeof(BITMAP); 867 } 868 869 /* 870 * @implemented 871 */ 872 HDC 873 APIENTRY 874 NtGdiGetDCforBitmap( 875 IN HBITMAP hsurf) 876 { 877 HDC hdc = NULL; 878 PSURFACE psurf = SURFACE_ShareLockSurface(hsurf); 879 if (psurf) 880 { 881 hdc = psurf->hdc; 882 SURFACE_ShareUnlockSurface(psurf); 883 } 884 return hdc; 885 } 886 887 888 /* EOF */ 889