Author: tkreuzer
Date: Fri Aug 3 02:14:32 2007
New Revision: 28110
URL:
http://svn.reactos.org/svn/reactos?rev=28110&view=rev
Log:
NtGdiGetSetBitmapBits:
- use SEH and probe the user mode buffers
- SetLastWin32Error on invalid handle
- move the copying to IntGetSetBitmapBits
- only use IntGetSetBitmapBits from inside win32k
- move NtGdiGetBitmapBits to bitmap.c
- allow copying a number of bytes not matching one entire line, like on windows
I think that was all changes.
Modified:
trunk/reactos/subsystems/win32/win32k/include/intgdi.h
trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
trunk/reactos/subsystems/win32/win32k/objects/bitmaps.c
trunk/reactos/subsystems/win32/win32k/objects/dibobj.c
Modified: trunk/reactos/subsystems/win32/win32k/include/intgdi.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/in…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/include/intgdi.h (original)
+++ trunk/reactos/subsystems/win32/win32k/include/intgdi.h Fri Aug 3 02:14:32 2007
@@ -259,5 +259,9 @@
VOID STDCALL IntGdiSetDCState ( HDC hDC, HDC hDCSave );
+LONG STDCALL IntSetBitmapBits(PBITMAPOBJ bmp, DWORD Bytes, IN PBYTE Bits);
+
+LONG STDCALL IntGetBitmapBits(PBITMAPOBJ bmp, DWORD Bytes, OUT PBYTE Bits);
+
#endif /* _WIN32K_INTGDI_H */
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/nt…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c (original)
+++ trunk/reactos/subsystems/win32/win32k/ntuser/cursoricon.c Fri Aug 3 02:14:32 2007
@@ -1552,7 +1552,7 @@
}
/* get icon bits */
- NtGdiGetBitmapBits(hbmOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
+ IntGetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
/* premultiply with the alpha channel value */
for (i = 0; i < cyHeight; i++)
@@ -1581,7 +1581,7 @@
}
/* set icon bits */
- NtGdiSetBitmapBits(hbmOff, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
+ IntSetBitmapBits(Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), pBits);
ExFreePool(pBits);
GDIOBJ_UnlockObjByPtr(GdiHandleTable, Bitmap);
Modified: trunk/reactos/subsystems/win32/win32k/objects/bitmaps.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ob…
==============================================================================
--- trunk/reactos/subsystems/win32/win32k/objects/bitmaps.c (original)
+++ trunk/reactos/subsystems/win32/win32k/objects/bitmaps.c Fri Aug 3 02:14:32 2007
@@ -406,7 +406,7 @@
INT Height,
UINT Planes,
UINT BitsPixel,
- IN OPTIONAL LPBYTE Bits)
+ IN OPTIONAL LPBYTE pUnsafeBits)
{
PBITMAPOBJ bmp;
HBITMAP hBitmap;
@@ -432,7 +432,7 @@
hBitmap = IntCreateBitmap(Size, WidthBytes,
BitmapFormat(BitsPixel, BI_RGB),
(Height < 0 ? BMF_TOPDOWN : 0) |
- (NULL == Bits ? 0 : BMF_NOZEROINIT), NULL);
+ (NULL == pUnsafeBits ? 0 : BMF_NOZEROINIT), NULL);
if (!hBitmap)
{
DPRINT("NtGdiCreateBitmap: returned 0\n");
@@ -450,18 +450,21 @@
}
bmp->flFlags = BITMAPOBJ_IS_APIBITMAP;
+
+ if (NULL != pUnsafeBits)
+ {
+ _SEH_TRY
+ {
+ ProbeForRead(pUnsafeBits, bmp->SurfObj.cjBits, 1);
+ IntSetBitmapBits(bmp, bmp->SurfObj.cjBits, pUnsafeBits);
+ }
+ _SEH_HANDLE
+ {
+ }
+ _SEH_END
+ }
+
BITMAPOBJ_UnlockBitmap( bmp );
-
- /*
- * NOTE: It's ugly practice, but we are using the object even
- * after unlocking. Since the handle is currently known only
- * to us it should be safe.
- */
-
- if (NULL != Bits)
- {
- NtGdiSetBitmapBits(hBitmap, bmp->SurfObj.cjBits, Bits);
- }
return hBitmap;
}
@@ -911,64 +914,160 @@
return FALSE;
}
+
+LONG STDCALL
+IntGetBitmapBits(
+ PBITMAPOBJ bmp,
+ DWORD Bytes,
+ OUT PBYTE Bits)
+{
+ LONG ret;
+
+ ASSERT(Bits);
+
+ /* Don't copy more bytes than the buffer has */
+ Bytes = min(Bytes, bmp->SurfObj.cjBits);
+
+#if 0
+ /* FIXME: Call DDI CopyBits here if available */
+ if(bmp->DDBitmap)
+ {
+ DPRINT("Calling device specific BitmapBits\n");
+ if(bmp->DDBitmap->funcs->pBitmapBits)
+ {
+ ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count, DDB_GET);
+ }
+ else
+ {
+ ERR_(bitmap)("BitmapBits == NULL??\n");
+ ret = 0;
+ }
+ }
+ else
+#endif
+ {
+ RtlCopyMemory(Bits, bmp->SurfObj.pvBits, Bytes);
+ ret = Bytes;
+ }
+ return ret;
+}
+
+LONG STDCALL
+NtGdiGetBitmapBits(HBITMAP hBitmap,
+ ULONG Bytes,
+ OUT OPTIONAL PBYTE pUnsafeBits)
+{
+ PBITMAPOBJ bmp;
+ LONG ret;
+
+ if (pUnsafeBits != NULL && Bytes == 0)
+ {
+ return 0;
+ }
+
+ bmp = BITMAPOBJ_LockBitmap (hBitmap);
+ if (!bmp)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
+ return 0;
+ }
+
+ /* If the bits vector is null, the function should return the read size */
+ if (pUnsafeBits == NULL)
+ {
+ ret = bmp->SurfObj.cjBits;
+ BITMAPOBJ_UnlockBitmap (bmp);
+ return ret;
+ }
+
+ /* Don't copy more bytes than the buffer has */
+ Bytes = min(Bytes, bmp->SurfObj.cjBits);
+
+ _SEH_TRY
+ {
+ ProbeForWrite(pUnsafeBits, Bytes, 1);
+ ret = IntGetBitmapBits(bmp, Bytes, pUnsafeBits);
+ }
+ _SEH_HANDLE
+ {
+ ret = 0;
+ }
+ _SEH_END
+
+ BITMAPOBJ_UnlockBitmap (bmp);
+
+ return ret;
+}
+
+
+LONG STDCALL
+IntSetBitmapBits(
+ PBITMAPOBJ bmp,
+ DWORD Bytes,
+ IN PBYTE Bits)
+{
+ LONG ret;
+
+ /* Don't copy more bytes than the buffer has */
+ Bytes = min(Bytes, bmp->SurfObj.cjBits);
+
+#if 0
+ /* FIXME: call DDI specific function here if available */
+ if(bmp->DDBitmap)
+ {
+ DPRINT ("Calling device specific BitmapBits\n");
+ if (bmp->DDBitmap->funcs->pBitmapBits)
+ {
+ ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes,
DDB_SET);
+ }
+ else
+ {
+ DPRINT ("BitmapBits == NULL??\n");
+ ret = 0;
+ }
+ }
+ else
+#endif
+ {
+ RtlCopyMemory(bmp->SurfObj.pvBits, Bits, Bytes);
+ ret = Bytes;
+ }
+
+ return ret;
+}
+
+
LONG STDCALL
NtGdiSetBitmapBits(
HBITMAP hBitmap,
DWORD Bytes,
- IN PBYTE Bits)
-{
- LONG height, ret;
+ IN PBYTE pUnsafeBits)
+{
+ LONG ret;
PBITMAPOBJ bmp;
+ if (pUnsafeBits == NULL || Bytes == 0)
+ {
+ return 0;
+ }
+
bmp = BITMAPOBJ_LockBitmap(hBitmap);
- if (bmp == NULL || Bits == NULL)
- {
+ if (bmp == NULL)
+ {
+ SetLastWin32Error(ERROR_INVALID_HANDLE);
return 0;
}
- if (Bytes < 0)
- {
- DPRINT ("(%ld): Negative number of bytes passed???\n", Bytes );
- Bytes = -Bytes;
- }
-
- /* Only get entire lines */
- height = Bytes / abs(bmp->SurfObj.lDelta);
- if (height > bmp->SurfObj.sizlBitmap.cy)
- {
- height = bmp->SurfObj.sizlBitmap.cy;
- }
- Bytes = height * abs(bmp->SurfObj.lDelta);
- DPRINT ("(%08x, bytes:%ld, bits:%p) %dx%d %d colors fetched height: %ld\n",
- hBitmap,
- Bytes,
- Bits,
- bmp->SurfObj.sizlBitmap.cx,
- bmp->SurfObj.sizlBitmap.cy,
- 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat),
- height);
-
-#if 0
- /* FIXME: call DDI specific function here if available */
- if(bmp->DDBitmap)
- {
- DPRINT ("Calling device specific BitmapBits\n");
- if (bmp->DDBitmap->funcs->pBitmapBits)
- {
- ret = bmp->DDBitmap->funcs->pBitmapBits(hBitmap, (void *) Bits, Bytes,
DDB_SET);
- }
- else
- {
- DPRINT ("BitmapBits == NULL??\n");
- ret = 0;
- }
- }
- else
-#endif
- {
- memcpy(bmp->SurfObj.pvBits, Bits, Bytes);
- ret = Bytes;
- }
+ _SEH_TRY
+ {
+ ProbeForRead(pUnsafeBits, Bytes, 1);
+ ret = IntSetBitmapBits(bmp, Bytes, pUnsafeBits);
+ }
+ _SEH_HANDLE
+ {
+ ret = 0;
+ }
+ _SEH_END
BITMAPOBJ_UnlockBitmap(bmp);
@@ -1464,7 +1563,7 @@
{
HBITMAP res;
BITMAP bm;
- BITMAPOBJ *Bitmap;
+ BITMAPOBJ *Bitmap, *resBitmap;
if (hBitmap == NULL)
{
@@ -1491,10 +1590,15 @@
{
PBYTE buf;
- buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight),
TAG_BITMAP);
- NtGdiGetBitmapBits (hBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
- NtGdiSetBitmapBits (res, bm.bmWidthBytes * abs(bm.bmHeight), buf);
- ExFreePool (buf);
+ resBitmap = GDIOBJ_LockObj(GdiHandleTable, res, GDI_OBJECT_TYPE_BITMAP);
+ if (resBitmap)
+ {
+ buf = ExAllocatePoolWithTag (PagedPool, bm.bmWidthBytes * abs(bm.bmHeight),
TAG_BITMAP);
+ IntGetBitmapBits (Bitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
+ IntSetBitmapBits (resBitmap, bm.bmWidthBytes * abs(bm.bmHeight), buf);
+ ExFreePool (buf);
+ GDIOBJ_UnlockObjByPtr(GdiHandleTable, resBitmap);
+ }
}
GDIOBJ_UnlockObjByPtr(GdiHandleTable, Bitmap);
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 Fri Aug 3 02:14:32 2007
@@ -631,78 +631,6 @@
return SrcHeight;
}
-LONG STDCALL NtGdiGetBitmapBits(HBITMAP hBitmap,
- ULONG Count,
- OUT OPTIONAL PBYTE Bits)
-{
- PBITMAPOBJ bmp;
- LONG height, ret;
-
- bmp = BITMAPOBJ_LockBitmap (hBitmap);
- if (!bmp)
- {
- return 0;
- }
-
- /* If the bits vector is null, the function should return the read size */
- if (Bits == NULL)
- {
- ret = bmp->SurfObj.cjBits;
- BITMAPOBJ_UnlockBitmap (bmp);
- return ret;
- }
-
- if (Count < 0)
- {
- DPRINT ("(%ld): Negative number of bytes passed???\n", Count);
- Count = -Count;
- }
-
- /* Only get entire lines */
- height = Count / abs(bmp->SurfObj.lDelta);
- if (height > bmp->SurfObj.sizlBitmap.cy)
- {
- height = bmp->SurfObj.sizlBitmap.cy;
- }
- Count = height * abs(bmp->SurfObj.lDelta);
- if (Count == 0)
- {
- DPRINT("Less then one entire line requested\n");
- BITMAPOBJ_UnlockBitmap (bmp);
- return 0;
- }
-
- DPRINT("(%08x, %ld, %p) %dx%d %d colors fetched height: %ld\n",
- hBitmap, Count, Bits, bmp->SurfObj.sizlBitmap.cx,
- bmp->SurfObj.sizlBitmap.cy,
- 1 << BitsPerFormat(bmp->SurfObj.iBitmapFormat), height );
-#if 0
- /* FIXME: Call DDI CopyBits here if available */
- if(bmp->DDBitmap)
- {
- DPRINT("Calling device specific BitmapBits\n");
- if(bmp->DDBitmap->funcs->pBitmapBits)
- {
- ret = bmp->DDBitmap->funcs->pBitmapBits(hbitmap, bits, count,
- DDB_GET);
- }
- else
- {
- ERR_(bitmap)("BitmapBits == NULL??\n");
- ret = 0;
- }
- }
- else
-#endif
- {
- memcpy(Bits, bmp->SurfObj.pvBits, Count);
- ret = Count;
- }
-
- BITMAPOBJ_UnlockBitmap (bmp);
-
- return ret;
-}
HBITMAP FASTCALL
IntCreateDIBitmap(PDC Dc, const BITMAPINFOHEADER *header,