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_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete
;
24 extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout
;
26 /* PRIVATE FUNCTIONS *********************************************************/
30 PsConvertToGuiThread(VOID
)
34 PETHREAD Thread
= PsGetCurrentThread();
35 PEPROCESS Process
= PsGetCurrentProcess();
39 /* Validate the previous mode */
40 if (KeGetPreviousMode() == KernelMode
) return STATUS_INVALID_PARAMETER
;
42 /* If no win32k, crashes later */
43 ASSERT(PspW32ProcessCallout
!= NULL
);
45 /* Make sure win32k is here */
46 if (!PspW32ProcessCallout
) return STATUS_ACCESS_DENIED
;
48 /* Make sure it's not already win32 */
49 if (Thread
->Tcb
.ServiceTable
!= KeServiceDescriptorTable
)
51 /* We're already a win32 thread */
52 return STATUS_ALREADY_WIN32
;
55 /* Check if we don't already have a kernel-mode stack */
56 if (!Thread
->Tcb
.LargeStack
)
58 /* We don't create one */
59 NewStack
= (ULONG_PTR
)MmCreateKernelStack(TRUE
, 0);
62 /* Panic in user-mode */
63 NtCurrentTeb()->LastErrorValue
= ERROR_NOT_ENOUGH_MEMORY
;
64 return STATUS_NO_MEMORY
;
67 /* We're about to switch stacks. Enter a guarded region */
68 KeEnterGuardedRegion();
71 OldStack
= KeSwitchKernelStack((PVOID
)NewStack
,
72 (PVOID
)(NewStack
- KERNEL_STACK_SIZE
));
74 /* Leave the guarded region */
75 KeLeaveGuardedRegion();
77 /* Delete the old stack */
78 MmDeleteKernelStack(OldStack
, FALSE
);
81 /* This check is bizare. Check out win32k later */
82 if (!Process
->Win32Process
)
84 /* Now tell win32k about us */
85 Status
= PspW32ProcessCallout(Process
, TRUE
);
86 if (!NT_SUCCESS(Status
)) return Status
;
89 /* Set the new service table */
90 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTableShadow
;
91 ASSERT(Thread
->Tcb
.Win32Thread
== 0);
93 /* Tell Win32k about our thread */
94 Status
= PspW32ThreadCallout(Thread
, PsW32ThreadCalloutInitialize
);
95 if (!NT_SUCCESS(Status
))
97 /* Revert our table */
98 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTable
;
105 /* PUBLIC FUNCTIONS **********************************************************/
112 PsEstablishWin32Callouts(IN PWIN32_CALLOUTS_FPNS CalloutData
)
114 /* Setup the callback pointers */
115 PspW32ProcessCallout
= CalloutData
->ProcessCallout
;
116 PspW32ThreadCallout
= CalloutData
->ThreadCallout
;
117 ExpWindowStationObjectParse
= CalloutData
->WindowStationParseProcedure
;
118 ExpWindowStationObjectDelete
= CalloutData
->WindowStationDeleteProcedure
;
119 ExpDesktopObjectDelete
= CalloutData
->DesktopDeleteProcedure
;
120 PopEventCallout
= CalloutData
->PowerEventCallout
;
121 KeGdiFlushUserBatch
= CalloutData
->BatchFlushRoutine
;
126 NtW32Call(IN ULONG RoutineIndex
,
128 IN ULONG ArgumentLength
,
130 OUT PULONG ResultLength
)
133 ULONG RetResultLength
;
134 NTSTATUS Status
= STATUS_SUCCESS
;
135 ASSERT(KeGetPreviousMode() != KernelMode
);
137 /* Enter SEH for probing */
140 /* Probe arguments */
141 ProbeForWritePointer(Result
);
142 ProbeForWriteUlong(ResultLength
);
144 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
146 /* Get exception code */
147 Status
= _SEH2_GetExceptionCode();
151 /* Make sure we got success */
152 if (NT_SUCCESS(Status
))
154 /* Call kernel function */
155 Status
= KeUserModeCallback(RoutineIndex
,
160 if (NT_SUCCESS(Status
))
162 /* Enter SEH for write back */
165 /* Return results to user mode */
167 *ResultLength
= RetResultLength
;
169 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
171 /* Get the exception code */
172 Status
= _SEH2_GetExceptionCode();
178 /* Return the result */