[WIN32K]
authorJérôme Gardou <jerome.gardou@reactos.org>
Sun, 21 Sep 2014 17:44:40 +0000 (17:44 +0000)
committerJérôme Gardou <jerome.gardou@reactos.org>
Sun, 21 Sep 2014 17:44:40 +0000 (17:44 +0000)
 - Introduce the base of what should become a proper user object manager, with proper refcounting, handle management, cleanup callbacks and inter-object referencing.
Approved by Jim and Giannis.
CORE-8539 #resolve

svn path=/trunk/; revision=64219

21 files changed:
reactos/win32ss/include/ntuser.h
reactos/win32ss/user/ntuser/accelerator.c
reactos/win32ss/user/ntuser/accelerator.h
reactos/win32ss/user/ntuser/callproc.c
reactos/win32ss/user/ntuser/class.c
reactos/win32ss/user/ntuser/class.h
reactos/win32ss/user/ntuser/cursoricon.c
reactos/win32ss/user/ntuser/cursoricon.h
reactos/win32ss/user/ntuser/event.c
reactos/win32ss/user/ntuser/hook.c
reactos/win32ss/user/ntuser/hook.h
reactos/win32ss/user/ntuser/main.c
reactos/win32ss/user/ntuser/menu.c
reactos/win32ss/user/ntuser/menu.h
reactos/win32ss/user/ntuser/object.c
reactos/win32ss/user/ntuser/object.h
reactos/win32ss/user/ntuser/simplecall.c
reactos/win32ss/user/ntuser/userfuncs.h
reactos/win32ss/user/ntuser/win32.h
reactos/win32ss/user/ntuser/window.c
reactos/win32ss/user/user32/misc/misc.c

index 3a80945..be60358 100644 (file)
@@ -172,7 +172,7 @@ typedef struct _THRDESKHEAD
 typedef struct _PROCDESKHEAD
 {
   HEAD;
-  DWORD hTaskWow;
+  DWORD_PTR hTaskWow;
   struct _DESKTOP *rpdesk;
   PVOID       pSelf;
 } PROCDESKHEAD, *PPROCDESKHEAD;
