Author: tkreuzer Date: Thu Sep 20 20:13:55 2007 New Revision: 29123
URL: http://svn.reactos.org/svn/reactos?rev=29123&view=rev Log: - make gdi object's type field more windows compatible, using only the basetype in the upper 16 bits - On windows deleted objects have a KernelData value != NULL, so don't check for that when validating a handle, instead check if the type field in the upper 16 bits is 0
Modified: trunk/reactos/dll/win32/gdi32/misc/misc.c trunk/reactos/include/reactos/win32k/ntgdihdl.h trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c
Modified: trunk/reactos/dll/win32/gdi32/misc/misc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/gdi32/misc/misc.c... ============================================================================== --- trunk/reactos/dll/win32/gdi32/misc/misc.c (original) +++ trunk/reactos/dll/win32/gdi32/misc/misc.c Thu Sep 20 20:13:55 2007 @@ -94,9 +94,8 @@ BOOL GdiIsHandleValid(HGDIOBJ hGdiObj) { PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj); - if(Entry->KernelData != NULL && - (Entry->Type & GDI_HANDLE_TYPE_MASK) == - (LONG)GDI_HANDLE_GET_TYPE(hGdiObj)) + if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 && + (Entry->Type << GDI_ENTRY_UPPER_SHIFT) == GDI_HANDLE_GET_UPPER(hGdiObj)) { HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1); if(pid == NULL || pid == CurrentProcessId) @@ -110,9 +109,8 @@ BOOL GdiGetHandleUserData(HGDIOBJ hGdiObj, PVOID *UserData) { PGDI_TABLE_ENTRY Entry = GdiHandleTable + GDI_HANDLE_GET_INDEX(hGdiObj); - if(Entry->KernelData != NULL && - (Entry->Type & GDI_HANDLE_TYPE_MASK) == - (LONG)GDI_HANDLE_GET_TYPE(hGdiObj)) + if((Entry->Type & GDI_ENTRY_BASETYPE_MASK) != 0 && + (Entry->Type << GDI_ENTRY_UPPER_SHIFT) == GDI_HANDLE_GET_UPPER(hGdiObj)) { HANDLE pid = (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1); if(pid == NULL || pid == CurrentProcessId)
Modified: trunk/reactos/include/reactos/win32k/ntgdihdl.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/reactos/win32k/ntgd... ============================================================================== --- trunk/reactos/include/reactos/win32k/ntgdihdl.h (original) +++ trunk/reactos/include/reactos/win32k/ntgdihdl.h Thu Sep 20 20:13:55 2007 @@ -33,6 +33,7 @@ #define GDI_ENTRY_STOCK_MASK 0x00000080 #define GDI_ENTRY_REUSE_MASK 0x0000ff00 #define GDI_ENTRY_REUSE_INC 0x00000100 +#define GDI_ENTRY_BASETYPE_MASK 0x001f0000 #define GDI_ENTRY_REUSECNT_SHIFT 8 #define GDI_ENTRY_UPPER_SHIFT 16
Modified: trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/obj... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c (original) +++ trunk/reactos/subsystems/win32/win32k/objects/gdiobj.c Thu Sep 20 20:13:55 2007 @@ -316,10 +316,10 @@ DPRINT1("%s: Attempted to lock object 0x%x, wrong reuse counter (Handle: 0x%x, Entry: 0x%x)\n", Function, hObj, GDI_HANDLE_GET_REUSECNT(hObj), GDI_ENTRY_GET_REUSECNT(Entry->Type)); } - else if (GDI_HANDLE_GET_TYPE(hObj) != GDI_HANDLE_GET_TYPE(Entry->Type)) + else if (GDI_HANDLE_GET_TYPE(hObj) != ((Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK)) { DPRINT1("%s: Attempted to lock object 0x%x, type mismatch (Handle: 0x%x, Entry: 0x%x)\n", - Function, hObj, GDI_HANDLE_GET_TYPE(hObj), GDI_HANDLE_GET_TYPE(Entry->Type)); + Function, hObj, GDI_HANDLE_GET_TYPE(hObj), (Entry->Type << GDI_ENTRY_UPPER_SHIFT) & GDI_HANDLE_TYPE_MASK); } else { @@ -403,10 +403,10 @@
RtlZeroMemory(ObjectBody, GetObjectSize(TypeIndex));
- /* FIXME: On Windows the higher 16 bit of the type field don't always match - the type from the handle, it is probably a storage type - (type = pen, storage = brush) */ - TypeInfo = (ObjectType & GDI_HANDLE_TYPE_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);
FreeEntry = InterlockedPopEntrySList(&HandleTable->FreeEntriesHead); if(FreeEntry != NULL) @@ -705,7 +705,7 @@ Entry++, Index++) { /* ignore the lock bit */ - if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0) + if((HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcId && (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0) { HGDIOBJ ObjectHandle;
@@ -1050,7 +1050,7 @@
Entry = GDI_HANDLE_GET_ENTRY(HandleTable, ObjectHandle); Ret = Entry->KernelData != NULL && - (Entry->Type & ~GDI_HANDLE_REUSE_MASK) != 0 && + (Entry->Type & ~GDI_ENTRY_REUSE_MASK) != 0 && (HANDLE)((ULONG_PTR)Entry->ProcessId & ~0x1) == ProcessId;
return Ret; @@ -1060,7 +1060,7 @@ }
BOOL INTERNAL_CALL -GDIOBJ_ConvertToStockObj(PGDI_HANDLE_TABLE HandleTable, HGDIOBJ *hObj) +GDIOBJ_ConvertToStockObj(PGDI_HANDLE_TABLE HandleTable, HGDIOBJ *phObj) { /* * FIXME !!!!! THIS FUNCTION NEEDS TO BE FIXED - IT IS NOT SAFE WHEN OTHER THREADS @@ -1069,22 +1069,24 @@ PGDI_TABLE_ENTRY Entry; HANDLE ProcessId, LockedProcessId, PrevProcId; PETHREAD Thread; + HGDIOBJ hObj; #ifdef GDI_DEBUG ULONG Attempts = 0; #endif
- ASSERT(hObj); - - DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", *hObj); + ASSERT(phObj); + hObj = *phObj; + + DPRINT("GDIOBJ_ConvertToStockObj: hObj: 0x%08x\n", hObj);
Thread = PsGetCurrentThread();
- if(!GDI_HANDLE_IS_STOCKOBJ(*hObj)) + if(!GDI_HANDLE_IS_STOCKOBJ(hObj)) { ProcessId = PsGetCurrentProcessId(); LockedProcessId = (HANDLE)((ULONG_PTR)ProcessId | 0x1);
- Entry = GDI_HANDLE_GET_ENTRY(HandleTable, *hObj); + Entry = GDI_HANDLE_GET_ENTRY(HandleTable, hObj);
LockHandle: /* lock the object, we must not convert stock objects, so don't check!!! */ @@ -1096,16 +1098,11 @@ /* 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.*/ - /* FIXME: On Windows the higher 16 bit of the type field don't always match - the type from the handle, it is probably a storage type - (type = pen, storage = brush) */ - NewType = GDI_HANDLE_GET_TYPE(*hObj); - NewType |= GDI_HANDLE_GET_UPPER(*hObj) >> GDI_ENTRY_UPPER_SHIFT; - - /* This is the type that the object should have right now, save it */ - OldType = NewType; + OldType = ((ULONG)hObj & GDI_HANDLE_BASETYPE_MASK); + OldType |= GDI_HANDLE_GET_UPPER(hObj) >> GDI_ENTRY_UPPER_SHIFT; + /* As the object should be a stock object, set it's flag, but only in the lower 16 bits */ - NewType |= GDI_ENTRY_STOCK_MASK; + 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); @@ -1146,7 +1143,8 @@ /* remove the process id lock and make it global */ (void)InterlockedExchangePointer(&Entry->ProcessId, GDI_GLOBAL_PROCESS);
- *hObj = (HGDIOBJ)((ULONG)(*hObj) | GDI_HANDLE_STOCK_MASK); + hObj = (HGDIOBJ)((ULONG)(hObj) | GDI_HANDLE_STOCK_MASK); + *phObj = hObj;
/* we're done, successfully converted the object */ return TRUE;