2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: Driver entry and initialization of win32k
5 * FILE: win32ss/user/ntuser/main.c
18 NTSTATUS
ExitProcessCallback(PEPROCESS Process
);
19 NTSTATUS NTAPI
ExitThreadCallback(PETHREAD Thread
);
21 // TODO: Should be moved to some GDI header
22 NTSTATUS
GdiProcessCreate(PEPROCESS Process
);
23 NTSTATUS
GdiProcessDestroy(PEPROCESS Process
);
24 NTSTATUS
GdiThreadCreate(PETHREAD Thread
);
25 NTSTATUS
GdiThreadDestroy(PETHREAD Thread
);
27 PSERVERINFO gpsi
= NULL
; // Global User Server Information.
30 PPROCESSINFO ppiScrnSaver
;
31 PPROCESSINFO gppiList
= NULL
;
33 extern ULONG_PTR Win32kSSDT
[];
34 extern UCHAR Win32kSSPT
[];
35 extern ULONG Win32kNumberOfSysCalls
;
40 DbgPreServiceHook(ULONG ulSyscallId
, PULONG_PTR pulArguments
)
42 GdiDbgPreServiceHook(ulSyscallId
, pulArguments
);
43 UserDbgPreServiceHook(ulSyscallId
, pulArguments
);
48 DbgPostServiceHook(ULONG ulSyscallId
, ULONG_PTR ulResult
)
50 ulResult
= GdiDbgPostServiceHook(ulSyscallId
, ulResult
);
51 ulResult
= UserDbgPostServiceHook(ulSyscallId
, ulResult
);
58 AllocW32Process(IN PEPROCESS Process
,
59 OUT PPROCESSINFO
* W32Process
)
61 PPROCESSINFO ppiCurrent
;
63 TRACE_CH(UserProcess
, "In AllocW32Process(0x%p)\n", Process
);
65 /* Check that we were not called with an already existing Win32 process info */
66 ppiCurrent
= PsGetProcessWin32Process(Process
);
67 if (ppiCurrent
) return STATUS_SUCCESS
;
69 /* Allocate a new Win32 process info */
70 ppiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
73 if (ppiCurrent
== NULL
)
75 ERR_CH(UserProcess
, "Failed to allocate ppi for PID:0x%lx\n",
76 HandleToUlong(Process
->UniqueProcessId
));
77 return STATUS_NO_MEMORY
;
80 TRACE_CH(UserProcess
, "Allocated ppi 0x%p for PID:0x%lx\n",
81 ppiCurrent
, HandleToUlong(Process
->UniqueProcessId
));
83 RtlZeroMemory(ppiCurrent
, sizeof(*ppiCurrent
));
85 PsSetProcessWin32Process(Process
, ppiCurrent
, NULL
);
86 IntReferenceProcessInfo(ppiCurrent
);
88 *W32Process
= ppiCurrent
;
89 return STATUS_SUCCESS
;
92 #define FreeW32Process(/*Process*/ W32Process) \
94 /*PPROCESSINFO W32Process = PsGetProcessWin32Process(Process);*/ \
95 /*ASSERT(W32Process);*/ \
96 IntDereferenceProcessInfo(W32Process); \
100 * Called from IntDereferenceProcessInfo
103 UserDeleteW32Process(
104 _Pre_notnull_
__drv_freesMem(Mem
) PPROCESSINFO ppiCurrent
)
106 if (ppiCurrent
->InputIdleEvent
)
108 /* Free the allocated memory */
109 ExFreePoolWithTag(ppiCurrent
->InputIdleEvent
, USERTAG_EVENT
);
112 /* Close the startup desktop */
113 if (ppiCurrent
->rpdeskStartup
)
114 ObDereferenceObject(ppiCurrent
->rpdeskStartup
);
117 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent
, DbgChUserObj
, WARN_LEVEL
))
119 TRACE_PPI(ppiCurrent
, UserObj
, "Dumping user handles now that process info %p is gets freed.\n", ppiCurrent
);
120 DbgUserDumpHandleTable();
124 /* Free the PROCESSINFO */
125 ExFreePoolWithTag(ppiCurrent
, USERTAG_PROCESSINFO
);
129 UserProcessCreate(PEPROCESS Process
)
131 PPROCESSINFO ppiCurrent
= PsGetProcessWin32Process(Process
);
134 InitializeListHead(&ppiCurrent
->DriverObjListHead
);
135 ExInitializeFastMutex(&ppiCurrent
->DriverObjListLock
);
137 ppiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
141 /* Allocate memory for the event structure */
142 Event
= ExAllocatePoolWithTag(NonPagedPool
,
147 /* Initialize the kernel event */
148 KeInitializeEvent(Event
,
149 SynchronizationEvent
,
155 DPRINT("CreateEvent() failed\n");
160 ppiCurrent
->InputIdleEvent
= Event
;
161 KeInitializeEvent(ppiCurrent
->InputIdleEvent
, NotificationEvent
, FALSE
);
164 ppiCurrent
->peProcess
= Process
;
165 ppiCurrent
->W32Pid
= HandleToUlong(PsGetProcessId(Process
));
167 /* Setup process flags */
168 ppiCurrent
->W32PF_flags
|= W32PF_PROCESSCONNECTED
;
169 if ( Process
->Peb
->ProcessParameters
&&
170 Process
->Peb
->ProcessParameters
->WindowFlags
& STARTF_SCRNSAVER
)
172 ppiScrnSaver
= ppiCurrent
;
173 ppiCurrent
->W32PF_flags
|= W32PF_SCREENSAVER
;
176 // FIXME: check if this process is allowed.
177 ppiCurrent
->W32PF_flags
|= W32PF_ALLOWFOREGROUNDACTIVATE
; // Starting application will get it toggled off.
179 return STATUS_SUCCESS
;
183 UserProcessDestroy(PEPROCESS Process
)
185 PPROCESSINFO ppiCurrent
= PsGetProcessWin32Process(Process
);
188 if (ppiScrnSaver
== ppiCurrent
)
191 /* Destroy user objects */
192 UserDestroyObjectsForOwner(gHandleTable
, ppiCurrent
);
194 TRACE_CH(UserProcess
, "Freeing ppi 0x%p\n", ppiCurrent
);
196 if (DBG_IS_CHANNEL_ENABLED(ppiCurrent
, DbgChUserObj
, WARN_LEVEL
))
198 TRACE_CH(UserObj
, "Dumping user handles at the end of the process %s (Info %p).\n",
199 ppiCurrent
->peProcess
->ImageFileName
, ppiCurrent
);
200 DbgUserDumpHandleTable();
204 /* Remove it from the list of GUI apps */
205 co_IntGraphicsCheck(FALSE
);
208 * Deregister logon application automatically
210 if (gpidLogon
== ppiCurrent
->peProcess
->UniqueProcessId
)
213 /* Close the current window station */
214 UserSetProcessWindowStation(NULL
);
216 if (gppiInputProvider
== ppiCurrent
) gppiInputProvider
= NULL
;
218 if (ppiCurrent
->hdeskStartup
)
220 ZwClose(ppiCurrent
->hdeskStartup
);
221 ppiCurrent
->hdeskStartup
= NULL
;
224 /* Clean up the process icon cache */
225 IntCleanupCurIconCache(ppiCurrent
);
227 return STATUS_SUCCESS
;
231 InitProcessCallback(PEPROCESS Process
)
234 PPROCESSINFO ppiCurrent
;
235 PVOID KernelMapping
= NULL
, UserMapping
= NULL
;
237 /* We might be called with an already allocated win32 process */
238 ppiCurrent
= PsGetProcessWin32Process(Process
);
239 if (ppiCurrent
!= NULL
)
241 /* There is no more to do for us (this is a success code!) */
242 return STATUS_ALREADY_WIN32
;
244 // if (ppiCurrent->W32PF_flags & W32PF_PROCESSCONNECTED)
245 // return STATUS_ALREADY_WIN32;
247 /* Allocate a new Win32 process info */
248 Status
= AllocW32Process(Process
, &ppiCurrent
);
249 if (!NT_SUCCESS(Status
))
251 ERR_CH(UserProcess
, "Failed to allocate ppi for PID:0x%lx\n",
252 HandleToUlong(Process
->UniqueProcessId
));
257 DbgInitDebugChannels();
259 KdRosRegisterCliCallback(DbgGdiKdbgCliCallback
);
263 /* Map the global user heap into the process */
264 Status
= MapGlobalUserHeap(Process
, &KernelMapping
, &UserMapping
);
265 if (!NT_SUCCESS(Status
))
267 TRACE_CH(UserProcess
, "Failed to map the global heap! 0x%x\n", Status
);
271 TRACE_CH(UserProcess
, "InitProcessCallback -- We have KernelMapping 0x%p and UserMapping 0x%p with delta = 0x%x\n",
272 KernelMapping
, UserMapping
, (ULONG_PTR
)KernelMapping
- (ULONG_PTR
)UserMapping
);
274 /* Initialize USER process info */
275 Status
= UserProcessCreate(Process
);
276 if (!NT_SUCCESS(Status
))
278 ERR_CH(UserProcess
, "UserProcessCreate failed, Status 0x%08lx\n", Status
);
282 /* Initialize GDI process info */
283 Status
= GdiProcessCreate(Process
);
284 if (!NT_SUCCESS(Status
))
286 ERR_CH(UserProcess
, "GdiProcessCreate failed, Status 0x%08lx\n", Status
);
290 /* Add the process to the global list */
291 ppiCurrent
->ppiNext
= gppiList
;
292 gppiList
= ppiCurrent
;
294 return STATUS_SUCCESS
;
297 ERR_CH(UserProcess
, "InitProcessCallback failed! Freeing ppi 0x%p for PID:0x%lx\n",
298 ppiCurrent
, HandleToUlong(Process
->UniqueProcessId
));
299 ExitProcessCallback(Process
);
304 ExitProcessCallback(PEPROCESS Process
)
306 PPROCESSINFO ppiCurrent
, *pppi
;
308 /* Get the Win32 Process */
309 ppiCurrent
= PsGetProcessWin32Process(Process
);
311 ASSERT(ppiCurrent
->peProcess
== Process
);
313 TRACE_CH(UserProcess
, "Destroying ppi 0x%p\n", ppiCurrent
);
314 ppiCurrent
->W32PF_flags
|= W32PF_TERMINATED
;
316 /* Remove it from the list */
318 while (*pppi
!= NULL
&& *pppi
!= ppiCurrent
)
320 pppi
= &(*pppi
)->ppiNext
;
322 ASSERT(*pppi
== ppiCurrent
);
323 *pppi
= ppiCurrent
->ppiNext
;
325 /* Cleanup GDI info */
326 GdiProcessDestroy(Process
);
328 /* Cleanup USER info */
329 UserProcessDestroy(Process
);
331 /* The process is dying */
332 PsSetProcessWin32Process(Process
, NULL
, ppiCurrent
);
333 ppiCurrent
->peProcess
= NULL
;
335 /* Finally, dereference */
336 FreeW32Process(/*Process*/ ppiCurrent
); // IntDereferenceProcessInfo(ppiCurrent);
338 return STATUS_SUCCESS
;
343 Win32kProcessCallback(PEPROCESS Process
,
348 ASSERT(Process
->Peb
);
350 TRACE_CH(UserProcess
, "Win32kProcessCallback -->\n");
352 UserEnterExclusive();
356 Status
= InitProcessCallback(Process
);
360 Status
= ExitProcessCallback(Process
);
365 TRACE_CH(UserProcess
, "<-- Win32kProcessCallback\n");
373 AllocW32Thread(IN PETHREAD Thread
,
374 OUT PTHREADINFO
* W32Thread
)
376 PTHREADINFO ptiCurrent
;
378 TRACE_CH(UserThread
, "In AllocW32Thread(0x%p)\n", Thread
);
380 /* Check that we were not called with an already existing Win32 thread info */
381 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
382 NT_ASSERT(ptiCurrent
== NULL
);
384 /* Allocate a new Win32 thread info */
385 ptiCurrent
= ExAllocatePoolWithTag(NonPagedPool
,
388 if (ptiCurrent
== NULL
)
390 ERR_CH(UserThread
, "Failed to allocate pti for TID:0x%lx\n",
391 HandleToUlong(Thread
->Cid
.UniqueThread
));
392 return STATUS_NO_MEMORY
;
395 TRACE_CH(UserThread
, "Allocated pti 0x%p for TID:0x%lx\n",
396 ptiCurrent
, HandleToUlong(Thread
->Cid
.UniqueThread
));
398 RtlZeroMemory(ptiCurrent
, sizeof(*ptiCurrent
));
400 PsSetThreadWin32Thread(Thread
, ptiCurrent
, NULL
);
401 IntReferenceThreadInfo(ptiCurrent
);
403 *W32Thread
= ptiCurrent
;
404 return STATUS_SUCCESS
;
407 #define FreeW32Thread(/*Thread*/ W32Thread) \
409 /*PTHREADINFO W32Thread = PsGetThreadWin32Thread(Thread);*/ \
410 /*ASSERT(W32Thread);*/ \
411 IntDereferenceThreadInfo(W32Thread); \
415 * Called from IntDereferenceThreadInfo
418 UserDeleteW32Thread(PTHREADINFO pti
)
420 PPROCESSINFO ppi
= pti
->ppi
;
422 TRACE_CH(UserThread
, "UserDeleteW32Thread pti 0x%p\n",pti
);
424 /* Free the message queue */
425 if (pti
->MessageQueue
)
427 MsqDestroyMessageQueue(pti
);
430 MsqCleanupThreadMsgs(pti
);
432 ExFreePoolWithTag(pti
, USERTAG_THREADINFO
);
434 IntDereferenceProcessInfo(ppi
);
438 UserThreadCreate(PETHREAD Thread
)
440 return STATUS_SUCCESS
;
444 UserThreadDestroy(PETHREAD Thread
)
446 return STATUS_SUCCESS
;
450 InitThreadCallback(PETHREAD Thread
)
454 PTHREADINFO ptiCurrent
;
456 NTSTATUS Status
= STATUS_SUCCESS
;
458 LARGE_INTEGER LargeTickCount
;
459 PRTL_USER_PROCESS_PARAMETERS ProcessParams
;
461 Process
= Thread
->ThreadsProcess
;
463 pTeb
= NtCurrentTeb();
466 ProcessParams
= pTeb
->ProcessEnvironmentBlock
->ProcessParameters
;
468 /* Allocate a new Win32 thread info */
469 Status
= AllocW32Thread(Thread
, &ptiCurrent
);
470 if (!NT_SUCCESS(Status
))
472 ERR_CH(UserThread
, "Failed to allocate pti for TID:0x%lx\n",
473 HandleToUlong(Thread
->Cid
.UniqueThread
));
477 /* Initialize the THREADINFO */
478 ptiCurrent
->pEThread
= Thread
;
479 ptiCurrent
->ppi
= PsGetProcessWin32Process(Process
);
480 IntReferenceProcessInfo(ptiCurrent
->ppi
);
481 pTeb
->Win32ThreadInfo
= ptiCurrent
;
482 ptiCurrent
->pClientInfo
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
484 /* Mark the process as having threads */
485 ptiCurrent
->ppi
->W32PF_flags
|= W32PF_THREADCONNECTED
;
487 InitializeListHead(&ptiCurrent
->WindowListHead
);
488 InitializeListHead(&ptiCurrent
->W32CallbackListHead
);
489 InitializeListHead(&ptiCurrent
->PostedMessagesListHead
);
490 InitializeListHead(&ptiCurrent
->SentMessagesListHead
);
491 InitializeListHead(&ptiCurrent
->PtiLink
);
492 for (i
= 0; i
< NB_HOOKS
; i
++)
494 InitializeListHead(&ptiCurrent
->aphkStart
[i
]);
496 ptiCurrent
->ptiSibling
= ptiCurrent
->ppi
->ptiList
;
497 ptiCurrent
->ppi
->ptiList
= ptiCurrent
;
498 ptiCurrent
->ppi
->cThreads
++;
500 ptiCurrent
->hEventQueueClient
= NULL
;
501 Status
= ZwCreateEvent(&ptiCurrent
->hEventQueueClient
, EVENT_ALL_ACCESS
,
502 NULL
, SynchronizationEvent
, FALSE
);
503 if (!NT_SUCCESS(Status
))
505 ERR_CH(UserThread
, "Event creation failed, Status 0x%08x.\n", Status
);
508 Status
= ObReferenceObjectByHandle(ptiCurrent
->hEventQueueClient
, 0,
509 *ExEventObjectType
, UserMode
,
510 (PVOID
*)&ptiCurrent
->pEventQueueServer
, NULL
);
511 if (!NT_SUCCESS(Status
))
513 ERR_CH(UserThread
, "Failed referencing the event object, Status 0x%08x.\n", Status
);
514 ObCloseHandle(ptiCurrent
->hEventQueueClient
, UserMode
);
515 ptiCurrent
->hEventQueueClient
= NULL
;
519 KeQueryTickCount(&LargeTickCount
);
520 ptiCurrent
->timeLast
= LargeTickCount
.u
.LowPart
;
522 ptiCurrent
->MessageQueue
= MsqCreateMessageQueue(ptiCurrent
);
523 if (ptiCurrent
->MessageQueue
== NULL
)
525 ERR_CH(UserThread
, "Failed to allocate message loop\n");
526 Status
= STATUS_NO_MEMORY
;
530 ptiCurrent
->KeyboardLayout
= W32kGetDefaultKeyLayout();
531 if (ptiCurrent
->KeyboardLayout
)
532 UserReferenceObject(ptiCurrent
->KeyboardLayout
);
534 ptiCurrent
->TIF_flags
&= ~TIF_INCLEANUP
;
536 /* CSRSS threads have some special features */
537 if (Process
== gpepCSRSS
)
538 ptiCurrent
->TIF_flags
= TIF_CSRSSTHREAD
| TIF_DONTATTACHQUEUE
;
540 // FIXME: Flag SYSTEM threads with... TIF_SYSTEMTHREAD !!
542 ptiCurrent
->pcti
= &ptiCurrent
->cti
;
544 /* Initialize the CLIENTINFO */
545 pci
= (PCLIENTINFO
)pTeb
->Win32ClientInfo
;
546 RtlZeroMemory(pci
, sizeof(*pci
));
547 pci
->ppi
= ptiCurrent
->ppi
;
548 pci
->fsHooks
= ptiCurrent
->fsHooks
;
549 pci
->dwTIFlags
= ptiCurrent
->TIF_flags
;
550 if (ptiCurrent
->KeyboardLayout
)
552 pci
->hKL
= ptiCurrent
->KeyboardLayout
->hkl
;
553 pci
->CodePage
= ptiCurrent
->KeyboardLayout
->CodePage
;
556 /* Need to pass the user Startup Information to the current process. */
559 if ( ptiCurrent
->ppi
->usi
.cb
== 0 ) // Not initialized yet.
561 if ( ProcessParams
->WindowFlags
!= 0 ) // Need window flags set.
563 ptiCurrent
->ppi
->usi
.cb
= sizeof(USERSTARTUPINFO
);
564 ptiCurrent
->ppi
->usi
.dwX
= ProcessParams
->StartingX
;
565 ptiCurrent
->ppi
->usi
.dwY
= ProcessParams
->StartingY
;
566 ptiCurrent
->ppi
->usi
.dwXSize
= ProcessParams
->CountX
;
567 ptiCurrent
->ppi
->usi
.dwYSize
= ProcessParams
->CountY
;
568 ptiCurrent
->ppi
->usi
.dwFlags
= ProcessParams
->WindowFlags
;
569 ptiCurrent
->ppi
->usi
.wShowWindow
= (WORD
)ProcessParams
->ShowWindowFlags
;
574 /* Assign a default window station and desktop to the process */
575 /* Do not try to open a desktop or window station before winlogon initializes */
576 if (ptiCurrent
->ppi
->hdeskStartup
== NULL
&& gpidLogon
!= 0)
578 HWINSTA hWinSta
= NULL
;
580 UNICODE_STRING DesktopPath
;
584 * inherit the thread desktop and process window station (if not yet inherited) from the process startup
585 * info structure. See documentation of CreateProcess()
588 Status
= STATUS_UNSUCCESSFUL
;
589 if (ProcessParams
&& ProcessParams
->DesktopInfo
.Length
> 0)
591 Status
= IntSafeCopyUnicodeStringTerminateNULL(&DesktopPath
, &ProcessParams
->DesktopInfo
);
593 if (!NT_SUCCESS(Status
))
595 RtlInitUnicodeString(&DesktopPath
, NULL
);
598 Status
= IntParseDesktopPath(Process
,
603 if (DesktopPath
.Buffer
)
604 ExFreePoolWithTag(DesktopPath
.Buffer
, TAG_STRING
);
606 if (!NT_SUCCESS(Status
))
608 ERR_CH(UserThread
, "Failed to assign default dekstop and winsta to process\n");
612 if (!UserSetProcessWindowStation(hWinSta
))
614 Status
= STATUS_UNSUCCESSFUL
;
615 ERR_CH(UserThread
, "Failed to set initial process winsta\n");
619 /* Validate the new desktop. */
620 Status
= IntValidateDesktopHandle(hDesk
, UserMode
, 0, &pdesk
);
621 if (!NT_SUCCESS(Status
))
623 ERR_CH(UserThread
, "Failed to validate initial desktop handle\n");
627 /* Store the parsed desktop as the initial desktop */
628 ptiCurrent
->ppi
->hdeskStartup
= hDesk
;
629 ptiCurrent
->ppi
->rpdeskStartup
= pdesk
;
632 if (ptiCurrent
->ppi
->hdeskStartup
!= NULL
)
634 if (!IntSetThreadDesktop(ptiCurrent
->ppi
->hdeskStartup
, FALSE
))
636 ERR_CH(UserThread
, "Failed to set thread desktop\n");
637 Status
= STATUS_UNSUCCESSFUL
;
642 /* Mark the thread as fully initialized */
643 ptiCurrent
->TIF_flags
|= TIF_GUITHREADINITIALIZED
;
645 if (!(ptiCurrent
->ppi
->W32PF_flags
& (W32PF_ALLOWFOREGROUNDACTIVATE
| W32PF_APPSTARTING
)) &&
646 (gptiForeground
&& gptiForeground
->ppi
== ptiCurrent
->ppi
))
648 ptiCurrent
->TIF_flags
|= TIF_ALLOWFOREGROUNDACTIVATE
;
650 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
652 /* Last things to do only if we are not a SYSTEM or CSRSS thread */
653 if (!(ptiCurrent
->TIF_flags
& (TIF_SYSTEMTHREAD
| TIF_CSRSSTHREAD
)))
655 /* Callback to User32 Client Thread Setup */
656 TRACE_CH(UserThread
, "Call co_IntClientThreadSetup...\n");
657 Status
= co_IntClientThreadSetup();
658 if (!NT_SUCCESS(Status
))
660 ERR_CH(UserThread
, "ClientThreadSetup failed with Status 0x%08lx\n", Status
);
663 TRACE_CH(UserThread
, "co_IntClientThreadSetup succeeded!\n");
667 TRACE_CH(UserThread
, "co_IntClientThreadSetup cannot be called...\n");
670 TRACE_CH(UserThread
, "UserCreateW32Thread pti 0x%p\n", ptiCurrent
);
671 return STATUS_SUCCESS
;
674 ERR_CH(UserThread
, "InitThreadCallback failed! Freeing pti 0x%p for TID:0x%lx\n",
675 ptiCurrent
, HandleToUlong(Thread
->Cid
.UniqueThread
));
676 ExitThreadCallback(Thread
);
681 UserDisplayNotifyShutdown(PPROCESSINFO ppiCurrent
);
685 ExitThreadCallback(PETHREAD Thread
)
688 PSINGLE_LIST_ENTRY psle
;
689 PPROCESSINFO ppiCurrent
;
691 PTHREADINFO ptiCurrent
;
693 Process
= Thread
->ThreadsProcess
;
695 /* Get the Win32 Thread */
696 ptiCurrent
= PsGetThreadWin32Thread(Thread
);
699 TRACE_CH(UserThread
, "Destroying pti 0x%p eThread 0x%p\n", ptiCurrent
, Thread
);
701 ptiCurrent
->TIF_flags
|= TIF_INCLEANUP
;
702 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
704 ppiCurrent
= ptiCurrent
->ppi
;
707 IsRemoveAttachThread(ptiCurrent
);
709 ptiCurrent
->TIF_flags
|= TIF_DONTATTACHQUEUE
;
710 ptiCurrent
->pClientInfo
->dwTIFlags
= ptiCurrent
->TIF_flags
;
712 /* Decrement thread count and check if its 0 */
713 ppiCurrent
->cThreads
--;
715 if (ptiCurrent
->TIF_flags
& TIF_GUITHREADINITIALIZED
)
717 /* Do now some process cleanup that requires a valid win32 thread */
718 if (ptiCurrent
->ppi
->cThreads
== 0)
720 /* Check if we have registered the user api hook */
721 if (ptiCurrent
->ppi
== ppiUahServer
)
723 /* Unregister the api hook */
724 UserUnregisterUserApiHook();
727 /* Notify logon application to restart shell if needed */
728 if (ptiCurrent
->pDeskInfo
)
730 if (ptiCurrent
->pDeskInfo
->ppiShellProcess
== ppiCurrent
)
732 DWORD ExitCode
= PsGetProcessExitStatus(Process
);
734 TRACE_CH(UserProcess
, "Shell process is exiting (%lu)\n", ExitCode
);
736 UserPostMessage(hwndSAS
,
741 ptiCurrent
->pDeskInfo
->ppiShellProcess
= NULL
;
746 DceFreeThreadDCE(ptiCurrent
);
747 DestroyTimersForThread(ptiCurrent
);
748 KeSetEvent(ptiCurrent
->pEventQueueServer
, IO_NO_INCREMENT
, FALSE
);
749 UnregisterThreadHotKeys(ptiCurrent
);
751 if (!UserDestroyObjectsForOwner(gHandleTable
, ptiCurrent
))
753 DPRINT1("Failed to delete objects belonging to thread %p. This is VERY BAD!.\n", ptiCurrent
);
755 return STATUS_UNSUCCESSFUL
;
758 if (ppiCurrent
&& ppiCurrent
->ptiList
== ptiCurrent
&& !ptiCurrent
->ptiSibling
&&
759 ppiCurrent
->W32PF_flags
& W32PF_CLASSESREGISTERED
)
761 TRACE_CH(UserThread
, "DestroyProcessClasses\n");
762 /* no process windows should exist at this point, or the function will assert! */
763 DestroyProcessClasses(ppiCurrent
);
764 ppiCurrent
->W32PF_flags
&= ~W32PF_CLASSESREGISTERED
;
767 IntBlockInput(ptiCurrent
, FALSE
);
768 IntCleanupThreadCallbacks(ptiCurrent
);
770 /* cleanup user object references stack */
771 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
774 PUSER_REFERENCE_ENTRY ref
= CONTAINING_RECORD(psle
, USER_REFERENCE_ENTRY
, Entry
);
775 TRACE_CH(UserThread
, "thread clean: remove reference obj 0x%p\n",ref
->obj
);
776 UserDereferenceObject(ref
->obj
);
778 psle
= PopEntryList(&ptiCurrent
->ReferencesList
);
782 if (ptiCurrent
->cEnterCount
)
784 KeSetKernelStackSwapEnable(TRUE
);
785 ptiCurrent
->cEnterCount
= 0;
788 /* Find the THREADINFO in the PROCESSINFO's list */
789 ppti
= &ppiCurrent
->ptiList
;
790 while (*ppti
!= NULL
&& *ppti
!= ptiCurrent
)
792 ppti
= &((*ppti
)->ptiSibling
);
795 /* we must have found it */
796 ASSERT(*ppti
== ptiCurrent
);
798 /* Remove it from the list */
799 *ppti
= ptiCurrent
->ptiSibling
;
801 if (ptiCurrent
->KeyboardLayout
)
802 UserDereferenceObject(ptiCurrent
->KeyboardLayout
);
804 if (gptiForeground
== ptiCurrent
)
806 // IntNotifyWinEvent(EVENT_OBJECT_FOCUS, NULL, OBJID_CLIENT, CHILDID_SELF, 0);
807 // IntNotifyWinEvent(EVENT_SYSTEM_FOREGROUND, NULL, OBJID_WINDOW, CHILDID_SELF, 0);
809 gptiForeground
= NULL
;
812 /* Restore display mode when we are the last thread, and we changed the display mode */
813 if (ppiCurrent
->cThreads
== 0)
814 UserDisplayNotifyShutdown(ppiCurrent
);
817 // Fixes CORE-6384 & CORE-7030.
818 /* if (ptiLastInput == ptiCurrent)
820 if (!ppiCurrent->ptiList)
821 ptiLastInput = gptiForeground;
823 ptiLastInput = ppiCurrent->ptiList;
824 ERR_CH(UserThread, "DTI: ptiLastInput is Cleared!!\n");
827 TRACE_CH(UserThread
, "Freeing pti 0x%p\n", ptiCurrent
);
829 IntSetThreadDesktop(NULL
, TRUE
);
831 if (ptiCurrent
->hEventQueueClient
!= NULL
)
833 ObCloseHandle(ptiCurrent
->hEventQueueClient
, UserMode
);
834 ObDereferenceObject(ptiCurrent
->pEventQueueServer
);
836 ptiCurrent
->hEventQueueClient
= NULL
;
838 /* The thread is dying */
839 PsSetThreadWin32Thread(Thread
/*ptiCurrent->pEThread*/, NULL
, ptiCurrent
);
840 ptiCurrent
->pEThread
= NULL
;
842 /* Free the THREADINFO */
843 FreeW32Thread(/*Thread*/ ptiCurrent
); // IntDereferenceThreadInfo(ptiCurrent);
845 return STATUS_SUCCESS
;
850 Win32kThreadCallback(PETHREAD Thread
,
851 PSW32THREADCALLOUTTYPE Type
)
855 ASSERT(NtCurrentTeb());
857 UserEnterExclusive();
859 if (Type
== PsW32ThreadCalloutInitialize
)
861 ASSERT(PsGetThreadWin32Thread(Thread
) == NULL
);
862 Status
= InitThreadCallback(Thread
);
864 else // if (Type == PsW32ThreadCalloutExit)
866 ASSERT(PsGetThreadWin32Thread(Thread
) != NULL
);
867 Status
= ExitThreadCallback(Thread
);
875 _Function_class_(DRIVER_UNLOAD
)
877 DriverUnload(IN PDRIVER_OBJECT DriverObject
)
879 // TODO: Do more cleanup!
889 if (!NT_SUCCESS(Status)) \
891 DPRINT1("Failed '%s' (0x%lx)\n", #x, Status); \
897 * This definition doesn't work
903 IN PDRIVER_OBJECT DriverObject
,
904 IN PUNICODE_STRING RegistryPath
)
908 WIN32_CALLOUTS_FPNS CalloutData
= {0};
909 PVOID GlobalUserHeapBase
= NULL
;
912 * Register user mode call interface
913 * (system service table index = 1)
915 Result
= KeAddSystemServiceTable(Win32kSSDT
,
917 Win32kNumberOfSysCalls
,
922 DPRINT1("Adding system services failed!\n");
923 return STATUS_UNSUCCESSFUL
;
926 hModuleWin
= MmPageEntireDriver(DriverEntry
);
927 DPRINT("Win32k hInstance 0x%p!\n", hModuleWin
);
929 DriverObject
->DriverUnload
= DriverUnload
;
931 /* Register Object Manager Callbacks */
932 CalloutData
.ProcessCallout
= Win32kProcessCallback
;
933 CalloutData
.ThreadCallout
= Win32kThreadCallback
;
934 // CalloutData.GlobalAtomTableCallout = NULL;
935 // CalloutData.PowerEventCallout = NULL;
936 // CalloutData.PowerStateCallout = NULL;
937 // CalloutData.JobCallout = NULL;
938 CalloutData
.BatchFlushRoutine
= NtGdiFlushUserBatch
;
939 CalloutData
.DesktopOpenProcedure
= IntDesktopObjectOpen
;
940 CalloutData
.DesktopOkToCloseProcedure
= IntDesktopOkToClose
;
941 CalloutData
.DesktopCloseProcedure
= IntDesktopObjectClose
;
942 CalloutData
.DesktopDeleteProcedure
= IntDesktopObjectDelete
;
943 CalloutData
.WindowStationOkToCloseProcedure
= IntWinstaOkToClose
;
944 // CalloutData.WindowStationCloseProcedure = NULL;
945 CalloutData
.WindowStationDeleteProcedure
= IntWinStaObjectDelete
;
946 CalloutData
.WindowStationParseProcedure
= IntWinStaObjectParse
;
947 // CalloutData.WindowStationOpenProcedure = NULL;
949 /* Register our per-process and per-thread structures. */
950 PsEstablishWin32Callouts(&CalloutData
);
952 /* Register service hook callbacks */
953 #if DBG && defined(KDBG)
954 KdSystemDebugControl('CsoR', DbgPreServiceHook
, ID_Win32PreServiceHook
, 0, 0, 0, 0);
955 KdSystemDebugControl('CsoR', DbgPostServiceHook
, ID_Win32PostServiceHook
, 0, 0, 0, 0);
958 /* Create the global USER heap */
959 GlobalUserHeap
= UserCreateHeap(&GlobalUserHeapSection
,
961 1 * 1024 * 1024); /* FIXME: 1 MB for now... */
962 if (GlobalUserHeap
== NULL
)
964 DPRINT1("Failed to initialize the global heap!\n");
965 return STATUS_UNSUCCESSFUL
;
968 /* Allocate global server info structure */
969 gpsi
= UserHeapAlloc(sizeof(*gpsi
));
972 DPRINT1("Failed allocate server info structure!\n");
973 return STATUS_UNSUCCESSFUL
;
976 RtlZeroMemory(gpsi
, sizeof(*gpsi
));
977 DPRINT("Global Server Data -> %p\n", gpsi
);
979 NT_ROF(InitGdiHandleTable());
980 NT_ROF(InitPaletteImpl());
982 /* Create stock objects, ie. precreated objects commonly
983 used by win32 applications */
984 CreateStockObjects();
985 CreateSysColorObjects();
987 NT_ROF(InitBrushImpl());
988 NT_ROF(InitPDEVImpl());
989 NT_ROF(InitLDEVImpl());
990 NT_ROF(InitDeviceImpl());
991 NT_ROF(InitDcImpl());
992 NT_ROF(InitUserImpl());
993 NT_ROF(InitWindowStationImpl());
994 NT_ROF(InitDesktopImpl());
995 NT_ROF(InitInputImpl());
996 NT_ROF(InitKeyboardImpl());
997 NT_ROF(MsqInitializeImpl());
998 NT_ROF(InitTimerImpl());
999 NT_ROF(InitDCEImpl());
1001 /* Initialize FreeType library */
1002 if (!InitFontSupport())
1004 DPRINT1("Unable to initialize font support\n");
1008 gusLanguageID
= UserGetLanguageID();
1010 return STATUS_SUCCESS
;