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 ****************************************************************/
16 /* GLOBALS ******************************************************************/
18 PKWIN32_PROCESS_CALLOUT PspW32ProcessCallout
= NULL
;
19 PKWIN32_THREAD_CALLOUT PspW32ThreadCallout
= NULL
;
20 PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch
= NULL
;
21 extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse
;
22 extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete
;
23 extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose
;
24 extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose
;
25 extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete
;
26 extern PKWIN32_OPENMETHOD_CALLOUT ExpDesktopObjectOpen
;
27 extern PKWIN32_CLOSEMETHOD_CALLOUT ExpDesktopObjectClose
;
28 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout
;
30 /* PRIVATE FUNCTIONS *********************************************************/
34 PsConvertToGuiThread(VOID
)
38 PETHREAD Thread
= PsGetCurrentThread();
39 PEPROCESS Process
= PsGetCurrentProcess();
43 /* Validate the previous mode */
44 if (KeGetPreviousMode() == KernelMode
) return STATUS_INVALID_PARAMETER
;
46 /* If no win32k, crashes later */
47 ASSERT(PspW32ProcessCallout
!= NULL
);
49 /* Make sure win32k is here */
50 if (!PspW32ProcessCallout
) return STATUS_ACCESS_DENIED
;
52 /* Make sure it's not already win32 */
53 if (Thread
->Tcb
.ServiceTable
!= KeServiceDescriptorTable
)
55 /* We're already a win32 thread */
56 return STATUS_ALREADY_WIN32
;
59 /* Check if we don't already have a kernel-mode stack */
60 if (!Thread
->Tcb
.LargeStack
)
62 /* We don't create one */
63 NewStack
= (ULONG_PTR
)MmCreateKernelStack(TRUE
, 0);
66 /* Panic in user-mode */
67 NtCurrentTeb()->LastErrorValue
= ERROR_NOT_ENOUGH_MEMORY
;
68 return STATUS_NO_MEMORY
;
71 /* We're about to switch stacks. Enter a guarded region */
72 KeEnterGuardedRegion();
75 OldStack
= KeSwitchKernelStack((PVOID
)NewStack
,
76 (PVOID
)(NewStack
- KERNEL_STACK_SIZE
));
78 /* Leave the guarded region */
79 KeLeaveGuardedRegion();
81 /* Delete the old stack */
82 MmDeleteKernelStack(OldStack
, FALSE
);
85 /* This check is bizare. Check out win32k later */
86 if (!Process
->Win32Process
)
88 /* Now tell win32k about us */
89 Status
= PspW32ProcessCallout(Process
, TRUE
);
90 if (!NT_SUCCESS(Status
)) return Status
;
93 /* Set the new service table */
94 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTableShadow
;
95 ASSERT(Thread
->Tcb
.Win32Thread
== 0);
97 /* Tell Win32k about our thread */
98 Status
= PspW32ThreadCallout(Thread
, PsW32ThreadCalloutInitialize
);
99 if (!NT_SUCCESS(Status
))
101 /* Revert our table */
102 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTable
;
109 /* PUBLIC FUNCTIONS **********************************************************/
116 PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData
)
118 /* Setup the callback pointers */
119 PspW32ProcessCallout
= CalloutData
->ProcessCallout
;
120 PspW32ThreadCallout
= CalloutData
->ThreadCallout
;
121 ExpWindowStationObjectParse
= CalloutData
->WindowStationParseProcedure
;
122 ExpWindowStationObjectDelete
= CalloutData
->WindowStationDeleteProcedure
;
123 ExpWindowStationObjectOkToClose
= CalloutData
->WindowStationOkToCloseProcedure
;
124 ExpDesktopObjectOkToClose
= CalloutData
->DesktopOkToCloseProcedure
;
125 ExpDesktopObjectDelete
= CalloutData
->DesktopDeleteProcedure
;
126 ExpDesktopObjectOpen
= CalloutData
->DesktopOpenProcedure
;
127 ExpDesktopObjectClose
= CalloutData
->DesktopCloseProcedure
;
128 PopEventCallout
= CalloutData
->PowerEventCallout
;
129 KeGdiFlushUserBatch
= CalloutData
->BatchFlushRoutine
;
134 NtW32Call(IN ULONG RoutineIndex
,
136 IN ULONG ArgumentLength
,
138 OUT PULONG ResultLength
)
141 ULONG RetResultLength
;
143 ASSERT(KeGetPreviousMode() != KernelMode
);
145 /* Enter SEH for probing */
148 /* Probe arguments */
149 ProbeForWritePointer(Result
);
150 ProbeForWriteUlong(ResultLength
);
152 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
154 /* Return the exception code */
155 _SEH2_YIELD(return _SEH2_GetExceptionCode());
159 /* Call kernel function */
160 Status
= KeUserModeCallback(RoutineIndex
,
165 if (NT_SUCCESS(Status
))
167 /* Enter SEH for write back */
170 /* Return results to user mode */
172 *ResultLength
= RetResultLength
;
174 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
176 /* Get the exception code */
177 Status
= _SEH2_GetExceptionCode();
182 /* Return the result */