[WIN32K]
[reactos.git] / reactos / win32ss / user / ntuser / object.c
index d778575..321d90f 100644 (file)
@@ -12,32 +12,259 @@ DBG_DEFAULT_CHANNEL(UserObj);
 //int usedHandles=0;
 PUSER_HANDLE_TABLE gHandleTable = NULL;
 
+/* Forward declarations */
+static PVOID AllocThreadObject(
+    _In_ PDESKTOP pDesk,
+    _In_ PTHREADINFO pti,
+    _In_ SIZE_T Size,
+    _Out_ PVOID* HandleOwner)
+{
+    PTHROBJHEAD ObjHead;
+
+    UNREFERENCED_PARAMETER(pDesk);
+
+    ASSERT(Size > sizeof(*ObjHead));
+    ASSERT(pti != NULL);
+
+    ObjHead = UserHeapAlloc(Size);
+    if (!ObjHead)
+        return NULL;
+
+    RtlZeroMemory(ObjHead, Size);
+
+    ObjHead->pti = pti;
+    IntReferenceThreadInfo(pti);
+    *HandleOwner = pti;
+    /* It's a thread object, but it still count as one for the process */
+    pti->ppi->UserHandleCount++;
+
+    return ObjHead;
+}
+
+static void FreeThreadObject(
+    _In_ PVOID Object)
+{
+    PTHROBJHEAD ObjHead = (PTHROBJHEAD)Object;
+    PTHREADINFO pti = ObjHead->pti;
+
+    UserHeapFree(ObjHead);
+
+    pti->ppi->UserHandleCount--;
+    IntDereferenceThreadInfo(pti);
+}
+
+static PVOID AllocDeskThreadObject(
+    _In_ PDESKTOP pDesk,
+    _In_ PTHREADINFO pti,
+    _In_ SIZE_T Size,
+    _Out_ PVOID* HandleOwner)
+{
+    PTHRDESKHEAD ObjHead;
+
+    ASSERT(Size > sizeof(*ObjHead));
+    ASSERT(pti != NULL);
+
+    if (!pDesk)
+        pDesk = pti->rpdesk;
+
+    ObjHead = DesktopHeapAlloc(pDesk, Size);
+    if (!ObjHead)
+        return NULL;
+
+    RtlZeroMemory(ObjHead, Size);
+
+    ObjHead->pSelf = ObjHead;
+    ObjHead->rpdesk = pDesk;
+    ObjHead->pti = pti;
+    IntReferenceThreadInfo(pti);
+    *HandleOwner = pti;
+    /* It's a thread object, but it still count as one for the process */
+    pti->ppi->UserHandleCount++;
+
+    return ObjHead;
+}
+
+static void FreeDeskThreadObject(
+    _In_ PVOID Object)
+{
+    PTHRDESKHEAD ObjHead = (PTHRDESKHEAD)Object;
+    PDESKTOP pDesk = ObjHead->rpdesk;
+    PTHREADINFO pti = ObjHead->pti;
+
+    DesktopHeapFree(pDesk, Object);
+
+    pti->ppi->UserHandleCount--;
+    IntDereferenceThreadInfo(pti);
+}
+
+static PVOID AllocDeskProcObject(
+    _In_ PDESKTOP pDesk,
+    _In_ PTHREADINFO pti,
+    _In_ SIZE_T Size,
+    _Out_ PVOID* HandleOwner)
+{
+    PPROCDESKHEAD ObjHead;
+    PPROCESSINFO ppi;
+
+    ASSERT(Size > sizeof(*ObjHead));
+    ASSERT(pDesk != NULL);
+    ASSERT(pti != NULL);
+
+    ObjHead = DesktopHeapAlloc(pDesk, Size);
+    if (!ObjHead)
+        return NULL;
+
+    RtlZeroMemory(ObjHead, Size);
+
+    ppi = pti->ppi;
+
+    ObjHead->pSelf = ObjHead;
+    ObjHead->rpdesk = pDesk;
+    ObjHead->hTaskWow = (DWORD_PTR)ppi;
+    ppi->UserHandleCount++;
+    IntReferenceProcessInfo(ppi);
+    *HandleOwner = ppi;
+
+    return ObjHead;
+}
+
+static void FreeDeskProcObject(
+    _In_ PVOID Object)
+{
+    PPROCDESKHEAD ObjHead = (PPROCDESKHEAD)Object;
+    PDESKTOP pDesk = ObjHead->rpdesk;
+    PPROCESSINFO ppi = (PPROCESSINFO)ObjHead->hTaskWow;
+
+    ppi->UserHandleCount--;
+    IntDereferenceProcessInfo(ppi);
+
+    DesktopHeapFree(pDesk, Object);
+}
+
+static PVOID AllocProcMarkObject(
+    _In_ PDESKTOP pDesk,
+    _In_ PTHREADINFO pti,
+    _In_ SIZE_T Size,
+    _Out_ PVOID* HandleOwner)
+{
+    PPROCMARKHEAD ObjHead;
+    PPROCESSINFO ppi = pti->ppi;
+
+    UNREFERENCED_PARAMETER(pDesk);
+
+    ASSERT(Size > sizeof(*ObjHead));
+
+    ObjHead = UserHeapAlloc(Size);
+    if (!ObjHead)
+        return NULL;
+
+    RtlZeroMemory(ObjHead, Size);
+
+    ObjHead->ppi = ppi;
+    IntReferenceProcessInfo(ppi);
+    *HandleOwner = ppi;
+    ppi->UserHandleCount++;
+
+    return ObjHead;
+}
+
+static void FreeProcMarkObject(
+    _In_ PVOID Object)
+{
+    PPROCESSINFO ppi = ((PPROCMARKHEAD)Object)->ppi;
+
+    UserHeapFree(Object);
+
+    ppi->UserHandleCount--;
+    IntDereferenceProcessInfo(ppi);
+}
+
+static PVOID AllocSysObject(
+    _In_ PDESKTOP pDesk,
+    _In_ PTHREADINFO pti,
+    _In_ SIZE_T Size,
+    _Out_ PVOID* ObjectOwner)
+{
+    PVOID Object;
+
+    UNREFERENCED_PARAMETER(pDesk);
+    UNREFERENCED_PARAMETER(pti);
+
+    ASSERT(Size > sizeof(HEAD));
+
+    Object = UserHeapAlloc(Size);
+    if (!Object)
+        return NULL;
+
+    *ObjectOwner = NULL;
+
+    RtlZeroMemory(Object, Size);
+    return Object;
+}
+
+static void FreeSysObject(
+    _In_ PVOID Object)
+{
+    UserHeapFree(Object);
+}
+
+static const struct
+{
+    PVOID   (*ObjectAlloc)(PDESKTOP, PTHREADINFO, SIZE_T, PVOID*);
+    BOOLEAN (*ObjectDestroy)(PVOID);
+    void    (*ObjectFree)(PVOID);
+} ObjectCallbacks[TYPE_CTYPES] =
+{
+    { NULL,                     NULL,                       NULL },                 /* TYPE_FREE */
+    { AllocDeskThreadObject,    co_UserDestroyWindow,       FreeDeskThreadObject }, /* TYPE_WINDOW */
+    { AllocDeskProcObject,      UserDestroyMenuObject,      FreeDeskProcObject },   /* TYPE_MENU */
+    { AllocProcMarkObject,      /*UserCursorCleanup*/NULL,  FreeProcMarkObject },   /* TYPE_CURSOR */
+    { AllocSysObject,           /*UserSetWindowPosCleanup*/NULL, FreeSysObject },   /* TYPE_SETWINDOWPOS */
+    { AllocDeskThreadObject,    IntRemoveHook,              FreeDeskThreadObject }, /* TYPE_HOOK */
+    { AllocSysObject,           /*UserClipDataCleanup*/NULL,FreeSysObject },        /* TYPE_CLIPDATA */
+    { AllocDeskProcObject,      DestroyCallProc,            FreeDeskProcObject },   /* TYPE_CALLPROC */
+    { AllocProcMarkObject,      UserDestroyAccelTable,      FreeProcMarkObject },   /* TYPE_ACCELTABLE */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_DDEACCESS */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_DDECONV */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_DDEXACT */
+    { AllocSysObject,           /*UserMonitorCleanup*/NULL, FreeSysObject },        /* TYPE_MONITOR */
+    { AllocSysObject,           /*UserKbdLayoutCleanup*/NULL,FreeSysObject },       /* TYPE_KBDLAYOUT */
+    { AllocSysObject,           /*UserKbdFileCleanup*/NULL, FreeSysObject },        /* TYPE_KBDFILE */
+    { AllocThreadObject,        IntRemoveEvent,             FreeThreadObject },     /* TYPE_WINEVENTHOOK */
+    { AllocSysObject,           /*UserTimerCleanup*/NULL,   FreeSysObject },        /* TYPE_TIMER */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_INPUTCONTEXT */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_HIDDATA */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_DEVICEINFO */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_TOUCHINPUTINFO */
+    { NULL,                     NULL,                       NULL },                 /* TYPE_GESTUREINFOOBJ */
+};
+
 #if DBG
 
 void DbgUserDumpHandleTable()
 {
-    int HandleCounts[USER_HANDLE_TYPE_COUNT];
+    int HandleCounts[TYPE_CTYPES];
     PPROCESSINFO ppiList;
     int i;
     PWCHAR TypeNames[] = {L"Free",L"Window",L"Menu", L"CursorIcon", L"SMWP", L"Hook", L"ClipBoardData", L"CallProc",
                           L"Accel", L"DDEaccess", L"DDEconv", L"DDExact", L"Monitor", L"KBDlayout", L"KBDfile",
                           L"Event", L"Timer", L"InputContext", L"HidData", L"DeviceInfo", L"TouchInput",L"GestureInfo"};
 
-    ERR("Total handles count: %d\n", gpsi->cHandleEntries);
+    ERR("Total handles count: %lu\n", gpsi->cHandleEntries);
 
     memset(HandleCounts, 0, sizeof(HandleCounts));
 
-    /* First of all count the number of handles per tpe */
+    /* First of all count the number of handles per type */
     ppiList = gppiList;
     while (ppiList)
     {
-        ERR("Process %s (%d) handles count: %d\n\t", ppiList->peProcess->ImageFileName, ppiList->peProcess->UniqueProcessId, ppiList->UserHandleCount);
+        ERR("Process %s (%p) handles count: %d\n\t", ppiList->peProcess->ImageFileName, ppiList->peProcess->UniqueProcessId, ppiList->UserHandleCount);
 
-        for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++)
+        for (i = 1 ;i < TYPE_CTYPES; i++)
         {
             HandleCounts[i] += ppiList->DbgHandleCount[i];
 
-            DbgPrint("%S: %d, ", TypeNames[i], ppiList->DbgHandleCount[i]);
+            DbgPrint("%S: %lu, ", TypeNames[i], ppiList->DbgHandleCount[i]);
             if (i % 6 == 0)
                 DbgPrint("\n\t");
         }
@@ -48,7 +275,7 @@ void DbgUserDumpHandleTable()
 
     /* Print total type counts */
     ERR("Total handles of the running processes: \n\t");
-    for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++)
+    for (i = 1 ;i < TYPE_CTYPES; i++)
     {
         DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]);
         if (i % 6 == 0)
