Fix CreateDIBSection() and add some stuff to GetDIBits()

svn path=/trunk/; revision=4849
This commit is contained in:
Gé van Geldorp
2003-06-06 10:17:44 +00:00
parent a988e5ab0e
commit 2b5affa11d
4 changed files with 196 additions and 73 deletions
+28 -8
View File
@@ -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 <ddk/ntddk.h>
#include <ddk/winddi.h>
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 */
+24 -5
View File
@@ -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 <windows.h>
#include <stdlib.h>
@@ -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;
}
+117 -47
View File
@@ -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 <windows.h>
#include <stdlib.h>
@@ -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;
}
+27 -13
View File
@@ -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;
}
/*!