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
;
44 /* FUNCTIONS ***************************************************************/
51 PsEstablishWin32Callouts(PW32_CALLOUT_DATA CalloutData
)
53 PspWin32ProcessCallback
= CalloutData
->W32ProcessCallout
;
54 PspWin32ThreadCallback
= CalloutData
->W32ThreadCallout
;
55 ExpWindowStationObjectOpen
= CalloutData
->WinStaCreate
;
56 ExpWindowStationObjectParse
= CalloutData
->WinStaParse
;
57 ExpWindowStationObjectDelete
= CalloutData
->WinStaDelete
;
58 ExpWindowStationObjectFind
= CalloutData
->WinStaFind
;
59 ExpDesktopObjectCreate
= CalloutData
->DesktopCreate
;
60 ExpDesktopObjectDelete
= CalloutData
->DesktopDelete
;
65 PsInitWin32Thread (PETHREAD Thread
)
68 NTSTATUS Status
= STATUS_SUCCESS
;
70 Process
= Thread
->ThreadsProcess
;
72 if (Process
->Win32Process
== NULL
)
74 if (PspWin32ProcessCallback
!= NULL
)
76 Status
= PspWin32ProcessCallback(Process
, TRUE
);
80 if (Thread
->Tcb
.Win32Thread
== NULL
)
82 if (PspWin32ThreadCallback
!= NULL
)
84 Status
= PspWin32ThreadCallback(Thread
, TRUE
);
94 PsTerminateWin32Process (PEPROCESS Process
)
96 if (Process
->Win32Process
== NULL
)
99 if (PspWin32ProcessCallback
!= NULL
)
101 PspWin32ProcessCallback (Process
, FALSE
);
104 /* don't delete the W32PROCESS structure at this point, wait until the
105 EPROCESS structure is being freed */
111 PsTerminateWin32Thread (PETHREAD Thread
)
113 if (Thread
->Tcb
.Win32Thread
!= NULL
)
115 if (PspWin32ThreadCallback
!= NULL
)
117 PspWin32ThreadCallback (Thread
, FALSE
);
120 /* don't delete the W32THREAD structure at this point, wait until the
121 ETHREAD structure is being freed */
127 DumpEspData(ULONG Esp
, ULONG ThLimit
, ULONG ThStack
, ULONG PcrLimit
, ULONG PcrStack
, ULONG Esp0
)
129 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
) ;
134 PsAllocateCallbackStack(ULONG StackSize
)
136 PVOID KernelStack
= NULL
;
138 PMEMORY_AREA StackArea
;
140 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
141 PPFN_TYPE Pages
= alloca(sizeof(PFN_TYPE
) * (StackSize
/PAGE_SIZE
));
143 DPRINT1("PsAllocateCallbackStack\n");
144 BoundaryAddressMultiple
.QuadPart
= 0;
145 StackSize
= PAGE_ROUND_UP(StackSize
);
146 MmLockAddressSpace(MmGetKernelAddressSpace());
147 Status
= MmCreateMemoryArea(MmGetKernelAddressSpace(),
148 MEMORY_AREA_KERNEL_STACK
,
155 BoundaryAddressMultiple
);
156 MmUnlockAddressSpace(MmGetKernelAddressSpace());
157 if (!NT_SUCCESS(Status
))
159 DPRINT1("Failed to create thread stack\n");
162 for (i
= 0; i
< (StackSize
/ PAGE_SIZE
); i
++)
164 Status
= MmRequestPageMemoryConsumer(MC_NPPOOL
, TRUE
, &Pages
[i
]);
165 if (!NT_SUCCESS(Status
))
167 for (j
= 0; j
< i
; j
++)
169 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pages
[j
]);
174 Status
= MmCreateVirtualMapping(NULL
,
178 StackSize
/ PAGE_SIZE
);
179 if (!NT_SUCCESS(Status
))
181 for (i
= 0; i
< (StackSize
/ PAGE_SIZE
); i
++)
183 MmReleasePageMemoryConsumer(MC_NPPOOL
, Pages
[i
]);
187 DPRINT1("PsAllocateCallbackStack %x\n", KernelStack
);
193 NtW32Call(IN ULONG RoutineIndex
,
195 IN ULONG ArgumentLength
,
196 OUT PVOID
* Result OPTIONAL
,
197 OUT PULONG ResultLength OPTIONAL
)
199 NTSTATUS CallbackStatus
;
201 DPRINT("NtW32Call(RoutineIndex %d, Argument %X, ArgumentLength %d)\n",
202 RoutineIndex
, Argument
, ArgumentLength
);
206 /* Call kernel function */
207 CallbackStatus
= KeUserModeCallback(RoutineIndex
,
213 /* Return the result */
214 return(CallbackStatus
);
217 #ifndef ALEX_CB_REWRITE
219 NtCallbackReturn (PVOID Result
,
225 PNTSTATUS CallbackStatus
;
226 PULONG CallerResultLength
;
230 ULONG_PTR StackLimit
;
232 PNTW32CALL_SAVED_STATE State
;
233 PKTRAP_FRAME SavedTrapFrame
;
234 PVOID SavedCallbackStack
;
235 PVOID SavedExceptionStack
;
239 Thread
= PsGetCurrentThread();
240 if (Thread
->Tcb
.CallbackStack
== NULL
)
242 return(STATUS_NO_CALLBACK_ACTIVE
);
245 OldStack
= (PULONG
)Thread
->Tcb
.CallbackStack
;
248 * Get the values that NtW32Call left on the inactive stack for us.
250 State
= (PNTW32CALL_SAVED_STATE
)OldStack
[0];
251 CallbackStatus
= State
->CallbackStatus
;
252 CallerResultLength
= State
->CallerResultLength
;
253 CallerResult
= State
->CallerResult
;
254 InitialStack
= State
->SavedInitialStack
;
255 StackBase
= State
->SavedStackBase
;
256 StackLimit
= State
->SavedStackLimit
;
257 SavedTrapFrame
= State
->SavedTrapFrame
;
258 SavedCallbackStack
= State
->SavedCallbackStack
;
259 SavedExceptionStack
= State
->SavedExceptionStack
;
262 * Copy the callback status and the callback result to NtW32Call
264 *CallbackStatus
= Status
;
265 if (CallerResult
!= NULL
&& CallerResultLength
!= NULL
)
269 *CallerResultLength
= 0;
273 *CallerResultLength
= min(ResultLength
, *CallerResultLength
);
274 RtlCopyMemory(*CallerResult
, Result
, *CallerResultLength
);
279 * Restore the old stack.
281 KeRaiseIrql(HIGH_LEVEL
, &oldIrql
);
282 if ((Thread
->Tcb
.NpxState
& NPX_STATE_VALID
) &&
283 &Thread
->Tcb
!= KeGetCurrentPrcb()->NpxThread
)
285 RtlCopyMemory((char*)InitialStack
- sizeof(FX_SAVE_AREA
),
286 (char*)Thread
->Tcb
.InitialStack
- sizeof(FX_SAVE_AREA
),
287 sizeof(FX_SAVE_AREA
));
289 Thread
->Tcb
.InitialStack
= InitialStack
;
290 Thread
->Tcb
.StackBase
= StackBase
;
291 Thread
->Tcb
.StackLimit
= StackLimit
;
292 Thread
->Tcb
.TrapFrame
= SavedTrapFrame
;
293 Thread
->Tcb
.CallbackStack
= SavedCallbackStack
;
294 KeGetCurrentKPCR()->TSS
->Esp0
= (ULONG
)SavedExceptionStack
;
295 KeStackSwitchAndRet((PVOID
)(OldStack
+ 1));
297 /* Should never return. */
299 return(STATUS_UNSUCCESSFUL
);