@@ -62,7 +289,7 @@ void DbgUserDumpHandleTable()
          HandleCounts[gHandleTable->handles[i].type]++;
 
     ERR("Total handles count allocated: \n\t");
-    for (i = 1 ;i < USER_HANDLE_TYPE_COUNT; i++)
+    for (i = 1 ;i < TYPE_CTYPES; i++)
     {
         DbgPrint("%S: %d, ", TypeNames[i], HandleCounts[i]);
         if (i % 6 == 0)
@@ -96,8 +323,7 @@ __inline static HANDLE entry_to_handle(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY
 __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
 {
    PUSER_HANDLE_ENTRY entry;
-   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
-   TRACE("handles used %i\n",gpsi->cHandleEntries);
+   TRACE("handles used %lu\n", gpsi->cHandleEntries);
 
    if (ht->freelist)
    {
@@ -105,13 +331,12 @@ __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
       ht->freelist = entry->ptr;
 
       gpsi->cHandleEntries++;
-      ppi->UserHandleCount++;
       return entry;
    }
 
    if (ht->nb_handles >= ht->allocated_handles)  /* Need to grow the array */
    {
-       ERR("Out of user handles! Used -> %i, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles);
+       ERR("Out of user handles! Used -> %lu, NM_Handle -> %d\n", gpsi->cHandleEntries, ht->nb_handles);
 
 #if DBG
        DbgUserDumpHandleTable();
@@ -137,7 +362,6 @@ __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
    entry->generation = 1;
 
    gpsi->cHandleEntries++;
-   ppi->UserHandleCount++;
 
    return entry;
 }
@@ -151,13 +375,33 @@ VOID UserInitHandleTable(PUSER_HANDLE_TABLE ht, PVOID mem, ULONG bytes)
    ht->allocated_handles = bytes / sizeof(USER_HANDLE_ENTRY);
 }
 
+
 __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY entry)
 {
-   PPROCESSINFO ppi = PsGetCurrentProcessWin32Process();
    void *ret;
 
 #if DBG
-   ppi->DbgHandleCount[entry->type]--;
+   {
+       PPROCESSINFO ppi;
+       switch (entry->type)
+       {
+           case TYPE_WINDOW:
+           case TYPE_HOOK:
+           case TYPE_WINEVENTHOOK:
+               ppi = ((PTHREADINFO)entry->pi)->ppi;
+               break;
+           case TYPE_MENU:
+           case TYPE_CURSOR:
+           case TYPE_CALLPROC:
+           case TYPE_ACCELTABLE:
+               ppi = entry->pi;
+               break;
+           default:
+               ppi = NULL;
+       }
+       if (ppi)
+           ppi->DbgHandleCount[entry->type]--;
+   }
 #endif
 
    ret = entry->ptr;
@@ -168,46 +412,16 @@ __inline static void *free_user_entry(PUSER_HANDLE_TABLE ht, PUSER_HANDLE_ENTRY
    ht->freelist  = entry;
 
    gpsi->cHandleEntries--;
-   ppi->UserHandleCount--;
 
    return ret;
 }
 
-static __inline PVOID
-UserHandleOwnerByType(USER_OBJECT_TYPE type)
-{
-    PVOID pi;
-
-    switch (type)
-    {
-        case otWindow:
-        case otInputContext:
-            pi = GetW32ThreadInfo();
-            break;
-
-        case otMenu:
-        case otCursorIcon:
-        case otHook:
-        case otCallProc:
-        case otAccel:
-        case otSMWP:
-            pi = GetW32ProcessInfo();
-            break;
-
-        case otMonitor:
-            pi = NULL; /* System */
-            break;
-
-        default:
-            pi = NULL;
-            break;
-    }
-
-    return pi;
-}
-
 /* allocate a user handle for a given object */
-HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE type )
+HANDLE UserAllocHandle(
+    _Inout_ PUSER_HANDLE_TABLE ht,
+    _In_ PVOID object,
+    _In_ HANDLE_TYPE type,
+    _In_ PVOID HandleOwner)
 {
    PUSER_HANDLE_ENTRY entry = alloc_user_entry(ht);
    if (!entry)
@@ -215,7 +429,7 @@ HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE typ
    entry->ptr  = object;
    entry->type = type;
    entry->flags = 0;
-   entry->pi = UserHandleOwnerByType(type);
+   entry->pi = HandleOwner;
    if (++entry->generation >= 0xffff)
       entry->generation = 1;
 
@@ -226,7 +440,7 @@ HANDLE UserAllocHandle(PUSER_HANDLE_TABLE ht, PVOID object, USER_OBJECT_TYPE typ
 }
 
 /* return a pointer to a user object from its handle without setting an error */
-PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type )
+PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type )
 {
    PUSER_HANDLE_ENTRY entry;
 
@@ -240,7 +454,7 @@ PVOID UserGetObjectNoErr(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE
 }
 
 /* return a pointer to a user object from its handle */
-PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, USER_OBJECT_TYPE type )
+PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type )
 {
    PUSER_HANDLE_ENTRY entry;
 
@@ -269,7 +483,7 @@ HANDLE get_user_full_handle(PUSER_HANDLE_TABLE ht,  HANDLE handle )
 
 
 /* Same as get_user_object plus set the handle to the full 32-bit value */
-void *get_user_object_handle(PUSER_HANDLE_TABLE ht,  HANDLE* handle, USER_OBJECT_TYPE type )
+void *get_user_object_handle(PUSER_HANDLE_TABLE ht,  HANDLE* handle, HANDLE_TYPE type )
 {
    PUSER_HANDLE_ENTRY entry;
 
@@ -317,87 +531,46 @@ UserCreateObject( PUSER_HANDLE_TABLE ht,
                   PDESKTOP pDesktop,
                   PTHREADINFO pti,
                   HANDLE* h,
-                  USER_OBJECT_TYPE type,
+                  HANDLE_TYPE type,
                   ULONG size)
 {
    HANDLE hi;
    PVOID Object;
-   PPROCESSINFO ppi;
-   BOOL dt;
-   PDESKTOP rpdesk = pDesktop;
+   PVOID ObjectOwner;
 
-   /* We could get the desktop for the new object from the pti however this is 
-    * not always the case for example when creating a new desktop window for 
-    * the desktop thread*/
+   /* Some sanity checks. Other checks will be made in the allocator */
+   ASSERT(type < TYPE_CTYPES);
+   ASSERT(type != TYPE_FREE);
+   ASSERT(ht != NULL);
 
-   if (!pti) pti = GetW32ThreadInfo();
-   if (!pDesktop) rpdesk = pti->rpdesk;
-   ppi = pti->ppi;
-
-   switch (type)
+   /* Allocate the object */
+   ASSERT(ObjectCallbacks[type].ObjectAlloc != NULL);
+   Object = ObjectCallbacks[type].ObjectAlloc(pDesktop, pti, size, &ObjectOwner);
+   if (!Object)
    {
-      case otWindow:
-//      case otMenu:
-      case otHook:
-      case otCallProc:
-      case otInputContext:
-         Object = DesktopHeapAlloc(rpdesk, size);
-         dt = TRUE;
-         break;
-
-      default:
-         Object = UserHeapAlloc(size);
-         dt = FALSE;
-         break;
+       ERR("User object allocation failed. Out of memory!\n");
+       return NULL;
    }
 
-   if (!Object)
-      return NULL;
-
-
-   hi = UserAllocHandle(ht, Object, type );
-   if (!hi)
+   hi = UserAllocHandle(ht, Object, type, ObjectOwner);
+   if (hi == NULL)
    {
-      if (dt)
-         DesktopHeapFree(rpdesk, Object);
-      else
-         UserHeapFree(Object);
-      return NULL;
+       ERR("Out of user handles!\n");
+       ObjectCallbacks[type].ObjectFree(Object);
+       return NULL;
    }
 
 #if DBG
-   ppi->DbgHandleCount[type]++;
+   if (pti)
+       pti->ppi->DbgHandleCount[type]++;
 #endif
 
-   RtlZeroMemory(Object, size);
-
-   switch (type)
-   {
-        case otWindow:
-        case otHook:
-        case otInputContext:
-            ((PTHRDESKHEAD)Object)->rpdesk = rpdesk;
-            ((PTHRDESKHEAD)Object)->pSelf = Object;
-        case otEvent:
-            ((PTHROBJHEAD)Object)->pti = pti;
-            break;
-
-        case otMenu:
-        case otCallProc:
-            ((PPROCDESKHEAD)Object)->rpdesk = rpdesk;
-            ((PPROCDESKHEAD)Object)->pSelf = Object;
-            break;
-
-        case otCursorIcon:
-            ((PPROCMARKHEAD)Object)->ppi = ppi;
-            break;
-
-        default:
-            break;
-   }
-   /* Now set default headers. */
+   /* Give this object its identity. */
    ((PHEAD)Object)->h = hi;
-   ((PHEAD)Object)->cLockObj = 2; // We need this, because we create 2 refs: handle and pointer!
+
+   /* The caller will get a locked object.
+    * Note: with the reference from the handle, that makes two */
+   UserReferenceObject(Object);
 
    if (h)
       *h = hi;
@@ -407,46 +580,43 @@ UserCreateObject( PUSER_HANDLE_TABLE ht,
 
 BOOL
 FASTCALL
-UserDereferenceObject(PVOID object)
+UserDereferenceObject(PVOID Object)
 {
-  PUSER_HANDLE_ENTRY entry;
-  USER_OBJECT_TYPE type;
+    PHEAD ObjHead = (PHEAD)Object;
 
-  ASSERT(((PHEAD)object)->cLockObj >= 1);
+    ASSERT(ObjHead->cLockObj >= 1);
 
-  if ((INT)--((PHEAD)object)->cLockObj <= 0)
-  {
-     entry = handle_to_entry(gHandleTable, ((PHEAD)object)->h );
+    if (--ObjHead->cLockObj == 0)
+    {
+        PUSER_HANDLE_ENTRY entry;
+        HANDLE_TYPE type;
 
-     if (!entry)
-     {
-        ERR("Warning! Dereference Object without ENTRY! Obj -> 0x%x\n", object);
-        return FALSE;
-     }
-     TRACE("Warning! Dereference to zero! Obj -> 0x%x\n", object);
+        entry = handle_to_entry(gHandleTable, ObjHead->h);
 
-     ((PHEAD)object)->cLockObj = 0;
+        ASSERT(entry != NULL);
+        /* The entry should be marked as in deletion */
+        ASSERT(entry->flags & HANDLEENTRY_INDESTROY);
 
-     if (!(entry->flags & HANDLEENTRY_INDESTROY))
-        return TRUE;
+        type = entry->type;
+        ASSERT(type != TYPE_FREE);
+        ASSERT(type < TYPE_CTYPES);
 
-     type = entry->type;
-     free_user_entry(gHandleTable, entry );
+        /* We can now get rid of everything */
+        free_user_entry(gHandleTable, entry );
 
-     switch (type)
-     {
-        case otWindow:
-//        case otMenu:
-        case otHook:
-        case otCallProc:
-        case otInputContext:
-           return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
+#if 0
+        /* Call the object destructor */
+        ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL);
+        ObjectCallbacks[type].ObjectCleanup(Object);
+#endif
 
-        default:
-           return UserHeapFree(object);
-     }
-  }
-  return FALSE;
+        /* And free it */
+        ASSERT(ObjectCallbacks[type].ObjectFree != NULL);
+        ObjectCallbacks[type].ObjectFree(Object);
+
+        return TRUE;
+    }
+    return FALSE;
 }
 
 BOOL
@@ -475,14 +645,14 @@ UserObjectInDestroy(HANDLE h)
   if (!(entry = handle_to_entry( gHandleTable, h )))
   {
      SetLastNtError( STATUS_INVALID_HANDLE );
-     return FALSE;
+     return TRUE;
   }
   return (entry->flags & HANDLEENTRY_INDESTROY);
 }
 
 BOOL
 FASTCALL
-UserDeleteObject(HANDLE h, USER_OBJECT_TYPE type )
+UserDeleteObject(HANDLE h, HANDLE_TYPE type )
 {
    PVOID body = UserGetObject(gHandleTable, h, type);
 
@@ -504,7 +674,7 @@ UserReferenceObject(PVOID obj)
 
 PVOID
 FASTCALL
-UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
+UserReferenceObjectByHandle(HANDLE handle, HANDLE_TYPE type)
 {
     PVOID object;
 
@@ -518,18 +688,18 @@ UserReferenceObjectByHandle(HANDLE handle, USER_OBJECT_TYPE type)
 
 VOID
 FASTCALL
-UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner)
+UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner)
 {
     PUSER_HANDLE_ENTRY entry = handle_to_entry(gHandleTable, ((PHEAD)obj)->h );
     PPROCESSINFO ppi, oldppi;
-    
+
     /* This must be called with a valid object */
     ASSERT(entry);
-    
+
     /* For now, only supported for CursorIcon object */
     switch(type)
     {
-        case otCursorIcon:
+        case TYPE_CURSOR:
             ppi = (PPROCESSINFO)owner;
             entry->pi = ppi;
             oldppi = ((PPROCMARKHEAD)obj)->ppi;
@@ -540,16 +710,61 @@ UserSetObjectOwner(PVOID obj, USER_OBJECT_TYPE type, PVOID owner)
             return;
     }
 
-    oldppi->UserHandleCount--;
-    ppi->UserHandleCount++;
 #if DBG
     oldppi->DbgHandleCount[type]--;
     ppi->DbgHandleCount[type]++;
 #endif
+
+    oldppi->UserHandleCount--;
+    IntDereferenceProcessInfo(oldppi);
+    ppi->UserHandleCount++;
+    IntReferenceProcessInfo(ppi);
 }
 
+BOOLEAN
+UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
+{
+    int i;
+    PUSER_HANDLE_ENTRY Entry;
+    BOOLEAN Ret = TRUE;
+
+    /* Sweep the whole handle table */
+    for (i = 0; i < Table->allocated_handles; i++)
+    {
+        Entry = &Table->handles[i];
+
+        if (Entry->pi != Owner)
+            continue;
+
+        /* Do not destroy if it's already been done */
+        if (Entry->flags & HANDLEENTRY_INDESTROY)
+            continue;
+
+        /* Spcial case for cursors until cursoricon_new is there */
+        if (Entry->type == TYPE_CURSOR)
+        {
+            UserReferenceObject(Entry->ptr);
+            if (!IntDestroyCurIconObject(Entry->ptr, Owner))
+            {
+                Ret = FALSE;
+            }
+            continue;
+        }
+
+        /* Call destructor */
+        if (!ObjectCallbacks[Entry->type].ObjectDestroy(Entry->ptr))
+        {
+            ERR("Failed destructing object %p, type %u.\n", Entry->ptr, Entry->type);
+            /* Don't return immediately, we must continue destroying the other objects */
+            Ret = FALSE;
+        }
+    }
+
+    return Ret;
+}
+      
 /*
- * NtUserValidateHandleSecure
+ * NtUserValidateHandleSecure W2k3 has one argument.
  *
  * Status
  *    @implemented
@@ -561,62 +776,46 @@ NtUserValidateHandleSecure(
    HANDLE handle,
    BOOL Restricted)
 {
-   if(!Restricted)
+   UINT uType;
+   PPROCESSINFO ppi;
+   PUSER_HANDLE_ENTRY entry;
+
+   DECLARE_RETURN(BOOL);
+   UserEnterExclusive();
+
+   if (!(entry = handle_to_entry(gHandleTable, handle )))
    {
-     UINT uType;
-     {
-       PUSER_HANDLE_ENTRY entry;
-       if (!(entry = handle_to_entry(gHandleTable, handle )))
-       {
-          EngSetLastError(ERROR_INVALID_HANDLE);
-          return FALSE;
-       }
-       uType = entry->type;
-     }
-     switch (uType)
-     {
-       case otWindow:
-       {
-         if (UserGetWindowObject((HWND) handle)) return TRUE;
-         return FALSE;
-       }
-       case otMenu:
-       {
-         if (UserGetMenuObject((HMENU) handle)) return TRUE;
-         return FALSE;
-       }
-       case otAccel:
-       {
-         if (UserGetAccelObject((HACCEL) handle)) return TRUE;
-         return FALSE;
-       }
-       case otCursorIcon:
-       {
-         if (UserGetCurIconObject((HCURSOR) handle)) return TRUE;
-         return FALSE;
-       }
-       case otHook:
-       {
-         if (IntGetHookObject((HHOOK) handle)) return TRUE;
-         return FALSE;
-       }
-       case otMonitor:
-       {
-         if (UserGetMonitorObject((HMONITOR) handle)) return TRUE;
-         return FALSE;
-       }
-       case otCallProc:
-       {
-         WNDPROC_INFO Proc;
-         return UserGetCallProcInfo( handle, &Proc );
-       }
-       default:
-         EngSetLastError(ERROR_INVALID_HANDLE);
-     }
+      EngSetLastError(ERROR_INVALID_HANDLE);
+      RETURN( FALSE);
    }
-   else
-   { /* Is handle entry restricted? */
-     STUB
+   uType = entry->type;
+   switch (uType)
+   {
+       case TYPE_WINDOW:
+       case TYPE_INPUTCONTEXT:
+          ppi = ((PTHREADINFO)entry->pi)->ppi;
+          break;
+       case TYPE_MENU:
+       case TYPE_ACCELTABLE:
+       case TYPE_CURSOR:
+       case TYPE_HOOK:
+       case TYPE_CALLPROC:
+       case TYPE_SETWINDOWPOS:
+          ppi = entry->pi;
+          break;
+       default:
+          ppi = NULL;
+          break;
    }
-   return FALSE;
+
+   if (!ppi) RETURN( FALSE);
+
+   // Same process job returns TRUE.
+   if (gptiCurrent->ppi->pW32Job == ppi->pW32Job) RETURN( TRUE);
+
+   RETURN( FALSE);
+
+CLEANUP:
+   UserLeave();
+   END_CLEANUP;
 }