/*
* GDIOBJ.C - GDI object manipulation routines
*
- * $Id: gdiobj.c,v 1.37 2003/08/19 11:48:50 weiden Exp $
+ * $Id: gdiobj.c,v 1.46 2003/10/15 03:09:23 vizzini Exp $
*
*/
#define NDEBUG
#include <win32k/debug1.h>
-#define GDI_HANDLE2INDEX(h) (((WORD)(size_t)(h)) & 0xffff)
-#define GDI_INDEX2HANDLE(i) ((HANDLE) (((size_t)(i))&0xffff) )
+/*! Size of the GDI handle table
+ * http://www.windevnet.com/documents/s=7290/wdj9902b/9902b.htm
+ * gdi handle table can hold 0x4000 handles
+*/
+#define GDI_HANDLE_COUNT 0x4000
+
+#define GDI_GLOBAL_PROCESS ((HANDLE) 0xffffffff)
+
+#define GDI_HANDLE_INDEX_MASK (GDI_HANDLE_COUNT - 1)
+#define GDI_HANDLE_TYPE_MASK 0x007f0000
+#define GDI_HANDLE_STOCK_MASK 0x00800000
+
+#define GDI_HANDLE_CREATE(i, t) ((HANDLE)(((i) & GDI_HANDLE_INDEX_MASK) | ((t) & GDI_HANDLE_TYPE_MASK)))
+#define GDI_HANDLE_GET_INDEX(h) (((DWORD)(h)) & GDI_HANDLE_INDEX_MASK)
+#define GDI_HANDLE_GET_TYPE(h) (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK)
+#define GDI_HANDLE_IS_TYPE(h, t) ((t) == (((DWORD)(h)) & GDI_HANDLE_TYPE_MASK))
+#define GDI_HANDLE_IS_STOCKOBJ(h) (0 != (((DWORD)(h)) & GDI_HANDLE_STOCK_MASK))
+#define GDI_HANDLE_SET_STOCKOBJ(h) ((h) = (HANDLE)(((DWORD)(h)) | GDI_HANDLE_STOCK_MASK))
+
+#define GDI_TYPE_TO_MAGIC(t) ((WORD) ((t) >> 16))
+#define GDI_MAGIC_TO_TYPE(m) ((DWORD)(m) << 16)
+
+#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)) \
+ && (((obj)->hProcessId == PsGetCurrentProcessId()) \
+ || (GDI_GLOBAL_PROCESS == (obj)->hProcessId) \
+ || ((f) & GDIOBJFLAG_IGNOREPID)))
-// GDI stock objects
+typedef struct _GDI_HANDLE_TABLE
+{
+ WORD wTableSize;
+ PGDIOBJHDR Handles[1];
+} GDI_HANDLE_TABLE, *PGDI_HANDLE_TABLE;
+
+/* GDI stock objects */
static LOGBRUSH WhiteBrush =
{ BS_SOLID, RGB(255,255,255), 0 };
{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, OEM_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
-/* Filler to make the location counter dword aligned again. This is necessary
- since (a) LOGFONT is packed, (b) gcc places initialised variables in the code
- segment, and (c) Solaris assembler is stupid. */
-//static UINT align_OEMFixedFont = 1;
-
static LOGFONTW AnsiFixedFont =
{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
-//static UINT align_AnsiFixedFont = 1;
-
-//static LOGFONTW AnsiVarFont =
-//{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
-// 0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"MS Sans Serif" };
-
-//static UINT align_AnsiVarFont = 1;
+/*static LOGFONTW AnsiVarFont =
+ *{ 14, 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" };
-//static UINT align_SystemFont = 1;
-
static LOGFONTW DeviceDefaultFont =
{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, L"" };
-//static UINT align_DeviceDefaultFont = 1;
-
static LOGFONTW SystemFixedFont =
{ 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
0, 0, DEFAULT_QUALITY, FIXED_PITCH | FF_MODERN, L"" };
-//static UINT align_SystemFixedFont = 1;
-
/* 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" };
-//static UINT align_DefaultGuiFont = 1;
-
-static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS]; // we dont assign these statically as WINE does because we might redesign
- // the way handles work, so it's more dynamic now
-
-
-HBITMAP hPseudoStockBitmap; /*! 1x1 bitmap for memory DCs */
+#define NB_STOCK_OBJECTS (DEFAULT_GUI_FONT + 1)
+static HGDIOBJ *StockObjects[NB_STOCK_OBJECTS];
static PGDI_HANDLE_TABLE HandleTable = 0;
static FAST_MUTEX HandleTableMutex;
static FAST_MUTEX RefCountHandling;
-/*! Size of the GDI handle table
- * per http://www.wd-mag.com/articles/1999/9902/9902b/9902b.htm?topic=articles
- * gdi handle table can hold 0x4000 handles
-*/
-#define GDI_HANDLE_NUMBER 0x4000
-
/*!
* Allocate GDI object table.
* \param Size - number of entries in the object table.
GDIOBJ_iAllocHandleTable (WORD Size)
{
PGDI_HANDLE_TABLE handleTable;
+ KIRQL OldIrql;
+ BOOLEAN IrqlRaised = FALSE;
+
+ if(KeGetCurrentIrql() < APC_LEVEL)
+ {
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+ IrqlRaised = TRUE;
+ }
ExAcquireFastMutexUnsafe (&HandleTableMutex);
handleTable = ExAllocatePool(PagedPool,
- sizeof (GDI_HANDLE_TABLE) +
- sizeof (GDI_HANDLE_ENTRY) * Size);
+ sizeof(GDI_HANDLE_TABLE) +
+ sizeof(PGDIOBJ) * Size);
ASSERT( handleTable );
memset (handleTable,
0,
- sizeof (GDI_HANDLE_TABLE) + sizeof (GDI_HANDLE_ENTRY) * Size);
+ sizeof(GDI_HANDLE_TABLE) + sizeof(PGDIOBJ) * Size);
handleTable->wTableSize = Size;
ExReleaseFastMutexUnsafe (&HandleTableMutex);
- return handleTable;
+ if(IrqlRaised)
+ KeLowerIrql(OldIrql);
+
+ return handleTable;
}
/*!
* Returns the entry into the handle table by index.
*/
-static PGDI_HANDLE_ENTRY FASTCALL
-GDIOBJ_iGetHandleEntryForIndex (WORD TableIndex)
+static PGDIOBJHDR FASTCALL
+GDIOBJ_iGetObjectForIndex(WORD TableIndex)
{
- //DPRINT("GDIOBJ_iGetHandleEntryForIndex: TableIndex: %d,\n handle: %x, ptr: %x\n", TableIndex, HandleTable->Handles [TableIndex], &(HandleTable->Handles [TableIndex]) );
- //DPRINT("GIG: HandleTable: %x, Handles: %x, \n TableIndex: %x, pt: %x\n", HandleTable, HandleTable->Handles, TableIndex, ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex));
- //DPRINT("GIG: Hndl: %x, mag: %x\n", ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex), ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex)->wMagic);
- return ((PGDI_HANDLE_ENTRY)HandleTable->Handles+TableIndex);
+ if (0 == TableIndex || HandleTable->wTableSize < TableIndex)
+ {
+ DPRINT1("Invalid TableIndex %u\n", (unsigned) TableIndex);
+ return NULL;
+ }
+
+ return HandleTable->Handles[TableIndex];
}
/*!
static WORD FASTCALL
GDIOBJ_iGetNextOpenHandleIndex (void)
{
- WORD tableIndex;
+ WORD tableIndex;
+ BOOLEAN IrqlRaised = FALSE;
+ KIRQL OldIrql;
+
+ if(KeGetCurrentIrql() < APC_LEVEL)
+ {
+ KeRaiseIrql(APC_LEVEL, &OldIrql);
+ IrqlRaised = TRUE;
+ }
ExAcquireFastMutexUnsafe (&HandleTableMutex);
for (tableIndex = 1; tableIndex < HandleTable->wTableSize; tableIndex++)
- {
- if (HandleTable->Handles [tableIndex].wMagic == 0)
{
- HandleTable->Handles [tableIndex].wMagic = GO_MAGIC_DONTCARE;
- break;
+ if (NULL == HandleTable->Handles[tableIndex])
+ {
+ HandleTable->Handles[tableIndex] = (PGDIOBJHDR) -1;
+ break;
+ }
}
- }
ExReleaseFastMutexUnsafe (&HandleTableMutex);
- return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
+ if(IrqlRaised)
+ KeLowerIrql(OldIrql);
+
+ return (tableIndex < HandleTable->wTableSize) ? tableIndex : 0;
}
/*!
*
* \param Size - size of the GDI object. This shouldn't to include the size of GDIOBJHDR.
* The actual amount of allocated memory is sizeof(GDIOBJHDR)+Size
- * \param Magic - object magic (see GDI Magic)
+ * \param ObjectType - type of object \ref GDI object types
+ * \param CleanupProcPtr - Routine to be called on destruction of object
*
* \return Handle of the allocated object.
*
* \note Use GDIOBJ_Lock() to obtain pointer to the new object.
*/
HGDIOBJ FASTCALL
-GDIOBJ_AllocObj(WORD Size, WORD Magic)
+GDIOBJ_AllocObj(WORD Size, DWORD ObjectType, GDICLEANUPPROC CleanupProc)
{
PGDIOBJHDR newObject;
- PGDI_HANDLE_ENTRY handleEntry;
+ WORD Index;
+
+ Index = GDIOBJ_iGetNextOpenHandleIndex ();
+ if (0 == Index)
+ {
+ DPRINT1("Out of GDI handles\n");
+ return NULL;
+ }
- DPRINT("GDIOBJ_AllocObj: size: %d, magic: %x\n", Size, Magic);
- newObject = ExAllocatePool (PagedPool, Size + sizeof (GDIOBJHDR));
+ DPRINT("GDIOBJ_AllocObj: handle: %d, size: %d, type: 0x%08x\n", Index, Size, ObjectType);
+ newObject = ExAllocatePool(PagedPool, Size + sizeof (GDIOBJHDR));
if (newObject == NULL)
{
- DPRINT("GDIOBJ_AllocObj: failed\n");
- return NULL;
+ DPRINT1("GDIOBJ_AllocObj: failed\n");
+ return NULL;
}
- RtlZeroMemory (newObject, Size + sizeof (GDIOBJHDR));
+ RtlZeroMemory (newObject, Size + sizeof(GDIOBJHDR));
+
+ newObject->wTableIndex = Index;
- newObject->wTableIndex = GDIOBJ_iGetNextOpenHandleIndex ();
newObject->dwCount = 0;
- handleEntry = GDIOBJ_iGetHandleEntryForIndex (newObject->wTableIndex);
- handleEntry->wMagic = Magic;
- handleEntry->hProcessId = PsGetCurrentProcessId ();
- handleEntry->pObject = newObject;
- handleEntry->lockfile = NULL;
- handleEntry->lockline = 0;
- DPRINT("GDIOBJ_AllocObj: object handle %d\n", newObject->wTableIndex );
- return GDI_INDEX2HANDLE(newObject->wTableIndex);
+ newObject->hProcessId = PsGetCurrentProcessId ();
+ newObject->CleanupProc = CleanupProc;
+ newObject->Magic = GDI_TYPE_TO_MAGIC(ObjectType);
+ newObject->lockfile = NULL;
+ newObject->lockline = 0;
+ HandleTable->Handles[Index] = newObject;
+
+ return GDI_HANDLE_CREATE(Index, ObjectType);
}
/*!
* Free memory allocated for the GDI object. For each object type this function calls the
* appropriate cleanup routine.
*
- * \param hObj - handle of the object to be deleted.
- * \param Magic - object magic or GO_MAGIC_DONTCARE.
- * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
+ * \param hObj - handle of the object to be deleted.
+ * \param ObjectType - one of the \ref GDI object types
+ * or GDI_OBJECT_TYPE_DONTCARE.
+ * \param Flag - if set to GDIOBJFLAG_IGNOREPID then the routine doesn't check if the process that
* tries to delete the object is the same one that created it.
*
* \return Returns TRUE if succesful.
* \note This function deferres object deletion if it is still in use.
*/
BOOL STDCALL
-GDIOBJ_FreeObj(HGDIOBJ hObj, WORD Magic, DWORD Flag)
+GDIOBJ_FreeObj(HGDIOBJ hObj, DWORD ObjectType, DWORD Flag)
{
- PGDIOBJHDR objectHeader;
- PGDI_HANDLE_ENTRY handleEntry;
- PGDIOBJ Obj;
- BOOL bRet = TRUE;
+ PGDIOBJHDR objectHeader;
+ PGDIOBJ Obj;
+ BOOL bRet = TRUE;
- handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
- DPRINT("GDIOBJ_FreeObj: hObj: %d, magic: %x, handleEntry: %x\n", (WORD)hObj & 0xffff, Magic, handleEntry );
+ objectHeader = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+ DPRINT("GDIOBJ_FreeObj: hObj: 0x%08x, object: %x\n", hObj, objectHeader);
- if (handleEntry == 0 || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- || ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag & GDIOBJFLAG_IGNOREPID))){
+ if (! GDI_VALID_OBJECT(hObj, objectHeader, ObjectType, Flag)
+ || GDI_GLOBAL_PROCESS == objectHeader->hProcessId)
- DPRINT("Can't Delete hObj: %d, magic: %x, pid:%d\n currpid:%d, flag:%d, hmm:%d\n",(WORD)hObj & 0xffff, handleEntry->wMagic, handleEntry->hProcessId, PsGetCurrentProcessId(), (Flag&GDIOBJFLAG_IGNOREPID), ((handleEntry->hProcessId != PsGetCurrentProcessId()) && !(Flag&GDIOBJFLAG_IGNOREPID)) );
- return FALSE;
- }
+ {
+ DPRINT1("Can't delete hObj:0x%08x, type:0x%08x, flag:%d\n", hObj, ObjectType, Flag);
+ return FALSE;
+ }
- objectHeader = handleEntry->pObject;
- ASSERT(objectHeader);
- DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
- if( !(Flag & GDIOBJFLAG_IGNORELOCK) ){
- // check that the reference count is zero. if not then set flag
- // and delete object when releaseobj is called
- ExAcquireFastMutex(&RefCountHandling);
- if( ( objectHeader->dwCount & ~0x80000000 ) > 0 ){
- DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
- objectHeader->dwCount |= 0x80000000;
- ExReleaseFastMutex(&RefCountHandling);
- return TRUE;
- }
- ExReleaseFastMutex(&RefCountHandling);
+ DPRINT("FreeObj: locks: %x\n", objectHeader->dwCount );
+ if (!(Flag & GDIOBJFLAG_IGNORELOCK))
+ {
+ /* check that the reference count is zero. if not then set flag
+ * and delete object when releaseobj is called */
+ ExAcquireFastMutex(&RefCountHandling);
+ if ((objectHeader->dwCount & ~0x80000000) > 0 )
+ {
+ DPRINT("GDIOBJ_FreeObj: delayed object deletion: count %d\n", objectHeader->dwCount);
+ objectHeader->dwCount |= 0x80000000;
+ ExReleaseFastMutex(&RefCountHandling);
+ return TRUE;
}
+ ExReleaseFastMutex(&RefCountHandling);
+ }
- //allow object to delete internal data
- Obj = (PGDIOBJ)((PCHAR)handleEntry->pObject + sizeof(GDIOBJHDR));
- switch( handleEntry->wMagic ){
- case GO_REGION_MAGIC:
- bRet = RGNDATA_InternalDelete( (PROSRGNDATA) Obj );
- break;
- case GO_BITMAP_MAGIC:
- bRet = Bitmap_InternalDelete( (PBITMAPOBJ) Obj );
- break;
- case GO_DC_MAGIC:
- bRet = DC_InternalDeleteDC( (PDC) Obj );
- break;
- case GO_PEN_MAGIC:
- case GO_PALETTE_MAGIC:
- case GO_DISABLED_DC_MAGIC:
- case GO_META_DC_MAGIC:
- case GO_METAFILE_MAGIC:
- case GO_METAFILE_DC_MAGIC:
- case GO_ENHMETAFILE_MAGIC:
- case GO_ENHMETAFILE_DC_MAGIC:
-
- case GO_BRUSH_MAGIC:
- case GO_FONT_MAGIC:
- break;
- case GO_DCE_MAGIC:
- bRet = DCE_InternalDelete( (PDCE) Obj );
- break;
- case GO_ICONCURSOR_MAGIC:
- bRet = IconCursor_InternalDelete( (PICONCURSOROBJ) Obj );
- break;
- }
- ExFreePool (handleEntry->pObject);
- memset ( handleEntry, 0, sizeof(GDI_HANDLE_ENTRY) );
+ /* allow object to delete internal data */
+ if (NULL != objectHeader->CleanupProc)
+ {
+ Obj = (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
+ bRet = (*(objectHeader->CleanupProc))(Obj);
+ }
+
+ ExFreePool(objectHeader);
+ HandleTable->Handles[GDI_HANDLE_GET_INDEX(hObj)] = NULL;
- return TRUE;
+ return bRet;
}
/*!
* Lock multiple objects. Use this function when you need to lock multiple objects and some of them may be
* duplicates. You should use this function to avoid trying to lock the same object twice!
*
- * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
+ * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
* \param nObj number of objects to lock
* \return for each entry in pList this function sets pObj field to point to the object.
*
* \note this function uses an O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
*/
BOOL FASTCALL
-GDIOBJ_LockMultipleObj( PGDIMULTILOCK pList, INT nObj )
+GDIOBJ_LockMultipleObj(PGDIMULTILOCK pList, INT nObj)
{
INT i, j;
ASSERT( pList );
- // FIXME - check for "invalid" handles
- //go through the list checking for duplicate objects
- for( i = 0; i < nObj; i++ )
+ /* FIXME - check for "invalid" handles */
+ /* go through the list checking for duplicate objects */
+ for (i = 0; i < nObj; i++)
{
- (pList+i)->pObj = NULL;
- for( j = 0; j < i; j++ )
+ pList[i].pObj = NULL;
+ for (j = 0; j < i; j++)
{
- if( ((pList+i)->hObj == (pList+j)->hObj)
- && ((pList+i)->Magic == (pList+j)->Magic)
- )
+ if (pList[i].hObj == pList[j].hObj)
{
- //already locked, so just copy the pointer to the object
- (pList+i)->pObj = (pList+j)->pObj;
+ /* already locked, so just copy the pointer to the object */
+ pList[i].pObj = pList[j].pObj;
break;
}
}
- if( (pList+i)->pObj == NULL )
- {
- //object hasn't been locked, so lock it.
- if ( (pList+i)->hObj )
- (pList+i)->pObj = GDIOBJ_LockObj( (pList+i)->hObj, (pList+i)->Magic );
- }
+
+ if (NULL == pList[i].pObj)
+ {
+ /* object hasn't been locked, so lock it. */
+ if (NULL != pList[i].hObj)
+ {
+ pList[i].pObj = GDIOBJ_LockObj(pList[i].hObj, pList[i].ObjectType);
+ }
+ }
}
+
return TRUE;
}
* Unlock multiple objects. Use this function when you need to unlock multiple objects and some of them may be
* duplicates.
*
- * \param pList pointer to the list that contains handles to the objects. You should set hObj and Magic fields.
+ * \param pList pointer to the list that contains handles to the objects. You should set hObj and ObjectType fields.
* \param nObj number of objects to lock
*
* \note this function uses O(n^2) algoritm because we shouldn't need to call it with more than 3 or 4 objects.
*/
BOOL FASTCALL
-GDIOBJ_UnlockMultipleObj( PGDIMULTILOCK pList, INT nObj )
+GDIOBJ_UnlockMultipleObj(PGDIMULTILOCK pList, INT nObj)
{
INT i, j;
- ASSERT( pList );
- //go through the list checking for duplicate objects
- for( i = 0; i < nObj; i++ )
+ ASSERT(pList);
+
+ /* go through the list checking for duplicate objects */
+ for (i = 0; i < nObj; i++)
{
- if( (pList+i)->pObj != NULL )
+ if (NULL != pList[i].pObj)
{
- for( j = i+1; j < nObj; j++ )
+ for (j = i + 1; j < nObj; j++)
{
- if( ((pList+i)->pObj == (pList+j)->pObj) )
+ if ((pList[i].pObj == pList[j].pObj))
{
- //set the pointer to zero for all duplicates
- (pList+j)->pObj = NULL;
+ /* set the pointer to zero for all duplicates */
+ pList[j].pObj = NULL;
}
}
- GDIOBJ_UnlockObj( (pList+i)->hObj, (pList+i)->Magic );
- (pList+i)->pObj = NULL;
+ GDIOBJ_UnlockObj(pList[i].hObj, pList[i].ObjectType);
+ pList[i].pObj = NULL;
}
}
+
return TRUE;
}
/*!
- * Marks the object as global. (Creator process ID is set to 0xFFFFFFFF). Global objects may be
+ * 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.
*
VOID FASTCALL
GDIOBJ_MarkObjectGlobal(HGDIOBJ ObjectHandle)
{
- PGDI_HANDLE_ENTRY handleEntry;
+ PGDIOBJHDR ObjHdr;
- if (ObjectHandle == NULL)
- return;
+ 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;
+}
- handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle) );
- if (handleEntry == 0)
- return;
+/*!
+ * 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;
- handleEntry->hProcessId = (HANDLE)0xFFFFFFFF;
+ 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 (magic value) of the object.
+ * Get the type of the object.
* \param ObjectHandle - handle of the object.
- * \return GDI Magic value.
+ * \return One of the \ref GDI object types
*/
-WORD FASTCALL
-GDIOBJ_GetHandleMagic (HGDIOBJ ObjectHandle)
+DWORD FASTCALL
+GDIOBJ_GetObjectType(HGDIOBJ ObjectHandle)
{
- PGDI_HANDLE_ENTRY handleEntry;
+ PGDIOBJHDR ObjHdr;
- if (ObjectHandle == NULL)
- return 0;
-
- handleEntry = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(ObjectHandle) );
- if (handleEntry == 0 ||
- (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF &&
- handleEntry->hProcessId != PsGetCurrentProcessId ()))
- return 0;
+ ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(ObjectHandle));
+ if (NULL == ObjHdr
+ || ! GDI_VALID_OBJECT(ObjectHandle, ObjHdr, GDI_MAGIC_TO_TYPE(ObjHdr->Magic), 0))
+ {
+ DPRINT1("Invalid ObjectHandle 0x%08x\n", ObjectHandle);
+ return 0;
+ }
+ DPRINT("GDIOBJ_GetObjectType for handle 0x%08x returns 0x%08x\n", ObjectHandle,
+ GDI_MAGIC_TO_TYPE(ObjHdr->Magic));
- return handleEntry->wMagic;
+ return GDI_MAGIC_TO_TYPE(ObjHdr->Magic);
}
/*!
VOID FASTCALL
InitGdiObjectHandleTable (VOID)
{
- DPRINT ("InitGdiObjectHandleTable\n");
+ DPRINT("InitGdiObjectHandleTable\n");
ExInitializeFastMutex (&HandleTableMutex);
ExInitializeFastMutex (&RefCountHandling);
- HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_NUMBER);
+ HandleTable = GDIOBJ_iAllocHandleTable (GDI_HANDLE_COUNT);
DPRINT("HandleTable: %x\n", HandleTable );
InitEngHandleTable();
VOID FASTCALL
CreateStockObjects(void)
{
- // Create GDI Stock Objects from the logical structures we've defined
+ unsigned Object;
+
+ DPRINT("Beginning creation of stock objects\n");
+
+ /* Create GDI Stock Objects from the logical structures we've defined */
StockObjects[WHITE_BRUSH] = NtGdiCreateBrushIndirect(&WhiteBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_BRUSH]);
StockObjects[LTGRAY_BRUSH] = NtGdiCreateBrushIndirect(&LtGrayBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[LTGRAY_BRUSH]);
StockObjects[GRAY_BRUSH] = NtGdiCreateBrushIndirect(&GrayBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[GRAY_BRUSH]);
StockObjects[DKGRAY_BRUSH] = NtGdiCreateBrushIndirect(&DkGrayBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[DKGRAY_BRUSH]);
StockObjects[BLACK_BRUSH] = NtGdiCreateBrushIndirect(&BlackBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_BRUSH]);
StockObjects[NULL_BRUSH] = NtGdiCreateBrushIndirect(&NullBrush);
- GDIOBJ_MarkObjectGlobal(StockObjects[NULL_BRUSH]);
StockObjects[WHITE_PEN] = NtGdiCreatePenIndirect(&WhitePen);
- GDIOBJ_MarkObjectGlobal(StockObjects[WHITE_PEN]);
StockObjects[BLACK_PEN] = NtGdiCreatePenIndirect(&BlackPen);
- GDIOBJ_MarkObjectGlobal(StockObjects[BLACK_PEN]);
StockObjects[NULL_PEN] = NtGdiCreatePenIndirect(&NullPen);
- GDIOBJ_MarkObjectGlobal(StockObjects[NULL_PEN]);
(void) TextIntCreateFontIndirect(&OEMFixedFont, (HFONT*)&StockObjects[OEM_FIXED_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[OEM_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&AnsiFixedFont, (HFONT*)&StockObjects[ANSI_FIXED_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[ANSI_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&SystemFont, (HFONT*)&StockObjects[SYSTEM_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FONT]);
(void) TextIntCreateFontIndirect(&DeviceDefaultFont, (HFONT*)&StockObjects[DEVICE_DEFAULT_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[DEVICE_DEFAULT_FONT]);
(void) TextIntCreateFontIndirect(&SystemFixedFont, (HFONT*)&StockObjects[SYSTEM_FIXED_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[SYSTEM_FIXED_FONT]);
(void) TextIntCreateFontIndirect(&DefaultGuiFont, (HFONT*)&StockObjects[DEFAULT_GUI_FONT]);
- GDIOBJ_MarkObjectGlobal(StockObjects[DEFAULT_GUI_FONT]);
StockObjects[DEFAULT_PALETTE] = (HGDIOBJ*)PALETTE_Init();
+
+ for (Object = 0; Object < NB_STOCK_OBJECTS; Object++)
+ {
+ if (NULL != StockObjects[Object])
+ {
+ GDIOBJ_MarkObjectGlobal(StockObjects[Object]);
+/* GDI_HANDLE_SET_STOCKOBJ(StockObjects[Object]);*/
+ }
+ }
+
+ DPRINT("Completed creation of stock objects\n");
}
/*!
* \return Handle to the object.
*/
HGDIOBJ STDCALL
-NtGdiGetStockObject(INT Object)
+NtGdiGetStockObject(INT Object)
{
- // check when adding new objects
- if( (Object < 0) || (Object >= NB_STOCK_OBJECTS) )
- return NULL;
- return StockObjects[Object];
+ DPRINT("NtGdiGetStockObject index %d\n", Object);
+
+ return ((Object < 0) || (NB_STOCK_OBJECTS <= Object)) ? NULL : StockObjects[Object];
}
/*!
* Delete GDI object
* \param hObject object handle
- * \return if the function fails the returned value is NULL.
+ * \return if the function fails the returned value is FALSE.
*/
BOOL STDCALL
NtGdiDeleteObject(HGDIOBJ hObject)
{
- return GDIOBJ_FreeObj( hObject, GO_MAGIC_DONTCARE, GDIOBJFLAG_DEFAULT );
+ DPRINT("NtGdiDeleteObject handle 0x%08x\n", hObject);
+
+ return GDIOBJ_FreeObj(hObject, GDI_OBJECT_TYPE_DONTCARE, GDIOBJFLAG_DEFAULT);
}
/*!
CleanupForProcess (struct _EPROCESS *Process, INT Pid)
{
DWORD i;
- PGDI_HANDLE_ENTRY handleEntry;
PGDIOBJHDR objectHeader;
PEPROCESS CurrentProcess;
- //NTSTATUS Status;
+ DPRINT("Starting CleanupForProcess prochandle %x Pid %d\n", Process, Pid);
CurrentProcess = PsGetCurrentProcess();
if (CurrentProcess != Process)
{
KeAttachProcess(Process);
}
- for(i = 1; i < GDI_HANDLE_NUMBER; i++)
+ for(i = 1; i < HandleTable->wTableSize; i++)
{
- handleEntry = GDIOBJ_iGetHandleEntryForIndex((WORD) i & 0xffff);
- if (NULL != handleEntry && 0 != handleEntry->wMagic &&
- (INT)handleEntry->hProcessId == Pid)
+ objectHeader = GDIOBJ_iGetObjectForIndex(i);
+ if (NULL != objectHeader &&
+ (INT) objectHeader->hProcessId == Pid)
{
- objectHeader = (PGDIOBJHDR) handleEntry->pObject;
- DPRINT("\nNtGdiCleanup: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
- GDIOBJ_FreeObj( GDI_INDEX2HANDLE(i), GO_MAGIC_DONTCARE, GDIOBJFLAG_IGNOREPID|GDIOBJFLAG_IGNORELOCK );
+ DPRINT("CleanupForProcess: %d, process: %d, locks: %d, magic: 0x%x", i, objectHeader->hProcessId, objectHeader->dwCount, objectHeader->Magic);
+ GDIOBJ_FreeObj(GDI_HANDLE_CREATE(i, GDI_MAGIC_TO_TYPE(objectHeader->Magic)),
+ GDI_MAGIC_TO_TYPE(objectHeader->Magic),
+ GDIOBJFLAG_IGNOREPID | GDIOBJFLAG_IGNORELOCK);
}
}
KeDetachProcess();
}
- return TRUE;
-}
-
-/*!
- * Internal function. Dumps all the objects for the given process.
- * \param If process == 0 dump all the objects.
- *
-*/
-VOID STDCALL
-NtGdiDumpGdiObjects( INT Process )
-{
- DWORD i;
- PGDI_HANDLE_ENTRY handleEntry;
- PGDIOBJHDR objectHeader;
-
- for( i=1; i < GDI_HANDLE_NUMBER; i++ ){
- handleEntry = GDIOBJ_iGetHandleEntryForIndex ((WORD) i & 0xffff);
- if( handleEntry && handleEntry->wMagic != 0 ){
- objectHeader = (PGDIOBJHDR) handleEntry->pObject;
- DPRINT("\nHandle: %d, magic: %x \n process: %d, locks: %d", i, handleEntry->wMagic, handleEntry->hProcessId, objectHeader->dwCount);
- }
- }
+ DPRINT("Completed cleanup for process %d\n", Pid);
+ return TRUE;
}
#define GDIOBJ_TRACKLOCKS
#ifdef GDIOBJ_LockObj
#undef GDIOBJ_LockObj
PGDIOBJ FASTCALL
-GDIOBJ_LockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
+GDIOBJ_LockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
{
PGDIOBJ rc;
- PGDI_HANDLE_ENTRY handleEntry
- = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
- if ( handleEntry == 0
- || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
- && handleEntry->hProcessId != PsGetCurrentProcessId ()
- )
- )
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+ if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
{
int reason = 0;
- if ( handleEntry == 0 )
- reason = 1;
- else if ( handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- reason = 2;
- else if ( handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
- && handleEntry->hProcessId != PsGetCurrentProcessId () )
- reason = 3;
-
- DPRINT1("GDIOBJ_LockObj failed for %d, magic: %d, reqMagic %d reason %d\n",
- (WORD)((size_t)hObj&0xffff), handleEntry->wMagic, Magic, reason );
+ if (NULL == ObjHdr)
+ {
+ reason = 1;
+ }
+ else if (GDI_MAGIC_TO_TYPE(ObjHdr->Magic) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
+ {
+ reason = 2;
+ }
+ else if (ObjHdr->hProcessId != GDI_GLOBAL_PROCESS
+ && ObjHdr->hProcessId != PsGetCurrentProcessId())
+ {
+ reason = 3;
+ }
+ else if (GDI_HANDLE_GET_TYPE(hObj) != ObjectType && ObjectType != GDI_OBJECT_TYPE_DONTCARE)
+ {
+ reason = 4;
+ }
+ DPRINT1("GDIOBJ_LockObj failed for 0x%08x, reqtype 0x%08x reason %d\n",
+ hObj, ObjectType, reason );
DPRINT1("\tcalled from: %s:%i\n", file, line );
- return NULL;
+ return NULL;
}
- if ( handleEntry->lockfile )
+ if (NULL != ObjHdr->lockfile)
{
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", handleEntry->lockfile, handleEntry->lockline );
+ DPRINT1("\tpreviously locked from: %s:%i\n", ObjHdr->lockfile, ObjHdr->lockline );
}
- //DbgPrint("(%s:%i) GDIOBJ_LockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
- rc = GDIOBJ_LockObj(hObj,Magic);
- if ( rc && !handleEntry->lockfile )
+ DPRINT("(%s:%i) GDIOBJ_LockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
+ rc = GDIOBJ_LockObj(hObj, ObjectType);
+ if (rc && NULL == ObjHdr->lockfile)
{
- handleEntry->lockfile = file;
- handleEntry->lockline = line;
+ ObjHdr->lockfile = file;
+ ObjHdr->lockline = line;
}
+
return rc;
}
#endif//GDIOBJ_LockObj
#ifdef GDIOBJ_UnlockObj
#undef GDIOBJ_UnlockObj
BOOL FASTCALL
-GDIOBJ_UnlockObjDbg ( const char* file, int line, HGDIOBJ hObj, WORD Magic )
+GDIOBJ_UnlockObjDbg (const char* file, int line, HGDIOBJ hObj, DWORD ObjectType)
{
- PGDI_HANDLE_ENTRY handleEntry
- = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
- if ( handleEntry == 0
- || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
- && handleEntry->hProcessId != PsGetCurrentProcessId ()
- )
- )
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+ if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
{
- DPRINT1("GDIBOJ_UnlockObj failed for %d, magic: %d, reqMagic\n",
- (WORD)((size_t)hObj & 0xffff), handleEntry->wMagic, Magic );
- DPRINT1("\tcalled from: %s:%i\n", file, line );
+ DPRINT1("GDIBOJ_UnlockObj failed for 0x%08x, reqtype 0x%08x\n",
+ hObj, ObjectType);
+ DPRINT1("\tcalled from: %s:%i\n", file, line);
return FALSE;
}
- //DbgPrint("(%s:%i) GDIOBJ_UnlockObj(0x%x,0x%x)\n", file, line, hObj, Magic );
- handleEntry->lockfile = NULL;
- handleEntry->lockline = 0;
- return GDIOBJ_UnlockObj(hObj,Magic);
+ DPRINT("(%s:%i) GDIOBJ_UnlockObj(0x%08x,0x%08x)\n", file, line, hObj, ObjectType);
+ ObjHdr->lockfile = NULL;
+ ObjHdr->lockline = 0;
+
+ return GDIOBJ_UnlockObj(hObj, ObjectType);
}
#endif//GDIOBJ_LockObj
* Return pointer to the object by handle.
*
* \param hObj Object handle
- * \param Magic one of the magic numbers defined in \ref GDI Magic
- * \return Pointer to the object.
+ * \param ObjectType one of the object types defined in \ref GDI object types
+ * \return Pointer to the object.
*
* \note Process can only get pointer to the objects it created or global objects.
*
* \todo Don't allow to lock the objects twice! Synchronization!
*/
PGDIOBJ FASTCALL
-GDIOBJ_LockObj( HGDIOBJ hObj, WORD Magic )
+GDIOBJ_LockObj(HGDIOBJ hObj, DWORD ObjectType)
{
- PGDI_HANDLE_ENTRY handleEntry
- = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
- PGDIOBJHDR objectHeader;
-
- DPRINT("GDIOBJ_LockObj: hObj: %d, magic: %x, \n handleEntry: %x, mag %x\n", hObj, Magic, handleEntry, handleEntry->wMagic);
- if ( handleEntry == 0
- || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
- && handleEntry->hProcessId != PsGetCurrentProcessId ()
- )
- )
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+ DPRINT("GDIOBJ_LockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
+ if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
{
- DPRINT1("GDIBOJ_LockObj failed for %d, magic: %d, reqMagic\n",
- (WORD)((size_t)hObj & 0xffff), handleEntry->wMagic, Magic);
+ DPRINT1("GDIBOJ_LockObj failed for 0x%08x, type 0x%08x\n",
+ hObj, ObjectType);
return NULL;
}
- objectHeader = (PGDIOBJHDR) handleEntry->pObject;
- ASSERT(objectHeader);
- if( objectHeader->dwCount > 0 )
+ if(0 < ObjHdr->dwCount)
{
- DbgPrint("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj );
- DbgPrint("\t called from: %x\n", __builtin_return_address(0));
+ DPRINT1("Caution! GDIOBJ_LockObj trying to lock object (0x%x) second time\n", hObj);
+ DPRINT1("\t called from: %x\n", __builtin_return_address(0));
}
ExAcquireFastMutex(&RefCountHandling);
- objectHeader->dwCount++;
+ ObjHdr->dwCount++;
ExReleaseFastMutex(&RefCountHandling);
- return (PGDIOBJ)((PCHAR)objectHeader + sizeof(GDIOBJHDR));
+ return (PGDIOBJ)((PCHAR)ObjHdr + sizeof(GDIOBJHDR));
}
/*!
* as soon as you don't need to have access to it's data.
* \param hObj Object handle
- * \param Magic one of the magic numbers defined in \ref GDI Magic
+ * \param ObjectType one of the object types defined in \ref GDI object types
*
* \note This function performs delayed cleanup. If the object is locked when GDI_FreeObj() is called
* then \em this function frees the object when reference count is zero.
*/
#undef GDIOBJ_UnlockObj
BOOL FASTCALL
-GDIOBJ_UnlockObj( HGDIOBJ hObj, WORD Magic )
+GDIOBJ_UnlockObj(HGDIOBJ hObj, DWORD ObjectType)
{
- PGDI_HANDLE_ENTRY handleEntry
- = GDIOBJ_iGetHandleEntryForIndex ( GDI_HANDLE2INDEX(hObj) );
- PGDIOBJHDR objectHeader;
-
- DPRINT("GDIOBJ_UnlockObj: hObj: %d, magic: %x, \n handleEntry: %x\n", hObj, Magic, handleEntry);
- if ( handleEntry == 0
- || (handleEntry->wMagic != Magic && Magic != GO_MAGIC_DONTCARE )
- || (handleEntry->hProcessId != (HANDLE)0xFFFFFFFF
- && handleEntry->hProcessId != PsGetCurrentProcessId ()
- )
- )
- {
+ PGDIOBJHDR ObjHdr = GDIOBJ_iGetObjectForIndex(GDI_HANDLE_GET_INDEX(hObj));
+
+ DPRINT("GDIOBJ_UnlockObj: hObj: 0x%08x, type: 0x%08x, objhdr: %x\n", hObj, ObjectType, ObjHdr);
+ if (! GDI_VALID_OBJECT(hObj, ObjHdr, ObjectType, GDIOBJFLAG_DEFAULT))
+ {
DPRINT1( "GDIOBJ_UnLockObj: failed\n");
return FALSE;
}
- objectHeader = (PGDIOBJHDR) handleEntry->pObject;
- ASSERT(objectHeader);
-
ExAcquireFastMutex(&RefCountHandling);
- if( ( objectHeader->dwCount & ~0x80000000 ) == 0 )
+ if (0 == (ObjHdr->dwCount & ~0x80000000))
{
ExReleaseFastMutex(&RefCountHandling);
- DPRINT( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj );
+ DPRINT1( "GDIOBJ_UnLockObj: unlock object (0x%x) that is not locked\n", hObj );
return FALSE;
}
- objectHeader = (PGDIOBJHDR) handleEntry->pObject;
- ASSERT(objectHeader);
- objectHeader->dwCount--;
+ ObjHdr->dwCount--;
- if( objectHeader->dwCount == 0x80000000 )
+ if (ObjHdr->dwCount == 0x80000000)
{
//delayed object release
- objectHeader->dwCount = 0;
+ ObjHdr->dwCount = 0;
ExReleaseFastMutex(&RefCountHandling);
DPRINT("GDIOBJ_UnlockObj: delayed delete\n");
- return GDIOBJ_FreeObj( hObj, Magic, GDIOBJFLAG_DEFAULT );
+ return GDIOBJ_FreeObj(hObj, ObjectType, GDIOBJFLAG_DEFAULT);
}
ExReleaseFastMutex(&RefCountHandling);
+
return TRUE;
}
+
/* EOF */