- Cleanup Win32kProcessCallback and Win32kThreadCallback
- Even though it works, trying to post a message in Win32kProcessCallback after the THREADINFO is destroyed can only cause trouble, so move it in Win32kThreadCallback
- There is no need to try opening a desktop and windowstation before winlogon initializes
- Handle errors properly when we fail to get a default window station and desktop for the new process
- Enable win32k syscall hook callbacks
- Rewrite SetThreadDesktop to update THREADINFO properly and handle errors properly
- Do not initialize the THREADINFO in GetW32ThreadInfo as it is now done properly (actually leave a small hack that updates pci->dwTIFlags)
- Add UserDbgAssertThreadInfo that asserts the integrity of THREADINFO, CLIENTINFO and CLIENTTHREADINFO. This is called by GetW32ThreadInfo and the syscall hook callbacks

svn path=/trunk/; revision=55458
This commit is contained in:
Giannis Adamopoulos 2012-02-06 12:30:59 +00:00
parent da5891c24b
commit 0e7cf2af87
8 changed files with 342 additions and 335 deletions

View file

@ -55,11 +55,11 @@ NTSYSAPI ULONG APIENTRY RtlWalkFrameChain(OUT PVOID *Callers, IN ULONG Count, IN
#if DBG
void
NTAPI
DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments);
GdiDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments);
ULONG_PTR
NTAPI
DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult);
GdiDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult);
#define ID_Win32PreServiceHook 'WSH0'
#define ID_Win32PostServiceHook 'WSH1'

View file

@ -9,6 +9,7 @@
#define UserEnterCo UserEnterExclusive
#define UserLeaveCo UserLeave
extern BOOL gbInitialized;
extern PSERVERINFO gpsi;
extern PTHREADINFO gptiCurrent;
extern PPROCESSINFO ppiScrnSaver;

View file

@ -198,3 +198,9 @@ typedef struct _PROCESSINFO
BYTE DbgChannelLevel[DbgChCount];
#endif
} PROCESSINFO;
#ifdef DBG
void NTAPI UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments);
ULONG_PTR NTAPI UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult);
#endif

View file

