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
;
21 static ULONG PspWin32ProcessSize
= 0;
22 static ULONG PspWin32ThreadSize
= 0;
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
;
31 #ifndef ALEX_CB_REWRITE
32 typedef struct _NTW32CALL_SAVED_STATE
34 ULONG_PTR SavedStackLimit
;
36 PVOID SavedInitialStack
;
38 PULONG CallerResultLength
;
39 PNTSTATUS CallbackStatus
;
40 PKTRAP_FRAME SavedTrapFrame
;
41 PVOID SavedCallbackStack
;
42 PVOID SavedExceptionStack
;
43 } NTW32CALL_SAVED_STATE
, *PNTW32CALL_SAVED_STATE
;
46 /* FUNCTIONS ***************************************************************/
49 PsGetWin32Thread(VOID
)
51 return(PsGetCurrentThread()->Tcb
.Win32Thread
);
55 PsGetWin32Process(VOID
)
57 return(PsGetCurrentProcess()->Win32Process
);
61 PsCreateWin32Process(PEPROCESS Process
)
63 if (Process
->Win32Process
!= NULL
)
64 return(STATUS_SUCCESS
);
66 Process
->Win32Process
= ExAllocatePool(NonPagedPool
,
68 if (Process
->Win32Process
== NULL
)
69 return(STATUS_NO_MEMORY
);
71 RtlZeroMemory(Process
->Win32Process
,
74 return(STATUS_SUCCESS
);
82 PsEstablishWin32Callouts (PW32_PROCESS_CALLBACK W32ProcessCallback
,
83 PW32_THREAD_CALLBACK W32ThreadCallback
,
84 PW32_OBJECT_CALLBACK W32ObjectCallback
,
89 PspWin32ProcessCallback
= W32ProcessCallback
;
90 PspWin32ThreadCallback
= W32ThreadCallback
;
92 PspWin32ProcessSize
= W32ProcessSize
;
93 PspWin32ThreadSize
= W32ThreadSize
;
95 ExpWindowStationObjectCreate
= W32ObjectCallback
->WinStaCreate
;
96 ExpWindowStationObjectParse
= W32ObjectCallback
->WinStaParse
;
97 ExpWindowStationObjectDelete
= W32ObjectCallback
->WinStaDelete
;
98 ExpWindowStationObjectFind
= W32ObjectCallback
->WinStaFind
;
99 ExpDesktopObjectCreate
= W32ObjectCallback
->DesktopCreate
;
100 ExpDesktopObjectDelete
= W32ObjectCallback
->DesktopDelete
;
104 PsInitWin32Thread (PETHREAD Thread
)
108 Process
= Thread
->ThreadsProcess
;
110 if (Process
->Win32Process
== NULL
)
112 /* FIXME - lock the process */
113 Process
->Win32Process
= ExAllocatePool (NonPagedPool
,
114 PspWin32ProcessSize
);
116 if (Process
->Win32Process
== NULL
)
117 return STATUS_NO_MEMORY
;
119 RtlZeroMemory (Process
->Win32Process
,
120 PspWin32ProcessSize
);
121 /* FIXME - unlock the process */
123 if (PspWin32ProcessCallback
!= NULL
)
125 PspWin32ProcessCallback (Process
, TRUE
);
129 if (Thread
->Tcb
.Win32Thread
== NULL
)
131 Thread
->Tcb
.Win32Thread
= ExAllocatePool (NonPagedPool
,
133 if (Thread
->Tcb
.Win32Thread
== NULL
)
134 return STATUS_NO_MEMORY
;
136 RtlZeroMemory (Thread
->Tcb
.Win32Thread
,
139 if (PspWin32ThreadCallback
!= NULL
)
141 PspWin32ThreadCallback (Thread
, TRUE
);
145 return(STATUS_SUCCESS
);
150 PsTerminateWin32Process (PEPROCESS Process
)
152 if (Process
->Win32Process
== NULL
)
155 if (PspWin32ProcessCallback
!= NULL
)
157 PspWin32ProcessCallback (Process
, FALSE
);
160 /* don't delete the W32PROCESS structure at this point, wait until the
161 EPROCESS structure is being freed */
166 PsTerminateWin32Thread (PETHREAD Thread
)
168 if (Thread
->Tcb
.Win32Thread
!= NULL
)
170 if (PspWin32ThreadCallback
!= NULL
)
172 PspWin32ThreadCallback (Thread
, FALSE
);
175 /* don't delete the W32THREAD structure at this point, wait until the
176 ETHREAD structure is being freed */
182 DumpEspData(ULONG Esp
, ULONG ThLimit
, ULONG ThStack
, ULONG PcrLimit
, ULONG PcrStack
, ULONG Esp0
)
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
) ;
189 PsAllocateCallbackStack(ULONG StackSize
)
191 PVOID KernelStack
= NULL
;
193 PMEMORY_AREA StackArea
;
195 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
196 PPFN_TYPE Pages
= alloca(sizeof(PFN_TYPE
) * (StackSize
/PAGE_SIZE
));
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
,
211 BoundaryAddressMultiple
);
212 MmUnlockAddressSpace(MmGetKernelAddressSpace());
213 if (!NT_SUCCESS(Status
))
215 DPRINT1("Failed to create thread stack\n");
218 for (i
= 0; i
< (StackSize
/ PAGE_SIZE
); i
++)
220 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pages
[i
]);
221 if (!NT_SUCCESS(Status
))
223 for (j
= 0; j
< i
; j
++)
225 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pages
[j
]);
230 Status
= MmCreateVirtualMapping(NULL
,
234 StackSize
/ PAGE_SIZE
);
235 if (!NT_SUCCESS(Status
))
237 for (i
= 0; i
< (StackSize
/ PAGE_SIZE
); i
++)
239 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pages
[i
]);
243 DPRINT1("PsAllocateCallbackStack %x\n", KernelStack
);
249 NtW32Call(IN ULONG RoutineIndex
,
251 IN ULONG ArgumentLength
,
252 OUT PVOID
* Result OPTIONAL
,
253 OUT PULONG ResultLength OPTIONAL
)
255 NTSTATUS CallbackStatus
;
257 DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
258 RoutineIndex
, Argument
, ArgumentLength
);
262 /* Call kernel function */
263 CallbackStatus
= KeUserModeCallback(RoutineIndex
,
269 /* Return the result */
270 return(CallbackStatus
);
273 #ifndef ALEX_CB_REWRITE
275 NtCallbackReturn (PVOID Result
,
281 PNTSTATUS CallbackStatus
;
282 PULONG CallerResultLength
;
286 ULONG_PTR StackLimit
;
288 PNTW32CALL_SAVED_STATE State
;
289 PKTRAP_FRAME SavedTrapFrame
;
290 PVOID SavedCallbackStack
;
291 PVOID SavedExceptionStack
;
295 Thread
= PsGetCurrentThread();
296 if (Thread
->Tcb
.CallbackStack
== NULL
)
298 return(STATUS_NO_CALLBACK_ACTIVE
);
301 OldStack
= (PULONG
)Thread
->Tcb
.CallbackStack
;
304 * Get the values that NtW32Call left on the inactive stack for us.
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
;
318 * Copy the callback status and the callback result to NtW32Call
320 *CallbackStatus
= Status
;
321 if (CallerResult
!= NULL
&& CallerResultLength
!= NULL
)
325 *CallerResultLength
= 0;
329 *CallerResultLength
= min(ResultLength
, *CallerResultLength
);
330 RtlCopyMemory(*CallerResult
, Result
, *CallerResultLength
);
335 * Restore the old stack.
337 KeRaiseIrql(HIGH_LEVEL
, &oldIrql
);
338 if ((Thread
->Tcb
.NpxState
& NPX_STATE_VALID
) &&
339 ETHREAD_TO_KTHREAD(Thread
) != KeGetCurrentPrcb()->NpxThread
)
341 RtlCopyMemory((char*)InitialStack
- sizeof(FX_SAVE_AREA
),
342 (char*)Thread
->Tcb
.InitialStack
- sizeof(FX_SAVE_AREA
),
343 sizeof(FX_SAVE_AREA
));
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));
353 /* Should never return. */
355 return(STATUS_UNSUCCESSFUL
);