static BOOL INTERNAL_CALL
GDI_CleanupDummy(PVOID ObjectBody)
{
- return TRUE;
+ return TRUE;
}
typedef struct
PGDI_HANDLE_TABLE INTERNAL_CALL
GDIOBJ_iAllocHandleTable(OUT PSECTION_OBJECT *SectionObject)
{
- PGDI_HANDLE_TABLE HandleTable = NULL;
- LARGE_INTEGER htSize;
- UINT ObjType;
- ULONG ViewSize = 0;
- NTSTATUS Status;
-
- ASSERT(SectionObject != NULL);
-
- htSize.QuadPart = sizeof(GDI_HANDLE_TABLE);
-
- Status = MmCreateSection((PVOID*)SectionObject,
- SECTION_ALL_ACCESS,
- NULL,
- &htSize,
- PAGE_READWRITE,
- SEC_COMMIT,
- NULL,
- NULL);
- if (!NT_SUCCESS(Status))
- return NULL;
-
- /* FIXME - use MmMapViewInSessionSpace once available! */
- Status = MmMapViewInSystemSpace(*SectionObject,
- (PVOID*)&HandleTable,
- &ViewSize);
- if (!NT_SUCCESS(Status))
- {
- ObDereferenceObject(*SectionObject);
- *SectionObject = NULL;
- return NULL;
- }
-
- RtlZeroMemory(HandleTable, sizeof(GDI_HANDLE_TABLE));
-
- HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool,
- BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
- TAG_GDIHNDTBLE);
- if(HandleTable->LookasideLists == NULL)
- {
- MmUnmapViewInSystemSpace(HandleTable);
- ObDereferenceObject(*SectionObject);
- *SectionObject = NULL;
- return NULL;
- }
+ PGDI_HANDLE_TABLE HandleTable = NULL;
+ LARGE_INTEGER htSize;
+ UINT ObjType;
+ ULONG ViewSize = 0;
+ NTSTATUS Status;
+
+ ASSERT(SectionObject != NULL);
+
+ htSize.QuadPart = sizeof(GDI_HANDLE_TABLE);
- for(ObjType = 0; ObjType < BASE_OBJTYPE_COUNT; ObjType++)
- {
- if (ObjTypeInfo[ObjType].bUseLookaside)
+ Status = MmCreateSection((PVOID*)SectionObject,
+ SECTION_ALL_ACCESS,
+ NULL,
+ &htSize,
+ PAGE_READWRITE,
+ SEC_COMMIT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ return NULL;
+
+ /* FIXME - use MmMapViewInSessionSpace once available! */
+ Status = MmMapViewInSystemSpace(*SectionObject,
+ (PVOID*)&HandleTable,
+ &ViewSize);
+ if (!NT_SUCCESS(Status))
{
- ExInitializePagedLookasideList(HandleTable->LookasideLists + ObjType, NULL, NULL, 0,
- ObjTypeInfo[ObjType].ulBodySize, ObjTypeInfo[ObjType].Tag, 0);
+ ObDereferenceObject(*SectionObject);
+ *SectionObject = NULL;
+ return NULL;
}
- }
- ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */
+ RtlZeroMemory(HandleTable, sizeof(GDI_HANDLE_TABLE));
- HandleTable->FirstFree = 0;
- HandleTable->FirstUnused = RESERVE_ENTRIES_COUNT;
+ HandleTable->LookasideLists = ExAllocatePoolWithTag(NonPagedPool,
+ BASE_OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
+ TAG_GDIHNDTBLE);
+ if (HandleTable->LookasideLists == NULL)
+ {
+ MmUnmapViewInSystemSpace(HandleTable);
+ ObDereferenceObject(*SectionObject);
+ *SectionObject = NULL;
+ return NULL;
+ }
+
+ for (ObjType = 0; ObjType < BASE_OBJTYPE_COUNT; ObjType++)
+ {
+ if (ObjTypeInfo[ObjType].bUseLookaside)
+ {
+ ExInitializePagedLookasideList(HandleTable->LookasideLists + ObjType,
+ NULL,
+ NULL,
+ 0,
+ ObjTypeInfo[ObjType].ulBodySize,
+ ObjTypeInfo[ObjType].Tag,
+ 0);
+ }
+ }
+
+ ShortDelay.QuadPart = -5000LL; /* FIXME - 0.5 ms? */
- return HandleTable;
+ HandleTable->FirstFree = 0;
+ HandleTable->FirstUnused = RESERVE_ENTRIES_COUNT;
+
+ return HandleTable;
}
static __inline PPAGED_LOOKASIDE_LIST
FindLookasideList(ULONG TypeIndex)
{
- return GdiHandleTable->LookasideLists + TypeIndex;
+ return GdiHandleTable->LookasideLists + TypeIndex;
}
static __inline BOOL
RunCleanupCallback(PGDIOBJ pObj, ULONG TypeIndex)
{
- return ((GDICLEANUPPROC)ObjTypeInfo[TypeIndex].CleanupProc)(pObj);
+ return ((GDICLEANUPPROC)ObjTypeInfo[TypeIndex].CleanupProc)(pObj);
}
static __inline ULONG
GetObjectSize(ULONG TypeIndex)
{
- return ObjTypeInfo[TypeIndex].ulBodySize;
+ return ObjTypeInfo[TypeIndex].ulBodySize;
}
#ifdef GDI_DEBUG
static ULONG GDIHandleLocker[GDI_HANDLE_COUNT][GDI_STACK_LEVELS+1];
struct DbgOpenGDIHandle
{
- ULONG idx;
- int count;
+ ULONG idx;
+ int count;
};
#define H 1024
static struct DbgOpenGDIHandle h[H];
void IntDumpHandleTable(PGDI_HANDLE_TABLE HandleTable)
{
- int i, n = 0, j, k, J;
-
- if ( leak_reported )
- {
- DPRINT1("gdi handle abusers already reported!\n");
- return;
- }
-
- leak_reported = 1;
- DPRINT1("reporting gdi handle abusers:\n");
-
- /* step through GDI handle table and find out who our culprit is... */
- for ( i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++ )
- {
- for ( j = 0; j < n; j++ )
- {
+ int i, n = 0, j, k, J;
+
+ if (leak_reported)
+ {
+ DPRINT1("gdi handle abusers already reported!\n");
+ return;
+ }
+
+ leak_reported = 1;
+ DPRINT1("reporting gdi handle abusers:\n");
+
+ /* step through GDI handle table and find out who our culprit is... */
+ for (i = RESERVE_ENTRIES_COUNT; i < GDI_HANDLE_COUNT; i++)
+ {
+ for (j = 0; j < n; j++)
+ {
next:
- J = h[j].idx;
- for ( k = 0; k < GDI_STACK_LEVELS; k++ )
- {
- if ( GDIHandleAllocator[i][k]
- != GDIHandleAllocator[J][k] )
- {
- if ( ++j == n )
- goto done;
- else
- goto next;
- }
- }
- goto done;
- }
+ J = h[j].idx;
+ for (k = 0; k < GDI_STACK_LEVELS; k++)
+ {
+ if (GDIHandleAllocator[i][k]
+ != GDIHandleAllocator[J][k])
+ {
+ if (++j == n)
+ goto done;
+ else
+ goto next;
+ }
+ }
+ goto done;
+ }
done:
- if ( j < H )
- {
- if ( j == n )
- {
- h[j].idx = i;
- h[j].count = 1;
- n = n + 1;
- }
- else
- h[j].count++;
- }
- }
- /* bubble sort time! weeeeee!! */
- for ( i = 0; i < n-1; i++ )
- {
- if ( h[i].count < h[i+1].count )
- {
- struct DbgOpenGDIHandle t;
- t = h[i+1];
- h[i+1] = h[i];
- j = i;
- while ( j > 0 && h[j-1].count < t.count )
- j--;
- h[j] = t;
- }
- }
- /* print the worst offenders... */
- DbgPrint ( "Worst GDI Handle leak offenders (out of %i unique locations):\n", n );
- for ( i = 0; i < n && h[i].count > 1; i++ )
- {
- int j;
- DbgPrint ( " %i allocs: ", h[i].count );
- for ( j = 0; j < GDI_STACK_LEVELS; j++ )
- {
- ULONG Addr = GDIHandleAllocator[h[i].idx][j];
- if ( !KiRosPrintAddress ( (PVOID)Addr ) )
- DbgPrint ( "<%X>", Addr );
- }
- DbgPrint ( "\n" );
- }
- if ( i < n && h[i].count == 1 )
- DbgPrint ( "(list terminated - the remaining entries have 1 allocation only)\n" );
+ if (j < H)
+ {
+ if (j == n)
+ {
+ h[j].idx = i;
+ h[j].count = 1;
+ n = n + 1;
+ }
+ else
+ h[j].count++;
+ }
+ }
+ /* bubble sort time! weeeeee!! */
+ for (i = 0; i < n-1; i++)
+ {
+ if (h[i].count < h[i+1].count)
+ {
+ struct DbgOpenGDIHandle t;
+ t = h[i+1];
+ h[i+1] = h[i];
+ j = i;
+ while (j > 0 && h[j-1].count < t.count)
+ j--;
+ h[j] = t;
+ }
+ }
+ /* print the worst offenders... */
+ DbgPrint("Worst GDI Handle leak offenders (out of %i unique locations):\n", n);
+ for (i = 0; i < n && h[i].count > 1; i++)
+ {
+ int j;
+ DbgPrint(" %i allocs: ", h[i].count);
+ for (j = 0; j < GDI_STACK_LEVELS; j++)
+ {
+ ULONG Addr = GDIHandleAllocator[h[i].idx][j];
+ if (!KiRosPrintAddress((PVOID)Addr))
+ DbgPrint("<%X>", Addr);
+ }
+ DbgPrint("\n");
+ }
+ if (i < n && h[i].count == 1)
+ DbgPrint("(list terminated - the remaining entries have 1 allocation only)\n");
}
ULONG
FASTCALL
InterlockedPopFreeEntry()
{
- ULONG idxFirstFree, idxNextFree, idxPrev;
- PGDI_TABLE_ENTRY pFreeEntry;
-
- DPRINT("Enter InterLockedPopFreeEntry\n");
-
- do
- {
- idxFirstFree = GdiHandleTable->FirstFree;
- if (idxFirstFree)
- {
- pFreeEntry = GdiHandleTable->Entries + idxFirstFree;
- ASSERT(((ULONG)pFreeEntry->KernelData & ~GDI_HANDLE_INDEX_MASK) == 0);
- idxNextFree = (ULONG)pFreeEntry->KernelData;
- idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstFree, idxNextFree, idxFirstFree);
- }
- else
- {
- idxFirstFree = GdiHandleTable->FirstUnused;
- idxNextFree = idxFirstFree + 1;
- if (idxNextFree >= GDI_HANDLE_COUNT)
- {
- DPRINT1("No more gdi handles left!\n");
- return 0;
- }
- idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstUnused, idxNextFree, idxFirstFree);
- }
- }
- while (idxPrev != idxFirstFree);
-
- return idxFirstFree;
+ ULONG idxFirstFree, idxNextFree, idxPrev;
+ PGDI_TABLE_ENTRY pFreeEntry;
+
+ DPRINT("Enter InterLockedPopFreeEntry\n");
+
+ do
+ {
+ idxFirstFree = GdiHandleTable->FirstFree;
+ if (idxFirstFree)
+ {
+ pFreeEntry = GdiHandleTable->Entries + idxFirstFree;
+ ASSERT(((ULONG)pFreeEntry->KernelData & ~GDI_HANDLE_INDEX_MASK) == 0);
+ idxNextFree = (ULONG)pFreeEntry->KernelData;
+ idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstFree, idxNextFree, idxFirstFree);
+ }
+ else
+ {
+ idxFirstFree = GdiHandleTable->FirstUnused;
+ idxNextFree = idxFirstFree + 1;
+ if (idxNextFree >= GDI_HANDLE_COUNT)
+ {
+ DPRINT1("No more gdi handles left!\n");
+ return 0;
+ }
+ idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstUnused, idxNextFree, idxFirstFree);
+ }
+ }
+ while (idxPrev != idxFirstFree);
+
+ return idxFirstFree;
}
/* Pushes an entry of the handle table to the free list,
FASTCALL
InterlockedPushFreeEntry(ULONG idxToFree)
{
- ULONG idxFirstFree, idxPrev;
- PGDI_TABLE_ENTRY pFreeEntry;
+ ULONG idxFirstFree, idxPrev;
+ PGDI_TABLE_ENTRY pFreeEntry;
- DPRINT("Enter InterlockedPushFreeEntry\n");
+ DPRINT("Enter InterlockedPushFreeEntry\n");
- pFreeEntry = GdiHandleTable->Entries + idxToFree;
- ASSERT((pFreeEntry->Type & GDI_ENTRY_BASETYPE_MASK) == 0);
- ASSERT(pFreeEntry->ProcessId == 0);
- pFreeEntry->UserData = NULL;
+ pFreeEntry = GdiHandleTable->Entries + idxToFree;
+ ASSERT((pFreeEntry->Type & GDI_ENTRY_BASETYPE_MASK) == 0);
+ ASSERT(pFreeEntry->ProcessId == 0);
+ pFreeEntry->UserData = NULL;
- do
- {
- idxFirstFree = GdiHandleTable->FirstFree;
- pFreeEntry->KernelData = (PVOID)idxFirstFree;
+ do
+ {
+ idxFirstFree = GdiHandleTable->FirstFree;
+ pFreeEntry->KernelData = (PVOID)idxFirstFree;
- idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstFree, idxToFree, idxFirstFree);
- }
- while (idxPrev != idxFirstFree);
+ idxPrev = (ULONG)_InterlockedCompareExchange((LONG*)&GdiHandleTable->FirstFree, idxToFree, idxFirstFree);
+ }
+ while (idxPrev != idxFirstFree);
}
INTERNAL_CALL
GDIOBJ_ValidateHandle(HGDIOBJ hObj, ULONG ObjectType)
{
- PGDI_TABLE_ENTRY Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
- if((((ULONG_PTR)hObj & GDI_HANDLE_TYPE_MASK) == ObjectType) &&
- (Entry->Type << GDI_ENTRY_UPPER_SHIFT) == GDI_HANDLE_GET_UPPER(hObj))
- {
- HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
- if(pid == NULL || pid == PsGetCurrentProcessId())
+ PGDI_TABLE_ENTRY Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
+ if ((((ULONG_PTR)hObj & GDI_HANDLE_TYPE_MASK) == ObjectType) &&
+ (Entry->Type << GDI_ENTRY_UPPER_SHIFT) == GDI_HANDLE_GET_UPPER(hObj))
{
- return TRUE;
+ HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1);
+ if (pid == NULL || pid == PsGetCurrentProcessId())
+ {
+ return TRUE;
+ }
}
- }
- return FALSE;
+ return FALSE;
}
/*!
HGDIOBJ INTERNAL_CALL
GDIOBJ_AllocObj(ULONG ObjectType)
{
- PW32PROCESS W32Process;
- POBJ newObject = NULL;
- PPAGED_LOOKASIDE_LIST LookasideList = NULL;
- HANDLE CurrentProcessId, LockedProcessId;
- ULONG TypeIndex;
+ PW32PROCESS W32Process;
+ POBJ newObject = NULL;
+ PPAGED_LOOKASIDE_LIST LookasideList = NULL;
+ HANDLE CurrentProcessId, LockedProcessId;
+ ULONG TypeIndex;
#ifdef GDI_DEBUG
- ULONG Attempts = 0;
+ ULONG Attempts = 0;
#endif
- W32Process = PsGetCurrentProcessWin32Process();
- /* HACK HACK HACK: simplest-possible quota implementation - don't allow a process
- to take too many GDI objects, itself. */
- if ( W32Process && W32Process->GDIObjects >= 0x2710 )
- return NULL;
+ W32Process = PsGetCurrentProcessWin32Process();
+ /* HACK HACK HACK: simplest-possible quota implementation - don't allow a process
+ to take too many GDI objects, itself. */
+ if (W32Process && W32Process->GDIObjects >= 0x2710)
+ return NULL;
- ASSERT(ObjectType != GDI_OBJECT_TYPE_DONTCARE);
+ ASSERT(ObjectType != GDI_OBJECT_TYPE_DONTCARE);
- TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(ObjectType);
- if (ObjTypeInfo[TypeIndex].bUseLookaside)
- {
- LookasideList = FindLookasideList(TypeIndex);
- if(LookasideList != NULL)
+ TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(ObjectType);
+ if (ObjTypeInfo[TypeIndex].bUseLookaside)
{
- newObject = ExAllocateFromPagedLookasideList(LookasideList);
+ LookasideList = FindLookasideList(TypeIndex);
+ if (LookasideList != NULL)
+ {
+ newObject = ExAllocateFromPagedLookasideList(LookasideList);
+ }
}
- }
- else
- {
- newObject = ExAllocatePoolWithTag(PagedPool,
- ObjTypeInfo[TypeIndex].ulBodySize,
- ObjTypeInfo[TypeIndex].Tag);
- }
- if(newObject != NULL)
- {
- UINT Index;
- PGDI_TABLE_ENTRY Entry;
- LONG TypeInfo;
+ else
+ {
+ newObject = ExAllocatePoolWithTag(PagedPool,
+ ObjTypeInfo[TypeIndex].ulBodySize,
+ ObjTypeInfo[TypeIndex].Tag);
+ }
+ if (newObject != NULL)
+ {
+ UINT Index;
+ PGDI_TABLE_ENTRY Entry;
+ LONG TypeInfo;
- CurrentProcessId = PsGetCurrentProcessId();
- LockedProcessId = (HANDLE)((ULONG_PTR)CurrentProcessId | 0x1);
+ CurrentProcessId = PsGetCurrentProcessId();
+ LockedProcessId = (HANDLE)((ULONG_PTR)CurrentProcessId | 0x1);
- RtlZeroMemory(newObject, GetObjectSize(TypeIndex));
+ RtlZeroMemory(newObject, GetObjectSize(TypeIndex));
- /* On Windows the higher 16 bit of the type field don't contain the
- full type from the handle, but the base type.
- (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
- TypeInfo = (ObjectType & GDI_HANDLE_BASETYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
+ /* On Windows the higher 16 bit of the type field don't contain the
+ full type from the handle, but the base type.
+ (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
+ TypeInfo = (ObjectType & GDI_HANDLE_BASETYPE_MASK) | (ObjectType >> GDI_ENTRY_UPPER_SHIFT);
- Index = InterlockedPopFreeEntry();
- if (Index != 0)
- {
- HANDLE PrevProcId;
+ Index = InterlockedPopFreeEntry();
+ if (Index != 0)
+ {
+ HANDLE PrevProcId;
- Entry = &GdiHandleTable->Entries[Index];
+ Entry = &GdiHandleTable->Entries[Index];
LockHandle:
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, 0);
- if(PrevProcId == NULL)
- {
- HGDIOBJ Handle;
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, 0);
+ if (PrevProcId == NULL)
+ {
+ HGDIOBJ Handle;
- Entry->KernelData = newObject;
+ Entry->KernelData = newObject;
- /* copy the reuse-counter */
- TypeInfo |= Entry->Type & GDI_ENTRY_REUSE_MASK;
+ /* copy the reuse-counter */
+ TypeInfo |= Entry->Type & GDI_ENTRY_REUSE_MASK;
- /* we found a free entry, no need to exchange this field atomically
- since we're holding the lock */
- Entry->Type = TypeInfo;
+ /* we found a free entry, no need to exchange this field atomically
+ since we're holding the lock */
+ Entry->Type = TypeInfo;
- /* unlock the entry */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, CurrentProcessId);
+ /* unlock the entry */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, CurrentProcessId);
- GDIDBG_CAPTUREALLOCATOR(Index);
+ GDIDBG_CAPTUREALLOCATOR(Index);
- if(W32Process != NULL)
- {
- _InterlockedIncrement(&W32Process->GDIObjects);
- }
- Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo << GDI_ENTRY_UPPER_SHIFT));
+ if (W32Process != NULL)
+ {
+ _InterlockedIncrement(&W32Process->GDIObjects);
+ }
+ Handle = (HGDIOBJ)((Index & 0xFFFF) | (TypeInfo << GDI_ENTRY_UPPER_SHIFT));
- DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, newObject);
- return Handle;
- }
- else
- {
+ DPRINT("GDIOBJ_AllocObj: 0x%x ob: 0x%x\n", Handle, newObject);
+ return Handle;
+ }
+ else
+ {
#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index);
- }
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Waiting on handle in index 0x%x\n", Attempts, Index);
+ }
#endif
- /* damn, someone is trying to lock the object even though it doesn't
- eve nexist anymore, wait a little and try again!
- FIXME - we shouldn't loop forever! Give up after some time! */
- DelayExecution();
- /* try again */
- goto LockHandle;
- }
- }
+ /* damn, someone is trying to lock the object even though it doesn't
+ eve nexist anymore, wait a little and try again!
+ FIXME - we shouldn't loop forever! Give up after some time! */
+ DelayExecution();
+ /* try again */
+ goto LockHandle;
+ }
+ }
- if (ObjTypeInfo[TypeIndex].bUseLookaside)
- {
- ExFreeToPagedLookasideList(LookasideList, newObject);
+ if (ObjTypeInfo[TypeIndex].bUseLookaside)
+ {
+ ExFreeToPagedLookasideList(LookasideList, newObject);
+ }
+ else
+ {
+ ExFreePool(newObject);
+ }
+ DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n");
+ GDIDBG_DUMPHANDLETABLE();
}
else
{
- ExFreePool(newObject);
+ DPRINT1("Not enough memory to allocate gdi object!\n");
}
- DPRINT1("Failed to insert gdi object into the handle table, no handles left!\n");
- GDIDBG_DUMPHANDLETABLE();
- }
- else
- {
- DPRINT1("Not enough memory to allocate gdi object!\n");
- }
- return NULL;
+ return NULL;
}
/*!
BOOL INTERNAL_CALL
GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ExpectedType)
{
- PGDI_TABLE_ENTRY Entry;
- PPAGED_LOOKASIDE_LIST LookasideList;
- HANDLE ProcessId, LockedProcessId, PrevProcId;
- ULONG HandleType, HandleUpper, TypeIndex;
- BOOL Silent;
+ PGDI_TABLE_ENTRY Entry;
+ PPAGED_LOOKASIDE_LIST LookasideList;
+ HANDLE ProcessId, LockedProcessId, PrevProcId;
+ ULONG HandleType, HandleUpper, TypeIndex;
+ BOOL Silent;
#ifdef GDI_DEBUG
- ULONG Attempts = 0;
+ ULONG Attempts = 0;
#endif
- DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x\n", hObj);
+ DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x\n", hObj);
- if(GDI_HANDLE_IS_STOCKOBJ(hObj))
- {
- DPRINT1("GDIOBJ_FreeObj() failed, can't delete stock object handle: 0x%x !!!\n", hObj);
- GDIDBG_TRACECALLER();
- return FALSE;
- }
+ if (GDI_HANDLE_IS_STOCKOBJ(hObj))
+ {
+ DPRINT1("GDIOBJ_FreeObj() failed, can't delete stock object handle: 0x%x !!!\n", hObj);
+ GDIDBG_TRACECALLER();
+ return FALSE;
+ }
- ProcessId = PsGetCurrentProcessId();
- LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
+ ProcessId = PsGetCurrentProcessId();
+ LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
- Silent = (ExpectedType & GDI_OBJECT_TYPE_SILENT);
- ExpectedType &= ~GDI_OBJECT_TYPE_SILENT;
+ Silent = (ExpectedType & GDI_OBJECT_TYPE_SILENT);
+ ExpectedType &= ~GDI_OBJECT_TYPE_SILENT;
- HandleType = GDI_HANDLE_GET_TYPE(hObj);
- HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
+ HandleType = GDI_HANDLE_GET_TYPE(hObj);
+ HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
- /* Check if we have the requested type */
- if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
- HandleType != ExpectedType) ||
- HandleType == 0 )
- {
- DPRINT1("Attempted to free object 0x%x of wrong type (Handle: 0x%x, expected: 0x%x)\n",
- hObj, HandleType, ExpectedType);
- GDIDBG_TRACECALLER();
- return FALSE;
- }
+ /* Check if we have the requested type */
+ if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
+ HandleType != ExpectedType) ||
+ HandleType == 0 )
+ {
+ DPRINT1("Attempted to free object 0x%x of wrong type (Handle: 0x%x, expected: 0x%x)\n",
+ hObj, HandleType, ExpectedType);
+ GDIDBG_TRACECALLER();
+ return FALSE;
+ }
- Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
+ Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
LockHandle:
- /* lock the object, we must not delete global objects, so don't exchange the locking
- process ID to zero when attempting to lock a global object... */
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId);
- if(PrevProcId == ProcessId)
- {
- if( (Entry->KernelData != NULL) &&
- ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) &&
- ((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == (HandleUpper & GDI_ENTRY_BASETYPE_MASK)) )
+ /* lock the object, we must not delete global objects, so don't exchange the locking
+ process ID to zero when attempting to lock a global object... */
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId);
+ if (PrevProcId == ProcessId)
{
- POBJ Object;
-
- Object = Entry->KernelData;
-
- if(Object->cExclusiveLock == 0)
- {
- BOOL Ret;
- PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
-
- /* 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_BASETYPE_MASK;
-
- /* unlock the handle slot */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
-
- /* push this entry to the free list */
- InterlockedPushFreeEntry(GDI_ENTRY_TO_INDEX(GdiHandleTable, Entry));
-
- if(W32Process != NULL)
+ if ( (Entry->KernelData != NULL) &&
+ ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) &&
+ ((Entry->Type & GDI_ENTRY_BASETYPE_MASK) == (HandleUpper & GDI_ENTRY_BASETYPE_MASK)) )
{
- _InterlockedDecrement(&W32Process->GDIObjects);
- }
+ POBJ Object;
- /* call the cleanup routine. */
- TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(HandleType);
- Ret = RunCleanupCallback(Object, TypeIndex);
+ Object = Entry->KernelData;
- /* Now it's time to free the memory */
- if (ObjTypeInfo[TypeIndex].bUseLookaside)
- {
- LookasideList = FindLookasideList(TypeIndex);
- if(LookasideList != NULL)
- {
- ExFreeToPagedLookasideList(LookasideList, Object);
- }
+ if (Object->cExclusiveLock == 0)
+ {
+ BOOL Ret;
+ PW32PROCESS W32Process = PsGetCurrentProcessWin32Process();
+
+ /* 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_BASETYPE_MASK;
+
+ /* unlock the handle slot */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, NULL);
+
+ /* push this entry to the free list */
+ InterlockedPushFreeEntry(GDI_ENTRY_TO_INDEX(GdiHandleTable, Entry));
+
+ if (W32Process != NULL)
+ {
+ _InterlockedDecrement(&W32Process->GDIObjects);
+ }
+
+ /* call the cleanup routine. */
+ TypeIndex = GDI_OBJECT_GET_TYPE_INDEX(HandleType);
+ Ret = RunCleanupCallback(Object, TypeIndex);
+
+ /* Now it's time to free the memory */
+ if (ObjTypeInfo[TypeIndex].bUseLookaside)
+ {
+ LookasideList = FindLookasideList(TypeIndex);
+ if (LookasideList != NULL)
+ {
+ ExFreeToPagedLookasideList(LookasideList, Object);
+ }
+ }
+ else
+ {
+ ExFreePool(Object);
+ }
+
+ return Ret;
+ }
+ else
+ {
+ /*
+ * The object is currently locked, so freeing is forbidden!
+ */
+ DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock);
+ GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
+ ASSERT(FALSE);
+ }
}
else
{
- ExFreePool(Object);
+ LockErrorDebugOutput(hObj, Entry, "GDIOBJ_FreeObj");
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
}
-
- return Ret;
- }
- else
- {
- /*
- * The object is currently locked, so freeing is forbidden!
- */
- DPRINT1("Object->cExclusiveLock = %d\n", Object->cExclusiveLock);
- GDIDBG_TRACELOCKER(GDI_HANDLE_GET_INDEX(hObj));
- ASSERT(FALSE);
- }
}
- else
+ else if (PrevProcId == LockedProcessId)
{
- LockErrorDebugOutput(hObj, Entry, "GDIOBJ_FreeObj");
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
- }
- }
- else if(PrevProcId == LockedProcessId)
- {
#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Waiting on 0x%x\n", Attempts, hObj);
- }
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Waiting on 0x%x\n", Attempts, hObj);
+ }
#endif
- /* the object is currently locked, wait some time and try again.
- FIXME - we shouldn't loop forever! Give up after some time! */
- DelayExecution();
- /* try again */
- goto LockHandle;
- }
- else
- {
- if(!Silent)
+ /* the object is currently locked, wait some time and try again.
+ FIXME - we shouldn't loop forever! Give up after some time! */
+ DelayExecution();
+ /* try again */
+ goto LockHandle;
+ }
+ else
{
- if(((ULONG_PTR)PrevProcId & ~0x1) == 0)
- {
- DPRINT1("Attempted to free global gdi handle 0x%x, caller needs to get ownership first!!!\n", hObj);
- DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
- }
- 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);
- }
- GDIDBG_TRACECALLER();
- GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ if (!Silent)
+ {
+ if (((ULONG_PTR)PrevProcId & ~0x1) == 0)
+ {
+ DPRINT1("Attempted to free global gdi handle 0x%x, caller needs to get ownership first!!!\n", hObj);
+ DPRINT1("Type = 0x%lx, KernelData = 0x%p, ProcessId = 0x%p\n", Entry->Type, Entry->KernelData, Entry->ProcessId);
+ }
+ 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);
+ }
+ GDIDBG_TRACECALLER();
+ GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ }
}
- }
- return FALSE;
+ return FALSE;
}
BOOL
FASTCALL
IsObjectDead(HGDIOBJ hObject)
{
- INT Index = GDI_HANDLE_GET_INDEX(hObject);
- PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
- // We check to see if the objects are knocking on deaths door.
- if ((Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && Entry->KernelData != NULL)
- return FALSE;
- else
- {
- DPRINT1("Object 0x%x currently being destroyed!!!\n",hObject);
- return TRUE; // return true and move on.
- }
+ INT Index = GDI_HANDLE_GET_INDEX(hObject);
+ PGDI_TABLE_ENTRY Entry = &GdiHandleTable->Entries[Index];
+ // We check to see if the objects are knocking on deaths door.
+ if ((Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && Entry->KernelData != NULL)
+ return FALSE;
+ else
+ {
+ DPRINT1("Object 0x%x currently being destroyed!!!\n",hObject);
+ return TRUE; // return true and move on.
+ }
}
FASTCALL
NtGdiDeleteObject(HGDIOBJ hObject)
{
- DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
- if(!IsObjectDead(hObject))
- {
- return NULL != hObject
- ? GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE) : FALSE;
- }
- else
- {
- DPRINT1("Attempt DeleteObject 0x%x currently being destroyed!!!\n",hObject);
- return TRUE; // return true and move on.
- }
+ DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
+ if (!IsObjectDead(hObject))
+ {
+ return NULL != hObject
+ ? GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE) : FALSE;
+ }
+ else
+ {
+ DPRINT1("Attempt DeleteObject 0x%x currently being destroyed!!!\n",hObject);
+ return TRUE; // return true and move on.
+ }
}
/*!
* \param Process - PID of the process that will be destroyed.
*/
BOOL INTERNAL_CALL
-GDI_CleanupForProcess (struct _EPROCESS *Process)
+GDI_CleanupForProcess(struct _EPROCESS *Process)
{
- PGDI_TABLE_ENTRY Entry, End;
- PEPROCESS CurrentProcess;
- PW32PROCESS W32Process;
- HANDLE ProcId;
- ULONG Index = RESERVE_ENTRIES_COUNT;
-
- DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Process->UniqueProcessId);
- CurrentProcess = PsGetCurrentProcess();
- if (CurrentProcess != Process)
+ PGDI_TABLE_ENTRY Entry, End;
+ PEPROCESS CurrentProcess;
+ PW32PROCESS W32Process;
+ HANDLE ProcId;
+ ULONG Index = RESERVE_ENTRIES_COUNT;
+
+ DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Process->UniqueProcessId);
+ CurrentProcess = PsGetCurrentProcess();
+ if (CurrentProcess != Process)
{
- KeAttachProcess(&Process->Pcb);
+ KeAttachProcess(&Process->Pcb);
}
- W32Process = (PW32PROCESS)Process->Win32Process;
- ASSERT(W32Process);
-
- if(W32Process->GDIObjects > 0)
- {
- /* FIXME - Instead of building the handle here and delete it using GDIOBJ_FreeObj
- we should delete it directly here! */
- ProcId = Process->UniqueProcessId;
-
- End = &GdiHandleTable->Entries[GDI_HANDLE_COUNT];
- for(Entry = &GdiHandleTable->Entries[RESERVE_ENTRIES_COUNT];
- Entry != End;
- Entry++, Index++)
+ W32Process = (PW32PROCESS)Process->Win32Process;
+ ASSERT(W32Process);
+
+ if (W32Process->GDIObjects > 0)
{
- /* ignore the lock bit */
- if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0)
- {
- HGDIOBJ ObjectHandle;
-
- /* Create the object handle for the entry, the lower(!) 16 bit of the
- Type field includes the type of the object including the stock
- object flag - but since stock objects don't have a process id we can
- simply ignore this fact here. */
- ObjectHandle = (HGDIOBJ)(Index | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
-
- if(GDIOBJ_FreeObj(ObjectHandle, GDI_OBJECT_TYPE_DONTCARE) &&
- W32Process->GDIObjects == 0)
+ /* FIXME - Instead of building the handle here and delete it using GDIOBJ_FreeObj
+ we should delete it directly here! */
+ ProcId = Process->UniqueProcessId;
+
+ End = &GdiHandleTable->Entries[GDI_HANDLE_COUNT];
+ for (Entry = &GdiHandleTable->Entries[RESERVE_ENTRIES_COUNT];
+ Entry != End;
+ Entry++, Index++)
{
- /* there are no more gdi handles for this process, bail */
- break;
+ /* ignore the lock bit */
+ if ( (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId &&
+ (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 )
+ {
+ HGDIOBJ ObjectHandle;
+
+ /* Create the object handle for the entry, the lower(!) 16 bit of the
+ Type field includes the type of the object including the stock
+ object flag - but since stock objects don't have a process id we can
+ simply ignore this fact here. */
+ ObjectHandle = (HGDIOBJ)(Index | (Entry->Type << GDI_ENTRY_UPPER_SHIFT));
+
+ if (GDIOBJ_FreeObj(ObjectHandle, GDI_OBJECT_TYPE_DONTCARE) &&
+ W32Process->GDIObjects == 0)
+ {
+ /* there are no more gdi handles for this process, bail */
+ break;
+ }
+ }
}
- }
}
- }
- if (CurrentProcess != Process)
+ if (CurrentProcess != Process)
{
- KeDetachProcess();
+ KeDetachProcess();
}
- DPRINT("Completed cleanup for process %d\n", Process->UniqueProcessId);
+ DPRINT("Completed cleanup for process %d\n", Process->UniqueProcessId);
- return TRUE;
+ return TRUE;
}
/*!
* \todo Get rid of the ExpectedType parameter!
*/
PGDIOBJ INTERNAL_CALL
-GDIOBJ_LockObj (HGDIOBJ hObj, DWORD ExpectedType)
+GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ExpectedType)
{
- ULONG HandleIndex;
- PGDI_TABLE_ENTRY Entry;
- HANDLE ProcessId, HandleProcessId, LockedProcessId, PrevProcId;
- POBJ Object = NULL;
- ULONG HandleType, HandleUpper;
-
- HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
- HandleType = GDI_HANDLE_GET_TYPE(hObj);
- HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
-
- /* Check that the handle index is valid. */
- if (HandleIndex >= GDI_HANDLE_COUNT)
- return NULL;
-
- Entry = &GdiHandleTable->Entries[HandleIndex];
-
- /* Check if we have the requested type */
- if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
- HandleType != ExpectedType) ||
- HandleType == 0 )
- {
- DPRINT1("Attempted to lock object 0x%x of wrong type (Handle: 0x%x, requested: 0x%x)\n",
- hObj, HandleType, ExpectedType);
- GDIDBG_TRACECALLER();
- GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
- return NULL;
- }
-
- ProcessId = (HANDLE)((ULONG_PTR)PsGetCurrentProcessId() & ~1);
- HandleProcessId = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~1);
-
- /* Check for invalid owner. */
- if (ProcessId != HandleProcessId && HandleProcessId != NULL)
- {
- DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId);
- GDIDBG_TRACECALLER();
- GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
- return NULL;
- }
-
- /*
- * Prevent the thread from being terminated during the locking process.
- * It would result in undesired effects and inconsistency of the global
- * handle table.
- */
-
- KeEnterCriticalRegion();
-
- /*
- * Loop until we either successfully lock the handle entry & object or
- * fail some of the check.
- */
-
- for (;;)
- {
- /* Lock the handle table entry. */
- LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1);
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId,
- LockedProcessId,
- HandleProcessId);
-
- if (PrevProcId == HandleProcessId)
- {
- /*
- * We're locking an object that belongs to our process or it's a
- * global object if HandleProcessId is 0 here.
- */
-
- if ( (Entry->KernelData != NULL) &&
- ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) )
- {
- PW32THREAD Thread = PsGetCurrentThreadWin32Thread();
- Object = Entry->KernelData;
+ ULONG HandleIndex;
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE ProcessId, HandleProcessId, LockedProcessId, PrevProcId;
+ POBJ Object = NULL;
+ ULONG HandleType, HandleUpper;
- if (Object->cExclusiveLock == 0)
+ HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
+ HandleType = GDI_HANDLE_GET_TYPE(hObj);
+ HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
+
+ /* Check that the handle index is valid. */
+ if (HandleIndex >= GDI_HANDLE_COUNT)
+ return NULL;
+
+ Entry = &GdiHandleTable->Entries[HandleIndex];
+
+ /* Check if we have the requested type */
+ if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
+ HandleType != ExpectedType) ||
+ HandleType == 0 )
+ {
+ DPRINT1("Attempted to lock object 0x%x of wrong type (Handle: 0x%x, requested: 0x%x)\n",
+ hObj, HandleType, ExpectedType);
+ GDIDBG_TRACECALLER();
+ GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ return NULL;
+ }
+
+ ProcessId = (HANDLE)((ULONG_PTR)PsGetCurrentProcessId() & ~1);
+ HandleProcessId = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~1);
+
+ /* Check for invalid owner. */
+ if (ProcessId != HandleProcessId && HandleProcessId != NULL)
+ {
+ DPRINT1("Tried to lock object (0x%p) of wrong owner! ProcessId = %p, HandleProcessId = %p\n", hObj, ProcessId, HandleProcessId);
+ GDIDBG_TRACECALLER();
+ GDIDBG_TRACEALLOCATOR(GDI_HANDLE_GET_INDEX(hObj));
+ return NULL;
+ }
+
+ /*
+ * Prevent the thread from being terminated during the locking process.
+ * It would result in undesired effects and inconsistency of the global
+ * handle table.
+ */
+
+ KeEnterCriticalRegion();
+
+ /*
+ * Loop until we either successfully lock the handle entry & object or
+ * fail some of the check.
+ */
+
+ for (;;)
+ {
+ /* Lock the handle table entry. */
+ LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1);
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId,
+ LockedProcessId,
+ HandleProcessId);
+
+ if (PrevProcId == HandleProcessId)
+ {
+ /*
+ * We're locking an object that belongs to our process or it's a
+ * global object if HandleProcessId is 0 here.
+ */
+
+ if ( (Entry->KernelData != NULL) &&
+ ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) == HandleUpper) )
{
- Object->Tid = Thread;
- Object->cExclusiveLock = 1;
- GDIDBG_CAPTURELOCKER(GDI_HANDLE_GET_INDEX(hObj))
+ PW32THREAD Thread = PsGetCurrentThreadWin32Thread();
+ Object = Entry->KernelData;
+
+ if (Object->cExclusiveLock == 0)
+ {
+ Object->Tid = Thread;
+ Object->cExclusiveLock = 1;
+ GDIDBG_CAPTURELOCKER(GDI_HANDLE_GET_INDEX(hObj))
+ }
+ else
+ {
+ if (Object->Tid != Thread)
+ {
+ /* Unlock the handle table entry. */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+
+ DelayExecution();
+ continue;
+ }
+ _InterlockedIncrement((PLONG)&Object->cExclusiveLock);
+ }
}
else
{
- if (Object->Tid != Thread)
- {
- /* Unlock the handle table entry. */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
-
- DelayExecution();
- continue;
- }
- _InterlockedIncrement((PLONG)&Object->cExclusiveLock);
+ /*
+ * Debugging code. Report attempts to lock deleted handles and
+ * locking type mismatches.
+ */
+ LockErrorDebugOutput(hObj, Entry, "GDIOBJ_LockObj");
}
- }
- else
- {
- /*
- * Debugging code. Report attempts to lock deleted handles and
- * locking type mismatches.
- */
- LockErrorDebugOutput(hObj, Entry, "GDIOBJ_LockObj");
- }
- /* Unlock the handle table entry. */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+ /* Unlock the handle table entry. */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
- break;
- }
- else
- {
- /*
- * The handle is currently locked, wait some time and try again.
- */
+ break;
+ }
+ else
+ {
+ /*
+ * The handle is currently locked, wait some time and try again.
+ */
- DelayExecution();
- continue;
- }
- }
+ DelayExecution();
+ continue;
+ }
+ }
- KeLeaveCriticalRegion();
+ KeLeaveCriticalRegion();
- return Object;
+ return Object;
}
* \todo Get rid of the ExpectedType parameter!
*/
PGDIOBJ INTERNAL_CALL
-GDIOBJ_ShareLockObj (HGDIOBJ hObj, DWORD ExpectedType)
+GDIOBJ_ShareLockObj(HGDIOBJ hObj, DWORD ExpectedType)
{
- ULONG HandleIndex;
- PGDI_TABLE_ENTRY Entry;
- HANDLE ProcessId, HandleProcessId, LockedProcessId, PrevProcId;
- POBJ Object = NULL;
- ULONG_PTR HandleType, HandleUpper;
-
- HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
- HandleType = GDI_HANDLE_GET_TYPE(hObj);
- HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
-
- /* Check that the handle index is valid. */
- if (HandleIndex >= GDI_HANDLE_COUNT)
- return NULL;
-
- /* Check if we have the requested type */
- if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
- HandleType != ExpectedType) ||
- HandleType == 0 )
- {
- DPRINT1("Attempted to lock object 0x%x of wrong type (Handle: 0x%x, requested: 0x%x)\n",
- hObj, HandleType, ExpectedType);
- return NULL;
- }
-
- Entry = &GdiHandleTable->Entries[HandleIndex];
-
- ProcessId = (HANDLE)((ULONG_PTR)PsGetCurrentProcessId() & ~1);
- HandleProcessId = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~1);
-
- /* Check for invalid owner. */
- if (ProcessId != HandleProcessId && HandleProcessId != NULL)
- {
- return NULL;
- }
-
- /*
- * Prevent the thread from being terminated during the locking process.
- * It would result in undesired effects and inconsistency of the global
- * handle table.
- */
-
- KeEnterCriticalRegion();
-
- /*
- * Loop until we either successfully lock the handle entry & object or
- * fail some of the check.
- */
-
- for (;;)
- {
- /* Lock the handle table entry. */
- LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1);
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId,
- LockedProcessId,
- HandleProcessId);
-
- if (PrevProcId == HandleProcessId)
- {
- /*
- * We're locking an object that belongs to our process or it's a
- * global object if HandleProcessId is 0 here.
- */
-
- if ( (Entry->KernelData != NULL) &&
- (HandleUpper == (Entry->Type << GDI_ENTRY_UPPER_SHIFT)) )
- {
- Object = (POBJ)Entry->KernelData;
+ ULONG HandleIndex;
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE ProcessId, HandleProcessId, LockedProcessId, PrevProcId;
+ POBJ Object = NULL;
+ ULONG_PTR HandleType, HandleUpper;
-#ifdef GDI_DEBUG
- if (_InterlockedIncrement((PLONG)&Object->ulShareCount) == 1)
+ HandleIndex = GDI_HANDLE_GET_INDEX(hObj);
+ HandleType = GDI_HANDLE_GET_TYPE(hObj);
+ HandleUpper = GDI_HANDLE_GET_UPPER(hObj);
+
+ /* Check that the handle index is valid. */
+ if (HandleIndex >= GDI_HANDLE_COUNT)
+ return NULL;
+
+ /* Check if we have the requested type */
+ if ( (ExpectedType != GDI_OBJECT_TYPE_DONTCARE &&
+ HandleType != ExpectedType) ||
+ HandleType == 0 )
+ {
+ DPRINT1("Attempted to lock object 0x%x of wrong type (Handle: 0x%x, requested: 0x%x)\n",
+ hObj, HandleType, ExpectedType);
+ return NULL;
+ }
+
+ Entry = &GdiHandleTable->Entries[HandleIndex];
+
+ ProcessId = (HANDLE)((ULONG_PTR)PsGetCurrentProcessId() & ~1);
+ HandleProcessId = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~1);
+
+ /* Check for invalid owner. */
+ if (ProcessId != HandleProcessId && HandleProcessId != NULL)
+ {
+ return NULL;
+ }
+
+ /*
+ * Prevent the thread from being terminated during the locking process.
+ * It would result in undesired effects and inconsistency of the global
+ * handle table.
+ */
+
+ KeEnterCriticalRegion();
+
+ /*
+ * Loop until we either successfully lock the handle entry & object or
+ * fail some of the check.
+ */
+
+ for (;;)
+ {
+ /* Lock the handle table entry. */
+ LockedProcessId = (HANDLE)((ULONG_PTR)HandleProcessId | 0x1);
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId,
+ LockedProcessId,
+ HandleProcessId);
+
+ if (PrevProcId == HandleProcessId)
+ {
+ /*
+ * We're locking an object that belongs to our process or it's a
+ * global object if HandleProcessId is 0 here.
+ */
+
+ if ( (Entry->KernelData != NULL) &&
+ (HandleUpper == (Entry->Type << GDI_ENTRY_UPPER_SHIFT)) )
{
- memset(GDIHandleLocker[HandleIndex], 0x00, GDI_STACK_LEVELS * sizeof(ULONG));
- RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleLocker[HandleIndex], NULL);
- }
+ Object = (POBJ)Entry->KernelData;
+
+#ifdef GDI_DEBUG
+ if (_InterlockedIncrement((PLONG)&Object->ulShareCount) == 1)
+ {
+ memset(GDIHandleLocker[HandleIndex], 0x00, GDI_STACK_LEVELS * sizeof(ULONG));
+ RtlCaptureStackBackTrace(1, GDI_STACK_LEVELS, (PVOID*)GDIHandleLocker[HandleIndex], NULL);
+ }
#else
- _InterlockedIncrement((PLONG)&Object->ulShareCount);
+ _InterlockedIncrement((PLONG)&Object->ulShareCount);
#endif
- }
- else
- {
- /*
- * Debugging code. Report attempts to lock deleted handles and
- * locking type mismatches.
- */
- LockErrorDebugOutput(hObj, Entry, "GDIOBJ_ShareLockObj");
- }
+ }
+ else
+ {
+ /*
+ * Debugging code. Report attempts to lock deleted handles and
+ * locking type mismatches.
+ */
+ LockErrorDebugOutput(hObj, Entry, "GDIOBJ_ShareLockObj");
+ }
- /* Unlock the handle table entry. */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+ /* Unlock the handle table entry. */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
- break;
- }
- else
- {
- /*
- * The handle is currently locked, wait some time and try again.
- */
+ break;
+ }
+ else
+ {
+ /*
+ * The handle is currently locked, wait some time and try again.
+ */
- DelayExecution();
- continue;
- }
- }
+ DelayExecution();
+ continue;
+ }
+ }
- KeLeaveCriticalRegion();
+ KeLeaveCriticalRegion();
- return Object;
+ return Object;
}
BOOL INTERNAL_CALL
GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle)
{
- PGDI_TABLE_ENTRY Entry;
- HANDLE ProcessId;
- BOOL Ret;
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE ProcessId;
+ BOOL Ret;
- DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle);
+ DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle);
- if(!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle))
- {
- ProcessId = PsGetCurrentProcessId();
+ if (!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle))
+ {
+ ProcessId = PsGetCurrentProcessId();
- Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, ObjectHandle);
- Ret = Entry->KernelData != NULL &&
- (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 &&
- (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
+ Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, ObjectHandle);
+ Ret = Entry->KernelData != NULL &&
+ (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 &&
+ (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
- return Ret;
- }
+ return Ret;
+ }
- return FALSE;
+ return FALSE;
}
BOOL INTERNAL_CALL
GDIOBJ_ConvertToStockObj(HGDIOBJ *phObj)
{
-/*
- * FIXME !!!!! THIS FUNCTION NEEDS TO BE FIXED - IT IS NOT SAFE WHEN OTHER THREADS
- * MIGHT ATTEMPT TO LOCK THE OBJECT DURING THIS CALL!!!
- */
- PGDI_TABLE_ENTRY Entry;
- HANDLE ProcessId, LockedProcessId, PrevProcId;
- PW32THREAD Thread;
- HGDIOBJ hObj;
+ /*
+ * FIXME !!!!! THIS FUNCTION NEEDS TO BE FIXED - IT IS NOT SAFE WHEN OTHER THREADS
+ * MIGHT ATTEMPT TO LOCK THE OBJECT DURING THIS CALL!!!
+ */
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE ProcessId, LockedProcessId, PrevProcId;
+ PW32THREAD Thread;
+ HGDIOBJ hObj;
#ifdef GDI_DEBUG
- ULONG Attempts = 0;
+ ULONG Attempts = 0;
#endif
- ASSERT(phObj);
- hObj = *phObj;
+ ASSERT(phObj);
+ hObj = *phObj;
- DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", hObj);
+ DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", hObj);
- Thread = PsGetCurrentThreadWin32Thread();
+ Thread = PsGetCurrentThreadWin32Thread();
- if(!GDI_HANDLE_IS_STOCKOBJ(hObj))
- {
- ProcessId = PsGetCurrentProcessId();
- LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
+ if (!GDI_HANDLE_IS_STOCKOBJ(hObj))
+ {
+ ProcessId = PsGetCurrentProcessId();
+ LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
- Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
+ Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, hObj);
LockHandle:
- /* lock the object, we must not convert stock objects, so don't check!!! */
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId);
- if(PrevProcId == ProcessId)
- {
- LONG NewType, PrevType, OldType;
-
- /* we're locking an object that belongs to our process. First calculate
- the new object type including the stock object flag and then try to
- exchange it.*/
- /* On Windows the higher 16 bit of the type field don't contain the
- full type from the handle, but the base type.
- (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
- OldType = ((ULONG)hObj & GDI_HANDLE_BASETYPE_MASK) | ((ULONG)hObj >> GDI_ENTRY_UPPER_SHIFT);
- /* We are currently not using bits 24..31 (flags) of the type field, but for compatibility
- we copy them as we can't get them from the handle */
- OldType |= Entry->Type & GDI_ENTRY_FLAGS_MASK;
-
- /* As the object should be a stock object, set it's flag, but only in the lower 16 bits */
- NewType = OldType | GDI_ENTRY_STOCK_MASK;
-
- /* Try to exchange the type field - but only if the old (previous type) matches! */
- PrevType = _InterlockedCompareExchange(&Entry->Type, NewType, OldType);
- if(PrevType == OldType && Entry->KernelData != NULL)
- {
- PW32THREAD PrevThread;
- POBJ Object;
-
- /* We successfully set the stock object flag.
- KernelData should never be NULL here!!! */
- ASSERT(Entry->KernelData);
-
- Object = Entry->KernelData;
-
- PrevThread = Object->Tid;
- if(Object->cExclusiveLock == 0 || PrevThread == Thread)
+ /* lock the object, we must not convert stock objects, so don't check!!! */
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, LockedProcessId, ProcessId);
+ if (PrevProcId == ProcessId)
{
- /* dereference the process' object counter */
- if(PrevProcId != GDI_GLOBAL_PROCESS)
- {
- PEPROCESS OldProcess;
- PW32PROCESS W32Process;
- NTSTATUS Status;
-
- /* FIXME */
- Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
- if(NT_SUCCESS(Status))
+ LONG NewType, PrevType, OldType;
+
+ /* we're locking an object that belongs to our process. First calculate
+ the new object type including the stock object flag and then try to
+ exchange it.*/
+ /* On Windows the higher 16 bit of the type field don't contain the
+ full type from the handle, but the base type.
+ (type = BRSUH, PEN, EXTPEN, basetype = BRUSH) */
+ OldType = ((ULONG)hObj & GDI_HANDLE_BASETYPE_MASK) | ((ULONG)hObj >> GDI_ENTRY_UPPER_SHIFT);
+ /* We are currently not using bits 24..31 (flags) of the type field, but for compatibility
+ we copy them as we can't get them from the handle */
+ OldType |= Entry->Type & GDI_ENTRY_FLAGS_MASK;
+
+ /* As the object should be a stock object, set it's flag, but only in the lower 16 bits */
+ NewType = OldType | GDI_ENTRY_STOCK_MASK;
+
+ /* Try to exchange the type field - but only if the old (previous type) matches! */
+ PrevType = _InterlockedCompareExchange(&Entry->Type, NewType, OldType);
+ if (PrevType == OldType && Entry->KernelData != NULL)
{
- W32Process = (PW32PROCESS)OldProcess->Win32Process;
- if(W32Process != NULL)
- {
- _InterlockedDecrement(&W32Process->GDIObjects);
- }
- ObDereferenceObject(OldProcess);
+ PW32THREAD PrevThread;
+ POBJ Object;
+
+ /* We successfully set the stock object flag.
+ KernelData should never be NULL here!!! */
+ ASSERT(Entry->KernelData);
+
+ Object = Entry->KernelData;
+
+ PrevThread = Object->Tid;
+ if (Object->cExclusiveLock == 0 || PrevThread == Thread)
+ {
+ /* dereference the process' object counter */
+ if (PrevProcId != GDI_GLOBAL_PROCESS)
+ {
+ PEPROCESS OldProcess;
+ PW32PROCESS W32Process;
+ NTSTATUS Status;
+
+ /* FIXME */
+ Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
+ if (NT_SUCCESS(Status))
+ {
+ W32Process = (PW32PROCESS)OldProcess->Win32Process;
+ if (W32Process != NULL)
+ {
+ _InterlockedDecrement(&W32Process->GDIObjects);
+ }
+ ObDereferenceObject(OldProcess);
+ }
+ }
+
+ /* remove the process id lock and make it global */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS);
+
+ hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK);
+ *phObj = hObj;
+
+ /* we're done, successfully converted the object */
+ return TRUE;
+ }
+ else
+ {
+#ifdef GDI_DEBUG
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
+ }
+#endif
+ /* WTF?! The object is already locked by a different thread!
+ Release the lock, wait a bit and try again!
+ FIXME - we should give up after some time unless we want to wait forever! */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+
+ DelayExecution();
+ goto LockHandle;
+ }
+ }
+ else
+ {
+ DPRINT1("Attempted to convert object 0x%x that is deleted! Should never get here!!!\n", hObj);
+ DPRINT1("OldType = 0x%x, Entry->Type = 0x%x, NewType = 0x%x, Entry->KernelData = 0x%x\n", OldType, Entry->Type, NewType, Entry->KernelData);
}
- }
-
- /* remove the process id lock and make it global */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, GDI_GLOBAL_PROCESS);
-
- hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK);
- *phObj = hObj;
-
- /* we're done, successfully converted the object */
- return TRUE;
}
- else
+ else if (PrevProcId == LockedProcessId)
{
#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
- }
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Waiting on 0x%x\n", Attempts, hObj);
+ }
#endif
- /* WTF?! The object is already locked by a different thread!
- Release the lock, wait a bit and try again!
- FIXME - we should give up after some time unless we want to wait forever! */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
-
- DelayExecution();
- goto LockHandle;
+ /* the object is currently locked, wait some time and try again.
+ FIXME - we shouldn't loop forever! Give up after some time! */
+ DelayExecution();
+ /* try again */
+ goto LockHandle;
+ }
+ else
+ {
+ DPRINT1("Attempted to convert invalid handle: 0x%x\n", hObj);
}
- }
- else
- {
- DPRINT1("Attempted to convert object 0x%x that is deleted! Should never get here!!!\n", hObj);
- DPRINT1("OldType = 0x%x, Entry->Type = 0x%x, NewType = 0x%x, Entry->KernelData = 0x%x\n", OldType, Entry->Type, NewType, Entry->KernelData);
- }
- }
- else if(PrevProcId == LockedProcessId)
- {
-#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Waiting on 0x%x\n", Attempts, hObj);
- }
-#endif
- /* the object is currently locked, wait some time and try again.
- FIXME - we shouldn't loop forever! Give up after some time! */
- DelayExecution();
- /* try again */
- goto LockHandle;
- }
- else
- {
- DPRINT1("Attempted to convert invalid handle: 0x%x\n", hObj);
}
- }
- return FALSE;
+ return FALSE;
}
void INTERNAL_CALL
GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner)
{
- PGDI_TABLE_ENTRY Entry;
- HANDLE ProcessId, LockedProcessId, PrevProcId;
- PW32THREAD Thread;
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE ProcessId, LockedProcessId, PrevProcId;
+ PW32THREAD Thread;
#ifdef GDI_DEBUG
- ULONG Attempts = 0;
+ ULONG Attempts = 0;
#endif
- DPRINT("GDIOBJ_SetOwnership: hObj: 0x%x, NewProcess: 0x%x\n", ObjectHandle, (NewOwner ? PsGetProcessId(NewOwner) : 0));
-
- Thread = PsGetCurrentThreadWin32Thread();
-
- if(!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle))
- {
- ProcessId = PsGetCurrentProcessId();
- LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
+ DPRINT("GDIOBJ_SetOwnership: hObj: 0x%x, NewProcess: 0x%x\n", ObjectHandle, (NewOwner ? PsGetProcessId(NewOwner) : 0));
- Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, ObjectHandle);
+ Thread = PsGetCurrentThreadWin32Thread();
-LockHandle:
- /* lock the object, we must not convert stock objects, so don't check!!! */
- PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, ProcessId, LockedProcessId);
- if(PrevProcId == ProcessId)
+ if (!GDI_HANDLE_IS_STOCKOBJ(ObjectHandle))
{
- PW32THREAD PrevThread;
+ ProcessId = PsGetCurrentProcessId();
+ LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
- if((Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && Entry->KernelData != NULL)
- {
- POBJ Object = Entry->KernelData;
+ Entry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, ObjectHandle);
- PrevThread = Object->Tid;
- if(Object->cExclusiveLock == 0 || PrevThread == Thread)
+LockHandle:
+ /* lock the object, we must not convert stock objects, so don't check!!! */
+ PrevProcId = _InterlockedCompareExchangePointer((PVOID*)&Entry->ProcessId, ProcessId, LockedProcessId);
+ if (PrevProcId == ProcessId)
{
- PEPROCESS OldProcess;
- PW32PROCESS W32Process;
- NTSTATUS Status;
-
- /* dereference the process' object counter */
- /* FIXME */
- if((ULONG_PTR)PrevProcId & ~0x1)
- {
- Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
- if(NT_SUCCESS(Status))
+ PW32THREAD PrevThread;
+
+ if ((Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && Entry->KernelData != NULL)
{
- W32Process = (PW32PROCESS)OldProcess->Win32Process;
- if(W32Process != NULL)
- {
- _InterlockedDecrement(&W32Process->GDIObjects);
- }
- ObDereferenceObject(OldProcess);
+ POBJ Object = Entry->KernelData;
+
+ PrevThread = Object->Tid;
+ if (Object->cExclusiveLock == 0 || PrevThread == Thread)
+ {
+ PEPROCESS OldProcess;
+ PW32PROCESS W32Process;
+ NTSTATUS Status;
+
+ /* dereference the process' object counter */
+ /* FIXME */
+ if ((ULONG_PTR)PrevProcId & ~0x1)
+ {
+ Status = PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)PrevProcId & ~0x1), &OldProcess);
+ if (NT_SUCCESS(Status))
+ {
+ W32Process = (PW32PROCESS)OldProcess->Win32Process;
+ if (W32Process != NULL)
+ {
+ _InterlockedDecrement(&W32Process->GDIObjects);
+ }
+ ObDereferenceObject(OldProcess);
+ }
+ }
+
+ if (NewOwner != NULL)
+ {
+ ProcessId = PsGetProcessId(NewOwner);
+
+ /* Increase the new process' object counter */
+ W32Process = (PW32PROCESS)NewOwner->Win32Process;
+ if (W32Process != NULL)
+ {
+ _InterlockedIncrement(&W32Process->GDIObjects);
+ }
+ }
+ else
+ ProcessId = 0;
+
+ /* remove the process id lock and change it to the new process id */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, ProcessId);
+
+ /* we're done! */
+ return;
+ }
+ else
+ {
+#ifdef GDI_DEBUG
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
+ }
+#endif
+ /* WTF?! The object is already locked by a different thread!
+ Release the lock, wait a bit and try again! DO reset the pid lock
+ so we make sure we don't access invalid memory in case the object is
+ being deleted in the meantime (because we don't have aquired a reference
+ at this point).
+ FIXME - we should give up after some time unless we want to wait forever! */
+ (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
+
+ DelayExecution();
+ goto LockHandle;
+ }
}
- }
-
- if(NewOwner != NULL)
- {
- ProcessId = PsGetProcessId(NewOwner);
-
- /* Increase the new process' object counter */
- W32Process = (PW32PROCESS)NewOwner->Win32Process;
- if(W32Process != NULL)
+ else
{
- _InterlockedIncrement(&W32Process->GDIObjects);
+ DPRINT1("Attempted to change ownership of an object 0x%x currently being destroyed!!!\n", ObjectHandle);
+ DPRINT1("Entry->Type = 0x%lx, Entry->KernelData = 0x%p\n", Entry->Type, Entry->KernelData);
}
- }
- else
- ProcessId = 0;
-
- /* remove the process id lock and change it to the new process id */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, ProcessId);
-
- /* we're done! */
- return;
}
- else
+ else if (PrevProcId == LockedProcessId)
{
#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
- }
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Waiting on 0x%x\n", Attempts, ObjectHandle);
+ }
#endif
- /* WTF?! The object is already locked by a different thread!
- Release the lock, wait a bit and try again! DO reset the pid lock
- so we make sure we don't access invalid memory in case the object is
- being deleted in the meantime (because we don't have aquired a reference
- at this point).
- FIXME - we should give up after some time unless we want to wait forever! */
- (void)_InterlockedExchangePointer((PVOID*)&Entry->ProcessId, PrevProcId);
-
- DelayExecution();
- goto LockHandle;
+ /* the object is currently locked, wait some time and try again.
+ FIXME - we shouldn't loop forever! Give up after some time! */
+ DelayExecution();
+ /* try again */
+ goto LockHandle;
+ }
+ else if (((ULONG_PTR)PrevProcId & ~0x1) == 0)
+ {
+ /* allow changing ownership of global objects */
+ ProcessId = NULL;
+ LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
+ goto LockHandle;
+ }
+ else if ((HANDLE)((ULONG_PTR)PrevProcId & ~0x1) != PsGetCurrentProcessId())
+ {
+ DPRINT1("Attempted to change ownership of object 0x%x (pid: 0x%x) from pid 0x%x!!!\n", ObjectHandle, (ULONG_PTR)PrevProcId & ~0x1, PsGetCurrentProcessId());
+ }
+ else
+ {
+ DPRINT1("Attempted to change owner of invalid handle: 0x%x\n", ObjectHandle);
}
- }
- else
- {
- DPRINT1("Attempted to change ownership of an object 0x%x currently being destroyed!!!\n", ObjectHandle);
- DPRINT1("Entry->Type = 0x%lx, Entry->KernelData = 0x%p\n", Entry->Type, Entry->KernelData);
- }
- }
- else if(PrevProcId == LockedProcessId)
- {
-#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Waiting on 0x%x\n", Attempts, ObjectHandle);
- }
-#endif
- /* the object is currently locked, wait some time and try again.
- FIXME - we shouldn't loop forever! Give up after some time! */
- DelayExecution();
- /* try again */
- goto LockHandle;
- }
- else if(((ULONG_PTR)PrevProcId & ~0x1) == 0)
- {
- /* allow changing ownership of global objects */
- ProcessId = NULL;
- LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
- goto LockHandle;
- }
- else if((HANDLE)((ULONG_PTR)PrevProcId & ~0x1) != PsGetCurrentProcessId())
- {
- DPRINT1("Attempted to change ownership of object 0x%x (pid: 0x%x) from pid 0x%x!!!\n", ObjectHandle, (ULONG_PTR)PrevProcId & ~0x1, PsGetCurrentProcessId());
- }
- else
- {
- DPRINT1("Attempted to change owner of invalid handle: 0x%x\n", ObjectHandle);
}
- }
}
void INTERNAL_CALL
GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo)
{
- PGDI_TABLE_ENTRY FromEntry;
- PW32THREAD Thread;
- HANDLE FromProcessId, FromLockedProcessId, FromPrevProcId;
+ PGDI_TABLE_ENTRY FromEntry;
+ PW32THREAD Thread;
+ HANDLE FromProcessId, FromLockedProcessId, FromPrevProcId;
#ifdef GDI_DEBUG
- ULONG Attempts = 0;
+ ULONG Attempts = 0;
#endif
- DPRINT("GDIOBJ_CopyOwnership: from: 0x%x, to: 0x%x\n", CopyFrom, CopyTo);
-
- Thread = PsGetCurrentThreadWin32Thread();
-
- if(!GDI_HANDLE_IS_STOCKOBJ(CopyFrom) && !GDI_HANDLE_IS_STOCKOBJ(CopyTo))
- {
- FromEntry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, CopyFrom);
+ DPRINT("GDIOBJ_CopyOwnership: from: 0x%x, to: 0x%x\n", CopyFrom, CopyTo);
- FromProcessId = (HANDLE)((ULONG_PTR)FromEntry->ProcessId & ~0x1);
- FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);
+ Thread = PsGetCurrentThreadWin32Thread();
-LockHandleFrom:
- /* lock the object, we must not convert stock objects, so don't check!!! */
- FromPrevProcId = _InterlockedCompareExchangePointer((PVOID*)&FromEntry->ProcessId, FromProcessId, FromLockedProcessId);
- if(FromPrevProcId == FromProcessId)
+ if (!GDI_HANDLE_IS_STOCKOBJ(CopyFrom) && !GDI_HANDLE_IS_STOCKOBJ(CopyTo))
{
- PW32THREAD PrevThread;
- POBJ Object;
+ FromEntry = GDI_HANDLE_GET_ENTRY(GdiHandleTable, CopyFrom);
- if((FromEntry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && FromEntry->KernelData != NULL)
- {
- Object = FromEntry->KernelData;
+ FromProcessId = (HANDLE)((ULONG_PTR)FromEntry->ProcessId & ~0x1);
+ FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);
- /* save the pointer to the calling thread so we know it was this thread
- that locked the object */
- PrevThread = Object->Tid;
- if(Object->cExclusiveLock == 0 || PrevThread == Thread)
+LockHandleFrom:
+ /* lock the object, we must not convert stock objects, so don't check!!! */
+ FromPrevProcId = _InterlockedCompareExchangePointer((PVOID*)&FromEntry->ProcessId, FromProcessId, FromLockedProcessId);
+ if (FromPrevProcId == FromProcessId)
{
- /* now let's change the ownership of the target object */
+ PW32THREAD PrevThread;
+ POBJ Object;
- if(((ULONG_PTR)FromPrevProcId & ~0x1) != 0)
- {
- PEPROCESS ProcessTo;
- /* FIXME */
- if(NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1), &ProcessTo)))
+ if ((FromEntry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && FromEntry->KernelData != NULL)
+ {
+ Object = FromEntry->KernelData;
+
+ /* save the pointer to the calling thread so we know it was this thread
+ that locked the object */
+ PrevThread = Object->Tid;
+ if (Object->cExclusiveLock == 0 || PrevThread == Thread)
+ {
+ /* now let's change the ownership of the target object */
+
+ if (((ULONG_PTR)FromPrevProcId & ~0x1) != 0)
+ {
+ PEPROCESS ProcessTo;
+ /* FIXME */
+ if (NT_SUCCESS(PsLookupProcessByProcessId((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1), &ProcessTo)))
+ {
+ GDIOBJ_SetOwnership(CopyTo, ProcessTo);
+ ObDereferenceObject(ProcessTo);
+ }
+ }
+ else
+ {
+ /* mark the object as global */
+ GDIOBJ_SetOwnership(CopyTo, NULL);
+ }
+
+ (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId);
+ }
+ else
+ {
+#ifdef GDI_DEBUG
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
+ }
+#endif
+ /* WTF?! The object is already locked by a different thread!
+ Release the lock, wait a bit and try again! DO reset the pid lock
+ so we make sure we don't access invalid memory in case the object is
+ being deleted in the meantime (because we don't have aquired a reference
+ at this point).
+ FIXME - we should give up after some time unless we want to wait forever! */
+ (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId);
+
+ DelayExecution();
+ goto LockHandleFrom;
+ }
+ }
+ else
{
- GDIOBJ_SetOwnership(CopyTo, ProcessTo);
- ObDereferenceObject(ProcessTo);
+ DPRINT1("Attempted to copy ownership from an object 0x%x currently being destroyed!!!\n", CopyFrom);
}
- }
- else
- {
- /* mark the object as global */
- GDIOBJ_SetOwnership(CopyTo, NULL);
- }
-
- (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId);
}
- else
+ else if (FromPrevProcId == FromLockedProcessId)
{
#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Locked by 0x%x (we're 0x%x)\n", Attempts, PrevThread, Thread);
- }
+ if (++Attempts > 20)
+ {
+ DPRINT1("[%d]Waiting on 0x%x\n", Attempts, CopyFrom);
+ }
#endif
- /* WTF?! The object is already locked by a different thread!
- Release the lock, wait a bit and try again! DO reset the pid lock
- so we make sure we don't access invalid memory in case the object is
- being deleted in the meantime (because we don't have aquired a reference
- at this point).
- FIXME - we should give up after some time unless we want to wait forever! */
- (void)_InterlockedExchangePointer((PVOID*)&FromEntry->ProcessId, FromPrevProcId);
-
- DelayExecution();
- goto LockHandleFrom;
+ /* the object is currently locked, wait some time and try again.
+ FIXME - we shouldn't loop forever! Give up after some time! */
+ DelayExecution();
+ /* try again */
+ goto LockHandleFrom;
+ }
+ else if ((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1) != PsGetCurrentProcessId())
+ {
+ /* FIXME - should we really allow copying ownership from objects that we don't even own? */
+ DPRINT1("WARNING! Changing copying ownership of object 0x%x (pid: 0x%x) to pid 0x%x!!!\n", CopyFrom, (ULONG_PTR)FromPrevProcId & ~0x1, PsGetCurrentProcessId());
+ FromProcessId = (HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1);
+ FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);
+ goto LockHandleFrom;
+ }
+ else
+ {
+ DPRINT1("Attempted to copy ownership from invalid handle: 0x%x\n", CopyFrom);
}
- }
- else
- {
- DPRINT1("Attempted to copy ownership from an object 0x%x currently being destroyed!!!\n", CopyFrom);
- }
- }
- else if(FromPrevProcId == FromLockedProcessId)
- {
-#ifdef GDI_DEBUG
- if(++Attempts > 20)
- {
- DPRINT1("[%d]Waiting on 0x%x\n", Attempts, CopyFrom);
- }
-#endif
- /* the object is currently locked, wait some time and try again.
- FIXME - we shouldn't loop forever! Give up after some time! */
- DelayExecution();
- /* try again */
- goto LockHandleFrom;
- }
- else if((HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1) != PsGetCurrentProcessId())
- {
- /* FIXME - should we really allow copying ownership from objects that we don't even own? */
- DPRINT1("WARNING! Changing copying ownership of object 0x%x (pid: 0x%x) to pid 0x%x!!!\n", CopyFrom, (ULONG_PTR)FromPrevProcId & ~0x1, PsGetCurrentProcessId());
- FromProcessId = (HANDLE)((ULONG_PTR)FromPrevProcId & ~0x1);
- FromLockedProcessId = (HANDLE)((ULONG_PTR)FromProcessId | 0x1);
- goto LockHandleFrom;
- }
- else
- {
- DPRINT1("Attempted to copy ownership from invalid handle: 0x%x\n", CopyFrom);
}
- }
}
PVOID INTERNAL_CALL
APIENTRY
NtGdiCreateClientObj(
IN ULONG ulType
- )
+)
{
// ATM we use DC object for KernelData. I think it should be at a minimum GDIOBJEMPTYHDR.
// The UserData is set in user mode, so it is always NULL.
//
- INT Index;
- PGDI_TABLE_ENTRY Entry;
- HANDLE handle = GDIOBJ_AllocObj(GDI_OBJECT_TYPE_CLIOBJ);
+ INT Index;
+ PGDI_TABLE_ENTRY Entry;
+ HANDLE handle = GDIOBJ_AllocObj(GDI_OBJECT_TYPE_CLIOBJ);
// Need to change handle type based on ulType.
- Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)handle);
- Entry = &GdiHandleTable->Entries[Index];
+ Index = GDI_HANDLE_GET_INDEX((HGDIOBJ)handle);
+ Entry = &GdiHandleTable->Entries[Index];
// mask out lower half and set the type by ulType.
- Entry->Type &= GDI_HANDLE_UPPER_MASK;
- Entry->Type |= ulType >> GDI_ENTRY_UPPER_SHIFT;
+ Entry->Type &= GDI_HANDLE_UPPER_MASK;
+ Entry->Type |= ulType >> GDI_ENTRY_UPPER_SHIFT;
// mask out handle type than set it by ulType.
- handle = (HANDLE)(((ULONG_PTR)(handle)) & (GDI_HANDLE_REUSE_MASK|GDI_HANDLE_STOCK_MASK|0x0ffff));
- handle = (HANDLE)(((ULONG_PTR)(handle)) | ulType);
- return handle;
+ handle = (HANDLE)(((ULONG_PTR)(handle)) & (GDI_HANDLE_REUSE_MASK|GDI_HANDLE_STOCK_MASK|0x0ffff));
+ handle = (HANDLE)(((ULONG_PTR)(handle)) | ulType);
+ return handle;
}
W32KAPI
APIENTRY
NtGdiDeleteClientObj(
IN HANDLE h
- )
+)
{
- return GDIOBJ_FreeObj(h, GDI_OBJECT_TYPE_CLIOBJ);
+ return GDIOBJ_FreeObj(h, GDI_OBJECT_TYPE_CLIOBJ);
}
/* EOF */