index 7777c50..2723e7b 100644 (file)
@@ -235,6 +235,7 @@ NtUserCreateAcceleratorTable(
     ULONG Index;
     NTSTATUS Status = STATUS_SUCCESS;
     DECLARE_RETURN(HACCEL);
+    PTHREADINFO pti;
 
     TRACE("Enter NtUserCreateAcceleratorTable(Entries %p, EntriesCount %u)\n",
           Entries, EntriesCount);
@@ -246,7 +247,14 @@ NtUserCreateAcceleratorTable(
         RETURN( (HACCEL) NULL );
     }
 
-    Accel = UserCreateObject(gHandleTable, NULL, NULL, (PHANDLE)&hAccel, TYPE_ACCELTABLE, sizeof(ACCELERATOR_TABLE));
+    pti = PsGetCurrentThreadWin32Thread();
+
+    Accel = UserCreateObject(gHandleTable,
+        pti->rpdesk,
+        pti,
+        (PHANDLE)&hAccel,
+        TYPE_ACCELTABLE,
+        sizeof(ACCELERATOR_TABLE));
 
     if (Accel == NULL)
     {
@@ -313,6 +321,21 @@ CLEANUP:
     END_CLEANUP;
 }
 
+BOOLEAN
+UserDestroyAccelTable(PVOID Object)
+{
+    PACCELERATOR_TABLE Accel = Object;
+
+    if (Accel->Table != NULL)
+    {
+        ExFreePoolWithTag(Accel->Table, USERTAG_ACCEL);
+        Accel->Table = NULL;
+    }
+
+    UserDeleteObject(Accel->head.h, TYPE_ACCELTABLE);
+    return TRUE;
+}
+
 BOOLEAN
 APIENTRY
 NtUserDestroyAcceleratorTable(
@@ -334,13 +357,7 @@ NtUserDestroyAcceleratorTable(
         RETURN( FALSE);
     }
 
-    if (Accel->Table != NULL)
-    {
-        ExFreePoolWithTag(Accel->Table, USERTAG_ACCEL);
-        Accel->Table = NULL;
-    }
-
-    UserDeleteObject(hAccel, TYPE_ACCELTABLE);
+    UserDestroyAccelTable(Accel);
 
     RETURN( TRUE);
 
index 4bd8807..cbe5c37 100644 (file)
@@ -2,9 +2,11 @@
 
 typedef struct _ACCELERATOR_TABLE
 {
-  HEAD head;
+  PROCMARKHEAD head;
   ULONG Count;
   LPACCEL Table;
 } ACCELERATOR_TABLE, *PACCELERATOR_TABLE;
 
 PACCELERATOR_TABLE FASTCALL UserGetAccelObject(HACCEL);
+BOOLEAN
+UserDestroyAccelTable(PVOID Object);
index a1b6356..970f7b2 100644 (file)
@@ -17,11 +17,11 @@ GetCallProcHandle(IN PCALLPROCDATA CallProc)
     return (WNDPROC)((ULONG_PTR)UserHMGetHandle(CallProc) | 0xFFFF0000);
 }
 
-VOID
-DestroyCallProc(IN PDESKTOPINFO Desktop,
-                IN OUT PCALLPROCDATA CallProc)
+BOOLEAN
+DestroyCallProc(_Inout_ PVOID Object)
 {
-    UserDeleteObject(UserHMGetHandle(CallProc), TYPE_CALLPROC);
+    UserDeleteObject(UserHMGetHandle((PCALLPROCDATA)Object), TYPE_CALLPROC);
+    return TRUE;
 }
 
 PCALLPROCDATA
@@ -33,9 +33,11 @@ CreateCallProc(IN PDESKTOP Desktop,
     PCALLPROCDATA NewCallProc;
     HANDLE Handle;
 
+    /* We can send any thread pointer to the object manager here,
+     * What's important is the process info */
     NewCallProc = (PCALLPROCDATA)UserCreateObject(gHandleTable,
                                              Desktop,
-                                             NULL,
+                                             pi->ptiList,
                                              &Handle,
                                              TYPE_CALLPROC,
                                              sizeof(CALLPROCDATA));
@@ -129,7 +131,7 @@ UserGetCPD(
    // No luck, create a new one for the requested proc.
    if (!CallProc)
    {
-      CallProc = CreateCallProc( NULL,
+      CallProc = CreateCallProc( pCls->rpdeskParent,
                                  (WNDPROC)ProcIn,
                                  !!(Flags & UserGetCPDA2U),
                                  pti->ppi);
index 5852104..f14071e 100644 (file)
@@ -224,8 +224,7 @@ IntDestroyClass(IN OUT PCLS Class)
             NextCallProc = CallProc->spcpdNext;
 
             CallProc->spcpdNext = NULL;
-            DestroyCallProc(NULL,
-                            CallProc);
+            DestroyCallProc(CallProc);
 
             CallProc = NextCallProc;
         }
index 8b82929..0c66ae9 100644 (file)
@@ -16,9 +16,8 @@ IsCallProcHandle(IN WNDPROC lpWndProc)
     return ((ULONG_PTR)lpWndProc & 0xFFFF0000) == 0xFFFF0000;
 }
 
-VOID
-DestroyCallProc(IN PDESKTOPINFO Desktop,
-                IN OUT PCALLPROCDATA CallProc);
+BOOLEAN
+DestroyCallProc(_Inout_ PVOID Object);
 
 PCALLPROCDATA
 CreateCallProc(IN PDESKTOP Desktop,
index 335aa87..c8f89cf 100644 (file)
@@ -209,7 +209,13 @@ IntCreateCurIconHandle(BOOLEAN Anim)
     PCURICON_OBJECT CurIcon;
     HANDLE hCurIcon;
 
-    CurIcon = UserCreateObject(gHandleTable, NULL, NULL, &hCurIcon, TYPE_CURSOR, sizeof(CURICON_OBJECT));
+    CurIcon = UserCreateObject(
+        gHandleTable,
+        NULL,
+        GetW32ThreadInfo(),
+        &hCurIcon,
+        TYPE_CURSOR,
+        sizeof(CURICON_OBJECT));
 
     if (!CurIcon)
     {
@@ -317,19 +323,6 @@ emptyList:
     return Ret;
 }
 
-VOID FASTCALL
-IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
-{
-    PCURICON_OBJECT CurIcon, tmp;
-
-    /* Run through the list of icon objects */
-    LIST_FOR_EACH_SAFE(CurIcon, tmp, &gCurIconList, CURICON_OBJECT, ListEntry)
-    {
-        UserReferenceObject(CurIcon);
-        IntDestroyCurIconObject(CurIcon, Win32Process);
-    }
-}
-
 HCURSOR FASTCALL
 IntSetCursor(
     HCURSOR hCursor)
index a6d842c..c6b998a 100644 (file)
@@ -105,7 +105,6 @@ typedef struct _SYSTEM_CURSORINFO
 
 BOOL InitCursorImpl(VOID);
 HANDLE IntCreateCurIconHandle(BOOLEAN Anim);
-VOID FASTCALL IntCleanupCurIcons(struct _EPROCESS *Process, PPROCESSINFO Win32Process);
 
 BOOL UserDrawIconEx(HDC hDc, INT xLeft, INT yTop, PCURICON_OBJECT pIcon, INT cxWidth,
    INT cyHeight, UINT istepIfAniCur, HBRUSH hbrFlickerFreeDraw, UINT diFlags);
@@ -115,6 +114,7 @@ BOOL APIENTRY UserClipCursor(RECTL *prcl);
 PSYSTEM_CURSORINFO IntGetSysCursorInfo(VOID);
 HCURSOR FASTCALL IntSetCursor(HCURSOR hCursor);
 BOOL FASTCALL IntDestroyCursor(HANDLE hCurIcon, BOOL bForce);
+BOOLEAN FASTCALL IntDestroyCurIconObject(PCURICON_OBJECT CurIcon, PPROCESSINFO ppi);
 
 #define IntReleaseCurIconObject(CurIconObj) \
   UserDereferenceObject(CurIconObj)
index 0fe5a10..b944f08 100644 (file)
@@ -129,11 +129,10 @@ IntCallLowLevelEvent( PEVENTHOOK pEH,
    return NT_SUCCESS(Status) ? uResult : 0;
 }
 
-static
-BOOL
-FASTCALL
-IntRemoveEvent(PEVENTHOOK pEH)
+BOOLEAN
+IntRemoveEvent(PVOID Object)
 {
+   PEVENTHOOK pEH = Object;
    if (pEH)
    {
       TRACE("IntRemoveEvent pEH %p\n", pEH);
@@ -148,38 +147,6 @@ IntRemoveEvent(PEVENTHOOK pEH)
    return FALSE;
 }
 
-VOID
-FASTCALL
-EVENT_DestroyThreadEvents(PETHREAD Thread)
-{
-   PTHREADINFO pti;
-   PEVENTHOOK pEH;
-   PLIST_ENTRY pLE;
-
-   pti = Thread->Tcb.Win32Thread;
-   if (!pti) return;
-
-   if (!GlobalEvents || !GlobalEvents->Counts) return;
-
-   pLE = GlobalEvents->Events.Flink;
-   if (IsListEmpty(pLE)) return;
-
-   pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
-   do
-   {
-      if (IsListEmpty(pLE)) break;
-      if (!pEH) break;
-      pLE = pEH->Chain.Flink;
-      if (pEH->head.pti == pti)
-      {
-         IntRemoveEvent(pEH);
-      }
-      pEH = CONTAINING_RECORD(pLE, EVENTHOOK, Chain);
-   } while (pLE != &GlobalEvents->Events);
-
-   return;
-}
-
 /* FUNCTIONS *****************************************************************/
 
 //
@@ -332,7 +299,7 @@ NtUserSetWinEventHook(
    HWINEVENTHOOK Ret = NULL;
    NTSTATUS Status;
    HANDLE Handle;
-   PETHREAD Thread = NULL;
+   PTHREADINFO pti;
 
    TRACE("NtUserSetWinEventHook hmod %p, pfn %p\n", hmodWinEventProc, lpfnWinEventProc);
 
@@ -370,15 +337,22 @@ NtUserSetWinEventHook(
 
    if (idThread)
    {
+      PETHREAD Thread;
       Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread);
       if (!NT_SUCCESS(Status))
       {   
          EngSetLastError(ERROR_INVALID_THREAD_ID);
          goto SetEventExit;
       }
+      pti = PsGetThreadWin32Thread(Thread);
+      ObDereferenceObject(Thread);
+   }
+   else
+   {
+       pti = PsGetCurrentThreadWin32Thread();
    }
    // Creator, pti is set here.
-   pEH = UserCreateObject(gHandleTable, NULL, NULL, &Handle, TYPE_WINEVENTHOOK, sizeof(EVENTHOOK));
+   pEH = UserCreateObject(gHandleTable, NULL, pti, &Handle, TYPE_WINEVENTHOOK, sizeof(EVENTHOOK));
    if (pEH)
    {
       InsertTailList(&GlobalEvents->Events, &pEH->Chain);
@@ -413,7 +387,6 @@ NtUserSetWinEventHook(
    }
 
 SetEventExit:
-   if (Thread) ObDereferenceObject(Thread);
    UserLeave();
    return Ret;
 }
index 984d32e..3e6e942 100644 (file)
@@ -1028,14 +1028,13 @@ IntFreeHook(PHOOK Hook)
 }
 
 /* Remove a hook, freeing it from the chain */
-static
-VOID
-FASTCALL
-IntRemoveHook(PHOOK Hook)
+BOOLEAN
+IntRemoveHook(PVOID Object)
 {
     INT HookId;
     PTHREADINFO pti;
     PDESKTOP pdo;
+    PHOOK Hook = Object;
 
     HookId = Hook->HookId;
 
@@ -1073,65 +1072,8 @@ IntRemoveHook(PHOOK Hook)
           pdo->pDeskInfo->fsHooks &= ~HOOKID_TO_FLAG(HookId);
        }
     }
-}
 
-VOID
-FASTCALL
-HOOK_DestroyThreadHooks(PETHREAD Thread)
-{
-   PTHREADINFO pti;
-   PDESKTOP pdo;
-   int HookId;
-   PHOOK HookObj;
-   PLIST_ENTRY pElem;
-
-   pti = Thread->Tcb.Win32Thread;
-   pdo = IntGetActiveDesktop();
-
-   if (!pti || !pdo)
-   {
-      ERR("Kill Thread Hooks pti %p pdo %p\n", pti, pdo);
-      return;
-   }
-
-// Local Thread cleanup.
-   if (pti->fsHooks)
-   {
-      for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
-      {
-         PLIST_ENTRY pLastHead = &pti->aphkStart[HOOKID_TO_INDEX(HookId)];
-
-         pElem = pLastHead->Flink;
-         while (pElem != pLastHead)
-         {
-            HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
-            pElem = HookObj->Chain.Flink; // get next element before hook is destroyed
-            IntRemoveHook(HookObj);
-         }
-      }
-      pti->fsHooks = 0;
-      pti->pClientInfo->fsHooks = 0;
-   }
-// Global search based on Thread and cleanup.
-   if (pdo->pDeskInfo->fsHooks)
-   {
-      for (HookId = WH_MINHOOK; HookId <= WH_MAXHOOK; HookId++)
-      {
-         PLIST_ENTRY pGLE = &pdo->pDeskInfo->aphkStart[HOOKID_TO_INDEX(HookId)];
-
-         pElem = pGLE->Flink;
-         while (pElem != pGLE)
-         {
-            HookObj = CONTAINING_RECORD(pElem, HOOK, Chain);
-            pElem = HookObj->Chain.Flink; // Get next element before hook is destroyed
-            if (HookObj->head.pti == pti)
-            {
-               IntRemoveHook(HookObj);
-            }
-         }
-      }
-   }
-   return;
+    return TRUE;
 }
 
 /*
@@ -1576,7 +1518,7 @@ NtUserSetWindowsHookEx( HINSTANCE Mod,
     }
     ObDereferenceObject(WinStaObj);
 
-    Hook = UserCreateObject(gHandleTable, NULL, NULL, (PHANDLE)&Handle, TYPE_HOOK, sizeof(HOOK));
+    Hook = UserCreateObject(gHandleTable, NULL, ptiHook, (PHANDLE)&Handle, TYPE_HOOK, sizeof(HOOK));
 
     if (!Hook)
     {
index 146bd08..f3f1f80 100644 (file)
@@ -43,12 +43,12 @@ typedef struct _NOTIFYEVENT
 LRESULT FASTCALL co_CallHook(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam);
 LRESULT FASTCALL co_EVENT_CallEvents(DWORD, HWND, UINT_PTR, LONG_PTR);
-VOID FASTCALL HOOK_DestroyThreadHooks(PETHREAD Thread);
-VOID FASTCALL EVENT_DestroyThreadEvents(PETHREAD Thread);
 PHOOK FASTCALL IntGetHookObject(HHOOK);
 PHOOK FASTCALL IntGetNextHook(PHOOK Hook);
 LRESULT FASTCALL UserCallNextHookEx( PHOOK pHook, int Code, WPARAM wParam, LPARAM lParam, BOOL Ansi);
 BOOL FASTCALL IntUnhookWindowsHook(int,HOOKPROC);
+BOOLEAN IntRemoveHook(PVOID Object);
+BOOLEAN IntRemoveEvent(PVOID Object);
 
 BOOL FASTCALL UserLoadApiHook(VOID);
 BOOL IntLoadHookModule(int iHookID, HHOOK hHook, BOOL Unload);
index 905fa04..c668bbb 100644 (file)
@@ -51,207 +51,247 @@ DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
 }
 #endif
 
+static
 NTSTATUS
-APIENTRY
-Win32kProcessCallback(struct _EPROCESS *Process,
-                      BOOLEAN Create)
+CreateProcessInfo(PEPROCESS Process)
 {
-    PPROCESSINFO ppiCurrent, *pppi;
+    PPROCESSINFO ppiCurrent;
     NTSTATUS Status;
-
-    ASSERT(Process->Peb);
-
-    UserEnterExclusive();
-
-    if (Create)
+    SIZE_T ViewSize = 0;
+    LARGE_INTEGER Offset;
+    PVOID UserBase = NULL;
+    PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
+
+    /* We might be called with an already allocated win32 process */
+    ppiCurrent = PsGetProcessWin32Process(Process);
+    if (ppiCurrent != NULL)
     {
-        SIZE_T ViewSize = 0;
-        LARGE_INTEGER Offset;
-        PVOID UserBase = NULL;
-        PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
-
-        /* We might be called with an already allocated win32 process */
-        ppiCurrent = PsGetProcessWin32Process(Process);
-        if (ppiCurrent != NULL)
-        {
-            /* There is no more to do for us (this is a success code!) */
-            Status = STATUS_ALREADY_WIN32;
-            goto Leave;
-        }
+        /* There is no more to do for us (this is a success code!) */
+        return STATUS_ALREADY_WIN32;
+    }
 
-        /* Allocate a new win32 process */
-        ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
-                                           sizeof(PROCESSINFO),
-                                           USERTAG_PROCESSINFO);
-        if (ppiCurrent == NULL)
-        {
-            ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n",
-                   HandleToUlong(Process->UniqueProcessId));
-            Status = STATUS_NO_MEMORY;
-            goto Leave;
-        }
+    /* Allocate a new win32 process */
+    ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
+                                       sizeof(PROCESSINFO),
+                                       USERTAG_PROCESSINFO);
+    if (ppiCurrent == NULL)
+    {
+        ERR_CH(UserProcess, "Failed to allocate ppi for PID:0x%lx\n",
+               HandleToUlong(Process->UniqueProcessId));
+        return STATUS_NO_MEMORY;
+    }
 
