[Win32k]
[reactos.git] / reactos / subsystems / win32 / win32k / ntuser / object.c
index 20378f4..4df5c8f 100644 (file)
@@ -22,7 +22,7 @@
 
 /* INCLUDES ******************************************************************/
 
-#include <w32k.h>
+#include <win32k.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -151,6 +151,7 @@ __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY
    ret = entry->ptr;
    entry->ptr  = ht->freelist;
    entry->type = 0;
+   entry->flags = 0;
    entry->pi = NULL;
    ht->freelist  = entry;
 
@@ -167,6 +168,7 @@ UserHandleOwnerByType(USER_OBJECT_TYPE type)
     switch (type)
     {
         case otWindow:
+        case otInputContext:
             pi = GetW32ThreadInfo();
             break;
 
@@ -175,6 +177,7 @@ UserHandleOwnerByType(USER_OBJECT_TYPE type)
         case otHook:
         case otCallProc:
         case otAccel:
+        case otSMWP:
             pi = GetW32ProcessInfo();
             break;
 
@@ -198,6 +201,7 @@ HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE typ
       return 0;
    entry->ptr  = object;
    entry->type = type;
+   entry->flags = 0;
    entry->pi = UserHandleOwnerByType(type);
    if (++entry->generation >= 0xffff)
       entry->generation = 1;
@@ -217,7 +221,7 @@ PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type
 
    if (!(entry = handle_to_entry(ht, handle )) || entry->type != type)
    {
-      SetLastWin32Error(ERROR_INVALID_HANDLE);
+      EngSetLastError(ERROR_INVALID_HANDLE);
       return NULL;
    }
    return entry->ptr;
@@ -248,26 +252,6 @@ void *get_user_object_handle(PUSER_HANDLE_TABLE ht,  HANDLE* handle, USER_OBJECT
    return entry->ptr;
 }
 
-/* free a user handle */
-BOOL UserFreeHandle(PUSER_HANDLE_TABLE ht,  HANDLE handle )
-{
-   PUSER_HANDLE_ENTRY entry;
-   PVOID object;
-
-   if (!(entry = handle_to_entry( ht, handle )))
-   {
-      SetLastNtError( STATUS_INVALID_HANDLE );
-      return FALSE;
-   }
-
-   object = free_user_entry(ht, entry );
-
-   /* We removed the handle, which was a reference! */
-   return UserDereferenceObject(object);
-
-   return TRUE;
-}
-
 /* return the next user handle after 'handle' that is of a given type */
 PVOID UserGetNextHandle(PUSER_HANDLE_TABLE ht, HANDLE* handle, USER_OBJECT_TYPE type )
 {
@@ -294,138 +278,210 @@ PVOID UserGetNextHandle(PUSER_HANDLE_TABLE ht, HANDLE* handle, USER_OBJECT_TYPE
    return NULL;
 }
 
-
-
-PVOID FASTCALL
-UserCreateObject(PUSER_HANDLE_TABLE ht, HANDLE* h,USER_OBJECT_TYPE type , ULONG size)
+BOOL FASTCALL UserCreateHandleTable(VOID)
 {
 
-   HANDLE hi;
-   PUSER_OBJECT_HEADER hdr = UserHeapAlloc(size + sizeof(USER_OBJECT_HEADER));//ExAllocatePool(PagedPool, size + sizeof(USER_OBJECT_HEADER));
-   if (!hdr)
-      return NULL;
+   PVOID mem;
 
+   //FIXME: dont alloc all at once! must be mapped into umode also...
+   mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * 1024*2);
+   if (!mem)
+   {
+      DPRINT1("Failed creating handle table\n");
+      return FALSE;
+   }
 
-   hi = UserAllocHandle(ht, USER_HEADER_TO_BODY(hdr), type );
-   if (!hi)
+   gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE));
+   if (gHandleTable == NULL)
    {
-      //ExFreePool(hdr);
-       UserHeapFree(hdr);
-      return NULL;
+       UserHeapFree(mem);
+       DPRINT1("Failed creating handle table\n");
+       return FALSE;
    }
 
