[DXG] Implement DdAllocateObject, DdFreeObject, DdGetFreeHandle, DdHmgAlloc, DdHmgFre...
authorSebastian Gasiorek <sebastian.gasiorek@reactos.org>
Fri, 10 Mar 2017 17:51:20 +0000 (17:51 +0000)
committerSebastian Gasiorek <sebastian.gasiorek@reactos.org>
Fri, 10 Mar 2017 17:51:20 +0000 (17:51 +0000)
svn path=/trunk/; revision=74143

reactos/win32ss/reactx/dxg/ddhmg.c
reactos/win32ss/reactx/dxg/dxg_int.h
reactos/win32ss/reactx/dxg/tags.h

index 13e002b..7130890 100644 (file)
 #include <dxg_int.h>
 
 /* The DdHmgr manger stuff */
-ULONG gcSizeDdHmgr =  64 * sizeof(DD_ENTRY);
+ULONG gcSizeDdHmgr =  1024;
 PDD_ENTRY gpentDdHmgr = NULL;
 
 ULONG gcMaxDdHmgr = 0;
 PDD_ENTRY gpentDdHmgrLast = NULL;
 
-HANDLE ghFreeDdHmgr = 0;
+/* next free ddhmg handle number available to reuse */
+ULONG ghFreeDdHmgr = 0;
 HSEMAPHORE ghsemHmgr = NULL;
 
 BOOL
@@ -25,7 +26,7 @@ FASTCALL
 VerifyObjectOwner(PDD_ENTRY pEntry)
 {
     DWORD Pid = (DWORD)(DWORD_PTR)PsGetCurrentProcessId() & 0xFFFFFFFC;
-    DWORD check = pEntry->ObjectOwner.ulObj & 0xFFFFFFFE;
+    DWORD check = (DWORD)pEntry->Pid & 0xFFFFFFFE;
     return ( (check == Pid) || (!check));
 }
 
@@ -46,7 +47,7 @@ BOOL
 FASTCALL
 DdHmgCreate(VOID)
 {
-    gpentDdHmgr = EngAllocMem(FL_ZERO_MEMORY, gcSizeDdHmgr, TAG_THDD);
+    gpentDdHmgr = EngAllocMem(FL_ZERO_MEMORY, gcSizeDdHmgr * sizeof(DD_ENTRY), TAG_THDD);
     ghFreeDdHmgr = 0;
     gcMaxDdHmgr = 1;
 
@@ -144,8 +145,8 @@ PVOID
 FASTCALL
 DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned)
 {
+    DWORD Index = DDHMG_HTOI(DdHandle);
 
-    DWORD Index = (DWORD)(DWORD_PTR)DdHandle & 0x1FFFFF;
     PDD_ENTRY pEntry = NULL;
     PVOID Object = NULL;
 
@@ -157,19 +158,17 @@ DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned)
     if ( Index < gcMaxDdHmgr )
     {
         pEntry = (PDD_ENTRY)((PBYTE)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
+
         if ( VerifyObjectOwner(pEntry) )
         {
-            /* FIXME
-            if ( (pEntry->Objt == ObjectType ) &&
-                 (pEntry->FullUnique == (((DWORD)DdHandle >> 21) & 0x7FF) ) &&
-                 (pEntry->pobj->cExclusiveLock == 0) &&
-                 (pEntry->pobj->Tid == PsGetCurrentThread()))
-               {
-                    InterlockedIncrement(&pEntry->pobj->cExclusiveLock);
-                    pEntry->pobj->Tid = PsGetCurrentThread();
-                    Object = pEntry->pobj;
-               }
-           */
+            if ( ( pEntry->Objt == ObjectType ) &&
+                 ( pEntry->FullUnique == (((ULONG)DdHandle >> 21) & 0x7FF) ) &&
+                 ( !pEntry->pobj->cExclusiveLock ) )
+            {
+                InterlockedIncrement((VOID*)&pEntry->pobj->cExclusiveLock);
+                pEntry->pobj->Tid = KeGetCurrentThread();
+                Object = pEntry->pobj;
+            }
         }
     }
 
@@ -180,3 +179,244 @@ DdHmgLock(HANDLE DdHandle, UCHAR ObjectType, BOOLEAN LockOwned)
 
     return Object;
 }