-        RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
+    RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
 
-        PsSetProcessWin32Process(Process, ppiCurrent, NULL);
+    PsSetProcessWin32Process(Process, ppiCurrent, NULL);
 
 #if DBG
-        DbgInitDebugChannels();
+    DbgInitDebugChannels();
 #if KDBG
-        KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
+    KdRosRegisterCliCallback(DbgGdiKdbgCliCallback);
 #endif
 #endif
 
-        TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
-
-        /* map the global heap into the process */
-        Offset.QuadPart = 0;
-        Status = MmMapViewOfSection(GlobalUserHeapSection,
-                                    PsGetCurrentProcess(),
-                                    &UserBase,
-                                    0,
-                                    0,
-                                    &Offset,
-                                    &ViewSize,
-                                    ViewUnmap,
-                                    SEC_NO_CHANGE,
-                                    PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
-        if (!NT_SUCCESS(Status))
-        {
-            TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
-            goto Leave;
-        }
-        ppiCurrent->HeapMappings.Next = NULL;
-        ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
-        ppiCurrent->HeapMappings.UserMapping = UserBase;
-        ppiCurrent->HeapMappings.Count = 1;
+    TRACE_CH(UserProcess,"Allocated ppi 0x%p for PID:0x%lx\n", ppiCurrent, HandleToUlong(Process->UniqueProcessId));
+
+    /* map the global heap into the process */
+    Offset.QuadPart = 0;
+    Status = MmMapViewOfSection(GlobalUserHeapSection,
+                                PsGetCurrentProcess(),
+                                &UserBase,
+                                0,
+                                0,
+                                &Offset,
+                                &ViewSize,
+                                ViewUnmap,
+                                SEC_NO_CHANGE,
+                                PAGE_EXECUTE_READ); /* would prefer PAGE_READONLY, but thanks to RTL heaps... */
+    if (!NT_SUCCESS(Status))
+    {
+        TRACE_CH(UserProcess,"Failed to map the global heap! 0x%x\n", Status);
+        return Status;
+    }
+    ppiCurrent->HeapMappings.Next = NULL;
+    ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
+    ppiCurrent->HeapMappings.UserMapping = UserBase;
+    ppiCurrent->HeapMappings.Count = 1;
+
+    InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
+    InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
 
-        InitializeListHead(&ppiCurrent->MenuListHead);
+    InitializeListHead(&ppiCurrent->PrivateFontListHead);
+    ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
 
-        InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
-        InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
+    InitializeListHead(&ppiCurrent->DriverObjListHead);
+    ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
 
-        InitializeListHead(&ppiCurrent->PrivateFontListHead);
-        ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
+    ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
+    if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
+    {
+        KeBugCheck(0);
+    }
 
-        InitializeListHead(&ppiCurrent->DriverObjListHead);
-        ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
+    KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
 
-        ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
-        if (!EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent))
-        {
-            KeBugCheck(0);
-        }
 
-        KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
+    /* map the gdi handle table to user land */
+    Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
+    Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
+    pParams = Process->Peb->ProcessParameters;
 
+    ppiCurrent->peProcess = Process;
+    /* setup process flags */
+    ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
 
-        /* map the gdi handle table to user land */
-        Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
-        Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
-        pParams = Process->Peb->ProcessParameters;
+    if ( pParams &&
+         pParams->WindowFlags & STARTF_SCRNSAVER )
+    {
+       ppiScrnSaver = ppiCurrent;
+       ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
+    }
 
-        ppiCurrent->peProcess = Process;
-        /* setup process flags */
-        ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
+    // Fixme check if this process is allowed.
+    ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off.
 
