mirror of
https://github.com/reactos/reactos.git
synced 2024-09-28 21:44:31 +00:00
[WIN32K]
- 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
This commit is contained in:
parent
c2068d9c05
commit
01da3a14ed
|
@ -172,7 +172,7 @@ typedef struct _THRDESKHEAD
|
|||
typedef struct _PROCDESKHEAD
|
||||
{
|
||||
HEAD;
|
||||
DWORD hTaskWow;
|
||||
DWORD_PTR hTaskWow;
|
||||
struct _DESKTOP *rpdesk;
|
||||
PVOID pSelf;
|
||||
} PROCDESKHEAD, *PPROCDESKHEAD;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -224,8 +224,7 @@ IntDestroyClass(IN OUT PCLS Class)
|
|||
NextCallProc = CallProc->spcpdNext;
|
||||
|
||||
CallProc->spcpdNext = NULL;
|
||||
DestroyCallProc(NULL,
|
||||
CallProc);
|
||||
DestroyCallProc(CallProc);
|
||||
|
||||
CallProc = NextCallProc;
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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_);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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?
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue