ReactOS 0.4.15-dev-6056-gb29b268
stubs.c File Reference
#include <ntoskrnl.h>
#include <fltkernel.h>
#include <debug.h>
Include dependency graph for stubs.c:

Go to the source code of this file.

Macros

#define NDEBUG
 
#define MAX_SYSCALL_PARAMS   16
 

Functions

VOID KiRetireDpcListInDpcStack (PKPRCB Prcb, PVOID DpcStack)
 
NTSTATUS KiConvertToGuiThread (VOID)
 
 _Requires_lock_not_held_ (Prcb->PrcbLock) VOID NTAPI KiDpcInterruptHandler(VOID)
 
PVOID KiSwitchKernelStackHelper (LONG_PTR StackOffset, PVOID OldStackBase)
 
PVOID NTAPI KiSwitchKernelStack (PVOID StackBase, PVOID StackLimit)
 
DECLSPEC_NORETURN VOID KiIdleLoop (VOID)
 
VOID NTAPI KiSwapProcess (IN PKPROCESS NewProcess, IN PKPROCESS OldProcess)
 
NTSTATUS NtSyscallFailure (void)
 
PVOID KiSystemCallHandler (VOID)
 
VOID KiSystemService (IN PKTHREAD Thread, IN PKTRAP_FRAME TrapFrame, IN ULONG Instruction)
 
NTSTATUS NTAPI NtSetLdtEntries (ULONG Selector1, LDT_ENTRY LdtEntry1, ULONG Selector2, LDT_ENTRY LdtEntry2)
 
NTSTATUS NTAPI NtVdmControl (IN ULONG ControlCode, IN PVOID ControlData)
 

Variables

ULONG ProcessCount
 
SIZE_T KeXStateLength = sizeof(XSAVE_FORMAT)
 

Macro Definition Documentation

◆ MAX_SYSCALL_PARAMS

#define MAX_SYSCALL_PARAMS   16

Definition at line 250 of file stubs.c.

◆ NDEBUG

#define NDEBUG

Definition at line 13 of file stubs.c.

Function Documentation

◆ _Requires_lock_not_held_()

_Requires_lock_not_held_ ( Prcb->  PrcbLock)

Definition at line 28 of file stubs.c.

