strip whitespace from end of lines
[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 static ULONG PspWin32ProcessSize = 0;
22 static ULONG PspWin32ThreadSize = 0;
23
24 extern OBJECT_CREATE_ROUTINE ExpWindowStationObjectCreate;
25 extern OBJECT_PARSE_ROUTINE ExpWindowStationObjectParse;
26 extern OBJECT_DELETE_ROUTINE ExpWindowStationObjectDelete;
27 extern OBJECT_FIND_ROUTINE ExpWindowStationObjectFind;
28 extern OBJECT_CREATE_ROUTINE ExpDesktopObjectCreate;
29 extern OBJECT_DELETE_ROUTINE ExpDesktopObjectDelete;
30
31 #ifndef ALEX_CB_REWRITE
32 typedef struct _NTW32CALL_SAVED_STATE
33 {
34 ULONG_PTR SavedStackLimit;
35 PVOID SavedStackBase;
36 PVOID SavedInitialStack;
37 PVOID CallerResult;
38 PULONG CallerResultLength;
39 PNTSTATUS CallbackStatus;
40 PKTRAP_FRAME SavedTrapFrame;
41 PVOID SavedCallbackStack;
42 PVOID SavedExceptionStack;
43 } NTW32CALL_SAVED_STATE, *PNTW32CALL_SAVED_STATE;
44 #endif
45
46 /* FUNCTIONS ***************************************************************/
47
48 PW32THREAD STDCALL
49 PsGetWin32Thread(VOID)
50 {
51 return(PsGetCurrentThread()->Tcb.Win32Thread);
52 }
53
54 PW32PROCESS STDCALL
55 PsGetWin32Process(VOID)
56 {
57 return (PW32PROCESS)PsGetCurrentProcess()->Win32Process;
58 }
59
60 NTSTATUS STDCALL
61 PsCreateWin32Process(PEPROCESS Process)
62 {
63 if (Process->Win32Process != NULL)
64 return(STATUS_SUCCESS);
65
66 Process->Win32Process = ExAllocatePool(NonPagedPool,
67 PspWin32ProcessSize);
68 if (Process->Win32Process == NULL)
69 return(STATUS_NO_MEMORY);
70
71 RtlZeroMemory(Process->Win32Process,
72 PspWin32ProcessSize);
73
74 return(STATUS_SUCCESS);
75 }
76
77
78 /*
79 * @implemented
80 */
81 VOID STDCALL
82 PsEstablishWin32Callouts (PW32_PROCESS_CALLBACK W32ProcessCallback,
83 PW32_THREAD_CALLBACK W32ThreadCallback,
84 PW32_OBJECT_CALLBACK W32ObjectCallback,
85 PVOID Param4,
86 ULONG W32ThreadSize,
87 ULONG W32ProcessSize)
88 {
89 PspWin32ProcessCallback = W32ProcessCallback;
90 PspWin32ThreadCallback = W32ThreadCallback;
91
92 PspWin32ProcessSize = W32ProcessSize;
93 PspWin32ThreadSize = W32ThreadSize;
94
95 ExpWindowStationObjectCreate = W32ObjectCallback->WinStaCreate;
96 ExpWindowStationObjectParse = W32ObjectCallback->WinStaParse;
97 ExpWindowStationObjectDelete = W32ObjectCallback->WinStaDelete;
98 ExpWindowStationObjectFind = W32ObjectCallback->WinStaFind;
99 ExpDesktopObjectCreate = W32ObjectCallback->DesktopCreate;
100 ExpDesktopObjectDelete = W32ObjectCallback->DesktopDelete;
101 }
102
103 NTSTATUS
104 PsInitWin32Thread (PETHREAD Thread)
105 {
106 PEPROCESS Process;
107
108 Process = Thread->ThreadsProcess;
109
110 if (Process->Win32Process == NULL)
111 {
112 /* FIXME - lock the process */
113 Process->Win32Process = ExAllocatePool (NonPagedPool,
114 PspWin32ProcessSize);
115
116 if (Process->Win32Process == NULL)
117 return STATUS_NO_MEMORY;
118
119 RtlZeroMemory (Process->Win32Process,
120 PspWin32ProcessSize);
121 /* FIXME - unlock the process */
122
123 if (PspWin32ProcessCallback != NULL)
124 {
125 PspWin32ProcessCallback (Process, TRUE);
126 }
127 }
128
129 if (Thread->Tcb.Win32Thread == NULL)
130 {
131 Thread->Tcb.Win32Thread = ExAllocatePool (NonPagedPool,
132 PspWin32ThreadSize);
133 if (Thread->Tcb.Win32Thread == NULL)
134 return STATUS_NO_MEMORY;
135
136 RtlZeroMemory (Thread->Tcb.Win32Thread,
137 PspWin32ThreadSize);
138
139 if (PspWin32ThreadCallback != NULL)
140 {
141 PspWin32ThreadCallback (Thread, TRUE);
142 }
143 }
144
145 return(STATUS_SUCCESS);
146 }
147
148
149 VOID
150 PsTerminateWin32Process (PEPROCESS Process)
151 {
152 if (Process->Win32Process == NULL)
153 return;
154
155 if (PspWin32ProcessCallback != NULL)
156 {
157 PspWin32ProcessCallback (Process, FALSE);
158 }
159
160 /* don't delete the W32PROCESS structure at this point, wait until the
161 EPROCESS structure is being freed */
162 }
163
164
165 VOID
166 PsTerminateWin32Thread (PETHREAD Thread)
167 {
168 if (Thread->Tcb.Win32Thread != NULL)
169 {
170 if (PspWin32ThreadCallback != NULL)
171 {
172 PspWin32ThreadCallback (Thread, FALSE);
173 }
174
175 /* don't delete the W32THREAD structure at this point, wait until the
176 ETHREAD structure is being freed */
177 }
178 }
179
180 VOID
181 STDCALL
182 DumpEspData(ULONG Esp, ULONG ThLimit, ULONG ThStack, ULONG PcrLimit, ULONG PcrStack, ULONG Esp0)
183 {
184 DPRINT1("Current Esp: %p\n Thread Stack Limit: %p\n Thread Stack: %p\n Pcr Limit: %p, Pcr Stack: %p\n Esp0 :%p\n",Esp, ThLimit, ThStack, PcrLimit, PcrStack, Esp0) ;
185 }
186
187 PVOID
188 STDCALL
189 PsAllocateCallbackStack(ULONG StackSize)
190 {
191 PVOID KernelStack = NULL;
192 NTSTATUS Status;
193 PMEMORY_AREA StackArea;
194 ULONG i, j;
195 PHYSICAL_ADDRESS BoundaryAddressMultiple;
196 PPFN_TYPE Pages = alloca(sizeof(PFN_TYPE) * (StackSize /PAGE_SIZE));
197
198 DPRINT1("PsAllocateCallbackStack\n");
199 BoundaryAddressMultiple.QuadPart = 0;
200 StackSize = PAGE_ROUND_UP(StackSize);
201 MmLockAddressSpace(MmGetKernelAddressSpace());
202 Status = MmCreateMemoryArea(NULL,
203 MmGetKernelAddressSpace(),
204 MEMORY_AREA_KERNEL_STACK,
205 &KernelStack,
206 StackSize,
207 0,
208 &StackArea,
209 FALSE,
210 FALSE,
211 BoundaryAddressMultiple);
212 MmUnlockAddressSpace(MmGetKernelAddressSpace());
213 if (!NT_SUCCESS(Status))
214 {
215 DPRINT1("Failed to create thread stack\n");
216 return(NULL);
217 }
218 for (i = 0; i < (StackSize / PAGE_SIZE); i++)
219 {
220 Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &Pages[i]);
221 if (!NT_SUCCESS(Status))
222 {
223 for (j = 0; j < i; j++)
224 {
225 MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[j]);
226 }
227 return(NULL);
228 }
229 }
230 Status = MmCreateVirtualMapping(NULL,
231 KernelStack,
232 PAGE_READWRITE,
233 Pages,
234 StackSize / PAGE_SIZE);
235 if (!NT_SUCCESS(Status))
236 {
237 for (i = 0; i < (StackSize / PAGE_SIZE); i++)
238 {
239 MmReleasePageMemoryConsumer(MC_NPPOOL, Pages[i]);
240 }
241 return(NULL);
242 }
243 DPRINT1("PsAllocateCallbackStack %x\n", KernelStack);
244 return(KernelStack);
245 }
246
247 NTSTATUS
248 STDCALL
249 NtW32Call(IN ULONG RoutineIndex,
250 IN PVOID Argument,
251 IN ULONG ArgumentLength,
252 OUT PVOID* Result OPTIONAL,
253 OUT PULONG ResultLength OPTIONAL)
254 {
255 NTSTATUS CallbackStatus;
256
257 DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
258 RoutineIndex, Argument, ArgumentLength);
259
260 /* FIXME: SEH!!! */
261
262 /* Call kernel function */
263 CallbackStatus = KeUserModeCallback(RoutineIndex,
264 Argument,
265 ArgumentLength,
266 Result,
267 ResultLength);
268
269 /* Return the result */
270 return(CallbackStatus);
271 }
272
273 #ifndef ALEX_CB_REWRITE
274 NTSTATUS STDCALL
275 NtCallbackReturn (PVOID Result,
276 ULONG ResultLength,
277 NTSTATUS Status)
278 {
279 PULONG OldStack;
280 PETHREAD Thread;
281 PNTSTATUS CallbackStatus;
282 PULONG CallerResultLength;
283 PVOID* CallerResult;
284 PVOID InitialStack;
285 PVOID StackBase;
286 ULONG_PTR StackLimit;
287 KIRQL oldIrql;
288 PNTW32CALL_SAVED_STATE State;
289 PKTRAP_FRAME SavedTrapFrame;
290 PVOID SavedCallbackStack;
291 PVOID SavedExceptionStack;
292
293 PAGED_CODE();
294
295 Thread = PsGetCurrentThread();
296 if (Thread->Tcb.CallbackStack == NULL)
297 {
298 return(STATUS_NO_CALLBACK_ACTIVE);
299 }
300
301 OldStack = (PULONG)Thread->Tcb.CallbackStack;
302
303 /*
304 * Get the values that NtW32Call left on the inactive stack for us.
305 */
306 State = (PNTW32CALL_SAVED_STATE)OldStack[0];
307 CallbackStatus = State->CallbackStatus;
308 CallerResultLength = State->CallerResultLength;
309 CallerResult = State->CallerResult;
310 InitialStack = State->SavedInitialStack;
311 StackBase = State->SavedStackBase;
312 StackLimit = State->SavedStackLimit;
313 SavedTrapFrame = State->SavedTrapFrame;
314 SavedCallbackStack = State->SavedCallbackStack;
315 SavedExceptionStack = State->SavedExceptionStack;
316
317 /*
318 * Copy the callback status and the callback result to NtW32Call
319 */
320 *CallbackStatus = Status;
321 if (CallerResult != NULL && CallerResultLength != NULL)
322 {
323 if (Result == NULL)
324 {
325 *CallerResultLength = 0;
326 }
327 else
328 {
329 *CallerResultLength = min(ResultLength, *CallerResultLength);
330 RtlCopyMemory(*CallerResult, Result, *CallerResultLength);
331 }
332 }
333
334 /*
335 * Restore the old stack.
336 */
337 KeRaiseIrql(HIGH_LEVEL, &oldIrql);
338 if ((Thread->Tcb.NpxState & NPX_STATE_VALID) &&
339 ETHREAD_TO_KTHREAD(Thread) != KeGetCurrentPrcb()->NpxThread)
340 {
341 RtlCopyMemory((char*)InitialStack - sizeof(FX_SAVE_AREA),
342 (char*)Thread->Tcb.InitialStack - sizeof(FX_SAVE_AREA),
343 sizeof(FX_SAVE_AREA));
344 }
345 Thread->Tcb.InitialStack = InitialStack;
346 Thread->Tcb.StackBase = StackBase;
347 Thread->Tcb.StackLimit = StackLimit;
348 Thread->Tcb.TrapFrame = SavedTrapFrame;
349 Thread->Tcb.CallbackStack = SavedCallbackStack;
350 KeGetCurrentKPCR()->TSS->Esp0 = (ULONG)SavedExceptionStack;
351 KeStackSwitchAndRet((PVOID)(OldStack + 1));
352
353 /* Should never return. */
354 KEBUGCHECK(0);
355 return(STATUS_UNSUCCESSFUL);
356 #endif
357 }
358 /* EOF */