[ros-dev] About GDIOBJHDR header changes

Alex Ionescu ionucu at videotron.ca
Sun Dec 30 16:18:35 CET 2007


There is no DD_BASEOBJECT, the cExclusiveLock really is at +0x08,  
I've verified in the disassembly as well as with WinDBG.


On 30-Dec-07, at 10:00 AM, Magnus Olsen wrote:

> Hi
> I try verify some stuff, the _BASEOBJECT does not match for dxg
> I want it be in this order.
>
>  struct DD_BASEOBJECT
>  {
>     HANDLE hHmgr; // Handle for this object
>     LONG cExclusiveLock; // lock with InterlockedIncrement or not
>     ULONG ulShareCount;
>     PW32THREAD Tid;   // contain which thread it belong to,  
> PsGetCurrentThread()
>     ULONG BaseFlags;
>  } *POBJ;
> ----- Original Message -----
> From: Alex Ionescu
> To: ReactOS Development List
> Sent: Sunday, December 30, 2007 2:52 PM
> Subject: Re: [ros-dev] About GDIOBJHDR header changes
>
> Both Timo and Magnus are half-right, half-wrong, and are confused  
> by no less then three different structures that come into play. The  
> fact that Feng's book is outdated doesn't help much! Greatlord's  
> reversing of the DdHmgLock function was also completely busted,  
> further confusing matters.
>
> So here's my attempt to clear things up.
>
> Let's begin with the GDI Base Object, which is a header at the top  
> of every GDI Object. The structure is called _BASEOBJECT (what you  
> refer to as "GDIOBJHDR") and is defined as follows:
>
> struct _BASEOBJECT
> {
>     HANDLE hHmgr;
>     ULONG ulShareCount;
>     LONG cExclusiveLock;
>     ULONG BaseFlags;
>     PW32THREAD Tid;
> };
>
> The pointer to a _BASEOBJECT is known as a POBJ.
>
> Now, how to get to this object? Well, dxg and win32k.sys now both  
> implement different Hmhr's (Handle Managers).
>
> In Win32K land, the handles come from gpentHmgr, and each handle is  
> indexed from it. The resulting structure is called an _ENTRY, and  
> is defined as follows:
>
> struct _ENTRY
> {
>     union
>     {
>         POBJ pobj;
>         HANDLE hFree;
>     };
>     union
>     {
>          ULONG ulObj;
>          struct
>          {
>                 USHORT Count:15;
>                 USHORT Lock:1;
>                 HANDLE Pid;
>          };
>     } ObjectOwner;
>     USHORT FullUnique;
>     UCHAR Objt;
>     UCHAR Flags;
>     PVOID pUser;
> };
>
> DXG uses a DDENTRY structure, which is similar. Handles are indexed  
> from gpentDdHmgr.
>
> What Greatlord hadn't noticed while reversing is that part of the  
> code was dealing with the DD_ENTRY object, and part of it was  
> dereferencing the first member of DD_ENTRY, which is the pObj (and  
> was now dealing with the _BASEOBJECT).
>
> Objt is where the object type is defined -- you already seem to  
> know the Win32K Objects. Here are the DXG objects:
>
> DD_MOTIONCOMP_TYPE
> DD_VIDEOPORT_TYPE
> D3D_HANDLE_TYPE
> DD_SURFACE_TYPE
> DD_DIRECTDRAW_TYPE
> DD_DEF_TYPE.
>
> So how exactly then does DdHmgrLock work? Quite similarly to HmgrLock:
>
> POBJ
> FASTCALL
> DdHmgLock(HDD_OBJ DdHandle,
>           UCHAR ObjectType,
>           BOOLEAN LockOwned)
> {
>     POBJ Object = NULL;
>     PDD_ENTRY Entry;
>     ULONG Index;
>
>     //
>     // Acquire the DirectX Handle Manager Lock
>     //
>     if (!LockOwned) DdHmgAcquireHmgrSemaphore();
>
>     //
>     // Get the handle index and validate it
>     //
>     Index = DdHandle & 0x1FFFFF;
>     if (Index < gcMaxDdHmgr)
>     {
>         //
>         // Get the entry
>         //
>         Entry = gpentDdHmgr[Index];
>
>         //
>         // Validate the owner
>         //
>         if ((Entry->ObjectOwner.Pid = PsGetCurrentProcessId() &  
> 0xFFFFFFFC) ||
>             !(Entry->ObjectOwner.Pid))
>         {
>             //
>             // Validate the object type
>             //
>             if (Entry->Objt == ObjectType)
>             {
>                 //
>                 // Validate the handle type
>                 //
>                 if (Entry->FullUnique == ((DdHandle >> 21) & 0x7FF))
>                 {
>                     //
>                     // Get the GDI Object
>                     //
>                     Object = DdEntry->pObj;
>
>                     //
>                     // Make sure we can lock it
>                     //
>                     if (!(Object->cExclusiveLock) ||
>                         (Object->Tid == (PW32THREAD) 
> PsGetCurrentThread()))
>                     {
>                         //
>                         // Acquire the lock
>                         //
>                         InterlockedIncrement(&Object->cExclusiveLock);
>                         Object->Tid = (PW32THREAD)PsGetCurrentThread 
> ();
>                     }
>                     else
>                     {
>                         //
>                         // Already locked by someone else
>                         //
>                         Object = NULL;
>                     }
>                 }
>             }
>         }
>     }
>
>     //
>     // Release the lock
>     //
>     if (!LockOwned) DdHmgReleaseHmgrSemaphore();
>
>     //
>     // Return the object
>     //
>     return Object;
> }
>
>
> I am looking forward to compatible Hmgr implementation in win32k!
>
> Any questions?
>
> On 30-Dec-07, at 7:02 AM, Magnus Olsen wrote:
>
>>
>> I forget to say this
>> EDD_SURFACE DxLock expect it is always value 2 in Type
>> other wise the lock will fail.
>> here is some of my code it is part of DxLock lock process I am  
>> working on.
>> here is the code  I am working on and some rethinking how GDIOBJHDR
>> can look like.
>>
>> Some rethinking why not ?
>>
>> typedef struct _GDIOBJHDR
>> {
>>     HGDIOBJ     hHmgr;
>>     union {
>>                   struct {
>>                                 WORD count;
>>                           };
>>                   struct {
>>                                 WORD type;
>>                           } u;
>>               DWORD Entry;
>>             }
>>
>>     ULONG       cExcLock;
>>     ULONG       Tid;
>> }GDIOBJHDR, PGDIOBJHDR;
>>
>> DWORD
>> STDCALL
>> DxLock(HANDLE hSurface, PDD_LOCKDATA puLockData, HDC hdcClip)
>> {
>>     DD_LOCKDATA LockData;
>>     PEDD_SURFACE pSurface;
>>     _SEH_TRY
>>     {
>>         ProbeForRead(puLockData, sizeof(DD_LOCKDATA), 1);
>>         RtlCopyMemory(&LockData,puLockData, sizeof(DD_LOCKDATA));
>>     }
>>     _SEH_HANDLE
>>     {
>>         _SEH_YIELD(return DDERR_GENERIC);
>>     }
>>     _SEH_END;
>>
>>     pSurface = DdHmgLock(hSurface,2,0);
>>     .......
>>     .......
>>     .......
>> }
>>
>>
>>
>> LPVOID
>> STDCALL
>> DdHmgLock(HANDLE hObject, WORD GdiObjectType, BOOL  
>> AcqurieHmgrSemaphoreAndRelease )
>> {
>>     PGDIOBJHDR pObjhdr = NULL;
>>     PVOID pRetObjhdr = NULL;
>>     DWORD position = hObject & 0x1FFFFF;
>>
>>     /* check see if we need Acqurie Hmgr Semaphore */
>>     if ( !AcqurieHmgrSemaphoreAndRelease )
>>     {
>>         DdHmgAcquireHmgrSemaphore();
>>     }
>>
>>     /* Check see if  position we are in range,  gcMaxDdHmgr is our  
>> counter how many object we got */
>>     if (  position < gcMaxDdHmgr   )
>>     {
>>         /* Get our Gdi Object */
>>         pObjhdr = (LPBYTE)gpentDdHmgr + (position * sizeof 
>> (GDIOBJHDR) );
>>
>>         /* Vaildate if we got the object type we wanted */
>>         if ( ( pObjhdr->Type == GdiObjectType ) &&
>>              (( pObjhdr->Entry) == (((DWORD)hObject >> 21) &  
>> 0x7FF) ) &&
>>              (pObjhdr->cExcLock) &&
>>              (pObjhdr->Tid != PsGetCurrentThread() ) )
>>         {
>>             InterlockedIncrement(pObjhdr->cExcLock);
>>             pObjhdr->Tid = PsGetCurrentThread();
>>             pRetObjhdr = (PVOID) pObjhdr;
>>         }
>>     }
>>
>>     /* check see if we need release Hmgr Semaphore */
>>     if ( !AcqurieHmgrSemaphoreAndRelease )
>>     {
>>         DdHmgReleaseHmgrSemaphore();
>>     }
>>
>>     return pRetObjhdr;
>> }
>> Original Message -----
>> From: Magnus Olsen
>> To: ReactOS Development List
>> Sent: Sunday, December 30, 2007 12:07 PM
>> Subject: Re: [ros-dev] About GDIOBJHDR header changes
>>
>> Hi Jim and Timo
>> I base it on how dxg.sys acts when it lock a
>> dx object.
>> rember that DWORD store data diffent
>> the 2 we see it should be the type
>> rember that the byte order for DWORD is
>> casted it mean if it got 2 it is store in the higher part
>> see memory layout
>>
>> memory layout
>>  ---------------------------------
>> | WORD 00  | bit 0-15   |
>>  ---------------------------------
>> | WORD 01  | bit 16-31 |
>>  ---------------------------------
>>
>> word 01 and word 00 are swaped when it display as DWORD, in DWORD  
>> the word 01 will become bit 0-15, word 00 will become bit 16-31
>> that expain the value 0,1,2,3 we see in PVOID Entry. if we split  
>> it. we will see value 0,1,2,3,4 in Type amd count is often 0.
>> I have no clude yet what diffent type it exists.
>> the count is often set to 0
>> and the type is set to 0, 1, 2, 3 and so on.
>>
>> Still any unclear why I think it we should Split PVOID into two  
>> diffent members ?
>>
>>
>>
>>
>> ----- Original Message -----
>> From: Timo Kreuzer
>> To: ReactOS Development List
>> Sent: Sunday, December 30, 2007 4:24 AM
>> Subject: Re: [ros-dev] About GDIOBJHDR header changes
>>
>> James Tabor schrieb:
>>>
>>> Hi!
>>>
>>>
>>>> typedef struct _GDIOBJHDR
>>>> {
>>>>     HGDIOBJ     hHmgr;
>>>>     PVOID       unknownCount;
>>>>     ULONG       cExcLock;
>>>>     ULONG       Tid;
>>>> }GDIOBJHDR, PGDIOBJHDR;
>>>>
>>>>
>>> I thought PVOID unknownCount was PVOID pEntry which is the pointer
>>> back to the handle table entry. That could have changed since  
>>> this is
>>> based on Yuan book and w2k. Remember too, that DxDD handles are
>>> different and handled outside normal DC's.
>>>
>> Yuan says it's pEntry, I came to the conclusion it's probably a  
>> counter, because it's values are small like 1,2,3..0x200
>> see http://www.reactos.org/wiki/index.php/Techwiki/win32k/GDIOBJHDR
>> Has probably changed from 2k to xp.
>> I agree, DX objects might be different, maybe they have a  
>> different header structure, I have never looked at DX object  
>> memory, so I don't know how they look...
>> I just can say that all GDI objects I have dumped the memory of,  
>> don't have a type field there, it's always been 0.
>>
>> Timo
>>
>>
>>
>> _______________________________________________
>> Ros-dev mailing list
>> Ros-dev at reactos.org
>> http://www.reactos.org/mailman/listinfo/ros-dev
>>
>>
>> _______________________________________________
>> Ros-dev mailing list
>> Ros-dev at reactos.org
>> http://www.reactos.org/mailman/listinfo/ros-dev
>> _______________________________________________
>> Ros-dev mailing list
>> Ros-dev at reactos.org
>> http://www.reactos.org/mailman/listinfo/ros-dev
>
> Best regards,
> Alex Ionescu
>
>
>
> _______________________________________________
> Ros-dev mailing list
> Ros-dev at reactos.org
> http://www.reactos.org/mailman/listinfo/ros-dev
> _______________________________________________
> Ros-dev mailing list
> Ros-dev at reactos.org
> http://www.reactos.org/mailman/listinfo/ros-dev

Best regards,
Alex Ionescu

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.reactos.org/pipermail/ros-dev/attachments/20071230/274f1fa8/attachment-0001.html 


More information about the Ros-dev mailing list