1. implemented shared sections used for (shared) desktop heaps

2. map the gdi handle table to userland

svn path=/trunk/; revision=13624
This commit is contained in:
Thomas Bluemel 2005-02-18 01:57:32 +00:00
parent 6d97eb3b0f
commit 18a7ecc14b
13 changed files with 545 additions and 20 deletions

View file

@ -118,6 +118,6 @@ BOOL INTERNAL_CALL GDIOBJ_UnlockObj (HGDIOBJ hObj);
#define GDIOBJFLAG_IGNOREPID (0x1)
#define GDIOBJFLAG_IGNORELOCK (0x2)
PVOID INTERNAL_CALL GDI_MapHandleTable(HANDLE hProcess);
PVOID INTERNAL_CALL GDI_MapHandleTable(PEPROCESS Process);
#endif

View file

@ -164,7 +164,6 @@ NtUserCallNextHookEx(
#define NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO 0xffff0005
#define NOPARAM_ROUTINE_ANYPOPUP 0xffff0006
#define NOPARAM_ROUTINE_CSRSS_INITIALIZED 0xffff0007
#define NOPARAM_ROUTINE_GDI_QUERY_TABLE 0xffff0008
DWORD
STDCALL
NtUserCallNoParam(

View file

@ -9,9 +9,6 @@
#define NTOS_MODE_USER
#include <ntos.h>
#define NtGdiQueryTable() \
(PGDI_TABLE_ENTRY)NtUserCallNoParam(NOPARAM_ROUTINE_GDI_QUERY_TABLE)
#define NtUserGetDCBrushColor(hbr) \
(COLORREF)NtUserCallTwoParam((DWORD)(hbr), OBJ_BRUSH, TWOPARAM_ROUTINE_GETDCCOLOR)

View file

@ -32,7 +32,7 @@ GdiProcessSetup (VOID)
hProcessHeap = GetProcessHeap();
/* map the gdi handle table to user space */
GdiHandleTable = NtGdiQueryTable();
GdiHandleTable = NtCurrentTeb()->Peb->GdiSharedHandleTable;
}

View file

@ -17,6 +17,8 @@ typedef enum
typedef struct _WINSTATION_OBJECT
{
PVOID SharedHeap; /* points to kmode memory! */
CSHORT Type;
CSHORT Size;
KSPIN_LOCK Lock;
@ -44,6 +46,8 @@ typedef struct _WINSTATION_OBJECT
typedef struct _DESKTOP_OBJECT
{
PVOID DesktopHeap; /* points to kmode memory! */
CSHORT Type;
CSHORT Size;
LIST_ENTRY ListEntry;

View file

@ -0,0 +1,73 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: shared sections
* FILE: include/ssec.h
* PROGRAMMER: Thomas Weidenmueller <w3seek@reactos.com>
*
*/
#ifndef _WIN32K_SSEC_H
#define _WIN32K_SSEC_H
typedef struct _SHARED_SECTION
{
PSECTION_OBJECT SectionObject;
PVOID SystemMappedBase;
ULONG ViewSize;
} SHARED_SECTION, *PSHARED_SECTION;
typedef struct _SHARED_SECTIONS_ARRAY
{
struct _SHARED_SECTIONS_ARRAY *Next;
ULONG nEntries;
SHARED_SECTION SharedSection[0];
} SHARED_SECTIONS_ARRAY, *PSHARED_SECTIONS_ARRAY;
typedef struct _SHARED_SECTION_POOL
{
FAST_MUTEX Lock;
ULONG PoolSize;
ULONG PoolFree;
ULONG SharedSectionCount;
SHARED_SECTIONS_ARRAY SectionsArray;
} SHARED_SECTION_POOL, *PSHARED_SECTION_POOL;
NTSTATUS INTERNAL_CALL
IntUserCreateSharedSectionPool(IN ULONG MaximumPoolSize,
IN PSHARED_SECTION_POOL *SharedSectionPool);
VOID INTERNAL_CALL
IntUserFreeSharedSectionPool(IN PSHARED_SECTION_POOL SharedSectionPool);
NTSTATUS INTERNAL_CALL
InUserDeleteSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN PVOID SystemMappedBase);
NTSTATUS INTERNAL_CALL
IntUserCreateSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN OUT PVOID *SystemMappedBase,
IN OUT ULONG *SharedSectionSize);
NTSTATUS INTERNAL_CALL
IntUserMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN PEPROCESS Process,
IN PVOID SystemMappedBase,
IN PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PVOID *UserMappedBase,
IN PULONG ViewSize OPTIONAL,
IN BOOLEAN ReadOnly);
NTSTATUS INTERNAL_CALL
IntUserUnMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN PEPROCESS Process,
IN PVOID SystemMappedBase,
IN PVOID UserMappedBase);
extern PSHARED_SECTION_POOL SessionSharedSectionPool;
#endif /* ! defined(_WIN32K_SSEC_H) */
/* EOF */

