2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ps/win32.c
5 * PURPOSE: Process Manager: Win32K Initialization and Support
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
9 /* INCLUDES ****************************************************************/
15 /* GLOBALS ******************************************************************/
17 PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout
= NULL
;
18 PKWIN32_THREAD_CALLOUT PspW32ThreadCallout
= NULL
;
19 PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch
= NULL
;
20 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectParse
;
21 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectDelete
;
22 extern PKWIN32_SESSION_CALLOUT ExpWindowStationObjectOkToClose
;
23 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOkToClose
;
24 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectDelete
;
25 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectOpen
;
26 extern PKWIN32_SESSION_CALLOUT ExpDesktopObjectClose
;
27 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout
;
29 /* PRIVATE FUNCTIONS *********************************************************/
33 PsConvertToGuiThread(VOID
)
37 PETHREAD Thread
= PsGetCurrentThread();
38 PEPROCESS Process
= PsGetCurrentProcess();
42 /* Validate the previous mode */
43 if (KeGetPreviousMode() == KernelMode
) return STATUS_INVALID_PARAMETER
;
45 /* If no win32k, crashes later */
46 ASSERT(PspW32ProcessCallout
!= NULL
);
48 /* Make sure win32k is here */
49 if (!PspW32ProcessCallout
) return STATUS_ACCESS_DENIED
;
51 /* Make sure it's not already win32 */
52 if (Thread
->Tcb
.ServiceTable
!= KeServiceDescriptorTable
)
54 /* We're already a win32 thread */
55 return STATUS_ALREADY_WIN32
;
58 /* Check if we don't already have a kernel-mode stack */
59 if (!Thread
->Tcb
.LargeStack
)
61 /* We don't create one */
62 NewStack
= (ULONG_PTR
)MmCreateKernelStack(TRUE
, 0);
65 /* Panic in user-mode */
66 return STATUS_NO_MEMORY
;
69 /* We're about to switch stacks. Enter a guarded region */
70 KeEnterGuardedRegion();
73 OldStack
= KeSwitchKernelStack((PVOID
)NewStack
,
74 (PVOID
)(NewStack
- KERNEL_STACK_SIZE
));
76 /* Leave the guarded region */
77 KeLeaveGuardedRegion();
79 /* Delete the old stack */
80 MmDeleteKernelStack(OldStack
, FALSE
);
83 /* Always do the process callout! */
84 Status
= PspW32ProcessCallout(Process
, TRUE
);
85 if (!NT_SUCCESS(Status
)) return Status
;
87 /* Set the new service table */
88 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTableShadow
;
89 ASSERT(Thread
->Tcb
.Win32Thread
== 0);
91 /* Tell Win32k about our thread */
92 Status
= PspW32ThreadCallout(Thread
, PsW32ThreadCalloutInitialize
);
93 if (!NT_SUCCESS(Status
))
95 /* Revert our table */
96 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTable
;
103 /* PUBLIC FUNCTIONS **********************************************************/
110 PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData
)
112 /* Setup the callback pointers */
113 PspW32ProcessCallout
= CalloutData
->ProcessCallout
;
114 PspW32ThreadCallout
= CalloutData
->ThreadCallout
;
115 ExpWindowStationObjectParse
= CalloutData
->WindowStationParseProcedure
;
116 ExpWindowStationObjectDelete
= CalloutData
->WindowStationDeleteProcedure
;
117 ExpWindowStationObjectOkToClose
= CalloutData
->WindowStationOkToCloseProcedure
;
118 ExpDesktopObjectOkToClose
= CalloutData
->DesktopOkToCloseProcedure
;
119 ExpDesktopObjectDelete
= CalloutData
->DesktopDeleteProcedure
;
120 ExpDesktopObjectOpen
= CalloutData
->DesktopOpenProcedure
;
121 ExpDesktopObjectClose
= CalloutData
->DesktopCloseProcedure
;
122 PopEventCallout
= CalloutData
->PowerEventCallout
;
123 KeGdiFlushUserBatch
= CalloutData
->BatchFlushRoutine
;