-        if ( pParams &&
-             pParams->WindowFlags & STARTF_SCRNSAVER )
-        {
-           ppiScrnSaver = ppiCurrent;
-           ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
-        }
+    /* Create pools for GDI object attributes */
+    ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
+    ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
+    ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
+    ASSERT(ppiCurrent->pPoolDcAttr);
+    ASSERT(ppiCurrent->pPoolBrushAttr);
+    ASSERT(ppiCurrent->pPoolRgnAttr);
 
-        // Fixme check if this process is allowed.
-        ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off.
+    /* Add the process to the global list */
+    ppiCurrent->ppiNext = gppiList;
+    gppiList = ppiCurrent;
+    IntReferenceProcessInfo(ppiCurrent);
 
-        /* Create pools for GDI object attributes */
-        ppiCurrent->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
-        ppiCurrent->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
-        ppiCurrent->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
-        ASSERT(ppiCurrent->pPoolDcAttr);
-        ASSERT(ppiCurrent->pPoolBrushAttr);
-        ASSERT(ppiCurrent->pPoolRgnAttr);
+    return STATUS_SUCCESS;
+}
 
-        /* Add the process to the global list */
-        ppiCurrent->ppiNext = gppiList;
-        gppiList = ppiCurrent;
-    }
-    else
-    {
-        /* Get the Win32 Process */
-        ppiCurrent = PsGetProcessWin32Process(Process);
+static
+NTSTATUS
+DestroyProcessInfo(PEPROCESS Process)
+{
+    PPROCESSINFO ppiCurrent, *pppi;
 
-        ASSERT(ppiCurrent);
+    /* Get the Win32 Process */
+    ppiCurrent = PsGetProcessWin32Process(Process);
 
-        TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
-        ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
+    ASSERT(ppiCurrent);
 
-        if (ppiScrnSaver == ppiCurrent)
-            ppiScrnSaver = NULL;
+    TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent);
+    ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
 
-        if (ppiCurrent->InputIdleEvent)
-        {
-           EngFreeMem(ppiCurrent->InputIdleEvent);
-           ppiCurrent->InputIdleEvent = NULL;
-        }
+    if (ppiScrnSaver == ppiCurrent)
+        ppiScrnSaver = NULL;
 
-        IntCleanupMenus(Process, ppiCurrent);
-        IntCleanupCurIcons(Process, ppiCurrent);
+    /* Destroy user objects */
+    UserDestroyObjectsForOwner(gHandleTable, ppiCurrent);
 
+    TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
+#if DBG
+    if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
+    {
+        TRACE_CH(UserObj, "Dumping user handles at the end of the process %s (Info %p).\n",
+            ppiCurrent->peProcess->ImageFileName, ppiCurrent);
+        DbgUserDumpHandleTable();
+    }
+#endif
 
-        GDI_CleanupForProcess(Process);
+    /* And GDI ones too */
+    GDI_CleanupForProcess(Process);
 
-        co_IntGraphicsCheck(FALSE);
+    /* So we can now free the pools */
+    GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
+    GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
+    GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
 
-        /*
-         * Deregister logon application automatically
-         */
-        if(LogonProcess == ppiCurrent)
-        {
-            LogonProcess = NULL;
-        }
+    /* Remove it from the list of GUI apps */
+    co_IntGraphicsCheck(FALSE);
 
-        /* Close the startup desktop */
-        if(ppiCurrent->rpdeskStartup)
-            ObDereferenceObject(ppiCurrent->rpdeskStartup);
-        if(ppiCurrent->hdeskStartup)
-            ZwClose(ppiCurrent->hdeskStartup);
+    /*
+     * Deregister logon application automatically
+     */
+    if(LogonProcess == ppiCurrent)
+    {
+        LogonProcess = NULL;
+    }
+
+    /* Close the current window station */
+    UserSetProcessWindowStation(NULL);
+
+    if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
+
+    /* Remove it from the list */
+    pppi = &gppiList;
+    while (*pppi != NULL && *pppi != ppiCurrent)
+        pppi = &(*pppi)->ppiNext;
 
-        /* Close the current window station */
-        UserSetProcessWindowStation(NULL);
+    ASSERT(*pppi == ppiCurrent);
 
-        /* Destroy GDI pools */
-        GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
-        GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
-        GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
+    *pppi = ppiCurrent->ppiNext;
 
-        if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL;
+    if(ppiCurrent->hdeskStartup)
+    {
+        ZwClose(ppiCurrent->hdeskStartup);
+        ppiCurrent->hdeskStartup = NULL;
+    }
 
-        pppi = &gppiList;
-        while (*pppi != NULL && *pppi != ppiCurrent)
-            pppi = &(*pppi)->ppiNext;
+    /* The process is dying */
+    PsSetProcessWin32Process(Process, NULL, ppiCurrent);
+    ppiCurrent->peProcess = NULL;
 
-        ASSERT(*pppi == ppiCurrent);
+    /* At last, dereference */
+    IntDereferenceProcessInfo(ppiCurrent);
 
-        *pppi = ppiCurrent->ppiNext;
+    return STATUS_SUCCESS;
+}
+
+VOID
+UserDeleteW32Process(PPROCESSINFO ppiCurrent)
+{
+    if (ppiCurrent->InputIdleEvent)
+    {
+       EngDeleteEvent((PEVENT)ppiCurrent->InputIdleEvent);
+    }
+
+    /* Close the startup desktop */
+    if(ppiCurrent->rpdeskStartup)
+        ObDereferenceObject(ppiCurrent->rpdeskStartup);
 
-        TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent);
 #if DBG
-        if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
-        {
-            DbgUserDumpHandleTable();
-        }
+    if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL))
+    {
+        TRACE_PPI(ppiCurrent, UserObj, "Dumping user handles now that process info %p is gets freed.\n", ppiCurrent);
+        DbgUserDumpHandleTable();
+    }
 #endif
 
-        /* Free the PROCESSINFO */
-        PsSetProcessWin32Process(Process, NULL, ppiCurrent);
-        ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
-    }
+    /* Free the PROCESSINFO */
+    ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
+}
+
+NTSTATUS
+APIENTRY
+Win32kProcessCallback(struct _EPROCESS *Process,
+                      BOOLEAN Create)
+{
+    NTSTATUS Status;
+
+    ASSERT(Process->Peb);
+
+    UserEnterExclusive();
 
-    Status = STATUS_SUCCESS;
+    if (Create)
+    {
+        Status = CreateProcessInfo(Process);
+    }
+    else
+    {
+        Status = DestroyProcessInfo(Process);
+    }
 
-Leave:
     UserLeave();
     return Status;
 }
@@ -291,7 +331,8 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
     PsSetThreadWin32Thread(Thread, ptiCurrent, NULL);
     IntReferenceThreadInfo(ptiCurrent);
     ptiCurrent->pEThread = Thread;
-    ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
+    ptiCurrent->ppi = PsGetProcessWin32Process(Process);
+    IntReferenceProcessInfo(ptiCurrent->ppi);
     pTeb->Win32ThreadInfo = ptiCurrent;
     ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
 
