/*
* PROJECT: ReactOS win32 kernel mode subsystem
* LICENSE: GPL - See COPYING in the top level directory
- * FILE: subsystems/win32/win32k/objects/dibobj.c
+ * FILE: win32ss/gdi/ntgdi/dibobj.c
* PURPOSE: Dib object functions
* PROGRAMMER:
*/
UINT StartScan,
UINT ScanLines,
CONST VOID *Bits,
+ ULONG cjMaxBits,
CONST BITMAPINFO *bmi,
UINT ColorUse)
{
POINTL ptSrc;
EXLATEOBJ exlo;
PPALETTE ppalDIB = 0;
+ ULONG cjSizeImage;
- if (!bmi) return 0;
+ if (!bmi || !Bits) return 0;
+
+ /* Check for uncompressed formats */
+ if ((bmi->bmiHeader.biCompression == BI_RGB) ||
+ (bmi->bmiHeader.biCompression == BI_BITFIELDS))
+ {
+ /* Calculate the image size */
+ cjSizeImage = DIB_GetDIBImageBytes(bmi->bmiHeader.biWidth,
+ ScanLines,
+ bmi->bmiHeader.biBitCount);
+ }
+ /* Check if the header provided an image size */
+ else if (bmi->bmiHeader.biSizeImage != 0)
+ {
+ /* Use the given size */
+ cjSizeImage = bmi->bmiHeader.biSizeImage;
+ }
+ else
+ {
+ /* Compressed format without a size. This is invalid. */
+ DPRINT1("Compressed format without a size!");
+ return 0;
+ }
+
+ /* Check if the size that we have is ok */
+ if ((cjSizeImage > cjMaxBits) || (cjSizeImage == 0))
+ {
+ DPRINT1("Invalid bitmap size! cjSizeImage = %lu, cjMaxBits = %lu\n",
+ cjSizeImage, cjMaxBits);
+ return 0;
+ }
SourceBitmap = GreCreateBitmapEx(bmi->bmiHeader.biWidth,
ScanLines,
BitmapFormat(bmi->bmiHeader.biBitCount,
bmi->bmiHeader.biCompression),
bmi->bmiHeader.biHeight < 0 ? BMF_TOPDOWN : 0,
- bmi->bmiHeader.biSizeImage,
+ cjSizeImage,
(PVOID)Bits,
0);
if (!SourceBitmap)
ptSrc.x = 0;
ptSrc.y = 0;
+ NT_ASSERT(psurfSrc->SurfObj.cjBits <= cjMaxBits);
+
result = IntEngCopyBits(&psurfDst->SurfObj,
&psurfSrc->SurfObj,
NULL,
{
INT ret = 0;
NTSTATUS Status = STATUS_SUCCESS;
- PDC pDC;
+ PDC pDC = NULL;
HBITMAP hSourceBitmap = NULL, hMaskBitmap = NULL;
SURFOBJ *pDestSurf, *pSourceSurf = NULL, *pMaskSurf = NULL;
SURFACE *pSurf;
if (!NT_SUCCESS(Status))
{
- goto Exit2;
+ goto Exit;
}
ScanLines = min(ScanLines, abs(bmi->bmiHeader.biHeight) - StartScan);
+ if (ScanLines == 0)
+ {
+ DPRINT1("ScanLines == 0\n");
+ goto Exit;
+ }
pDC = DC_LockDc(hDC);
if (!pDC)
{
EngSetLastError(ERROR_INVALID_HANDLE);
- goto Exit2;
+ goto Exit;
}
if (pDC->dctype == DC_TYPE_INFO)
{
- DC_UnlockDc(pDC);
goto Exit;
}
}
if (ppalDIB) PALETTE_ShareUnlockPalette(ppalDIB);
-
if (pSourceSurf) EngUnlockSurface(pSourceSurf);
if (hSourceBitmap) EngDeleteSurface((HSURF)hSourceBitmap);
if (pMaskSurf) EngUnlockSurface(pMaskSurf);
if (hMaskBitmap) EngDeleteSurface((HSURF)hMaskBitmap);
- DC_UnlockDc(pDC);
-Exit2:
+ if (pDC) DC_UnlockDc(pDC);
ExFreePoolWithTag(pbmiSafe, 'pmTG');
+
return ret;
}
RGBQUAD* rgbQuads;
VOID* colorPtr;
- DPRINT("Entered NtGdiGetDIBitsInternal()\n");
+ DPRINT("Entered GreGetDIBitsInternal()\n");
if ((Usage && Usage != DIB_PAL_COLORS) || !Info || !hBitmap)
return 0;
return ScanLines;
}
+_Success_(return!=0)
+__kernel_entry
INT
APIENTRY
NtGdiGetDIBitsInternal(
_In_ HBITMAP hbm,
_In_ UINT iStartScan,
_In_ UINT cScans,
- _Out_opt_ LPBYTE pjBits,
- _Inout_ LPBITMAPINFO pbmiUser,
+ _Out_writes_bytes_opt_(cjMaxBits) LPBYTE pjBits,
+ _Inout_ LPBITMAPINFO pbmi,
_In_ UINT iUsage,
_In_ UINT cjMaxBits,
_In_ UINT cjMaxInfo)
{
- PBITMAPINFO pbmi;
+ PBITMAPINFO pbmiSafe;
HANDLE hSecure = NULL;
INT iResult = 0;
UINT cjAlloc;
cjAlloc = sizeof(BITMAPV5HEADER) + 256 * sizeof(RGBQUAD);
/* Allocate a buffer the bitmapinfo */
- pbmi = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
- if (!pbmi)
+ pbmiSafe = ExAllocatePoolWithTag(PagedPool, cjAlloc, 'imBG');
+ if (!pbmiSafe)
{
/* Fail */
return 0;
_SEH2_TRY
{
/* Probe and copy the BITMAPINFO */
- ProbeForRead(pbmiUser, cjMaxInfo, 1);
- RtlCopyMemory(pbmi, pbmiUser, cjMaxInfo);
+ ProbeForRead(pbmi, cjMaxInfo, 1);
+ RtlCopyMemory(pbmiSafe, pbmi, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
_SEH2_END;
/* Check if the header size is large enough */
- if ((pbmi->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
- (pbmi->bmiHeader.biSize > cjMaxInfo))
+ if ((pbmiSafe->bmiHeader.biSize < sizeof(BITMAPCOREHEADER)) ||
+ (pbmiSafe->bmiHeader.biSize > cjMaxInfo))
{
goto cleanup;
}
iStartScan,
cScans,
pjBits,
- pbmi,
+ pbmiSafe,
iUsage,
cjMaxBits,
cjMaxInfo);
_SEH2_TRY
{
/* Copy the data back */
- cjMaxInfo = DIB_BitmapInfoSize(pbmi, (WORD)iUsage);
- ProbeForWrite(pbmiUser, cjMaxInfo, 1);
- RtlCopyMemory(pbmiUser, pbmi, cjMaxInfo);
+ cjMaxInfo = min(cjMaxInfo, (UINT)DIB_BitmapInfoSize(pbmiSafe, (WORD)iUsage));
+ ProbeForWrite(pbmi, cjMaxInfo, 1);
+ RtlCopyMemory(pbmi, pbmiSafe, cjMaxInfo);
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
/* Ignore */
+ (VOID)0;
}
_SEH2_END;
}
cleanup:
if (hSecure) EngUnsecureMem(hSecure);
- ExFreePoolWithTag(pbmi, 'imBG');
+ ExFreePoolWithTag(pbmiSafe, 'imBG');
return iResult;
}
RECTL_vOffsetRect(&rcDst, pdc->ptlDCOrig.x, pdc->ptlDCOrig.y);
hbmTmp = GreCreateBitmapEx(pbmi->bmiHeader.biWidth,
- pbmi->bmiHeader.biHeight,
+ abs(pbmi->bmiHeader.biHeight),
0,
BitmapFormat(pbmi->bmiHeader.biBitCount,
pbmi->bmiHeader.biCompression),
pdc->pdcattr->crBackgroundClr,
pdc->pdcattr->crForegroundClr);
- /* Mask away everything except foreground rop index */
- dwRop = dwRop & 0x00FF0000;
- dwRop |= dwRop << 8;
-
/* Perform the stretch operation */
bResult = IntEngStretchBlt(&psurfDst->SurfObj,
&psurfTmp->SurfObj,
NULL,
&pdc->eboFill.BrushObject,
NULL,
- ROP_TO_ROP4(dwRop));
+ WIN32_ROP3_TO_ENG_ROP4(dwRop));
/* Cleanup */
DC_vFinishBlit(pdc, NULL);
ULONG compression,
DWORD init,
LPBYTE bits,
+ ULONG cjMaxBits,
PBITMAPINFO data,
DWORD coloruse)
{
/* Undocumented flag which creates a DDB of the format specified by the bitmap info. */
handle = IntCreateCompatibleBitmap(Dc, width, height, planes, bpp);
if (!handle)
+ {
+ DPRINT1("IntCreateCompatibleBitmap() failed!\n");
return NULL;
+ }
+
/* The palette must also match the given data */
Surface = SURFACE_ShareLockSurface(handle);
ASSERT(Surface);
else
{
handle = GreCreateBitmap(width,
- height,
+ abs(height),
1,
1,
NULL);
if ((NULL != handle) && (CBM_INIT & init))
{
- IntSetDIBits(Dc, handle, 0, height, bits, data, coloruse);
+ IntSetDIBits(Dc, handle, 0, height, bits, cjMaxBits, data, coloruse);
}
return handle;
PBYTE safeBits = NULL;
HBITMAP hbmResult = NULL;
+ if (pjInit == NULL)
+ {
+ fInit &= ~CBM_INIT;
+ }
+
if(pjInit && (fInit & CBM_INIT))
{
if (cjMaxBits == 0) return NULL;
safeBits = ExAllocatePoolWithTag(PagedPool, cjMaxBits, TAG_DIB);
if(!safeBits)
{
+ DPRINT1("Failed to allocate %lu bytes\n", cjMaxBits);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
if(!NT_SUCCESS(Status))
{
+ DPRINT1("Got an exception! pjInit = %p\n", pjInit);
SetLastNtError(Status);
goto cleanup;
}
hdcDest = NtGdiCreateCompatibleDC(0);
if(!hdcDest)
{
+ DPRINT1("NtGdiCreateCompatibleDC failed\n");
return NULL;
}
}
Dc = DC_LockDc(hdcDest);
if (!Dc)
{
+ DPRINT1("Failed to lock hdcDest %p\n", hdcDest);
EngSetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
planes = 0;
compression = 0;
}
- Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, planes, compression, fInit, pjInit, pbmi, iUsage);
+ Bmp = IntCreateDIBitmap(Dc, cx, cy, planes, bpp, compression, fInit, pjInit, cjMaxBits, pbmi, iUsage);
DC_UnlockDc(Dc);
if(!hDc)
return Bmp;
}
+HBITMAP
+NTAPI
+GreCreateDIBitmapFromPackedDIB(
+ _In_reads_(cjPackedDIB )PVOID pvPackedDIB,
+ _In_ UINT cjPackedDIB,
+ _In_ ULONG uUsage)
+{
+ PBITMAPINFO pbmi;
+ PBYTE pjBits;
+ UINT cjInfo, cjBits;
+ HBITMAP hbm;
+
+ /* We only support BITMAPINFOHEADER, make sure the size is ok */
+ if (cjPackedDIB < sizeof(BITMAPINFOHEADER))
+ {
+ return NULL;
+ }
+
+ /* The packed DIB starts with the BITMAPINFOHEADER */
+ pbmi = pvPackedDIB;
+
+ if (cjPackedDIB < pbmi->bmiHeader.biSize)
+ {
+ return NULL;
+ }
+
+ /* Calculate the info size and make sure the packed DIB is large enough */
+ cjInfo = DIB_BitmapInfoSize(pbmi, uUsage);
+ if (cjPackedDIB <= cjInfo)
+ {
+ return NULL;
+ }
+
+ /* The bitmap bits start after the header */
+ pjBits = (PBYTE)pvPackedDIB + cjInfo;
+ cjBits = cjPackedDIB - cjInfo;
+
+ hbm = GreCreateDIBitmapInternal(NULL,
+ pbmi->bmiHeader.biWidth,
+ abs(pbmi->bmiHeader.biHeight),
+ CBM_INIT | CBM_CREATDIB,
+ pjBits,
+ pbmi,
+ uUsage,
+ 0,
+ cjBits,
+ NULL);
+
+ return hbm;
+}
HBITMAP
APIENTRY
// Get storage location for DIB bits. Only use biSizeImage if it's valid and
// we're dealing with a compressed bitmap. Otherwise, use width * height.
- totalSize = bi->biSizeImage && bi->biCompression != BI_RGB && bi->biCompression != BI_BITFIELDS
+ totalSize = (bi->biSizeImage && (bi->biCompression != BI_RGB) && (bi->biCompression != BI_BITFIELDS))
? bi->biSizeImage : (ULONG)(bm.bmWidthBytes * effHeight);
if (section)
}
mapOffset = offset - (offset % Sbi.AllocationGranularity);
- mapSize = bi->biSizeImage + (offset - mapOffset);
+ mapSize = totalSize + (offset - mapOffset);
SectionOffset.LowPart = mapOffset;
SectionOffset.HighPart = 0;
BitmapFormat(bi->biBitCount * bi->biPlanes, bi->biCompression),
BMF_DONTCACHE | BMF_USERMEM | BMF_NOZEROINIT |
((bi->biHeight < 0) ? BMF_TOPDOWN : 0),
- bi->biSizeImage,
+ totalSize,
bm.bmBits,
0);
if (!res)
INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
{
unsigned int colors, size, masks = 0;
+ unsigned int colorsize;
+
+ colorsize = (coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) :
+ (coloruse == DIB_PAL_INDICES) ? 0 :
+ sizeof(WORD);
if (info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
const BITMAPCOREHEADER *core = (const BITMAPCOREHEADER *)info;
colors = (core->bcBitCount <= 8) ? 1 << core->bcBitCount : 0;
- return sizeof(BITMAPCOREHEADER) + colors *
- ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBTRIPLE) : sizeof(WORD));
+ return sizeof(BITMAPCOREHEADER) + colors * colorsize;
}
else /* Assume BITMAPINFOHEADER */
{
colors = 1 << info->bmiHeader.biBitCount;
if (info->bmiHeader.biCompression == BI_BITFIELDS) masks = 3;
size = max( info->bmiHeader.biSize, sizeof(BITMAPINFOHEADER) + masks * sizeof(DWORD) );
- return size + colors * ((coloruse == DIB_RGB_COLORS) ? sizeof(RGBQUAD) : sizeof(WORD));
+ return size + colors * colorsize;
}
}