+
+/*++
+* @name DdAllocateObject
+* @implemented
+*
+* The function DdAllocateObject is used internally in dxg.sys
+* It allocates memory for a DX kernel object
+*
+* @param UINT32 oSize
+* Size of memory to be allocated
+* @param UCHAR oType
+* Object type
+* @param BOOLEAN oZeroMemory
+* Zero memory
+*
+* @remarks.
+* Only used internally in dxg.sys
+*/
+PVOID
+FASTCALL
+DdAllocateObject(ULONG objSize, UCHAR objType, BOOLEAN objZeroMemory)
+{
+    PVOID pObject = NULL;
+
+    if (objZeroMemory)
+        pObject = EngAllocMem(FL_ZERO_MEMORY, objSize, ((ULONG)objType << 24) + TAG_DH_0);
+    else
+        pObject = EngAllocMem(0, objSize, ((ULONG)objType << 24) + TAG_DH_0);
+
+    if (!pObject)
+    {
+        EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
+    }
+
+    return pObject;
+}
+
+/*++
+* @name DdFreeObject
+* @implemented
+*
+* The function DdFreeObject is used internally in dxg.sys
+* It frees memory of DX kernel object
+*
+* @param PVOID pObject
+* Object memory to be freed
+*
+* @remarks.
+* Only used internally in dxg.sys
+*/
+VOID
+FASTCALL
+DdFreeObject(PVOID pObject)
+{
+    EngFreeMem(pObject);
+}
+
+
+/*++
+* @name DdGetFreeHandle
+* @implemented
+*
+* The function DdGetFreeHandle is used internally in dxg.sys
+* It allocates new handle for specified object type
+*
+* @param UCHAR oType
+* Object type
+*
+* @return
+* Returns handle or 0 if it fails.
+*
+* @remarks.
+* Only used internally in dxg.sys
+*--*/
+HANDLE
+FASTCALL
+DdGetFreeHandle(UCHAR objType)
+{
+    PVOID mAllocMem = NULL;
+    ULONG mAllocEntries = 0;
+    PDD_ENTRY pEntry = NULL;
+    ULONG retVal;
+    ULONG index;
+
+    // check if memory is allocated
+    if (!gpentDdHmgr)
+        return 0;
+
+    // check if we reached maximum handle index
+    if (gcMaxDdHmgr == DDHMG_HANDLE_LIMIT)
+        return 0;
+
+    // check if we have free handle to reuse
+    if (ghFreeDdHmgr)
+    {
+       index = ghFreeDdHmgr;
+       pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * index));
+
+       // put next free index to our global variable
+       ghFreeDdHmgr = pEntry->NextFree;             
+
+       // build handle 
+       pEntry->FullUnique = objType | 8;
+       retVal = (pEntry->FullUnique << 21) | index;
+       return (HANDLE)retVal;
+    }
+
+    // if all pre-allocated memory is already used then allocate more
+    if (gcSizeDdHmgr == gcMaxDdHmgr)
+    {
+        // allocate buffer for next 1024 handles
+        mAllocEntries = gcSizeDdHmgr + 1024;
+        mAllocMem = EngAllocMem(FL_ZERO_MEMORY, sizeof(DD_ENTRY) * (mAllocEntries), TAG_THDD);
+        if (!mAllocMem)
+            return 0;
+
+        memmove(&mAllocMem, gpentDdHmgr, sizeof(DD_ENTRY) * gcSizeDdHmgr);
+        gcSizeDdHmgr = mAllocEntries;
+        gpentDdHmgrLast = gpentDdHmgr;
+        EngFreeMem(gpentDdHmgr);
+        gpentDdHmgr = mAllocMem;
+    }
+
+    pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * gcMaxDdHmgr));
+
+    // build handle 
+    pEntry->FullUnique = objType | 8;
+    retVal = (pEntry->FullUnique << 21) | gcMaxDdHmgr;
+    gcMaxDdHmgr = gcMaxDdHmgr + 1;
+
+    return (HANDLE)retVal;
+}
+
+/*++
+* @name DdHmgAlloc
+* @implemented
+*
+* The function DdHmgAlloc is used internally in dxg.sys
+* It allocates object
+*
+* @param ULONG objSize
+* Size of memory to be allocated
+* @param CHAR objType
+* Object type
+* @param UINT objFlags
+* Object flags
+*
+* @return
+* Handle if object is not locked by objFlags
+* Object if lock is set in objFlags
+* 0 if it fails.
+*
+* @remarks.
+* Only used internally in dxg.sys
+*--*/
+HANDLE
+FASTCALL
+DdHmgAlloc(ULONG objSize, CHAR objType, UINT objFlags)
+{
+    PVOID pObject = NULL;
+    HANDLE DdHandle = NULL;
+    PDD_ENTRY pEntry = NULL;
+    DWORD Index;
+
+    pObject = DdAllocateObject(objSize, objType, TRUE);
+    if (!pObject)
+        return 0;
+
+    EngAcquireSemaphore(ghsemHmgr);
+
+    /* Get next free handle */
+    DdHandle = DdGetFreeHandle(objType);
+
+    if (DdHandle)
+    {
+        Index = DDHMG_HTOI(DdHandle);
+
+        pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
+
+        pEntry->pobj = pObject;
+        pEntry->Objt = objType;
+
+        pEntry->Pid = (HANDLE)(((ULONG)PsGetCurrentProcessId() & 0xFFFFFFFC) | ((ULONG)(pEntry->Pid) & 1));
+
+        if (objFlags & 1)
+            pEntry->pobj->Tid = KeGetCurrentThread();
+
+        pEntry->pobj->cExclusiveLock = objFlags & 1;
+        pEntry->pobj->hHmgr = DdHandle;
+        
+        EngReleaseSemaphore(ghsemHmgr);
+
+        /* Return handle if object not locked */
+        if (!(objFlags & 1))
+           return DdHandle;
+
+        return (HANDLE)pEntry;
+    }
+
+    EngReleaseSemaphore(ghsemHmgr);
+    DdFreeObject(pObject);
+    return 0;
+}
+
+/*++
+* @name DdHmgFree
+* @implemented
+*
+* The function DdHmgFree is used internally in dxg.sys
+* It frees DX object and memory allocated to it
+*
+* @param HANDLE DdHandle
+* DX object handle
+*
+* @remarks.
+* Only used internally in dxg.sys
+*--*/
+VOID
+FASTCALL
+DdHmgFree(HANDLE DdHandle)
+{
+    PDD_ENTRY pEntry = NULL;
+
+    DWORD Index = DDHMG_HTOI(DdHandle);
+
+    EngAcquireSemaphore(ghsemHmgr);
+
+    pEntry = (PDD_ENTRY)((PLONG)gpentDdHmgr + (sizeof(DD_ENTRY) * Index));
+
+    // check if we have object that should be freed
+    if (pEntry->pobj)
+        DdFreeObject(pEntry->pobj);
+
+    pEntry->NextFree = ghFreeDdHmgr;
+
+    // reset process ID
+    pEntry->Pid = (HANDLE)((DWORD)pEntry->Pid & 1);
+    ghFreeDdHmgr = Index;
+
+    EngReleaseSemaphore(ghsemHmgr);
+}
index c4d6a5b..1379e4a 100644 (file)
 #define INTERNAL_CALL NTAPI
 #define NT_BUILD_ENVIRONMENT
 
