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
)
74 PVOID NewStack
, OldStack
;
75 PETHREAD Thread
= PsGetCurrentThread();
76 PEPROCESS Process
= PsGetCurrentProcess();
80 /* Validate the previous mode */
81 if (KeGetPreviousMode() == KernelMode
)
83 DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
84 return STATUS_INVALID_PARAMETER
;
87 /* Make sure win32k is here */
88 if (!PspWin32ProcessCallback
)
90 DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
91 return STATUS_ACCESS_DENIED
;
94 /* Make sure it's not already win32 */
95 if (Thread
->Tcb
.ServiceTable
!= KeServiceDescriptorTable
)
97 DPRINT1("Danger: Thread is already a win32 thread. Limit bypassed?\n");
98 return STATUS_ALREADY_WIN32
;
101 /* Check if we don't already have a kernel-mode stack */
102 if (!Thread
->Tcb
.LargeStack
)
104 /* We don't create one */
105 NewStack
= MmCreateKernelStack(TRUE
);
108 /* Panic in user-mode */
109 NtCurrentTeb()->LastErrorValue
= ERROR_NOT_ENOUGH_MEMORY
;
110 return STATUS_NO_MEMORY
;
113 /* We're about to switch stacks. Enter a critical region */
114 KeEnterCriticalRegion();
117 OldStack
= KeSwitchKernelStack((PVOID
)((ULONG_PTR
)NewStack
+ 0x3000),
120 /* Leave the critical region */
121 KeLeaveCriticalRegion();
123 /* Delete the old stack */
124 //MmDeleteKernelStack(OldStack, FALSE);
127 /* This check is bizare. Check out win32k later */
128 if (!Process
->Win32Process
)
130 /* Now tell win32k about us */
131 Status
= PspWin32ProcessCallback(Process
, TRUE
);
132 if (!NT_SUCCESS(Status
))
134 DPRINT1("Danger: Win32k wasn't happy about us!\n");
139 /* Set the new service table */
140 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTableShadow
;
141 ASSERT(Thread
->Tcb
.Win32Thread
== 0);
143 /* Tell Win32k about our thread */
144 Status
= PspWin32ThreadCallback(Thread
, TRUE
);
145 if (!NT_SUCCESS(Status
))
147 /* Revert our table */
148 DPRINT1("Danger: Win32k wasn't happy about us!\n");
149 Thread
->Tcb
.ServiceTable
= KeServiceDescriptorTable
;
158 PsTerminateWin32Process (PEPROCESS Process
)
160 if (Process
->Win32Process
== NULL
)
163 if (PspWin32ProcessCallback
!= NULL
)
165 PspWin32ProcessCallback (Process
, FALSE
);
168 /* don't delete the W32PROCESS structure at this point, wait until the
169 EPROCESS structure is being freed */
175 PsTerminateWin32Thread (PETHREAD Thread
)
177 if (Thread
->Tcb
.Win32Thread
!= NULL
)
179 if (PspWin32ThreadCallback
!= NULL
)
181 PspWin32ThreadCallback (Thread
, FALSE
);
184 /* don't delete the W32THREAD structure at this point, wait until the
185 ETHREAD structure is being freed */
191 NtW32Call(IN ULONG RoutineIndex
,
193 IN ULONG ArgumentLength
,
194 OUT PVOID
* Result OPTIONAL
,
195 OUT PULONG ResultLength OPTIONAL
)
197 NTSTATUS CallbackStatus
;
199 DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
200 RoutineIndex
, Argument
, ArgumentLength
);
204 /* Call kernel function */
205 CallbackStatus
= KeUserModeCallback(RoutineIndex
,
211 /* Return the result */
212 return(CallbackStatus
);