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/inc... ============================================================================== --- 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/ntu... ============================================================================== --- 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/obj... ============================================================================== --- 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/obj... ============================================================================== --- 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,