@@ -317,6 +358,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
                             NULL, SynchronizationEvent, FALSE);
     if (!NT_SUCCESS(Status))
     {
+       ERR_CH(UserThread, "Event creation failed, Status 0x%08x.\n", Status);
        goto error;
     }
     Status = ObReferenceObjectByHandle(ptiCurrent->hEventQueueClient, 0,
@@ -324,6 +366,7 @@ UserCreateThreadInfo(struct _ETHREAD *Thread)
                                        (PVOID*)&ptiCurrent->pEventQueueServer, NULL);
     if (!NT_SUCCESS(Status))
     {
+       ERR_CH(UserThread, "Failed referencing the event object, Status 0x%08x.\n", Status);
        ZwClose(ptiCurrent->hEventQueueClient);
        ptiCurrent->hEventQueueClient = NULL;
        goto error;
@@ -451,29 +494,23 @@ error:
   Called from IntDereferenceThreadInfo.
  */
 VOID
-FASTCALL
 UserDeleteW32Thread(PTHREADINFO pti)
 {
-    if (!pti->RefCount)
-    {
-       TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
-       if (pti->hEventQueueClient != NULL)
-          ZwClose(pti->hEventQueueClient);
-       pti->hEventQueueClient = NULL;
+   PPROCESSINFO ppi = pti->ppi;
 
-       /* Free the message queue */
-       if (pti->MessageQueue)
-       {
-          MsqDestroyMessageQueue(pti);
-       }
+   TRACE_CH(UserThread,"UserDeleteW32Thread pti 0x%p\n",pti);
 
-       MsqCleanupThreadMsgs(pti);
+   /* Free the message queue */
+   if (pti->MessageQueue)
+   {
+      MsqDestroyMessageQueue(pti);
+   }
 
-       IntSetThreadDesktop(NULL, TRUE);
+   MsqCleanupThreadMsgs(pti);
 
-       PsSetThreadWin32Thread(pti->pEThread, NULL, pti);
-       ExFreePoolWithTag(pti, USERTAG_THREADINFO);
-    }
+   ExFreePoolWithTag(pti, USERTAG_THREADINFO);
+
+   IntDereferenceProcessInfo(ppi);
 }
 
 NTSTATUS
@@ -541,18 +578,16 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
         }
 
         DceFreeThreadDCE(ptiCurrent);
-        HOOK_DestroyThreadHooks(Thread);
-        EVENT_DestroyThreadEvents(Thread);
         DestroyTimersForThread(ptiCurrent);
         KeSetEvent(ptiCurrent->pEventQueueServer, IO_NO_INCREMENT, FALSE);
         UnregisterThreadHotKeys(ptiCurrent);
-/*
-        if (IsListEmpty(&ptiCurrent->WindowListHead))
+
+        if (!UserDestroyObjectsForOwner(gHandleTable, ptiCurrent))
         {
-           ERR_CH(UserThread,"Thread Window List is Empty!\n");
+            DPRINT1("Failed to delete objects belonging to thread %p. This is VERY BAD!.\n", ptiCurrent);
+            ASSERT(FALSE);
+            return STATUS_UNSUCCESSFUL;
         }
-*/
-        co_DestroyThreadWindows(Thread);
 
         if (ppiCurrent && ppiCurrent->ptiList == ptiCurrent && !ptiCurrent->ptiSibling &&
             ppiCurrent->W32PF_flags & W32PF_CLASSESREGISTERED)
@@ -614,6 +649,19 @@ UserDestroyThreadInfo(struct _ETHREAD *Thread)
 */
     TRACE_CH(UserThread,"Freeing pti 0x%p\n", ptiCurrent);
 
+    IntSetThreadDesktop(NULL, TRUE);
+
+    if (ptiCurrent->hEventQueueClient != NULL)
+    {
+       ZwClose(ptiCurrent->hEventQueueClient);
+       ObDereferenceObject(ptiCurrent->pEventQueueServer);
+    }
+    ptiCurrent->hEventQueueClient = NULL;
+
+    /* The thread is dying */
+    PsSetThreadWin32Thread(ptiCurrent->pEThread, NULL, ptiCurrent);
+    ptiCurrent->pEThread = NULL;
+
     /* Free the THREADINFO */
     IntDereferenceThreadInfo(ptiCurrent);
 
index 2fed7c1..9cd0917 100644 (file)
@@ -176,7 +176,7 @@ PMENU FASTCALL VerifyMenu(PMENU pMenu)
    return pMenu;
 }
 
-BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
+BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse)
 {
     PMENU SubMenu;
 
@@ -204,7 +204,7 @@ BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
            {
               /* Release submenu since it was referenced when inserted */
               IntReleaseMenuObject(SubMenu);
-              IntDestroyMenuObject(SubMenu, bRecurse, RemoveFromProcess);
+              IntDestroyMenuObject(SubMenu, bRecurse);
            }
        }
        /* Free the Item */
@@ -215,20 +215,22 @@ BOOL IntDestroyMenu( PMENU pMenu, BOOL bRecurse, BOOL RemoveFromProcess)
     return TRUE;
 }
 
+/* Callback for the object manager */
+BOOLEAN
+UserDestroyMenuObject(PVOID Object)
+{
+    return IntDestroyMenuObject(Object, TRUE);
+}
+
 BOOL FASTCALL
