- remove useless memory reallocation : the buffer size must be dword aligned, we have no way to guarantee the buffer location will be.
  - pass BITMAPINFO pointer size to NtGdiGetDIBitsInternal
[WIN32K]
  - Improve "not enough memory" check when creating a bitmap
  - use correct function to set the last error.

svn path=/trunk/; revision=50133
This commit is contained in:
Jérôme Gardou 2010-12-24 20:29:25 +00:00
parent 23499a2d4d
commit 1513741845
2 changed files with 60 additions and 42 deletions

View file

@ -3,6 +3,36 @@
#define NDEBUG #define NDEBUG
#include <debug.h> #include <debug.h>
/*
* DIB_BitmapInfoSize
*
* Return the size of the bitmap info structure including color table.
* 11/16/1999 (RJJ) lifted from wine
*/
INT FASTCALL DIB_BitmapInfoSize(const BITMAPINFO * info, WORD coloruse)
{
unsigned int colors, size, masks = 0;
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));
}
else /* assume BITMAPINFOHEADER */
{
colors = info->bmiHeader.biClrUsed;
if (colors > 256) colors = 256;
if (!colors && (info->bmiHeader.biBitCount <= 8))
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 the full scan size for a bitmap. * Return the full scan size for a bitmap.
* *
@ -391,59 +421,40 @@ GetDIBits(
LPBITMAPINFO lpbmi, LPBITMAPINFO lpbmi,
UINT uUsage) UINT uUsage)
{ {
INT Ret = 0; UINT cjBmpScanSize;
UINT cjBmpScanSize; UINT cjInfoSize;
PVOID pvSafeBits = lpvBits;
if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC)) if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC) || !lpbmi)
{ {
GdiSetLastError(ERROR_INVALID_PARAMETER); GdiSetLastError(ERROR_INVALID_PARAMETER);
return Ret; return 0;
} }
cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines); cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
cjInfoSize = DIB_BitmapInfoSize(lpbmi, uUsage);
if ( lpvBits ) if ( lpvBits )
{ {
if ( lpbmi )
{
if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) ) if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{ {
if ( lpbmi->bmiHeader.biCompression == BI_JPEG || if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
lpbmi->bmiHeader.biCompression == BI_PNG ) lpbmi->bmiHeader.biCompression == BI_PNG )
{ {
SetLastError(ERROR_INVALID_PARAMETER); SetLastError(ERROR_INVALID_PARAMETER);
return Ret; return 0;
} }
} }
} }
if ((ULONG)lpvBits & (sizeof(DWORD) - 1)) return NtGdiGetDIBitsInternal(hDC,
{
pvSafeBits = RtlAllocateHeap(RtlGetProcessHeap(), 0, cjBmpScanSize);
if (!pvSafeBits)
return Ret;
}
}
Ret = NtGdiGetDIBitsInternal(hDC,
hbmp, hbmp,
uStartScan, uStartScan,
cScanLines, cScanLines,
pvSafeBits, lpvBits,
lpbmi, lpbmi,
uUsage, uUsage,
cjBmpScanSize, cjBmpScanSize,
0); cjInfoSize);
if (lpvBits != pvSafeBits)
{
if (Ret)
{
RtlCopyMemory(lpvBits, pvSafeBits, cjBmpScanSize);
}
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
}
return Ret;
} }
/* /*

View file

@ -170,11 +170,18 @@ NtGdiCreateBitmap(
iFormat = BitmapFormat(cBitsPixel, BI_RGB); iFormat = BitmapFormat(cBitsPixel, BI_RGB);
/* Check parameters */ /* Check parameters */
if (iFormat == 0 || nWidth <= 0 || nWidth >= 0x8000000 || nHeight <= 0) if (iFormat == 0 || nWidth <= 0 || nHeight <= 0)
{ {
DPRINT1("Width = %d, Height = %d BitsPixel = %d\n", DPRINT1("Width = %d, Height = %d BitsPixel = %d\n",
nWidth, nHeight, cBitsPixel); nWidth, nHeight, cBitsPixel);
EngSetLastError(ERROR_INVALID_PARAMETER); SetLastWin32Error(ERROR_INVALID_PARAMETER);
return NULL;
}
if(WIDTH_BYTES_ALIGN16(nWidth, cBitsPixel)*nHeight >= 0x8000000)
{
/* I just can't get enough, I just can't get enough */
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return NULL; return NULL;
} }