ReactOS  0.4.11-dev-433-g473ca91
procobj.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Kernel
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: ntoskrnl/ke/procobj.c
5  * PURPOSE: Kernel Process Management and System Call Tables
6  * PROGRAMMERS: Alex Ionescu
7  * Gregor Anich
8  */
9 
10 /* INCLUDES ******************************************************************/
11 
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15 
16 /* GLOBALS *******************************************************************/
17 
22 
25 
30 
31 /* PRIVATE FUNCTIONS *********************************************************/
32 
33 VOID
34 NTAPI
37  IN PKLOCK_QUEUE_HANDLE ApcLock,
38  IN PRKAPC_STATE SavedApcState)
39 {
40 #if 0
41  PLIST_ENTRY ListHead, NextEntry;
42  PKTHREAD CurrentThread;
43 #endif
44  ASSERT(Process != Thread->ApcState.Process);
45 
46  /* Increase Stack Count */
47  ASSERT(Process->StackCount != MAXULONG_PTR);
48  Process->StackCount++;
49 
50  /* Swap the APC Environment */
51  KiMoveApcState(&Thread->ApcState, SavedApcState);
52 
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;
60 
61  /* Update Environment Pointers if needed*/
62  if (SavedApcState == &Thread->SavedApcState)
63  {
64  Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->
65  SavedApcState;
66  Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
67  Thread->ApcStateIndex = AttachedApcEnvironment;
68  }
69 
70  /* Check if the process is paged in */
71  if (Process->State == ProcessInMemory)
72  {
73  /* Scan the ready list */
74 #if 0
75  ListHead = &Process->ReadyListHead;
76  NextEntry = ListHead->Flink;
77  while (NextEntry != ListHead)
78  {
79  /* Get the thread */
80  CurrentThread = CONTAINING_RECORD(NextEntry, KTHREAD, WaitListEntry);
81 
82  /* Remove it */
83  RemoveEntryList(NextEntry);
84  CurrentThread->ProcessReadyQueue = FALSE;
85 
86  /* Mark it ready */
87  KiReadyThread(CurrentThread);
88 
89  /* Go to the next one */
90  NextEntry = ListHead->Flink;
91  }
92 #endif
93 
94  /* Release dispatcher lock */
96 
97  /* Release lock */
99 
100  /* Swap Processes */
101  KiSwapProcess(Process, SavedApcState->Process);
102 
103  /* Exit the dispatcher */
104  KiExitDispatcher(ApcLock->OldIrql);
105  }
106  else
107  {
108  DPRINT1("Errr. ReactOS doesn't support paging out processes yet...\n");
109  ASSERT(FALSE);
110  }
111 }
112 
113 VOID
114 NTAPI
118  IN PULONG_PTR DirectoryTableBase,
119  IN BOOLEAN Enable)
120 {
121 #ifdef CONFIG_SMP
122  ULONG i = 0;
123  UCHAR IdealNode = 0;
124  PKNODE Node;
125 #endif
126 
127  /* Initialize the Dispatcher Header */
128  Process->Header.Type = ProcessObject;
129  Process->Header.Size = sizeof(KPROCESS) / sizeof(ULONG);
130  Process->Header.SignalState = 0;
131  InitializeListHead(&(Process->Header.WaitListHead));
132 
133  /* Initialize Scheduler Data, Alignment Faults and Set the PDE */
134  Process->Affinity = Affinity;
135  Process->BasePriority = (CHAR)Priority;
136  Process->QuantumReset = 6;
137  Process->DirectoryTableBase[0] = DirectoryTableBase[0];
138  Process->DirectoryTableBase[1] = DirectoryTableBase[1];
139  Process->AutoAlignment = Enable;
140 #if defined(_M_IX86)
141  Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
142 #endif
143 
144  /* Initialize the lists */
145  InitializeListHead(&Process->ThreadListHead);
146  InitializeListHead(&Process->ProfileListHead);
147  InitializeListHead(&Process->ReadyListHead);
148 
149  /* Initialize the current State */
150  Process->State = ProcessInMemory;
151 
152  /* Check how many Nodes there are on the system */
153 #ifdef CONFIG_SMP
154  if (KeNumberNodes > 1)
155  {
156  /* Set the new seed */
158  IdealNode = KeProcessNodeSeed;
159 
160  /* Loop every node */
161  do
162  {
163  /* Check if the affinity matches */
164  if (KeNodeBlock[IdealNode]->ProcessorMask != Affinity) break;
165 
166  /* No match, try next Ideal Node and increase node loop index */
167  IdealNode++;
168  i++;
169 
170  /* Check if the Ideal Node is beyond the total number of nodes */
171  if (IdealNode >= KeNumberNodes)
172  {
173  /* Normalize the Ideal Node */
174  IdealNode -= KeNumberNodes;
175  }
176  } while (i < KeNumberNodes);
177  }
178 
179  /* Set the ideal node and get the ideal node block */
180  Process->IdealNode = IdealNode;
181  Node = KeNodeBlock[IdealNode];
182  ASSERT(Node->ProcessorMask & Affinity);
183 
184  /* Find the matching affinity set to calculate the thread seed */
185  Affinity &= Node->ProcessorMask;
186  Process->ThreadSeed = KeFindNextRightSetAffinity(Node->Seed,
187  (ULONG)Affinity);
188  Node->Seed = Process->ThreadSeed;
189 #endif
190 }
191 
192 ULONG
193 NTAPI
196  IN BOOLEAN InWait)
197 {
198  KIRQL OldIrql;
199  ULONG OldState;
200  ASSERT_PROCESS(Process);
202 
203  /* Lock Dispatcher */
204  OldIrql = KiAcquireDispatcherLock();
205 
206  /* Get Old State */
207  OldState = Process->Header.SignalState;
208 
209  /* Signal the Process */
210  Process->Header.SignalState = TRUE;
211 
212  /* Check if was unsignaled and has waiters */
213  if (!(OldState) &&
214  !(IsListEmpty(&Process->Header.WaitListHead)))
215  {
216  /* Unwait the threads */
217  KxUnwaitThread(&Process->Header, Increment);
218  }
219 
220  /* Release Dispatcher Database */
221  KiReleaseDispatcherLock(OldIrql);
222 
223  /* Return the previous State */
224  return OldState;
225 }
226 
227 VOID
228 NTAPI
230  IN UCHAR Quantum)
231 {
232  KLOCK_QUEUE_HANDLE ProcessLock;
233  PLIST_ENTRY NextEntry, ListHead;
235  ASSERT_PROCESS(Process);
237 
238  /* Lock the process */
239  KiAcquireProcessLock(Process, &ProcessLock);
240 
241  /* Set new quantum */
242  Process->QuantumReset = Quantum;
243 
244  /* Loop all child threads */
245  ListHead = &Process->ThreadListHead;
246  NextEntry = ListHead->Flink;
247  while (ListHead != NextEntry)
248  {
249  /* Get the thread */
250  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
251 
252  /* Set quantum */
253  Thread->QuantumReset = Quantum;
254 
255  /* Go to the next one */
256  NextEntry = NextEntry->Flink;
257  }
258 
259  /* Release lock */
260  KiReleaseProcessLock(&ProcessLock);
261 }
262 
263 KAFFINITY
264 NTAPI
267 {
268 
269  KLOCK_QUEUE_HANDLE ProcessLock;
270  PLIST_ENTRY NextEntry, ListHead;
271  KAFFINITY OldAffinity;
273  ASSERT_PROCESS(Process);
275  ASSERT((Affinity & KeActiveProcessors) != 0);
276 
277  /* Lock the process */
278  KiAcquireProcessLock(Process, &ProcessLock);
279 
280  /* Acquire the dispatcher lock */
282 
283  /* Capture old affinity and update it */
284  OldAffinity = Process->Affinity;
285  Process->Affinity = Affinity;
286 
287  /* Loop all child threads */
288  ListHead = &Process->ThreadListHead;
289  NextEntry = ListHead->Flink;
290  while (ListHead != NextEntry)
291  {
292  /* Get the thread */
293  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
294 
295  /* Set affinity on it */
296  KiSetAffinityThread(Thread, Affinity);
297  NextEntry = NextEntry->Flink;
298  }
299 
300  /* Release Dispatcher Database */
302 
303  /* Release the process lock */
304  KiReleaseProcessLockFromDpcLevel(&ProcessLock);
305  KiExitDispatcher(ProcessLock.OldIrql);
306 
307  /* Return previous affinity */
308  return OldAffinity;
309 }
310 
311 BOOLEAN
312 NTAPI
314  IN BOOLEAN Enable)
315 {
316  /* Set or reset the bit depending on what the enable flag says */
317  if (Enable)
318  {
319  return InterlockedBitTestAndSet(&Process->ProcessFlags,
321  }
322  else
323  {
324  return InterlockedBitTestAndReset(&Process->ProcessFlags,
326  }
327 }
328 
329 BOOLEAN
330 NTAPI
332  IN BOOLEAN Disable)
333 {
334  /* Set or reset the bit depending on what the disable flag says */
335  if (Disable)
336  {
337  return InterlockedBitTestAndSet(&Process->ProcessFlags,
339  }
340  else
341  {
342  return InterlockedBitTestAndReset(&Process->ProcessFlags,
344  }
345 }
346 
347 KPRIORITY
348 NTAPI
351  IN UCHAR Quantum OPTIONAL)
352 {
353  KLOCK_QUEUE_HANDLE ProcessLock;
355  PLIST_ENTRY NextEntry, ListHead;
356  KPRIORITY NewPriority, OldPriority;
358  ASSERT_PROCESS(Process);
360 
361  /* Check if the process already has this priority */
362  if (Process->BasePriority == Priority) return Process->BasePriority;
363 
364  /* If the caller gave priority 0, normalize to 1 */
365  if (!Priority) Priority = LOW_PRIORITY + 1;
366 
367  /* Lock the process */
368  KiAcquireProcessLock(Process, &ProcessLock);
369 
370  /* Check if we are modifying the quantum too */
371  if (Quantum) Process->QuantumReset = Quantum;
372 
373  /* Save the current base priority and update it */
374  OldPriority = Process->BasePriority;
375  Process->BasePriority = (SCHAR)Priority;
376 
377  /* Calculate the priority delta */
378  Delta = Priority - OldPriority;
379 
380  /* Set the list head and list entry */
381  ListHead = &Process->ThreadListHead;
382  NextEntry = ListHead->Flink;
383 
384  /* Check if this is a real-time priority */
385  if (Priority >= LOW_REALTIME_PRIORITY)
386  {
387  /* Loop the thread list */
388  while (NextEntry != ListHead)
389  {
390  /* Get the thread */
391  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
392 
393  /* Update the quantum if we had one */
394  if (Quantum) Thread->QuantumReset = Quantum;
395 
396  /* Acquire the thread lock */
397  KiAcquireThreadLock(Thread);
398 
399  /* Calculate the new priority */
400  NewPriority = Thread->BasePriority + Delta;
401  if (NewPriority < LOW_REALTIME_PRIORITY)
402  {
403  /* We're in real-time range, don't let it go below */
404  NewPriority = LOW_REALTIME_PRIORITY;
405  }
406  else if (NewPriority > HIGH_PRIORITY)
407  {
408  /* We're going beyond the maximum priority, normalize */
409  NewPriority = HIGH_PRIORITY;
410  }
411 
412  /*
413  * If priority saturation occured or the old priority was still in
414  * the real-time range, don't do anything.
415  */
416  if (!(Thread->Saturation) || (OldPriority < LOW_REALTIME_PRIORITY))
417  {
418  /* Check if we had priority saturation */
419  if (Thread->Saturation > 0)
420  {
421  /* Boost priority to maximum */
422  NewPriority = HIGH_PRIORITY;
423  }
424  else if (Thread->Saturation < 0)
425  {
426  /* If we had negative saturation, set minimum priority */
427  NewPriority = LOW_REALTIME_PRIORITY;
428  }
429 
430  /* Update priority and quantum */
431  Thread->BasePriority = (SCHAR)NewPriority;
432  Thread->Quantum = Thread->QuantumReset;
433 
434  /* Disable decrements and update priority */
435  Thread->PriorityDecrement = 0;
436  KiSetPriorityThread(Thread, NewPriority);
437  }
438 
439  /* Release the thread lock */
440  KiReleaseThreadLock(Thread);
441 
442  /* Go to the next thread */
443  NextEntry = NextEntry->Flink;
444  }
445  }
446  else
447  {
448  /* Loop the thread list */
449  while (NextEntry != ListHead)
450  {
451  /* Get the thread */
452  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
453 
454  /* Update the quantum if we had one */
455  if (Quantum) Thread->QuantumReset = Quantum;
456 
457  /* Lock the thread */
458  KiAcquireThreadLock(Thread);
459 
460  /* Calculate the new priority */
461  NewPriority = Thread->BasePriority + Delta;
462  if (NewPriority >= LOW_REALTIME_PRIORITY)
463  {
464  /* We're not real-time range, don't let it enter RT range */
465  NewPriority = LOW_REALTIME_PRIORITY - 1;
466  }
467  else if (NewPriority <= LOW_PRIORITY)
468  {
469  /* We're going below the minimum priority, normalize */
470  NewPriority = 1;
471  }
472 
473  /*
474  * If priority saturation occured or the old priority was still in
475  * the real-time range, don't do anything.
476  */
477  if (!(Thread->Saturation) ||
478  (OldPriority >= LOW_REALTIME_PRIORITY))
479  {
480  /* Check if we had priority saturation */
481  if (Thread->Saturation > 0)
482  {
483  /* Boost priority to maximum */
484  NewPriority = LOW_REALTIME_PRIORITY - 1;
485  }
486  else if (Thread->Saturation < 0)
487  {
488  /* If we had negative saturation, set minimum priority */
489  NewPriority = 1;
490  }
491 
492  /* Update priority and quantum */
493  Thread->BasePriority = (SCHAR)NewPriority;
494  Thread->Quantum = Thread->QuantumReset;
495 
496  /* Disable decrements and update priority */
497  Thread->PriorityDecrement = 0;
498  KiSetPriorityThread(Thread, NewPriority);
499  }
500 
501  /* Release the thread lock */
502  KiReleaseThreadLock(Thread);
503 
504  /* Go to the next thread */
505  NextEntry = NextEntry->Flink;
506  }
507  }
508 
509  /* Release Dispatcher Database */
511 
512  /* Release the process lock */
513  KiReleaseProcessLockFromDpcLevel(&ProcessLock);
514  KiExitDispatcher(ProcessLock.OldIrql);
515 
516  /* Return previous priority */
517  return OldPriority;
518 }
519 
520 VOID
521 NTAPI
523  PPROCESS_VALUES Values)
524 {
525  PEPROCESS EProcess;
526  PLIST_ENTRY NextEntry;
527  ULONG TotalKernel, TotalUser;
528  KLOCK_QUEUE_HANDLE ProcessLock;
529 
530  ASSERT_PROCESS(Process);
532 
533  /* Lock the process */
534  KiAcquireProcessLock(Process, &ProcessLock);
535 
536  /* Initialize user and kernel times */
537  TotalKernel = Process->KernelTime;
538  TotalUser = Process->UserTime;
539 
540  /* Copy the IO_COUNTERS from the process */
541  EProcess = (PEPROCESS)Process;
548 
549  /* Loop all child threads and sum up their times */
550  for (NextEntry = Process->ThreadListHead.Flink;
551  NextEntry != &Process->ThreadListHead;
552  NextEntry = NextEntry->Flink)
553  {
555 
556  /* Get the thread */
557  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
558 
559  /* Sum up times */
560  TotalKernel += Thread->KernelTime;
561  TotalUser += Thread->UserTime;
562  }
563 
564  /* Release the process lock */
565  KiReleaseProcessLock(&ProcessLock);
566 
567  /* Compute total times */
568  Values->TotalKernelTime.QuadPart = TotalKernel * (LONGLONG)KeMaximumIncrement;
569  Values->TotalUserTime.QuadPart = TotalUser * (LONGLONG)KeMaximumIncrement;
570 }
571 
572 /* PUBLIC FUNCTIONS **********************************************************/
573 
574 /*
575  * @implemented
576  */
577 VOID
578 NTAPI
580 {
581  KLOCK_QUEUE_HANDLE ApcLock;
583  ASSERT_PROCESS(Process);
585 
586  /* Check if we're already in that process */
587  if (Thread->ApcState.Process == Process) return;
588 
589  /* Check if a DPC is executing or if we're already attached */
590  if ((Thread->ApcStateIndex != OriginalApcEnvironment) ||
591  (KeIsExecutingDpc()))
592  {
593  /* Invalid attempt */
594  KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
595  (ULONG_PTR)Process,
596  (ULONG_PTR)Thread->ApcState.Process,
597  Thread->ApcStateIndex,
598  KeIsExecutingDpc());
599  }
600  else
601  {
602  /* Acquire APC Lock */
603  KiAcquireApcLock(Thread, &ApcLock);
604 
605  /* Acquire the dispatcher lock */
607 
608  /* Legit attach attempt: do it! */
609  KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
610  }
611 }
612 
613 /*
614  * @implemented
615  */
616 VOID
617 NTAPI
619 {
621  KLOCK_QUEUE_HANDLE ApcLock;
624 
625  /* Check if it's attached */
626  if (Thread->ApcStateIndex == OriginalApcEnvironment) return;
627 
628  /* Acquire APC Lock */
629  KiAcquireApcLock(Thread, &ApcLock);
630 
631  /* Check for invalid attach attempts */
632  if ((Thread->ApcState.KernelApcInProgress) ||
633  !(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
634  !(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
635  {
636  /* Crash the system */
637  KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
638  }
639 
640  /* Get the process */
641  Process = Thread->ApcState.Process;
642 
643  /* Acquire dispatcher lock */
645 
646  /* Decrease the stack count */
647  ASSERT(Process->StackCount != 0);
648  ASSERT(Process->State == ProcessInMemory);
649  Process->StackCount--;
650 
651  /* Check if we can swap the process out */
652  if (!Process->StackCount)
653  {
654  /* FIXME: Swap the process out */
655  }
656 
657  /* Release dispatcher lock */
659 
660  /* Restore the APC State */
661  KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
662  Thread->SavedApcState.Process = NULL;
663  Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
664  Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
666 
667  /* Release lock */
669 
670  /* Swap Processes */
671  KiSwapProcess(Thread->ApcState.Process, Process);
672 
673  /* Exit the dispatcher */
674  KiExitDispatcher(ApcLock.OldIrql);
675 
676  /* Check if we have pending APCs */
677  if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
678  {
679  /* What do you know, we do! Request them to be delivered */
680  Thread->ApcState.KernelApcPending = TRUE;
682  }
683 }
684 
685 /*
686  * @implemented
687  */
688 BOOLEAN
689 NTAPI
691 {
692  /* Return the APC State */
693  return KeGetCurrentThread()->ApcStateIndex;
694 }
695 
696 /*
697  * @implemented
698  */
699 VOID
700 NTAPI
703 {
704  KLOCK_QUEUE_HANDLE ApcLock;
706  ASSERT_PROCESS(Process);
708 
709  /* Crash system if DPC is being executed! */
710  if (KeIsExecutingDpc())
711  {
712  /* Executing a DPC, crash! */
713  KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
714  (ULONG_PTR)Process,
715  (ULONG_PTR)Thread->ApcState.Process,
716  Thread->ApcStateIndex,
717  KeIsExecutingDpc());
718  }
719 
720  /* Check if we are already in the target process */
721  if (Thread->ApcState.Process == Process)
722  {
723  /* Set magic value so we don't crash later when detaching */
724  ApcState->Process = (PKPROCESS)1;
725  return;
726  }
727 
728  /* Acquire APC Lock */
729  KiAcquireApcLock(Thread, &ApcLock);
730 
731  /* Acquire dispatcher lock */
733 
734  /* Check if the Current Thread is already attached */
735  if (Thread->ApcStateIndex != OriginalApcEnvironment)
736  {
737  /* We're already attached, so save the APC State into what we got */
738  KiAttachProcess(Thread, Process, &ApcLock, ApcState);
739  }
740  else
741  {
742  /* We're not attached, so save the APC State into SavedApcState */
743  KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
744  ApcState->Process = NULL;
745  }
746 }
747 
748 /*
749  * @implemented
750  */
751 VOID
752 NTAPI
754 {
755  KLOCK_QUEUE_HANDLE ApcLock;
759 
760  /* Check for magic value meaning we were already in the same process */
761  if (ApcState->Process == (PKPROCESS)1) return;
762 
763  /* Loop to make sure no APCs are pending */
764  for (;;)
765  {
766  /* Acquire APC Lock */
767  KiAcquireApcLock(Thread, &ApcLock);
768 
769  /* Check if a kernel APC is pending */
770  if (Thread->ApcState.KernelApcPending)
771  {
772  /* Check if kernel APC should be delivered */
773  if (!(Thread->KernelApcDisable) && (ApcLock.OldIrql <= APC_LEVEL))
774  {
775  /* Release the APC lock so that the APC can be delivered */
776  KiReleaseApcLock(&ApcLock);
777  continue;
778  }
779  }
780 
781  /* Otherwise, break out */
782  break;
783  }
784 
785  /*
786  * Check if the process isn't attacked, or has a Kernel APC in progress
787  * or has pending APC of any kind.
788  */
789  if ((Thread->ApcStateIndex == OriginalApcEnvironment) ||
790  (Thread->ApcState.KernelApcInProgress) ||
791  (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
792  (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
793  {
794  /* Bugcheck the system */
795  KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
796  }
797 
798  /* Get the process */
799  Process = Thread->ApcState.Process;
800 
801  /* Acquire dispatcher lock */
803 
804  /* Decrease the stack count */
805  ASSERT(Process->StackCount != 0);
806  ASSERT(Process->State == ProcessInMemory);
807  Process->StackCount--;
808 
809  /* Check if we can swap the process out */
810  if (!Process->StackCount)
811  {
812  /* FIXME: Swap the process out */
813  }
814 
815  /* Release dispatcher lock */
817 
818  /* Check if there's an APC state to restore */
819  if (ApcState->Process)
820  {
821  /* Restore the APC State */
822  KiMoveApcState(ApcState, &Thread->ApcState);
823  }
824  else
825  {
826  /* The ApcState parameter is useless, so use the saved data and reset it */
827  KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
828  Thread->SavedApcState.Process = NULL;
830  Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
831  Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
832  }
833 
834  /* Release lock */
836 
837  /* Swap Processes */
838  KiSwapProcess(Thread->ApcState.Process, Process);
839 
840  /* Exit the dispatcher */
841  KiExitDispatcher(ApcLock.OldIrql);
842 
843  /* Check if we have pending APCs */
844  if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
845  {
846  /* What do you know, we do! Request them to be delivered */
847  Thread->ApcState.KernelApcPending = TRUE;
849  }
850 }
851 
852 /*
853  * @implemented
854  */
855 ULONG
856 NTAPI
859 {
860  ULONG TotalUser, TotalKernel;
861  KLOCK_QUEUE_HANDLE ProcessLock;
862  PLIST_ENTRY NextEntry, ListHead;
864 
865  ASSERT_PROCESS(Process);
866 
867  /* Initialize user and kernel times */
868  TotalUser = Process->UserTime;
869  TotalKernel = Process->KernelTime;
870 
871  /* Lock the process */
872  KiAcquireProcessLock(Process, &ProcessLock);
873 
874  /* Loop all child threads and sum up their times */
875  ListHead = &Process->ThreadListHead;
876  NextEntry = ListHead->Flink;
877  while (ListHead != NextEntry)
878  {
879  /* Get the thread */
880  Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
881 
882  /* Sum up times */
883  TotalKernel += Thread->KernelTime;
884  TotalUser += Thread->UserTime;
885 
886  /* Go to the next one */
887  NextEntry = NextEntry->Flink;
888  }
889 
890  /* Release lock */
891  KiReleaseProcessLock(&ProcessLock);
892 
893  /* Return the user time */
894  *UserTime = TotalUser;
895 
896  /* Return the kernel time */
897  return TotalKernel;
898 }
899 
900 /*
901  * @implemented
902  */
903 BOOLEAN
904 NTAPI
907  IN ULONG Limit,
908  IN PUCHAR Number,
909  IN ULONG Index)
910 {
911  PAGED_CODE();
912 
913  /* Check if descriptor table entry is free */
914  if ((Index > SSDT_MAX_ENTRIES - 1) ||
915  (KeServiceDescriptorTable[Index].Base) ||
916  (KeServiceDescriptorTableShadow[Index].Base))
917  {
918  /* It's not, fail */
919  return FALSE;
920  }
921 
922  /* Initialize the shadow service descriptor table */
923  KeServiceDescriptorTableShadow[Index].Base = Base;
924  KeServiceDescriptorTableShadow[Index].Limit = Limit;
925  KeServiceDescriptorTableShadow[Index].Number = Number;
926  KeServiceDescriptorTableShadow[Index].Count = Count;
927  return TRUE;
928 }
929 
930 /*
931  * @implemented
932  */
933 BOOLEAN
934 NTAPI
936 {
937  PAGED_CODE();
938 
939  /* Make sure the Index is valid */
940  if (Index > (SSDT_MAX_ENTRIES - 1)) return FALSE;
941 
942  /* Is there a Normal Descriptor Table? */
943  if (!KeServiceDescriptorTable[Index].Base)
944  {
945  /* Not with the index, is there a shadow at least? */
946  if (!KeServiceDescriptorTableShadow[Index].Base) return FALSE;
947  }
948 
949  /* Now clear from the Shadow Table. */
950  KeServiceDescriptorTableShadow[Index].Base = NULL;
951  KeServiceDescriptorTableShadow[Index].Number = NULL;
952  KeServiceDescriptorTableShadow[Index].Limit = 0;
953  KeServiceDescriptorTableShadow[Index].Count = NULL;
954 
955  /* Check if we should clean from the Master one too */
956  if (Index == 1)
957  {
958  KeServiceDescriptorTable[Index].Base = NULL;
959  KeServiceDescriptorTable[Index].Number = NULL;
960  KeServiceDescriptorTable[Index].Limit = 0;
961  KeServiceDescriptorTable[Index].Count = NULL;
962  }
963 
964  /* Return success */
965  return TRUE;
966 }
967 /* EOF */
LARGE_INTEGER WriteOperationCount
Definition: pstypes.h:1278
DWORD *typedef PVOID
Definition: winlogon.h:61
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
FORCEINLINE VOID KiReleaseThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:244
#define LOW_PRIORITY
ULONG KeMaximumIncrement
Definition: clock.c:20
BOOLEAN NTAPI KeSetAutoAlignmentProcess(IN PKPROCESS Process, IN BOOLEAN Enable)
Definition: procobj.c:313
KAFFINITY FASTCALL KiSetAffinityThread(IN PKTHREAD Thread, IN KAFFINITY Affinity)
Definition: thrdschd.c:685
PVOID KeUserCallbackDispatcher
Definition: procobj.c:27
ULONGLONG OtherOperationCount
Definition: pstypes.h:85
#define ASSERT_IRQL_LESS_OR_EQUAL(x)
Definition: debug.h:251
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
LARGE_INTEGER ReadOperationCount
Definition: pstypes.h:1277
VOID NTAPI KiAttachProcess(IN PKTHREAD Thread, IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE ApcLock, IN PRKAPC_STATE SavedApcState)
Definition: procobj.c:35
UCHAR State
Definition: ketypes.h:2013
BOOLEAN Enable
Definition: acefiex.h:245
#define KPSF_DISABLE_BOOST_BIT
Definition: pstypes.h:252
FORCEINLINE VOID KiReleaseProcessLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:660
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
KAPC_STATE SavedApcState
Definition: ketypes.h:1850
BOOLEAN NTAPI KeAddSystemServiceTable(IN PULONG_PTR Base, IN PULONG Count OPTIONAL, IN ULONG Limit, IN PUCHAR Number, IN ULONG Index)
Definition: procobj.c:905
unsigned char * PUCHAR
Definition: retypes.h:3
KEVENT KiSwapEvent
Definition: procobj.c:21
ULONG NTAPI KeSetProcess(IN PKPROCESS Process, IN KPRIORITY Increment, IN BOOLEAN InWait)
Definition: procobj.c:194
_In_opt_ ULONG Base
Definition: rtlfuncs.h:2327
struct _EPROCESS * PEPROCESS
Definition: nt_native.h:30
_In_ KPRIORITY Priority
Definition: kefuncs.h:516
FORCEINLINE VOID KiAcquireApcLock(IN PKTHREAD Thread, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:600
ULONGLONG WriteOperationCount
Definition: pstypes.h:84
CHAR Saturation
Definition: ketypes.h:1856
#define MAXULONG_PTR
Definition: basetsd.h:103
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
#define LOW_REALTIME_PRIORITY
IO_COUNTERS IoInfo
Definition: ke.h:43
#define SSDT_MAX_ENTRIES
Definition: ketypes.h:100
ULONG ProcessReadyQueue
Definition: ketypes.h:1585
FORCEINLINE VOID KiReleaseApcLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:627
BOOLEAN NTAPI KeIsExecutingDpc(VOID)
Definition: dpc.c:946
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
LONG KPRIORITY
Definition: compat.h:454
#define PAGED_CODE()
Definition: video.h:57
uint32_t ULONG_PTR
Definition: typedefs.h:63
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
UCHAR KIRQL
Definition: env_spec_w32.h:591
GLenum GLclampf GLint i
Definition: glfuncs.h:14
UCHAR NTAPI KeFindNextRightSetAffinity(IN UCHAR Number, IN ULONG Set)
Definition: thrdobj.c:32
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
SHORT KernelApcDisable
Definition: ketypes.h:1770
#define FALSE
Definition: types.h:117
BOOLEAN NTAPI KeRemoveSystemServiceTable(IN ULONG Index)
Definition: procobj.c:935
VOID NTAPI KeStackAttachProcess(IN PKPROCESS Process, OUT PRKAPC_STATE ApcState)
Definition: procobj.c:701
LIST_ENTRY KiStackInSwapListHead
Definition: procobj.c:20
KAFFINITY NTAPI KeSetAffinityProcess(IN PKPROCESS Process, IN KAFFINITY Affinity)
Definition: procobj.c:265
KAPC_STATE ApcState
Definition: ketypes.h:1668
UCHAR KeProcessNodeSeed
Definition: krnlinit.c:41
VOID FASTCALL KiSetPriorityThread(IN PKTHREAD Thread, IN KPRIORITY Priority)
Definition: thrdschd.c:511
BOOLEAN NTAPI KeIsAttachedProcess(VOID)
Definition: procobj.c:690
ULONG NTAPI KeQueryRuntimeProcess(IN PKPROCESS Process, OUT PULONG UserTime)
Definition: procobj.c:857
#define InterlockedBitTestAndReset
Definition: interlocked.h:35
ULONG StackCount
Definition: ketypes.h:2023
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES]
Definition: procobj.c:24
smooth NULL
Definition: ftsmooth.c:416
LARGE_INTEGER OtherTransferCount
Definition: pstypes.h:1282
VOID NTAPI KeInitializeProcess(IN OUT PKPROCESS Process, IN KPRIORITY Priority, IN KAFFINITY Affinity, IN PULONG_PTR DirectoryTableBase, IN BOOLEAN Enable)
Definition: procobj.c:115
FORCEINLINE VOID KiReleaseApcLockFromDpcLevel(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:635
LIST_ENTRY KiProcessInSwapListHead
Definition: procobj.c:19
VOID NTAPI KeBugCheck(ULONG BugCheckCode)
Definition: bug.c:1469
ULONGLONG WriteTransferCount
Definition: pstypes.h:87
#define HIGH_PRIORITY
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
VOID FASTCALL KiExitDispatcher(KIRQL OldIrql)
CHAR BasePriority
Definition: ketypes.h:1807
VOID NTAPI KiReadyThread(IN PKTHREAD Thread)
Definition: thrdschd.c:429
_Out_ PULONG UserTime
Definition: kefuncs.h:784
#define InterlockedBitTestAndSet
Definition: interlocked.h:30
VOID NTAPI KeQueryValuesProcess(IN PKPROCESS Process, PPROCESS_VALUES Values)
Definition: procobj.c:522
FORCEINLINE VOID KiAcquireThreadLock(IN PKTHREAD Thread)
Definition: ke_x.h:234
int64_t LONGLONG
Definition: typedefs.h:66
#define IO_ACCESS_MAP_NONE
Definition: ketypes.h:263
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
unsigned char BOOLEAN
struct _KPROCESS KPROCESS
ULONG KernelTime
Definition: ketypes.h:1877
PVOID KeUserExceptionDispatcher
Definition: procobj.c:28
#define KPSF_AUTO_ALIGNMENT_BIT
Definition: pstypes.h:251
KPRIORITY NTAPI KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, IN KPRIORITY Priority, IN UCHAR Quantum OPTIONAL)
Definition: procobj.c:349
VOID NTAPI KeSetQuantumProcess(IN PKPROCESS Process, IN UCHAR Quantum)
Definition: procobj.c:229
PKNODE KeNodeBlock[1]
Definition: krnlinit.c:39
static const UCHAR Index[8]
Definition: usbohci.c:18
signed char SCHAR
Definition: sqltypes.h:14
_In_ ULONG _In_ ULONG _In_ ULONG _Out_ PKIRQL _Out_ PKAFFINITY Affinity
Definition: halfuncs.h:170
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
LARGE_INTEGER WriteTransferCount
Definition: pstypes.h:1281
FORCEINLINE VOID KiReleaseProcessLock(IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:652
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:618
unsigned char UCHAR
Definition: xmlstorage.h:181
ULONGLONG ReadTransferCount
Definition: pstypes.h:86
_Requires_lock_held_ Interrupt _Releases_lock_ Interrupt _In_ _IRQL_restores_ KIRQL OldIrql
Definition: kefuncs.h:803
FORCEINLINE VOID KiAcquireProcessLock(IN PKPROCESS Process, IN PKLOCK_QUEUE_HANDLE Handle)
Definition: ke_x.h:643
Definition: typedefs.h:117
_In_opt_ PENTER_STATE_SYSTEM_HANDLER _In_opt_ PVOID _In_ LONG _In_opt_ LONG volatile * Number
Definition: ntpoapi.h:204
KAFFINITY KeActiveProcessors
Definition: krnlinit.c:23
UCHAR KeNumberNodes
Definition: krnlinit.c:40
VOID NTAPI KiSwapProcess(struct _KPROCESS *NewProcess, struct _KPROCESS *OldProcess)
Definition: stubs.c:139
UCHAR QuantumReset
Definition: ketypes.h:1872
#define DISPATCH_LEVEL
Definition: env_spec_w32.h:696
VOID FASTCALL HalRequestSoftwareInterrupt(IN KIRQL Irql)
Definition: pic.c:271
FORCEINLINE VOID KiReleaseDispatcherLock(IN KIRQL OldIrql)
Definition: ke_x.h:152
FORCEINLINE KIRQL KiAcquireDispatcherLock(VOID)
Definition: ke_x.h:144
struct _KPROCESS * PKPROCESS
Definition: wdm.template.h:199
CHAR PriorityDecrement
Definition: ketypes.h:1810
ULONG_PTR KAFFINITY
Definition: compat.h:75
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:579
#define KiComputeIopmOffset(MapNumber)
Definition: ketypes.h:265
VOID NTAPI KiMoveApcState(PKAPC_STATE OldState, PKAPC_STATE NewState)
Definition: apc.c:538
VOID NTAPI KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
Definition: procobj.c:753
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
*RESTRICTED_POINTER PRKAPC_STATE
Definition: ketypes.h:1273
static ULONG Delta
Definition: xboxvideo.c:28
_Out_ PKAPC_STATE ApcState
Definition: mm.h:1471
unsigned int * PULONG
Definition: retypes.h:1
LARGE_INTEGER TotalKernelTime
Definition: ke.h:41
LIST_ENTRY KiProcessOutSwapListHead
Definition: procobj.c:19
#define DPRINT1
Definition: precomp.h:8
ULONG UserTime
Definition: ketypes.h:1893
LARGE_INTEGER OtherOperationCount
Definition: pstypes.h:1279
FORCEINLINE VOID KiReleaseDispatcherLockFromDpcLevel(VOID)
Definition: ke_x.h:168
BOOLEAN NTAPI KeSetDisableBoostProcess(IN PKPROCESS Process, IN BOOLEAN Disable)
Definition: procobj.c:331
LARGE_INTEGER ReadTransferCount
Definition: pstypes.h:1280
PVOID KeRaiseUserExceptionDispatcher
Definition: procobj.c:29
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
#define OUT
Definition: typedefs.h:39
KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[SSDT_MAX_ENTRIES]
Definition: procobj.c:23
LIST_ENTRY KiProcessListHead
Definition: procobj.c:18
unsigned int ULONG
Definition: retypes.h:1
uint32_t * PULONG_PTR
Definition: typedefs.h:63
LARGE_INTEGER TotalUserTime
Definition: ke.h:42
UCHAR ApcStateIndex
Definition: ketypes.h:1832
KAFFINITY ProcessorMask
Definition: ketypes.h:776
PVOID KeUserApcDispatcher
Definition: procobj.c:26
UCHAR Seed
Definition: ketypes.h:778
ULONGLONG OtherTransferCount
Definition: pstypes.h:88
FORCEINLINE VOID KxUnwaitThread(IN DISPATCHER_HEADER *Object, IN KPRIORITY Increment)
Definition: ke_x.h:1250
#define KeGetCurrentThread
Definition: hal.h:44
IN OUT PLONG IN OUT PLONG Addend IN OUT PLONG IN LONG Increment
Definition: CrNtStubs.h:42
#define CHAR(Char)
#define ASSERT_PROCESS(object)
Definition: ketypes.h:2030
#define APC_LEVEL
Definition: env_spec_w32.h:695
_In_ LONG _In_ LONG Limit
Definition: kefuncs.h:328
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
union gl_dlist_node Node
Definition: dlist.c:302
VOID NTAPI KeBugCheckEx(_In_ ULONG BugCheckCode, _In_ ULONG_PTR BugCheckParameter1, _In_ ULONG_PTR BugCheckParameter2, _In_ ULONG_PTR BugCheckParameter3, _In_ ULONG_PTR BugCheckParameter4)
Definition: rtlcompat.c:107
FORCEINLINE VOID KiAcquireDispatcherLockAtDpcLevel(VOID)
Definition: ke_x.h:160
LONGLONG QuadPart
Definition: typedefs.h:112
ULONGLONG ReadOperationCount
Definition: pstypes.h:83