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

process.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS CSR Sub System
00004  * FILE:            subsys/csr/csrsrv/process.c
00005  * PURPOSE:         CSR Server DLL Process Implementation
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "srv.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* DATA **********************************************************************/
00017 
00018 PCSR_PROCESS CsrRootProcess = NULL;
00019 RTL_CRITICAL_SECTION CsrProcessLock;
00020 ULONG CsrProcessSequenceCount = 5;
00021 ULONG CsrTotalPerProcessDataLength;
00022 
00023 /* PRIVATE FUNCTIONS *********************************************************/
00024 
00025 /*++
00026  * @name ProtectHandle
00027  * @implemented NT5.2
00028  *
00029  * The ProtectHandle routine protects an object handle against closure.
00030  *
00031  * @return TRUE or FALSE.
00032  *
00033  * @remarks None.
00034  *
00035  *--*/
00036 BOOLEAN
00037 NTAPI
00038 ProtectHandle(IN HANDLE ObjectHandle)
00039 {
00040     NTSTATUS Status;
00041     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
00042 
00043     /* Query current state */
00044     Status = NtQueryObject(ObjectHandle,
00045                            ObjectHandleFlagInformation,
00046                            &HandleInfo,
00047                            sizeof(HandleInfo),
00048                            NULL);
00049     if (NT_SUCCESS(Status))
00050     {
00051         /* Enable protect from close */
00052         HandleInfo.ProtectFromClose = TRUE;
00053         Status = NtSetInformationObject(ObjectHandle,
00054                                         ObjectHandleFlagInformation,
00055                                         &HandleInfo,
00056                                         sizeof(HandleInfo));
00057         if (NT_SUCCESS(Status)) return TRUE;
00058     }
00059 
00060     /* We failed to or set the state */
00061     return FALSE;
00062 }
00063 
00064 /*++
00065  * @name UnProtectHandle
00066  * @implemented NT5.2
00067  *
00068  * The UnProtectHandle routine unprotects an object handle against closure.
00069  *
00070  * @return TRUE or FALSE.
00071  *
00072  * @remarks None.
00073  *
00074  *--*/
00075 BOOLEAN
00076 NTAPI
00077 UnProtectHandle(IN HANDLE ObjectHandle)
00078 {
00079     NTSTATUS Status;
00080     OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo;
00081 
00082     /* Query current state */
00083     Status = NtQueryObject(ObjectHandle,
00084                            ObjectHandleFlagInformation,
00085                            &HandleInfo,
00086                            sizeof(HandleInfo),
00087                            NULL);
00088     if (NT_SUCCESS(Status))
00089     {
00090         /* Disable protect from close */
00091         HandleInfo.ProtectFromClose = FALSE;
00092         Status = NtSetInformationObject(ObjectHandle,
00093                                         ObjectHandleFlagInformation,
00094                                         &HandleInfo,
00095                                         sizeof(HandleInfo));
00096         if (NT_SUCCESS(Status)) return TRUE;
00097     }
00098 
00099     /* We failed to or set the state */
00100     return FALSE;
00101 }
00102 
00103 /*++
00104  * @name CsrAllocateProcess
00105  * @implemented NT4
00106  *
00107  * The CsrAllocateProcess routine allocates a new CSR Process object.
00108  *
00109  * @return Pointer to the newly allocated CSR Process.
00110  *
00111  * @remarks None.
00112  *
00113  *--*/
00114 PCSR_PROCESS
00115 NTAPI
00116 CsrAllocateProcess(VOID)
00117 {
00118     PCSR_PROCESS CsrProcess;
00119     ULONG TotalSize;
00120 
00121     /* Calculate the amount of memory this should take */
00122     TotalSize = sizeof(CSR_PROCESS) +
00123                 (CSR_SERVER_DLL_MAX * sizeof(PVOID)) +
00124                 CsrTotalPerProcessDataLength;
00125 
00126     /* Allocate a Process */
00127     CsrProcess = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, TotalSize);
00128     if (!CsrProcess) return NULL;
00129 
00130     /* Handle the Sequence Number and protect against overflow */
00131     CsrProcess->SequenceNumber = CsrProcessSequenceCount++;
00132     if (CsrProcessSequenceCount < 5) CsrProcessSequenceCount = 5;
00133 
00134     /* Increase the reference count */
00135     CsrProcess->ReferenceCount++;
00136 
00137     /* Initialize the Thread List */
00138     InitializeListHead(&CsrProcess->ThreadList);
00139 
00140     /* Return the Process */
00141     return CsrProcess;
00142 }
00143 
00144 /*++
00145  * @name CsrServerInitialization
00146  * @implemented NT4
00147  *
00148  * The CsrInitializeProcessStructure routine sets up support for CSR Processes
00149  * and CSR Threads.
00150  *
00151  * @param None.
00152  *
00153  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00154  *         othwerwise.
00155  *
00156  * @remarks None.
00157  *
00158  *--*/
00159 NTSTATUS
00160 NTAPI
00161 CsrInitializeProcessStructure(VOID)
00162 {
00163     NTSTATUS Status;
00164     ULONG i;
00165 
00166     /* Initialize the Lock */
00167     Status = RtlInitializeCriticalSection(&CsrProcessLock);
00168     if (!NT_SUCCESS(Status)) return Status;
00169 
00170     /* Set up the Root Process */
00171     CsrRootProcess = CsrAllocateProcess();
00172     if (!CsrRootProcess) return STATUS_NO_MEMORY;
00173 
00174     /* Set up the minimal information for it */
00175     InitializeListHead(&CsrRootProcess->ListLink);
00176     CsrRootProcess->ProcessHandle = (HANDLE)-1;
00177     CsrRootProcess->ClientId = NtCurrentTeb()->ClientId;
00178 
00179     /* Initialize the Thread Hash List */
00180     for (i = 0; i < 256; i++) InitializeListHead(&CsrThreadHashTable[i]);
00181 
00182     /* Initialize the Wait Lock */
00183     return RtlInitializeCriticalSection(&CsrWaitListsLock);
00184 }
00185 
00186 /*++
00187  * @name CsrDeallocateProcess
00188  *
00189  * The CsrDeallocateProcess frees the memory associated with a CSR Process.
00190  *
00191  * @param CsrProcess
00192  *        Pointer to the CSR Process to be freed.
00193  *
00194  * @return None.
00195  *
00196  * @remarks Do not call this routine. It is reserved for the internal
00197  *          thread management routines when a CSR Process has been cleanly
00198  *          dereferenced and killed.
00199  *
00200  *--*/
00201 VOID
00202 NTAPI
00203 CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess)
00204 {
00205     /* Free the process object from the heap */
00206     RtlFreeHeap(CsrHeap, 0, CsrProcess);
00207 }
00208 
00209 /*++
00210  * @name CsrInsertProcess
00211  *
00212  * The CsrInsertProcess routine inserts a CSR Process into the Process List
00213  * and notifies Server DLLs of the creation of a new CSR Process.
00214  *
00215  * @param Parent
00216  *        Optional pointer to the CSR Process creating this CSR Process.
00217  *
00218  * @param CurrentProcess
00219  *        Optional pointer to the current CSR Process.
00220  *
00221  * @param CsrProcess
00222  *        Pointer to the CSR Process which is to be inserted.
00223  *
00224  * @return None.
00225  *
00226  * @remarks None.
00227  *
00228  *--*/
00229 VOID
00230 NTAPI
00231 CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL,
00232                  IN PCSR_PROCESS CurrentProcess OPTIONAL,
00233                  IN PCSR_PROCESS CsrProcess)
00234 {
00235     PCSR_SERVER_DLL ServerDll;
00236     ULONG i;
00237     ASSERT(ProcessStructureListLocked());
00238 
00239     /* Set the parent */
00240     CsrProcess->Parent = Parent;
00241 
00242     /* Insert it into the Root List */
00243     InsertTailList(&CsrRootProcess->ListLink, &CsrProcess->ListLink);
00244 
00245     /* Notify the Server DLLs */
00246     for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
00247     {
00248         /* Get the current Server DLL */
00249         ServerDll = CsrLoadedServerDll[i];
00250 
00251         /* Make sure it's valid and that it has callback */
00252         if ((ServerDll) && (ServerDll->NewProcessCallback))
00253         {
00254             ServerDll->NewProcessCallback(CurrentProcess, CsrProcess);
00255         }
00256     }
00257 }
00258 
00259 /*++
00260  * @name CsrLockedDereferenceProcess
00261  *
00262  * The CsrLockedDereferenceProcess dereferences a CSR Process while the
00263  * Process Lock is already being held.
00264  *
00265  * @param CsrProcess
00266  *        Pointer to the CSR Process to be dereferenced.
00267  *
00268  * @return None.
00269  *
00270  * @remarks This routine will return with the Process Lock held.
00271  *
00272  *--*/
00273 VOID
00274 NTAPI
00275 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
00276 {
00277     LONG LockCount;
00278 
00279     /* Decrease reference count */
00280     LockCount = --CsrProcess->ReferenceCount;
00281     ASSERT(LockCount >= 0);
00282     if (!LockCount)
00283     {
00284         /* Call the generic cleanup code */
00285         CsrProcessRefcountZero(CsrProcess);
00286         CsrAcquireProcessLock();
00287     }
00288 }
00289 
00290 /*++
00291  * @name CsrLockedReferenceProcess
00292  *
00293  * The CsrLockedReferenceProcess refences a CSR Process while the
00294  * Process Lock is already being held.
00295  *
00296  * @param CsrProcess
00297  *        Pointer to the CSR Process to be referenced.
00298  *
00299  * @return None.
00300  *
00301  * @remarks This routine will return with the Process Lock held.
00302  *
00303  *--*/
00304 VOID
00305 NTAPI
00306 CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
00307 {
00308     /* Increment the reference count */
00309     ++CsrProcess->ReferenceCount;
00310 }
00311 
00312 /*++
00313  * @name CsrRemoveProcess
00314  *
00315  * The CsrRemoveProcess function undoes a CsrInsertProcess operation and
00316  * removes the CSR Process from the Process List and notifies Server DLLs
00317  * of this removal.
00318  *
00319  * @param CsrProcess
00320  *        Pointer to the CSR Process to remove.
00321  *
00322  * @return None.
00323  *
00324  * @remarks None.
00325  *
00326  *--*/
00327 VOID
00328 NTAPI
00329 CsrRemoveProcess(IN PCSR_PROCESS CsrProcess)
00330 {
00331     PCSR_SERVER_DLL ServerDll;
00332     ULONG i;
00333     ASSERT(ProcessStructureListLocked());
00334 
00335     /* Remove us from the Process List */
00336     RemoveEntryList(&CsrProcess->ListLink);
00337 
00338     /* Release the lock */
00339     CsrReleaseProcessLock();
00340 
00341     /* Loop every Server DLL */
00342     for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
00343     {
00344         /* Get the Server DLL */
00345         ServerDll = CsrLoadedServerDll[i];
00346 
00347         /* Check if it's valid and if it has a Disconnect Callback */
00348         if ((ServerDll) && (ServerDll->DisconnectCallback))
00349         {
00350             /* Call it */
00351             ServerDll->DisconnectCallback(CsrProcess);
00352         }
00353     }
00354 }
00355 
00356 /*++
00357  * @name CsrProcessRefcountZero
00358  *
00359  * The CsrProcessRefcountZero routine is executed when a CSR Process has lost
00360  * all its active references. It removes and de-allocates the CSR Process.
00361  *
00362  * @param CsrProcess
00363  *        Pointer to the CSR Process that is to be deleted.
00364  *
00365  * @return None.
00366  *
00367  * @remarks Do not call this routine. It is reserved for the internal
00368  *          thread management routines when a CSR Process has lost all
00369  *          its references.
00370  *
00371  *          This routine is called with the Process Lock held.
00372  *
00373  *--*/
00374 VOID
00375 NTAPI
00376 CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess)
00377 {
00378     /* Remove the Process from the list */
00379     CsrRemoveProcess(CsrProcess);
00380 
00381     /* Check if there's a session */
00382     if (CsrProcess->NtSession)
00383     {
00384         /* Dereference the Session */
00385         CsrDereferenceNtSession(CsrProcess->NtSession, 0);
00386     }
00387 
00388     /* Close the Client Port if there is one */
00389     if (CsrProcess->ClientPort) NtClose(CsrProcess->ClientPort);
00390 
00391     /* Close the process handle */
00392     NtClose(CsrProcess->ProcessHandle);
00393 
00394     /* Free the Proces Object */
00395     CsrDeallocateProcess(CsrProcess);
00396 }
00397 
00398 /*++
00399  * @name CsrpSetToNormalPriority
00400  *
00401  * The CsrpSetToNormalPriority routine sets the current NT Process'
00402  * priority to the normal priority for CSR Processes.
00403  *
00404  * @param None.
00405  *
00406  * @return None.
00407  *
00408  * @remarks The "Normal" Priority corresponds to the Normal Forground
00409  *          Priority (9) plus a boost of 4.
00410  *
00411  *--*/
00412 VOID
00413 NTAPI
00414 CsrpSetToNormalPriority(VOID)
00415 {
00416     KPRIORITY BasePriority = (8 + 1) + 4;
00417 
00418     /* Set the Priority */
00419     NtSetInformationProcess(NtCurrentProcess(),
00420                             ProcessBasePriority,
00421                             &BasePriority,
00422                             sizeof(KPRIORITY));
00423 }
00424 
00425 /*++
00426  * @name CsrpSetToShutdownPriority
00427  *
00428  * The CsrpSetToShutdownPriority routine sets the current NT Process'
00429  * priority to the boosted priority for CSR Processes doing shutdown.
00430  * Additonally, it acquires the Shutdown Privilege required for shutdown.
00431  *
00432  * @param None.
00433  *
00434  * @return None.
00435  *
00436  * @remarks The "Shutdown" Priority corresponds to the Normal Forground
00437  *          Priority (9) plus a boost of 6.
00438  *
00439  *--*/
00440 VOID
00441 NTAPI
00442 CsrpSetToShutdownPriority(VOID)
00443 {
00444     KPRIORITY SetBasePriority = (8 + 1) + 6;
00445     BOOLEAN Old;
00446 
00447     /* Get the shutdown privilege */
00448     if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,
00449                                       TRUE,
00450                                       FALSE,
00451                                       &Old)))
00452     {
00453         /* Set the Priority */
00454         NtSetInformationProcess(NtCurrentProcess(),
00455                                 ProcessBasePriority,
00456                                 &SetBasePriority,
00457                                 sizeof(KPRIORITY));
00458     }
00459 }
00460 
00461 /*++
00462  * @name FindProcessForShutdown
00463  *
00464  * The FindProcessForShutdown routine returns a CSR Process which is ready
00465  * to be shutdown, and sets the appropriate shutdown flags for it.
00466  *
00467  * @param CallerLuid
00468  *        Pointer to the LUID of the CSR Process calling this routine.
00469  *
00470  * @return Pointer to a CSR Process which is ready to be shutdown.
00471  *
00472  * @remarks None.
00473  *
00474  *--*/
00475 PCSR_PROCESS
00476 NTAPI
00477 FindProcessForShutdown(IN PLUID CallerLuid)
00478 {
00479     PLIST_ENTRY NextEntry;
00480     LUID ProcessLuid;
00481     NTSTATUS Status;
00482     LUID SystemLuid = SYSTEM_LUID;
00483     PCSR_PROCESS CsrProcess;
00484     PCSR_THREAD CsrThread;
00485     PCSR_PROCESS ReturnCsrProcess = NULL;
00486     ULONG Level = 0;
00487 
00488     /* Set the List Pointers */
00489     NextEntry = CsrRootProcess->ListLink.Flink;
00490     while (NextEntry != &CsrRootProcess->ListLink)
00491     {
00492         /* Get the process */
00493         CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
00494 
00495         /* Move to the next entry */
00496         NextEntry = NextEntry->Flink;
00497 
00498         /* Skip this process if it's already been processed*/
00499         if (CsrProcess->Flags & CsrProcessSkipShutdown) continue;
00500 
00501         /* Get the LUID of this Process */
00502         Status = CsrGetProcessLuid(CsrProcess->ProcessHandle, &ProcessLuid);
00503 
00504         /* Check if we didn't get access to the LUID */
00505         if (Status == STATUS_ACCESS_DENIED)
00506         {
00507             /* Check if we have any threads */
00508             if (CsrProcess->ThreadCount)
00509             {
00510                 /* Impersonate one of the threads and retry */
00511                 CsrThread = CONTAINING_RECORD(CsrProcess->ThreadList.Flink,
00512                                               CSR_THREAD,
00513                                               Link);
00514                 CsrImpersonateClient(CsrThread);
00515                 Status = CsrGetProcessLuid(NULL, &ProcessLuid);
00516                 CsrRevertToSelf();
00517             }
00518         }
00519 
00520         if (!NT_SUCCESS(Status))
00521         {
00522             /* We didn't have access, so skip it */
00523             CsrProcess->Flags |= CsrProcessSkipShutdown;
00524             continue;
00525         }
00526 
00527         /* Check if this is the System LUID */
00528         if (RtlEqualLuid(&ProcessLuid, &SystemLuid))
00529         {
00530             /* Mark this process */
00531             CsrProcess->ShutdownFlags |= CsrShutdownSystem;
00532         }
00533         else if (!RtlEqualLuid(&ProcessLuid, CallerLuid))
00534         {
00535             /* Our LUID doesn't match with the caller's */
00536             CsrProcess->ShutdownFlags |= CsrShutdownOther;
00537         }
00538 
00539         /* Check if we're past the previous level */
00540         if ((CsrProcess->ShutdownLevel > Level) || !(ReturnCsrProcess))
00541         {
00542             /* Update the level */
00543             Level = CsrProcess->ShutdownLevel;
00544 
00545             /* Set the final process */
00546             ReturnCsrProcess = CsrProcess;
00547         }
00548     }
00549 
00550     /* Check if we found a process */
00551     if (ReturnCsrProcess)
00552     {
00553         /* Skip this one next time */
00554         ReturnCsrProcess->Flags |= CsrProcessSkipShutdown;
00555     }
00556 
00557     return ReturnCsrProcess;
00558 }
00559 
00560 /* PUBLIC FUNCTIONS ***********************************************************/
00561 
00562 /*++
00563  * @name CsrCreateProcess
00564  * @implemented NT4
00565  *
00566  * Do nothing for 500ms.
00567  *
00568  * @param ArgumentCount
00569  *        Description of the parameter. Wrapped to more lines on ~70th
00570  *        column.
00571  *
00572  * @param Arguments
00573  *        Description of the parameter. Wrapped to more lines on ~70th
00574  *        column.
00575  *
00576  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00577  *         othwerwise.
00578  *
00579  * @remarks None.
00580  *
00581  *--*/
00582 NTSTATUS
00583 NTAPI
00584 CsrCreateProcess(IN HANDLE hProcess,
00585                  IN HANDLE hThread,
00586                  IN PCLIENT_ID ClientId,
00587                  IN PCSR_NT_SESSION NtSession,
00588                  IN ULONG Flags,
00589                  IN PCLIENT_ID DebugCid)
00590 {
00591     PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
00592     CLIENT_ID CurrentCid;
00593     PCSR_PROCESS CurrentProcess;
00594     PVOID ProcessData;
00595     ULONG i;
00596     PCSR_PROCESS CsrProcess;
00597     NTSTATUS Status;
00598     PCSR_THREAD CsrThread;
00599     KERNEL_USER_TIMES KernelTimes;
00600 
00601     /* Get the current CID and lock Processes */
00602     CurrentCid = CurrentThread->ClientId;
00603     CsrAcquireProcessLock();
00604 
00605     /* Get the current CSR Thread */
00606     CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
00607     if (!CurrentThread)
00608     {
00609         /* We've failed to locate the thread */
00610         CsrReleaseProcessLock();
00611         return STATUS_THREAD_IS_TERMINATING;
00612     }
00613 
00614     /* Allocate a new Process Object */
00615     CsrProcess = CsrAllocateProcess();
00616     if (!CsrProcess)
00617     {
00618         /* Couldn't allocate Process */
00619         CsrReleaseProcessLock();
00620         return STATUS_NO_MEMORY;
00621     }
00622 
00623     /* Inherit the Process Data */
00624     CurrentProcess = CurrentThread->Process;
00625     ProcessData = &CurrentProcess->ServerData[CSR_SERVER_DLL_MAX];
00626     for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
00627     {
00628         /* Check if the DLL is Loaded and has Per Process Data */
00629         if (CsrLoadedServerDll[i] && CsrLoadedServerDll[i]->SizeOfProcessData)
00630         {
00631             /* Set the pointer */
00632             CsrProcess->ServerData[i] = ProcessData;
00633 
00634             /* Copy the Data */
00635             RtlMoveMemory(ProcessData,
00636                           CurrentProcess->ServerData[i],
00637                           CsrLoadedServerDll[i]->SizeOfProcessData);
00638 
00639             /* Update next data pointer */
00640             ProcessData = (PVOID)((ULONG_PTR)ProcessData +
00641                                   CsrLoadedServerDll[i]->SizeOfProcessData);
00642         }
00643         else
00644         {
00645             /* No data for this Server */
00646             CsrProcess->ServerData[i] = NULL;
00647         }
00648     }
00649 
00650     /* Set the Exception port to us */
00651     Status = NtSetInformationProcess(hProcess,
00652                                      ProcessExceptionPort,
00653                                      &CsrApiPort,
00654                                      sizeof(HANDLE));
00655     if (!NT_SUCCESS(Status))
00656     {
00657         /* Failed */
00658         CsrDeallocateProcess(CsrProcess);
00659         CsrReleaseProcessLock();
00660         return STATUS_NO_MEMORY;
00661     }
00662 
00663     /* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
00664     if (!(Flags & CsrProcessCreateNewGroup))
00665     {
00666         /* Create new data */
00667         CsrProcess->ProcessGroupId = HandleToUlong(ClientId->UniqueProcess);
00668         CsrProcess->ProcessGroupSequence = CsrProcess->SequenceNumber;
00669     }
00670     else
00671     {
00672         /* Copy it from the current process */
00673         CsrProcess->ProcessGroupId = CurrentProcess->ProcessGroupId;
00674         CsrProcess->ProcessGroupSequence = CurrentProcess->ProcessGroupSequence;
00675     }
00676 
00677     /* Check if this is a console process */
00678     if (Flags & CsrProcessIsConsoleApp) CsrProcess->Flags |= CsrProcessIsConsoleApp;
00679 
00680     /* Mask out non-debug flags */
00681     Flags &= ~(CsrProcessIsConsoleApp | CsrProcessCreateNewGroup | CsrProcessPriorityFlags);
00682 
00683     /* Check if every process will be debugged */
00684     if (!(Flags) && (CurrentProcess->DebugFlags & CsrDebugProcessChildren))
00685     {
00686         /* Pass it on to the current process */
00687         CsrProcess->DebugFlags = CsrDebugProcessChildren;
00688         CsrProcess->DebugCid = CurrentProcess->DebugCid;
00689     }
00690 
00691     /* Check if Debugging was used on this process */
00692     if ((Flags & (CsrDebugOnlyThisProcess | CsrDebugProcessChildren)) && (DebugCid))
00693     {
00694         /* Save the debug flag used */
00695         CsrProcess->DebugFlags = Flags;
00696 
00697         /* Save the CID */
00698         CsrProcess->DebugCid = *DebugCid;
00699     }
00700 
00701     /* Check if we debugging is enabled */
00702     if (CsrProcess->DebugFlags)
00703     {
00704         /* Set the Debug Port to us */
00705         Status = NtSetInformationProcess(hProcess,
00706                                          ProcessDebugPort,
00707                                          &CsrApiPort,
00708                                          sizeof(HANDLE));
00709         ASSERT(NT_SUCCESS(Status));
00710         if (!NT_SUCCESS(Status))
00711         {
00712             /* Failed */
00713             CsrDeallocateProcess(CsrProcess);
00714             CsrReleaseProcessLock();
00715             return STATUS_NO_MEMORY;
00716         }
00717     }
00718 
00719     /* Get the Thread Create Time */
00720     Status = NtQueryInformationThread(hThread,
00721                                       ThreadTimes,
00722                                       (PVOID)&KernelTimes,
00723                                       sizeof(KernelTimes),
00724                                       NULL);
00725     if (!NT_SUCCESS(Status))
00726     {
00727         /* Failed */
00728         CsrDeallocateProcess(CsrProcess);
00729         CsrReleaseProcessLock();
00730         return STATUS_NO_MEMORY;
00731     }
00732 
00733     /* Allocate a CSR Thread Structure */
00734     CsrThread = CsrAllocateThread(CsrProcess);
00735     if (!CsrThread)
00736     {
00737         /* Failed */
00738         CsrDeallocateProcess(CsrProcess);
00739         CsrReleaseProcessLock();
00740         return STATUS_NO_MEMORY;
00741     }
00742 
00743     /* Save the data we have */
00744     CsrThread->CreateTime = KernelTimes.CreateTime;
00745     CsrThread->ClientId = *ClientId;
00746     CsrThread->ThreadHandle = hThread;
00747     ProtectHandle(hThread);
00748     CsrThread->Flags = 0;
00749 
00750     /* Insert the Thread into the Process */
00751     CsrInsertThread(CsrProcess, CsrThread);
00752 
00753     /* Reference the session */
00754     CsrReferenceNtSession(NtSession);
00755     CsrProcess->NtSession = NtSession;
00756 
00757     /* Setup Process Data */
00758     CsrProcess->ClientId = *ClientId;
00759     CsrProcess->ProcessHandle = hProcess;
00760     CsrProcess->ShutdownLevel = 0x280;
00761 
00762     /* Set the Priority to Background */
00763     CsrSetBackgroundPriority(CsrProcess);
00764 
00765     /* Insert the Process */
00766     CsrInsertProcess(NULL, CurrentProcess, CsrProcess);
00767 
00768     /* Release lock and return */
00769     CsrReleaseProcessLock();
00770     return Status;
00771 }
00772 
00773 /*++
00774  * @name CsrDebugProcess
00775  * @implemented NT4
00776  *
00777  * The CsrDebugProcess routine is deprecated in NT 5.1 and higher. It is
00778  * exported only for compatibility with older CSR Server DLLs.
00779  *
00780  * @param CsrProcess
00781  *        Deprecated.
00782  *
00783  * @return Deprecated
00784  *
00785  * @remarks Deprecated.
00786  *
00787  *--*/
00788 NTSTATUS
00789 NTAPI
00790 CsrDebugProcess(IN PCSR_PROCESS CsrProcess)
00791 {
00792     /* CSR does not handle debugging anymore */
00793     DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
00794     return STATUS_UNSUCCESSFUL;
00795 }
00796 
00797 /*++
00798  * @name CsrServerInitialization
00799  * @implemented NT4
00800  *
00801  * The CsrDebugProcessStop routine is deprecated in NT 5.1 and higher. It is
00802  * exported only for compatibility with older CSR Server DLLs.
00803  *
00804  * @param CsrProcess
00805  *        Deprecated.
00806  *
00807  * @return Deprecated
00808  *
00809  * @remarks Deprecated.
00810  *
00811  *--*/
00812 NTSTATUS
00813 NTAPI
00814 CsrDebugProcessStop(IN PCSR_PROCESS CsrProcess)
00815 {
00816     /* CSR does not handle debugging anymore */
00817     DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__, CsrProcess);
00818     return STATUS_UNSUCCESSFUL;
00819 }
00820 
00821 /*++
00822  * @name CsrDereferenceProcess
00823  * @implemented NT4
00824  *
00825  * The CsrDereferenceProcess routine removes a reference from a CSR Process.
00826  *
00827  * @param CsrThread
00828  *        Pointer to the CSR Process to dereference.
00829  *
00830  * @return None.
00831  *
00832  * @remarks If the reference count has reached zero (ie: the CSR Process has
00833  *          no more active references), it will be deleted.
00834  *
00835  *--*/
00836 VOID
00837 NTAPI
00838 CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
00839 {
00840     LONG LockCount;
00841 
00842     /* Acquire process lock */
00843     CsrAcquireProcessLock();
00844 
00845     /* Decrease reference count */
00846     LockCount = --CsrProcess->ReferenceCount;
00847     ASSERT(LockCount >= 0);
00848     if (!LockCount)
00849     {
00850         /* Call the generic cleanup code */
00851         CsrProcessRefcountZero(CsrProcess);
00852     }
00853     else
00854     {
00855         /* Just release the lock */
00856         CsrReleaseProcessLock();
00857     }
00858 }
00859 
00860 /*++
00861  * @name CsrDestroyProcess
00862  * @implemented NT4
00863  *
00864  * The CsrDestroyProcess routine destroys the CSR Process corresponding to
00865  * a given Client ID.
00866  *
00867  * @param Cid
00868  *        Pointer to the Client ID Structure corresponding to the CSR
00869  *        Process which is about to be destroyed.
00870  *
00871  * @param ExitStatus
00872  *        Unused.
00873  *
00874  * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
00875  *         if the CSR Process is already terminating.
00876  *
00877  * @remarks None.
00878  *
00879  *--*/
00880 NTSTATUS
00881 NTAPI
00882 CsrDestroyProcess(IN PCLIENT_ID Cid,
00883                   IN NTSTATUS ExitStatus)
00884 {
00885     PCSR_THREAD CsrThread;
00886     PCSR_PROCESS CsrProcess;
00887     CLIENT_ID ClientId = *Cid;
00888     PLIST_ENTRY NextEntry;
00889 
00890     /* Acquire lock */
00891     CsrAcquireProcessLock();
00892 
00893     /* Find the thread */
00894     CsrThread = CsrLocateThreadByClientId(&CsrProcess, &ClientId);
00895 
00896     /* Make sure we got one back, and that it's not already gone */
00897     if (!(CsrThread) || (CsrProcess->Flags & CsrProcessTerminating))
00898     {
00899         /* Release the lock and return failure */
00900         CsrReleaseProcessLock();
00901         return STATUS_THREAD_IS_TERMINATING;
00902     }
00903 
00904     /* Set the terminated flag */
00905     CsrProcess->Flags |= CsrProcessTerminating;
00906 
00907     /* Get the List Pointers */
00908     NextEntry = CsrProcess->ThreadList.Flink;
00909     while (NextEntry != &CsrProcess->ThreadList)
00910     {
00911         /* Get the current thread entry */
00912         CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
00913 
00914         /* Make sure the thread isn't already dead */
00915         if (CsrThread->Flags & CsrThreadTerminated)
00916         {
00917             NextEntry = NextEntry->Flink;
00918             continue;
00919         }
00920 
00921         /* Set the Terminated flag */
00922         CsrThread->Flags |= CsrThreadTerminated;
00923 
00924         /* Acquire the Wait Lock */
00925         CsrAcquireWaitLock();
00926 
00927         /* Do we have an active wait block? */
00928         if (CsrThread->WaitBlock)
00929         {
00930             /* Notify waiters of termination */
00931             CsrNotifyWaitBlock(CsrThread->WaitBlock,
00932                                NULL,
00933                                NULL,
00934                                NULL,
00935                                CsrProcessTerminating,
00936                                TRUE);
00937         }
00938 
00939         /* Release the Wait Lock */
00940         CsrReleaseWaitLock();
00941 
00942         /* Dereference the thread */
00943         CsrLockedDereferenceThread(CsrThread);
00944         NextEntry = CsrProcess->ThreadList.Flink;
00945     }
00946 
00947     /* Release the Process Lock and return success */
00948     CsrReleaseProcessLock();
00949     return STATUS_SUCCESS;
00950 }
00951 
00952 /*++
00953  * @name CsrGetProcessLuid
00954  * @implemented NT4
00955  *
00956  * Do nothing for 500ms.
00957  *
00958  * @param hProcess
00959  *        Optional handle to the process whose LUID should be returned.
00960  *
00961  * @param Luid
00962  *        Pointer to a LUID Pointer which will receive the CSR Process' LUID
00963  *
00964  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00965  *         othwerwise.
00966  *
00967  * @remarks If hProcess is not supplied, then the current thread's token will
00968  *          be used. If that too is missing, then the current process' token
00969  *          will be used.
00970  *
00971  *--*/
00972 NTSTATUS
00973 NTAPI
00974 CsrGetProcessLuid(HANDLE hProcess OPTIONAL,
00975                   PLUID Luid)
00976 {
00977     HANDLE hToken = NULL;
00978     NTSTATUS Status;
00979     ULONG Length;
00980     PTOKEN_STATISTICS TokenStats;
00981 
00982     /* Check if we have a handle to a CSR Process */
00983     if (!hProcess)
00984     {
00985         /* We don't, so try opening the Thread's Token */
00986         Status = NtOpenThreadToken(NtCurrentThread(),
00987                                    TOKEN_QUERY,
00988                                    FALSE,
00989                                    &hToken);
00990 
00991         /* Check for success */
00992         if (!NT_SUCCESS(Status))
00993         {
00994             /* If we got some other failure, then return and quit */
00995             if (Status != STATUS_NO_TOKEN) return Status;
00996 
00997             /* We don't have a Thread Token, use a Process Token */
00998             hProcess = NtCurrentProcess();
00999             hToken = NULL;
01000         }
01001     }
01002 
01003     /* Check if we have a token by now */
01004     if (!hToken)
01005     {
01006         /* No token yet, so open the Process Token */
01007         Status = NtOpenProcessToken(hProcess,
01008                                     TOKEN_QUERY,
01009                                     &hToken);
01010         if (!NT_SUCCESS(Status)) return Status;
01011     }
01012 
01013     /* Now get the size we'll need for the Token Information */
01014     Status = NtQueryInformationToken(hToken,
01015                                      TokenStatistics,
01016                                      NULL,
01017                                      0,
01018                                      &Length);
01019 
01020     /* Allocate memory for the Token Info */
01021     TokenStats = RtlAllocateHeap(CsrHeap, 0, Length);
01022     if (!TokenStats)
01023     {
01024         /* Fail and close the token */
01025         NtClose(hToken);
01026         return STATUS_NO_MEMORY;
01027     }
01028 
01029     /* Now query the information */
01030     Status = NtQueryInformationToken(hToken,
01031                                      TokenStatistics,
01032                                      TokenStats,
01033                                      Length,
01034                                      &Length);
01035 
01036     /* Close the handle */
01037     NtClose(hToken);
01038 
01039     /* Check for success to return the LUID */
01040     if (NT_SUCCESS(Status)) *Luid = TokenStats->AuthenticationId;
01041 
01042     /* Free the query information */
01043     RtlFreeHeap(CsrHeap, 0, TokenStats);
01044 
01045     /* Return the Status */
01046     return Status;
01047 }
01048 
01049 /*++
01050  * @name CsrLockProcessByClientId
01051  * @implemented NT4
01052  *
01053  * The CsrLockProcessByClientId routine locks the CSR Process corresponding
01054  * to the given Process ID and optionally returns it.
01055  *
01056  * @param Pid
01057  *        Process ID corresponding to the CSR Process which will be locked.
01058  *
01059  * @param CsrProcess
01060  *        Optional pointer to a CSR Process pointer which will hold the
01061  *        CSR Process corresponding to the given Process ID.
01062  *
01063  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
01064  *         othwerwise.
01065  *
01066  * @remarks Locking a CSR Process is defined as acquiring an extra
01067  *          reference to it and returning with the Process Lock held.
01068  *
01069  *--*/
01070 NTSTATUS
01071 NTAPI
01072 CsrLockProcessByClientId(IN HANDLE Pid,
01073                          OUT PCSR_PROCESS *CsrProcess)
01074 {
01075     PLIST_ENTRY NextEntry;
01076     PCSR_PROCESS CurrentProcess = NULL;
01077     NTSTATUS Status;
01078 
01079     /* Acquire the lock */
01080     CsrAcquireProcessLock();
01081 
01082     /* Assume failure */
01083     ASSERT(CsrProcess != NULL);
01084     *CsrProcess = NULL;
01085 
01086     /* Setup the List Pointers */
01087     NextEntry = &CsrRootProcess->ListLink;
01088     do
01089     {
01090         /* Get the Process */
01091         CurrentProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
01092 
01093         /* Check for PID Match */
01094         if (CurrentProcess->ClientId.UniqueProcess == Pid)
01095         {
01096             Status = STATUS_SUCCESS;
01097             break;
01098         }
01099 
01100         /* Next entry */
01101         NextEntry = NextEntry->Flink;
01102     } while (NextEntry != &CsrRootProcess->ListLink);
01103 
01104     /* Check if we didn't find it in the list */
01105     if (!NT_SUCCESS(Status))
01106     {
01107         /* Nothing found, release the lock */
01108         CsrReleaseProcessLock();
01109     }
01110     else
01111     {
01112         /* Lock the found process and return it */
01113         CsrLockedReferenceProcess(CurrentProcess);
01114         *CsrProcess = CurrentProcess;
01115     }
01116     
01117     /* Return the result */
01118     return Status;
01119 }
01120 
01121 /*++
01122  * @name CsrSetForegroundPriority
01123  * @implemented NT4
01124  *
01125  * The CsrSetForegroundPriority routine sets the priority for the given CSR
01126  * Process as a Foreground priority.
01127  *
01128  * @param CsrProcess
01129  *        Pointer to the CSR Process whose priority will be modified.
01130  *
01131  * @return None.
01132  *
01133  * @remarks None.
01134  *
01135  *--*/
01136 VOID
01137 NTAPI
01138 CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess)
01139 {
01140     PROCESS_PRIORITY_CLASS PriorityClass;
01141 
01142     /* Set the Foreground bit on */
01143     PriorityClass.Foreground = TRUE;
01144 
01145     /* Set the new Priority */
01146     NtSetInformationProcess(CsrProcess->ProcessHandle,
01147                             ProcessPriorityClass,
01148                             &PriorityClass,
01149                             sizeof(PriorityClass));
01150 }
01151 
01152 /*++
01153  * @name CsrSetBackgroundPriority
01154  * @implemented NT4
01155  *
01156  * The CsrSetBackgroundPriority routine sets the priority for the given CSR
01157  * Process as a Background priority.
01158  *
01159  * @param CsrProcess
01160  *        Pointer to the CSR Process whose priority will be modified.
01161  *
01162  * @return None.
01163  *
01164  * @remarks None.
01165  *
01166  *--*/
01167 VOID
01168 NTAPI
01169 CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess)
01170 {
01171     PROCESS_PRIORITY_CLASS PriorityClass;
01172 
01173     /* Set the Foreground bit off */
01174     PriorityClass.Foreground = FALSE;
01175 
01176     /* Set the new Priority */
01177     NtSetInformationProcess(CsrProcess->ProcessHandle,
01178                             ProcessPriorityClass,
01179                             &PriorityClass,
01180                             sizeof(PriorityClass));
01181 }
01182 
01183 /*++
01184  * @name CsrShutdownProcesses
01185  * @implemented NT4
01186  *
01187  * The CsrShutdownProcesses routine shuts down every CSR Process possible
01188  * and calls each Server DLL's shutdown notification.
01189  *
01190  * @param CallerLuid
01191  *        Pointer to the LUID of the CSR Process that is ordering the
01192  *        shutdown.
01193  *
01194  * @param Flags
01195  *        Flags to send to the shutdown notification routine.
01196  *
01197  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
01198  *         othwerwise.
01199  *
01200  * @remarks None.
01201  *
01202  *--*/
01203 NTSTATUS
01204 NTAPI
01205 CsrShutdownProcesses(IN PLUID CallerLuid,
01206                      IN ULONG Flags)
01207 {
01208     PLIST_ENTRY NextEntry;
01209     PCSR_PROCESS CsrProcess;
01210     NTSTATUS Status;
01211     BOOLEAN FirstTry;
01212     ULONG i;
01213     PCSR_SERVER_DLL ServerDll;
01214     ULONG Result;
01215 
01216     /* Acquire process lock */
01217     CsrAcquireProcessLock();
01218 
01219     /* Add shutdown flag */
01220     CsrRootProcess->ShutdownFlags |= CsrShutdownSystem;
01221 
01222     /* Get the list pointers */
01223     NextEntry = CsrRootProcess->ListLink.Flink;
01224     while (NextEntry != &CsrRootProcess->ListLink)
01225     {
01226         /* Get the Process */
01227         CsrProcess = CONTAINING_RECORD(NextEntry, CSR_PROCESS, ListLink);
01228 
01229         /* Remove the skip flag, set shutdown flags to 0*/
01230         CsrProcess->Flags &= ~CsrProcessSkipShutdown;
01231         CsrProcess->ShutdownFlags = 0;
01232 
01233         /* Move to the next */
01234         NextEntry = NextEntry->Flink;
01235     }
01236 
01237     /* Set shudown Priority */
01238     CsrpSetToShutdownPriority();
01239 
01240     /* Start looping */
01241     while (TRUE)
01242     {
01243         /* Find the next process to shutdown */
01244         CsrProcess = FindProcessForShutdown(CallerLuid);
01245         if (!CsrProcess) break;
01246 
01247         /* Increase reference to process */
01248         CsrProcess->ReferenceCount++;
01249 
01250         FirstTry = TRUE;
01251         while (TRUE)
01252         {
01253             /* Loop all the servers */
01254             for (i = 0; i < CSR_SERVER_DLL_MAX; i++)
01255             {
01256                 /* Get the current server */
01257                 ServerDll = CsrLoadedServerDll[i];
01258                 if ((ServerDll) && (ServerDll->ShutdownProcessCallback))
01259                 {
01260                     /* Release the lock, make the callback, and acquire it back */
01261                     CsrReleaseProcessLock();
01262                     Result = ServerDll->ShutdownProcessCallback(CsrProcess,
01263                                                                 Flags,
01264                                                                 FirstTry);
01265                     CsrAcquireProcessLock();
01266 
01267                     /* Check the result */
01268                     if (Result == CsrShutdownCsrProcess)
01269                     {
01270                         /* The callback unlocked the process */
01271                         break;
01272                     }
01273                     else if (Result == CsrShutdownCancelled)
01274                     {
01275                         /* Check if this was a forced shutdown */
01276                         if (Flags & EWX_FORCE)
01277                         {
01278                             DPRINT1("Process %x cancelled forced shutdown (Dll = %d)\n",
01279                                      CsrProcess->ClientId.UniqueProcess, i);
01280                             DbgBreakPoint();
01281                         }
01282 
01283                         /* Shutdown was cancelled, unlock and exit */
01284                         CsrReleaseProcessLock();
01285                         Status = STATUS_CANCELLED;
01286                         goto Quickie;
01287                     }
01288                 }
01289             }
01290 
01291             /* No matches during the first try, so loop again */
01292             if ((FirstTry) && (Result == CsrShutdownNonCsrProcess))
01293             {
01294                 FirstTry = FALSE;
01295                 continue;
01296             }
01297 
01298             /* Second try, break out */
01299             break;
01300         }
01301 
01302         /* We've reached the final loop here, so dereference */
01303         if (i == CSR_SERVER_DLL_MAX) CsrLockedDereferenceProcess(CsrProcess);
01304     }
01305 
01306     /* Success path */
01307     CsrReleaseProcessLock();
01308     Status = STATUS_SUCCESS;
01309 
01310 Quickie:
01311     /* Return to normal priority */
01312     CsrpSetToNormalPriority();
01313     return Status;
01314 }
01315 
01316 /*++
01317  * @name CsrUnlockProcess
01318  * @implemented NT4
01319  *
01320  * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
01321  *
01322  * @param CsrProcess
01323  *        Pointer to a previously locked CSR Process.
01324  *
01325  * @return STATUS_SUCCESS.
01326  *
01327  * @remarks This routine must be called with the Process Lock held.
01328  *
01329  *--*/
01330 NTSTATUS
01331 NTAPI
01332 CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
01333 {
01334     /* Dereference the process */
01335     CsrLockedDereferenceProcess(CsrProcess);
01336 
01337     /* Release the lock and return */
01338     CsrReleaseProcessLock();
01339     return STATUS_SUCCESS;
01340 }
01341 
01342 /* EOF */

Generated on Fri May 25 2012 04:15:32 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.