mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
change gdi object deleting mechanism to a windows compatible one.
svn path=/trunk/; revision=31661
This commit is contained in:
parent
238f8e2ac9
commit
eb5c44b4a9
2 changed files with 78 additions and 31 deletions
|
@ -24,9 +24,9 @@ typedef struct _GDI_HANDLE_TABLE
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
PPAGED_LOOKASIDE_LIST LookasideLists;
|
PPAGED_LOOKASIDE_LIST LookasideLists;
|
||||||
|
|
||||||
SLIST_HEADER FreeEntriesHead;
|
ULONG FirstFree;
|
||||||
SLIST_ENTRY FreeEntries[((GDI_HANDLE_COUNT * sizeof(GDI_TABLE_ENTRY)) << 3) /
|
ULONG FirstUnused;
|
||||||
(sizeof(SLIST_ENTRY) << 3)];
|
|
||||||
} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
|
} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
|
||||||
|
|
||||||
extern PGDI_HANDLE_TABLE GdiHandleTable;
|
extern PGDI_HANDLE_TABLE GdiHandleTable;
|
||||||
|
|
|
@ -124,9 +124,7 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
|
||||||
PGDI_HANDLE_TABLE HandleTable = NULL;
|
PGDI_HANDLE_TABLE HandleTable = NULL;
|
||||||
LARGE_INTEGER htSize;
|
LARGE_INTEGER htSize;
|
||||||
UINT ObjType;
|
UINT ObjType;
|
||||||
UINT i;
|
|
||||||
ULONG ViewSize = 0;
|
ULONG ViewSize = 0;
|
||||||
PGDI_TABLE_ENTRY Entry;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
|
||||||
ASSERT(SectionObject != NULL);
|
ASSERT(SectionObject != NULL);
|
||||||
|
@ -157,16 +155,6 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
|
||||||
|
|
||||||
RtlZeroMemory(HandleTable, sizeof(GDI_HANDLE_TABLE));
|
RtlZeroMemory(HandleTable, sizeof(GDI_HANDLE_TABLE));
|
||||||
|
|
||||||
/*
|
|
||||||
* initialize the free entry cache
|
|
||||||
*/
|
|
||||||
InitializeSListHead(&HandleTable->FreeEntriesHead);
|
|
||||||
Entry = &HandleTable->Entries[RESERVE_ENTRIES_COUNT];
|
|
||||||
for(i = GDI_HANDLE_COUNT - 1; i >= RESERVE_ENTRIES_COUNT; i--)
|
|
||||||
{
|
|
||||||
InterlockedPushEntrySList(&HandleTable->FreeEntriesHead, &HandleTable->FreeEntries[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool,
|
HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool,
|
||||||
BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
|
BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
|
||||||
TAG_GDIHNDTBLE);
|
TAG_GDIHNDTBLE);
|
||||||
|
@ -188,6 +176,9 @@ GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
|
||||||
}
|
}
|
||||||
|
|
||||||
ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */
|
ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */
|
||||||
|
|
||||||
|
HandleTable->FirstFree = 0;
|
||||||
|
HandleTable->FirstUnused = RESERVE_ENTRIES_COUNT;
|
||||||
|
|
||||||
return HandleTable;
|
return HandleTable;
|
||||||
}
|
}
|
||||||
|
@ -329,6 +320,69 @@ LockErrorDebugOutput(HGDIOBJ hObj, PGDI_TABLE_ENTRY Entry, LPSTR Function)
|
||||||
KeRosDumpStackFrames(NULL, 20);
|
KeRosDumpStackFrames(NULL, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ULONG
|
||||||
|
FASTCALL
|
||||||
|
InterlockedPopFreeEntry(PGDI_HANDLE_TABLE HandleTable)
|
||||||
|
{
|
||||||
|
ULONG idxFirstFree, idxNextFree, idxPrev;
|
||||||
|
PGDI_TABLE_ENTRY pFreeEntry;
|
||||||
|
|
||||||
|
DPRINT("Enter InterLockedPopFreeEntry\n");
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
idxFirstFree = HandleTable->FirstFree;
|
||||||
|
if (idxFirstFree)
|
||||||
|
{
|
||||||
|
pFreeEntry = HandleTable->Entries + idxFirstFree;
|
||||||
|
ASSERT(((ULONG)pFreeEntry->KernelData & ~GDI_HANDLE_INDEX_MASK) == 0);
|
||||||
|
idxNextFree = (ULONG)pFreeEntry->KernelData;
|
||||||
|
idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstFree, idxNextFree, idxFirstFree);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
idxFirstFree = HandleTable->FirstUnused;
|
||||||
|
idxNextFree = idxFirstFree + 1;
|
||||||
|
if (idxNextFree >= GDI_HANDLE_COUNT)
|
||||||
|
{
|
||||||
|
DPRINT1("No more gdi handles left!\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstUnused, idxNextFree, idxFirstFree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (idxPrev != idxFirstFree);
|
||||||
|
|
||||||
|
return idxFirstFree;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pushes an entry of the handle table to the free list,
|
||||||
|
The entry must be unlocked and the base type field must be 0 */
|
||||||
|
VOID
|
||||||
|
FASTCALL
|
||||||
|
InterlockedPushFreeEntry(PGDI_HANDLE_TABLE HandleTable, ULONG idxToFree)
|
||||||
|
{
|
||||||
|
ULONG idxFirstFree, idxPrev;
|
||||||
|
PGDI_TABLE_ENTRY pFreeEntry;
|
||||||
|
|
||||||
|
DPRINT("Enter InterlockedPushFreeEntry\n");
|
||||||
|
|
||||||
|
pFreeEntry = HandleTable->Entries + idxToFree;
|
||||||
|
ASSERT((pFreeEntry->Type & GDI_ENTRY_BASETYPE_MASK) == 0);
|
||||||
|
ASSERT(pFreeEntry->ProcessId == 0);
|
||||||
|
pFreeEntry->UserData = NULL;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
idxFirstFree = HandleTable->FirstFree;
|
||||||
|
pFreeEntry->KernelData = (PVOID)idxFirstFree;
|
||||||
|
|
||||||
|
idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&HandleTable->FirstFree, idxToFree, idxFirstFree);
|
||||||
|
}
|
||||||
|
while (idxPrev != idxFirstFree);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Allocate memory for GDI object and return handle to it.
|
* Allocate memory for GDI object and return handle to it.
|
||||||
*
|
*
|
||||||
|
@ -380,7 +434,7 @@ GDIOBJ_AllocObj(PGDI_HANDLE_TABLE HandleTable, ULONG ObjectType)
|
||||||
}
|
}
|
||||||
if(newObject != NULL)
|
if(newObject != NULL)
|
||||||
{
|
{
|
||||||
PSLIST_ENTRY FreeEntry;
|
UINT Index;
|
||||||
PGDI_TABLE_ENTRY Entry;
|
PGDI_TABLE_ENTRY Entry;
|
||||||
PGDIOBJ ObjectBody;
|
PGDIOBJ ObjectBody;
|
||||||
LONG TypeInfo;
|
LONG TypeInfo;
|
||||||
|
@ -407,15 +461,11 @@ GDIOBJ_AllocObj(PGDI_HANDLE_TABLE HandleTable, ULONG ObjectType)
|
||||||
(type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
|
(type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
|
||||||
TypeInfo = (ObjectType & GDI_HANDLE_BASETYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
|
TypeInfo = (ObjectType & GDI_HANDLE_BASETYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
|
||||||
|
|
||||||
FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead);
|
Index = InterlockedPopFreeEntry(HandleTable);
|
||||||
if(FreeEntry != NULL)
|
if (Index != 0)
|
||||||
{
|
{
|
||||||
HANDLE PrevProcId;
|
HANDLE PrevProcId;
|
||||||
UINT Index;
|
|
||||||
|
|
||||||
/* calculate the entry from the address of the entry in the free slot array */
|
|
||||||
Index = ((ULONG_PTR)FreeEntry - (ULONG_PTR)&HandleTable->FreeEntries[0]) /
|
|
||||||
sizeof(HandleTable->FreeEntries[0]);
|
|
||||||
Entry = &HandleTable->Entries[Index];
|
Entry = &HandleTable->Entries[Index];
|
||||||
|
|
||||||
LockHandle:
|
LockHandle:
|
||||||
|
@ -424,8 +474,6 @@ LockHandle:
|
||||||
{
|
{
|
||||||
HGDIOBJ Handle;
|
HGDIOBJ Handle;
|
||||||
|
|
||||||
ASSERT(Entry->KernelData == NULL);
|
|
||||||
|
|
||||||
Entry->KernelData = ObjectBody;
|
Entry->KernelData = ObjectBody;
|
||||||
|
|
||||||
/* copy the reuse-counter */
|
/* copy the reuse-counter */
|
||||||
|
@ -554,7 +602,8 @@ LockHandle:
|
||||||
if(PrevProcId == ProcessId)
|
if(PrevProcId == ProcessId)
|
||||||
{
|
{
|
||||||
if( (Entry->KernelData != NULL) &&
|
if( (Entry->KernelData != NULL) &&
|
||||||
((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) )
|
((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) &&
|
||||||
|
((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == (HandleUpper & GDI_ENTRY_BASETYPE_MASK)) )
|
||||||
{
|
{
|
||||||
PGDIOBJHDR GdiHdr;
|
PGDIOBJHDR GdiHdr;
|
||||||
|
|
||||||
|
@ -565,16 +614,14 @@ LockHandle:
|
||||||
BOOL Ret;
|
BOOL Ret;
|
||||||
PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
|
PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
|
||||||
|
|
||||||
/* Clear the type field so when unlocking the handle it gets finally deleted and increment reuse counter */
|
/* Clear the basetype field so when unlocking the handle it gets finally deleted and increment reuse counter */
|
||||||
Entry->Type = (Entry->Type + GDI_ENTRY_REUSE_INC) & GDI_ENTRY_REUSE_MASK;
|
Entry->Type = (Entry->Type + GDI_ENTRY_REUSE_INC) & ~GDI_ENTRY_BASETYPE_MASK;
|
||||||
Entry->KernelData = NULL;
|
|
||||||
|
|
||||||
/* unlock the handle slot */
|
/* unlock the handle slot */
|
||||||
(void)InterlockedExchangePointer(&Entry->ProcessId, NULL);
|
(void)InterlockedExchangePointer(&Entry->ProcessId, NULL);
|
||||||
|
|
||||||
/* push this entry to the free list */
|
/* push this entry to the free list */
|
||||||
InterlockedPushEntrySList(&HandleTable->FreeEntriesHead,
|
InterlockedPushFreeEntry(HandleTable, GDI_ENTRY_TO_INDEX(HandleTable, Entry));
|
||||||
&HandleTable->FreeEntries[GDI_ENTRY_TO_INDEX(HandleTable, Entry)]);
|
|
||||||
|
|
||||||
if(W32Process != NULL)
|
if(W32Process != NULL)
|
||||||
{
|
{
|
||||||
|
@ -646,7 +693,7 @@ LockHandle:
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)ProcessId & ~0x1);
|
DPRINT1("Attempted to free foreign handle: 0x%x Owner: 0x%x from Caller: 0x%x\n", hObj, (ULONG_PTR)PrevProcId & ~0x1, (ULONG_PTR)ProcessId & ~0x1);
|
||||||
KeRosDumpStackFrames(NULL, 20);
|
KeRosDumpStackFrames(NULL, 20);
|
||||||
}
|
}
|
||||||
#ifdef GDI_DEBUG
|
#ifdef GDI_DEBUG
|
||||||
DPRINT1("-> called from %s:%i\n", file, line);
|
DPRINT1("-> called from %s:%i\n", file, line);
|
||||||
|
|
Loading…
Reference in a new issue