-   RtlZeroMemory(hdr, size + sizeof(USER_OBJECT_HEADER));
-   hdr->hSelf = hi;
-   hdr->RefCount = 2; // we need this, because we create 2 refs: handle and pointer!
+   //FIXME: make auto growable
+   UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
 
-   if (h)
-      *h = hi;
-   return USER_HEADER_TO_BODY(hdr);
+   return TRUE;
 }
 
-BOOL FASTCALL
-UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type )
+//
+// New
+//
+PVOID
+FASTCALL
+UserCreateObject( PUSER_HANDLE_TABLE ht,
+                  PDESKTOP pDesktop,
+                  HANDLE* h,
+                  USER_OBJECT_TYPE type,
+                  ULONG size)
 {
-   PUSER_OBJECT_HEADER hdr;
-   PVOID body = UserGetObject(gHandleTable, h, type);
-   if (!body)
-      return FALSE;
+   HANDLE hi;
+   PVOID Object;
+   PTHREADINFO pti;
+   PPROCESSINFO ppi;
+   BOOL dt;
+   PDESKTOP rpdesk = pDesktop;
 
-   hdr = USER_BODY_TO_HEADER(body);
-   ASSERT(hdr->RefCount >= 1);
-
-   hdr->destroyed = TRUE;
-   return UserFreeHandle(gHandleTable, h);
-}
+   pti = GetW32ThreadInfo();
+   ppi = pti->ppi;
+   if (!pDesktop) rpdesk = pti->rpdesk;
 
+   switch (type)
+   {
+      case otWindow:
+//      case otMenu:
+      case otHook:
+      case otCallProc:
+      case otInputContext:
+         Object = DesktopHeapAlloc(rpdesk, size);
+         dt = TRUE;
+         break;
+
+      default:
+         Object = UserHeapAlloc(size);
+         dt = FALSE;
+         break;
+   }
 
-VOID FASTCALL UserReferenceObject(PVOID obj)
-{
-   PUSER_OBJECT_HEADER hdr = USER_BODY_TO_HEADER(obj);
+   if (!Object)
+      return NULL;
 
-   ASSERT(hdr->RefCount >= 0);
 
-   hdr->RefCount++;
-}
+   hi = UserAllocHandle(ht, Object, type );
+   if (!hi)
+   {
+      if (dt)
+         DesktopHeapFree(rpdesk, Object);
+      else
+         UserHeapFree(Object);
+      return NULL;
+   }
 
+   RtlZeroMemory(Object, size);
 
-PVOID FASTCALL UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
-{
-    PVOID object;
+   switch (type)
+   {
+        case otWindow:
+        case otHook:
+        case otInputContext:
+            ((PTHRDESKHEAD)Object)->rpdesk = rpdesk;
+            ((PTHRDESKHEAD)Object)->pSelf = Object;
+        case otEvent:
+            ((PTHROBJHEAD)Object)->pti = pti;
+            break;
 
-    object = UserGetObject(gHandleTable, handle, type);
-    if(object)
-    {
-        UserReferenceObject(object);
-    }
+        case otMenu:
+        case otCallProc:
+            ((PPROCDESKHEAD)Object)->rpdesk = rpdesk;
+            ((PPROCDESKHEAD)Object)->pSelf = Object;            
+            break;
 
-    return object;
-}
+        case otCursorIcon:
+            ((PPROCMARKHEAD)Object)->ppi = ppi;
+            break;
 
+        default:
+            break;
+   }
+   /* Now set default headers. */
+   ((PHEAD)Object)->h = hi;
+   ((PHEAD)Object)->cLockObj = 2; // we need this, because we create 2 refs: handle and pointer!
 
-HANDLE FASTCALL UserObjectToHandle(PVOID obj)
-{
-    PUSER_OBJECT_HEADER hdr = USER_BODY_TO_HEADER(obj);
-    return hdr->hSelf;
+   if (h)
+      *h = hi;
+   return Object;
 }
 
 