@ -29,52 +29,62 @@ extern ULONG_PTR Win32kSSDT[];
extern UCHAR Win32kSSPT[];
extern ULONG Win32kNumberOfSysCalls;
void
NTAPI
DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
{
GdiDbgPreServiceHook(ulSyscallId, pulArguments);
UserDbgPreServiceHook(ulSyscallId, pulArguments);
}
ULONG_PTR
NTAPI
DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
{
ulResult = GdiDbgPostServiceHook(ulSyscallId, ulResult);
ulResult = UserDbgPostServiceHook(ulSyscallId, ulResult);
return ulResult;
}
NTSTATUS
APIENTRY
Win32kProcessCallback(struct _EPROCESS *Process,
BOOLEAN Create)
{
PPROCESSINFO Win32Process;
PPROCESSINFO ppiCurrent;
DECLARE_RETURN(NTSTATUS);
ASSERT(Process->Peb);
DPRINT("Enter Win32kProcessCallback\n");
UserEnterExclusive();
/* Get the Win32 Process */
Win32Process = PsGetProcessWin32Process(Process);
/* Allocate one if needed */
if (!Win32Process)
{
/* FIXME: Lock the process */
Win32Process = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PROCESSINFO),
USERTAG_PROCESSINFO);
if (Win32Process == NULL) RETURN( STATUS_NO_MEMORY);
RtlZeroMemory(Win32Process, sizeof(PROCESSINFO));
PsSetProcessWin32Process(Process, Win32Process);
/* FIXME: Unlock the process */
}
if (Create)
{
SIZE_T ViewSize = 0;
LARGE_INTEGER Offset;
PVOID UserBase = NULL;
PRTL_USER_PROCESS_PARAMETERS pParams = NULL;
PRTL_USER_PROCESS_PARAMETERS pParams = Process->Peb->ProcessParameters;
NTSTATUS Status;
extern PSECTION_OBJECT GlobalUserHeapSection;
ASSERT(PsGetProcessWin32Process(Process) == NULL);
ppiCurrent = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PROCESSINFO),
USERTAG_PROCESSINFO);
if (ppiCurrent == NULL)
RETURN( STATUS_NO_MEMORY);
RtlZeroMemory(ppiCurrent, sizeof(PROCESSINFO));
PsSetProcessWin32Process(Process, ppiCurrent);
#ifdef DBG
DbgInitDebugChannels();
#endif
TRACE_PPI(Win32Process, UserProcess,"Allocated ppi for PID:%d\n", Process->UniqueProcessId);
DPRINT("Creating W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
TRACE_PPI(ppiCurrent, UserProcess,"Allocated ppi for PID:%d\n", Process->UniqueProcessId);
/* map the global heap into the process */
Offset.QuadPart = 0;
@ -93,89 +103,76 @@ Win32kProcessCallback(struct _EPROCESS *Process,
DPRINT1("Failed to map the global heap! 0x%x\n", Status);
RETURN(Status);
}
Win32Process->HeapMappings.Next = NULL;
Win32Process->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
Win32Process->HeapMappings.UserMapping = UserBase;
Win32Process->HeapMappings.Count = 1;
ppiCurrent->HeapMappings.Next = NULL;
ppiCurrent->HeapMappings.KernelMapping = (PVOID)GlobalUserHeap;
ppiCurrent->HeapMappings.UserMapping = UserBase;
ppiCurrent->HeapMappings.Count = 1;
InitializeListHead(&Win32Process->MenuListHead);
InitializeListHead(&ppiCurrent->MenuListHead);
InitializeListHead(&Win32Process->GDIBrushAttrFreeList);
InitializeListHead(&Win32Process->GDIDcAttrFreeList);
InitializeListHead(&ppiCurrent->GDIBrushAttrFreeList);
InitializeListHead(&ppiCurrent->GDIDcAttrFreeList);
InitializeListHead(&Win32Process->PrivateFontListHead);
ExInitializeFastMutex(&Win32Process->PrivateFontListLock);
InitializeListHead(&ppiCurrent->PrivateFontListHead);
ExInitializeFastMutex(&ppiCurrent->PrivateFontListLock);
InitializeListHead(&Win32Process->DriverObjListHead);
ExInitializeFastMutex(&Win32Process->DriverObjListLock);
InitializeListHead(&ppiCurrent->DriverObjListHead);
ExInitializeFastMutex(&ppiCurrent->DriverObjListLock);
Win32Process->KeyboardLayout = W32kGetDefaultKeyLayout();
EngCreateEvent((PEVENT *)&Win32Process->InputIdleEvent);
KeInitializeEvent(Win32Process->InputIdleEvent, NotificationEvent, FALSE);
ppiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
EngCreateEvent((PEVENT *)&ppiCurrent->InputIdleEvent);
KeInitializeEvent(ppiCurrent->InputIdleEvent, NotificationEvent, FALSE);
if(Process->Peb != NULL)
{
/* map the gdi handle table to user land */
Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
pParams = Process->Peb->ProcessParameters;
}
/* map the gdi handle table to user land */
Process->Peb->GdiSharedHandleTable = GDI_MapHandleTable(Process);
Process->Peb->GdiDCAttributeList = GDI_BATCH_LIMIT;
pParams = Process->Peb->ProcessParameters;
Win32Process->peProcess = Process;
ppiCurrent->peProcess = Process;
/* setup process flags */
Win32Process->W32PF_flags = W32PF_THREADCONNECTED;
ppiCurrent->W32PF_flags = W32PF_THREADCONNECTED;
if ( pParams &&
pParams->WindowFlags & STARTF_SCRNSAVER )
{
ppiScrnSaver = Win32Process;
Win32Process->W32PF_flags |= W32PF_SCREENSAVER;
ppiScrnSaver = ppiCurrent;
ppiCurrent->W32PF_flags |= W32PF_SCREENSAVER;
}
/* Create pools for GDI object attributes */
Win32Process->pPoolDcAttr = GdiPoolCreate(sizeof(DC_ATTR), 'acdG');
Win32Process->pPoolBrushAttr = GdiPoolCreate(sizeof(BRUSH_ATTR), 'arbG');
Win32Process->pPoolRgnAttr = GdiPoolCreate(sizeof(RGN_ATTR), 'agrG');
ASSERT(Win32Process->pPoolDcAttr);
ASSERT(Win32Process->pPoolBrushAttr);
ASSERT(Win32Process->pPoolRgnAttr);
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);
}
else
{
DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
Win32Process->W32PF_flags |= W32PF_TERMINATED;
/* Get the Win32 Process */
ppiCurrent = PsGetProcessWin32Process(Process);
if (ppiScrnSaver == Win32Process) ppiScrnSaver = NULL;
ASSERT(ppiCurrent);
/* Notify logon application to restart shell if needed */
if(Win32Process->rpdeskStartup->pDeskInfo)
TRACE_CH(UserProcess, "Destroying W32 process PID:%d at IRQ level: %lu\n", Process->UniqueProcessId, KeGetCurrentIrql());
ppiCurrent->W32PF_flags |= W32PF_TERMINATED;
if (ppiScrnSaver == ppiCurrent)
ppiScrnSaver = NULL;
if (ppiCurrent->InputIdleEvent)
{
if(Win32Process->rpdeskStartup->pDeskInfo->ppiShellProcess == Win32Process)
{
DWORD ExitCode;
ExitCode = PsGetProcessExitStatus(Win32Process->peProcess);
DPRINT1("Shell process is exiting (%d)\n", ExitCode);
UserPostMessage(hwndSAS,
WM_LOGONNOTIFY,
LN_SHELL_EXITED,
ExitCode);
}
EngFreeMem(ppiCurrent->InputIdleEvent);
ppiCurrent->InputIdleEvent = NULL;
}
if (Win32Process->InputIdleEvent)
{
EngFreeMem((PVOID)Win32Process->InputIdleEvent);
Win32Process->InputIdleEvent = NULL;
}
IntCleanupMenus(Process, Win32Process);
IntCleanupCurIcons(Process, Win32Process);
IntCleanupMenus(Process, ppiCurrent);
IntCleanupCurIcons(Process, ppiCurrent);
/* no process windows should exist at this point, or the function will assert! */
DestroyProcessClasses(Win32Process);
Win32Process->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
DestroyProcessClasses(ppiCurrent);
ppiCurrent->W32PF_flags &= ~W32PF_CLASSESREGISTERED;
GDI_CleanupForProcess(Process);
@ -184,28 +181,28 @@ Win32kProcessCallback(struct _EPROCESS *Process,
/*
* Deregister logon application automatically
*/
if(LogonProcess == Win32Process)
if(LogonProcess == ppiCurrent)
{
LogonProcess = NULL;
}
/* Close the startup desktop */
ASSERT(Win32Process->rpdeskStartup);
ASSERT(Win32Process->hdeskStartup);
ObDereferenceObject(Win32Process->rpdeskStartup);
ZwClose(Win32Process->hdeskStartup);
ASSERT(ppiCurrent->rpdeskStartup);
ASSERT(ppiCurrent->hdeskStartup);
ObDereferenceObject(ppiCurrent->rpdeskStartup);
ZwClose(ppiCurrent->hdeskStartup);
/* Close the current window station */
UserSetProcessWindowStation(NULL);
/* Destroy GDI pools */
GdiPoolDestroy(Win32Process->pPoolDcAttr);
GdiPoolDestroy(Win32Process->pPoolBrushAttr);
GdiPoolDestroy(Win32Process->pPoolRgnAttr);
GdiPoolDestroy(ppiCurrent->pPoolDcAttr);
GdiPoolDestroy(ppiCurrent->pPoolBrushAttr);
GdiPoolDestroy(ppiCurrent->pPoolRgnAttr);
/* Ftee the PROCESSINFO */
PsSetProcessWin32Process(Process, NULL);
ExFreePoolWithTag(Win32Process, USERTAG_PROCESSINFO);
ExFreePoolWithTag(ppiCurrent, USERTAG_PROCESSINFO);
}
RETURN( STATUS_SUCCESS);
@ -226,23 +223,30 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
PTHREADINFO ptiCurrent;
int i;
NTSTATUS Status;
PTEB pTeb;
DPRINT("Enter Win32kThreadCallback\n");
UserEnterExclusive();
Process = Thread->ThreadsProcess;
pTeb = NtCurrentTeb();
/* Get the Win32 Thread */
ptiCurrent = PsGetThreadWin32Thread(Thread);
ASSERT(pTeb);
/* Allocate one if needed */
if (!ptiCurrent)
if (Type == PsW32ThreadCalloutInitialize)
{
/* FIXME: Lock the process */
HWINSTA hWinSta = NULL;
PCLIENTINFO pci;
HDESK hDesk = NULL;
PUNICODE_STRING DesktopPath;
PDESKTOP pdesk;
PRTL_USER_PROCESS_PARAMETERS ProcessParams = Process->Peb->ProcessParameters;
ASSERT(PsGetThreadWin32Thread(Thread)==NULL);
ptiCurrent = ExAllocatePoolWithTag(NonPagedPool,
sizeof(THREADINFO),
USERTAG_THREADINFO);
if (ptiCurrent == NULL)
{
Status = STATUS_NO_MEMORY;
@ -252,20 +256,12 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
RtlZeroMemory(ptiCurrent, sizeof(THREADINFO));
PsSetThreadWin32Thread(Thread, ptiCurrent);
/* FIXME: Unlock the process */
}
pTeb->Win32ThreadInfo = ptiCurrent;
ptiCurrent->pClientInfo = (PCLIENTINFO)pTeb->Win32ClientInfo;
if (Type == PsW32ThreadCalloutInitialize)
{
HWINSTA hWinSta = NULL;
PTEB pTeb;
HDESK hDesk = NULL;
PUNICODE_STRING DesktopPath;
PDESKTOP pdesk;
PRTL_USER_PROCESS_PARAMETERS ProcessParams = (Process->Peb ? Process->Peb->ProcessParameters : NULL);
DPRINT("Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
TRACE_CH(UserThread, "Creating W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
/* Initialize the THREADINFO */
InitializeListHead(&ptiCurrent->WindowListHead);
InitializeListHead(&ptiCurrent->W32CallbackListHead);
InitializeListHead(&ptiCurrent->PtiLink);
@ -273,25 +269,29 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
{
InitializeListHead(&ptiCurrent->aphkStart[i]);
}
ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
co_IntDestroyCaret(ptiCurrent);
ptiCurrent->pEThread = Thread;
ptiCurrent->ppi = PsGetCurrentProcessWin32Process();
ptiCurrent->ptiSibling = ptiCurrent->ppi->ptiList;
ptiCurrent->ppi->ptiList = ptiCurrent;
ptiCurrent->ppi->cThreads++;
if (ptiCurrent->rpdesk && !ptiCurrent->pDeskInfo)
{
ptiCurrent->pDeskInfo = ptiCurrent->rpdesk->pDeskInfo;
}
ptiCurrent->MessageQueue = MsqCreateMessageQueue(Thread);
ptiCurrent->KeyboardLayout = W32kGetDefaultKeyLayout();
if (ptiCurrent->KeyboardLayout)
UserReferenceObject(ptiCurrent->KeyboardLayout);
ptiCurrent->pEThread = Thread;
ptiCurrent->TIF_flags &= ~TIF_INCLEANUP;
/* HAAAAAAAACK! This should go to Win32kProcessCallback */
if(ptiCurrent->ppi->hdeskStartup == NULL)
/* Initialize the CLIENTINFO */
pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
RtlZeroMemory(pci, sizeof(CLIENTINFO));
pci->ppi = ptiCurrent->ppi;
pci->fsHooks = ptiCurrent->fsHooks;
pci->dwTIFlags = ptiCurrent->TIF_flags;
if (ptiCurrent->KeyboardLayout)
pci->hKL = ptiCurrent->KeyboardLayout->hkl;
/* Assign a default window station and desktop to the process */
/* Do not try to open a desktop or window station before winlogon initializes */
if(ptiCurrent->ppi->hdeskStartup == NULL && LogonProcess != NULL)
{
/*
* inherit the thread desktop and process window station (if not yet inherited) from the process startup
@ -302,74 +302,39 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
DesktopPath,
&hWinSta,
&hDesk);
if(NT_SUCCESS(Status))
if(!NT_SUCCESS(Status))
{
if(hWinSta != NULL)
{
if(!UserSetProcessWindowStation(hWinSta))
{
DPRINT1("Failed to set process window station\n");
}
}
if (hDesk != NULL)
{
/* Validate the new desktop. */
Status = IntValidateDesktopHandle(hDesk,
UserMode,
0,
&pdesk);
if(NT_SUCCESS(Status))
{
ptiCurrent->ppi->hdeskStartup = hDesk;
ptiCurrent->ppi->rpdeskStartup = pdesk;
}
}
ERR_CH(UserThread, "Failed to assign default dekstop and winsta to process\n");
goto leave;
}
else
if(!UserSetProcessWindowStation(hWinSta))
{
DPRINT1("No Desktop handle for this Thread!\n");
Status = STATUS_UNSUCCESSFUL;
goto leave;
}
/* Validate the new desktop. */
Status = IntValidateDesktopHandle(hDesk, UserMode, 0, &pdesk);
if(!NT_SUCCESS(Status))
{
goto leave;
}
/* Store the parsed desktop as the initial desktop */
ptiCurrent->ppi->hdeskStartup = hDesk;
ptiCurrent->ppi->rpdeskStartup = pdesk;
}
if (ptiCurrent->ppi->hdeskStartup != NULL)
{
if (!IntSetThreadDesktop(ptiCurrent->ppi->hdeskStartup, FALSE))
{
DPRINT1("Unable to set thread desktop\n");
ERR_CH(UserThread,"Unable to set thread desktop\n");
Status = STATUS_UNSUCCESSFUL;
goto leave;
}
}
pTeb = NtCurrentTeb();
if (pTeb)
{ /* Attempt to startup client support which should have been initialized in IntSetThreadDesktop. */
PCLIENTINFO pci = (PCLIENTINFO)pTeb->Win32ClientInfo;
ptiCurrent->pClientInfo = pci;
pci->ppi = ptiCurrent->ppi;
pci->fsHooks = ptiCurrent->fsHooks;
if (ptiCurrent->KeyboardLayout) pci->hKL = ptiCurrent->KeyboardLayout->hkl;
pci->dwTIFlags = ptiCurrent->TIF_flags;
/* CI may not have been initialized. */
if (!pci->pDeskInfo && ptiCurrent->pDeskInfo)
{
if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta();
pci->pDeskInfo = (PVOID)((ULONG_PTR)ptiCurrent->pDeskInfo - pci->ulClientDelta);
}
if (ptiCurrent->pcti && pci->pDeskInfo)
pci->pClientThreadInfo = (PVOID)((ULONG_PTR)ptiCurrent->pcti - pci->ulClientDelta);
else
pci->pClientThreadInfo = NULL;
}
else
{
DPRINT1("No TEB for this Thread!\n");
// System thread running! Now SendMessage should be okay.
ptiCurrent->pcti = &ptiCurrent->cti;
}
GetW32ThreadInfo();
}
else
{
@ -377,10 +342,16 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
PSINGLE_LIST_ENTRY psle;
PPROCESSINFO ppiCurrent;
DPRINT("Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
/* Get the Win32 Thread */
ptiCurrent = PsGetThreadWin32Thread(Thread);
ASSERT(ptiCurrent);
TRACE_CH(UserThread,"Destroying W32 thread TID:%d at IRQ level: %lu\n", Thread->Cid.UniqueThread, KeGetCurrentIrql());
ppiCurrent = ptiCurrent->ppi;
ptiCurrent->TIF_flags |= TIF_INCLEANUP;
ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
/* Find the THREADINFO in the PROCESSINFO's list */
ppti = &ppiCurrent->ptiList;
@ -407,6 +378,24 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
/* Unregister the api hook without blocking */
UserUnregisterUserApiHook();
}
/* Notify logon application to restart shell if needed */
if(ptiCurrent->pDeskInfo)
{
if(ptiCurrent->pDeskInfo->ppiShellProcess == ppiCurrent)
{
DWORD ExitCode = PsGetProcessExitStatus(Process);
TRACE_PPI(ppiCurrent, UserProcess, "Shell process is exiting (%d)\n", ExitCode);
UserPostMessage(hwndSAS,
WM_LOGONNOTIFY,
LN_SHELL_EXITED,
ExitCode);
ptiCurrent->pDeskInfo->ppiShellProcess = NULL;
}
}
}
DceFreeThreadDCE(ptiCurrent);
@ -418,7 +407,6 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
KeSetEvent(ptiCurrent->MessageQueue->NewMessages, IO_NO_INCREMENT, FALSE);
UnregisterThreadHotKeys(Thread);
/* what if this co_ func crash in umode? what will clean us up then? */
co_DestroyThreadWindows(Thread);
IntBlockInput(ptiCurrent, FALSE);
MsqDestroyMessageQueue(ptiCurrent->MessageQueue);
@ -431,7 +419,7 @@ Win32kThreadCallback(struct _ETHREAD *Thread,
while (psle)
{
PUSER_REFERENCE_ENTRY ref = CONTAINING_RECORD(psle, USER_REFERENCE_ENTRY, Entry);
DPRINT("thread clean: remove reference obj 0x%x\n",ref->obj);
TRACE_CH(UserThread,"thread clean: remove reference obj 0x%x\n",ref->obj);
UserDereferenceObject(ref->obj);
psle = PopEntryList(&ptiCurrent->ReferencesList);
@ -474,8 +462,8 @@ INIT_FUNCTION
NTSTATUS
APIENTRY
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
NTSTATUS Status;
BOOLEAN Result;
@ -513,11 +501,9 @@ DriverEntry(
/* Register our per-process and per-thread structures. */
PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
#if DBG_ENABLE_SERVICE_HOOKS
/* Register service hook callbacks */
KdSystemDebugControl('CsoR', DbgPreServiceHook, ID_Win32PreServiceHook, 0, 0, 0, 0);
KdSystemDebugControl('CsoR', DbgPostServiceHook, ID_Win32PostServiceHook, 0, 0, 0, 0);
#endif
/* Create the global USER heap */
GlobalUserHeap = UserCreateHeap(&GlobalUserHeapSection,

View file

@ -864,6 +864,7 @@ NtUserCreateDesktop(
/* Turn off hooks when calling any CreateWindowEx from inside win32k. */
NoHooks = (ptiCurrent->TIF_flags & TIF_DISABLEHOOKS);
ptiCurrent->TIF_flags |= TIF_DISABLEHOOKS;
ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
}
DesktopName.Buffer = NULL;
@ -1069,7 +1070,11 @@ CLEANUP:
{
ExFreePoolWithTag(DesktopName.Buffer, TAG_STRING);
}
if (!NoHooks && ptiCurrent) ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
if (!NoHooks && ptiCurrent)
{
ptiCurrent->TIF_flags &= ~TIF_DISABLEHOOKS;
ptiCurrent->pClientInfo->dwTIFlags = ptiCurrent->TIF_flags;
}
TRACE("Leave NtUserCreateDesktop, ret=%i\n",_ret_);
UserLeave();
END_CLEANUP;
@ -1676,15 +1681,14 @@ CLEANUP:
static NTSTATUS
IntUnmapDesktopView(IN PDESKTOP DesktopObject)
{
PTHREADINFO ti;
PPROCESSINFO CurrentWin32Process;
PPROCESSINFO ppi;
PW32HEAP_USER_MAPPING HeapMapping, *PrevLink;
NTSTATUS Status = STATUS_SUCCESS;
TRACE("DO %p\n");
CurrentWin32Process = PsGetCurrentProcessWin32Process();
PrevLink = &CurrentWin32Process->HeapMappings.Next;
ppi = PsGetCurrentProcessWin32Process();
PrevLink = &ppi->HeapMappings.Next;
/* Unmap if we're the last thread using the desktop */
HeapMapping = *PrevLink;
@ -1710,13 +1714,6 @@ IntUnmapDesktopView(IN PDESKTOP DesktopObject)
HeapMapping = HeapMapping->Next;
}
ti = GetW32ThreadInfo();
if (ti != NULL)
{
GetWin32ClientInfo()->pDeskInfo = NULL;
}
GetWin32ClientInfo()->ulClientDelta = 0;
return Status;
}
@ -1792,17 +1789,21 @@ BOOL
IntSetThreadDesktop(IN HDESK hDesktop,
IN BOOL FreeOnFailure)
{
PDESKTOP DesktopObject = NULL, OldDesktop;
HDESK hOldDesktop;
PTHREADINFO W32Thread;
PDESKTOP pdesk = NULL, pdeskOld;
HDESK hdeskOld;
PTHREADINFO pti;
NTSTATUS Status;
BOOL MapHeap;
CLIENTTHREADINFO ctiSave;
PCLIENTTHREADINFO pctiOld, pctiNew;
PCLIENTINFO pci;
ASSERT(NtCurrentTeb());
TRACE("IntSetThreadDesktop() , FOF=%d\n", FreeOnFailure);
MapHeap = (PsGetCurrentProcess() != PsInitialSystemProcess);
W32Thread = PsGetCurrentThreadWin32Thread();
pti = PsGetCurrentThreadWin32Thread();
pci = pti->pClientInfo;
/* If the caller gave us a desktop, ensure it is valid */
if(hDesktop != NULL)
{
/* Validate the new desktop. */
@ -1810,7 +1811,7 @@ IntSetThreadDesktop(IN HDESK hDesktop,
hDesktop,
UserMode,
0,
&DesktopObject);
&pdesk);
if (!NT_SUCCESS(Status))
{
@ -1818,106 +1819,113 @@ IntSetThreadDesktop(IN HDESK hDesktop,
return FALSE;
}
if (W32Thread->rpdesk == DesktopObject)
if (pti->rpdesk == pdesk)
{
/* Nothing to do */
ObDereferenceObject(DesktopObject);
ObDereferenceObject(pdesk);
return TRUE;
}
}
if (!IsListEmpty(&W32Thread->WindowListHead))
/* Make sure that we don't own any window in the current desktop */
if (!IsListEmpty(&pti->WindowListHead))
{
if(pdesk)
ObDereferenceObject(pdesk);
ERR("Attempted to change thread desktop although the thread has windows!\n");
EngSetLastError(ERROR_BUSY);
return FALSE;
}
OldDesktop = W32Thread->rpdesk;
hOldDesktop = W32Thread->hdesk;
W32Thread->rpdesk = DesktopObject;
W32Thread->hdesk = hDesktop;
if (MapHeap && DesktopObject != NULL)
/* Before doing the switch, map the new desktop heap and allocate the new pcti */
if(pdesk != NULL)
{
Status = IntMapDesktopView(DesktopObject);
Status = IntMapDesktopView(pdesk);
if (!NT_SUCCESS(Status))
{
ERR("Failed to map desktop heap!\n");
ObDereferenceObject(pdesk);
SetLastNtError(Status);
return FALSE;
}
W32Thread->pDeskInfo = DesktopObject->pDeskInfo;
pctiNew = DesktopHeapAlloc( pdesk, sizeof(CLIENTTHREADINFO));
if(pctiNew == NULL)
{
ERR("Failed to allocate new pcti\n");
IntUnmapDesktopView(pdesk);
ObDereferenceObject(pdesk);
EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
}
RtlZeroMemory(&ctiSave, sizeof(CLIENTTHREADINFO));
if (W32Thread->pcti && OldDesktop && NtCurrentTeb())
/* free all classes or move them to the shared heap */
if(pti->rpdesk != NULL)
{
RtlCopyMemory(&ctiSave, W32Thread->pcti, sizeof(CLIENTTHREADINFO));
TRACE("Free ClientThreadInfo\n");
DesktopHeapFree(OldDesktop, W32Thread->pcti);
W32Thread->pcti = NULL;
if(!IntCheckProcessDesktopClasses(pti->rpdesk, FreeOnFailure))
{
ERR("Failed to move process classes to shared heap!\n");
if(pdesk)
{
DesktopHeapFree(pdesk, pctiNew);
IntUnmapDesktopView(pdesk);
ObDereferenceObject(pdesk);
}
return FALSE;
}
}
if (!W32Thread->pcti && DesktopObject && NtCurrentTeb())
{
TRACE("Allocate ClientThreadInfo\n");
W32Thread->pcti = DesktopHeapAlloc( DesktopObject,
sizeof(CLIENTTHREADINFO));
RtlCopyMemory(W32Thread->pcti, &ctiSave, sizeof(CLIENTTHREADINFO));
}
pdeskOld = pti->rpdesk;
hdeskOld = pti->hdesk;
pctiOld = pti->pcti;
if (NtCurrentTeb())
/* do the switch */
if(pdesk != NULL)
{
PCLIENTINFO pci = GetWin32ClientInfo();
pti->rpdesk = pdesk;
pti->hdesk = hDesktop;
pti->pDeskInfo = pti->rpdesk->pDeskInfo;
pti->pcti = pctiNew;
pci->ulClientDelta = DesktopHeapGetUserDelta();
if (DesktopObject)
pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
pci->pClientThreadInfo = (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta);
/* initialize the new pcti */
if(pctiOld != NULL)
{
pci->pDeskInfo = (PVOID)((ULONG_PTR)DesktopObject->pDeskInfo - pci->ulClientDelta);
if (W32Thread->pcti) pci->pClientThreadInfo = (PVOID)((ULONG_PTR)W32Thread->pcti - pci->ulClientDelta);
RtlCopyMemory(pctiNew, pctiOld, sizeof(CLIENTTHREADINFO));
}
else
{
RtlZeroMemory(pctiNew, sizeof(CLIENTTHREADINFO));
}
}
if (OldDesktop != NULL &&
!IntCheckProcessDesktopClasses(OldDesktop,
FreeOnFailure))
else
{
ERR("Failed to move process classes to shared heap!\n");
/* Failed to move desktop classes to the shared heap,
unmap the view and return the error */
if (MapHeap && DesktopObject != NULL)
IntUnmapDesktopView(DesktopObject);
return FALSE;
pti->rpdesk = NULL;
pti->hdesk = NULL;
pti->pDeskInfo = NULL;
pti->pcti = NULL;
pci->ulClientDelta = 0;
pci->pDeskInfo = NULL;
pci->pClientThreadInfo = NULL;
}
/* clean up the old desktop */
if(pdeskOld != NULL)
{
RemoveEntryList(&pti->PtiLink);
DesktopHeapFree(pdeskOld, pctiOld);
IntUnmapDesktopView(pdeskOld);
ObDereferenceObject(pdeskOld);
ZwClose(hdeskOld);
}
/* Remove the thread from the old desktop's list */
RemoveEntryList(&W32Thread->PtiLink);
if (DesktopObject != NULL)
if(pdesk)
{
ObReferenceObject(DesktopObject);
/* Insert into new desktop's list */
InsertTailList(&DesktopObject->PtiList, &W32Thread->PtiLink);
}
/* Close the old desktop */
if (OldDesktop != NULL)
{
if (MapHeap)
{
IntUnmapDesktopView(OldDesktop);
}
ObDereferenceObject(OldDesktop);
}
if (hOldDesktop != NULL)
{
ZwClose(hOldDesktop);
InsertTailList(&pdesk->PtiList, &pti->PtiLink);
}
return TRUE;

View file

@ -141,8 +141,10 @@ RawInputThreadMain()
ByteOffset.QuadPart = (LONGLONG)0;
//WaitTimeout.QuadPart = (LONGLONG)(-10000000);
ptiRawInput = PsGetCurrentThreadWin32Thread();
ptiRawInput = GetW32ThreadInfo();
ptiRawInput->TIF_flags |= TIF_SYSTEMTHREAD;
ptiRawInput->pClientInfo->dwTIFlags = ptiRawInput->TIF_flags;
TRACE("Raw Input Thread 0x%x\n", ptiRawInput);
KeSetPriorityThread(&PsGetCurrentThread()->Tcb,

View file

@ -542,6 +542,68 @@ IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest,
return STATUS_SUCCESS;
}
void UserDbgAssertThreadInfo(BOOL showCaller)
{
PTEB Teb;
PPROCESSINFO ppi;
PCLIENTINFO pci;
PTHREADINFO pti;
ppi = PsGetCurrentProcessWin32Process();
pti = PsGetCurrentThreadWin32Thread();
Teb = NtCurrentTeb();
pci = GetWin32ClientInfo();
ASSERT(Teb);
ASSERT(pti);
ASSERT(pti->ppi == ppi);
ASSERT(pti->pClientInfo == pci);
ASSERT(Teb->Win32ThreadInfo == pti);
ASSERT(pci->ppi == ppi);
ASSERT(pci->fsHooks == pti->fsHooks);
ASSERT(pci->ulClientDelta == DesktopHeapGetUserDelta());
if (pti->pcti && pci->pDeskInfo)
ASSERT(pci->pClientThreadInfo == (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta));
if (pti->KeyboardLayout)
ASSERT(pci->hKL == pti->KeyboardLayout->hkl);
if(pti->rpdesk != NULL)
ASSERT(pti->pDeskInfo == pti->rpdesk->pDeskInfo);
/*too bad we still get this assertion*/
/* ASSERT(pci->dwTIFlags == pti->TIF_flags); */
if(pci->dwTIFlags != pti->TIF_flags)
{
ERR("pci->dwTIFlags(0x%x) doesn't match pti->TIF_flags(0x%x)\n", pci->dwTIFlags, pti->TIF_flags);
if(showCaller)
{
DbgPrint("Caller:\n");
KeRosDumpStackFrames(NULL, 10);
}
pci->dwTIFlags = pti->TIF_flags;
}
}
void
NTAPI
UserDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
{
UserDbgAssertThreadInfo(FALSE);
}
ULONG_PTR
NTAPI
UserDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
{
/* Make sure that the first syscall is NtUserInitialize */
/* too bad this fails */
//ASSERT(gbInitialized);
UserDbgAssertThreadInfo(TRUE);
return ulResult;
}
PPROCESSINFO
GetW32ProcessInfo(VOID)
{
@ -551,66 +613,8 @@ GetW32ProcessInfo(VOID)
PTHREADINFO
GetW32ThreadInfo(VOID)
{
PTEB Teb;
PPROCESSINFO ppi;
PCLIENTINFO pci;
PTHREADINFO pti = PsGetCurrentThreadWin32Thread();
if (pti == NULL)
{
/* FIXME: Temporary hack for system threads... */
return NULL;
}
/* Initialize it */
pti->ppi = ppi = GetW32ProcessInfo();
if (pti->rpdesk != NULL)
{
pti->pDeskInfo = pti->rpdesk->pDeskInfo;
}
else
{
pti->pDeskInfo = NULL;
}
/* Update the TEB */
Teb = NtCurrentTeb();
pci = GetWin32ClientInfo();
pti->pClientInfo = pci;
_SEH2_TRY
{
if(Teb)
{
ProbeForWrite( Teb,
sizeof(TEB),
sizeof(ULONG));
Teb->Win32ThreadInfo = (PW32THREAD) pti;
}
pci->ppi = ppi;
pci->fsHooks = pti->fsHooks;
if (pti->KeyboardLayout) pci->hKL = pti->KeyboardLayout->hkl;
pci->dwTIFlags = pti->TIF_flags;
/* CI may not have been initialized. */
if (!pci->pDeskInfo && pti->pDeskInfo)
{
if (!pci->ulClientDelta) pci->ulClientDelta = DesktopHeapGetUserDelta();
pci->pDeskInfo = (PVOID)((ULONG_PTR)pti->pDeskInfo - pci->ulClientDelta);
}
if (pti->pcti && pci->pDeskInfo)
pci->pClientThreadInfo = (PVOID)((ULONG_PTR)pti->pcti - pci->ulClientDelta);
else
pci->pClientThreadInfo = NULL;
}
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{
SetLastNtError(_SEH2_GetExceptionCode());
}
_SEH2_END;
return pti;
UserDbgAssertThreadInfo(TRUE);
return (PTHREADINFO)PsGetCurrentThreadWin32Thread();
}
/* EOF */

View file

@ -483,7 +483,7 @@ DbgCleanupEventList(PSLIST_HEADER pslh)
void
NTAPI
DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
GdiDbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
{
PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread();
if (pti && pti->cExclusiveLocks != 0)
@ -498,7 +498,7 @@ DbgPreServiceHook(ULONG ulSyscallId, PULONG_PTR pulArguments)
ULONG_PTR
NTAPI
DbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
GdiDbgPostServiceHook(ULONG ulSyscallId, ULONG_PTR ulResult)
{
PTHREADINFO pti = (PTHREADINFO)PsGetCurrentThreadWin32Thread();
if (pti && pti->cExclusiveLocks != 0)