/*
* GDIOBJ.C - GDI object manipulation routines
*
- * $Id: gdiobj.c,v 1.45 2003/10/04 21:09:29 gvg Exp $
+ * $Id: gdiobj.c,v 1.73 2004/10/02 16:48:12 navaraf Exp $
*
*/
+#include <w32k.h>
-#undef WIN32_LEAN_AND_MEAN
-#define WIN32_NO_STATUS
-#include <windows.h>
-#include <ddk/ntddk.h>
-#include <include/dce.h>
-#include <include/object.h>
-#include <win32k/gdiobj.h>
-#include <win32k/brush.h>
-#include <win32k/pen.h>
-#include <win32k/text.h>
-#include <win32k/dc.h>
-#include <win32k/bitmaps.h>
-#include <win32k/region.h>
-#include <win32k/cursoricon.h>
-#include <include/palette.h>
-#define NDEBUG
-#include <win32k/debug1.h>
+/* count all gdi objects */
+#define GDI_COUNT_OBJECTS 1
/*! Size of the GDI handle table
* http://www.windevnet.com/documents/s=7290/wdj9902b/9902b.htm
#define GDI_TYPE_TO_MAGIC(t) ((WORD) ((t) >> 16))
#define GDI_MAGIC_TO_TYPE(m) ((DWORD)(m) << 16)
+/* FIXME Ownership of GDI objects by processes not properly implemented yet */
+#if 0
#define GDI_VALID_OBJECT(h, obj, t, f) \
(NULL != (obj) \
&& (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
&& (((obj)->hProcessId == PsGetCurrentProcessId()) \
|| (GDI_GLOBAL_PROCESS == (obj)->hProcessId) \
|| ((f) & GDIOBJFLAG_IGNOREPID)))
+#else
+#define GDI_VALID_OBJECT(h, obj, t, f) \
+ (NULL != (obj) \
+ && (GDI_MAGIC_TO_TYPE((obj)->Magic) == (t) || GDI_OBJECT_TYPE_DONTCARE == (t)) \
+ && (GDI_HANDLE_GET_TYPE((h)) == GDI_MAGIC_TO_TYPE((obj)->Magic)))
+#endif
typedef struct _GDI_HANDLE_TABLE
{
- WORD wTableSize;
+ WORD wTableSize;
+ WORD AllocationHint;
+ #if GDI_COUNT_OBJECTS
+ ULONG HandlesCount;
+ #endif
+ PPAGED_LOOKASIDE_LIST LookasideLists;
PGDIOBJHDR Handles[1];
} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
+typedef struct
+{
+ ULONG Type;
+ ULONG Size;
+} GDI_OBJ_SIZE;
+
+const
+GDI_OBJ_SIZE ObjSizes[] =
+{
+ /* Testing shows that regions are the most used GDIObj type,
+ so put that one first for performance */
+ {GDI_OBJECT_TYPE_REGION, sizeof(ROSRGNDATA)},
+ {GDI_OBJECT_TYPE_BITMAP, sizeof(BITMAPOBJ)},
+ {GDI_OBJECT_TYPE_DC, sizeof(DC)},
+ {GDI_OBJECT_TYPE_PALETTE, sizeof(PALGDI)},
+ {GDI_OBJECT_TYPE_BRUSH, sizeof(GDIBRUSHOBJ)},
+ {GDI_OBJECT_TYPE_PEN, sizeof(GDIBRUSHOBJ)},
+ {GDI_OBJECT_TYPE_FONT, sizeof(TEXTOBJ)},
+ {GDI_OBJECT_TYPE_DCE, sizeof(DCE)},
+/*
+ {GDI_OBJECT_TYPE_DIRECTDRAW, sizeof(DD_DIRECTDRAW)},
+ {GDI_OBJECT_TYPE_DD_SURFACE, sizeof(DD_SURFACE)},
+*/
+ {GDI_OBJECT_TYPE_EXTPEN, 0},
+ {GDI_OBJECT_TYPE_METADC, 0},
+ {GDI_OBJECT_TYPE_METAFILE, 0},
+ {GDI_OBJECT_TYPE_ENHMETAFILE, 0},
+ {GDI_OBJECT_TYPE_ENHMETADC, 0},
+ {GDI_OBJECT_TYPE_MEMDC, 0},
+ {GDI_OBJECT_TYPE_EMF, 0}
+};
+
+#define OBJTYPE_COUNT (sizeof(ObjSizes) / sizeof(ObjSizes[0]))
+
/* GDI stock objects */
static LOGBRUSH WhiteBrush =
{ PS_NULL, { 0, 0 }, 0 };
static LOGFONTW OEMFixedFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
- 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"Bitstream Vera Sans Mono" };
static LOGFONTW AnsiFixedFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
- 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"Bitstream Vera Sans Mono" };
/*static LOGFONTW AnsiVarFont =
- *{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ *{ 10, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
* 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" }; */
static LOGFONTW SystemFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
- 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"System" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"Bitstream Vera Sans" };
static LOGFONTW DeviceDefaultFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
- 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"Bitstream Vera Sans" };
static LOGFONTW SystemFixedFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
- 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"Bitstream Vera Sans Mono" };
/* FIXME: Is this correct? */
static LOGFONTW DefaultGuiFont =
-{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
- 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
+{ 11, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
+ 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"Bitstream Vera Sans" };
#define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1)
-static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS];
+static HGDIOBJ StockObjects[NB_STOCK_OBJECTS];
static PGDI_HANDLE_TABLE HandleTable = 0;
static FAST_MUTEX HandleTableMutex;
static FAST_MUTEX RefCountHandling;
+static LARGE_INTEGER ShortDelay;
/*!
* Allocate GDI object table.
* \param Size - number of entries in the object table.
+ * Notes:: Must be called at IRQL < DISPATCH_LEVEL.
*/
static PGDI_HANDLE_TABLE FASTCALL
GDIOBJ_iAllocHandleTable (WORD Size)
{
PGDI_HANDLE_TABLE handleTable;
+ ULONG MemSize;
+ UINT ObjType;
+
+ MemSize = sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size;
- ExAcquireFastMutexUnsafe (&HandleTableMutex);
- handleTable = ExAllocatePool(PagedPool,
- sizeof(GDI_HANDLE_TABLE) +
- sizeof(PGDIOBJ) * Size);
+ ExAcquireFastMutex(&HandleTableMutex);
+ handleTable = ExAllocatePoolWithTag(PagedPool, MemSize, TAG_GDIHNDTBLE);
ASSERT( handleTable );
- memset (handleTable,
- 0,
- sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size);
+ memset (handleTable, 0, MemSize);
+#if GDI_COUNT_OBJECTS
+ handleTable->HandlesCount = 0;
+#endif
handleTable->wTableSize = Size;
- ExReleaseFastMutexUnsafe (&HandleTableMutex);
+ handleTable->AllocationHint = 1;
+ handleTable->LookasideLists = ExAllocatePoolWithTag(PagedPool,
+ OBJTYPE_COUNT * sizeof(PAGED_LOOKASIDE_LIST),
+ TAG_GDIHNDTBLE);
+ if (NULL == handleTable->LookasideLists)
+ {
+ ExFreePool(handleTable);
+ ExReleaseFastMutex(&HandleTableMutex);
+ return NULL;
+ }
+ for (ObjType = 0; ObjType < OBJTYPE_COUNT; ObjType++)
+ {
+ ExInitializePagedLookasideList(handleTable->LookasideLists + ObjType, NULL, NULL, 0,
+ ObjSizes[ObjType].Size + sizeof(GDIOBJHDR), TAG_GDIOBJ, 0);
+ }
+ ExReleaseFastMutex(&HandleTableMutex);
return handleTable;
}
static WORD FASTCALL
GDIOBJ_iGetNextOpenHandleIndex (void)
{
- WORD tableIndex;
+ WORD tableIndex;
+
+ for (tableIndex = HandleTable->AllocationHint;
+ tableIndex < HandleTable->wTableSize;
+ tableIndex++)
+ {
+ if (HandleTable->Handles[tableIndex] == NULL)
+ {
+ HandleTable->AllocationHint = tableIndex + 1;
+ return tableIndex;
+ }
+ }
+
+ for (tableIndex = 1;
+ tableIndex < HandleTable->AllocationHint;
+ tableIndex++)
+ {
+ if (HandleTable->Handles[tableIndex] == NULL)
+ {
+ HandleTable->AllocationHint = tableIndex + 1;
+ return tableIndex;
+ }
+ }
+
+ return 0;
+}
- ExAcquireFastMutexUnsafe (&HandleTableMutex);
- for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
+static PPAGED_LOOKASIDE_LIST FASTCALL
+FindLookasideList(DWORD ObjectType)
+{
+ int Index;
+
+ for (Index = 0; Index < OBJTYPE_COUNT; Index++)
{
- if (NULL == HandleTable->Handles[tableIndex])
- {
- HandleTable->Handles[tableIndex] = (PGDIOBJHDR) -1;
- break;
- }
+ if (ObjSizes[Index].Type == ObjectType)
+ {
+ return HandleTable->LookasideLists + Index;
+ }
}
- ExReleaseFastMutexUnsafe (&HandleTableMutex);
- return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
+ DPRINT1("Can't find lookaside list for object type 0x%08x\n", ObjectType);
+
+ return NULL;
}
/*!
HGDIOBJ FASTCALL
GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
{
+ PW32PROCESS W32Process;
PGDIOBJHDR newObject;
WORD Index;
-
+ PPAGED_LOOKASIDE_LIST LookasideList;
+
+ ExAcquireFastMutex(&HandleTableMutex);
Index = GDIOBJ_iGetNextOpenHandleIndex ();
if (0 == Index)
{
+ ExReleaseFastMutex(&HandleTableMutex);
DPRINT1("Out of GDI handles\n");
return NULL;
}
- DPRINT("GDIOBJ_AllocObj: handle: %d, size: %d, type: 0x%08x\n", Index, Size, ObjectType);
- newObject = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
- if (newObject == NULL)
- {
- DPRINT1("GDIOBJ_AllocObj: failed\n");
- return NULL;
- }
+ LookasideList = FindLookasideList(ObjectType);
+ if (NULL == LookasideList)
+ {
+ ExReleaseFastMutex(&HandleTableMutex);
+ return NULL;
+ }
+ newObject = ExAllocateFromPagedLookasideList(LookasideList);
+ if (NULL == newObject)
+ {
+ ExReleaseFastMutex(&HandleTableMutex);
+ DPRINT1("Unable to allocate GDI object from lookaside list\n");
+ return NULL;
+ }
RtlZeroMemory (newObject, Size + sizeof(GDIOBJHDR));
newObject->wTableIndex = Index;
newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
newObject->lockfile = NULL;
newObject->lockline = 0;
+#ifdef GDIOBJ_USE_FASTMUTEX
+ ExInitializeFastMutex(&newObject->Lock);
+ newObject->RecursiveLockCount = 0;
+#else
+ newObject->LockTid = 0;
+ newObject->LockCount = 0;
+#endif
HandleTable->Handles[Index] = newObject;
+#if GDI_COUNT_OBJECTS
+ HandleTable->HandlesCount++;
+#endif
+ ExReleaseFastMutex(&HandleTableMutex);
+
+ W32Process = PsGetCurrentProcess()->Win32Process;
+ if(W32Process)
+ {
+ W32Process->GDIObjects++;
+ }
return GDI_HANDLE_CREATE(Index, ObjectType);
}
BOOL STDCALL
GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType, DWORD Flag)
{
+ PW32PROCESS W32Process;
PGDIOBJHDR objectHeader;
PGDIOBJ Obj;
+ PPAGED_LOOKASIDE_LIST LookasideList;
BOOL bRet = TRUE;
objectHeader = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
Obj = (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
bRet = (*(objectHeader->CleanupProc))(Obj);
}
-
- ExFreePool(objectHeader);
+ LookasideList = FindLookasideList(GDI_MAGIC_TO_TYPE(objectHeader->Magic));
+ if (NULL != LookasideList)
+ {
+ ExFreeToPagedLookasideList(LookasideList, objectHeader);
+ }
+ ExAcquireFastMutexUnsafe (&HandleTableMutex);
HandleTable->Handles[GDI_HANDLE_GET_INDEX(hObj)] = NULL;
+#if GDI_COUNT_OBJECTS
+ HandleTable->HandlesCount--;
+#endif
+ ExReleaseFastMutexUnsafe (&HandleTableMutex);
+
+ W32Process = PsGetCurrentProcess()->Win32Process;
+ if(W32Process)
+ {
+ W32Process->GDIObjects--;
+ }
return bRet;
}
return TRUE;
}
-/*!
- * Marks the object as global. (Creator process ID is set to GDI_GLOBAL_PROCESS). Global objects may be
- * accessed by any process.
- * \param ObjectHandle - handle of the object to make global.
- *
- * \note Only stock objects should be marked global.
-*/
-VOID FASTCALL
-GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
-{
- PGDIOBJHDR ObjHdr;
-
- DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
- ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
- if (NULL == ObjHdr)
- {
- return;
- }
-
- ObjHdr->hProcessId = GDI_GLOBAL_PROCESS;
-}
-
-/*!
- * Removes the global mark from the object. Global objects may be
- * accessed by any process.
- * \param ObjectHandle - handle of the object to make local.
- *
- * \note Only stock objects should be marked global.
-*/
-VOID FASTCALL
-GDIOBJ_UnmarkObjectGlobal(HGDIOBJ ObjectHandle)
-{
- PGDIOBJHDR ObjHdr;
-
- DPRINT("GDIOBJ_MarkObjectGlobal handle 0x%08x\n", ObjectHandle);
- ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
- if (NULL == ObjHdr || GDI_GLOBAL_PROCESS != ObjHdr->hProcessId)
- {
- return;
- }
-
- ObjHdr->hProcessId = PsGetCurrentProcessId();
-}
-
/*!
* Get the type of the object.
* \param ObjectHandle - handle of the object.
ExInitializeFastMutex (&HandleTableMutex);
ExInitializeFastMutex (&RefCountHandling);
+ ShortDelay.QuadPart = -100;
+
HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
DPRINT("HandleTable: %x\n", HandleTable );
/* Create GDI Stock Objects from the logical structures we've defined */
- StockObjects[WHITE_BRUSH] = NtGdiCreateBrushIndirect(&WhiteBrush);
- StockObjects[LTGRAY_BRUSH] = NtGdiCreateBrushIndirect(&LtGrayBrush);
- StockObjects[GRAY_BRUSH] = NtGdiCreateBrushIndirect(&GrayBrush);
- StockObjects[DKGRAY_BRUSH] = NtGdiCreateBrushIndirect(&DkGrayBrush);
- StockObjects[BLACK_BRUSH] = NtGdiCreateBrushIndirect(&BlackBrush);
- StockObjects[NULL_BRUSH] = NtGdiCreateBrushIndirect(&NullBrush);
+ StockObjects[WHITE_BRUSH] = IntGdiCreateBrushIndirect(&WhiteBrush);
+ StockObjects[LTGRAY_BRUSH] = IntGdiCreateBrushIndirect(&LtGrayBrush);
+ StockObjects[GRAY_BRUSH] = IntGdiCreateBrushIndirect(&GrayBrush);
+ StockObjects[DKGRAY_BRUSH] = IntGdiCreateBrushIndirect(&DkGrayBrush);
+ StockObjects[BLACK_BRUSH] = IntGdiCreateBrushIndirect(&BlackBrush);
+ StockObjects[NULL_BRUSH] = IntGdiCreateBrushIndirect(&NullBrush);
- StockObjects[WHITE_PEN] = NtGdiCreatePenIndirect(&WhitePen);
- StockObjects[BLACK_PEN] = NtGdiCreatePenIndirect(&BlackPen);
- StockObjects[NULL_PEN] = NtGdiCreatePenIndirect(&NullPen);
+ StockObjects[WHITE_PEN] = IntGdiCreatePenIndirect(&WhitePen);
+ StockObjects[BLACK_PEN] = IntGdiCreatePenIndirect(&BlackPen);
+ StockObjects[NULL_PEN] = IntGdiCreatePenIndirect(&NullPen);
(void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
{
if (NULL != StockObjects[Object])
{
- GDIOBJ_MarkObjectGlobal(StockObjects[Object]);
+ GDIOBJ_SetOwnership(StockObjects[Object], NULL);
/* GDI_HANDLE_SET_STOCKOBJ(StockObjects[Object]);*/
}
}
{
DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
- return GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_DEFAULT);
+ return NULL != hObject
+ ? GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_DEFAULT) : FALSE;
}
/*!
PGDIOBJ FASTCALL
GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
{
- PGDIOBJ rc;
PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+#ifndef GDIOBJ_USE_FASTMUTEX
+ DWORD CurrentTid = (DWORD)PsGetCurrentThreadId();
+#endif
+ DPRINT("(%s:%i) GDIOBJ_LockObjDbg(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
{
int reason = 0;
DPRINT1("\tcalled from: %s:%i\n", file, line );
return NULL;
}
- if (NULL != ObjHdr->lockfile)
+
+#ifdef GDIOBJ_USE_FASTMUTEX
+ if (ObjHdr->Lock.Owner == KeGetCurrentThread())
{
- DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj );
- DPRINT1("\tcalled from: %s:%i\n", file, line );
- DPRINT1("\tpreviously locked from: %s:%i\n", ObjHdr->lockfile, ObjHdr->lockline );
+ ObjHdr->RecursiveLockCount++;
}
- DPRINT("(%s:%i) GDIOBJ_LockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
- rc = GDIOBJ_LockObj(hObj, ObjectType);
- if (rc && NULL == ObjHdr->lockfile)
+ else
+ {
+#ifdef NDEBUG
+ ExAcquireFastMutex(&ObjHdr->Lock);
+#else /* NDEBUG */
+ if (! ExTryToAcquireFastMutex(&ObjHdr->Lock))
+ {
+ DPRINT1("Caution! GDIOBJ_LockObj trying to lock object 0x%x second time\n", hObj);
+ DPRINT1(" called from: %s:%i (thread %x)\n", file, line, KeGetCurrentThread());
+ if (NULL != ObjHdr->lockfile)
+ {
+ DPRINT1(" previously locked from: %s:%i (thread %x)\n", ObjHdr->lockfile, ObjHdr->lockline, ObjHdr->Lock.Owner);
+ }
+ ExAcquireFastMutex(&ObjHdr->Lock);
+ DPRINT1(" Disregard previous message about object 0x%x, it's ok\n", hObj);
+ }
+#endif /* NDEBUG */
+ ObjHdr->RecursiveLockCount++;
+ }
+#else
+ if (ObjHdr->LockTid == CurrentTid)
+ {
+ InterlockedIncrement(&ObjHdr->LockCount);
+ }
+ else
+ {
+ for (;;)
+ {
+ if (InterlockedCompareExchange(&ObjHdr->LockTid, CurrentTid, 0) == CurrentTid)
+ {
+ InterlockedIncrement(&ObjHdr->LockCount);
+ break;
+ }
+ /* FIXME: KeDelayExecutionThread(KernelMode, FALSE, &ShortDelay); */
+ }
+ }
+#endif
+
+ ExAcquireFastMutex(&RefCountHandling);
+ ObjHdr->dwCount++;
+ ExReleaseFastMutex(&RefCountHandling);
+
+ if (NULL == ObjHdr->lockfile)
{
ObjHdr->lockfile = file;
ObjHdr->lockline = line;
}
- return rc;
+ return (PGDIOBJ)((PCHAR)ObjHdr + sizeof(GDIOBJHDR));
}
#endif//GDIOBJ_LockObj
GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
{
PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+#ifndef GDIOBJ_USE_FASTMUTEX
+ DWORD CurrentTid = (DWORD)PsGetCurrentThreadId();
+#endif
DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
return NULL;
}
- if(0 < ObjHdr->dwCount)
+#ifdef GDIOBJ_USE_FASTMUTEX
+ if (ObjHdr->Lock.Owner == KeGetCurrentThread())
+ {
+ ObjHdr->RecursiveLockCount++;
+ }
+ else
+ {
+ ExAcquireFastMutex(&ObjHdr->Lock);
+ ObjHdr->RecursiveLockCount++;
+ }
+#else
+ if (ObjHdr->LockTid == CurrentTid)
{
- DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj);
- DPRINT1("\t called from: %x\n", __builtin_return_address(0));
+ InterlockedIncrement(&ObjHdr->LockCount);
}
+ else
+ {
+ for (;;)
+ {
+ if (InterlockedCompareExchange(&ObjHdr->LockTid, CurrentTid, 0) == CurrentTid)
+ {
+ InterlockedIncrement(&ObjHdr->LockCount);
+ break;
+ }
+ /* FIXME: KeDelayExecutionThread(KernelMode, FALSE, &ShortDelay); */
+ }
+ }
+#endif
ExAcquireFastMutex(&RefCountHandling);
ObjHdr->dwCount++;
return FALSE;
}
+#ifdef GDIOBJ_USE_FASTMUTEX
+ if (--ObjHdr->RecursiveLockCount == 0)
+ ExReleaseFastMutex(&ObjHdr->Lock);
+#else
+ if (InterlockedDecrement(&ObjHdr->LockCount) == 0)
+ {
+ InterlockedExchange(&ObjHdr->LockTid, 0);
+ }
+#endif
+
ExAcquireFastMutex(&RefCountHandling);
if (0 == (ObjHdr->dwCount & ~0x80000000))
{
return TRUE;
}
+BOOL FASTCALL
+GDIOBJ_OwnedByCurrentProcess(HGDIOBJ ObjectHandle)
+{
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+
+ DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle);
+ ASSERT(GDI_VALID_OBJECT(ObjectHandle, ObjHdr, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_IGNOREPID));
+
+ return ObjHdr->hProcessId == PsGetCurrentProcessId();
+}
+
+void FASTCALL
+GDIOBJ_SetOwnership(HGDIOBJ ObjectHandle, PEPROCESS NewOwner)
+{
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+ PEPROCESS OldProcess;
+ PW32PROCESS W32Process;
+ NTSTATUS Status;
+
+ DPRINT("GDIOBJ_OwnedByCurrentProcess: ObjectHandle: 0x%08x\n", ObjectHandle);
+ ASSERT(GDI_VALID_OBJECT(ObjectHandle, ObjHdr, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_IGNOREPID));
+
+ if ((NULL == NewOwner && GDI_GLOBAL_PROCESS != ObjHdr->hProcessId)
+ || (NULL != NewOwner && ObjHdr->hProcessId != (HANDLE) NewOwner->UniqueProcessId))
+ {
+ Status = PsLookupProcessByProcessId((PVOID)ObjHdr->hProcessId, &OldProcess);
+ if (NT_SUCCESS(Status))
+ {
+ W32Process = OldProcess->Win32Process;
+ if (W32Process)
+ {
+ W32Process->GDIObjects--;
+ }
+ ObDereferenceObject(OldProcess);
+ }
+ }
+
+ if (NULL == NewOwner)
+ {
+ ObjHdr->hProcessId = GDI_GLOBAL_PROCESS;
+ }
+ else if (ObjHdr->hProcessId != (HANDLE) NewOwner->UniqueProcessId)
+ {
+ ObjHdr->hProcessId = (HANDLE) NewOwner->UniqueProcessId;
+ W32Process = NewOwner->Win32Process;
+ if (W32Process)
+ {
+ W32Process->GDIObjects++;
+ }
+ }
+}
+
+void FASTCALL
+GDIOBJ_CopyOwnership(HGDIOBJ CopyFrom, HGDIOBJ CopyTo)
+{
+ PGDIOBJHDR ObjHdrFrom = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(CopyFrom));
+ PGDIOBJHDR ObjHdrTo = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(CopyTo));
+ NTSTATUS Status;
+ PEPROCESS ProcessFrom;
+ PEPROCESS CurrentProcess;
+
+ ASSERT(NULL != ObjHdrFrom && NULL != ObjHdrTo);
+ if (NULL != ObjHdrFrom && NULL != ObjHdrTo
+ && ObjHdrTo->hProcessId != ObjHdrFrom->hProcessId)
+ {
+ if (ObjHdrFrom->hProcessId == GDI_GLOBAL_PROCESS)
+ {
+ GDIOBJ_SetOwnership(CopyTo, NULL);
+ }
+ else
+ {
+ /* Warning: ugly hack ahead
+ *
+ * During process cleanup, we can't call PsLookupProcessByProcessId
+ * for the current process, 'cause that function will try to
+ * reference the process, and since the process is closing down
+ * that will result in a bugcheck.
+ * So, instead, we call PsGetCurrentProcess, which doesn't reference
+ * the process. If the current process is indeed the one we're
+ * looking for, we use it, otherwise we can (safely) call
+ * PsLookupProcessByProcessId
+ */
+ CurrentProcess = PsGetCurrentProcess();
+ if (ObjHdrFrom->hProcessId == (HANDLE) CurrentProcess->UniqueProcessId)
+ {
+ GDIOBJ_SetOwnership(CopyTo, CurrentProcess);
+ }
+ else
+ {
+ Status = PsLookupProcessByProcessId((PVOID) ObjHdrFrom->hProcessId, &ProcessFrom);
+ if (NT_SUCCESS(Status))
+ {
+ GDIOBJ_SetOwnership(CopyTo, ProcessFrom);
+ ObDereferenceObject(ProcessFrom);
+ }
+ }
+ }
+ }
+}
+
/* EOF */