-IntDestroyMenuObject(PMENU Menu, BOOL bRecurse, BOOL RemoveFromProcess)
+IntDestroyMenuObject(PMENU Menu, BOOL bRecurse)
 {
    if(Menu)
    {
       PWND Window;
 
       /* Remove all menu items */
-      IntDestroyMenu( Menu, bRecurse, RemoveFromProcess);
-
-      if (RemoveFromProcess)
-      {
-         RemoveEntryList(&Menu->ListEntry);
-      }
+      IntDestroyMenu( Menu, bRecurse);
 
       if (PsGetCurrentProcessSessionId() == Menu->head.rpdesk->rpwinstaParent->dwSessionId)
       {
@@ -361,7 +363,7 @@ IntRemoveMenuItem( PMENU pMenu, UINT nPos, UINT wFlags, BOOL bRecurse )
     FreeMenuText(pMenu,item);
     if (bRecurse && item->spSubMenu)
     {
-       IntDestroyMenuObject(item->spSubMenu, bRecurse, TRUE);
+       IntDestroyMenuObject(item->spSubMenu, bRecurse);
     }
     ////// Use cAlloced with inc's of 8's....
     if (--pMenu->cItems == 0)
@@ -477,14 +479,17 @@ IntInsertMenuItem(
 }
 
 PMENU FASTCALL
-IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
+IntCreateMenu(
+    _Out_ PHANDLE Handle,
+    _In_ BOOL IsMenuBar,
+    _In_ PDESKTOP Desktop,
+    _In_ PPROCESSINFO ppi)
 {
    PMENU Menu;
-   PPROCESSINFO CurrentWin32Process;
 
    Menu = (PMENU)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
+                                          Desktop,
+                                          ppi->ptiList,
                                           Handle,
                                           TYPE_MENU,
                                           sizeof(MENU));
@@ -512,10 +517,6 @@ IntCreateMenu(PHANDLE Handle, BOOL IsMenuBar)
    Menu->hWnd = NULL;
    Menu->TimeToHide = FALSE;
 
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
-
    return Menu;
 }
 
@@ -572,19 +573,19 @@ IntCloneMenuItems(PMENU Destination, PMENU Source)
 PMENU FASTCALL
 IntCloneMenu(PMENU Source)
 {
-   PPROCESSINFO CurrentWin32Process;
    HANDLE hMenu;
    PMENU Menu;
 
    if(!Source)
       return NULL;
 
+   /* A menu is valid process wide. We can pass to the object manager any thread ptr */
    Menu = (PMENU)UserCreateObject( gHandleTable,
-                                          NULL,
-                                          NULL,
-                                          &hMenu,
-                                          TYPE_MENU,
-                                          sizeof(MENU));
+                                   Source->head.rpdesk,
+                                   ((PPROCESSINFO)Source->head.hTaskWow)->ptiList,
+                                   &hMenu,
+                                   TYPE_MENU,
+                                   sizeof(MENU));
    if(!Menu)
       return NULL;
 
@@ -606,10 +607,6 @@ IntCloneMenu(PMENU Source)
    Menu->hWnd = NULL;
    Menu->TimeToHide = FALSE;
 
-   /* Insert menu item into process menu handle list */
-   CurrentWin32Process = PsGetCurrentProcessWin32Process();
-   InsertTailList(&CurrentWin32Process->MenuListHead, &Menu->ListEntry);
-
    IntCloneMenuItems(Menu, Source);
 
    return Menu;
@@ -870,7 +867,10 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
             {
                HANDLE hMenu;
                ERR("Pop Up Menu Double Trouble!\n");
-               SubMenuObject = IntCreateMenu(&hMenu, FALSE); // It will be marked.
+               SubMenuObject = IntCreateMenu(&hMenu,
+                   FALSE,
+                   MenuObject->head.rpdesk,
+                   (PPROCESSINFO)MenuObject->head.hTaskWow); // It will be marked.
                if (!SubMenuObject) return FALSE;
                IntReleaseMenuObject(SubMenuObject); // This will be referenced again after insertion.
                circref = TRUE;
@@ -878,7 +878,7 @@ IntSetMenuItemInfo(PMENU MenuObject, PITEM MenuItem, PROSMENUITEMINFO lpmii, PUN
             if ( MENU_depth( SubMenuObject, 0) > MAXMENUDEPTH )
             {
                ERR( "Loop detected in menu hierarchy or maximum menu depth exceeded!\n");
-               if (circref) IntDestroyMenuObject(SubMenuObject, FALSE, TRUE);
+               if (circref) IntDestroyMenuObject(SubMenuObject, FALSE);
                return FALSE;
             }
             /* Make sure the submenu is marked as a popup menu */
@@ -1135,36 +1135,6 @@ co_IntTrackPopupMenu(PMENU Menu, PWND Window,
    return FALSE;
 }
 
-
-/*!
- * Internal function. Called when the process is destroyed to free the remaining menu handles.
-*/
-BOOL FASTCALL
-IntCleanupMenus(struct _EPROCESS *Process, PPROCESSINFO Win32Process)
-{
-   PEPROCESS CurrentProcess;
-   PMENU MenuObject;
-
-   CurrentProcess = PsGetCurrentProcess();
-   if (CurrentProcess != Process)
-   {
-      KeAttachProcess(&Process->Pcb);
-   }
-
-   while (!IsListEmpty(&Win32Process->MenuListHead))
-   {
-      MenuObject = CONTAINING_RECORD(Win32Process->MenuListHead.Flink, MENU, ListEntry);
-      TRACE("Menus are stuck on the process list!\n");
-      IntDestroyMenuObject(MenuObject, FALSE, TRUE);
-   }
-
-   if (CurrentProcess != Process)
-   {
-      KeDetachProcess();
-   }
-   return TRUE;
-}
-
 BOOLEAN APIENTRY
 intGetTitleBarInfo(PWND pWindowObject, PTITLEBARINFO bti)
 {
@@ -1415,7 +1385,7 @@ UINT FASTCALL IntFindSubMenu(HMENU *hMenu, HMENU hSubTarget )
 }
 
 
-HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
+HMENU FASTCALL UserCreateMenu(PDESKTOP Desktop, BOOL PopupMenu)
 {
    PWINSTATION_OBJECT WinStaObject;
    HANDLE Handle;
@@ -1441,7 +1411,7 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
           SetLastNtError(Status);
           return (HMENU)0;
        }
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
+       Menu = IntCreateMenu(&Handle, !PopupMenu, Desktop, GetW32ProcessInfo());
        if (Menu && Menu->head.rpdesk->rpwinstaParent != WinStaObject)
        {
           ERR("Desktop Window Station does not match Process one!\n");
@@ -1450,7 +1420,7 @@ HMENU FASTCALL UserCreateMenu(BOOL PopupMenu)
    }
    else
    {
-       Menu = IntCreateMenu(&Handle, !PopupMenu);
+       Menu = IntCreateMenu(&Handle, !PopupMenu, GetW32ThreadInfo()->rpdesk, GetW32ProcessInfo());
    }
 
    if (Menu) UserDereferenceObject(Menu);
@@ -1678,7 +1648,7 @@ PMENU FASTCALL MENU_GetSystemMenu(PWND Window, PMENU Popup)
    ROSMENUITEMINFO ItemInfo = {0};
    UNICODE_STRING MenuName;
 
-   hSysMenu = UserCreateMenu(FALSE);
+   hSysMenu = UserCreateMenu(Window->head.rpdesk, FALSE);
    if (NULL == hSysMenu)
    {
       return NULL;
@@ -1742,7 +1712,7 @@ PMENU FASTCALL MENU_GetSystemMenu(PWND Window, PMENU Popup)
       IntReleaseMenuObject(NewMenu);
       UserSetMenuDefaultItem(NewMenu, SC_CLOSE, FALSE);
 
-      IntDestroyMenuObject(Menu, FALSE, TRUE);
+      IntDestroyMenuObject(Menu, FALSE);
    }
    else
    {
@@ -1782,7 +1752,7 @@ IntGetSystemMenu(PWND Window, BOOL bRevert)
          Menu = UserGetMenuObject(Window->SystemMenu);
          if (Menu && !(Menu->fFlags & MNF_SYSDESKMN))
          {
-            IntDestroyMenuObject(Menu, TRUE, TRUE);
+            IntDestroyMenuObject(Menu, TRUE);
             Window->SystemMenu = NULL;
          }
       }
@@ -1826,7 +1796,7 @@ IntSetSystemMenu(PWND Window, PMENU Menu)
       if (OldMenu)
       {
           OldMenu->fFlags &= ~MNF_SYSMENU;
-         IntDestroyMenuObject(OldMenu, TRUE, TRUE);
+         IntDestroyMenuObject(OldMenu, TRUE);
       }
    }
 
@@ -2091,7 +2061,7 @@ BOOL FASTCALL UserDestroyMenu(HMENU hMenu)
       EngSetLastError(ERROR_ACCESS_DENIED);
       return FALSE;
    }
-   return IntDestroyMenuObject(Menu, FALSE, TRUE);
+   return IntDestroyMenuObject(Menu, FALSE);
 }
 
 /*
@@ -2116,7 +2086,7 @@ NtUserDestroyMenu(
       EngSetLastError(ERROR_ACCESS_DENIED);
       RETURN( FALSE);
    }
-   RETURN( IntDestroyMenuObject(Menu, TRUE, TRUE));
+   RETURN( IntDestroyMenuObject(Menu, TRUE));
 
 CLEANUP:
    TRACE("Leave NtUserDestroyMenu, ret=%i\n",_ret_);
index dffc55a..286e864 100644 (file)
@@ -23,8 +23,11 @@ IntGetMenuObject(HMENU hMenu);
 #define IntReleaseMenuObject(MenuObj) \
   UserDereferenceObject(MenuObj)
 
+BOOLEAN
+UserDestroyMenuObject(PVOID Object);
+
 BOOL FASTCALL
-IntDestroyMenuObject(PMENU MenuObject, BOOL bRecurse, BOOL RemoveFromProcess);
+IntDestroyMenuObject(PMENU MenuObject, BOOL bRecurse);
 
 PMENU FASTCALL
 IntCloneMenu(PMENU Source);
index c807be0..01964de 100644 (file)
@@ -12,6 +12,233 @@ 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()
@@ -27,7 +254,7 @@ void DbgUserDumpHandleTable()
 
     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)
     {
@@ -96,7 +323,6 @@ __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 %lu\n", gpsi->cHandleEntries);
 
    if (ht->freelist)
@@ -105,7 +331,6 @@ __inline static PUSER_HANDLE_ENTRY alloc_user_entry(PUSER_HANDLE_TABLE ht)
       ht->freelist = entry->ptr;
 
       gpsi->cHandleEntries++;
-      ppi->UserHandleCount++;
       return entry;
    }
 
@@ -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(HANDLE_TYPE type)
-{
-    PVOID pi;
-
-    switch (type)
-    {
-        case TYPE_WINDOW:
-        case TYPE_INPUTCONTEXT:
-            pi = GetW32ThreadInfo();
-            break;
-
-        case TYPE_MENU:
-        case TYPE_CURSOR:
-        case TYPE_HOOK:
-        case TYPE_CALLPROC:
-        case TYPE_ACCELTABLE:
-        case TYPE_SETWINDOWPOS:
-            pi = GetW32ProcessInfo();
-            break;
-
-        case TYPE_MONITOR:
-            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, HANDLE_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, HANDLE_TYPE type )
    entry->ptr  = object;
    entry->type = type;
    entry->flags = 0;
-   entry->pi = UserHandleOwnerByType(type);
+   entry->pi = HandleOwner;
    if (++entry->generation >= 0xffff)
       entry->generation = 1;
 
@@ -322,82 +536,41 @@ UserCreateObject( PUSER_HANDLE_TABLE ht,
 {
    HANDLE hi;
    PVOID Object;
-   PPROCESSINFO ppi;
-   BOOL dt;
-   PDESKTOP rpdesk = pDesktop;
-
-   /* 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*/
+   PVOID ObjectOwner;
 
-   if (!pti) pti = GetW32ThreadInfo();
-   if (!pDesktop) rpdesk = pti->rpdesk;
-   ppi = pti->ppi;
+   /* Some sanity checks. Other checks will be made in the allocator */
+   ASSERT(type < TYPE_CTYPES);
+   ASSERT(type != TYPE_FREE);
+   ASSERT(ht != NULL);
 
-   switch (type)
+   /* Allocate the object */
+   ASSERT(ObjectCallbacks[type].ObjectAlloc != NULL);
+   Object = ObjectCallbacks[type].ObjectAlloc(pDesktop, pti, size, &ObjectOwner);
+   if (!Object)
    {
-      case TYPE_WINDOW:
-      case TYPE_MENU:
-      case TYPE_HOOK:
-      case TYPE_CALLPROC:
-      case TYPE_INPUTCONTEXT:
-         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 TYPE_WINDOW:
-        case TYPE_HOOK:
-        case TYPE_INPUTCONTEXT:
-            ((PTHRDESKHEAD)Object)->rpdesk = rpdesk;
-            ((PTHRDESKHEAD)Object)->pSelf = Object;
-        case TYPE_WINEVENTHOOK:
-            ((PTHROBJHEAD)Object)->pti = pti;
-            break;
-
-        case TYPE_MENU:
-        case TYPE_CALLPROC:
-            ((PPROCDESKHEAD)Object)->rpdesk = rpdesk;
-            ((PPROCDESKHEAD)Object)->pSelf = Object;
-            break;
-
-        case TYPE_CURSOR:
-            ((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;
-  HANDLE_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 -> %p\n", object);
-        return FALSE;
-     }
-     TRACE("Warning! Dereference to zero! Obj -> %p\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);
+
+        /* We can now get rid of everything */
+        free_user_entry(gHandleTable, entry );
 
-     type = entry->type;
-     free_user_entry(gHandleTable, entry );
+#if 0
+        /* Call the object destructor */
+        ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL);
+        ObjectCallbacks[type].ObjectCleanup(Object);
+#endif
 
-     switch (type)
-     {
-        case TYPE_WINDOW:
-        case TYPE_MENU:
-        case TYPE_HOOK:
-        case TYPE_CALLPROC:
-        case TYPE_INPUTCONTEXT:
-           return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object);
+        /* And free it */
+        ASSERT(ObjectCallbacks[type].ObjectFree != NULL);
+        ObjectCallbacks[type].ObjectFree(Object);
 
-        default:
-           return UserHeapFree(object);
-     }
-  }
-  return FALSE;
+        return TRUE;
+    }
+    return FALSE;
 }
 
 BOOL