View file

@ -54,5 +54,6 @@
/* misc */
#define TAG_DRIVER TAG('G', 'D', 'R', 'V') /* video drivers */
#define TAG_FNTFILE TAG('F', 'N', 'T', 'F') /* font file */
#define TAG_SSECTPOOL TAG('S', 'S', 'C', 'P') /* shared section pool */
#endif /* _WIN32K_TAGS_H */

View file

@ -51,6 +51,8 @@ extern SSDT Win32kSSDT[];
extern SSPT Win32kSSPT[];
extern ULONG Win32kNumberOfSysCalls;
PSHARED_SECTION_POOL SessionSharedSectionPool = NULL;
NTSTATUS STDCALL
Win32kProcessCallback (struct _EPROCESS *Process,
BOOLEAN Create)
@ -76,6 +78,12 @@ Win32kProcessCallback (struct _EPROCESS *Process,
Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
if(Process->Peb != NULL)
{
/* map the gdi handle table to user land */
Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
}
/* setup process flags */
Win32Process->Flags = 0;
}
@ -237,6 +245,13 @@ DllMain (
sizeof(W32THREAD),
sizeof(W32PROCESS));
Status = IntUserCreateSharedSectionPool(48 * 1024 * 1024, /* 48 MB by default */
&SessionSharedSectionPool);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to initialize the shared section pool: Status 0x%x\n", Status);
}
Status = InitWindowStationImpl();
if (!NT_SUCCESS(Status))
{

View file

@ -53,7 +53,7 @@ ENG_OBJECTS= eng/debug.o eng/error.o eng/mem.o eng/brush.o eng/bitblt.o \
MAIN_OBJECTS = main/dllmain.o main/svctabm.o
MISC_OBJECTS = misc/driver.o misc/error.o misc/math.o misc/object.o
MISC_OBJECTS = misc/driver.o misc/error.o misc/math.o misc/object.o misc/ssec.o
LDR_OBJECTS = ldr/loader.o

View file

@ -0,0 +1,420 @@
/*
* ReactOS W32 Subsystem
* Copyright (C) 1998 - 2005 ReactOS Team
*
* 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.
*
* 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.
*/
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: shared sections support
* FILE: subsys/win32k/misc/ssec.c
* PROGRAMER: Thomas Weidenmueller <w3seek@reactos.com>
*/
#include <w32k.h>
#define NDEBUG
#include <debug.h>
/*
* FIXME - instead of mapping the memory into system space using
* MmMapViewInSystemSpace() we should rather use
* MmMapViewInSessionSpace() to map it into session space!
*/
NTSTATUS INTERNAL_CALL
IntUserCreateSharedSectionPool(IN ULONG MaximumPoolSize,
IN PSHARED_SECTION_POOL *SharedSectionPool)
{
PSHARED_SECTION_POOL Pool;
ULONG PoolStructSize;
ASSERT(SharedSectionPool);
PoolStructSize = ROUND_UP(sizeof(SHARED_SECTION_POOL), PAGE_SIZE);
Pool = ExAllocatePoolWithTag(NonPagedPool,
PoolStructSize,
TAG_SSECTPOOL);
if(Pool != NULL)
{
RtlZeroMemory(Pool, PoolStructSize);
/* initialize the session heap */
ExInitializeFastMutex(&Pool->Lock);
Pool->PoolSize = ROUND_UP(MaximumPoolSize, PAGE_SIZE);
Pool->PoolFree = Pool->PoolSize;
Pool->SharedSectionCount = 0;
Pool->SectionsArray.Next = NULL;
Pool->SectionsArray.nEntries = ((PoolStructSize - sizeof(SHARED_SECTION_POOL)) /
sizeof(SHARED_SECTION)) - 1;
ASSERT(Pool->SectionsArray.nEntries > 0);
*SharedSectionPool = Pool;
return STATUS_SUCCESS;
}
return STATUS_INSUFFICIENT_RESOURCES;
}
VOID INTERNAL_CALL
IntUserFreeSharedSectionPool(IN PSHARED_SECTION_POOL SharedSectionPool)
{
PSHARED_SECTIONS_ARRAY Array, OldArray;
PSHARED_SECTION SharedSection, LastSharedSection;
ASSERT(SharedSectionPool);
Array = &SharedSectionPool->SectionsArray;
ExAcquireFastMutex(&SharedSectionPool->Lock);
while(SharedSectionPool->SharedSectionCount > 0 && Array != NULL)
{
for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
SharedSection != LastSharedSection && SharedSectionPool->SharedSectionCount > 0;
SharedSection++)
{
if(SharedSection->SectionObject != NULL)
{
ASSERT(SharedSection->SystemMappedBase);
/* FIXME - use MmUnmapViewInSessionSpace() once implemented! */
MmUnmapViewInSystemSpace(SharedSection->SystemMappedBase);
/* dereference the keep-alive reference so the section get's deleted */
ObDereferenceObject(SharedSection->SectionObject);
SharedSectionPool->SharedSectionCount--;
}
}
OldArray = Array;
Array = Array->Next;
/* all shared sections in this array were freed, link the following array to
the main session heap and free this array */
SharedSectionPool->SectionsArray.Next = Array;
ExFreePool(OldArray);
}
ASSERT(SharedSectionPool->SectionsArray.Next == NULL);
ASSERT(SharedSectionPool->SharedSectionCount == 0);
ExReleaseFastMutex(&SharedSectionPool->Lock);
}
NTSTATUS INTERNAL_CALL
IntUserCreateSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN OUT PVOID *SystemMappedBase,
IN OUT ULONG *SharedSectionSize)
{
PSHARED_SECTIONS_ARRAY Array, LastArray;
PSHARED_SECTION FreeSharedSection, SharedSection, LastSharedSection;
LARGE_INTEGER SectionSize;
ULONG Size;
NTSTATUS Status;
ASSERT(SharedSectionPool && SharedSectionSize && (*SharedSectionSize) > 0 && SystemMappedBase);
FreeSharedSection = NULL;
Size = ROUND_UP(*SharedSectionSize, PAGE_SIZE);
ExAcquireFastMutex(&SharedSectionPool->Lock);
if(Size > SharedSectionPool->PoolFree)
{
ExReleaseFastMutex(&SharedSectionPool->Lock);
DPRINT1("Shared Section Pool limit (0x%x KB) reached, attempted to allocate a 0x%x KB shared section!\n",
SharedSectionPool->PoolSize / 1024, (*SharedSectionSize) / 1024);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* walk the array to find a free entry */
for(Array = &SharedSectionPool->SectionsArray, LastArray = Array;
Array != NULL && FreeSharedSection == NULL;
Array = Array->Next)
{
LastArray = Array;
for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
SharedSection != LastSharedSection;
SharedSection++)
{
if(SharedSection->SectionObject == NULL)
{
FreeSharedSection = SharedSection;
break;
}
}
if(Array->Next != NULL)
{
LastArray = Array;
}
}
ASSERT(LastArray);
if(FreeSharedSection == NULL)
{
ULONG nNewEntries;
PSHARED_SECTIONS_ARRAY NewArray;
ASSERT(LastArray->Next == NULL);
/* couldn't find a free entry in the array, extend the array */
nNewEntries = ((PAGE_SIZE - sizeof(SHARED_SECTIONS_ARRAY)) / sizeof(SHARED_SECTION)) + 1;
NewArray = ExAllocatePoolWithTag(NonPagedPool,
sizeof(SHARED_SECTIONS_ARRAY) + ((nNewEntries - 1) *
sizeof(SHARED_SECTION)),
TAG_SSECTPOOL);
if(NewArray == NULL)
{
ExReleaseFastMutex(&SharedSectionPool->Lock);
DPRINT1("Failed to allocate new array for shared sections!\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
NewArray->nEntries = nNewEntries;
NewArray->Next = NULL;
LastArray->Next = NewArray;
Array = NewArray;
FreeSharedSection = &Array->SharedSection[0];
}
ASSERT(FreeSharedSection);
/* now allocate a real section */
SectionSize.QuadPart = Size;
Status = MmCreateSection(&FreeSharedSection->SectionObject,
SECTION_ALL_ACCESS,
NULL,
&SectionSize,
PAGE_EXECUTE_READWRITE,
SEC_COMMIT,
NULL,
NULL);
if(NT_SUCCESS(Status))
{
Status = MmMapViewInSystemSpace(FreeSharedSection->SectionObject,
&FreeSharedSection->SystemMappedBase,
&FreeSharedSection->ViewSize);
if(NT_SUCCESS(Status))
{
(*SharedSectionSize) -= Size;
SharedSectionPool->SharedSectionCount++;
*SystemMappedBase = FreeSharedSection->SystemMappedBase;
*SharedSectionSize = FreeSharedSection->ViewSize;
}
else
{
ObDereferenceObject(FreeSharedSection->SectionObject);
FreeSharedSection->SectionObject = NULL;
DPRINT1("Failed to map the shared section into system space! Status 0x%x\n", Status);
}
}
ExReleaseFastMutex(&SharedSectionPool->Lock);
return Status;
}
NTSTATUS INTERNAL_CALL
InUserDeleteSharedSection(PSHARED_SECTION_POOL SharedSectionPool,
PVOID SystemMappedBase)
{
PSHARED_SECTIONS_ARRAY Array;
PSECTION_OBJECT SectionObject;
PSHARED_SECTION SharedSection, LastSharedSection;
NTSTATUS Status;
ASSERT(SharedSectionPool && SystemMappedBase);
SectionObject = NULL;
ExAcquireFastMutex(&SharedSectionPool->Lock);
for(Array = &SharedSectionPool->SectionsArray;
Array != NULL && SectionObject == NULL;
Array = Array->Next)
{
for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
SharedSection != LastSharedSection;
SharedSection++)
{
if(SharedSection->SystemMappedBase == SystemMappedBase)
{
SectionObject = SharedSection->SectionObject;
SharedSection->SectionObject = NULL;
SharedSection->SystemMappedBase = NULL;
ASSERT(SharedSectionPool->SharedSectionCount > 0);
SharedSectionPool->SharedSectionCount--;
break;
}
}
}
ExReleaseFastMutex(&SharedSectionPool->Lock);
if(SectionObject != NULL)
{
Status = MmUnmapViewInSystemSpace(SystemMappedBase);
ObDereferenceObject(SectionObject);
}
else
{
DPRINT1("Couldn't find and delete a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
Status = STATUS_UNSUCCESSFUL;
}
return Status;
}
NTSTATUS INTERNAL_CALL
IntUserMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN PEPROCESS Process,
IN PVOID SystemMappedBase,
IN PLARGE_INTEGER SectionOffset OPTIONAL,
IN OUT PVOID *UserMappedBase,
IN PULONG ViewSize OPTIONAL,
IN BOOLEAN ReadOnly)
{
PSHARED_SECTIONS_ARRAY Array;
PSECTION_OBJECT SectionObject;
PSHARED_SECTION SharedSection, LastSharedSection;
NTSTATUS Status;
ASSERT(SharedSectionPool && Process && SystemMappedBase && UserMappedBase);
SectionObject = NULL;
ExAcquireFastMutex(&SharedSectionPool->Lock);
for(Array = &SharedSectionPool->SectionsArray;
Array != NULL && SectionObject == NULL;
Array = Array->Next)
{
for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
SharedSection != LastSharedSection;
SharedSection++)
{
if(SharedSection->SystemMappedBase == SystemMappedBase)
{
SectionObject = SharedSection->SectionObject;
break;
}
}
}
if(SectionObject != NULL)
{
ULONG RealViewSize = (ViewSize ? min(*ViewSize, SharedSection->ViewSize) : SharedSection->ViewSize);
ObReferenceObjectByPointer(SectionObject,
(ReadOnly ? SECTION_MAP_READ : SECTION_MAP_READ | SECTION_MAP_WRITE),
NULL,
KernelMode);
Status = MmMapViewOfSection(SectionObject,
Process,
UserMappedBase,
0,
0,
SectionOffset,
&RealViewSize,
ViewUnmap, /* not sure if we should inherit it... */
MEM_COMMIT,
(ReadOnly ? PAGE_READONLY : PAGE_READWRITE));
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to map shared section (readonly=%d) into user memory! Status: 0x%x\n", ReadOnly, Status);
}
}
else
{
DPRINT1("Couldn't find and map a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
Status = STATUS_UNSUCCESSFUL;
}
ExReleaseFastMutex(&SharedSectionPool->Lock);
return Status;
}
NTSTATUS INTERNAL_CALL
IntUserUnMapSharedSection(IN PSHARED_SECTION_POOL SharedSectionPool,
IN PEPROCESS Process,
IN PVOID SystemMappedBase,
IN PVOID UserMappedBase)
{
PSHARED_SECTIONS_ARRAY Array;
PSECTION_OBJECT SectionObject;
PSHARED_SECTION SharedSection, LastSharedSection;
NTSTATUS Status;
ASSERT(SharedSectionPool && Process && SystemMappedBase && UserMappedBase);
SectionObject = NULL;
ExAcquireFastMutex(&SharedSectionPool->Lock);
for(Array = &SharedSectionPool->SectionsArray;
Array != NULL && SectionObject == NULL;
Array = Array->Next)
{
for(SharedSection = Array->SharedSection, LastSharedSection = SharedSection + Array->nEntries;
SharedSection != LastSharedSection;
SharedSection++)
{
if(SharedSection->SystemMappedBase == SystemMappedBase)
{
SectionObject = SharedSection->SectionObject;
break;
}
}
}
ExReleaseFastMutex(&SharedSectionPool->Lock);
if(SectionObject != NULL)
{
Status = MmUnmapViewOfSection(Process,
UserMappedBase);
ObDereferenceObject(SectionObject);
if(!NT_SUCCESS(Status))
{
DPRINT1("Failed to unmap shared section UserMappedBase=0x%x! Status: 0x%x\n", UserMappedBase, Status);
}
}
else
{
DPRINT1("Couldn't find and unmap a shared section with SystemMappedBase=0x%x!\n", SystemMappedBase);
Status = STATUS_UNSUCCESSFUL;
}
return Status;
}