+#define DDHMG_HANDLE_LIMIT 0x200000
+#define DDHMG_HTOI(DdHandle) ((DWORD)DdHandle & (DDHMG_HANDLE_LIMIT-1))
+
+
 #include <windef.h>
 #include <winerror.h>
 #include <wingdi.h>
@@ -45,22 +49,11 @@ typedef struct _DD_BASEOBJECT
     union
     {
         PDD_BASEOBJECT pobj;
-        HANDLE hFree;
+        ULONG NextFree;
     };
-    union
-    {
-         ULONG ulObj;
-         struct
-         {
-                USHORT Count;
-                USHORT Lock;
-                HANDLE Pid;
-         };
-    } ObjectOwner;
+    HANDLE Pid;
     USHORT FullUnique;
     UCHAR Objt;
-    UCHAR Flags;
-    PVOID pUser;
 } DD_ENTRY, *PDD_ENTRY;
 
 typedef struct _EDD_SURFACE_LOCAL
@@ -80,7 +73,7 @@ extern ULONG gcSizeDdHmgr;
 extern PDD_ENTRY gpentDdHmgr;
 extern ULONG gcMaxDdHmgr;
 extern PDD_ENTRY gpentDdHmgrLast;
-extern HANDLE ghFreeDdHmgr;
+extern ULONG ghFreeDdHmgr;
 extern HSEMAPHORE ghsemHmgr;
 extern LONG gcDummyPageRefCnt;
 extern HSEMAPHORE ghsemDummyPage;
index cf721f6..328289e 100644 (file)
@@ -1,2 +1,3 @@
 #define TAG_THDD    'ddht'
 #define TAG_GINI    'iniG'
+#define TAG_DH_0    '0 hD'