- Fixes bug 3864. While I was at it I fixed most of the gdi max bit max info sizes too.

- Added notes for the SEH abuse in win32k dibobj.c.
- Tested WinMerge 2.10.2, AbiWord 2.4.1, Firefox 1.5.0.3 and wine gdi32 bitmap cross test.
- When testing with gdi cross test in 24 and 32 bit display mode, we have a pixel conversion mismatch. Please fix it!


svn path=/trunk/; revision=37436
This commit is contained in:
James Tabor 2008-11-18 05:36:19 +00:00
parent 3595d1c30e
commit fa0375352f
6 changed files with 504 additions and 126 deletions

View file

@ -231,6 +231,7 @@ STDCALL
GdiSetLastError( DWORD dwErrCode ); GdiSetLastError( DWORD dwErrCode );
DWORD STDCALL GdiGetCodePage(HDC); DWORD STDCALL GdiGetCodePage(HDC);
UINT FASTCALL DIB_BitmapBitsSize( PBITMAPINFO );
/* EOF */ /* EOF */

View file

@ -1786,28 +1786,6 @@ CombineRgn(HRGN hDest,
return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode); return NtGdiCombineRgn(hDest, hSrc1, hSrc2, CombineMode);
} }
/*
* @unimplemented
*/
HBITMAP STDCALL
CreateBitmap(INT Width,
INT Height,
UINT Planes,
UINT BitsPixel,
PCVOID pUnsafeBits)
{
/* FIXME some part should be done in user mode */
if (Width && Height)
{
return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
}
else
{
/* Return 1x1 bitmap */
return GetStockObject(DEFAULT_BITMAP);
}
}
/* /*
* @unimplemented * @unimplemented
*/ */

View file

