3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/win32.c
6 * PURPOSE: win32k support
8 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
11 /* INCLUDES ****************************************************************/
15 #include <internal/debug.h>
17 /* GLOBALS ******************************************************************/
19 static PW32_PROCESS_CALLBACK PspWin32ProcessCallback
= NULL
;
20 static PW32_THREAD_CALLBACK PspWin32ThreadCallback
= NULL
;
22 extern OB_OPEN_METHOD ExpWindowStationObjectOpen
;
23 extern OB_PARSE_METHOD ExpWindowStationObjectParse
;
24 extern OB_DELETE_METHOD ExpWindowStationObjectDelete
;
25 extern OB_FIND_METHOD ExpWindowStationObjectFind
;
26 extern OB_CREATE_METHOD ExpDesktopObjectCreate
;
27 extern OB_DELETE_METHOD ExpDesktopObjectDelete
;
29 #ifndef ALEX_CB_REWRITE
30 typedef struct _NTW32CALL_SAVED_STATE
32 ULONG_PTR SavedStackLimit
;
34 PVOID SavedInitialStack
;
36 PULONG CallerResultLength
;
37 PNTSTATUS CallbackStatus
;
38 PKTRAP_FRAME SavedTrapFrame
;
39 PVOID SavedCallbackStack
;
40 PVOID SavedExceptionStack
;
41 } NTW32CALL_SAVED_STATE
, *PNTW32CALL_SAVED_STATE
;
51 /* FUNCTIONS ***************************************************************/
58 PsEstablishWin32Callouts(PW32_CALLOUT_DATA CalloutData
)
60 PspWin32ProcessCallback
= CalloutData
->W32ProcessCallout
;
61 PspWin32ThreadCallback
= CalloutData
->W32ThreadCallout
;
62 ExpWindowStationObjectOpen
= CalloutData
->WinStaCreate
;
63 ExpWindowStationObjectParse
= CalloutData
->WinStaParse
;
64 ExpWindowStationObjectDelete
= CalloutData
->WinStaDelete
;
65 ExpWindowStationObjectFind
= CalloutData
->WinStaFind
;
66 ExpDesktopObjectCreate
= CalloutData
->DesktopCreate
;
67 ExpDesktopObjectDelete
= CalloutData
->DesktopDelete
;
72 PsConvertToGuiThread(VOID
)
76 PETHREAD Thread
= PsGetCurrentThread();
77 PEPROCESS Process
= PsGetCurrentProcess();
81 /* Validate the previous mode */
82 if (KeGetPreviousMode() == KernelMode
)
84 DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
85 return STATUS_INVALID_PARAMETER
;
88 /* Make sure win32k is here */
89 if (!PspWin32ProcessCallback
)
91 DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
92 return STATUS_ACCESS_DENIED
;
95 /* Make sure it's not already win32 */
96 if (Thread
->Tcb
.ServiceTable
!= KeServiceDescriptorTable
)
98 DPRINT1("Danger: Thread is already a win32 thread. Limit bypassed?\n");
99 return STATUS_ALREADY_WIN32
;
102 /* Check if we don't already have a kernel-mode stack */
103 if (!Thread
->Tcb
.LargeStack
)
105 /* We don't create one */
106 NewStack
= (ULONG_PTR
)MmCreateKernelStack(TRUE
) + KERNEL_LARGE_STACK_SIZE
;
109 /* Panic in user-mode */
110 NtCurrentTeb()->LastErrorValue
= ERROR_NOT_ENOUGH_MEMORY
;
111 return STATUS_NO_MEMORY
;
114 /* We're about to switch stacks. Enter a critical region */
115 KeEnterCriticalRegion();
118 OldStack
= KeSwitchKernelStack((PVOID
)NewStack
,
119 (PVOID
)(NewStack
- KERNEL_STACK_SIZE
));
121 /* Leave the critical region */
122 KeLeaveCriticalRegion();
124 /* Delete the old stack */
125 MmDeleteKernelStack(OldStack
, FALSE
);
128 /* This check is bizare. Check out win32k later */
129 if (!Process
->Win32Process
)
131 /* Now tell win32k about us */
132 Status
= PspWin32ProcessCallback(Process
, TRUE
);
133 if (!NT_SUCCESS(Status
))
135 DPRINT1("Danger: Win32k wasn't happy about us!\n");
140 /* Set the new service table */
141 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTableShadow
;
142 ASSERT(Thread
->Tcb
.Win32Thread
== 0);
144 /* Tell Win32k about our thread */
145 Status
= PspWin32ThreadCallback(Thread
, TRUE
);
146 if (!NT_SUCCESS(Status
))
148 /* Revert our table */
149 DPRINT1("Danger: Win32k wasn't happy about us!\n");
150 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTable
;
159 PsTerminateWin32Process (PEPROCESS Process
)
161 if (Process
->Win32Process
== NULL
)
164 if (PspWin32ProcessCallback
!= NULL
)
166 PspWin32ProcessCallback (Process
, FALSE
);
169 /* don't delete the W32PROCESS structure at this point, wait until the
170 EPROCESS structure is being freed */
176 PsTerminateWin32Thread (PETHREAD Thread
)
178 if (Thread
->Tcb
.Win32Thread
!= NULL
)
180 if (PspWin32ThreadCallback
!= NULL
)
182 PspWin32ThreadCallback (Thread
, FALSE
);
185 /* don't delete the W32THREAD structure at this point, wait until the
186 ETHREAD structure is being freed */
192 NtW32Call(IN ULONG RoutineIndex
,
194 IN ULONG ArgumentLength
,
196 OUT PULONG ResultLength
)
199 ULONG RetResultLength
;
200 NTSTATUS Status
= STATUS_SUCCESS
;
202 DPRINT("NtW32Call(RoutineIndex %d, Argument %p, ArgumentLength %d)\n",
203 RoutineIndex
, Argument
, ArgumentLength
);
205 /* must not be called as KernelMode! */
206 ASSERT(KeGetPreviousMode() != KernelMode
);
210 ProbeForWritePointer(Result
);
211 ProbeForWriteUlong(ResultLength
);
215 Status
= _SEH_GetExceptionCode();
219 if (NT_SUCCESS(Status
))
221 /* Call kernel function */
222 Status
= KeUserModeCallback(RoutineIndex
,
228 if (NT_SUCCESS(Status
))
233 *ResultLength
= RetResultLength
;
237 Status
= _SEH_GetExceptionCode();
243 /* Return the result */