32{
33 PKPRCB Prcb = KeGetCurrentPrcb();
34 PKTHREAD NewThread, OldThread;
36
37 /* Raise to DISPATCH_LEVEL */
39
40 /* Send an EOI */
41 KiSendEOI();
42
43 /* Check for pending timers, pending DPCs, or pending ready threads */
44 if ((Prcb->DpcData[0].DpcQueueDepth) ||
45 (Prcb->TimerRequest) ||
47 {
48 /* Retire DPCs while under the DPC stack */
50 }
51
52 /* Enable interrupts */
53 _enable();
54
55 /* Check for quantum end */
56 if (Prcb->QuantumEnd)
57 {
58 /* Handle quantum end */
59 Prcb->QuantumEnd = FALSE;
61 }
62 else if (Prcb->NextThread)
63 {
64 /* Acquire the PRCB lock */
66
67 /* Capture current thread data */
68 OldThread = Prcb->CurrentThread;
69 NewThread = Prcb->NextThread;
70
71 /* Set new thread data */
72 Prcb->NextThread = NULL;
73 Prcb->CurrentThread = NewThread;
74
75 /* The thread is now running */
76 NewThread->State = Running;
77 OldThread->WaitReason = WrDispatchInt;
78
79 /* Make the old thread ready */
80 KxQueueReadyThread(OldThread, Prcb);
81
82 /* Swap to the new thread */
83 KiSwapContext(APC_LEVEL, OldThread);
84 }
85
86 /* Disable interrupts and go back to old irql */
87 _disable();
89}
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeLowerIrql(oldIrql)
Definition: env_spec_w32.h:602
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
KIRQL FASTCALL KfRaiseIrql(IN KIRQL NewIrql)
Definition: pic.c:187
void __cdecl _disable(void)
Definition: intrin_arm.h:365
void __cdecl _enable(void)
Definition: intrin_arm.h:373
FORCEINLINE VOID KiAcquirePrcbLock(IN PKPRCB Prcb)
Definition: ke_x.h:220
FORCEINLINE struct _KPRCB * KeGetCurrentPrcb(VOID)
Definition: ketypes.h:1080
@ Running
Definition: ketypes.h:423
FORCEINLINE VOID KiSendEOI(VOID)
Definition: ke.h:346
BOOLEAN FASTCALL KiSwapContext(IN KIRQL WaitIrql, IN PKTHREAD CurrentThread)
VOID NTAPI KiQuantumEnd(VOID)
VOID KiRetireDpcListInDpcStack(PKPRCB Prcb, PVOID DpcStack)
volatile ULONG DpcQueueDepth
Definition: ketypes.h:798
UCHAR QuantumEnd
Definition: ketypes.h:701
KDPC_DATA DpcData[2]
Definition: ketypes.h:681
struct _KTHREAD * CurrentThread
Definition: ketypes.h:571
struct _KTHREAD * NextThread
Definition: ketypes.h:572
UINT64 TimerRequest
Definition: ketypes.h:696
SINGLE_LIST_ENTRY DeferredReadyListHead
Definition: ketypes.h:633
PVOID DpcStack
Definition: ketypes.h:682
UCHAR WaitReason
Definition: ketypes.h:1904
volatile UCHAR State
Definition: ketypes.h:1729
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:629
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:792
@ WrDispatchInt
Definition: ketypes.h:434

◆ KiConvertToGuiThread()

NTSTATUS KiConvertToGuiThread ( VOID  )

Referenced by KiSystemCallHandler().

◆ KiIdleLoop()

DECLSPEC_NORETURN VOID KiIdleLoop ( VOID  )

Definition at line 170 of file stubs.c.

171{
172 PKPRCB Prcb = KeGetCurrentPrcb();
173 PKTHREAD OldThread, NewThread;
174
175 /* Now loop forever */
176 while (TRUE)
177 {
178 /* Start of the idle loop: disable interrupts */
179 _enable();
182 _disable();
183
184 /* Check for pending timers, pending DPCs, or pending ready threads */
185 if ((Prcb->DpcData[0].DpcQueueDepth) ||
186 (Prcb->TimerRequest) ||
188 {
189 /* Quiesce the DPC software interrupt */
191
192 /* Handle it */
193 KiRetireDpcList(Prcb);
194 }
195
196 /* Check if a new thread is scheduled for execution */
197 if (Prcb->NextThread)
198 {
199 /* Enable interrupts */
200 _enable();
201
202 /* Capture current thread data */
203 OldThread = Prcb->CurrentThread;
204 NewThread = Prcb->NextThread;
205
206 /* Set new thread data */
207 Prcb->NextThread = NULL;
208 Prcb->CurrentThread = NewThread;
209
210 /* The thread is now running */
211 NewThread->State = Running;
212
213 /* Do the swap at SYNCH_LEVEL */
215
216 /* Switch away from the idle thread */
217 KiSwapContext(APC_LEVEL, OldThread);
218
219 /* Go back to DISPATCH_LEVEL */
221 }
222 else
223 {
224 /* Continue staying idle. Note the HAL returns with interrupts on */
225 Prcb->PowerState.IdleFunction(&Prcb->PowerState);
226 }
227 }
228}
#define TRUE
Definition: types.h:120
#define SYNCH_LEVEL
Definition: env_spec_w32.h:704
VOID FASTCALL HalClearSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:282
VOID FASTCALL KiRetireDpcList(IN PKPRCB Prcb)
Definition: dpc.c:562
#define YieldProcessor
Definition: ke.h:48
PROCESSOR_POWER_STATE PowerState
Definition: ketypes.h:800
PPROCESSOR_IDLE_FUNCTION IdleFunction
Definition: potypes.h:68

◆ KiRetireDpcListInDpcStack()

VOID KiRetireDpcListInDpcStack ( PKPRCB  Prcb,
PVOID  DpcStack 
)

◆ KiSwapProcess()

VOID NTAPI KiSwapProcess ( IN PKPROCESS  NewProcess,
IN PKPROCESS  OldProcess 
)

Definition at line 232 of file stubs.c.

234{
235 PKIPCR Pcr = (PKIPCR)KeGetPcr();
236
237#ifdef CONFIG_SMP
238 /* Update active processor mask */
239 InterlockedXor64((PLONG64)&NewProcess->ActiveProcessors, Pcr->Prcb.SetMember);
240 InterlockedXor64((PLONG64)&OldProcess->ActiveProcessors, Pcr->Prcb.SetMember);
241#endif
242
243 /* Update CR3 */
244 __writecr3(NewProcess->DirectoryTableBase[0]);
245
246 /* Update IOPM offset */
247 Pcr->TssBase->IoMapBase = NewProcess->IopmOffset;
248}
__int64 * PLONG64
Definition: basetsd.h:185
#define InterlockedXor64
Definition: interlocked.h:291
__INTRIN_INLINE void __writecr3(unsigned int Data)
Definition: intrin_x86.h:1794
struct _KIPCR * PKIPCR
#define KeGetPcr()
Definition: ke.h:26
KPRCB Prcb
Definition: ketypes.h:894
struct _KTSS64 * TssBase
Definition: ketypes.h:866
UINT64 SetMember
Definition: ketypes.h:583

◆ KiSwitchKernelStack()

PVOID NTAPI KiSwitchKernelStack ( PVOID  StackBase,
PVOID  StackLimit 
)

Definition at line 111 of file stubs.c.

112{
113 PKTHREAD CurrentThread;
114 PVOID OldStackBase;
115 LONG_PTR StackOffset;
117 PKIPCR Pcr;
118 ULONG Eflags;
119
120 /* Get the current thread */
121 CurrentThread = KeGetCurrentThread();
122
123 /* Save the old stack base */
124 OldStackBase = CurrentThread->StackBase;
125
126 /* Get the size of the current stack */
127 StackSize = (ULONG_PTR)CurrentThread->StackBase - CurrentThread->StackLimit;
128 ASSERT(StackSize <= (ULONG_PTR)StackBase - (ULONG_PTR)StackLimit);
129
130 /* Copy the current stack contents to the new stack */
131 RtlCopyMemory((PUCHAR)StackBase - StackSize,
132 (PVOID)CurrentThread->StackLimit,
133 StackSize);
134
135 /* Calculate the offset between the old and the new stack */
136 StackOffset = (PUCHAR)StackBase - (PUCHAR)CurrentThread->StackBase;
137
138 /* Disable interrupts while messing with the stack */
139 Eflags = __readeflags();
140 _disable();
141
142 /* Set the new trap frame */
143 CurrentThread->TrapFrame = (PKTRAP_FRAME)Add2Ptr(CurrentThread->TrapFrame,
144 StackOffset);
145
146 /* Set the new initial stack */
147 CurrentThread->InitialStack = Add2Ptr(CurrentThread->InitialStack,
148 StackOffset);
149
150 /* Set the new stack limits */
151 CurrentThread->StackBase = StackBase;
152 CurrentThread->StackLimit = (ULONG_PTR)StackLimit;
153 CurrentThread->LargeStack = TRUE;
154
155 /* Adjust RspBase in the PCR */
156 Pcr = (PKIPCR)KeGetPcr();
157 Pcr->Prcb.RspBase += StackOffset;
158
159 /* Adjust Rsp0 in the TSS */
160 Pcr->TssBase->Rsp0 += StackOffset;
161
162 /* Restore interrupts */
163 __writeeflags(Eflags);
164
165 return OldStackBase;
166}
static ULONG StackSize
Definition: StackOverflow.c:19
#define ULONG_PTR
Definition: config.h:101
#define KeGetCurrentThread
Definition: hal.h:55
__INTRIN_INLINE void __writeeflags(uintptr_t Value)
Definition: intrin_x86.h:1669
__INTRIN_INLINE uintptr_t __readeflags(void)
Definition: intrin_x86.h:1674
#define Add2Ptr(PTR, INC)
#define ASSERT(a)
Definition: mode.c:44
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
struct _KTRAP_FRAME * PKTRAP_FRAME
UINT64 RspBase
Definition: ketypes.h:581
PKTRAP_FRAME TrapFrame
Definition: ketypes.h:1714
PVOID InitialStack
Definition: ketypes.h:1604
PVOID StackBase
Definition: ketypes.h:1606
volatile VOID * StackLimit
Definition: ketypes.h:1605
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59

◆ KiSwitchKernelStackHelper()

PVOID KiSwitchKernelStackHelper ( LONG_PTR  StackOffset,
PVOID  OldStackBase 
)

◆ KiSystemCallHandler()

PVOID KiSystemCallHandler ( VOID  )

Definition at line 260 of file stubs.c.

262{
263 PKTRAP_FRAME TrapFrame;
264 PKSERVICE_TABLE_DESCRIPTOR DescriptorTable;
266 PULONG64 KernelParams, UserParams;
267 ULONG ServiceNumber, Offset, Count;
268 ULONG64 UserRsp;
269
270 /* Get a pointer to the trap frame */
272
273 /* Increase system call count */
274 __addgsdword(FIELD_OFFSET(KIPCR, Prcb.KeSystemCalls), 1);
275
276 /* Get the current thread */
278
279 /* Set previous mode */
280 Thread->PreviousMode = TrapFrame->PreviousMode = UserMode;
281
282 /* Save the old trap frame and set the new */
283 TrapFrame->TrapFrame = (ULONG64)Thread->TrapFrame;
284 Thread->TrapFrame = TrapFrame;
285
286 /* We don't have an exception frame yet */
287 TrapFrame->ExceptionFrame = 0;
288
289 /* Before enabling interrupts get the user rsp from the KPCR */
290 UserRsp = __readgsqword(FIELD_OFFSET(KIPCR, UserRsp));
291 TrapFrame->Rsp = UserRsp;
292
293 /* Enable interrupts */
294 _enable();
295
296 /* If the usermode rsp was not a usermode address, prepare an exception */
297 if (UserRsp > MmUserProbeAddress) UserRsp = MmUserProbeAddress;
298
299 /* Get the address of the usermode and kernelmode parameters */
300 UserParams = (PULONG64)UserRsp + 1;
301 KernelParams = (PULONG64)TrapFrame - MAX_SYSCALL_PARAMS;
302
303 /* Get the system call number from the trap frame and decode it */
304 ServiceNumber = (ULONG)TrapFrame->Rax;
305 Offset = (ServiceNumber >> SERVICE_TABLE_SHIFT) & SERVICE_TABLE_MASK;
306 ServiceNumber &= SERVICE_NUMBER_MASK;
307
308 /* Check for win32k system calls */
310 {
311 ULONG GdiBatchCount;
312
313 /* Read the GDI batch count from the TEB */
315 {
316 GdiBatchCount = NtCurrentTeb()->GdiBatchCount;
317 }
319 {
320 GdiBatchCount = 0;
321 }
322 _SEH2_END;
323
324 /* Flush batch, if there are entries */
325 if (GdiBatchCount != 0)
326 {
328 }
329 }
330
331 /* Get descriptor table */
332 DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
333
334 /* Validate the system call number */
335 if (ServiceNumber >= DescriptorTable->Limit)
336 {
337 /* Check if this is a GUI call */
338 if (!(Offset & SERVICE_TABLE_TEST))
339 {
340 /* Fail the call */
342 return (PVOID)NtSyscallFailure;
343 }
344
345 /* Convert us to a GUI thread
346 To be entirely correct. we return KiConvertToGuiThread,
347 which allocates a new stack, switches to it, calls
348 PsConvertToGuiThread and resumes in the middle of
349 KiSystemCallEntry64 to restart the system call handling. */
351 }
352
353 /* Get stack bytes and calculate argument count */
354 Count = DescriptorTable->Number[ServiceNumber] / 8;
355
357 {
358 switch (Count)
359 {
360 case 16: KernelParams[15] = UserParams[15];
361 case 15: KernelParams[14] = UserParams[14];
362 case 14: KernelParams[13] = UserParams[13];
363 case 13: KernelParams[12] = UserParams[12];
364 case 12: KernelParams[11] = UserParams[11];
365 case 11: KernelParams[10] = UserParams[10];
366 case 10: KernelParams[9] = UserParams[9];
367 case 9: KernelParams[8] = UserParams[8];
368 case 8: KernelParams[7] = UserParams[7];
369 case 7: KernelParams[6] = UserParams[6];
370 case 6: KernelParams[5] = UserParams[5];
371 case 5: KernelParams[4] = UserParams[4];
372 case 4:
373 case 3:
374 case 2:
375 case 1:
376 case 0:
377 break;
378
379 default:
380 ASSERT(FALSE);
381 break;
382 }
383 }
385 {
386 TrapFrame->Rax = _SEH2_GetExceptionCode();
387 return (PVOID)NtSyscallFailure;
388 }
389 _SEH2_END;
390
391 return (PVOID)DescriptorTable->Base[ServiceNumber];
392}
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define _AddressOfReturnAddress()
Definition: intrin_ppc.h:40
#define NtCurrentTeb
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
#define UserMode
Definition: asm.h:35
#define SERVICE_TABLE_SHIFT
Definition: ketypes.h:71
#define SERVICE_TABLE_MASK
Definition: ketypes.h:78
#define SERVICE_NUMBER_MASK
Definition: ketypes.h:83
#define SERVICE_TABLE_TEST
Definition: ketypes.h:90
int Count
Definition: noreturn.cpp:7
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch
Definition: win32.c:20
#define MAX_SYSCALL_PARAMS
Definition: stubs.c:250
NTSTATUS KiConvertToGuiThread(VOID)
NTSTATUS NtSyscallFailure(void)
Definition: stubs.c:253
ULONG MmUserProbeAddress
Definition: init.c:50
#define STATUS_INVALID_SYSTEM_SERVICE
Definition: ntstatus.h:265
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
UINT64 Rsp
Definition: ketypes.h:391
CHAR PreviousMode
Definition: ketypes.h:318
UINT64 ExceptionFrame
Definition: ketypes.h:381
UINT64 Rax
Definition: ketypes.h:323
UINT64 TrapFrame
Definition: ketypes.h:373
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
void * PVOID
Definition: typedefs.h:50

◆ KiSystemService()

VOID KiSystemService ( IN PKTHREAD  Thread,
IN PKTRAP_FRAME  TrapFrame,
IN ULONG  Instruction 
)

Definition at line 397 of file stubs.c.

400{
402 __debugbreak();
403}
#define UNIMPLEMENTED
Definition: stubs.c:5
void __cdecl __debugbreak(void)
Definition: intrin_ppc.h:698

◆ NtSetLdtEntries()

NTSTATUS NTAPI NtSetLdtEntries ( ULONG  Selector1,
LDT_ENTRY  LdtEntry1,
ULONG  Selector2,
LDT_ENTRY  LdtEntry2 
)

Definition at line 407 of file stubs.c.

409{
411 __debugbreak();
412 return STATUS_UNSUCCESSFUL;
413}
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132

Referenced by init_funcs().

◆ NtSyscallFailure()

NTSTATUS NtSyscallFailure ( void  )

Definition at line 253 of file stubs.c.

254{
255 /* This is the failure function */
256 return (NTSTATUS)KeGetCurrentThread()->TrapFrame->Rax;
257}
LONG NTSTATUS
Definition: precomp.h:26

Referenced by KiSystemCallHandler().

◆ NtVdmControl()

NTSTATUS NTAPI NtVdmControl ( IN ULONG  ControlCode,
IN PVOID  ControlData 
)

Definition at line 417 of file stubs.c.

419{
420 /* Not supported */
422}
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:239

Referenced by KiEnterV86Mode().

Variable Documentation

◆ KeXStateLength

SIZE_T KeXStateLength = sizeof(XSAVE_FORMAT)

Definition at line 17 of file stubs.c.

◆ ProcessCount

ULONG ProcessCount

Definition at line 16 of file stubs.c.