ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

procobj.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Kernel
00003  * LICENSE:         GPL - See COPYING in the top level directory
00004  * FILE:            ntoskrnl/ke/process.c
00005  * PURPOSE:         Kernel Process Management and System Call Tables
00006  * PROGRAMMERS:     Alex Ionescu
00007  *                  Gregor Anich
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* GLOBALS *******************************************************************/
00017 
00018 LIST_ENTRY KiProcessListHead;
00019 LIST_ENTRY KiProcessInSwapListHead, KiProcessOutSwapListHead;
00020 LIST_ENTRY KiStackInSwapListHead;
00021 KEVENT KiSwapEvent;
00022 
00023 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTable[SSDT_MAX_ENTRIES];
00024 KSERVICE_TABLE_DESCRIPTOR KeServiceDescriptorTableShadow[SSDT_MAX_ENTRIES];
00025 
00026 PVOID KeUserApcDispatcher;
00027 PVOID KeUserCallbackDispatcher;
00028 PVOID KeUserExceptionDispatcher;
00029 PVOID KeRaiseUserExceptionDispatcher;
00030 
00031 /* PRIVATE FUNCTIONS *********************************************************/
00032 
00033 VOID
00034 NTAPI
00035 KiAttachProcess(IN PKTHREAD Thread,
00036                 IN PKPROCESS Process,
00037                 IN PKLOCK_QUEUE_HANDLE ApcLock,
00038                 IN PRKAPC_STATE SavedApcState)
00039 {
00040 #if 0
00041     PLIST_ENTRY ListHead, NextEntry;
00042     PKTHREAD CurrentThread;
00043 #endif
00044     ASSERT(Process != Thread->ApcState.Process);
00045 
00046     /* Increase Stack Count */
00047     ASSERT(Process->StackCount != MAXULONG_PTR);
00048     Process->StackCount++;
00049 
00050     /* Swap the APC Environment */
00051     KiMoveApcState(&Thread->ApcState, SavedApcState);
00052 
00053     /* Reinitialize Apc State */
00054     InitializeListHead(&Thread->ApcState.ApcListHead[KernelMode]);
00055     InitializeListHead(&Thread->ApcState.ApcListHead[UserMode]);
00056     Thread->ApcState.Process = Process;
00057     Thread->ApcState.KernelApcInProgress = FALSE;
00058     Thread->ApcState.KernelApcPending = FALSE;
00059     Thread->ApcState.UserApcPending = FALSE;
00060 
00061     /* Update Environment Pointers if needed*/
00062     if (SavedApcState == &Thread->SavedApcState)
00063     {
00064         Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->
00065                                                           SavedApcState;
00066         Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->ApcState;
00067         Thread->ApcStateIndex = AttachedApcEnvironment;
00068     }
00069 
00070     /* Check if the process is paged in */
00071     if (Process->State == ProcessInMemory)
00072     {
00073         /* Scan the ready list */
00074 #if 0
00075         ListHead = &Process->ReadyListHead;
00076         NextEntry = ListHead->Flink;
00077         while (NextEntry != ListHead)
00078         {
00079             /* Get the thread */
00080             CurrentThread = CONTAINING_RECORD(NextEntry, KTHREAD, WaitListEntry);
00081 
00082             /* Remove it */
00083             RemoveEntryList(NextEntry);
00084             CurrentThread->ProcessReadyQueue = FALSE;
00085 
00086             /* Mark it ready */
00087             KiReadyThread(CurrentThread);
00088 
00089             /* Go to the next one */
00090             NextEntry = ListHead->Flink;
00091         }
00092 #endif
00093 
00094         /* Release dispatcher lock */
00095         KiReleaseDispatcherLockFromDpcLevel();
00096 
00097         /* Release lock */
00098         KiReleaseApcLockFromDpcLevel(ApcLock);
00099 
00100         /* Swap Processes */
00101         KiSwapProcess(Process, SavedApcState->Process);
00102 
00103         /* Exit the dispatcher */
00104         KiExitDispatcher(ApcLock->OldIrql);
00105     }
00106     else
00107     {
00108         DPRINT1("Errr. ReactOS doesn't support paging out processes yet...\n");
00109         ASSERT(FALSE);
00110     }
00111 }
00112 
00113 VOID
00114 NTAPI
00115 KeInitializeProcess(IN OUT PKPROCESS Process,
00116                     IN KPRIORITY Priority,
00117                     IN KAFFINITY Affinity,
00118                     IN PULONG_PTR DirectoryTableBase,
00119                     IN BOOLEAN Enable)
00120 {
00121 #ifdef CONFIG_SMP
00122     ULONG i = 0;
00123     UCHAR IdealNode = 0;
00124     PKNODE Node;
00125 #endif
00126 
00127     /* Initialize the Dispatcher Header */
00128     Process->Header.Type = ProcessObject;
00129     Process->Header.Size = sizeof(KPROCESS) / sizeof(ULONG);
00130     Process->Header.SignalState = 0;
00131     InitializeListHead(&(Process->Header.WaitListHead));
00132 
00133     /* Initialize Scheduler Data, Alignment Faults and Set the PDE */
00134     Process->Affinity = Affinity;
00135     Process->BasePriority = (CHAR)Priority;
00136     Process->QuantumReset = 6;
00137     Process->DirectoryTableBase[0] = DirectoryTableBase[0];
00138     Process->DirectoryTableBase[1] = DirectoryTableBase[1];
00139     Process->AutoAlignment = Enable;
00140 #if defined(_M_IX86)
00141     Process->IopmOffset = KiComputeIopmOffset(IO_ACCESS_MAP_NONE);
00142 #endif
00143 
00144     /* Initialize the lists */
00145     InitializeListHead(&Process->ThreadListHead);
00146     InitializeListHead(&Process->ProfileListHead);
00147     InitializeListHead(&Process->ReadyListHead);
00148 
00149     /* Initialize the current State */
00150     Process->State = ProcessInMemory;
00151 
00152     /* Check how many Nodes there are on the system */
00153 #ifdef CONFIG_SMP
00154     if (KeNumberNodes > 1)
00155     {
00156         /* Set the new seed */
00157         KeProcessNodeSeed = (KeProcessNodeSeed + 1) / KeNumberNodes;
00158         IdealNode = KeProcessNodeSeed;
00159 
00160         /* Loop every node */
00161         do
00162         {
00163             /* Check if the affinity matches */
00164             if (KeNodeBlock[IdealNode]->ProcessorMask != Affinity) break;
00165 
00166             /* No match, try next Ideal Node and increase node loop index */
00167             IdealNode++;
00168             i++;
00169 
00170             /* Check if the Ideal Node is beyond the total number of nodes */
00171             if (IdealNode >= KeNumberNodes)
00172             {
00173                 /* Normalize the Ideal Node */
00174                 IdealNode -= KeNumberNodes;
00175             }
00176         } while (i < KeNumberNodes);
00177     }
00178 
00179     /* Set the ideal node and get the ideal node block */
00180     Process->IdealNode = IdealNode;
00181     Node = KeNodeBlock[IdealNode];
00182     ASSERT(Node->ProcessorMask & Affinity);
00183 
00184     /* Find the matching affinity set to calculate the thread seed */
00185     Affinity &= Node->ProcessorMask;
00186     Process->ThreadSeed = KeFindNextRightSetAffinity(Node->Seed,
00187                                                      (ULONG)Affinity);
00188     Node->Seed = Process->ThreadSeed;
00189 #endif
00190 }
00191 
00192 ULONG
00193 NTAPI
00194 KeSetProcess(IN PKPROCESS Process,
00195              IN KPRIORITY Increment,
00196              IN BOOLEAN InWait)
00197 {
00198     KIRQL OldIrql;
00199     ULONG OldState;
00200     ASSERT_PROCESS(Process);
00201     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00202 
00203     /* Lock Dispatcher */
00204     OldIrql = KiAcquireDispatcherLock();
00205 
00206     /* Get Old State */
00207     OldState = Process->Header.SignalState;
00208 
00209     /* Signal the Process */
00210     Process->Header.SignalState = TRUE;
00211 
00212     /* Check if was unsignaled and has waiters */
00213     if (!(OldState) &&
00214         !(IsListEmpty(&Process->Header.WaitListHead)))
00215     {
00216         /* Unwait the threads */
00217         KxUnwaitThread(&Process->Header, Increment);
00218     }
00219 
00220     /* Release Dispatcher Database */
00221     KiReleaseDispatcherLock(OldIrql);
00222 
00223     /* Return the previous State */
00224     return OldState;
00225 }
00226 
00227 VOID
00228 NTAPI
00229 KeSetQuantumProcess(IN PKPROCESS Process,
00230                     IN UCHAR Quantum)
00231 {
00232     KLOCK_QUEUE_HANDLE ProcessLock;
00233     PLIST_ENTRY NextEntry, ListHead;
00234     PKTHREAD Thread;
00235     ASSERT_PROCESS(Process);
00236     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00237 
00238     /* Lock the process */
00239     KiAcquireProcessLock(Process, &ProcessLock);
00240 
00241     /* Set new quantum */
00242     Process->QuantumReset = Quantum;
00243 
00244     /* Loop all child threads */
00245     ListHead = &Process->ThreadListHead;
00246     NextEntry = ListHead->Flink;
00247     while (ListHead != NextEntry)
00248     {
00249         /* Get the thread */
00250         Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
00251 
00252         /* Set quantum */
00253         Thread->QuantumReset = Quantum;
00254 
00255         /* Go to the next one */
00256         NextEntry = NextEntry->Flink;
00257     }
00258 
00259     /* Release lock */
00260     KiReleaseProcessLock(&ProcessLock);
00261 }
00262 
00263 KAFFINITY
00264 NTAPI
00265 KeSetAffinityProcess(IN PKPROCESS Process,
00266                      IN KAFFINITY Affinity)
00267 {
00268    
00269     KLOCK_QUEUE_HANDLE ProcessLock;
00270     PLIST_ENTRY NextEntry, ListHead;
00271     KAFFINITY OldAffinity;
00272     PKTHREAD Thread;
00273     ASSERT_PROCESS(Process);
00274     ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
00275     ASSERT((Affinity & KeActiveProcessors) != 0);
00276     
00277     /* Lock the process */
00278     KiAcquireProcessLock(Process, &ProcessLock);
00279     
00280     /* Acquire the dispatcher lock */
00281     KiAcquireDispatcherLockAtDpcLevel();
00282 
00283     /* Capture old affinity and update it */
00284     OldAffinity = Process->Affinity;
00285     Process->Affinity = Affinity;
00286 
00287     /* Loop all child threads */
00288     ListHead = &Process->ThreadListHead;
00289     NextEntry = ListHead->Flink;
00290     while (ListHead != NextEntry)
00291     {
00292         /* Get the thread */
00293         Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
00294         
00295         /* Set affinity on it */
00296         KiSetAffinityThread(Thread, Affinity);
00297         NextEntry = NextEntry->Flink;
00298     }
00299     
00300     /* Release Dispatcher Database */
00301     KiReleaseDispatcherLockFromDpcLevel();
00302     
00303     /* Release the process lock */
00304     KiReleaseProcessLockFromDpcLevel(&ProcessLock);
00305     KiExitDispatcher(ProcessLock.OldIrql);
00306     
00307     /* Return previous affinity */
00308     return OldAffinity;
00309 }
00310 
00311 BOOLEAN
00312 NTAPI
00313 KeSetAutoAlignmentProcess(IN PKPROCESS Process,
00314                           IN BOOLEAN Enable)
00315 {
00316     /* Set or reset the bit depending on what the enable flag says */
00317     if (Enable)
00318     {
00319         return InterlockedBitTestAndSet(&Process->ProcessFlags,
00320                                         KPSF_AUTO_ALIGNMENT_BIT);
00321     }
00322     else
00323     {
00324         return InterlockedBitTestAndReset(&Process->ProcessFlags,
00325                                           KPSF_AUTO_ALIGNMENT_BIT);
00326     }
00327 }
00328 
00329 BOOLEAN
00330 NTAPI
00331 KeSetDisableBoostProcess(IN PKPROCESS Process,
00332                          IN BOOLEAN Disable)
00333 {
00334     /* Set or reset the bit depending on what the disable flag says */
00335     if (Disable)
00336     {
00337         return InterlockedBitTestAndSet(&Process->ProcessFlags,
00338                                         KPSF_DISABLE_BOOST_BIT);
00339     }
00340     else
00341     {
00342         return InterlockedBitTestAndReset(&Process->ProcessFlags,
00343                                           KPSF_DISABLE_BOOST_BIT);
00344     }
00345 }
00346 
00347 KPRIORITY
00348 NTAPI
00349 KeSetPriorityAndQuantumProcess(IN PKPROCESS Process,
00350                                IN KPRIORITY Priority,
00351                                IN UCHAR Quantum OPTIONAL)
00352 {
00353     KLOCK_QUEUE_HANDLE ProcessLock;
00354     KPRIORITY Delta;
00355     PLIST_ENTRY NextEntry, ListHead;
00356     KPRIORITY NewPriority, OldPriority;
00357     PKTHREAD Thread;
00358     ASSERT_PROCESS(Process);
00359     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00360 
00361     /* Check if the process already has this priority */
00362     if (Process->BasePriority == Priority) return Process->BasePriority;
00363 
00364     /* If the caller gave priority 0, normalize to 1 */
00365     if (!Priority) Priority = LOW_PRIORITY + 1;
00366 
00367     /* Lock the process */
00368     KiAcquireProcessLock(Process, &ProcessLock);
00369 
00370     /* Check if we are modifying the quantum too */
00371     if (Quantum) Process->QuantumReset = Quantum;
00372 
00373     /* Save the current base priority and update it */
00374     OldPriority = Process->BasePriority;
00375     Process->BasePriority = (SCHAR)Priority;
00376 
00377     /* Calculate the priority delta */
00378     Delta = Priority - OldPriority;
00379 
00380     /* Set the list head and list entry */
00381     ListHead = &Process->ThreadListHead;
00382     NextEntry = ListHead->Flink;
00383 
00384     /* Check if this is a real-time priority */
00385     if (Priority >= LOW_REALTIME_PRIORITY)
00386     {
00387         /* Loop the thread list */
00388         while (NextEntry != ListHead)
00389         {
00390             /* Get the thread */
00391             Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
00392 
00393             /* Update the quantum if we had one */
00394             if (Quantum) Thread->QuantumReset = Quantum;
00395 
00396             /* Acquire the thread lock */
00397             KiAcquireThreadLock(Thread);
00398 
00399             /* Calculate the new priority */
00400             NewPriority = Thread->BasePriority + Delta;
00401             if (NewPriority < LOW_REALTIME_PRIORITY)
00402             {
00403                 /* We're in real-time range, don't let it go below */
00404                 NewPriority = LOW_REALTIME_PRIORITY;
00405             }
00406             else if (NewPriority > HIGH_PRIORITY)
00407             {
00408                 /* We're going beyond the maximum priority, normalize */
00409                 NewPriority = HIGH_PRIORITY;
00410             }
00411 
00412             /*
00413              * If priority saturation occured or the old priority was still in
00414              * the real-time range, don't do anything.
00415              */
00416             if (!(Thread->Saturation) || (OldPriority < LOW_REALTIME_PRIORITY))
00417             {
00418                 /* Check if we had priority saturation */
00419                 if (Thread->Saturation > 0)
00420                 {
00421                     /* Boost priority to maximum */
00422                     NewPriority = HIGH_PRIORITY;
00423                 }
00424                 else if (Thread->Saturation < 0)
00425                 {
00426                     /* If we had negative saturation, set minimum priority */
00427                     NewPriority = LOW_REALTIME_PRIORITY;
00428                 }
00429 
00430                 /* Update priority and quantum */
00431                 Thread->BasePriority = (SCHAR)NewPriority;
00432                 Thread->Quantum = Thread->QuantumReset;
00433 
00434                 /* Disable decrements and update priority */
00435                 Thread->PriorityDecrement = 0;
00436                 KiSetPriorityThread(Thread, NewPriority);
00437             }
00438 
00439             /* Release the thread lock */
00440             KiReleaseThreadLock(Thread);
00441 
00442             /* Go to the next thread */
00443             NextEntry = NextEntry->Flink;
00444         }
00445     }
00446     else
00447     {
00448         /* Loop the thread list */
00449         while (NextEntry != ListHead)
00450         {
00451             /* Get the thread */
00452             Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
00453 
00454             /* Update the quantum if we had one */
00455             if (Quantum) Thread->QuantumReset = Quantum;
00456 
00457             /* Lock the thread */
00458             KiAcquireThreadLock(Thread);
00459 
00460             /* Calculate the new priority */
00461             NewPriority = Thread->BasePriority + Delta;
00462             if (NewPriority >= LOW_REALTIME_PRIORITY)
00463             {
00464                 /* We're not real-time range, don't let it enter RT range */
00465                 NewPriority = LOW_REALTIME_PRIORITY - 1;
00466             }
00467             else if (NewPriority <= LOW_PRIORITY)
00468             {
00469                 /* We're going below the minimum priority, normalize */
00470                 NewPriority = 1;
00471             }
00472 
00473             /*
00474              * If priority saturation occured or the old priority was still in
00475              * the real-time range, don't do anything.
00476              */
00477             if (!(Thread->Saturation) ||
00478                 (OldPriority >= LOW_REALTIME_PRIORITY))
00479             {
00480                 /* Check if we had priority saturation */
00481                 if (Thread->Saturation > 0)
00482                 {
00483                     /* Boost priority to maximum */
00484                     NewPriority = LOW_REALTIME_PRIORITY - 1;
00485                 }
00486                 else if (Thread->Saturation < 0)
00487                 {
00488                     /* If we had negative saturation, set minimum priority */
00489                     NewPriority = 1;
00490                 }
00491 
00492                 /* Update priority and quantum */
00493                 Thread->BasePriority = (SCHAR)NewPriority;
00494                 Thread->Quantum = Thread->QuantumReset;
00495 
00496                 /* Disable decrements and update priority */
00497                 Thread->PriorityDecrement = 0;
00498                 KiSetPriorityThread(Thread, NewPriority);
00499             }
00500 
00501             /* Release the thread lock */
00502             KiReleaseThreadLock(Thread);
00503 
00504             /* Go to the next thread */
00505             NextEntry = NextEntry->Flink;
00506         }
00507     }
00508 
00509     /* Release Dispatcher Database */
00510     KiReleaseDispatcherLockFromDpcLevel();
00511 
00512     /* Release the process lock */
00513     KiReleaseProcessLockFromDpcLevel(&ProcessLock);
00514     KiExitDispatcher(ProcessLock.OldIrql);
00515 
00516     /* Return previous priority */
00517     return OldPriority;
00518 }
00519 
00520 /* PUBLIC FUNCTIONS **********************************************************/
00521 
00522 /*
00523  * @implemented
00524  */
00525 VOID
00526 NTAPI
00527 KeAttachProcess(IN PKPROCESS Process)
00528 {
00529     KLOCK_QUEUE_HANDLE ApcLock;
00530     PKTHREAD Thread = KeGetCurrentThread();
00531     ASSERT_PROCESS(Process);
00532     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00533 
00534     /* Check if we're already in that process */
00535     if (Thread->ApcState.Process == Process) return;
00536 
00537     /* Check if a DPC is executing or if we're already attached */
00538     if ((Thread->ApcStateIndex != OriginalApcEnvironment) ||
00539         (KeIsExecutingDpc()))
00540     {
00541         /* Invalid attempt */
00542         KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
00543                      (ULONG_PTR)Process,
00544                      (ULONG_PTR)Thread->ApcState.Process,
00545                      Thread->ApcStateIndex,
00546                      KeIsExecutingDpc());
00547     }
00548     else
00549     {
00550         /* Acquire APC Lock */
00551         KiAcquireApcLock(Thread, &ApcLock);
00552 
00553         /* Acquire the dispatcher lock */
00554         KiAcquireDispatcherLockAtDpcLevel();
00555 
00556         /* Legit attach attempt: do it! */
00557         KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
00558     }
00559 }
00560 
00561 /*
00562  * @implemented
00563  */
00564 VOID
00565 NTAPI
00566 KeDetachProcess(VOID)
00567 {
00568     PKTHREAD Thread = KeGetCurrentThread();
00569     KLOCK_QUEUE_HANDLE ApcLock;
00570     PKPROCESS Process;
00571     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00572 
00573     /* Check if it's attached */
00574     if (Thread->ApcStateIndex == OriginalApcEnvironment) return;
00575 
00576     /* Acquire APC Lock */
00577     KiAcquireApcLock(Thread, &ApcLock);
00578 
00579     /* Check for invalid attach attempts */
00580     if ((Thread->ApcState.KernelApcInProgress) ||
00581         !(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
00582         !(IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
00583     {
00584         /* Crash the system */
00585         KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
00586     }
00587 
00588     /* Get the process */
00589     Process = Thread->ApcState.Process;
00590 
00591     /* Acquire dispatcher lock */
00592     KiAcquireDispatcherLockAtDpcLevel();
00593 
00594     /* Decrease the stack count */
00595     ASSERT(Process->StackCount != 0);
00596     ASSERT(Process->State == ProcessInMemory);
00597     Process->StackCount--;
00598 
00599     /* Check if we can swap the process out */
00600     if (!Process->StackCount)
00601     {
00602         /* FIXME: Swap the process out */
00603     }
00604 
00605     /* Release dispatcher lock */
00606     KiReleaseDispatcherLockFromDpcLevel();
00607 
00608     /* Restore the APC State */
00609     KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
00610     Thread->SavedApcState.Process = NULL;
00611     Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
00612     Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
00613     Thread->ApcStateIndex = OriginalApcEnvironment;
00614 
00615     /* Release lock */
00616     KiReleaseApcLockFromDpcLevel(&ApcLock);
00617 
00618     /* Swap Processes */
00619     KiSwapProcess(Thread->ApcState.Process, Process);
00620 
00621     /* Exit the dispatcher */
00622     KiExitDispatcher(ApcLock.OldIrql);
00623 
00624     /* Check if we have pending APCs */
00625     if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
00626     {
00627         /* What do you know, we do! Request them to be delivered */
00628         Thread->ApcState.KernelApcPending = TRUE;
00629         HalRequestSoftwareInterrupt(APC_LEVEL);
00630     }
00631 }
00632 
00633 /*
00634  * @implemented
00635  */
00636 BOOLEAN
00637 NTAPI
00638 KeIsAttachedProcess(VOID)
00639 {
00640     /* Return the APC State */
00641     return KeGetCurrentThread()->ApcStateIndex;
00642 }
00643 
00644 /*
00645  * @implemented
00646  */
00647 VOID
00648 NTAPI
00649 KeStackAttachProcess(IN PKPROCESS Process,
00650                      OUT PRKAPC_STATE ApcState)
00651 {
00652     KLOCK_QUEUE_HANDLE ApcLock;
00653     PKTHREAD Thread = KeGetCurrentThread();
00654     ASSERT_PROCESS(Process);
00655     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00656 
00657     /* Crash system if DPC is being executed! */
00658     if (KeIsExecutingDpc())
00659     {
00660         /* Executing a DPC, crash! */
00661         KeBugCheckEx(INVALID_PROCESS_ATTACH_ATTEMPT,
00662                      (ULONG_PTR)Process,
00663                      (ULONG_PTR)Thread->ApcState.Process,
00664                      Thread->ApcStateIndex,
00665                      KeIsExecutingDpc());
00666     }
00667 
00668     /* Check if we are already in the target process */
00669     if (Thread->ApcState.Process == Process)
00670     {
00671         /* Set magic value so we don't crash later when detaching */
00672         ApcState->Process = (PKPROCESS)1;
00673         return;
00674     }
00675 
00676     /* Acquire APC Lock */
00677     KiAcquireApcLock(Thread, &ApcLock);
00678 
00679     /* Acquire dispatcher lock */
00680     KiAcquireDispatcherLockAtDpcLevel();
00681 
00682     /* Check if the Current Thread is already attached */
00683     if (Thread->ApcStateIndex != OriginalApcEnvironment)
00684     {
00685         /* We're already attached, so save the APC State into what we got */
00686         KiAttachProcess(Thread, Process, &ApcLock, ApcState);
00687     }
00688     else
00689     {
00690         /* We're not attached, so save the APC State into SavedApcState */
00691         KiAttachProcess(Thread, Process, &ApcLock, &Thread->SavedApcState);
00692         ApcState->Process = NULL;
00693     }
00694 }
00695 
00696 /*
00697  * @implemented
00698  */
00699 VOID
00700 NTAPI
00701 KeUnstackDetachProcess(IN PRKAPC_STATE ApcState)
00702 {
00703     KLOCK_QUEUE_HANDLE ApcLock;
00704     PKTHREAD Thread = KeGetCurrentThread();
00705     PKPROCESS Process;
00706     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
00707 
00708     /* Check for magic value meaning we were already in the same process */
00709     if (ApcState->Process == (PKPROCESS)1) return;
00710 
00711     /* Loop to make sure no APCs are pending  */
00712     for (;;)
00713     {
00714         /* Acquire APC Lock */
00715         KiAcquireApcLock(Thread, &ApcLock);
00716 
00717         /* Check if a kernel APC is pending */
00718         if (Thread->ApcState.KernelApcPending)
00719         {
00720             /* Check if kernel APC should be delivered */
00721             if (!(Thread->KernelApcDisable) && (ApcLock.OldIrql <= APC_LEVEL))
00722             {
00723                 /* Release the APC lock so that the APC can be delivered */
00724                 KiReleaseApcLock(&ApcLock);
00725                 continue;
00726             }
00727         }
00728 
00729         /* Otherwise, break out */
00730         break;
00731     }
00732 
00733     /*
00734      * Check if the process isn't attacked, or has a Kernel APC in progress
00735      * or has pending APC of any kind.
00736      */
00737     if ((Thread->ApcStateIndex == OriginalApcEnvironment) ||
00738         (Thread->ApcState.KernelApcInProgress) ||
00739         (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) ||
00740         (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
00741     {
00742         /* Bugcheck the system */
00743         KeBugCheck(INVALID_PROCESS_DETACH_ATTEMPT);
00744     }
00745 
00746     /* Get the process */
00747     Process = Thread->ApcState.Process;
00748 
00749     /* Acquire dispatcher lock */
00750     KiAcquireDispatcherLockAtDpcLevel();
00751 
00752     /* Decrease the stack count */
00753     ASSERT(Process->StackCount != 0);
00754     ASSERT(Process->State == ProcessInMemory);
00755     Process->StackCount--;
00756 
00757     /* Check if we can swap the process out */
00758     if (!Process->StackCount)
00759     {
00760         /* FIXME: Swap the process out */
00761     }
00762 
00763     /* Release dispatcher lock */
00764     KiReleaseDispatcherLockFromDpcLevel();
00765 
00766     /* Check if there's an APC state to restore */
00767     if (ApcState->Process)
00768     {
00769         /* Restore the APC State */
00770         KiMoveApcState(ApcState, &Thread->ApcState);
00771     }
00772     else
00773     {
00774         /* The ApcState parameter is useless, so use the saved data and reset it */
00775         KiMoveApcState(&Thread->SavedApcState, &Thread->ApcState);
00776         Thread->SavedApcState.Process = NULL;
00777         Thread->ApcStateIndex = OriginalApcEnvironment;
00778         Thread->ApcStatePointer[OriginalApcEnvironment] = &Thread->ApcState;
00779         Thread->ApcStatePointer[AttachedApcEnvironment] = &Thread->SavedApcState;
00780     }
00781 
00782     /* Release lock */
00783     KiReleaseApcLockFromDpcLevel(&ApcLock);
00784 
00785     /* Swap Processes */
00786     KiSwapProcess(Thread->ApcState.Process, Process);
00787 
00788     /* Exit the dispatcher */
00789     KiExitDispatcher(ApcLock.OldIrql);
00790 
00791     /* Check if we have pending APCs */
00792     if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])))
00793     {
00794         /* What do you know, we do! Request them to be delivered */
00795         Thread->ApcState.KernelApcPending = TRUE;
00796         HalRequestSoftwareInterrupt(APC_LEVEL);
00797     }
00798 }
00799 
00800 /*
00801  * @implemented
00802  */
00803 ULONG
00804 NTAPI
00805 KeQueryRuntimeProcess(IN PKPROCESS Process,
00806                       OUT PULONG UserTime)
00807 {
00808     ULONG TotalUser, TotalKernel;
00809     KLOCK_QUEUE_HANDLE ProcessLock;
00810     PLIST_ENTRY NextEntry, ListHead;
00811     PKTHREAD Thread;
00812 
00813     ASSERT_PROCESS(Process);
00814 
00815     /* Initialize user and kernel times */
00816     TotalUser = Process->UserTime;
00817     TotalKernel = Process->KernelTime;
00818 
00819     /* Lock the process */
00820     KiAcquireProcessLock(Process, &ProcessLock);
00821 
00822     /* Loop all child threads and sum up their times */
00823     ListHead = &Process->ThreadListHead;
00824     NextEntry = ListHead->Flink;
00825     while (ListHead != NextEntry)
00826     {
00827         /* Get the thread */
00828         Thread = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
00829 
00830         /* Sum up times */
00831         TotalKernel += Thread->KernelTime;
00832         TotalUser += Thread->UserTime;
00833 
00834         /* Go to the next one */
00835         NextEntry = NextEntry->Flink;
00836     }
00837 
00838     /* Release lock */
00839     KiReleaseProcessLock(&ProcessLock);
00840 
00841     /* Return the user time */
00842     *UserTime = TotalUser;
00843 
00844     /* Return the kernel time */
00845     return TotalKernel;
00846 }
00847 
00848 /*
00849  * @implemented
00850  */
00851 BOOLEAN
00852 NTAPI
00853 KeAddSystemServiceTable(IN PULONG_PTR Base,
00854                         IN PULONG Count OPTIONAL,
00855                         IN ULONG Limit,
00856                         IN PUCHAR Number,
00857                         IN ULONG Index)
00858 {
00859     PAGED_CODE();
00860 
00861     /* Check if descriptor table entry is free */
00862     if ((Index > SSDT_MAX_ENTRIES - 1) ||
00863         (KeServiceDescriptorTable[Index].Base) ||
00864         (KeServiceDescriptorTableShadow[Index].Base))
00865     {
00866         /* It's not, fail */
00867         return FALSE;
00868     }
00869 
00870     /* Initialize the shadow service descriptor table */
00871     KeServiceDescriptorTableShadow[Index].Base = Base;
00872     KeServiceDescriptorTableShadow[Index].Limit = Limit;
00873     KeServiceDescriptorTableShadow[Index].Number = Number;
00874     KeServiceDescriptorTableShadow[Index].Count = Count;
00875     return TRUE;
00876 }
00877 
00878 /*
00879  * @implemented
00880  */
00881 BOOLEAN
00882 NTAPI
00883 KeRemoveSystemServiceTable(IN ULONG Index)
00884 {
00885     PAGED_CODE();
00886 
00887     /* Make sure the Index is valid */
00888     if (Index > (SSDT_MAX_ENTRIES - 1)) return FALSE;
00889 
00890     /* Is there a Normal Descriptor Table? */
00891     if (!KeServiceDescriptorTable[Index].Base)
00892     {
00893         /* Not with the index, is there a shadow at least? */
00894         if (!KeServiceDescriptorTableShadow[Index].Base) return FALSE;
00895     }
00896 
00897     /* Now clear from the Shadow Table. */
00898     KeServiceDescriptorTableShadow[Index].Base = NULL;
00899     KeServiceDescriptorTableShadow[Index].Number = NULL;
00900     KeServiceDescriptorTableShadow[Index].Limit = 0;
00901     KeServiceDescriptorTableShadow[Index].Count = NULL;
00902 
00903     /* Check if we should clean from the Master one too */
00904     if (Index == 1)
00905     {
00906         KeServiceDescriptorTable[Index].Base = NULL;
00907         KeServiceDescriptorTable[Index].Number = NULL;
00908         KeServiceDescriptorTable[Index].Limit = 0;
00909         KeServiceDescriptorTable[Index].Count = NULL;
00910     }
00911 
00912     /* Return success */
00913     return TRUE;
00914 }
00915 /* EOF */

Generated on Thu May 24 2012 04:37:53 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.