@ -6,7 +6,7 @@
/* /*
* Return the full scan size for a bitmap. * Return the full scan size for a bitmap.
* *
* Based on Wine, Utils.c and Windows Graphics Prog pg 595 * Based on Wine, Utils.c and Windows Graphics Prog pg 595, SDK amvideo.h.
*/ */
UINT UINT
FASTCALL FASTCALL
@ -14,6 +14,8 @@ DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines )
{ {
UINT MaxBits = 0; UINT MaxBits = 0;
if (!Info) return 0;
if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{ {
PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info; PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
@ -30,6 +32,33 @@ DIB_BitmapMaxBitsSize( PBITMAPINFO Info, UINT ScanLines )
return (MaxBits * ScanLines); // ret the full Size. return (MaxBits * ScanLines); // ret the full Size.
} }
UINT
FASTCALL
DIB_BitmapBitsSize( PBITMAPINFO Info )
{
UINT Ret;
if (!Info) return 0;
if ( Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{
PBITMAPCOREHEADER Core = (PBITMAPCOREHEADER)Info;
Ret = Core->bcHeight *
((Core->bcWidth * Core->bcPlanes * Core->bcBitCount + 31) & ~31 ) / 8;
}
else /* assume BITMAPINFOHEADER */
{
if ((Info->bmiHeader.biCompression) &&
(Info->bmiHeader.biCompression != BI_BITFIELDS))
return Info->bmiHeader.biSizeImage;
// Make Height positive always....
Ret = abs(Info->bmiHeader.biHeight) *
((Info->bmiHeader.biWidth * Info->bmiHeader.biPlanes * Info->bmiHeader.biBitCount + 31) & ~31 ) / 8;
}
return Ret;
}
/* /*
* DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006 * DIB_GetBitmapInfo is complete copy of wine cvs 2/9-2006
* from file dib.c from gdi32.dll or orginal version * from file dib.c from gdi32.dll or orginal version
@ -111,16 +140,42 @@ CreateDIBSection(
PBITMAPINFO pConvertedInfo; PBITMAPINFO pConvertedInfo;
UINT ConvertedInfoSize; UINT ConvertedInfoSize;
HBITMAP hBitmap = NULL; HBITMAP hBitmap = NULL;
PVOID bmBits = NULL;
pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage, pConvertedInfo = ConvertBitmapInfo(BitmapInfo, Usage,
&ConvertedInfoSize, FALSE); &ConvertedInfoSize, FALSE);
if (pConvertedInfo) if (pConvertedInfo)
{ { // Verify header due to converted may == info.
hBitmap = NtGdiCreateDIBSection(hDC, hSection, dwOffset, pConvertedInfo, Usage, 0, 0, 0, Bits); if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
}
bmBits = Bits;
hBitmap = NtGdiCreateDIBSection( hDC,
hSection,
dwOffset,
pConvertedInfo,
Usage,
0,
0,
0,
&bmBits);
if (BitmapInfo != pConvertedInfo) if (BitmapInfo != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo); RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
if (!hBitmap)
{
bmBits = NULL;
}
} }
if (Bits) *Bits = bmBits;
return hBitmap; return hBitmap;
} }
@ -190,6 +245,28 @@ StretchBlt(
nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0); nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, dwRop, 0, 0);
} }
/*
* @unimplemented
*/
HBITMAP STDCALL
CreateBitmap(INT Width,
INT Height,
UINT Planes,
UINT BitsPixel,
PCVOID pUnsafeBits)
{
/* FIXME some part should be done in user mode */
if (Width && Height)
{
return NtGdiCreateBitmap(Width, Height, Planes, BitsPixel, (LPBYTE) pUnsafeBits);
}
else
{
/* Return 1x1 bitmap */
return GetStockObject(DEFAULT_BITMAP);
}
}
/* /*
* @implemented * @implemented
*/ */
@ -234,12 +311,38 @@ CreateCompatibleBitmap(
INT Width, INT Width,
INT Height) INT Height)
{ {
/* FIXME some part shall be done in user mode */ PDC_ATTR pDc_Attr;
return NtGdiCreateCompatibleBitmap(hDC, Width, Height); HBITMAP hBmp = NULL;
DIBSECTION dibs;
if (!GdiGetHandleUserData(hDC, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
return NULL;
if ( !Width || !Height )
return GetStockObject(DEFAULT_BITMAP);
if (!(pDc_Attr->ulDirty_ & DC_DIBSECTION))
{
return NtGdiCreateCompatibleBitmap(hDC, Width, Height);
}
hBmp = NtGdiGetDCObject(hDC, GDI_OBJECT_TYPE_BITMAP);
if ( GetObjectA(hBmp, sizeof(DIBSECTION), &dibs) != sizeof(DIBSECTION) )
return NULL;
if ( dibs.dsBm.bmBitsPixel <= 8 )
GetDIBColorTable(hDC, 0, 256, (RGBQUAD *)&dibs.dsBitfields);
dibs.dsBmih.biWidth = Width;
dibs.dsBmih.biHeight = Height;
return CreateDIBSection(hDC, (CONST BITMAPINFO *)&dibs.dsBmih, 0, NULL, NULL, 0);
} }
INT INT
STDCALL STDCALL
GetDIBits( GetDIBits(
@ -251,34 +354,50 @@ GetDIBits(
LPBITMAPINFO lpbmi, LPBITMAPINFO lpbmi,
UINT uUsage) UINT uUsage)
{ {
INT ret = 0; INT Ret = 0;
UINT cjBmpScanSize;
PVOID pvSafeBits = lpvBits;
if (hDC == NULL || !GdiIsHandleValid((HGDIOBJ)hDC)) if (!hDC || !GdiIsHandleValid((HGDIOBJ)hDC))
{ {
GdiSetLastError(ERROR_INVALID_PARAMETER); GdiSetLastError(ERROR_INVALID_PARAMETER);
} return Ret;
else if (lpbmi == NULL) }
{
// XP doesn't run this check and results in a
// crash in DIB_BitmapMaxBitsSize, we'll be more forgiving
GdiSetLastError(ERROR_INVALID_PARAMETER);
}
else
{
UINT cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
ret = NtGdiGetDIBitsInternal(hDC, cjBmpScanSize = DIB_BitmapMaxBitsSize(lpbmi, cScanLines);
hbmp,
uStartScan,
cScanLines,
lpvBits,
lpbmi,
uUsage,
cjBmpScanSize,
0);
}
return ret; if ( lpvBits )
{
if ( lpbmi )
{
if ( lpbmi->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
{
if ( lpbmi->bmiHeader.biCompression == BI_JPEG ||
lpbmi->bmiHeader.biCompression == BI_PNG )
{
SetLastError(ERROR_INVALID_PARAMETER);
return Ret;
}
}
}
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
}
Ret = NtGdiGetDIBitsInternal(hDC,
hbmp,
uStartScan,
cScanLines,
pvSafeBits,
lpbmi,
uUsage,
cjBmpScanSize,
0);
if ( lpvBits )
{
RtlCopyMemory( lpvBits, pvSafeBits, cjBmpScanSize);
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
}
return Ret;
} }
/* /*
@ -293,26 +412,73 @@ CreateDIBitmap( HDC hDC,
const BITMAPINFO *Data, const BITMAPINFO *Data,
UINT ColorUse) UINT ColorUse)
{ {
LONG width, height, compr, dibsize; LONG width, height, compr, dibsize;
WORD planes, bpp; WORD planes, bpp;
// PDC_ATTR pDc_Attr;
PBITMAPINFO pConvertedInfo;
UINT ConvertedInfoSize;
UINT cjBmpScanSize;
PVOID pvSafeBits = NULL;
HBITMAP hBmp;
if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1) pConvertedInfo = ConvertBitmapInfo(Data, ColorUse,
{ &ConvertedInfoSize, FALSE);
GdiSetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
return NtGdiCreateDIBitmapInternal(hDC, if (DIB_GetBitmapInfo(Header, &width, &height, &planes, &bpp, &compr, &dibsize) == -1)
width, {
height, GdiSetLastError(ERROR_INVALID_PARAMETER);
Init, return NULL;
(LPBYTE)Bits, }
(PBITMAPINFO)Data,
ColorUse, if ( pConvertedInfo )
bpp, {
dibsize, if ( pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER) )
0, {
0); if ( pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )
{
hBmp = NULL;
goto Exit;
}
}
}
// For Icm support.
// GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
DPRINT("pBMI %x, Size bpp %d, dibsize %d, Conv %d, BSS %d\n", pConvertedInfo,bpp,dibsize,ConvertedInfoSize,cjBmpScanSize);
if ( !width || !height )
hBmp = GetStockObject(DEFAULT_BITMAP);
else
{
if ( Bits )
{
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
if ( pvSafeBits )
RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
}
hBmp = NtGdiCreateDIBitmapInternal(hDC,
width,
height,
Init,
(LPBYTE)pvSafeBits,
(PBITMAPINFO)pConvertedInfo,
ColorUse,
ConvertedInfoSize,
cjBmpScanSize,
0,
0);
if ( Bits )
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
}
Exit:
if (Data != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return hBmp;
} }
#if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!! #if 0 // FIXME!!! This is a victim of the Win32k Initialization BUG!!!!!
@ -419,7 +585,25 @@ SetDIBits(HDC hdc,
CONST BITMAPINFO *lpbmi, CONST BITMAPINFO *lpbmi,
UINT fuColorUse) UINT fuColorUse)
{ {
return NtGdiSetDIBits(hdc, hbmp, uStartScan, cScanLines, lpvBits, lpbmi, fuColorUse); INT LinesCopied = 0;
// This needs to be almost the sames as SetDIBitsToDevice
if ( !cScanLines || !lpbmi || !lpvBits || (GDI_HANDLE_GET_TYPE(hbmp) != GDI_OBJECT_TYPE_BITMAP))
return 0;
if ( fuColorUse && fuColorUse != DIB_PAL_COLORS && fuColorUse != DIB_PAL_COLORS+1 )
return 0;
LinesCopied = NtGdiSetDIBits( hdc,
hbmp,
uStartScan,
cScanLines,
lpvBits,
lpbmi,
fuColorUse);
return LinesCopied;
} }
/* /*
@ -429,7 +613,7 @@ SetDIBits(HDC hdc,
INT INT
STDCALL STDCALL
SetDIBitsToDevice( SetDIBitsToDevice(
HDC hDC, HDC hdc,
int XDest, int XDest,
int YDest, int YDest,
DWORD Width, DWORD Width,
@ -442,22 +626,111 @@ SetDIBitsToDevice(
CONST BITMAPINFO *lpbmi, CONST BITMAPINFO *lpbmi,
UINT ColorUse) UINT ColorUse)
{ {
return NtGdiSetDIBitsToDeviceInternal(hDC, PDC_ATTR pDc_Attr;
XDest, PBITMAPINFO pConvertedInfo;
YDest, UINT ConvertedInfoSize;
Width, INT LinesCopied = 0;
Height, UINT cjBmpScanSize = 0;
XSrc, PVOID pvSafeBits = (PVOID)Bits;
YSrc,
StartScan, if ( !ScanLines || !lpbmi || !Bits )
ScanLines, return 0;
(LPBYTE)Bits,
(LPBITMAPINFO)lpbmi, if ( ColorUse && ColorUse != DIB_PAL_COLORS && ColorUse != DIB_PAL_COLORS+1 )
ColorUse, return 0;
lpbmi->bmiHeader.biSizeImage,
lpbmi->bmiHeader.biSize, pConvertedInfo = ConvertBitmapInfo(lpbmi, ColorUse,
TRUE, &ConvertedInfoSize, FALSE);
NULL); if (!pConvertedInfo)
return 0;
#if 0
// Handle something other than a normal dc object.
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
{
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
return MFDRV_SetDIBitsToDevice( hdc,
XDest,
YDest,
Width,
Height,
XSrc,
YSrc,
StartScan,
ScanLines,
Bits,
lpbmi,
ColorUse);
else
{
PLDC pLDC = GdiGetLDC(hdc);
if ( !pLDC )
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
if (pLDC->iType == LDC_EMFLDC)
{
return EMFDRV_SetDIBitsToDevice(hdc,
XDest,
YDest,
Width,
Height,
XSrc,
YSrc,
StartScan,
ScanLines,
Bits,
lpbmi,
ColorUse);
}
return 0;
}
}
#endif
cjBmpScanSize = DIB_BitmapMaxBitsSize((LPBITMAPINFO)lpbmi, ScanLines);
if ( Bits )
{
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
if (pvSafeBits)
RtlCopyMemory( pvSafeBits, Bits, cjBmpScanSize);
}
if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiSetDIBitsToDeviceInternal( hdc,
XDest,
YDest,
Width,
Height,
XSrc,
YSrc,
StartScan,
ScanLines,
(LPBYTE)pvSafeBits,
(LPBITMAPINFO)pConvertedInfo,
ColorUse,
cjBmpScanSize,
ConvertedInfoSize,
TRUE,
NULL);
}
if ( Bits )
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
if (lpbmi != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return LinesCopied;
} }
@ -481,9 +754,133 @@ StretchDIBits(HDC hdc,
DWORD dwRop) DWORD dwRop)
{ {
DPRINT("StretchDIBits %x : %x\n", lpBits, lpBitsInfo); PDC_ATTR pDc_Attr;
/* FIXME share memory */ PBITMAPINFO pConvertedInfo = NULL;
return NtGdiStretchDIBitsInternal(hdc, XDest, YDest, nDestWidth, nDestHeight, XSrc, YSrc, UINT ConvertedInfoSize = 0;
nSrcWidth, nSrcHeight, (LPBYTE)lpBits, (LPBITMAPINFO)lpBitsInfo, (DWORD)iUsage, dwRop, 0, 0, NULL); INT LinesCopied = 0;
UINT cjBmpScanSize = 0;
PVOID pvSafeBits = NULL;
BOOL Hit = FALSE;
DPRINT("StretchDIBits %x : %x : %d\n", lpBits, lpBitsInfo, iUsage);
#if 0
// Handle something other than a normal dc object.
if (GDI_HANDLE_GET_TYPE(hdc) != GDI_OBJECT_TYPE_DC)
{
if (GDI_HANDLE_GET_TYPE(hdc) == GDI_OBJECT_TYPE_METADC)
return MFDRV_StretchBlt( hdc,
XDest,
YDest,
nDestWidth,
nDestHeight,
XSrc,
YSrc,
nSrcWidth,
nSrcHeight,
lpBits,
lpBitsInfo,
iUsage,
dwRop);
else
{
PLDC pLDC = GdiGetLDC(hdc);
if ( !pLDC )
{
SetLastError(ERROR_INVALID_HANDLE);
return 0;
}
if (pLDC->iType == LDC_EMFLDC)
{
return EMFDRV_StretchBlt(hdc,
XDest,
YDest,
nDestWidth,
nDestHeight,
XSrc,
YSrc,
nSrcWidth,
nSrcHeight,
lpBits,
lpBitsInfo,
iUsage,
dwRop);
}
return 0;
}
}
#endif
if ( iUsage ) // Save time, we only look at non RGB.
{
pConvertedInfo = ConvertBitmapInfo(lpBitsInfo, iUsage,
&ConvertedInfoSize, FALSE);
if (!pConvertedInfo)
{
return 0;
}
}
else
pConvertedInfo = (PBITMAPINFO)lpBitsInfo;
cjBmpScanSize = DIB_BitmapBitsSize((LPBITMAPINFO)pConvertedInfo);
if ( lpBits )
{
pvSafeBits = RtlAllocateHeap(GetProcessHeap(), 0, cjBmpScanSize);
if (pvSafeBits)
{
_SEH_TRY
{
RtlCopyMemory( pvSafeBits, lpBits, cjBmpScanSize );
}
_SEH_HANDLE
{
Hit = TRUE;
}
_SEH_END
if (Hit)
{
// We don't die, we continue on with a allocated safe pointer to kernel
// space.....
DPRINT1("StretchDIBits fail to read BitMapInfo: %x or Bits: %x & Size: %d\n",pConvertedInfo,lpBits,cjBmpScanSize);
}
DPRINT("StretchDIBits Allocate Bits %d!!!\n", cjBmpScanSize);
}
}
if (!GdiGetHandleUserData(hdc, GDI_OBJECT_TYPE_DC, (PVOID)&pDc_Attr))
{
SetLastError(ERROR_INVALID_PARAMETER);
return 0;
}
/*
if ( !pDc_Attr ||
((pConvertedInfo->bmiHeader.biSize >= sizeof(BITMAPINFOHEADER)) &&
(pConvertedInfo->bmiHeader.biCompression == BI_JPEG ||
pConvertedInfo->bmiHeader.biCompression == BI_PNG )) )*/
{
LinesCopied = NtGdiStretchDIBitsInternal( hdc,
XDest,
YDest,
nDestWidth,
nDestHeight,
XSrc,
YSrc,
nSrcWidth,
nSrcHeight,
pvSafeBits,
pConvertedInfo,
(DWORD)iUsage,
dwRop,
ConvertedInfoSize,
cjBmpScanSize,
NULL);
}
if ( pvSafeBits )
RtlFreeHeap(RtlGetProcessHeap(), 0, pvSafeBits);
if (lpBitsInfo != pConvertedInfo)
RtlFreeHeap(RtlGetProcessHeap(), 0, pConvertedInfo);
return LinesCopied;
} }

View file

@ -214,32 +214,7 @@ ConvertBitmapInfo(
if (FollowedByData) if (FollowedByData)
{ {
if (BitmapInfo->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) DataSize = DIB_BitmapBitsSize((PBITMAPINFO)BitmapInfo );
{
DataSize =
CoreBitmapInfo->bmciHeader.bcHeight *
CoreBitmapInfo->bmciHeader.bcWidth *
CoreBitmapInfo->bmciHeader.bcBitCount;
DataSize = ((DataSize + 31) & ~31) / 8;
DataSize *= CoreBitmapInfo->bmciHeader.bcPlanes;
}
else
{
if (BitmapInfo->bmiHeader.biCompression == BI_RGB ||
BitmapInfo->bmiHeader.biCompression == BI_BITFIELDS)
{
DataSize =
abs(BitmapInfo->bmiHeader.biHeight) *
BitmapInfo->bmiHeader.biWidth *
BitmapInfo->bmiHeader.biBitCount;
DataSize = ((DataSize + 31) & ~31) / 8;
DataSize *= BitmapInfo->bmiHeader.biPlanes;
}
else
{
DataSize = BitmapInfo->bmiHeader.biSizeImage;
}
}
} }
/* /*

View file

@ -270,6 +270,7 @@ BOOL FASTCALL IntGdiCleanDC(HDC hDC);
VOID FASTCALL IntvGetDeviceCaps(PGDIDEVICE, PDEVCAPS); VOID FASTCALL IntvGetDeviceCaps(PGDIDEVICE, PDEVCAPS);
HPEN FASTCALL IntGdiSelectPen(PDC,HPEN); HPEN FASTCALL IntGdiSelectPen(PDC,HPEN);
HBRUSH FASTCALL IntGdiSelectBrush(PDC,HBRUSH); HBRUSH FASTCALL IntGdiSelectBrush(PDC,HBRUSH);
INT FASTCALL IntGdiGetDeviceCaps(PDC,INT);
extern PGDIDEVICE pPrimarySurface; extern PGDIDEVICE pPrimarySurface;

View file

@ -317,7 +317,7 @@ NtGdiSetDIBits(
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
return 0; return 0;
} }
// Need SEH to check Bits and bmi. BTW bmi was converted in gdi.
Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse); Ret = IntSetDIBits(Dc, hBitmap, StartScan, ScanLines, Bits, bmi, ColorUse);
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
@ -399,7 +399,7 @@ NtGdiSetDIBitsToDeviceInternal(
ptSource.y = YSrc; ptSource.y = YSrc;
/* Enter SEH, as the bits are user mode */ /* Enter SEH, as the bits are user mode */
_SEH_TRY _SEH_TRY // Look at NtGdiStretchDIBitsInternal
{ {
SourceSize.cx = bmi->bmiHeader.biWidth; SourceSize.cx = bmi->bmiHeader.biWidth;
SourceSize.cy = ScanLines; SourceSize.cy = ScanLines;
@ -541,8 +541,8 @@ NtGdiGetDIBitsInternal(HDC hDC,
/* fill out the BITMAPINFO struct */ /* fill out the BITMAPINFO struct */
if (Bits == NULL) if (Bits == NULL)
{ {
_SEH_TRY _SEH_TRY // Look at NtGdiStretchDIBitsInternal
{ { // Why check for anything, we converted in gdi!
if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER)) if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
{ {
BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info; BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
@ -806,6 +806,7 @@ NtGdiStretchDIBitsInternal(
HDC hdcMem; HDC hdcMem;
HPALETTE hPal = NULL; HPALETTE hPal = NULL;
PDC pDC; PDC pDC;
BOOL Hit = FALSE;
if (!Bits || !BitsInfo) if (!Bits || !BitsInfo)
{ {
@ -813,6 +814,23 @@ NtGdiStretchDIBitsInternal(
return 0; return 0;
} }
_SEH_TRY
{
ProbeForRead(BitsInfo, cjMaxInfo, 1);
ProbeForRead(Bits, cjMaxBits, 1);
}
_SEH_HANDLE
{
Hit = TRUE;
}
_SEH_END
if (Hit)
{
DPRINT1("NtGdiStretchDIBitsInternal fail to read BitMapInfo: %x or Bits: %x\n",BitsInfo,Bits);
return 0;
}
hdcMem = NtGdiCreateCompatibleDC(hDC); hdcMem = NtGdiCreateCompatibleDC(hDC);
if (hdcMem == NULL) if (hdcMem == NULL)
{ {
@ -993,6 +1011,7 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc,
{ {
PDC Dc; PDC Dc;
HBITMAP Bmp; HBITMAP Bmp;
UINT bpp;
if (!hDc) if (!hDc)
{ // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this. { // Should use System Bitmap DC hSystemBM, with CreateCompatibleDC for this.
@ -1010,9 +1029,8 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc,
SetLastWin32Error(ERROR_INVALID_HANDLE); SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL; return NULL;
} }
bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
cjMaxInitInfo = 1; Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage);
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
NtGdiDeleteObjectApp(hDc); NtGdiDeleteObjectApp(hDc);
@ -1025,8 +1043,16 @@ NtGdiCreateDIBitmapInternal(IN HDC hDc,
SetLastWin32Error(ERROR_INVALID_HANDLE); SetLastWin32Error(ERROR_INVALID_HANDLE);
return NULL; return NULL;
} }
/* pbmi == null
First create an un-initialised bitmap. The depth of the bitmap
should match that of the hdc and not that supplied in bmih.
*/
if (pbmi)
bpp = pbmi->bmiHeader.biBitCount;
else
bpp = IntGdiGetDeviceCaps(Dc, BITSPIXEL);
Bmp = IntCreateDIBitmap(Dc, cx, cy, cjMaxInitInfo, fInit, pjInit, pbmi, iUsage); Bmp = IntCreateDIBitmap(Dc, cx, cy, bpp, fInit, pjInit, pbmi, iUsage);
DC_UnlockDc(Dc); DC_UnlockDc(Dc);
} }
return Bmp; return Bmp;