diff --git a/reactos/win32ss/include/ntuser.h b/reactos/win32ss/include/ntuser.h index 3a80945126a..be603583838 100644 --- a/reactos/win32ss/include/ntuser.h +++ b/reactos/win32ss/include/ntuser.h @@ -172,7 +172,7 @@ typedef struct _THRDESKHEAD typedef struct _PROCDESKHEAD { HEAD; - DWORD hTaskWow; + DWORD_PTR hTaskWow; struct _DESKTOP *rpdesk; PVOID pSelf; } PROCDESKHEAD, *PPROCDESKHEAD; diff --git a/reactos/win32ss/user/ntuser/accelerator.c b/reactos/win32ss/user/ntuser/accelerator.c index 7777c509a24..2723e7b999b 100644 --- a/reactos/win32ss/user/ntuser/accelerator.c +++ b/reactos/win32ss/user/ntuser/accelerator.c @@ -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); diff --git a/reactos/win32ss/user/ntuser/accelerator.h b/reactos/win32ss/user/ntuser/accelerator.h index 4bd8807ce5e..cbe5c370172 100644 --- a/reactos/win32ss/user/ntuser/accelerator.h +++ b/reactos/win32ss/user/ntuser/accelerator.h @@ -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); diff --git a/reactos/win32ss/user/ntuser/callproc.c b/reactos/win32ss/user/ntuser/callproc.c index a1b6356261b..970f7b29c35 100644 --- a/reactos/win32ss/user/ntuser/callproc.c +++ b/reactos/win32ss/user/ntuser/callproc.c @@ -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); diff --git a/reactos/win32ss/user/ntuser/class.c b/reactos/win32ss/user/ntuser/class.c index 58521045aba..f14071e3ea8 100644 --- a/reactos/win32ss/user/ntuser/class.c +++ b/reactos/win32ss/user/ntuser/class.c @@ -224,8 +224,7 @@ IntDestroyClass(IN OUT PCLS Class) NextCallProc = CallProc->spcpdNext; CallProc->spcpdNext = NULL; - DestroyCallProc(NULL, - CallProc); + DestroyCallProc(CallProc); CallProc = NextCallProc; } diff --git a/reactos/win32ss/user/ntuser/class.h b/reactos/win32ss/user/ntuser/class.h index 8b82929a69b..0c66ae9f584 100644 --- a/reactos/win32ss/user/ntuser/class.h +++ b/reactos/win32ss/user/ntuser/class.h @@ -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, diff --git a/reactos/win32ss/user/ntuser/cursoricon.c b/reactos/win32ss/user/ntuser/cursoricon.c index 335aa87e216..c8f89cfc6b3 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.c +++ b/reactos/win32ss/user/ntuser/cursoricon.c @@ -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) diff --git a/reactos/win32ss/user/ntuser/cursoricon.h b/reactos/win32ss/user/ntuser/cursoricon.h index a6d842c0e27..c6b998a8d52 100644 --- a/reactos/win32ss/user/ntuser/cursoricon.h +++ b/reactos/win32ss/user/ntuser/cursoricon.h @@ -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) diff --git a/reactos/win32ss/user/ntuser/event.c b/reactos/win32ss/user/ntuser/event.c index 0fe5a10e2fe..b944f08020f 100644 --- a/reactos/win32ss/user/ntuser/event.c +++ b/reactos/win32ss/user/ntuser/event.c @@ -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; } diff --git a/reactos/win32ss/user/ntuser/hook.c b/reactos/win32ss/user/ntuser/hook.c index 984d32e392c..3e6e94211d1 100644 --- a/reactos/win32ss/user/ntuser/hook.c +++ b/reactos/win32ss/user/ntuser/hook.c @@ -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) { diff --git a/reactos/win32ss/user/ntuser/hook.h b/reactos/win32ss/user/ntuser/hook.h index 146bd087897..f3f1f80d587 100644 --- a/reactos/win32ss/user/ntuser/hook.h +++ b/reactos/win32ss/user/ntuser/hook.h @@ -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); diff --git a/reactos/win32ss/user/ntuser/main.c b/reactos/win32ss/user/ntuser/main.c index 905fa04e503..c668bbb27a3 100644 --- a/reactos/win32ss/user/ntuser/main.c +++ b/reactos/win32ss/user/ntuser/main.c @@ -51,12 +51,232 @@ DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult) } #endif +static +NTSTATUS +CreateProcessInfo(PEPROCESS Process) +{ + PPROCESSINFO ppiCurrent; + NTSTATUS Status; + 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!) */ + 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)); + return STATUS_NO_MEMORY; + } + + RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO)); + + PsSetProcessWin32Process(Process, ppiCurrent, NULL); + +#if DBG + DbgInitDebugChannels(); +#if KDBG + 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); + 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->PrivateFontListHead); + ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock); + + InitializeListHead(&ppiCurrent->DriverObjListHead); + ExInitializeFastMutex(&ppiCurrent->DriverObjListLock); + + 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; + + if ( pParams && + pParams->WindowFlags & STARTF_SCRNSAVER ) + { + ppiScrnSaver = ppiCurrent; + ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; + } + + // Fixme check if this process is allowed. + ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off. + + /* 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); + + /* Add the process to the global list */ + ppiCurrent->ppiNext = gppiList; + gppiList = ppiCurrent; + IntReferenceProcessInfo(ppiCurrent); + + return STATUS_SUCCESS; +} + +static +NTSTATUS +DestroyProcessInfo(PEPROCESS Process) +{ + PPROCESSINFO ppiCurrent, *pppi; + + /* Get the Win32 Process */ + ppiCurrent = PsGetProcessWin32Process(Process); + + ASSERT(ppiCurrent); + + TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent); + ppiCurrent->W32PF_flags |= W32PF_TERMINATED; + + if (ppiScrnSaver == ppiCurrent) + ppiScrnSaver = NULL; + + /* 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 + + /* And GDI ones too */ + GDI_CleanupForProcess(Process); + + /* So we can now free the pools */ + GdiPoolDestroy(ppiCurrent->pPoolDcAttr); + GdiPoolDestroy(ppiCurrent->pPoolBrushAttr); + GdiPoolDestroy(ppiCurrent->pPoolRgnAttr); + + /* Remove it from the list of GUI apps */ + co_IntGraphicsCheck(FALSE); + + /* + * 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; + + ASSERT(*pppi == ppiCurrent); + + *pppi = ppiCurrent->ppiNext; + + if(ppiCurrent->hdeskStartup) + { + ZwClose(ppiCurrent->hdeskStartup); + ppiCurrent->hdeskStartup = NULL; + } + + /* The process is dying */ + PsSetProcessWin32Process(Process, NULL, ppiCurrent); + ppiCurrent->peProcess = NULL; + + /* At last, dereference */ + IntDereferenceProcessInfo(ppiCurrent); + + return STATUS_SUCCESS; +} + +VOID +UserDeleteW32Process(PPROCESSINFO ppiCurrent) +{ + if (ppiCurrent->InputIdleEvent) + { + EngDeleteEvent((PEVENT)ppiCurrent->InputIdleEvent); + } + + /* Close the startup desktop */ + if(ppiCurrent->rpdeskStartup) + ObDereferenceObject(ppiCurrent->rpdeskStartup); + +#if DBG + 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 */ + ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); +} + NTSTATUS APIENTRY Win32kProcessCallback(struct _EPROCESS *Process, BOOLEAN Create) { - PPROCESSINFO ppiCurrent, *pppi; NTSTATUS Status; ASSERT(Process->Peb); @@ -65,193 +285,13 @@ Win32kProcessCallback(struct _EPROCESS *Process, 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) - { - /* There is no more to do for us (this is a success code!) */ - Status = STATUS_ALREADY_WIN32; - 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)); - Status = STATUS_NO_MEMORY; - goto Leave; - } - - RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO)); - - PsSetProcessWin32Process(Process, ppiCurrent, NULL); - -#if DBG - DbgInitDebugChannels(); -#if KDBG - 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; - - InitializeListHead(&ppiCurrent->MenuListHead); - - InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList); - InitializeListHead(&ppiCurrent->GDIDcAttrFreeList); - - InitializeListHead(&ppiCurrent->PrivateFontListHead); - ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock); - - InitializeListHead(&ppiCurrent->DriverObjListHead); - ExInitializeFastMutex(&ppiCurrent->DriverObjListLock); - - 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; - - if ( pParams && - pParams->WindowFlags & STARTF_SCRNSAVER ) - { - ppiScrnSaver = ppiCurrent; - ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER; - } - - // Fixme check if this process is allowed. - ppiCurrent->W32PF_flags |= W32PF_ALLOWFOREGROUNDACTIVATE; // Starting application it will get toggled off. - - /* 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); - - /* Add the process to the global list */ - ppiCurrent->ppiNext = gppiList; - gppiList = ppiCurrent; + Status = CreateProcessInfo(Process); } else { - /* Get the Win32 Process */ - ppiCurrent = PsGetProcessWin32Process(Process); - - ASSERT(ppiCurrent); - - TRACE_CH(UserProcess, "Destroying ppi 0x%p\n", ppiCurrent); - ppiCurrent->W32PF_flags |= W32PF_TERMINATED; - - if (ppiScrnSaver == ppiCurrent) - ppiScrnSaver = NULL; - - if (ppiCurrent->InputIdleEvent) - { - EngFreeMem(ppiCurrent->InputIdleEvent); - ppiCurrent->InputIdleEvent = NULL; - } - - IntCleanupMenus(Process, ppiCurrent); - IntCleanupCurIcons(Process, ppiCurrent); - - - GDI_CleanupForProcess(Process); - - co_IntGraphicsCheck(FALSE); - - /* - * Deregister logon application automatically - */ - if(LogonProcess == ppiCurrent) - { - LogonProcess = NULL; - } - - /* Close the startup desktop */ - if(ppiCurrent->rpdeskStartup) - ObDereferenceObject(ppiCurrent->rpdeskStartup); - if(ppiCurrent->hdeskStartup) - ZwClose(ppiCurrent->hdeskStartup); - - /* Close the current window station */ - UserSetProcessWindowStation(NULL); - - /* Destroy GDI pools */ - GdiPoolDestroy(ppiCurrent->pPoolDcAttr); - GdiPoolDestroy(ppiCurrent->pPoolBrushAttr); - GdiPoolDestroy(ppiCurrent->pPoolRgnAttr); - - if (gppiInputProvider == ppiCurrent) gppiInputProvider = NULL; - - pppi = &gppiList; - while (*pppi != NULL && *pppi != ppiCurrent) - pppi = &(*pppi)->ppiNext; - - ASSERT(*pppi == ppiCurrent); - - *pppi = ppiCurrent->ppiNext; - - TRACE_CH(UserProcess,"Freeing ppi 0x%p\n", ppiCurrent); -#if DBG - if (DBG_IS_CHANNEL_ENABLED(ppiCurrent, DbgChUserObj, WARN_LEVEL)) - { - DbgUserDumpHandleTable(); - } -#endif - - /* Free the PROCESSINFO */ - PsSetProcessWin32Process(Process, NULL, ppiCurrent); - ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO); + Status = DestroyProcessInfo(Process); } - Status = STATUS_SUCCESS; - -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); diff --git a/reactos/win32ss/user/ntuser/menu.c b/reactos/win32ss/user/ntuser/menu.c index 2fed7c12d48..9cd09171564 100644 --- a/reactos/win32ss/user/ntuser/menu.c +++ b/reactos/win32ss/user/ntuser/menu.c @@ -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_); diff --git a/reactos/win32ss/user/ntuser/menu.h b/reactos/win32ss/user/ntuser/menu.h index dffc55a2a45..286e8647cac 100644 --- a/reactos/win32ss/user/ntuser/menu.h +++ b/reactos/win32ss/user/ntuser/menu.h @@ -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); diff --git a/reactos/win32ss/user/ntuser/object.c b/reactos/win32ss/user/ntuser/object.c index c807be0852e..01964de86a7 100644 --- a/reactos/win32ss/user/ntuser/object.c +++ b/reactos/win32ss/user/ntuser/object.c @@ -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; + 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 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); + + type = entry->type; + ASSERT(type != TYPE_FREE); + ASSERT(type < TYPE_CTYPES); + + /* We can now get rid of everything */ + free_user_entry(gHandleTable, entry ); + +#if 0 + /* Call the object destructor */ + ASSERT(ObjectCallbacks[type].ObjectCleanup != NULL); + ObjectCallbacks[type].ObjectCleanup(Object); +#endif + + /* And free it */ + ASSERT(ObjectCallbacks[type].ObjectFree != NULL); + ObjectCallbacks[type].ObjectFree(Object); - if (!(entry->flags & HANDLEENTRY_INDESTROY)) return TRUE; - - type = entry->type; - free_user_entry(gHandleTable, entry ); - - switch (type) - { - case TYPE_WINDOW: - case TYPE_MENU: - case TYPE_HOOK: - case TYPE_CALLPROC: - case TYPE_INPUTCONTEXT: - return DesktopHeapFree(((PTHRDESKHEAD)object)->rpdesk, object); - - default: - return UserHeapFree(object); - } - } - return FALSE; + } + 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; } /* diff --git a/reactos/win32ss/user/ntuser/object.h b/reactos/win32ss/user/ntuser/object.h index f305633dea2..e90d66cc983 100644 --- a/reactos/win32ss/user/ntuser/object.h +++ b/reactos/win32ss/user/ntuser/object.h @@ -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) diff --git a/reactos/win32ss/user/ntuser/simplecall.c b/reactos/win32ss/user/ntuser/simplecall.c index 03c60c038c7..7996c9f4fed 100644 --- a/reactos/win32ss/user/ntuser/simplecall.c +++ b/reactos/win32ss/user/ntuser/simplecall.c @@ -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: diff --git a/reactos/win32ss/user/ntuser/userfuncs.h b/reactos/win32ss/user/ntuser/userfuncs.h index 2e45bc6e4f7..333a4bda092 100644 --- a/reactos/win32ss/user/ntuser/userfuncs.h +++ b/reactos/win32ss/user/ntuser/userfuncs.h @@ -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); diff --git a/reactos/win32ss/user/ntuser/win32.h b/reactos/win32ss/user/ntuser/win32.h index a086b8f19bd..ee16b362ddb 100644 --- a/reactos/win32ss/user/ntuser/win32.h +++ b/reactos/win32ss/user/ntuser/win32.h @@ -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; diff --git a/reactos/win32ss/user/ntuser/window.c b/reactos/win32ss/user/ntuser/window.c index 13d154685a4..9505717328e 100644 --- a/reactos/win32ss/user/ntuser/window.c +++ b/reactos/win32ss/user/ntuser/window.c @@ -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? diff --git a/reactos/win32ss/user/user32/misc/misc.c b/reactos/win32ss/user/user32/misc/misc.c index 5d97031b6ae..bdbdedaf516 100644 --- a/reactos/win32ss/user/user32/misc/misc.c +++ b/reactos/win32ss/user/user32/misc/misc.c @@ -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 */