Author: gedmurphy
Date: Mon Oct 1 15:53:31 2007
New Revision: 29326
URL:
http://svn.reactos.org/svn/reactos?rev=29326&view=rev
Log:
- partial rewrite of NtGdiGetDIBitsInternal
- wrap all usermode read/writes in seh
- make it more compatible with XP. We now pass all current GetDIBits tests and win32k
tests
Modified:
trunk/reactos/subsystems/win32/win32k/objects/dibobj.c
trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
Modified: trunk/reactos/subsystems/win32/win32k/objects/dibobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/dibobj.c (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/dibobj.c Mon Oct 1 15:53:31 2007
@@ -435,6 +435,7 @@
return ret;
}
+
/* Converts a device-dependent bitmap to a DIB */
INT STDCALL
NtGdiGetDIBitsInternal(HDC hDC,
@@ -447,156 +448,134 @@
UINT MaxBits,
UINT MaxInfo)
{
- BITMAPOBJ *BitmapObj;
- SURFOBJ *DestSurfObj;
- XLATEOBJ *XlateObj;
- HBITMAP DestBitmap;
- SIZEL DestSize;
- HPALETTE hSourcePalette;
- HPALETTE hDestPalette;
- PPALGDI SourcePalette;
- PPALGDI DestPalette;
- ULONG SourcePaletteType;
- ULONG DestPaletteType;
PDC Dc;
- POINTL SourcePoint;
- RECTL DestRect;
+ BITMAPOBJ *BitmapObj = NULL;
+ HBITMAP hDestBitmap = NULL;
+ HPALETTE hSourcePalette = NULL;
+ HPALETTE hDestPalette = NULL;
+ PPALGDI SourcePalette = NULL;
+ PPALGDI DestPalette = NULL;
+ NTSTATUS Status = STATUS_SUCCESS;
ULONG Result = 0;
- ULONG Index;
+ BOOL bPaletteMatch = FALSE;
+
+ DPRINT("Entered NtGdiGetDIBitsInternal()\n");
/* Get handle for the palette in DC. */
Dc = DC_LockDc(hDC);
- if (Dc == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
- return 0;
- }
+ if (Dc == NULL) return 0;
if (Dc->IsIC)
{
DC_UnlockDc(Dc);
return 0;
}
-
+ /* Source palette obtained from the windows hdc */
hSourcePalette = Dc->w.hPalette;
- hDestPalette = Dc->w.hPalette; // unsure of this (Ged)
DC_UnlockDc(Dc);
- /* Get pointer to the source bitmap object. */
+ /* don't do anything if we fail this */
+ if (Usage != DIB_RGB_COLORS && Usage != DIB_PAL_COLORS)
+ return 0;
+
+ /* Get a pointer to the source bitmap object */
BitmapObj = BITMAPOBJ_LockBitmap(hBitmap);
if (BitmapObj == NULL)
- {
- SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
- }
-
+
+ /* fill out the BITMAPINFO struct */
if (Bits == NULL)
{
- if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ _SEH_TRY
{
- BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
- coreheader->bcWidth =BitmapObj->SurfObj.sizlBitmap.cx;
- coreheader->bcPlanes = 1;
- coreheader->bcBitCount =
BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
-
- coreheader->bcHeight = BitmapObj->SurfObj.sizlBitmap.cy;
-
- if (BitmapObj->SurfObj.lDelta > 0)
- coreheader->bcHeight = -coreheader->bcHeight;
-
+ if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
+
+ BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
+ coreheader->bcWidth =BitmapObj->SurfObj.sizlBitmap.cx;
+ coreheader->bcPlanes = 1;
+ coreheader->bcBitCount =
BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
+ coreheader->bcHeight = BitmapObj->SurfObj.sizlBitmap.cy;
+
+ if (BitmapObj->SurfObj.lDelta > 0)
+ coreheader->bcHeight = -coreheader->bcHeight;
+ }
+
+ if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+ {
+ ProbeForWrite(Info, sizeof(BITMAPINFO), 1);
+
+ Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
+ Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
+ /* Report negtive height for top-down bitmaps. */
+ if (BitmapObj->SurfObj.lDelta > 0)
+ Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
+ Info->bmiHeader.biPlanes = 1;
+ Info->bmiHeader.biBitCount =
BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
+ if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+ {
+ switch (BitmapObj->SurfObj.iBitmapFormat)
+ {
+ case BMF_1BPP:
+ case BMF_4BPP:
+ case BMF_8BPP:
+ case BMF_16BPP:
+ case BMF_24BPP:
+ case BMF_32BPP:
+ Info->bmiHeader.biCompression = BI_RGB;
+ break;
+ case BMF_4RLE:
+ Info->bmiHeader.biCompression = BI_RLE4;
+ break;
+ case BMF_8RLE:
+ Info->bmiHeader.biCompression = BI_RLE8;
+ break;
+ case BMF_JPEG:
+ Info->bmiHeader.biCompression = BI_JPEG;
+ break;
+ case BMF_PNG:
+ Info->bmiHeader.biCompression = BI_PNG;
+ break;
+ }
+
+ Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
+ Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
+ Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
+ Info->bmiHeader.biClrUsed = 0;
+ Info->bmiHeader.biClrImportant = 1 <<
Info->bmiHeader.biBitCount; /* FIXME */
+ }
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END
+
+ if (NT_SUCCESS(Status))
+ {
Result = BitmapObj->SurfObj.sizlBitmap.cy;
}
-
- if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+ }
+ else
+ {
+ SIZEL DestSize;
+ ULONG SourcePaletteType = 0;
+ ULONG DestPaletteType;
+ POINTL SourcePoint;
+ ULONG Index;
+
+ _SEH_TRY
{
- Info->bmiHeader.biWidth = BitmapObj->SurfObj.sizlBitmap.cx;
- Info->bmiHeader.biHeight = BitmapObj->SurfObj.sizlBitmap.cy;
- /* Report negtive height for top-down bitmaps. */
- if (BitmapObj->SurfObj.lDelta > 0)
- Info->bmiHeader.biHeight = -Info->bmiHeader.biHeight;
- Info->bmiHeader.biPlanes = 1;
- Info->bmiHeader.biBitCount =
BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat);
- if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+ ProbeForRead(Info, sizeof(BITMAPINFO), 1);
+
+ if (Info->bmiHeader.biBitCount ==
BitsPerFormat(BitmapObj->SurfObj.iBitmapFormat))
{
- switch (BitmapObj->SurfObj.iBitmapFormat)
- {
- case BMF_1BPP:
- case BMF_4BPP:
- case BMF_8BPP:
- case BMF_16BPP:
- case BMF_24BPP:
- case BMF_32BPP:
- Info->bmiHeader.biCompression = BI_RGB;
- break;
- case BMF_4RLE:
- Info->bmiHeader.biCompression = BI_RLE4;
- break;
- case BMF_8RLE:
- Info->bmiHeader.biCompression = BI_RLE8;
- break;
- case BMF_JPEG:
- Info->bmiHeader.biCompression = BI_JPEG;
- break;
- case BMF_PNG:
- Info->bmiHeader.biCompression = BI_PNG;
- break;
- }
-
- Info->bmiHeader.biSizeImage = BitmapObj->SurfObj.cjBits;
- Info->bmiHeader.biXPelsPerMeter = 0; /* FIXME */
- Info->bmiHeader.biYPelsPerMeter = 0; /* FIXME */
- Info->bmiHeader.biClrUsed = 0;
- Info->bmiHeader.biClrImportant = 1 <<
Info->bmiHeader.biBitCount; /* FIXME */
- Result = BitmapObj->SurfObj.sizlBitmap.cy;
+ hDestPalette = hSourcePalette;
+ bPaletteMatch = TRUE;
}
- }
- }
- else
- {
- if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
- {
- Result = 0;
- }
- else
- {
- ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy - StartScan);
- DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
- DestSize.cy = ScanLines;
-
- DestBitmap = NULL;
- if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
- {
- BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
-
- DestBitmap = EngCreateBitmap(DestSize,
- DIB_GetDIBWidthBytes(DestSize.cx,
coreheader->bcBitCount),
- BitmapFormat(coreheader->bcBitCount,
BI_RGB),
- 0 < coreheader->bcHeight ? 0 :
BMF_TOPDOWN,
- Bits);
- }
-
- if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
- {
- INT one, two, three;
-
- one = DIB_GetDIBWidthBytes(DestSize.cx, Info->bmiHeader.biBitCount),
- two = ((DestSize.cx * Info->bmiHeader.biBitCount + 31) & ~31)
>> 3;
- three = DestSize.cx * (Info->bmiHeader.biBitCount >> 3);
-
- DestBitmap = EngCreateBitmap(DestSize,
- /* DIB_GetDIBWidthBytes(DestSize.cx,
Info->bmiHeader.biBitCount), */
- DestSize.cx * (Info->bmiHeader.biBitCount
>> 3), /* HACK */
- BitmapFormat(Info->bmiHeader.biBitCount,
Info->bmiHeader.biCompression),
- 0 < Info->bmiHeader.biHeight ? 0 :
BMF_TOPDOWN,
- Bits);
- }
-
- if(DestBitmap == NULL)
- {
- BITMAPOBJ_UnlockBitmap(BitmapObj);
- return 0;
- }
-
- DestSurfObj = EngLockSurface((HSURF)DestBitmap);
+ else
+ hDestPalette = BuildDIBPalette(Info, (PINT)&DestPaletteType);
//hDestPalette = Dc->DevInfo->hpalDefault;
SourcePalette = PALETTE_LockPalette(hSourcePalette);
/* FIXME - SourcePalette can be NULL!!! Don't assert here! */
@@ -604,10 +583,18 @@
SourcePaletteType = SourcePalette->Mode;
PALETTE_UnlockPalette(SourcePalette);
- DestPalette = PALETTE_LockPalette(hDestPalette);
- /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
- //ASSERT(DestPalette);
- DestPaletteType = DestPalette->Mode;
+ if (bPaletteMatch)
+ {
+ DestPalette = PALETTE_LockPalette(hDestPalette);
+ /* FIXME - DestPalette can be NULL!!!! Don't assert here!!! */
+ DPRINT1("DestPalette : %p\n", DestPalette);
+ ASSERT(DestPalette);
+ DestPaletteType = DestPalette->Mode;
+ }
+ else
+ {
+ DestPalette = SourcePalette;
+ }
/* Copy palette. */
/* FIXME: This is largely incomplete. */
@@ -631,9 +618,65 @@
}
}
- PALETTE_UnlockPalette(DestPalette);
-
- XlateObj = IntEngCreateXlate(DestPaletteType, SourcePaletteType,
hDestPalette, hSourcePalette);
+ if (bPaletteMatch)
+ PALETTE_UnlockPalette(DestPalette);
+
+ /* Create the destination bitmap to for the copy operation */
+ if (StartScan > BitmapObj->SurfObj.sizlBitmap.cy)
+ {
+ _SEH_YIELD(goto cleanup);
+ }
+ else
+ {
+ ScanLines = min(ScanLines, BitmapObj->SurfObj.sizlBitmap.cy -
StartScan);
+ DestSize.cx = BitmapObj->SurfObj.sizlBitmap.cx;
+ DestSize.cy = ScanLines;
+
+ hDestBitmap = NULL;
+
+ ProbeForWrite(Bits, sizeof(BitmapObj->SurfObj.cjBits), 1);
+
+ if (Info->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
+ {
+ BITMAPCOREHEADER* coreheader = (BITMAPCOREHEADER*) Info;
+
+ hDestBitmap = EngCreateBitmap(DestSize,
+ DIB_GetDIBWidthBytes(DestSize.cx,
coreheader->bcBitCount),
+ BitmapFormat(coreheader->bcBitCount,
BI_RGB),
+ 0 < coreheader->bcHeight ? 0 :
BMF_TOPDOWN,
+ Bits);
+ }
+
+ if (Info->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
+ {
+ hDestBitmap = EngCreateBitmap(DestSize,
+ /* DIB_GetDIBWidthBytes(DestSize.cx,
Info->bmiHeader.biBitCount), */
+ DestSize.cx *
(Info->bmiHeader.biBitCount >> 3), /* HACK */
+
BitmapFormat(Info->bmiHeader.biBitCount, Info->bmiHeader.biCompression),
+ 0 < Info->bmiHeader.biHeight ? 0
: BMF_TOPDOWN,
+ Bits);
+ }
+
+ if (hDestBitmap == NULL)
+ _SEH_YIELD(goto cleanup);
+ }
+ }
+ _SEH_HANDLE
+ {
+ Status = _SEH_GetExceptionCode();
+ }
+ _SEH_END
+
+ if (NT_SUCCESS(Status))
+ {
+ XLATEOBJ *XlateObj;
+ SURFOBJ *DestSurfObj;
+ RECTL DestRect;
+
+ XlateObj = IntEngCreateXlate(DestPaletteType,
+ SourcePaletteType,
+ hDestPalette,
+ hSourcePalette);
SourcePoint.x = 0;
SourcePoint.y = BitmapObj->SurfObj.sizlBitmap.cy - (StartScan +
ScanLines);
@@ -643,6 +686,8 @@
DestRect.left = 0;
DestRect.right = DestSize.cx;
DestRect.bottom = DestSize.cy;
+
+ DestSurfObj = EngLockSurface((HSURF)hDestBitmap);
if (EngCopyBits(DestSurfObj,
&BitmapObj->SurfObj,
@@ -659,7 +704,16 @@
}
}
+cleanup:
+ if (hDestBitmap != NULL)
+ EngDeleteSurface((HSURF)hDestBitmap);
+
+ if (hDestPalette != NULL && bPaletteMatch == FALSE)
+ PALETTE_FreePalette(hDestPalette);
+
BITMAPOBJ_UnlockBitmap(BitmapObj);
+
+ DPRINT("leaving NtGdiGetDIBitsInternal\n");
return Result;
}
@@ -1318,14 +1372,18 @@
// Determine Bits Per Pixel
bits = bmi->bmiHeader.biBitCount;
+ //DPRINT1("%d bits\n", bits);
+
// Determine paletteType from Bits Per Pixel
if (bits <= 8)
{
+ //DPRINT1("8\n");
*paletteType = PAL_INDEXED;
RedMask = GreenMask = BlueMask = 0;
}
else if(bits < 24)
{
+ //DPRINT1("24\n");
*paletteType = PAL_BITFIELDS;
RedMask = 0xf800;
GreenMask = 0x07e0;
@@ -1333,6 +1391,7 @@
}
else
{
+ //DPRINT1("else\n");
*paletteType = PAL_BGR;
RedMask = 0xff0000;
GreenMask = 0x00ff00;
@@ -1350,14 +1409,17 @@
if (PAL_INDEXED == *paletteType)
{
+ //DPRINT1("in\n");
hPal = PALETTE_AllocPaletteIndexedRGB(ColorCount, (RGBQUAD*)bmi->bmiColors);
}
else
{
+ //DPRINT1("out\n");
hPal = PALETTE_AllocPalette(*paletteType, ColorCount,
(ULONG*) palEntries,
RedMask, GreenMask, BlueMask );
}
+ //DPRINT1("returning %p\n", hPal);
return hPal;
}
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c Mon Oct 1 15:53:31 2007
@@ -1031,7 +1031,8 @@
GdiHdr->lockline = 0;
}
#else
- InterlockedDecrement((PLONG)&GdiHdr->Locks);
+ if (InterlockedDecrement((PLONG)&GdiHdr->Locks) < 0)
+ DPRINT1("Trying to unlock non-existant object\n");
#endif
}