2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ke/process.c
5 * PURPOSE: Kernel Process Management and System Call Tables
6 * PROGRAMMERS: Alex Ionescu
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 LIST_ENTRY KiProcessListHead
;
19 LIST_ENTRY KiProcessInSwapListHead
, KiProcessOutSwapListHead
;
20 LIST_ENTRY KiStackInSwapListHead
;
23 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable
[SSDT_MAX_ENTRIES
];
24 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow
[SSDT_MAX_ENTRIES
];
26 PVOID KeUserApcDispatcher
;
27 PVOID KeUserCallbackDispatcher
;
28 PVOID KeUserExceptionDispatcher
;
29 PVOID KeRaiseUserExceptionDispatcher
;
31 /* PRIVATE FUNCTIONS *********************************************************/
35 KiAttachProcess(IN PKTHREAD Thread
,
37 IN PKLOCK_QUEUE_HANDLE ApcLock
,
38 IN PRKAPC_STATE SavedApcState
)
41 PLIST_ENTRY ListHead
, NextEntry
;
42 PKTHREAD CurrentThread
;
44 ASSERT(Process
!= Thread
->ApcState
.Process
);
46 /* Increase Stack Count */
47 ASSERT(Process
->StackCount
!= MAXULONG_PTR
);
48 Process
->StackCount
++;
50 /* Swap the APC Environment */
51 KiMoveApcState(&Thread
->ApcState
, SavedApcState
);
53 /* Reinitialize Apc State */
54 InitializeListHead(&Thread
->ApcState
.ApcListHead
[KernelMode
]);
55 InitializeListHead(&Thread
->ApcState
.ApcListHead
[UserMode
]);
56 Thread
->ApcState
.Process
= Process
;
57 Thread
->ApcState
.KernelApcInProgress
= FALSE
;
58 Thread
->ApcState
.KernelApcPending
= FALSE
;
59 Thread
->ApcState
.UserApcPending
= FALSE
;
61 /* Update Environment Pointers if needed*/
62 if (SavedApcState
== &Thread
->SavedApcState
)
64 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->
66 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->ApcState
;
67 Thread
->ApcStateIndex
= AttachedApcEnvironment
;
70 /* Check if the process is paged in */
71 if (Process
->State
== ProcessInMemory
)
73 /* Scan the ready list */
75 ListHead
= &Process
->ReadyListHead
;
76 NextEntry
= ListHead
->Flink
;
77 while (NextEntry
!= ListHead
)
80 CurrentThread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, WaitListEntry
);
83 RemoveEntryList(NextEntry
);
84 CurrentThread
->ProcessReadyQueue
= FALSE
;
87 KiReadyThread(CurrentThread
);
89 /* Go to the next one */
90 NextEntry
= ListHead
->Flink
;
94 /* Release dispatcher lock */
95 KiReleaseDispatcherLockFromDpcLevel();
98 KiReleaseApcLockFromDpcLevel(ApcLock
);
100 /* Make sure that we are in the right page directory (ReactOS Mm Hack) */
101 MiSyncForProcessAttach(Thread
, (PEPROCESS
)Process
);
104 KiSwapProcess(Process
, SavedApcState
->Process
);
106 /* Exit the dispatcher */
107 KiExitDispatcher(ApcLock
->OldIrql
);
111 DPRINT1("Errr. ReactOS doesn't support paging out processes yet...\n");
118 KeInitializeProcess(IN OUT PKPROCESS Process
,
119 IN KPRIORITY Priority
,
120 IN KAFFINITY Affinity
,
121 IN PULONG DirectoryTableBase
,
130 /* Initialize the Dispatcher Header */
131 KeInitializeDispatcherHeader(&Process
->Header
,
136 /* Initialize Scheduler Data, Alignment Faults and Set the PDE */
137 Process
->Affinity
= Affinity
;
138 Process
->BasePriority
= (CHAR
)Priority
;
139 Process
->QuantumReset
= 6;
140 Process
->DirectoryTableBase
[0] = DirectoryTableBase
[0];
141 Process
->DirectoryTableBase
[1] = DirectoryTableBase
[1];
142 Process
->AutoAlignment
= Enable
;
144 Process
->IopmOffset
= KiComputeIopmOffset(IO_ACCESS_MAP_NONE
);
147 /* Initialize the lists */
148 InitializeListHead(&Process
->ThreadListHead
);
149 InitializeListHead(&Process
->ProfileListHead
);
150 InitializeListHead(&Process
->ReadyListHead
);
152 /* Initialize the current State */
153 Process
->State
= ProcessInMemory
;
155 /* Check how many Nodes there are on the system */
157 if (KeNumberNodes
> 1)
159 /* Set the new seed */
160 KeProcessNodeSeed
= (KeProcessNodeSeed
+ 1) / KeNumberNodes
;
161 IdealNode
= KeProcessNodeSeed
;
163 /* Loop every node */
166 /* Check if the affinity matches */
167 if (KeNodeBlock
[IdealNode
]->ProcessorMask
!= Affinity
) break;
169 /* No match, try next Ideal Node and increase node loop index */
173 /* Check if the Ideal Node is beyond the total number of nodes */
174 if (IdealNode
>= KeNumberNodes
)
176 /* Normalize the Ideal Node */
177 IdealNode
-= KeNumberNodes
;
179 } while (i
< KeNumberNodes
);
182 /* Set the ideal node and get the ideal node block */
183 Process
->IdealNode
= IdealNode
;
184 Node
= KeNodeBlock
[IdealNode
];
185 ASSERT(Node
->ProcessorMask
& Affinity
);
187 /* Find the matching affinity set to calculate the thread seed */
188 Affinity
&= Node
->ProcessorMask
;
189 Process
->ThreadSeed
= KeFindNextRightSetAffinity(Node
->Seed
,
191 Node
->Seed
= Process
->ThreadSeed
;
197 KeSetProcess(IN PKPROCESS Process
,
198 IN KPRIORITY Increment
,
203 ASSERT_PROCESS(Process
);
204 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
206 /* Lock Dispatcher */
207 OldIrql
= KiAcquireDispatcherLock();
210 OldState
= Process
->Header
.SignalState
;
212 /* Signal the Process */
213 Process
->Header
.SignalState
= TRUE
;
215 /* Check if was unsignaled and has waiters */
217 !(IsListEmpty(&Process
->Header
.WaitListHead
)))
219 /* Unwait the threads */
220 KxUnwaitThread(&Process
->Header
, Increment
);
223 /* Release Dispatcher Database */
224 KiReleaseDispatcherLock(OldIrql
);
226 /* Return the previous State */
232 KeSetQuantumProcess(IN PKPROCESS Process
,
235 KLOCK_QUEUE_HANDLE ProcessLock
;
236 PLIST_ENTRY NextEntry
, ListHead
;
238 ASSERT_PROCESS(Process
);
239 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
241 /* Lock the process */
242 KiAcquireProcessLock(Process
, &ProcessLock
);
244 /* Set new quantum */
245 Process
->QuantumReset
= Quantum
;
247 /* Loop all child threads */
248 ListHead
= &Process
->ThreadListHead
;
249 NextEntry
= ListHead
->Flink
;
250 while (ListHead
!= NextEntry
)
253 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
256 Thread
->QuantumReset
= Quantum
;
258 /* Go to the next one */
259 NextEntry
= NextEntry
->Flink
;
263 KiReleaseProcessLock(&ProcessLock
);
268 KeSetPriorityAndQuantumProcess(IN PKPROCESS Process
,
269 IN KPRIORITY Priority
,
270 IN UCHAR Quantum OPTIONAL
)
272 KLOCK_QUEUE_HANDLE ProcessLock
;
274 PLIST_ENTRY NextEntry
, ListHead
;
275 KPRIORITY NewPriority
, OldPriority
;
277 ASSERT_PROCESS(Process
);
278 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
280 /* Check if the process already has this priority */
281 if (Process
->BasePriority
== Priority
) return Process
->BasePriority
;
283 /* If the caller gave priority 0, normalize to 1 */
284 if (!Priority
) Priority
= LOW_PRIORITY
+ 1;
286 /* Lock the process */
287 KiAcquireProcessLock(Process
, &ProcessLock
);
289 /* Check if we are modifying the quantum too */
290 if (Quantum
) Process
->QuantumReset
= Quantum
;
292 /* Save the current base priority and update it */
293 OldPriority
= Process
->BasePriority
;
294 Process
->BasePriority
= (SCHAR
)Priority
;
296 /* Calculate the priority delta */
297 Delta
= Priority
- OldPriority
;
299 /* Set the list head and list entry */
300 ListHead
= &Process
->ThreadListHead
;
301 NextEntry
= ListHead
->Flink
;
303 /* Check if this is a real-time priority */
304 if (Priority
>= LOW_REALTIME_PRIORITY
)
306 /* Loop the thread list */
307 while (NextEntry
!= ListHead
)
310 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
312 /* Update the quantum if we had one */
313 if (Quantum
) Thread
->QuantumReset
= Quantum
;
315 /* Acquire the thread lock */
316 KiAcquireThreadLock(Thread
);
318 /* Calculate the new priority */
319 NewPriority
= Thread
->BasePriority
+ Delta
;
320 if (NewPriority
< LOW_REALTIME_PRIORITY
)
322 /* We're in real-time range, don't let it go below */
323 NewPriority
= LOW_REALTIME_PRIORITY
;
325 else if (NewPriority
> HIGH_PRIORITY
)
327 /* We're going beyond the maximum priority, normalize */
328 NewPriority
= HIGH_PRIORITY
;
332 * If priority saturation occured or the old priority was still in
333 * the real-time range, don't do anything.
335 if (!(Thread
->Saturation
) || (OldPriority
< LOW_REALTIME_PRIORITY
))
337 /* Check if we had priority saturation */
338 if (Thread
->Saturation
> 0)
340 /* Boost priority to maximum */
341 NewPriority
= HIGH_PRIORITY
;
343 else if (Thread
->Saturation
< 0)
345 /* If we had negative saturation, set minimum priority */
346 NewPriority
= LOW_REALTIME_PRIORITY
;
349 /* Update priority and quantum */
350 Thread
->BasePriority
= (SCHAR
)NewPriority
;
351 Thread
->Quantum
= Thread
->QuantumReset
;
353 /* Disable decrements and update priority */
354 Thread
->PriorityDecrement
= 0;
355 KiSetPriorityThread(Thread
, NewPriority
);
358 /* Release the thread lock */
359 KiReleaseThreadLock(Thread
);
361 /* Go to the next thread */
362 NextEntry
= NextEntry
->Flink
;
367 /* Loop the thread list */
368 while (NextEntry
!= ListHead
)
371 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
373 /* Update the quantum if we had one */
374 if (Quantum
) Thread
->QuantumReset
= Quantum
;
376 /* Lock the thread */
377 KiAcquireThreadLock(Thread
);
379 /* Calculate the new priority */
380 NewPriority
= Thread
->BasePriority
+ Delta
;
381 if (NewPriority
>= LOW_REALTIME_PRIORITY
)
383 /* We're not real-time range, don't let it enter RT range */
384 NewPriority
= LOW_REALTIME_PRIORITY
- 1;
386 else if (NewPriority
<= LOW_PRIORITY
)
388 /* We're going below the minimum priority, normalize */
393 * If priority saturation occured or the old priority was still in
394 * the real-time range, don't do anything.
396 if (!(Thread
->Saturation
) ||
397 (OldPriority
>= LOW_REALTIME_PRIORITY
))
399 /* Check if we had priority saturation */
400 if (Thread
->Saturation
> 0)
402 /* Boost priority to maximum */
403 NewPriority
= LOW_REALTIME_PRIORITY
- 1;
405 else if (Thread
->Saturation
< 0)
407 /* If we had negative saturation, set minimum priority */
411 /* Update priority and quantum */
412 Thread
->BasePriority
= (SCHAR
)NewPriority
;
413 Thread
->Quantum
= Thread
->QuantumReset
;
415 /* Disable decrements and update priority */
416 Thread
->PriorityDecrement
= 0;
417 KiSetPriorityThread(Thread
, NewPriority
);
420 /* Release the thread lock */
421 KiReleaseThreadLock(Thread
);
423 /* Go to the next thread */
424 NextEntry
= NextEntry
->Flink
;
428 /* Release Dispatcher Database */
429 KiReleaseDispatcherLockFromDpcLevel();
431 /* Release the process lock */
432 KiReleaseProcessLockFromDpcLevel(&ProcessLock
);
433 KiExitDispatcher(ProcessLock
.OldIrql
);
435 /* Return previous priority */
439 /* PUBLIC FUNCTIONS **********************************************************/
446 KeAttachProcess(IN PKPROCESS Process
)
448 KLOCK_QUEUE_HANDLE ApcLock
;
449 PKTHREAD Thread
= KeGetCurrentThread();
450 ASSERT_PROCESS(Process
);
451 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
453 /* Make sure that we are in the right page directory (ReactOS Mm Hack) */
454 MiSyncForProcessAttach(Thread
, (PEPROCESS
)Process
);
456 /* Check if we're already in that process */
457 if (Thread
->ApcState
.Process
== Process
) return;
459 /* Check if a DPC is executing or if we're already attached */
460 if ((Thread
->ApcStateIndex
!= OriginalApcEnvironment
) ||
461 (KeIsExecutingDpc()))
463 /* Invalid attempt */
464 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT
,
466 (ULONG_PTR
)Thread
->ApcState
.Process
,
467 Thread
->ApcStateIndex
,
472 /* Acquire APC Lock */
473 KiAcquireApcLock(Thread
, &ApcLock
);
475 /* Acquire the dispatcher lock */
476 KiAcquireDispatcherLockAtDpcLevel();
478 /* Legit attach attempt: do it! */
479 KiAttachProcess(Thread
, Process
, &ApcLock
, &Thread
->SavedApcState
);
488 KeDetachProcess(VOID
)
490 PKTHREAD Thread
= KeGetCurrentThread();
491 KLOCK_QUEUE_HANDLE ApcLock
;
493 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
495 /* Check if it's attached */
496 if (Thread
->ApcStateIndex
== OriginalApcEnvironment
) return;
498 /* Acquire APC Lock */
499 KiAcquireApcLock(Thread
, &ApcLock
);
501 /* Check for invalid attach attempts */
502 if ((Thread
->ApcState
.KernelApcInProgress
) ||
503 !(IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])) ||
504 !(IsListEmpty(&Thread
->ApcState
.ApcListHead
[UserMode
])))
506 /* Crash the system */
507 KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT
);
510 /* Get the process */
511 Process
= Thread
->ApcState
.Process
;
513 /* Acquire dispatcher lock */
514 KiAcquireDispatcherLockAtDpcLevel();
516 /* Decrease the stack count */
517 ASSERT(Process
->StackCount
!= 0);
518 ASSERT(Process
->State
== ProcessInMemory
);
519 Process
->StackCount
--;
521 /* Check if we can swap the process out */
522 if (!Process
->StackCount
)
524 /* FIXME: Swap the process out */
527 /* Release dispatcher lock */
528 KiReleaseDispatcherLockFromDpcLevel();
530 /* Restore the APC State */
531 KiMoveApcState(&Thread
->SavedApcState
, &Thread
->ApcState
);
532 Thread
->SavedApcState
.Process
= NULL
;
533 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->ApcState
;
534 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->SavedApcState
;
535 Thread
->ApcStateIndex
= OriginalApcEnvironment
;
538 KiReleaseApcLockFromDpcLevel(&ApcLock
);
541 KiSwapProcess(Thread
->ApcState
.Process
, Process
);
543 /* Exit the dispatcher */
544 KiExitDispatcher(ApcLock
.OldIrql
);
546 /* Check if we have pending APCs */
547 if (IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
]))
549 /* What do you know, we do! Request them to be delivered */
550 Thread
->ApcState
.KernelApcPending
= TRUE
;
551 HalRequestSoftwareInterrupt(APC_LEVEL
);
560 KeIsAttachedProcess(VOID
)
562 /* Return the APC State */
563 return KeGetCurrentThread()->ApcStateIndex
;
571 KeStackAttachProcess(IN PKPROCESS Process
,
572 OUT PRKAPC_STATE ApcState
)
574 KLOCK_QUEUE_HANDLE ApcLock
;
575 PKTHREAD Thread
= KeGetCurrentThread();
576 ASSERT_PROCESS(Process
);
577 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
579 /* Crash system if DPC is being executed! */
580 if (KeIsExecutingDpc())
582 /* Executing a DPC, crash! */
583 KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT
,
585 (ULONG_PTR
)Thread
->ApcState
.Process
,
586 Thread
->ApcStateIndex
,
590 /* Check if we are already in the target process */
591 if (Thread
->ApcState
.Process
== Process
)
593 /* Set magic value so we don't crash later when detaching */
594 ApcState
->Process
= (PKPROCESS
)1;
598 /* Acquire APC Lock */
599 KiAcquireApcLock(Thread
, &ApcLock
);
601 /* Acquire dispatcher lock */
602 KiAcquireDispatcherLockAtDpcLevel();
604 /* Check if the Current Thread is already attached */
605 if (Thread
->ApcStateIndex
!= OriginalApcEnvironment
)
607 /* We're already attached, so save the APC State into what we got */
608 KiAttachProcess(Thread
, Process
, &ApcLock
, ApcState
);
612 /* We're not attached, so save the APC State into SavedApcState */
613 KiAttachProcess(Thread
, Process
, &ApcLock
, &Thread
->SavedApcState
);
614 ApcState
->Process
= NULL
;
623 KeUnstackDetachProcess(IN PRKAPC_STATE ApcState
)
625 KLOCK_QUEUE_HANDLE ApcLock
;
626 PKTHREAD Thread
= KeGetCurrentThread();
628 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
630 /* Check for magic value meaning we were already in the same process */
631 if (ApcState
->Process
== (PKPROCESS
)1) return;
633 /* Loop to make sure no APCs are pending */
636 /* Acquire APC Lock */
637 KiAcquireApcLock(Thread
, &ApcLock
);
639 /* Check if a kernel APC is pending */
640 if (Thread
->ApcState
.KernelApcPending
)
642 /* Check if kernel APC should be delivered */
643 if (!(Thread
->KernelApcDisable
) && (ApcLock
.OldIrql
<= APC_LEVEL
))
645 /* Release the APC lock so that the APC can be delivered */
646 KiReleaseApcLock(&ApcLock
);
651 /* Otherwise, break out */
656 * Check if the process isn't attacked, or has a Kernel APC in progress
657 * or has pending APC of any kind.
659 if ((Thread
->ApcStateIndex
== OriginalApcEnvironment
) ||
660 (Thread
->ApcState
.KernelApcInProgress
) ||
661 (!IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
])) ||
662 (!IsListEmpty(&Thread
->ApcState
.ApcListHead
[UserMode
])))
664 /* Bugcheck the system */
665 KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT
);
668 /* Get the process */
669 Process
= Thread
->ApcState
.Process
;
671 /* Acquire dispatcher lock */
672 KiAcquireDispatcherLockAtDpcLevel();
674 /* Decrease the stack count */
675 ASSERT(Process
->StackCount
!= 0);
676 ASSERT(Process
->State
== ProcessInMemory
);
677 Process
->StackCount
--;
679 /* Check if we can swap the process out */
680 if (!Process
->StackCount
)
682 /* FIXME: Swap the process out */
685 /* Release dispatcher lock */
686 KiReleaseDispatcherLockFromDpcLevel();
688 /* Check if there's an APC state to restore */
689 if (ApcState
->Process
)
691 /* Restore the APC State */
692 KiMoveApcState(ApcState
, &Thread
->ApcState
);
696 /* The ApcState parameter is useless, so use the saved data and reset it */
697 KiMoveApcState(&Thread
->SavedApcState
, &Thread
->ApcState
);
698 Thread
->SavedApcState
.Process
= NULL
;
699 Thread
->ApcStateIndex
= OriginalApcEnvironment
;
700 Thread
->ApcStatePointer
[OriginalApcEnvironment
] = &Thread
->ApcState
;
701 Thread
->ApcStatePointer
[AttachedApcEnvironment
] = &Thread
->SavedApcState
;
705 KiReleaseApcLockFromDpcLevel(&ApcLock
);
708 KiSwapProcess(Thread
->ApcState
.Process
, Process
);
710 /* Exit the dispatcher */
711 KiExitDispatcher(ApcLock
.OldIrql
);
713 /* Check if we have pending APCs */
714 if (IsListEmpty(&Thread
->ApcState
.ApcListHead
[KernelMode
]))
716 /* What do you know, we do! Request them to be delivered */
717 Thread
->ApcState
.KernelApcPending
= TRUE
;
718 HalRequestSoftwareInterrupt(APC_LEVEL
);
727 KeQueryRuntimeProcess(IN PKPROCESS Process
,
730 ULONG TotalUser
, TotalKernel
;
731 KLOCK_QUEUE_HANDLE ProcessLock
;
732 PLIST_ENTRY NextEntry
, ListHead
;
735 ASSERT_PROCESS(Process
);
737 /* Initialize user and kernel times */
738 TotalUser
= Process
->UserTime
;
739 TotalKernel
= Process
->KernelTime
;
741 /* Lock the process */
742 KiAcquireProcessLock(Process
, &ProcessLock
);
744 /* Loop all child threads and sum up their times */
745 ListHead
= &Process
->ThreadListHead
;
746 NextEntry
= ListHead
->Flink
;
747 while (ListHead
!= NextEntry
)
750 Thread
= CONTAINING_RECORD(NextEntry
, KTHREAD
, ThreadListEntry
);
753 TotalKernel
+= Thread
->KernelTime
;
754 TotalUser
+= Thread
->UserTime
;
756 /* Go to the next one */
757 NextEntry
= NextEntry
->Flink
;
761 KiReleaseProcessLock(&ProcessLock
);
763 /* Return the user time */
764 *UserTime
= TotalUser
;
766 /* Return the kernel time */
775 KeAddSystemServiceTable(IN PULONG_PTR Base
,
776 IN PULONG Count OPTIONAL
,
783 /* Check if descriptor table entry is free */
784 if ((Index
> SSDT_MAX_ENTRIES
- 1) ||
785 (KeServiceDescriptorTable
[Index
].Base
) ||
786 (KeServiceDescriptorTableShadow
[Index
].Base
))
792 /* Initialize the shadow service descriptor table */
793 KeServiceDescriptorTableShadow
[Index
].Base
= Base
;
794 KeServiceDescriptorTableShadow
[Index
].Limit
= Limit
;
795 KeServiceDescriptorTableShadow
[Index
].Number
= Number
;
796 KeServiceDescriptorTableShadow
[Index
].Count
= Count
;
805 KeRemoveSystemServiceTable(IN ULONG Index
)
809 /* Make sure the Index is valid */
810 if (Index
> (SSDT_MAX_ENTRIES
- 1)) return FALSE
;
812 /* Is there a Normal Descriptor Table? */
813 if (!KeServiceDescriptorTable
[Index
].Base
)
815 /* Not with the index, is there a shadow at least? */
816 if (!KeServiceDescriptorTableShadow
[Index
].Base
) return FALSE
;
819 /* Now clear from the Shadow Table. */
820 KeServiceDescriptorTableShadow
[Index
].Base
= NULL
;
821 KeServiceDescriptorTableShadow
[Index
].Number
= NULL
;
822 KeServiceDescriptorTableShadow
[Index
].Limit
= 0;
823 KeServiceDescriptorTableShadow
[Index
].Count
= NULL
;
825 /* Check if we should clean from the Master one too */
828 KeServiceDescriptorTable
[Index
].Base
= NULL
;
829 KeServiceDescriptorTable
[Index
].Number
= NULL
;
830 KeServiceDescriptorTable
[Index
].Limit
= 0;
831 KeServiceDescriptorTable
[Index
].Count
= NULL
;