2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/process.c
5 * PURPOSE: CSR Server DLL Process Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 PCSR_PROCESS CsrRootProcess
= NULL
;
19 RTL_CRITICAL_SECTION CsrProcessLock
;
20 ULONG CsrProcessSequenceCount
= 5;
21 ULONG CsrTotalPerProcessDataLength
;
23 /* PRIVATE FUNCTIONS *********************************************************/
26 * @name CsrAllocateProcess
29 * The CsrAllocateProcess routine allocates a new CSR Process object.
31 * @return Pointer to the newly allocated CSR Process.
38 CsrAllocateProcess(VOID
)
40 PCSR_PROCESS CsrProcess
;
43 /* Calculate the amount of memory this should take */
44 TotalSize
= sizeof(CSR_PROCESS
) +
45 (CSR_SERVER_DLL_MAX
* sizeof(PVOID
)) +
46 CsrTotalPerProcessDataLength
;
48 /* Allocate a Process */
49 CsrProcess
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, TotalSize
);
50 if (!CsrProcess
) return NULL
;
52 /* Handle the Sequence Number */
53 CsrProcess
->SequenceNumber
= CsrProcessSequenceCount
++;
55 /* Increase the reference count */
56 CsrProcess
->ReferenceCount
++;
58 /* Initialize the Thread List */
59 InitializeListHead(&CsrProcess
->ThreadList
);
61 /* Return the Process */
66 * @name CsrServerInitialization
69 * The CsrInitializeProcesses routine sets up support for CSR Processes
74 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
82 CsrInitializeProcesses(VOID
)
87 /* Initialize the Lock */
88 Status
= RtlInitializeCriticalSection(&CsrProcessLock
);
90 /* Set up the Root Process */
91 CsrRootProcess
= CsrAllocateProcess();
92 if (!CsrRootProcess
) return STATUS_NO_MEMORY
;
94 /* Set up the minimal information for it */
95 InitializeListHead(&CsrRootProcess
->ListLink
);
96 CsrRootProcess
->ProcessHandle
= (HANDLE
)-1;
97 CsrRootProcess
->ClientId
= NtCurrentTeb()->ClientId
;
99 /* Initialize the Thread Hash List */
100 for (i
= 0; i
< 256; i
++) InitializeListHead(&CsrThreadHashTable
[i
]);
102 /* Initialize the Wait Lock */
103 Status
= RtlInitializeCriticalSection(&CsrWaitListsLock
);
108 * @name CsrDeallocateProcess
110 * The CsrDeallocateProcess frees the memory associated with a CSR Process.
113 * Pointer to the CSR Process to be freed.
117 * @remarks Do not call this routine. It is reserved for the internal
118 * thread management routines when a CSR Process has been cleanly
119 * dereferenced and killed.
124 CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess
)
126 /* Free the process object from the heap */
127 RtlFreeHeap(CsrHeap
, 0, CsrProcess
);
131 * @name CsrInsertProcess
133 * The CsrInsertProcess routine inserts a CSR Process into the Process List
134 * and notifies Server DLLs of the creation of a new CSR Process.
137 * Optional pointer to the CSR Process creating this CSR Process.
139 * @param CurrentProcess
140 * Optional pointer to the current CSR Process.
143 * Pointer to the CSR Process which is to be inserted.
152 CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL
,
153 IN PCSR_PROCESS CurrentProcess OPTIONAL
,
154 IN PCSR_PROCESS CsrProcess
)
156 PCSR_SERVER_DLL ServerDll
;
160 CsrProcess
->Parent
= Parent
;
162 /* Insert it into the Root List */
163 InsertTailList(&CsrRootProcess
->ListLink
, &CsrProcess
->ListLink
);
165 /* Notify the Server DLLs */
166 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
168 /* Get the current Server DLL */
169 ServerDll
= CsrLoadedServerDll
[i
];
171 /* Make sure it's valid and that it has callback */
172 if (ServerDll
&& ServerDll
->NewProcessCallback
)
174 (*ServerDll
->NewProcessCallback
)(CurrentProcess
, CsrProcess
);
180 * @name CsrLockedDereferenceProcess
182 * The CsrLockedDereferenceProcess dereferences a CSR Process while the
183 * Process Lock is already being held.
186 * Pointer to the CSR Process to be dereferenced.
190 * @remarks This routine will return with the Process Lock held.
195 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess
)
197 /* Decrease reference count */
198 if (!(--CsrProcess
->ReferenceCount
))
200 /* Call the generic cleanup code */
201 CsrAcquireProcessLock();
202 CsrProcessRefcountZero(CsrProcess
);
207 * @name CsrRemoveProcess
209 * The CsrRemoveProcess function undoes a CsrInsertProcess operation and
210 * removes the CSR Process from the Process List and notifies Server DLLs
214 * Pointer to the CSR Process to remove.
223 CsrRemoveProcess(IN PCSR_PROCESS CsrProcess
)
225 PCSR_SERVER_DLL ServerDll
;
228 /* Remove us from the Process List */
229 RemoveEntryList(&CsrProcess
->ListLink
);
231 /* Release the lock */
232 CsrReleaseProcessLock();
234 /* Loop every Server DLL */
235 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
237 /* Get the Server DLL */
238 ServerDll
= CsrLoadedServerDll
[i
];
240 /* Check if it's valid and if it has a Disconnect Callback */
241 if (ServerDll
&& ServerDll
->DisconnectCallback
)
244 (ServerDll
->DisconnectCallback
)(CsrProcess
);
250 * @name CsrProcessRefcountZero
252 * The CsrProcessRefcountZero routine is executed when a CSR Process has lost
253 * all its active references. It removes and de-allocates the CSR Process.
256 * Pointer to the CSR Process that is to be deleted.
260 * @remarks Do not call this routine. It is reserved for the internal
261 * thread management routines when a CSR Process has lost all
264 * This routine is called with the Process Lock held.
269 CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess
)
271 /* Remove the Process from the list */
272 CsrRemoveProcess(CsrProcess
);
274 /* Check if there's a session */
275 if (CsrProcess
->NtSession
)
277 /* Dereference the Session */
278 CsrDereferenceNtSession(CsrProcess
->NtSession
, 0);
281 /* Close the Client Port if there is one */
282 if (CsrProcess
->ClientPort
) NtClose(CsrProcess
->ClientPort
);
284 /* Close the process handle */
285 NtClose(CsrProcess
->ProcessHandle
);
287 /* Free the Proces Object */
288 CsrDeallocateProcess(CsrProcess
);
292 * @name CsrSetToNormalPriority
294 * The CsrSetToNormalPriority routine sets the current NT Process'
295 * priority to the normal priority for CSR Processes.
301 * @remarks The "Normal" Priority corresponds to the Normal Forground
302 * Priority (9) plus a boost of 4.
307 CsrSetToNormalPriority(VOID
)
309 KPRIORITY BasePriority
= (8 + 1) + 4;
311 /* Set the Priority */
312 NtSetInformationProcess(NtCurrentProcess(),
319 * @name CsrSetToShutdownPriority
321 * The CsrSetToShutdownPriority routine sets the current NT Process'
322 * priority to the boosted priority for CSR Processes doing shutdown.
323 * Additonally, it acquires the Shutdown Privilege required for shutdown.
329 * @remarks The "Shutdown" Priority corresponds to the Normal Forground
330 * Priority (9) plus a boost of 6.
335 CsrSetToShutdownPriority(VOID
)
337 KPRIORITY SetBasePriority
= (8 + 1) + 6;
340 /* Get the shutdown privilege */
341 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
346 /* Set the Priority */
347 NtSetInformationProcess(NtCurrentProcess(),
355 * @name FindProcessForShutdown
357 * The FindProcessForShutdown routine returns a CSR Process which is ready
358 * to be shutdown, and sets the appropriate shutdown flags for it.
361 * Pointer to the LUID of the CSR Process calling this routine.
363 * @return Pointer to a CSR Process which is ready to be shutdown.
370 FindProcessForShutdown(PLUID CallerLuid
)
372 PLIST_ENTRY ListHead
, NextEntry
;
375 LUID SystemLuid
= SYSTEM_LUID
;
376 PCSR_PROCESS CsrProcess
;
377 PCSR_THREAD CsrThread
;
378 BOOLEAN IsSystemLuid
= FALSE
, IsOurLuid
= FALSE
;
379 PCSR_PROCESS ReturnCsrProcess
= NULL
;
382 /* Set the List Pointers */
383 ListHead
= &CsrRootProcess
->ListLink
;
384 NextEntry
= ListHead
->Flink
;
387 while (NextEntry
!= ListHead
)
389 /* Get the process */
390 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
392 /* Move to the next entry */
393 NextEntry
= NextEntry
->Flink
;
395 /* Skip this process if it's already been processed*/
396 if (CsrProcess
->Flags
& CsrProcessSkipShutdown
) continue;
398 /* Get the LUID of this Process */
399 Status
= CsrGetProcessLuid(CsrProcess
->ProcessHandle
, &ProcessLuid
);
401 /* Check if we didn't get access to the LUID */
402 if (Status
== STATUS_ACCESS_DENIED
)
404 /* Check if we have any threads */
405 if (CsrProcess
->ThreadCount
)
407 /* Impersonate one of the threads and retry */
408 CsrThread
= CONTAINING_RECORD(CsrProcess
->ThreadList
.Flink
,
411 CsrImpersonateClient(CsrThread
);
412 Status
= CsrGetProcessLuid(NULL
, &ProcessLuid
);
417 if (!NT_SUCCESS(Status
))
419 /* We didn't have access, so skip it */
420 CsrProcess
->Flags
|= CsrProcessSkipShutdown
;
424 /* Check if this is the System LUID */
425 if ((IsSystemLuid
= RtlEqualLuid(&ProcessLuid
, &SystemLuid
)))
427 /* Mark this process */
428 CsrProcess
->ShutdownFlags
|= CsrShutdownSystem
;
430 else if (!(IsOurLuid
= RtlEqualLuid(&ProcessLuid
, CallerLuid
)))
432 /* Our LUID doesn't match with the caller's */
433 CsrProcess
->ShutdownFlags
|= CsrShutdownOther
;
436 /* Check if we're past the previous level */
437 if (CsrProcess
->ShutdownLevel
> Level
)
439 /* Update the level */
440 Level
= CsrProcess
->ShutdownLevel
;
442 /* Set the final process */
443 ReturnCsrProcess
= CsrProcess
;
447 /* Check if we found a process */
448 if (ReturnCsrProcess
)
450 /* Skip this one next time */
451 ReturnCsrProcess
->Flags
|= CsrProcessSkipShutdown
;
454 return ReturnCsrProcess
;
457 /* PUBLIC FUNCTIONS ***********************************************************/
460 * @name CsrCreateProcess
463 * Do nothing for 500ms.
465 * @param ArgumentCount
466 * Description of the parameter. Wrapped to more lines on ~70th
470 * Description of the parameter. Wrapped to more lines on ~70th
473 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
481 CsrCreateProcess(IN HANDLE hProcess
,
483 IN PCLIENT_ID ClientId
,
484 IN PCSR_NT_SESSION NtSession
,
486 IN PCLIENT_ID DebugCid
)
488 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
489 CLIENT_ID CurrentCid
;
490 PCSR_PROCESS CurrentProcess
;
493 PCSR_PROCESS CsrProcess
;
495 PCSR_THREAD CsrThread
;
496 KERNEL_USER_TIMES KernelTimes
;
498 /* Get the current CID and lock Processes */
499 CurrentCid
= CurrentThread
->ClientId
;
500 CsrAcquireProcessLock();
502 /* Get the current CSR Thread */
503 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
506 /* We've failed to locate the thread */
507 CsrReleaseProcessLock();
508 return STATUS_THREAD_IS_TERMINATING
;
511 /* Allocate a new Process Object */
512 if (!(CsrProcess
= CsrAllocateProcess()))
514 /* Couldn't allocate Process */
515 CsrReleaseProcessLock();
516 return STATUS_NO_MEMORY
;
519 /* Setup Process Data */
520 CsrProcess
->ClientId
= *ClientId
;
521 CsrProcess
->ProcessHandle
= hProcess
;
522 CsrProcess
->ShutdownLevel
= 0x280;
524 /* Inherit the Process Data */
525 ProcessData
= &CurrentProcess
->ServerData
[CSR_SERVER_DLL_MAX
];
526 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
528 /* Check if the DLL is Loaded and has Per Process Data */
529 if (CsrLoadedServerDll
[i
] && CsrLoadedServerDll
[i
]->SizeOfProcessData
)
531 /* Set the pointer */
532 CsrProcess
->ServerData
[i
] = ProcessData
;
535 RtlMoveMemory(ProcessData
,
536 CurrentProcess
->ServerData
[i
],
537 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
539 /* Update next data pointer */
540 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
541 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
545 /* No data for this Server */
546 CsrProcess
->ServerData
[i
] = NULL
;
550 /* Set the Exception port to us */
551 Status
= NtSetInformationProcess(hProcess
,
552 ProcessExceptionPort
,
555 if (!NT_SUCCESS(Status
))
558 CsrDeallocateProcess(CsrProcess
);
559 CsrReleaseProcessLock();
560 return STATUS_NO_MEMORY
;
563 /* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
564 if (!(Flags
& CsrProcessCreateNewGroup
))
566 /* Create new data */
567 CsrProcess
->ProcessGroupId
= HandleToUlong(ClientId
->UniqueProcess
);
568 CsrProcess
->ProcessGroupSequence
= CsrProcess
->SequenceNumber
;
572 /* Copy it from the current process */
573 CsrProcess
->ProcessGroupId
= CurrentProcess
->ProcessGroupId
;
574 CsrProcess
->ProcessGroupSequence
= CurrentProcess
->ProcessGroupSequence
;
577 /* Check if this is a console process */
578 if(Flags
& CsrProcessIsConsoleApp
) CsrProcess
->Flags
|= CsrProcessIsConsoleApp
;
580 /* Mask out non-debug flags */
581 Flags
&= ~(CsrProcessIsConsoleApp
| CsrProcessCreateNewGroup
);
583 /* Check if every process will be debugged */
584 if (!Flags
&& CurrentProcess
->DebugFlags
& CsrDebugProcessChildren
)
586 /* Pass it on to the current process */
587 CsrProcess
->DebugFlags
= CsrDebugProcessChildren
;
588 CsrProcess
->DebugCid
= CurrentProcess
->DebugCid
;
591 /* Check if Debugging was used on this process */
592 if (Flags
& (CsrDebugOnlyThisProcess
| CsrDebugProcessChildren
))
594 /* Save the debug flag used */
595 CsrProcess
->DebugFlags
= Flags
;
598 if (DebugCid
) CsrProcess
->DebugCid
= *DebugCid
;
601 /* Check if we debugging is enabled */
602 if (CsrProcess
->DebugFlags
)
604 /* Set the Debug Port to us */
605 Status
= NtSetInformationProcess(hProcess
,
609 if (!NT_SUCCESS(Status
))
612 CsrDeallocateProcess(CsrProcess
);
613 CsrReleaseProcessLock();
614 return STATUS_NO_MEMORY
;
618 /* Get the Thread Create Time */
619 Status
= NtQueryInformationThread(hThread
,
625 /* Allocate a CSR Thread Structure */
626 CsrThread
= CsrAllocateThread(CsrProcess
);
627 if (CsrThread
== NULL
)
630 CsrDeallocateProcess(CsrProcess
);
631 CsrReleaseProcessLock();
632 return STATUS_NO_MEMORY
;
635 /* Save the data we have */
636 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
637 CsrThread
->ClientId
= *ClientId
;
638 CsrThread
->ThreadHandle
= hThread
;
639 CsrThread
->Flags
= 0;
641 /* Insert the Thread into the Process */
642 CsrInsertThread(CsrProcess
, CsrThread
);
644 /* Reference the session */
645 CsrReferenceNtSession(NtSession
);
646 CsrProcess
->NtSession
= NtSession
;
648 /* Set the Priority to Background */
649 CsrSetBackgroundPriority(CsrProcess
);
651 /* Insert the Process */
652 CsrInsertProcess(NULL
, CurrentProcess
, CsrProcess
);
654 /* Release lock and return */
655 CsrReleaseProcessLock();
660 * @name CsrDebugProcess
663 * The CsrDebugProcess routine is deprecated in NT 5.1 and higher. It is
664 * exported only for compatibility with older CSR Server DLLs.
671 * @remarks Deprecated.
676 CsrDebugProcess(PCSR_PROCESS CsrProcess
)
678 /* CSR does not handle debugging anymore */
679 DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__
, CsrProcess
);
680 return STATUS_UNSUCCESSFUL
;
684 * @name CsrServerInitialization
687 * The CsrDebugProcessStop routine is deprecated in NT 5.1 and higher. It is
688 * exported only for compatibility with older CSR Server DLLs.
695 * @remarks Deprecated.
700 CsrDebugProcessStop(PCSR_PROCESS CsrProcess
)
702 /* CSR does not handle debugging anymore */
703 DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__
, CsrProcess
);
704 return STATUS_UNSUCCESSFUL
;
708 * @name CsrDereferenceProcess
711 * The CsrDereferenceProcess routine removes a reference from a CSR Process.
714 * Pointer to the CSR Process to dereference.
718 * @remarks If the reference count has reached zero (ie: the CSR Process has
719 * no more active references), it will be deleted.
724 CsrDereferenceProcess(PCSR_PROCESS CsrProcess
)
726 /* Acquire process lock */
727 CsrAcquireProcessLock();
729 /* Decrease reference count */
730 if (!(--CsrProcess
->ReferenceCount
))
732 /* Call the generic cleanup code */
733 CsrProcessRefcountZero(CsrProcess
);
737 /* Just release the lock */
738 CsrReleaseProcessLock();
743 * @name CsrDestroyProcess
746 * The CsrDestroyProcess routine destroys the CSR Process corresponding to
750 * Pointer to the Client ID Structure corresponding to the CSR
751 * Process which is about to be destroyed.
756 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
757 * if the CSR Process is already terminating.
764 CsrDestroyProcess(IN PCLIENT_ID Cid
,
765 IN NTSTATUS ExitStatus
)
767 PCSR_THREAD CsrThread
;
768 PCSR_PROCESS CsrProcess
;
769 CLIENT_ID ClientId
= *Cid
;
770 PLIST_ENTRY ListHead
, NextEntry
;
773 CsrAcquireProcessLock();
775 /* Find the thread */
776 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
779 /* Make sure we got one back, and that it's not already gone */
780 if (!CsrThread
|| CsrProcess
->Flags
& CsrProcessTerminating
)
782 /* Release the lock and return failure */
783 CsrReleaseProcessLock();
784 return STATUS_THREAD_IS_TERMINATING
;
787 /* Set the terminated flag */
788 CsrProcess
->Flags
|= CsrProcessTerminating
;
790 /* Get the List Pointers */
791 ListHead
= &CsrProcess
->ThreadList
;
792 NextEntry
= ListHead
->Flink
;
795 while (NextEntry
!= ListHead
)
797 /* Get the current thread entry */
798 CsrThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
800 /* Move to the next entry */
801 NextEntry
= NextEntry
->Flink
;
803 /* Make sure the thread isn't already dead */
804 if (CsrThread
->Flags
& CsrThreadTerminated
) continue;
806 /* Set the Terminated flag */
807 CsrThread
->Flags
|= CsrThreadTerminated
;
809 /* Acquire the Wait Lock */
810 CsrAcquireWaitLock();
812 /* Do we have an active wait block? */
813 if (CsrThread
->WaitBlock
)
815 /* Notify waiters of termination */
816 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
820 CsrProcessTerminating
,
824 /* Release the Wait Lock */
825 CsrReleaseWaitLock();
827 /* Dereference the thread */
828 CsrLockedDereferenceThread(CsrThread
);
831 /* Release the Process Lock and return success */
832 CsrReleaseProcessLock();
833 return STATUS_SUCCESS
;
837 * @name CsrGetProcessLuid
840 * Do nothing for 500ms.
843 * Optional handle to the process whose LUID should be returned.
846 * Pointer to a LUID Pointer which will receive the CSR Process' LUID
848 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
851 * @remarks If hProcess is not supplied, then the current thread's token will
852 * be used. If that too is missing, then the current process' token
858 CsrGetProcessLuid(HANDLE hProcess OPTIONAL
,
861 HANDLE hToken
= NULL
;
864 PTOKEN_STATISTICS TokenStats
;
866 /* Check if we have a handle to a CSR Process */
869 /* We don't, so try opening the Thread's Token */
870 Status
= NtOpenThreadToken(NtCurrentThread(),
875 /* Check for success */
876 if (!NT_SUCCESS(Status
))
878 /* If we got some other failure, then return and quit */
879 if (Status
!= STATUS_NO_TOKEN
) return Status
;
881 /* We don't have a Thread Token, use a Process Token */
882 hProcess
= NtCurrentProcess();
887 /* Check if we have a token by now */
890 /* No token yet, so open the Process Token */
891 Status
= NtOpenProcessToken(hProcess
,
894 if (!NT_SUCCESS(Status
))
896 /* Still no token, return the error */
901 /* Now get the size we'll need for the Token Information */
902 Status
= NtQueryInformationToken(hToken
,
908 /* Allocate memory for the Token Info */
909 if (!(TokenStats
= RtlAllocateHeap(CsrHeap
, 0, Length
)))
911 /* Fail and close the token */
913 return STATUS_NO_MEMORY
;
916 /* Now query the information */
917 Status
= NtQueryInformationToken(hToken
,
923 /* Close the handle */
926 /* Check for success */
927 if (NT_SUCCESS(Status
))
929 /* Return the LUID */
930 *Luid
= TokenStats
->AuthenticationId
;
933 /* Free the query information */
934 RtlFreeHeap(CsrHeap
, 0, TokenStats
);
936 /* Return the Status */
941 * @name CsrLockProcessByClientId
944 * The CsrLockProcessByClientId routine locks the CSR Process corresponding
945 * to the given Process ID and optionally returns it.
948 * Process ID corresponding to the CSR Process which will be locked.
951 * Optional pointer to a CSR Process pointer which will hold the
952 * CSR Process corresponding to the given Process ID.
954 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
957 * @remarks Locking a CSR Process is defined as acquiring an extra
958 * reference to it and returning with the Process Lock held.
963 CsrLockProcessByClientId(IN HANDLE Pid
,
964 OUT PCSR_PROCESS
*CsrProcess OPTIONAL
)
966 PLIST_ENTRY ListHead
, NextEntry
;
967 PCSR_PROCESS CurrentProcess
= NULL
;
968 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
970 /* Acquire the lock */
971 CsrAcquireProcessLock();
973 /* Setup the List Pointers */
974 ListHead
= &CsrRootProcess
->ListLink
;
975 NextEntry
= ListHead
;
978 while (NextEntry
!= ListHead
)
980 /* Get the Process */
981 CurrentProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
983 /* Check for PID Match */
984 if (CurrentProcess
->ClientId
.UniqueProcess
== Pid
)
986 /* Get out of here with success */
987 Status
= STATUS_SUCCESS
;
992 NextEntry
= NextEntry
->Flink
;
995 /* Did the loop find something? */
996 if (NT_SUCCESS(Status
))
998 /* Lock the found process */
999 CurrentProcess
->ReferenceCount
++;
1003 /* Nothing found, release the lock */
1004 CsrReleaseProcessLock();
1007 /* Return the status and process */
1008 if (CsrProcess
) *CsrProcess
= CurrentProcess
;
1013 * @name CsrSetForegroundPriority
1016 * The CsrSetForegroundPriority routine sets the priority for the given CSR
1017 * Process as a Foreground priority.
1020 * Pointer to the CSR Process whose priority will be modified.
1029 CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess
)
1031 PROCESS_PRIORITY_CLASS PriorityClass
;
1033 /* Set the Foreground bit on */
1034 PriorityClass
.Foreground
= TRUE
;
1036 /* Set the new Priority */
1037 NtSetInformationProcess(CsrProcess
->ProcessHandle
,
1038 ProcessPriorityClass
,
1040 sizeof(PriorityClass
));
1044 * @name CsrSetBackgroundPriority
1047 * The CsrSetBackgroundPriority routine sets the priority for the given CSR
1048 * Process as a Background priority.
1051 * Pointer to the CSR Process whose priority will be modified.
1060 CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess
)
1062 PROCESS_PRIORITY_CLASS PriorityClass
;
1064 /* Set the Foreground bit off */
1065 PriorityClass
.Foreground
= FALSE
;
1067 /* Set the new Priority */
1068 NtSetInformationProcess(CsrProcess
->ProcessHandle
,
1069 ProcessPriorityClass
,
1071 sizeof(PriorityClass
));
1075 * @name CsrShutdownProcesses
1078 * The CsrShutdownProcesses routine shuts down every CSR Process possible
1079 * and calls each Server DLL's shutdown notification.
1082 * Pointer to the LUID of the CSR Process that is ordering the
1086 * Flags to send to the shutdown notification routine.
1088 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1096 CsrShutdownProcesses(PLUID CallerLuid
,
1099 PLIST_ENTRY ListHead
, NextEntry
;
1100 PCSR_PROCESS CsrProcess
= NULL
;
1101 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
1102 BOOLEAN FirstTry
= TRUE
;
1104 PCSR_SERVER_DLL ServerDll
= NULL
;
1107 /* Acquire process lock */
1108 CsrAcquireProcessLock();
1110 /* Add shutdown flag */
1111 CsrRootProcess
->ShutdownFlags
|= CsrShutdownSystem
;
1113 /* Get the list pointers */
1114 ListHead
= &CsrRootProcess
->ListLink
;
1115 NextEntry
= ListHead
->Flink
;
1117 /* Start the loop */
1118 while (NextEntry
!= ListHead
)
1120 /* Get the Process */
1121 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
1123 /* Remove the skip flag, set shutdown flags to 0*/
1124 CsrProcess
->Flags
&= ~CsrProcessSkipShutdown
;
1125 CsrProcess
->ShutdownFlags
= 0;
1127 /* Move to the next */
1128 NextEntry
= NextEntry
->Flink
;
1131 /* Set shudown Priority */
1132 CsrSetToShutdownPriority();
1137 /* Find the next process to shutdown */
1138 if (!(CsrProcess
= FindProcessForShutdown(CallerLuid
)))
1141 CsrReleaseProcessLock();
1142 Status
= STATUS_SUCCESS
;
1146 /* Increase reference to process */
1147 CsrProcess
->ReferenceCount
++;
1150 /* Loop all the servers */
1151 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1153 /* Get the current server */
1154 ServerDll
= CsrLoadedServerDll
[i
];
1155 if (ServerDll
&& ServerDll
->ShutdownProcessCallback
)
1157 /* Release the lock, make the callback, and acquire it back */
1158 CsrReleaseProcessLock();
1159 Result
= (*ServerDll
->ShutdownProcessCallback
)(CsrProcess
,
1162 CsrAcquireProcessLock();
1164 /* Check the result */
1165 if (Result
== CsrShutdownCsrProcess
)
1167 /* The callback unlocked the process */
1170 else if (Result
== CsrShutdownNonCsrProcess
)
1172 /* A non-CSR process, the callback didn't touch it */
1175 else if (Result
== CsrShutdownCancelled
)
1177 /* Shutdown was cancelled, unlock and exit */
1178 CsrReleaseProcessLock();
1179 Status
= STATUS_CANCELLED
;
1185 /* No matches during the first try, so loop again */
1186 if (FirstTry
&& Result
== CsrShutdownNonCsrProcess
)
1192 /* We've reached the final loop here, so dereference */
1193 if (i
== CSR_SERVER_DLL_MAX
) CsrLockedDereferenceProcess(CsrProcess
);
1197 /* Return to normal priority */
1198 CsrSetToNormalPriority();
1203 * @name CsrUnlockProcess
1206 * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
1209 * Pointer to a previously locked CSR Process.
1211 * @return STATUS_SUCCESS.
1213 * @remarks This routine must be called with the Process Lock held.
1218 CsrUnlockProcess(PCSR_PROCESS CsrProcess
)
1220 /* Dereference the process */
1221 CsrLockedDereferenceProcess(CsrProcess
);
1223 /* Release the lock and return */
1224 CsrReleaseProcessLock();
1225 return STATUS_SUCCESS
;