View file

@ -131,10 +131,6 @@ NtUserCallNoParam(DWORD Routine)
Result = (DWORD)CsrInit();
break;
case NOPARAM_ROUTINE_GDI_QUERY_TABLE:
Result = (DWORD)GDI_MapHandleTable(NtCurrentProcess());
break;
case NOPARAM_ROUTINE_MSQCLEARWAKEMASK:
return (DWORD)IntMsqClearWakeMask();

View file

@ -58,13 +58,15 @@ KeRosGetStackFrames ( PULONG Frames, ULONG FrameCount );
typedef struct _GDI_HANDLE_TABLE
{
/* the table must be located at the beginning of this structure so it can be
properly mapped! */
GDI_TABLE_ENTRY Entries[GDI_HANDLE_COUNT];
PPAGED_LOOKASIDE_LIST LookasideLists;
SLIST_HEADER FreeEntriesHead;
SLIST_ENTRY FreeEntries[((GDI_HANDLE_COUNT * sizeof(GDI_TABLE_ENTRY)) << 3) /
(sizeof(SLIST_ENTRY) << 3)];
GDI_TABLE_ENTRY Entries[GDI_HANDLE_COUNT];
} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
typedef struct
@ -125,11 +127,17 @@ static PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(VOID)
{
PGDI_HANDLE_TABLE handleTable;
ULONG htSize;
UINT ObjType;
UINT i;
PGDI_TABLE_ENTRY Entry;
handleTable = ExAllocatePoolWithTag(NonPagedPool, sizeof(GDI_HANDLE_TABLE), TAG_GDIHNDTBLE);
handleTable = NULL;
htSize = sizeof(GDI_HANDLE_TABLE);
IntUserCreateSharedSection(SessionSharedSectionPool,
(PVOID*)&handleTable,
&htSize);
ASSERT( handleTable );
RtlZeroMemory(handleTable, sizeof(GDI_HANDLE_TABLE));
@ -148,7 +156,8 @@ GDIOBJ_iAllocHandleTable(VOID)
TAG_GDIHNDTBLE);
if(handleTable->LookasideLists == NULL)
{
ExFreePool(handleTable);
InUserDeleteSharedSection(SessionSharedSectionPool,
handleTable);
return NULL;
}
@ -1479,12 +1488,22 @@ LockHandleFrom:
}
PVOID INTERNAL_CALL
GDI_MapHandleTable(HANDLE hProcess)
GDI_MapHandleTable(PEPROCESS Process)
{
DPRINT("%s:%i: %s(): FIXME - Map handle table into the process memory space!\n",
__FILE__, __LINE__, __FUNCTION__);
/* FIXME - Map the entire gdi handle table read-only to userland into the
scope of hProcess and return the pointer */
ULONG TableSize = sizeof(HandleTable->Entries);
PVOID MappedGdiTable = NULL; /* FIXME - try preferred GDI_HANDLE_TABLE_BASE_ADDRESS? */
NTSTATUS Status = IntUserMapSharedSection(SessionSharedSectionPool,
Process,
HandleTable,
NULL,
&MappedGdiTable,
&TableSize,
TRUE);
if(NT_SUCCESS(Status))
{
return MappedGdiTable;
}
return NULL;
}

View file

@ -28,6 +28,7 @@
#include <rosrtl/string.h>
#include <user32/callback.h>
#include <include/ssec.h>
#include <include/accelerator.h>
#include <include/callback.h>
#include <include/caret.h>