/* * ReactOS W32 Subsystem * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #define NDEBUG #include LONG APIENTRY IntSetBitmapBits( PSURFACE psurf, DWORD Bytes, IN PBYTE Bits) { /* Don't copy more bytes than the buffer has */ Bytes = min(Bytes, psurf->SurfObj.cjBits); RtlCopyMemory(psurf->SurfObj.pvBits, Bits, Bytes); return Bytes; } void NTAPI UnsafeSetBitmapBits( PSURFACE psurf, IN ULONG cjBits, IN PVOID pvBits) { PUCHAR pjDst, pjSrc; LONG lDeltaDst, lDeltaSrc; ULONG nWidth, nHeight, cBitsPixel; nWidth = psurf->SurfObj.sizlBitmap.cx; nHeight = psurf->SurfObj.sizlBitmap.cy; cBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); /* Get pointers */ pjDst = psurf->SurfObj.pvScan0; pjSrc = pvBits; lDeltaDst = psurf->SurfObj.lDelta; lDeltaSrc = BITMAP_GetWidthBytes(nWidth, cBitsPixel); while (nHeight--) { /* Copy one line */ memcpy(pjDst, pjSrc, lDeltaSrc); pjSrc += lDeltaSrc; pjDst += lDeltaDst; } } HBITMAP APIENTRY GreCreateBitmapEx( IN INT nWidth, IN INT nHeight, IN ULONG cjWidthBytes, IN ULONG iFormat, IN USHORT fjBitmap, IN ULONG cjSizeImage, IN OPTIONAL PVOID pvBits, IN FLONG flags) { PSURFACE psurf; SURFOBJ *pso; HBITMAP hbmp; PVOID pvCompressedBits; SIZEL sizl; /* Verify format */ if (iFormat < BMF_1BPP || iFormat > BMF_PNG) return NULL; /* Allocate a surface */ psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); return NULL; } /* Get the handle for the bitmap and the surfobj */ hbmp = (HBITMAP)psurf->SurfObj.hsurf; pso = &psurf->SurfObj; /* The infamous RLE hack */ if (iFormat == BMF_4RLE) { sizl.cx = nWidth; sizl.cy = nHeight; pvCompressedBits = pvBits; pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); Decompress4bpp(sizl, pvCompressedBits, pvBits, pso->lDelta); fjBitmap |= BMF_RLE_HACK; } else if (iFormat == BMF_8RLE) { sizl.cx = nWidth; sizl.cy = nHeight; pvCompressedBits = pvBits; pvBits = EngAllocMem(FL_ZERO_MEMORY, pso->cjBits, TAG_DIB); Decompress8bpp(sizl, pvCompressedBits, pvBits, pso->lDelta); fjBitmap |= BMF_RLE_HACK; } /* Mark as API bitmap */ psurf->flags |= (flags | API_BITMAP); /* Set the bitmap bits */ if (!SURFACE_bSetBitmapBits(psurf, fjBitmap, cjWidthBytes, pvBits)) { /* Bail out if that failed */ DPRINT1("SURFACE_bSetBitmapBits failed.\n"); SURFACE_FreeSurfaceByHandle(hbmp); return NULL; } /* Unlock the surface and return */ SURFACE_UnlockSurface(psurf); return hbmp; } /* Creates a DDB surface, * as in CreateCompatibleBitmap or CreateBitmap. */ HBITMAP APIENTRY GreCreateBitmap( IN INT nWidth, IN INT nHeight, IN UINT cPlanes, IN UINT cBitsPixel, IN OPTIONAL PVOID pvBits) { /* Call the extended function */ return GreCreateBitmapEx(nWidth, nHeight, 0, /* auto width */ BitmapFormat(cBitsPixel * cPlanes, BI_RGB), 0, /* no bitmap flags */ 0, /* auto size */ pvBits, DDB_SURFACE /* DDB */); } HBITMAP APIENTRY NtGdiCreateBitmap( IN INT nWidth, IN INT nHeight, IN UINT cPlanes, IN UINT cBitsPixel, IN OPTIONAL LPBYTE pUnsafeBits) { HBITMAP hbmp; ULONG cjWidthBytes, iFormat; /* NOTE: Windows also doesn't store nr. of planes separately! */ cBitsPixel = BITMAP_GetRealBitsPixel(cBitsPixel * cPlanes); /* Calculate bitmap format */ iFormat = BitmapFormat(cBitsPixel, BI_RGB); /* Check parameters */ if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0) { DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", nWidth, nHeight, cBitsPixel); EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* Make sure that cjBits will not overflow */ cjWidthBytes = BITMAP_GetWidthBytes(nWidth, cBitsPixel); if ((ULONGLONG)cjWidthBytes * nHeight >= 0x100000000ULL) { DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", nWidth, nHeight, cBitsPixel); EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* cBitsPixel = cBitsPixel * cPlanes now! */ hbmp = GreCreateBitmap(nWidth, nHeight, 1, cBitsPixel, NULL); if (pUnsafeBits) { PSURFACE psurf = SURFACE_LockSurface(hbmp); _SEH2_TRY { ProbeForRead(pUnsafeBits, cjWidthBytes * nHeight, 1); UnsafeSetBitmapBits(psurf, 0, pUnsafeBits); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SURFACE_UnlockSurface(psurf); SURFACE_FreeSurfaceByHandle(hbmp); _SEH2_YIELD(return NULL;) } _SEH2_END SURFACE_UnlockSurface(psurf); } return hbmp; } HBITMAP FASTCALL IntCreateCompatibleBitmap( PDC Dc, INT Width, INT Height) { HBITMAP Bmp = NULL; /* MS doc says if width or height is 0, return 1-by-1 pixel, monochrome bitmap */ if (0 == Width || 0 == Height) { Bmp = NtGdiGetStockObject(DEFAULT_BITMAP); } else { if (Dc->dctype != DC_TYPE_MEMORY) { PSURFACE psurf; SIZEL size; size.cx = abs(Width); size.cy = abs(Height); Bmp = GreCreateBitmap(abs(Width), abs(Height), 1, Dc->ppdev->gdiinfo.cBitsPixel, NULL); psurf = SURFACE_LockSurface(Bmp); ASSERT(psurf); /* Set palette */ psurf->ppal = PALETTE_ShareLockPalette(Dc->ppdev->devinfo.hpalDefault); /* Set flags */ psurf->flags = API_BITMAP; psurf->hdc = NULL; // Fixme SURFACE_UnlockSurface(psurf); } else { DIBSECTION dibs; INT Count; PSURFACE psurf = Dc->dclevel.pSurface; Count = BITMAP_GetObject(psurf, sizeof(dibs), &dibs); if (Count) { if (Count == sizeof(BITMAP)) { SIZEL size; PSURFACE psurfBmp; size.cx = abs(Width); size.cy = abs(Height); Bmp = GreCreateBitmap(abs(Width), abs(Height), 1, dibs.dsBm.bmBitsPixel, NULL); psurfBmp = SURFACE_LockSurface(Bmp); ASSERT(psurfBmp); /* Assign palette */ psurfBmp->ppal = psurf->ppal; GDIOBJ_IncrementShareCount((POBJ)psurf->ppal); /* Set flags */ psurfBmp->flags = API_BITMAP; psurfBmp->hdc = NULL; // Fixme SURFACE_UnlockSurface(psurfBmp); } else { /* A DIB section is selected in the DC */ BYTE buf[sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD)] = {0}; PVOID Bits; BITMAPINFO* bi = (BITMAPINFO*)buf; bi->bmiHeader.biSize = sizeof(bi->bmiHeader); bi->bmiHeader.biWidth = Width; bi->bmiHeader.biHeight = Height; bi->bmiHeader.biPlanes = dibs.dsBmih.biPlanes; bi->bmiHeader.biBitCount = dibs.dsBmih.biBitCount; bi->bmiHeader.biCompression = dibs.dsBmih.biCompression; bi->bmiHeader.biSizeImage = 0; bi->bmiHeader.biXPelsPerMeter = dibs.dsBmih.biXPelsPerMeter; bi->bmiHeader.biYPelsPerMeter = dibs.dsBmih.biYPelsPerMeter; bi->bmiHeader.biClrUsed = dibs.dsBmih.biClrUsed; bi->bmiHeader.biClrImportant = dibs.dsBmih.biClrImportant; if (bi->bmiHeader.biCompression == BI_BITFIELDS) { /* Copy the color masks */ RtlCopyMemory(bi->bmiColors, dibs.dsBitfields, 3*sizeof(RGBQUAD)); } else if (bi->bmiHeader.biBitCount <= 8) { /* Copy the color table */ UINT Index; PPALETTE PalGDI; if (!psurf->ppal) { SetLastWin32Error(ERROR_INVALID_HANDLE); return 0; } PalGDI = PALETTE_LockPalette(psurf->ppal->BaseObject.hHmgr); for (Index = 0; Index < 256 && Index < PalGDI->NumColors; Index++) { bi->bmiColors[Index].rgbRed = PalGDI->IndexedColors[Index].peRed; bi->bmiColors[Index].rgbGreen = PalGDI->IndexedColors[Index].peGreen; bi->bmiColors[Index].rgbBlue = PalGDI->IndexedColors[Index].peBlue; bi->bmiColors[Index].rgbReserved = 0; } PALETTE_UnlockPalette(PalGDI); Bmp = DIB_CreateDIBSection(Dc, bi, DIB_RGB_COLORS, &Bits, NULL, 0, 0); return Bmp; } } } } } return Bmp; } HBITMAP APIENTRY NtGdiCreateCompatibleBitmap( HDC hDC, INT Width, INT Height) { HBITMAP Bmp; PDC Dc; if (Width <= 0 || Height <= 0 || (Width * Height) > 0x3FFFFFFF) { SetLastWin32Error(ERROR_INVALID_PARAMETER); return NULL; } if (!hDC) return GreCreateBitmap(Width, Height, 1, 1, 0); Dc = DC_LockDc(hDC); DPRINT("NtGdiCreateCompatibleBitmap(%04x,%d,%d, bpp:%d) = \n", hDC, Width, Height, Dc->ppdev->gdiinfo.cBitsPixel); if (NULL == Dc) { SetLastWin32Error(ERROR_INVALID_HANDLE); return NULL; } Bmp = IntCreateCompatibleBitmap(Dc, Width, Height); DPRINT("\t\t%04x\n", Bmp); DC_UnlockDc(Dc); return Bmp; } BOOL APIENTRY NtGdiGetBitmapDimension( HBITMAP hBitmap, LPSIZE Dimension) { PSURFACE psurfBmp; BOOL Ret = TRUE; if (hBitmap == NULL) return FALSE; psurfBmp = SURFACE_LockSurface(hBitmap); if (psurfBmp == NULL) { SetLastWin32Error(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForWrite(Dimension, sizeof(SIZE), 1); *Dimension = psurfBmp->sizlDim; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Ret = FALSE; } _SEH2_END SURFACE_UnlockSurface(psurfBmp); return Ret; } COLORREF APIENTRY NtGdiGetPixel(HDC hDC, INT XPos, INT YPos) { PDC dc = NULL; COLORREF Result = (COLORREF)CLR_INVALID; // default to failure BOOL bInRect = FALSE; SURFACE *psurf; SURFOBJ *pso; PPALETTE ppal; EXLATEOBJ exlo; HBITMAP hBmpTmp; dc = DC_LockDc(hDC); if (!dc) { SetLastWin32Error(ERROR_INVALID_HANDLE); return Result; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); return Result; } XPos += dc->ptlDCOrig.x; YPos += dc->ptlDCOrig.y; if (RECTL_bPointInRect(&dc->rosdc.CombinedClip->rclBounds, XPos, YPos)) { bInRect = TRUE; psurf = dc->dclevel.pSurface; if (psurf) { pso = &psurf->SurfObj; if (psurf->ppal) { ppal = psurf->ppal; GDIOBJ_IncrementShareCount(&ppal->BaseObject); } else ppal = PALETTE_ShareLockPalette(dc->ppdev->devinfo.hpalDefault); if (psurf->SurfObj.iBitmapFormat == BMF_1BPP && !psurf->hSecure) { /* FIXME: palette should be gpalMono already ! */ EXLATEOBJ_vInitialize(&exlo, &gpalMono, &gpalRGB, 0, 0xffffff, 0); } else { EXLATEOBJ_vInitialize(&exlo, ppal, &gpalRGB, 0, 0xffffff, 0); } // check if this DC has a DIB behind it... if (pso->pvScan0) // STYPE_BITMAP == pso->iType { ASSERT(pso->lDelta); Result = XLATEOBJ_iXlate(&exlo.xlo, DibFunctionsForBitmapFormat[pso->iBitmapFormat].DIB_GetPixel(pso, XPos, YPos)); } EXLATEOBJ_vCleanup(&exlo); PALETTE_ShareUnlockPalette(ppal); } } DC_UnlockDc(dc); // if Result is still CLR_INVALID, then the "quick" method above didn't work if (bInRect && Result == CLR_INVALID) { // FIXME: create a 1x1 32BPP DIB, and blit to it HDC hDCTmp = NtGdiCreateCompatibleDC(hDC); if (hDCTmp) { static const BITMAPINFOHEADER bih = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 32, BI_RGB, 0, 0, 0, 0, 0 }; BITMAPINFO bi; RtlMoveMemory(&(bi.bmiHeader), &bih, sizeof(bih)); hBmpTmp = NtGdiCreateDIBitmapInternal(hDC, bi.bmiHeader.biWidth, bi.bmiHeader.biHeight, 0, NULL, &bi, DIB_RGB_COLORS, bi.bmiHeader.biBitCount, bi.bmiHeader.biSizeImage, 0, 0); //HBITMAP hBmpTmp = GreCreateBitmap(1, 1, 1, 32, NULL); if (hBmpTmp) { HBITMAP hBmpOld = (HBITMAP)NtGdiSelectBitmap(hDCTmp, hBmpTmp); if (hBmpOld) { PSURFACE psurf; NtGdiBitBlt(hDCTmp, 0, 0, 1, 1, hDC, XPos, YPos, SRCCOPY, 0, 0); NtGdiSelectBitmap(hDCTmp, hBmpOld); // our bitmap is no longer selected, so we can access it's stuff... psurf = SURFACE_LockSurface(hBmpTmp); if (psurf) { // Dont you need to convert something here? Result = *(COLORREF*)psurf->SurfObj.pvScan0; SURFACE_UnlockSurface(psurf); } } GreDeleteObject(hBmpTmp); } NtGdiDeleteObjectApp(hDCTmp); } } return Result; } LONG APIENTRY IntGetBitmapBits( PSURFACE psurf, DWORD Bytes, OUT PBYTE Bits) { LONG ret; ASSERT(Bits); /* Don't copy more bytes than the buffer has */ Bytes = min(Bytes, psurf->SurfObj.cjBits); #if 0 /* FIXME: Call DDI CopyBits here if available */ if (psurf->DDBitmap) { DPRINT("Calling device specific BitmapBits\n"); if (psurf->DDBitmap->funcs->pBitmapBits) { ret = psurf->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count, DDB_GET); } else { ERR_(bitmap)("BitmapBits == NULL??\n"); ret = 0; } } else #endif { RtlCopyMemory(Bits, psurf->SurfObj.pvBits, Bytes); ret = Bytes; } return ret; } LONG APIENTRY NtGdiGetBitmapBits( HBITMAP hBitmap, ULONG Bytes, OUT OPTIONAL PBYTE pUnsafeBits) { PSURFACE psurf; LONG bmSize, ret; if (pUnsafeBits != NULL && Bytes == 0) { return 0; } psurf = SURFACE_LockSurface(hBitmap); if (!psurf) { SetLastWin32Error(ERROR_INVALID_HANDLE); return 0; } bmSize = BITMAP_GetWidthBytes(psurf->SurfObj.sizlBitmap.cx, BitsPerFormat(psurf->SurfObj.iBitmapFormat)) * abs(psurf->SurfObj.sizlBitmap.cy); /* If the bits vector is null, the function should return the read size */ if (pUnsafeBits == NULL) { SURFACE_UnlockSurface(psurf); return bmSize; } /* Don't copy more bytes than the buffer has */ Bytes = min(Bytes, bmSize); // FIXME: use MmSecureVirtualMemory _SEH2_TRY { ProbeForWrite(pUnsafeBits, Bytes, 1); ret = IntGetBitmapBits(psurf, Bytes, pUnsafeBits); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ret = 0; } _SEH2_END SURFACE_UnlockSurface(psurf); return ret; } LONG APIENTRY NtGdiSetBitmapBits( HBITMAP hBitmap, DWORD Bytes, IN PBYTE pUnsafeBits) { LONG ret; PSURFACE psurf; if (pUnsafeBits == NULL || Bytes == 0) { return 0; } psurf = SURFACE_LockSurface(hBitmap); if (psurf == NULL) { SetLastWin32Error(ERROR_INVALID_HANDLE); return 0; } _SEH2_TRY { ProbeForRead(pUnsafeBits, Bytes, 1); UnsafeSetBitmapBits(psurf, Bytes, pUnsafeBits); ret = 1; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ret = 0; } _SEH2_END SURFACE_UnlockSurface(psurf); return ret; } BOOL APIENTRY NtGdiSetBitmapDimension( HBITMAP hBitmap, INT Width, INT Height, LPSIZE Size) { PSURFACE psurf; BOOL Ret = TRUE; if (hBitmap == NULL) return FALSE; psurf = SURFACE_LockSurface(hBitmap); if (psurf == NULL) { SetLastWin32Error(ERROR_INVALID_HANDLE); return FALSE; } if (Size) { _SEH2_TRY { ProbeForWrite(Size, sizeof(SIZE), 1); *Size = psurf->sizlDim; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Ret = FALSE; } _SEH2_END } /* The dimension is changed even if writing the old value failed */ psurf->sizlDim.cx = Width; psurf->sizlDim.cy = Height; SURFACE_UnlockSurface(psurf); return Ret; } VOID IntHandleSpecialColorType(HDC hDC, COLORREF* Color) { PDC pdc = NULL; RGBQUAD quad; PALETTEENTRY palEntry; UINT index; switch (*Color >> 24) { case 0x10: /* DIBINDEX */ if (IntGetDIBColorTable(hDC, LOWORD(*Color), 1, &quad) == 1) { *Color = RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue); } else { /* Out of color table bounds - use black */ *Color = RGB(0, 0, 0); } break; case 0x02: /* PALETTERGB */ pdc = DC_LockDc(hDC); if (pdc->dclevel.hpal != NtGdiGetStockObject(DEFAULT_PALETTE)) { index = NtGdiGetNearestPaletteIndex(pdc->dclevel.hpal, *Color); IntGetPaletteEntries(pdc->dclevel.hpal, index, 1, &palEntry); *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); } else { /* Use the pure color */ *Color = *Color & 0x00FFFFFF; } DC_UnlockDc(pdc); break; case 0x01: /* PALETTEINDEX */ pdc = DC_LockDc(hDC); if (IntGetPaletteEntries(pdc->dclevel.hpal, LOWORD(*Color), 1, &palEntry) == 1) { *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); } else { /* Index does not exist, use zero index */ IntGetPaletteEntries(pdc->dclevel.hpal, 0, 1, &palEntry); *Color = RGB(palEntry.peRed, palEntry.peGreen, palEntry.peBlue); } DC_UnlockDc(pdc); break; default: DPRINT("Unsupported color type %d passed\n", *Color >> 24); break; } } BOOL APIENTRY GdiSetPixelV( HDC hDC, INT X, INT Y, COLORREF Color) { HBRUSH hBrush; HGDIOBJ OldBrush; if ((Color & 0xFF000000) != 0) { IntHandleSpecialColorType(hDC, &Color); } hBrush = NtGdiCreateSolidBrush(Color, NULL); if (hBrush == NULL) return FALSE; OldBrush = NtGdiSelectBrush(hDC, hBrush); if (OldBrush == NULL) { GreDeleteObject(hBrush); return FALSE; } NtGdiPatBlt(hDC, X, Y, 1, 1, PATCOPY); NtGdiSelectBrush(hDC, OldBrush); GreDeleteObject(hBrush); return TRUE; } COLORREF APIENTRY NtGdiSetPixel( HDC hDC, INT X, INT Y, COLORREF Color) { DPRINT("0 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); if (GdiSetPixelV(hDC,X,Y,Color)) { Color = NtGdiGetPixel(hDC,X,Y); DPRINT("1 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); return Color; } Color = (COLORREF)CLR_INVALID; DPRINT("2 NtGdiSetPixel X %ld Y %ld C %ld\n", X, Y, Color); return Color; } /* Internal Functions */ UINT FASTCALL BITMAP_GetRealBitsPixel(UINT nBitsPixel) { if (nBitsPixel <= 1) return 1; if (nBitsPixel <= 4) return 4; if (nBitsPixel <= 8) return 8; if (nBitsPixel <= 16) return 16; if (nBitsPixel <= 24) return 24; if (nBitsPixel <= 32) return 32; return 0; } INT FASTCALL BITMAP_GetWidthBytes(INT bmWidth, INT bpp) { #if 0 switch (bpp) { case 1: return 2 * ((bmWidth+15) >> 4); case 24: bmWidth *= 3; /* fall through */ case 8: return bmWidth + (bmWidth & 1); case 32: return bmWidth * 4; case 16: case 15: return bmWidth * 2; case 4: return 2 * ((bmWidth+3) >> 2); default: DPRINT ("stub"); } return -1; #endif return ((bmWidth * bpp + 15) & ~15) >> 3; } HBITMAP FASTCALL BITMAP_CopyBitmap(HBITMAP hBitmap) { HBITMAP res; BITMAP bm; SURFACE *Bitmap, *resBitmap; SIZEL Size; if (hBitmap == NULL) { return 0; } Bitmap = SURFACE_LockSurface(hBitmap); if (Bitmap == NULL) { return 0; } BITMAP_GetObject(Bitmap, sizeof(BITMAP), (PVOID)&bm); bm.bmBits = NULL; if (Bitmap->SurfObj.lDelta >= 0) bm.bmHeight = -bm.bmHeight; Size.cx = abs(bm.bmWidth); Size.cy = abs(bm.bmHeight); res = GreCreateBitmapEx(Size.cx, Size.cy, bm.bmWidthBytes, Bitmap->SurfObj.iBitmapFormat, Bitmap->SurfObj.fjBitmap, Bitmap->SurfObj.cjBits, NULL, Bitmap->flags); if (res) { resBitmap = SURFACE_LockSurface(res); if (resBitmap) { IntSetBitmapBits(resBitmap, Bitmap->SurfObj.cjBits, Bitmap->SurfObj.pvBits); SURFACE_UnlockSurface(resBitmap); } else { GreDeleteObject(res); res = NULL; } } SURFACE_UnlockSurface(Bitmap); return res; } INT APIENTRY BITMAP_GetObject(SURFACE *psurf, INT Count, LPVOID buffer) { PBITMAP pBitmap; if (!buffer) return sizeof(BITMAP); if ((UINT)Count < sizeof(BITMAP)) return 0; /* always fill a basic BITMAP structure */ pBitmap = buffer; pBitmap->bmType = 0; pBitmap->bmWidth = psurf->SurfObj.sizlBitmap.cx; pBitmap->bmHeight = psurf->SurfObj.sizlBitmap.cy; pBitmap->bmPlanes = 1; pBitmap->bmBitsPixel = BitsPerFormat(psurf->SurfObj.iBitmapFormat); pBitmap->bmWidthBytes = BITMAP_GetWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel); /* Check for DIB section */ if (psurf->hSecure) { /* Set bmBits in this case */ pBitmap->bmBits = psurf->SurfObj.pvBits; /* DIBs data are 32 bits aligned */ pBitmap->bmWidthBytes = DIB_GetDIBWidthBytes(pBitmap->bmWidth, pBitmap->bmBitsPixel); if (Count >= sizeof(DIBSECTION)) { /* Fill rest of DIBSECTION */ PDIBSECTION pds = buffer; pds->dsBmih.biSize = sizeof(BITMAPINFOHEADER); pds->dsBmih.biWidth = pds->dsBm.bmWidth; pds->dsBmih.biHeight = pds->dsBm.bmHeight; pds->dsBmih.biPlanes = pds->dsBm.bmPlanes; pds->dsBmih.biBitCount = pds->dsBm.bmBitsPixel; if(psurf->ppal->Mode & PAL_BITFIELDS) { pds->dsBmih.biCompression = BI_BITFIELDS; } else { switch (psurf->SurfObj.iBitmapFormat) { case BMF_1BPP: case BMF_4BPP: case BMF_8BPP: case BMF_16BPP: case BMF_24BPP: case BMF_32BPP: pds->dsBmih.biCompression = BI_RGB; break; case BMF_4RLE: pds->dsBmih.biCompression = BI_RLE4; break; case BMF_8RLE: pds->dsBmih.biCompression = BI_RLE8; break; case BMF_JPEG: pds->dsBmih.biCompression = BI_JPEG; break; case BMF_PNG: pds->dsBmih.biCompression = BI_PNG; break; } } pds->dsBmih.biSizeImage = psurf->SurfObj.cjBits; pds->dsBmih.biXPelsPerMeter = 0; pds->dsBmih.biYPelsPerMeter = 0; pds->dsBmih.biClrUsed = psurf->ppal->NumColors; pds->dsBmih.biClrImportant = psurf->biClrImportant; pds->dsBitfields[0] = psurf->ppal->RedMask; pds->dsBitfields[1] = psurf->ppal->GreenMask; pds->dsBitfields[2] = psurf->ppal->BlueMask; pds->dshSection = psurf->hDIBSection; pds->dsOffset = psurf->dwOffset; return sizeof(DIBSECTION); } } else { /* not set according to wine test, confirmed in win2k */ pBitmap->bmBits = NULL; } return sizeof(BITMAP); } /* * @implemented */ HDC APIENTRY NtGdiGetDCforBitmap( IN HBITMAP hsurf) { HDC hdc = NULL; PSURFACE psurf = SURFACE_LockSurface(hsurf); if (psurf) { hdc = psurf->hdc; SURFACE_UnlockSurface(psurf); } return hdc; } /* EOF */