-BOOL FASTCALL UserDereferenceObject(PVOID obj)
+BOOL
+FASTCALL
+UserDereferenceObject(PVOID object)
 {
-   PUSER_OBJECT_HEADER hdr = USER_BODY_TO_HEADER(obj);
+  PUSER_HANDLE_ENTRY entry;
+  USER_OBJECT_TYPE type;
 
-   ASSERT(hdr->RefCount >= 1);
+  ASSERT(((PHEAD)object)->cLockObj >= 1);
 
-   hdr->RefCount--;
+  if ((INT)--((PHEAD)object)->cLockObj <= 0)
+  {
+     entry = handle_to_entry(gHandleTable, ((PHEAD)object)->h );
 
-   // You can not have a zero here!
-   if (!hdr->destroyed && hdr->RefCount == 0)
-   {
-      hdr->RefCount++; // BOUNCE!!!!!
-      DPRINT1("warning! Dereference to zero without deleting! Obj -> 0x%x\n", obj);
-   }
+     DPRINT("warning! Dereference to zero! Obj -> 0x%x\n", object);
 
-   if (hdr->RefCount == 0 && hdr->destroyed)
-   {
-//      DPRINT1("info: something destroyed bcaise of deref, in use=%i\n",gpsi->cHandleEntries);
+     ((PHEAD)object)->cLockObj = 0;
 
-      memset(hdr, 0x55, sizeof(USER_OBJECT_HEADER));
+     if (!(entry->flags & HANDLEENTRY_INDESTROY))
+        return TRUE;
 
-      return UserHeapFree(hdr);
-      //ExFreePool(hdr);
+     type = entry->type;
+     free_user_entry(gHandleTable, entry );
 
-      return TRUE;
-   }
+     switch (type)
+     {
+        case otWindow:
+//        case otMenu:
+        case otHook:
+        case otCallProc:
+        case otInputContext:
+           return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
 
-   return FALSE;
+        default:
+           return UserHeapFree(object);
+     }
+  }
+  return FALSE;
 }
 
+BOOL
+FASTCALL
+UserFreeHandle(PUSER_HANDLE_TABLE ht,  HANDLE handle )
+{
+  PUSER_HANDLE_ENTRY entry;
 
+  if (!(entry = handle_to_entry( ht, handle )))
+  {
+     SetLastNtError( STATUS_INVALID_HANDLE );
+     return FALSE;
+  }
 
-BOOL FASTCALL UserCreateHandleTable(VOID)
+  entry->flags = HANDLEENTRY_INDESTROY;
+
+  return UserDereferenceObject(entry->ptr);
+}
+
+BOOL
+FASTCALL
+UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type )
 {
+   PVOID body = UserGetObject(gHandleTable, h, type);
+   
+   if (!body) return FALSE;
 
-   PVOID mem;
+   ASSERT( ((PHEAD)body)->cLockObj >= 1);
 
-   //FIXME: dont alloc all at once! must be mapped into umode also...
-   //mem = ExAllocatePool(PagedPool, sizeof(USER_HANDLE_ENTRY) * 1024*2);
-   mem = UserHeapAlloc(sizeof(USER_HANDLE_ENTRY) * 1024*2);
-   if (!mem)
-   {
-      DPRINT1("Failed creating handle table\n");
-      return FALSE;
-   }
+   return UserFreeHandle(gHandleTable, h);
+}
 
-   gHandleTable = UserHeapAlloc(sizeof(USER_HANDLE_TABLE));
-   if (gHandleTable == NULL)
-   {
-       UserHeapFree(mem);
-       DPRINT1("Failed creating handle table\n");
-       return FALSE;
-   }
+VOID
+FASTCALL
+UserReferenceObject(PVOID obj)
+{
+   ASSERT(((PHEAD)obj)->cLockObj >= 0);
 
-   //FIXME: make auto growable
-   UserInitHandleTable(gHandleTable, mem, sizeof(USER_HANDLE_ENTRY) * 1024*2);
+   ((PHEAD)obj)->cLockObj++;
+}
 
-   return TRUE;
+PVOID
+FASTCALL
+UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
+{
+    PVOID object;
+
+    object = UserGetObject(gHandleTable, handle, type);
+    if (object)
+    {
+       UserReferenceObject(object);
+    }
+    return object;
 }