- Rewrite usermode callbacks. These changes should greatly optimize graphic operation...
[reactos.git] / reactos / ntoskrnl / ps / win32.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/ps/win32.c
6 * PURPOSE: win32k support
7 *
8 * PROGRAMMERS: Eric Kohl (ekohl@rz-online.de)
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS ******************************************************************/
18
19 static PW32_PROCESS_CALLBACK PspWin32ProcessCallback = NULL;
20 static PW32_THREAD_CALLBACK PspWin32ThreadCallback = NULL;
21
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;
28
29 #ifndef ALEX_CB_REWRITE
30 typedef struct _NTW32CALL_SAVED_STATE
31 {
32 ULONG_PTR SavedStackLimit;
33 PVOID SavedStackBase;
34 PVOID SavedInitialStack;
35 PVOID CallerResult;
36 PULONG CallerResultLength;
37 PNTSTATUS CallbackStatus;
38 PKTRAP_FRAME SavedTrapFrame;
39 PVOID SavedCallbackStack;
40 PVOID SavedExceptionStack;
41 } NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
42 #endif
43
44 PVOID
45 STDCALL
46 KeSwitchKernelStack(
47 IN PVOID StackBase,
48 IN PVOID StackLimit
49 );
50
51 /* FUNCTIONS ***************************************************************/
52
53 /*
54 * @implemented
55 */
56 VOID
57 STDCALL
58 PsEstablishWin32Callouts(PW32_CALLOUT_DATA CalloutData)
59 {
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;
68 }
69
70 NTSTATUS
71 NTAPI
72 PsConvertToGuiThread(VOID)
73 {
74 PVOID NewStack, OldStack;
75 PETHREAD Thread = PsGetCurrentThread();
76 PEPROCESS Process = PsGetCurrentProcess();
77 NTSTATUS Status;
78 PAGED_CODE();
79
80 /* Validate the previous mode */
81 if (KeGetPreviousMode() == KernelMode)
82 {
83 DPRINT1("Danger: win32k call being made in kernel-mode?!\n");
84 return STATUS_INVALID_PARAMETER;
85 }
86
87 /* Make sure win32k is here */
88 if (!PspWin32ProcessCallback)
89 {
90 DPRINT1("Danger: Win32K call attempted but Win32k not ready!\n");
91 return STATUS_ACCESS_DENIED;
92 }
93
94 /* Make sure it's not already win32 */
95 if (Thread->Tcb.ServiceTable != KeServiceDescriptorTable)
96 {
97 DPRINT1("Danger: Thread is already a win32 thread. Limit bypassed?\n");
98 return STATUS_ALREADY_WIN32;
99 }
100
101 /* Check if we don't already have a kernel-mode stack */
102 if (!Thread->Tcb.LargeStack)
103 {
104 /* We don't create one */
105 NewStack = MmCreateKernelStack(TRUE);
106 if (!NewStack)
107 {
108 /* Panic in user-mode */
109 NtCurrentTeb()->LastErrorValue = ERROR_NOT_ENOUGH_MEMORY;
110 return STATUS_NO_MEMORY;
111 }
112
113 /* We're about to switch stacks. Enter a critical region */
114 KeEnterCriticalRegion();
115
116 /* Switch stacks */
117 OldStack = KeSwitchKernelStack((PVOID)((ULONG_PTR)NewStack + 0x3000),
118 NewStack);
119
120 /* Leave the critical region */
121 KeLeaveCriticalRegion();
122
123 /* Delete the old stack */
124 //MmDeleteKernelStack(OldStack, FALSE);
125 }
126
127 /* This check is bizare. Check out win32k later */
128 if (!Process->Win32Process)
129 {
130 /* Now tell win32k about us */
131 Status = PspWin32ProcessCallback(Process, TRUE);
132 if (!NT_SUCCESS(Status))
133 {
134 DPRINT1("Danger: Win32k wasn't happy about us!\n");
135 return Status;
136 }
137 }
138
139 /* Set the new service table */
140 Thread->Tcb.ServiceTable = KeServiceDescriptorTableShadow;
141 ASSERT(Thread->Tcb.Win32Thread == 0);
142
143 /* Tell Win32k about our thread */
144 Status = PspWin32ThreadCallback(Thread, TRUE);
145 if (!NT_SUCCESS(Status))
146 {
147 /* Revert our table */
148 DPRINT1("Danger: Win32k wasn't happy about us!\n");
149 Thread->Tcb.ServiceTable = KeServiceDescriptorTable;
150 }
151
152 /* Return status */
153 return Status;
154 }
155
156 VOID
157 NTAPI
158 PsTerminateWin32Process (PEPROCESS Process)
159 {
160 if (Process->Win32Process == NULL)
161 return;
162
163 if (PspWin32ProcessCallback != NULL)
164 {
165 PspWin32ProcessCallback (Process, FALSE);
166 }
167
168 /* don't delete the W32PROCESS structure at this point, wait until the
169 EPROCESS structure is being freed */
170 }
171
172
173 VOID
174 NTAPI
175 PsTerminateWin32Thread (PETHREAD Thread)
176 {
177 if (Thread->Tcb.Win32Thread != NULL)
178 {
179 if (PspWin32ThreadCallback != NULL)
180 {
181 PspWin32ThreadCallback (Thread, FALSE);
182 }
183
184 /* don't delete the W32THREAD structure at this point, wait until the
185 ETHREAD structure is being freed */
186 }
187 }
188
189 NTSTATUS
190 STDCALL
191 NtW32Call(IN ULONG RoutineIndex,
192 IN PVOID Argument,
193 IN ULONG ArgumentLength,
194 OUT PVOID* Result OPTIONAL,
195 OUT PULONG ResultLength OPTIONAL)
196 {
197 NTSTATUS CallbackStatus;
198
199 DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
200 RoutineIndex, Argument, ArgumentLength);
201
202 /* FIXME: SEH!!! */
203
204 /* Call kernel function */
205 CallbackStatus = KeUserModeCallback(RoutineIndex,
206 Argument,
207 ArgumentLength,
208 Result,
209 ResultLength);
210
211 /* Return the result */
212 return(CallbackStatus);
213 }
214
215 /* EOF */