From 2b5affa11dd2b499bccafee28fb5f98d81fa6417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9=20van=20Geldorp?= Date: Fri, 6 Jun 2003 10:17:44 +0000 Subject: [PATCH] Fix CreateDIBSection() and add some stuff to GetDIBits() svn path=/trunk/; revision=4849 --- reactos/subsys/win32k/eng/mem.c | 36 ++++-- reactos/subsys/win32k/objects/bitmaps.c | 29 ++++- reactos/subsys/win32k/objects/dib.c | 164 +++++++++++++++++------- reactos/subsys/win32k/objects/gdiobj.c | 40 ++++-- 4 files changed, 196 insertions(+), 73 deletions(-) diff --git a/reactos/subsys/win32k/eng/mem.c b/reactos/subsys/win32k/eng/mem.c index 2cebab25856..993930bc6f1 100644 --- a/reactos/subsys/win32k/eng/mem.c +++ b/reactos/subsys/win32k/eng/mem.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: mem.c,v 1.8 2003/05/18 17:16:17 ea Exp $ +/* $Id: mem.c,v 1.9 2003/06/06 10:17:44 gvg Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -30,6 +30,13 @@ #include #include +typedef struct _USERMEMHEADER + { + ULONG Tag; + ULONG MemSize; + } +USERMEMHEADER, *PUSERMEMHEADER; + PVOID STDCALL EngAllocMem(ULONG Flags, ULONG MemSize, @@ -54,20 +61,33 @@ EngFreeMem(PVOID Mem) } PVOID STDCALL -EngAllocUserMem(ULONG cj, ULONG tag) +EngAllocUserMem(ULONG cj, ULONG Tag) { - PVOID newMem = NULL; - NTSTATUS status; + PVOID NewMem = NULL; + NTSTATUS Status; + ULONG MemSize = sizeof(USERMEMHEADER) + cj; + PUSERMEMHEADER Header; - status = ZwAllocateVirtualMemory(NtCurrentProcess(), &newMem, 0, &cj, MEM_COMMIT, PAGE_READWRITE); + Status = ZwAllocateVirtualMemory(NtCurrentProcess(), &NewMem, 0, &MemSize, MEM_COMMIT, PAGE_READWRITE); - if(status != STATUS_SUCCESS) return NULL; - return newMem; + if (! NT_SUCCESS(Status)) + { + return NULL; + } + + Header = (PUSERMEMHEADER) NewMem; + Header->Tag = Tag; + Header->MemSize = cj; + + return (PVOID)(Header + 1); } VOID STDCALL EngFreeUserMem(PVOID pv) { - ZwFreeVirtualMemory (NtCurrentProcess(), &pv, 0, MEM_DECOMMIT); + PUSERMEMHEADER Header = ((PUSERMEMHEADER) pv) - 1; + ULONG MemSize = sizeof(USERMEMHEADER) + Header->MemSize; + + ZwFreeVirtualMemory(NtCurrentProcess(), (PVOID *) &Header, &MemSize, MEM_DECOMMIT); } /* EOF */ diff --git a/reactos/subsys/win32k/objects/bitmaps.c b/reactos/subsys/win32k/objects/bitmaps.c index b17040d5690..2e6684f7698 100644 --- a/reactos/subsys/win32k/objects/bitmaps.c +++ b/reactos/subsys/win32k/objects/bitmaps.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: bitmaps.c,v 1.28 2003/06/03 22:26:52 ekohl Exp $ */ +/* $Id: bitmaps.c,v 1.29 2003/06/06 10:17:44 gvg Exp $ */ #undef WIN32_LEAN_AND_MEAN #include #include @@ -193,10 +193,29 @@ HBITMAP STDCALL W32kCreateBitmap(INT Width, BOOL FASTCALL Bitmap_InternalDelete( PBITMAPOBJ pBmp ) { - ASSERT( pBmp ); - if( pBmp->bitmap.bmBits ) - ExFreePool(pBmp->bitmap.bmBits); - return TRUE; + ASSERT( pBmp ); + + if (NULL != pBmp->bitmap.bmBits) + { + if (NULL != pBmp->dib) + { + if (NULL == pBmp->dib->dshSection) + { + EngFreeUserMem(pBmp->bitmap.bmBits); + } + else + { + /* This is a file-mapped section */ + UNIMPLEMENTED; + } + } + else + { + ExFreePool(pBmp->bitmap.bmBits); + } + } + + return TRUE; } diff --git a/reactos/subsys/win32k/objects/dib.c b/reactos/subsys/win32k/objects/dib.c index 5c3d0d6620d..d1c351d540d 100644 --- a/reactos/subsys/win32k/objects/dib.c +++ b/reactos/subsys/win32k/objects/dib.c @@ -1,22 +1,24 @@ /* - * ReactOS W32 Subsystem - * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team + * $Id: dib.c,v 1.23 2003/06/06 10:17:44 gvg Exp $ * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * ReactOS W32 Subsystem + * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: dib.c,v 1.22 2003/05/18 17:16:18 ea Exp $ */ + #undef WIN32_LEAN_AND_MEAN #include #include @@ -227,9 +229,19 @@ INT STDCALL W32kGetDIBits(HDC hDC, UINT Usage) { BITMAPINFO Info; + BITMAPCOREHEADER *Core; PBITMAPOBJ BitmapObj; INT Result; NTSTATUS Status; + PDC DCObj; + PPALGDI PalGdi; + struct + { + BITMAPINFO Info; + DWORD BitFields[3]; + } InfoWithBitFields; + DWORD *BitField; + DWORD InfoSize; BitmapObj = (PBITMAPOBJ) GDIOBJ_LockObj(hBitmap, GO_BITMAP_MAGIC); if (NULL == BitmapObj) @@ -248,13 +260,18 @@ INT STDCALL W32kGetDIBits(HDC hDC, GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); return 0; } - if (sizeof(BITMAPCOREHEADER) != Info.bmiHeader.biSize && - sizeof(BITMAPINFOHEADER) != Info.bmiHeader.biSize) + + /* If the bits are not requested, UnsafeInfo can point to either a + BITMAPINFOHEADER or a BITMAPCOREHEADER */ + if (sizeof(BITMAPINFOHEADER) != Info.bmiHeader.biSize && + (sizeof(BITMAPCOREHEADER) != Info.bmiHeader.biSize || + NULL != Bits)) { SetLastWin32Error(ERROR_INVALID_PARAMETER); GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); return 0; } + Status = MmCopyFromCaller(&(Info.bmiHeader), &(UnsafeInfo->bmiHeader), Info.bmiHeader.biSize); @@ -267,18 +284,35 @@ INT STDCALL W32kGetDIBits(HDC hDC, if (NULL == Bits) { - if (0 != Info.bmiHeader.biCompression) + if (sizeof(BITMAPINFOHEADER) == Info.bmiHeader.biSize) { - UNIMPLEMENTED; + if (0 != Info.bmiHeader.biBitCount) + { + UNIMPLEMENTED; + } + + Info.bmiHeader.biWidth = BitmapObj->bitmap.bmWidth; + Info.bmiHeader.biHeight = BitmapObj->bitmap.bmHeight; + Info.bmiHeader.biPlanes = BitmapObj->bitmap.bmPlanes; + Info.bmiHeader.biBitCount = BitmapObj->bitmap.bmBitsPixel; + Info.bmiHeader.biCompression = BI_RGB; + Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes; + } + else + { + Core = (BITMAPCOREHEADER *)(&Info.bmiHeader); + if (0 != Core->bcBitCount) + { + UNIMPLEMENTED; + } + + Core->bcWidth = BitmapObj->bitmap.bmWidth; + Core->bcHeight = BitmapObj->bitmap.bmHeight; + Core->bcPlanes = BitmapObj->bitmap.bmPlanes; + Core->bcBitCount = BitmapObj->bitmap.bmBitsPixel; } - Info.bmiHeader.biWidth = BitmapObj->bitmap.bmWidth; - Info.bmiHeader.biHeight = BitmapObj->bitmap.bmHeight; - Info.bmiHeader.biPlanes = BitmapObj->bitmap.bmPlanes; - Info.bmiHeader.biBitCount = BitmapObj->bitmap.bmBitsPixel; - Info.bmiHeader.biCompression = BI_RGB; - Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes; - Status = MmCopyToCaller(UnsafeInfo, &Info, UnsafeInfo->bmiHeader.biSize); + Status = MmCopyToCaller(UnsafeInfo, &Info, Info.bmiHeader.biSize); if (! NT_SUCCESS(Status)) { SetLastNtError(Status); @@ -287,6 +321,52 @@ INT STDCALL W32kGetDIBits(HDC hDC, } Result = 1; } + else if (0 == StartScan && Info.bmiHeader.biHeight == StartScan + ScanLines && + Info.bmiHeader.biWidth == BitmapObj->bitmap.bmWidth && + Info.bmiHeader.biHeight == BitmapObj->bitmap.bmHeight && + Info.bmiHeader.biPlanes == BitmapObj->bitmap.bmPlanes && + Info.bmiHeader.biBitCount == BitmapObj->bitmap.bmBitsPixel && + 8 < Info.bmiHeader.biBitCount) + { + Info.bmiHeader.biSizeImage = BitmapObj->bitmap.bmHeight * BitmapObj->bitmap.bmWidthBytes; + Status = MmCopyToCaller(Bits, BitmapObj->bitmap.bmBits, Info.bmiHeader.biSizeImage); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); + return 0; + } + RtlZeroMemory(&InfoWithBitFields, sizeof(InfoWithBitFields)); + RtlCopyMemory(&(InfoWithBitFields.Info), &Info, sizeof(BITMAPINFO)); + if (BI_BITFIELDS == Info.bmiHeader.biCompression) + { + DCObj = DC_HandleToPtr(hDC); + if (NULL == DCObj) + { + SetLastWin32Error(ERROR_INVALID_HANDLE); + GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); + return 0; + } + PalGdi = (PPALGDI) AccessInternalObject((ULONG) DCObj->w.hPalette); + BitField = (DWORD *) ((char *) &InfoWithBitFields + InfoWithBitFields.Info.bmiHeader.biSize); + BitField[0] = PalGdi->RedMask; + BitField[1] = PalGdi->GreenMask; + BitField[2] = PalGdi->BlueMask; + InfoSize = InfoWithBitFields.Info.bmiHeader.biSize + 3 * sizeof(DWORD); + DC_ReleasePtr(hDC); + } + else + { + InfoSize = Info.bmiHeader.biSize; + } + Status = MmCopyToCaller(UnsafeInfo, &InfoWithBitFields, InfoSize); + if (! NT_SUCCESS(Status)) + { + SetLastNtError(Status); + GDIOBJ_UnlockObj(hBitmap, GO_BITMAP_MAGIC); + return 0; + } + } else { UNIMPLEMENTED; @@ -604,9 +684,12 @@ DIB_CreateDIBSection( { bmp = BITMAPOBJ_HandleToPtr (res); if (bmp) - { - bmp->dib = (DIBSECTION *) dib; - } + { + bmp->dib = (DIBSECTION *) dib; + /* Install user-mode bits instead of kernel-mode bits */ + ExFreePool(bmp->bitmap.bmBits); + bmp->bitmap.bmBits = bm.bmBits; + } } /* WINE NOTE: WINE makes use of a colormap, which is a color translation table between the DIB and the X physical @@ -637,29 +720,16 @@ DIB_CreateDIBSection( if (res) { GDIOBJ_FreeObj(res, GO_BITMAP_MAGIC, GDIOBJFLAG_DEFAULT); res = 0; } } - // Install fault handler, if possible -/* if (bm.bmBits) - { - if (VIRTUAL_SetFaultHandler(bm.bmBits, DIB_FaultHandler, (LPVOID)res)) + if (bmp) { - if (section || offset) - { - DIB_DoProtectDIBSection( bmp, PAGE_READWRITE ); - if (dib) dib->status = DIB_AppMod; - } - else - { - DIB_DoProtectDIBSection( bmp, PAGE_READONLY ); - if (dib) dib->status = DIB_InSync; - } + BITMAPOBJ_ReleasePtr(res); } - } */ - - if( bmp ) - BITMAPOBJ_ReleasePtr(res); // Return BITMAP handle and storage location - if (bm.bmBits && bits) *bits = bm.bmBits; + if (NULL != bm.bmBits && NULL != bits) + { + *bits = bm.bmBits; + } return res; } diff --git a/reactos/subsys/win32k/objects/gdiobj.c b/reactos/subsys/win32k/objects/gdiobj.c index a3b75b50cf2..187198bc308 100644 --- a/reactos/subsys/win32k/objects/gdiobj.c +++ b/reactos/subsys/win32k/objects/gdiobj.c @@ -19,7 +19,7 @@ /* * GDIOBJ.C - GDI object manipulation routines * - * $Id: gdiobj.c,v 1.26 2003/06/03 22:26:52 ekohl Exp $ + * $Id: gdiobj.c,v 1.27 2003/06/06 10:17:44 gvg Exp $ * */ @@ -592,21 +592,35 @@ BOOL STDCALL W32kDeleteObject(HGDIOBJ hObject) * Internal function. Called when the process is destroyed to free the remaining GDI handles. * \param Process - PID of the process that was destroyed. */ -BOOL STDCALL W32kCleanupForProcess( INT Process ) +BOOL STDCALL W32kCleanupForProcess(INT Pid) { - DWORD i; - PGDI_HANDLE_ENTRY handleEntry; - PGDIOBJHDR objectHeader; + DWORD i; + PGDI_HANDLE_ENTRY handleEntry; + PGDIOBJHDR objectHeader; + NTSTATUS Status; + PEPROCESS Process; - for( i=1; i < GDI_HANDLE_NUMBER; i++ ){ - handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff); - if( handleEntry && handleEntry->wMagic != 0 && handleEntry->hProcessId == Process){ - objectHeader = (PGDIOBJHDR) handleEntry->pObject; - DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount); - GDIOBJ_FreeObj( (WORD) i & 0xffff, GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK ); - } + if (! NT_SUCCESS(PsLookupProcessByProcessId(Pid, &Process))) + { + return FALSE; + } + KeAttachProcess(Process); + + for(i = 1; i < GDI_HANDLE_NUMBER; i++) + { + handleEntry = GDIOBJ_iGetHandleEntryForIndex((WORD) i & 0xffff); + if (NULL != handleEntry && 0 != handleEntry->wMagic && + handleEntry->hProcessId == Pid) + { + objectHeader = (PGDIOBJHDR) handleEntry->pObject; + DPRINT("\nW32kCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount); + GDIOBJ_FreeObj( (WORD) i & 0xffff, GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK ); } - return TRUE; + } + + KeDetachProcess(); + + return TRUE; } /*!