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 != DC_TYPE_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 psurfBmp = SURFACE_ShareLockSurface(Bmp); 337 ASSERT(psurfBmp); 338 339 /* Dereference old palette and set new palette */ 340 SURFACE_vSetPalette(psurfBmp, psurf->ppal); 341 342 /* Set flags */ 343 psurfBmp->flags = API_BITMAP; 344 psurfBmp->hdc = NULL; // FIXME: 345 psurf->SurfObj.hdev = (HDEV)Dc->ppdev; 346 SURFACE_ShareUnlockSurface(psurfBmp); 347 } 348 else if (Count == sizeof(DIBSECTION)) 349 { 350 /* A DIB section is selected in the DC */ 351 BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0}; 352 PVOID Bits; 353 BITMAPINFO* bi = (BITMAPINFO*)buf; 354 355 bi->bmiHeader.biSize = sizeof(bi->bmiHeader); 356 bi->bmiHeader.biWidth = Width; 357 bi->bmiHeader.biHeight = Height; 358 bi->bmiHeader.biPlanes = Planes ? Planes : dibs.dsBmih.biPlanes; 359 bi->bmiHeader.biBitCount = Bpp ? Bpp : dibs.dsBmih.biBitCount; 360 bi->bmiHeader.biCompression = dibs.dsBmih.biCompression; 361 bi->bmiHeader.biSizeImage = 0; 362 bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter; 363 bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter; 364 bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed; 365 bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant; 366 367 if (bi->bmiHeader.biCompression == BI_BITFIELDS) 368 { 369 /* Copy the color masks */ 370 RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD)); 371 } 372 else if (bi->bmiHeader.biBitCount <= 8) 373 { 374 /* Copy the color table */ 375 UINT Index; 376 PPALETTE PalGDI; 377 378 if (!psurf->ppal) 379 { 380 EngSetLastError(ERROR_INVALID_HANDLE); 381 return 0; 382 } 383 384 PalGDI = psurf->ppal; 385 386 for (Index = 0; 387 Index < 256 && Index < PalGDI->NumColors; 388 Index++) 389 { 390 bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed; 391 bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen; 392 bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue; 393 bi->bmiColors[Index].rgbReserved = 0; 394 } 395 } 396 397 Bmp = DIB_CreateDIBSection(Dc, 398 bi, 399 DIB_RGB_COLORS, 400 &Bits, 401 NULL, 402 0, 403 0); 404 return Bmp; 405 } 406 } 407 return Bmp; 408 } 409 410 HBITMAP APIENTRY 411 NtGdiCreateCompatibleBitmap( 412 HDC hDC, 413 INT Width, 414 INT Height) 415 { 416 HBITMAP Bmp; 417 PDC Dc; 418 419 /* Check parameters */ 420 if ((Width <= 0) || (Height <= 0) || ((Width * Height) > 0x3FFFFFFF)) 421 { 422 EngSetLastError(ERROR_INVALID_PARAMETER); 423 return NULL; 424 } 425 426 if (!hDC) 427 return GreCreateBitmap(Width, Height, 1, 1, 0); 428 429 Dc = DC_LockDc(hDC); 430 431 DPRINT("NtGdiCreateCompatibleBitmap(%p,%d,%d, bpp:%u) = \n", 432 hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel); 433 434 if (NULL == Dc) 435 { 436 EngSetLastError(ERROR_INVALID_HANDLE); 437 return NULL; 438 } 439 440 Bmp = IntCreateCompatibleBitmap(Dc, Width, Height, 0, 0); 441 442 DC_UnlockDc(Dc); 443 return Bmp; 444 } 445 446 BOOL 447 NTAPI 448 GreGetBitmapDimension( 449 _In_ HBITMAP hBitmap, 450 _Out_ LPSIZE psizDim) 451 { 452 PSURFACE psurfBmp; 453 454 if (hBitmap == NULL) 455 return FALSE; 456 457 /* Lock the bitmap */ 458 psurfBmp = SURFACE_ShareLockSurface(hBitmap); 459 if (psurfBmp == NULL) 460 { 461 EngSetLastError(ERROR_INVALID_HANDLE); 462 return FALSE; 463 } 464 465 *psizDim = psurfBmp->sizlDim; 466 467 /* Unlock the bitmap */ 468 SURFACE_ShareUnlockSurface(psurfBmp); 469 470 return TRUE; 471 } 472 473 BOOL 474 APIENTRY 475 NtGdiGetBitmapDimension( 476 HBITMAP hBitmap, 477 LPSIZE psizDim) 478 { 479 SIZE dim; 480 481 if (!GreGetBitmapDimension(hBitmap, &dim)) 482 return FALSE; 483 484 /* Use SEH to copy the data to the caller */ 485 _SEH2_TRY 486 { 487 ProbeForWrite(psizDim, sizeof(*psizDim), 1); 488 *psizDim = dim; 489 } 490 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 491 { 492 _SEH2_YIELD(return FALSE); 493 } 494 _SEH2_END 495 496 return TRUE; 497 } 498 499 500 LONG 501 FASTCALL 502 UnsafeGetBitmapBits( 503 PSURFACE psurf, 504 DWORD Bytes, 505 OUT PBYTE pvBits) 506 { 507 PUCHAR pjDst, pjSrc; 508 LONG lDeltaDst, lDeltaSrc, lDeltaSrcAbs; 509 ULONG Y, iSrc, iDst, cbSrc, cbDst, nWidth, nHeight, cBitsPixel; 510 511 nWidth = psurf->SurfObj.sizlBitmap.cx; 512 nHeight = psurf->SurfObj.sizlBitmap.cy; 513 cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 514 515 /* Get pointers */ 516 pjSrc = psurf->SurfObj.pvScan0; 517 pjDst = pvBits; 518 lDeltaSrc = psurf->SurfObj.lDelta; 519 lDeltaSrcAbs = labs(lDeltaSrc); 520 lDeltaDst = WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel); 521 NT_ASSERT(lDeltaSrcAbs >= lDeltaDst); 522 523 cbSrc = nHeight * lDeltaSrcAbs; 524 cbDst = nHeight * lDeltaDst; 525 Bytes = min(Bytes, cbDst); 526 527 iSrc = iDst = 0; 528 for (Y = 0; Y < nHeight; Y++) 529 { 530 if (iSrc + lDeltaSrcAbs > cbSrc || iDst + lDeltaDst > Bytes) 531 { 532 LONG lDelta = min(cbSrc - iSrc, Bytes - iDst); 533 NT_ASSERT(lDelta >= 0); 534 RtlCopyMemory(pjDst, pjSrc, lDelta); 535 iDst += lDelta; 536 break; 537 } 538 539 /* Copy one line */ 540 RtlCopyMemory(pjDst, pjSrc, lDeltaDst); 541 pjSrc += lDeltaSrc; 542 pjDst += lDeltaDst; 543 iSrc += lDeltaSrcAbs; 544 iDst += lDeltaDst; 545 } 546 547 return iDst; 548 } 549 550 LONG 551 APIENTRY 552 NtGdiGetBitmapBits( 553 HBITMAP hBitmap, 554 ULONG cjBuffer, 555 OUT OPTIONAL PBYTE pUnsafeBits) 556 { 557 PSURFACE psurf; 558 ULONG cjSize; 559 LONG ret; 560 561 /* Check parameters */ 562 if (pUnsafeBits != NULL && cjBuffer == 0) 563 { 564 return 0; 565 } 566 567 /* Lock the bitmap */ 568 psurf = SURFACE_ShareLockSurface(hBitmap); 569 if (!psurf) 570 { 571 EngSetLastError(ERROR_INVALID_HANDLE); 572 return 0; 573 } 574 575 /* Calculate the size of the bitmap in bytes */ 576 cjSize = WIDTH_BYTES_ALIGN16(psurf->SurfObj.sizlBitmap.cx, 577 BitsPerFormat(psurf->SurfObj.iBitmapFormat)) * 578 psurf->SurfObj.sizlBitmap.cy; 579 580 /* If the bits vector is null, the function should return the read size */ 581 if (pUnsafeBits == NULL) 582 { 583 SURFACE_ShareUnlockSurface(psurf); 584 return cjSize; 585 } 586 587 /* Don't copy more bytes than the buffer has */ 588 cjBuffer = min(cjBuffer, cjSize); 589 590 // FIXME: Use MmSecureVirtualMemory 591 _SEH2_TRY 592 { 593 ProbeForWrite(pUnsafeBits, cjBuffer, 1); 594 ret = UnsafeGetBitmapBits(psurf, cjBuffer, pUnsafeBits); 595 } 596 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 597 { 598 ret = 0; 599 } 600 _SEH2_END 601 602 SURFACE_ShareUnlockSurface(psurf); 603 604 return ret; 605 } 606 607 608 LONG APIENTRY 609 NtGdiSetBitmapBits( 610 HBITMAP hBitmap, 611 DWORD Bytes, 612 IN PBYTE pUnsafeBits) 613 { 614 LONG ret; 615 PSURFACE psurf; 616 617 if (pUnsafeBits == NULL || Bytes == 0) 618 { 619 return 0; 620 } 621 622 if (GDI_HANDLE_IS_STOCKOBJ(hBitmap)) 623 { 624 return 0; 625 } 626 627 psurf = SURFACE_ShareLockSurface(hBitmap); 628 if (psurf == NULL) 629 { 630 EngSetLastError(ERROR_INVALID_HANDLE); 631 return 0; 632 } 633 634 if (((psurf->flags & API_BITMAP) == 0) || 635 (psurf->SurfObj.iBitmapFormat > BMF_32BPP)) 636 { 637 DPRINT1("Invalid bitmap: iBitmapFormat = %lu, flags = 0x%lx\n", 638 psurf->SurfObj.iBitmapFormat, 639 psurf->flags); 640 EngSetLastError(ERROR_INVALID_HANDLE); 641 SURFACE_ShareUnlockSurface(psurf); 642 return 0; 643 } 644 645 _SEH2_TRY 646 { 647 /* NOTE: Win2k3 doesn't check WORD alignment here. */ 648 ProbeForWrite(pUnsafeBits, Bytes, 1); 649 ret = UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits); 650 } 651 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 652 { 653 ret = 0; 654 } 655 _SEH2_END 656 657 SURFACE_ShareUnlockSurface(psurf); 658 659 return ret; 660 } 661 662 BOOL APIENTRY 663 NtGdiSetBitmapDimension( 664 HBITMAP hBitmap, 665 INT Width, 666 INT Height, 667 LPSIZE Size) 668 { 669 PSURFACE psurf; 670 BOOL Ret = TRUE; 671 672 if (hBitmap == NULL) 673 return FALSE; 674 675 psurf = SURFACE_ShareLockSurface(hBitmap); 676 if (psurf == NULL) 677 { 678 EngSetLastError(ERROR_INVALID_HANDLE); 679 return FALSE; 680 } 681 682 if (Size) 683 { 684 _SEH2_TRY 685 { 686 ProbeForWrite(Size, sizeof(SIZE), 1); 687 *Size = psurf->sizlDim; 688 } 689 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) 690 { 691 Ret = FALSE; 692 } 693 _SEH2_END 694 } 695 696 /* The dimension is changed even if writing the old value failed */ 697 psurf->sizlDim.cx = Width; 698 psurf->sizlDim.cy = Height; 699 700 SURFACE_ShareUnlockSurface(psurf); 701 702 return Ret; 703 } 704 705 /* Internal Functions */ 706 707 HBITMAP 708 FASTCALL 709 BITMAP_CopyBitmap(HBITMAP hBitmap) 710 { 711 HBITMAP hbmNew; 712 SURFACE *psurfSrc, *psurfNew; 713 714 /* Fail, if no source bitmap is given */ 715 if (hBitmap == NULL) return 0; 716 717 /* Lock the source bitmap */ 718 psurfSrc = SURFACE_ShareLockSurface(hBitmap); 719 if (psurfSrc == NULL) 720 { 721 return 0; 722 } 723 724 /* Allocate a new bitmap with the same dimensions as the source bmp */ 725 hbmNew = GreCreateBitmapEx(psurfSrc->SurfObj.sizlBitmap.cx, 726 psurfSrc->SurfObj.sizlBitmap.cy, 727 abs(psurfSrc->SurfObj.lDelta), 728 psurfSrc->SurfObj.iBitmapFormat, 729 psurfSrc->SurfObj.fjBitmap & BMF_TOPDOWN, 730 psurfSrc->SurfObj.cjBits, 731 NULL, 732 psurfSrc->flags); 733 734 if (hbmNew) 735 { 736 /* Lock the new bitmap */ 737 psurfNew = SURFACE_ShareLockSurface(hbmNew); 738 if (psurfNew) 739 { 740 /* Copy the bitmap bits to the new bitmap buffer */ 741 RtlCopyMemory(psurfNew->SurfObj.pvBits, 742 psurfSrc->SurfObj.pvBits, 743 psurfNew->SurfObj.cjBits); 744 745 746 /* Reference the palette of the source bitmap and use it */ 747 SURFACE_vSetPalette(psurfNew, psurfSrc->ppal); 748 749 /* Unlock the new surface */ 750 SURFACE_ShareUnlockSurface(psurfNew); 751 } 752 else 753 { 754 /* Failed to lock the bitmap, shouldn't happen */ 755 GreDeleteObject(hbmNew); 756 hbmNew = NULL; 757 } 758 } 759 760 /* Unlock the source bitmap and return the handle of the new bitmap */ 761 SURFACE_ShareUnlockSurface(psurfSrc); 762 return hbmNew; 763 } 764 765 INT APIENTRY 766 BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer) 767 { 768 PBITMAP pBitmap; 769 770 if (!buffer) return sizeof(BITMAP); 771 if ((UINT)Count < sizeof(BITMAP)) return 0; 772 773 /* Always fill a basic BITMAP structure */ 774 pBitmap = buffer; 775 pBitmap->bmType = 0; 776 pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx; 777 pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy; 778 pBitmap->bmPlanes = 1; 779 pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); 780 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN16(pBitmap->bmWidth, pBitmap->bmBitsPixel); 781 782 /* Check for DIB section */ 783 if (psurf->hSecure) 784 { 785 /* Set bmBits in this case */ 786 pBitmap->bmBits = psurf->SurfObj.pvBits; 787 /* DIBs data are 32 bits aligned */ 788 pBitmap->bmWidthBytes = WIDTH_BYTES_ALIGN32(pBitmap->bmWidth, pBitmap->bmBitsPixel); 789 790 if (Count >= sizeof(DIBSECTION)) 791 { 792 /* Fill rest of DIBSECTION */ 793 PDIBSECTION pds = buffer; 794 795 pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER); 796 pds->dsBmih.biWidth = pds->dsBm.bmWidth; 797 pds->dsBmih.biHeight = pds->dsBm.bmHeight; 798 pds->dsBmih.biPlanes = pds->dsBm.bmPlanes; 799 pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel; 800 801 switch (psurf->SurfObj.iBitmapFormat) 802 { 803 case BMF_1BPP: 804 case BMF_4BPP: 805 case BMF_8BPP: 806 pds->dsBmih.biCompression = BI_RGB; 807 break; 808 809 case BMF_16BPP: 810 if (psurf->ppal->flFlags & PAL_RGB16_555) 811 pds->dsBmih.biCompression = BI_RGB; 812 else 813 pds->dsBmih.biCompression = BI_BITFIELDS; 814 break; 815 816 case BMF_24BPP: 817 case BMF_32BPP: 818 /* 24/32bpp BI_RGB is actually BGR format */ 819 if (psurf->ppal->flFlags & PAL_BGR) 820 pds->dsBmih.biCompression = BI_RGB; 821 else 822 pds->dsBmih.biCompression = BI_BITFIELDS; 823 break; 824 825 case BMF_4RLE: 826 pds->dsBmih.biCompression = BI_RLE4; 827 break; 828 case BMF_8RLE: 829 pds->dsBmih.biCompression = BI_RLE8; 830 break; 831 case BMF_JPEG: 832 pds->dsBmih.biCompression = BI_JPEG; 833 break; 834 case BMF_PNG: 835 pds->dsBmih.biCompression = BI_PNG; 836 break; 837 default: 838 ASSERT(FALSE); /* This shouldn't happen */ 839 } 840 841 pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits; 842 pds->dsBmih.biXPelsPerMeter = 0; 843 pds->dsBmih.biYPelsPerMeter = 0; 844 pds->dsBmih.biClrUsed = psurf->ppal->NumColors; 845 pds->dsBmih.biClrImportant = psurf->biClrImportant; 846 pds->dsBitfields[0] = psurf->ppal->RedMask; 847 pds->dsBitfields[1] = psurf->ppal->GreenMask; 848 pds->dsBitfields[2] = psurf->ppal->BlueMask; 849 pds->dshSection = psurf->hDIBSection; 850 pds->dsOffset = psurf->dwOffset; 851 852 return sizeof(DIBSECTION); 853 } 854 } 855 else 856 { 857 /* Not set according to wine test, confirmed in win2k */ 858 pBitmap->bmBits = NULL; 859 } 860 861 return sizeof(BITMAP); 862 } 863 864 /* 865 * @implemented 866 */ 867 HDC 868 APIENTRY 869 NtGdiGetDCforBitmap( 870 IN HBITMAP hsurf) 871 { 872 HDC hdc = NULL; 873 PSURFACE psurf = SURFACE_ShareLockSurface(hsurf); 874 if (psurf) 875 { 876 hdc = psurf->hdc; 877 SURFACE_ShareUnlockSurface(psurf); 878 } 879 return hdc; 880 } 881 882 883 /* EOF */ 884