@@ -522,10 +692,10 @@ 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)
     {
@@ -541,59 +711,55 @@ UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner)
     }
 
     oldppi->UserHandleCount--;
+    IntDereferenceProcessInfo(oldppi);
     ppi->UserHandleCount++;
+    IntReferenceProcessInfo(ppi);
 #if DBG
     oldppi->DbgHandleCount[type]--;
     ppi->DbgHandleCount[type]++;
 #endif
 }
 
-
-HANDLE FASTCALL ValidateHandleNoErr(HANDLE handle, HANDLE_TYPE type)
+BOOLEAN
+UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner)
 {
-   if (handle) return (PWND)UserGetObjectNoErr(gHandleTable, handle, type);
-   return NULL;
-}
+    int i;
+    PUSER_HANDLE_ENTRY Entry;
+    BOOLEAN Ret = TRUE;
 
-PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type)
-{
-  PVOID pObj;
-  DWORD dwError = 0;
-  if (handle) 
-  {
-      pObj = UserGetObjectNoErr(gHandleTable, handle, type);
-      if (!pObj)
-      {
-          switch (type)
-          {  
-              case TYPE_WINDOW:
-                  dwError = ERROR_INVALID_WINDOW_HANDLE;
-                  break;
-              case TYPE_MENU:
-                  dwError = ERROR_INVALID_MENU_HANDLE;
-                  break;
-              case TYPE_CURSOR:
-                  dwError = ERROR_INVALID_CURSOR_HANDLE;
-                  break;
-              case TYPE_SETWINDOWPOS:
-                  dwError = ERROR_INVALID_DWP_HANDLE;
-                  break;
-              case TYPE_HOOK:
-                  dwError = ERROR_INVALID_HOOK_HANDLE;
-                  break;
-              case TYPE_ACCELTABLE:
-                  dwError = ERROR_INVALID_ACCEL_HANDLE;
-                  break;
-              default:
-                  dwError = ERROR_INVALID_HANDLE;
-                  break;
-          }
-          EngSetLastError(dwError);
-          return NULL;
-      }
-      return pObj;
-  }
-  return NULL;
+    /* 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;
 }
       
 /*
index f305633..e90d66c 100644 (file)
@@ -18,8 +18,8 @@ BOOL FASTCALL UserCreateHandleTable(VOID);
 BOOL FASTCALL UserObjectInDestroy(HANDLE);
 void DbgUserDumpHandleTable();
 VOID FASTCALL UserSetObjectOwner(PVOID obj, HANDLE_TYPE type, PVOID owner);
-HANDLE FASTCALL ValidateHandleNoErr(HANDLE handle, HANDLE_TYPE type);
 PVOID FASTCALL ValidateHandle(HANDLE handle, HANDLE_TYPE type);
+BOOLEAN UserDestroyObjectsForOwner(PUSER_HANDLE_TABLE Table, PVOID Owner);
 
 static __inline VOID
 UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
index 03c60c0..7996c9f 100644 (file)
@@ -73,11 +73,11 @@ NtUserCallNoParam(DWORD Routine)
    switch(Routine)
    {
       case NOPARAM_ROUTINE_CREATEMENU:
-         Result = (DWORD_PTR)UserCreateMenu(FALSE);
+         Result = (DWORD_PTR)UserCreateMenu(GetW32ThreadInfo()->rpdesk, FALSE);
          break;
 
       case NOPARAM_ROUTINE_CREATEMENUPOPUP:
-         Result = (DWORD_PTR)UserCreateMenu(TRUE);
+         Result = (DWORD_PTR)UserCreateMenu(GetW32ThreadInfo()->rpdesk, TRUE);
          break;
 
       case NOPARAM_ROUTINE_DESTROY_CARET:
index 2e45bc6..333a4bd 100644 (file)
@@ -2,7 +2,7 @@
 
 FORCEINLINE PMENU UserGetMenuObject(HMENU hMenu)
 {
-   return ValidateHandle(hMenu, TYPE_MENU);
+   return UserGetObject(gHandleTable, hMenu, TYPE_MENU);
 }
 
 #define ASSERT_REFS_CO(_obj_) \
@@ -106,12 +106,12 @@ PWND FASTCALL UserGetWindowObject(HWND hWnd);
 VOID FASTCALL co_DestroyThreadWindows(struct _ETHREAD *Thread);
 HWND FASTCALL UserGetShellWindow(VOID);
 HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags);
-BOOLEAN FASTCALL co_UserDestroyWindow(PWND Wnd);
+BOOLEAN co_UserDestroyWindow(PVOID Object);
 PWND FASTCALL UserGetAncestor(PWND Wnd, UINT Type);
 
 /*************** MENU.C ***************/
 
-HMENU FASTCALL UserCreateMenu(BOOL PopupMenu);
+HMENU FASTCALL UserCreateMenu(PDESKTOP Desktop, BOOL PopupMenu);
 BOOL FASTCALL UserSetMenuDefaultItem(PMENU Menu, UINT uItem, UINT fByPos);
 BOOL FASTCALL UserDestroyMenu(HMENU hMenu);
 
index a086b8f..ee16b36 100644 (file)
@@ -158,17 +158,31 @@ typedef struct _THREADINFO
 #define IntReferenceThreadInfo(pti) \
   InterlockedIncrement(&(pti)->RefCount)
 
-VOID FASTCALL UserDeleteW32Thread(PTHREADINFO);
+VOID UserDeleteW32Thread(PTHREADINFO);
 
 #define IntDereferenceThreadInfo(pti) \
   do { \
     if(InterlockedDecrement(&(pti)->RefCount) == 0) \
     { \
-      ASSERT(pti->TIF_flags &= (TIF_INCLEANUP|TIF_DONTATTACHQUEUE) == (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)); \
+      ASSERT(((pti)->TIF_flags & (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)) == (TIF_INCLEANUP|TIF_DONTATTACHQUEUE)); \
       UserDeleteW32Thread(pti); \
     } \
   } while(0)
 
+#define IntReferenceProcessInfo(ppi) \
+  InterlockedIncrement((volatile LONG*)(&(ppi)->RefCount))
+
+VOID UserDeleteW32Process(PPROCESSINFO);
+
+#define IntDereferenceProcessInfo(ppi) \
+  do { \
+    if(InterlockedDecrement((volatile LONG*)(&(ppi)->RefCount)) == 0) \
+    { \
+      ASSERT(((ppi)->W32PF_flags & W32PF_TERMINATED) != 0); \
+      UserDeleteW32Process(ppi); \
+    } \
+  } while(0)
+
 
 typedef struct _W32HEAP_USER_MAPPING
 {
@@ -242,7 +256,6 @@ typedef struct _PROCESSINFO
   DWORD dwLayout;
   DWORD dwRegisteredClasses;
   /* ReactOS */
-  LIST_ENTRY MenuListHead;
   FAST_MUTEX PrivateFontListLock;
   LIST_ENTRY PrivateFontListHead;
   FAST_MUTEX DriverObjListLock;
index 13d1546..9505717 100644 (file)
@@ -587,14 +587,14 @@ static LRESULT co_UserFreeWindow(PWND Window,
         Window->IDMenu &&
         (Menu = UserGetMenuObject((HMENU)Window->IDMenu)))
    {
-      IntDestroyMenuObject(Menu, TRUE, TRUE);
+      IntDestroyMenuObject(Menu, TRUE);
       Window->IDMenu = 0;
    }
 
    if(Window->SystemMenu
          && (Menu = UserGetMenuObject(Window->SystemMenu)))
    {
-      IntDestroyMenuObject(Menu, TRUE, TRUE);
+      IntDestroyMenuObject(Menu, TRUE);
       Window->SystemMenu = (HMENU)0;
    }
 
@@ -861,40 +861,6 @@ IntSetMenu(
 /* INTERNAL ******************************************************************/
 
 
-VOID FASTCALL
-co_DestroyThreadWindows(struct _ETHREAD *Thread)
-{
-   PTHREADINFO WThread;
-   PLIST_ENTRY Current;
-   PWND Wnd;
-   USER_REFERENCE_ENTRY Ref;
-   WThread = (PTHREADINFO)Thread->Tcb.Win32Thread;
-
-   while (!IsListEmpty(&WThread->WindowListHead))
-   {
-      Current = WThread->WindowListHead.Flink;
-      Wnd = CONTAINING_RECORD(Current, WND, ThreadListEntry);
-
-      TRACE("thread cleanup: while destroy wnds, wnd=%p\n", Wnd);
-
-      /* Window removes itself from the list */
-
-      /*
-       * FIXME: It is critical that the window removes itself! If now, we will loop
-       * here forever...
-       */
-
-      //ASSERT(co_UserDestroyWindow(Wnd));
-
-      UserRefObjectCo(Wnd, &Ref); // FIXME: Temp HACK??
-      if (!co_UserDestroyWindow(Wnd))
-      {
-         ERR("Unable to destroy window %p at thread cleanup... This is _VERY_ bad!\n", Wnd);
-      }
-      UserDerefObjectCo(Wnd); // FIXME: Temp HACK??
-   }
-}
-
 BOOL FASTCALL
 IntIsChildWindow(PWND Parent, PWND BaseWindow)
 {
@@ -1788,7 +1754,7 @@ PWND FASTCALL IntCreateWindow(CREATESTRUCTW* Cs,
    if (Class->atomClassName == gpsi->atomSysClass[ICLS_EDIT])
    {
       PCALLPROCDATA CallProc;
-      CallProc = CreateCallProc(NULL, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
+      CallProc = CreateCallProc(pWnd->head.rpdesk, pWnd->lpfnWndProc, pWnd->Unicode , pWnd->head.pti->ppi);
 
       if (!CallProc)
       {
@@ -2431,9 +2397,10 @@ NtUserCreateWindowEx(
     if ( (dwStyle & (WS_POPUP|WS_CHILD)) != WS_CHILD) 
     {
         /* check hMenu is valid handle */
-        if (hMenu && !ValidateHandle(hMenu, TYPE_MENU))
+        if (hMenu && !UserGetMenuObject(hMenu))
         {
-            /* error is set in ValidateHandle */
+            ERR("NtUserCreateWindowEx: Got an invalid menu handle!\n");
+            EngSetLastError(ERROR_INVALID_MENU_HANDLE);
             return NULL;
         }
     } 
@@ -2520,12 +2487,13 @@ cleanup:
 }
 
 
-BOOLEAN FASTCALL co_UserDestroyWindow(PWND Window)
+BOOLEAN co_UserDestroyWindow(PVOID Object)
 {
    HWND hWnd;
    PWND pwndTemp;
    PTHREADINFO ti;
    MSG msg;
+   PWND Window = Object;
 
    ASSERT_REFS_CO(Window); // FIXME: Temp HACK?
 
index 5d97031..bdbdeda 100644 (file)
@@ -315,17 +315,17 @@ static const BOOL g_ObjectHeapTypeShared[TYPE_CTYPES] =
     TRUE,  /* TYPE_CURSOR */
     TRUE,  /* TYPE_SETWINDOWPOS */
     FALSE, /* TYPE_HOOK */
-    FALSE, /* TYPE_CLIPDATA */
+    TRUE,  /* TYPE_CLIPDATA */
     FALSE, /* TYPE_CALLPROC */
     TRUE,  /* TYPE_ACCELTABLE */
     FALSE, /* TYPE_DDEACCESS */
     FALSE, /* TYPE_DDECONV */
     FALSE, /* TYPE_DDEXACT */
     TRUE,  /* TYPE_MONITOR */
-    FALSE, /* TYPE_KBDLAYOUT */
-    FALSE, /* TYPE_KBDFILE */
+    TRUE,  /* TYPE_KBDLAYOUT */
+    TRUE,  /* TYPE_KBDFILE */
     TRUE,  /* TYPE_WINEVENTHOOK */
-    FALSE, /* TYPE_TIMER */
+    TRUE,  /* TYPE_TIMER */
     FALSE, /* TYPE_INPUTCONTEXT */
     FALSE, /* TYPE_HIDDATA */
     FALSE, /* TYPE_DEVICEINFO */