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 *********************************************************/
29 * The ProtectHandle routine protects an object handle against closure.
31 * @return TRUE or FALSE.
38 ProtectHandle(IN HANDLE ObjectHandle
)
41 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
43 /* Query current state */
44 Status
= NtQueryObject(ObjectHandle
,
45 ObjectHandleFlagInformation
,
49 if (NT_SUCCESS(Status
))
51 /* Enable protect from close */
52 HandleInfo
.ProtectFromClose
= TRUE
;
53 Status
= NtSetInformationObject(ObjectHandle
,
54 ObjectHandleFlagInformation
,
57 if (NT_SUCCESS(Status
)) return TRUE
;
60 /* We failed to or set the state */
65 * @name UnProtectHandle
68 * The UnProtectHandle routine unprotects an object handle against closure.
70 * @return TRUE or FALSE.
77 UnProtectHandle(IN HANDLE ObjectHandle
)
80 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo
;
82 /* Query current state */
83 Status
= NtQueryObject(ObjectHandle
,
84 ObjectHandleFlagInformation
,
88 if (NT_SUCCESS(Status
))
90 /* Disable protect from close */
91 HandleInfo
.ProtectFromClose
= FALSE
;
92 Status
= NtSetInformationObject(ObjectHandle
,
93 ObjectHandleFlagInformation
,
96 if (NT_SUCCESS(Status
)) return TRUE
;
99 /* We failed to or set the state */
104 * @name CsrAllocateProcess
107 * The CsrAllocateProcess routine allocates a new CSR Process object.
109 * @return Pointer to the newly allocated CSR Process.
116 CsrAllocateProcess(VOID
)
118 PCSR_PROCESS CsrProcess
;
121 /* Calculate the amount of memory this should take */
122 TotalSize
= sizeof(CSR_PROCESS
) +
123 (CSR_SERVER_DLL_MAX
* sizeof(PVOID
)) +
124 CsrTotalPerProcessDataLength
;
126 /* Allocate a Process */
127 CsrProcess
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, TotalSize
);
128 if (!CsrProcess
) return NULL
;
130 /* Handle the Sequence Number and protect against overflow */
131 CsrProcess
->SequenceNumber
= CsrProcessSequenceCount
++;
132 if (CsrProcessSequenceCount
< 5) CsrProcessSequenceCount
= 5;
134 /* Increase the reference count */
135 CsrProcess
->ReferenceCount
++;
137 /* Initialize the Thread List */
138 InitializeListHead(&CsrProcess
->ThreadList
);
140 /* Return the Process */
145 * @name CsrServerInitialization
148 * The CsrInitializeProcessStructure routine sets up support for CSR Processes
153 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
161 CsrInitializeProcessStructure(VOID
)
166 /* Initialize the Lock */
167 Status
= RtlInitializeCriticalSection(&CsrProcessLock
);
168 if (!NT_SUCCESS(Status
)) return Status
;
170 /* Set up the Root Process */
171 CsrRootProcess
= CsrAllocateProcess();
172 if (!CsrRootProcess
) return STATUS_NO_MEMORY
;
174 /* Set up the minimal information for it */
175 InitializeListHead(&CsrRootProcess
->ListLink
);
176 CsrRootProcess
->ProcessHandle
= (HANDLE
)-1;
177 CsrRootProcess
->ClientId
= NtCurrentTeb()->ClientId
;
179 /* Initialize the Thread Hash List */
180 for (i
= 0; i
< 256; i
++) InitializeListHead(&CsrThreadHashTable
[i
]);
182 /* Initialize the Wait Lock */
183 return RtlInitializeCriticalSection(&CsrWaitListsLock
);
187 * @name CsrDeallocateProcess
189 * The CsrDeallocateProcess frees the memory associated with a CSR Process.
192 * Pointer to the CSR Process to be freed.
196 * @remarks Do not call this routine. It is reserved for the internal
197 * thread management routines when a CSR Process has been cleanly
198 * dereferenced and killed.
203 CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess
)
205 /* Free the process object from the heap */
206 RtlFreeHeap(CsrHeap
, 0, CsrProcess
);
210 * @name CsrInsertProcess
212 * The CsrInsertProcess routine inserts a CSR Process into the Process List
213 * and notifies Server DLLs of the creation of a new CSR Process.
216 * Optional pointer to the CSR Process creating this CSR Process.
218 * @param CurrentProcess
219 * Optional pointer to the current CSR Process.
222 * Pointer to the CSR Process which is to be inserted.
231 CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL
,
232 IN PCSR_PROCESS CurrentProcess OPTIONAL
,
233 IN PCSR_PROCESS CsrProcess
)
235 PCSR_SERVER_DLL ServerDll
;
237 ASSERT(ProcessStructureListLocked());
240 CsrProcess
->Parent
= Parent
;
242 /* Insert it into the Root List */
243 InsertTailList(&CsrRootProcess
->ListLink
, &CsrProcess
->ListLink
);
245 /* Notify the Server DLLs */
246 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
248 /* Get the current Server DLL */
249 ServerDll
= CsrLoadedServerDll
[i
];
251 /* Make sure it's valid and that it has callback */
252 if ((ServerDll
) && (ServerDll
->NewProcessCallback
))
254 ServerDll
->NewProcessCallback(CurrentProcess
, CsrProcess
);
260 * @name CsrLockedDereferenceProcess
262 * The CsrLockedDereferenceProcess dereferences a CSR Process while the
263 * Process Lock is already being held.
266 * Pointer to the CSR Process to be dereferenced.
270 * @remarks This routine will return with the Process Lock held.
275 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess
)
279 /* Decrease reference count */
280 LockCount
= --CsrProcess
->ReferenceCount
;
281 ASSERT(LockCount
>= 0);
284 /* Call the generic cleanup code */
285 CsrProcessRefcountZero(CsrProcess
);
286 CsrAcquireProcessLock();
291 * @name CsrLockedReferenceProcess
293 * The CsrLockedReferenceProcess refences a CSR Process while the
294 * Process Lock is already being held.
297 * Pointer to the CSR Process to be referenced.
301 * @remarks This routine will return with the Process Lock held.
306 CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess
)
308 /* Increment the reference count */
309 ++CsrProcess
->ReferenceCount
;
313 * @name CsrRemoveProcess
315 * The CsrRemoveProcess function undoes a CsrInsertProcess operation and
316 * removes the CSR Process from the Process List and notifies Server DLLs
320 * Pointer to the CSR Process to remove.
329 CsrRemoveProcess(IN PCSR_PROCESS CsrProcess
)
331 PCSR_SERVER_DLL ServerDll
;
333 ASSERT(ProcessStructureListLocked());
335 /* Remove us from the Process List */
336 RemoveEntryList(&CsrProcess
->ListLink
);
338 /* Release the lock */
339 CsrReleaseProcessLock();
341 /* Loop every Server DLL */
342 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
344 /* Get the Server DLL */
345 ServerDll
= CsrLoadedServerDll
[i
];
347 /* Check if it's valid and if it has a Disconnect Callback */
348 if ((ServerDll
) && (ServerDll
->DisconnectCallback
))
351 ServerDll
->DisconnectCallback(CsrProcess
);
357 * @name CsrProcessRefcountZero
359 * The CsrProcessRefcountZero routine is executed when a CSR Process has lost
360 * all its active references. It removes and de-allocates the CSR Process.
363 * Pointer to the CSR Process that is to be deleted.
367 * @remarks Do not call this routine. It is reserved for the internal
368 * thread management routines when a CSR Process has lost all
371 * This routine is called with the Process Lock held.
376 CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess
)
378 /* Remove the Process from the list */
379 CsrRemoveProcess(CsrProcess
);
381 /* Check if there's a session */
382 if (CsrProcess
->NtSession
)
384 /* Dereference the Session */
385 CsrDereferenceNtSession(CsrProcess
->NtSession
, 0);
388 /* Close the Client Port if there is one */
389 if (CsrProcess
->ClientPort
) NtClose(CsrProcess
->ClientPort
);
391 /* Close the process handle */
392 NtClose(CsrProcess
->ProcessHandle
);
394 /* Free the Proces Object */
395 CsrDeallocateProcess(CsrProcess
);
399 * @name CsrpSetToNormalPriority
401 * The CsrpSetToNormalPriority routine sets the current NT Process'
402 * priority to the normal priority for CSR Processes.
408 * @remarks The "Normal" Priority corresponds to the Normal Forground
409 * Priority (9) plus a boost of 4.
414 CsrpSetToNormalPriority(VOID
)
416 KPRIORITY BasePriority
= (8 + 1) + 4;
418 /* Set the Priority */
419 NtSetInformationProcess(NtCurrentProcess(),
426 * @name CsrpSetToShutdownPriority
428 * The CsrpSetToShutdownPriority routine sets the current NT Process'
429 * priority to the boosted priority for CSR Processes doing shutdown.
430 * Additonally, it acquires the Shutdown Privilege required for shutdown.
436 * @remarks The "Shutdown" Priority corresponds to the Normal Forground
437 * Priority (9) plus a boost of 6.
442 CsrpSetToShutdownPriority(VOID
)
444 KPRIORITY SetBasePriority
= (8 + 1) + 6;
447 /* Get the shutdown privilege */
448 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
453 /* Set the Priority */
454 NtSetInformationProcess(NtCurrentProcess(),
462 * @name FindProcessForShutdown
464 * The FindProcessForShutdown routine returns a CSR Process which is ready
465 * to be shutdown, and sets the appropriate shutdown flags for it.
468 * Pointer to the LUID of the CSR Process calling this routine.
470 * @return Pointer to a CSR Process which is ready to be shutdown.
477 FindProcessForShutdown(IN PLUID CallerLuid
)
479 PLIST_ENTRY NextEntry
;
482 LUID SystemLuid
= SYSTEM_LUID
;
483 PCSR_PROCESS CsrProcess
;
484 PCSR_THREAD CsrThread
;
485 PCSR_PROCESS ReturnCsrProcess
= NULL
;
488 /* Set the List Pointers */
489 NextEntry
= CsrRootProcess
->ListLink
.Flink
;
490 while (NextEntry
!= &CsrRootProcess
->ListLink
)
492 /* Get the process */
493 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
495 /* Move to the next entry */
496 NextEntry
= NextEntry
->Flink
;
498 /* Skip this process if it's already been processed*/
499 if (CsrProcess
->Flags
& CsrProcessSkipShutdown
) continue;
501 /* Get the LUID of this Process */
502 Status
= CsrGetProcessLuid(CsrProcess
->ProcessHandle
, &ProcessLuid
);
504 /* Check if we didn't get access to the LUID */
505 if (Status
== STATUS_ACCESS_DENIED
)
507 /* Check if we have any threads */
508 if (CsrProcess
->ThreadCount
)
510 /* Impersonate one of the threads and retry */
511 CsrThread
= CONTAINING_RECORD(CsrProcess
->ThreadList
.Flink
,
514 CsrImpersonateClient(CsrThread
);
515 Status
= CsrGetProcessLuid(NULL
, &ProcessLuid
);
520 if (!NT_SUCCESS(Status
))
522 /* We didn't have access, so skip it */
523 CsrProcess
->Flags
|= CsrProcessSkipShutdown
;
527 /* Check if this is the System LUID */
528 if (RtlEqualLuid(&ProcessLuid
, &SystemLuid
))
530 /* Mark this process */
531 CsrProcess
->ShutdownFlags
|= CsrShutdownSystem
;
533 else if (!RtlEqualLuid(&ProcessLuid
, CallerLuid
))
535 /* Our LUID doesn't match with the caller's */
536 CsrProcess
->ShutdownFlags
|= CsrShutdownOther
;
539 /* Check if we're past the previous level */
540 if ((CsrProcess
->ShutdownLevel
> Level
) || !(ReturnCsrProcess
))
542 /* Update the level */
543 Level
= CsrProcess
->ShutdownLevel
;
545 /* Set the final process */
546 ReturnCsrProcess
= CsrProcess
;
550 /* Check if we found a process */
551 if (ReturnCsrProcess
)
553 /* Skip this one next time */
554 ReturnCsrProcess
->Flags
|= CsrProcessSkipShutdown
;
557 return ReturnCsrProcess
;
560 /* PUBLIC FUNCTIONS ***********************************************************/
563 * @name CsrCreateProcess
566 * Do nothing for 500ms.
568 * @param ArgumentCount
569 * Description of the parameter. Wrapped to more lines on ~70th
573 * Description of the parameter. Wrapped to more lines on ~70th
576 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
584 CsrCreateProcess(IN HANDLE hProcess
,
586 IN PCLIENT_ID ClientId
,
587 IN PCSR_NT_SESSION NtSession
,
589 IN PCLIENT_ID DebugCid
)
591 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
592 CLIENT_ID CurrentCid
;
593 PCSR_PROCESS CurrentProcess
;
596 PCSR_PROCESS CsrProcess
;
598 PCSR_THREAD CsrThread
;
599 KERNEL_USER_TIMES KernelTimes
;
601 /* Get the current CID and lock Processes */
602 CurrentCid
= CurrentThread
->ClientId
;
603 CsrAcquireProcessLock();
605 /* Get the current CSR Thread */
606 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
609 /* We've failed to locate the thread */
610 CsrReleaseProcessLock();
611 return STATUS_THREAD_IS_TERMINATING
;
614 /* Allocate a new Process Object */
615 CsrProcess
= CsrAllocateProcess();
618 /* Couldn't allocate Process */
619 CsrReleaseProcessLock();
620 return STATUS_NO_MEMORY
;
623 /* Inherit the Process Data */
624 CurrentProcess
= CurrentThread
->Process
;
625 ProcessData
= &CurrentProcess
->ServerData
[CSR_SERVER_DLL_MAX
];
626 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
628 /* Check if the DLL is Loaded and has Per Process Data */
629 if (CsrLoadedServerDll
[i
] && CsrLoadedServerDll
[i
]->SizeOfProcessData
)
631 /* Set the pointer */
632 CsrProcess
->ServerData
[i
] = ProcessData
;
635 RtlMoveMemory(ProcessData
,
636 CurrentProcess
->ServerData
[i
],
637 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
639 /* Update next data pointer */
640 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
641 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
645 /* No data for this Server */
646 CsrProcess
->ServerData
[i
] = NULL
;
650 /* Set the Exception port to us */
651 Status
= NtSetInformationProcess(hProcess
,
652 ProcessExceptionPort
,
655 if (!NT_SUCCESS(Status
))
658 CsrDeallocateProcess(CsrProcess
);
659 CsrReleaseProcessLock();
660 return STATUS_NO_MEMORY
;
663 /* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
664 if (!(Flags
& CsrProcessCreateNewGroup
))
666 /* Create new data */
667 CsrProcess
->ProcessGroupId
= HandleToUlong(ClientId
->UniqueProcess
);
668 CsrProcess
->ProcessGroupSequence
= CsrProcess
->SequenceNumber
;
672 /* Copy it from the current process */
673 CsrProcess
->ProcessGroupId
= CurrentProcess
->ProcessGroupId
;
674 CsrProcess
->ProcessGroupSequence
= CurrentProcess
->ProcessGroupSequence
;
677 /* Check if this is a console process */
678 if (Flags
& CsrProcessIsConsoleApp
) CsrProcess
->Flags
|= CsrProcessIsConsoleApp
;
680 /* Mask out non-debug flags */
681 Flags
&= ~(CsrProcessIsConsoleApp
| CsrProcessCreateNewGroup
| CsrProcessPriorityFlags
);
683 /* Check if every process will be debugged */
684 if (!(Flags
) && (CurrentProcess
->DebugFlags
& CsrDebugProcessChildren
))
686 /* Pass it on to the current process */
687 CsrProcess
->DebugFlags
= CsrDebugProcessChildren
;
688 CsrProcess
->DebugCid
= CurrentProcess
->DebugCid
;
691 /* Check if Debugging was used on this process */
692 if ((Flags
& (CsrDebugOnlyThisProcess
| CsrDebugProcessChildren
)) && (DebugCid
))
694 /* Save the debug flag used */
695 CsrProcess
->DebugFlags
= Flags
;
698 CsrProcess
->DebugCid
= *DebugCid
;
701 /* Check if we debugging is enabled */
702 if (CsrProcess
->DebugFlags
)
704 /* Set the Debug Port to us */
705 Status
= NtSetInformationProcess(hProcess
,
709 ASSERT(NT_SUCCESS(Status
));
710 if (!NT_SUCCESS(Status
))
713 CsrDeallocateProcess(CsrProcess
);
714 CsrReleaseProcessLock();
715 return STATUS_NO_MEMORY
;
719 /* Get the Thread Create Time */
720 Status
= NtQueryInformationThread(hThread
,
725 if (!NT_SUCCESS(Status
))
728 CsrDeallocateProcess(CsrProcess
);
729 CsrReleaseProcessLock();
730 return STATUS_NO_MEMORY
;
733 /* Allocate a CSR Thread Structure */
734 CsrThread
= CsrAllocateThread(CsrProcess
);
738 CsrDeallocateProcess(CsrProcess
);
739 CsrReleaseProcessLock();
740 return STATUS_NO_MEMORY
;
743 /* Save the data we have */
744 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
745 CsrThread
->ClientId
= *ClientId
;
746 CsrThread
->ThreadHandle
= hThread
;
747 ProtectHandle(hThread
);
748 CsrThread
->Flags
= 0;
750 /* Insert the Thread into the Process */
751 CsrInsertThread(CsrProcess
, CsrThread
);
753 /* Reference the session */
754 CsrReferenceNtSession(NtSession
);
755 CsrProcess
->NtSession
= NtSession
;
757 /* Setup Process Data */
758 CsrProcess
->ClientId
= *ClientId
;
759 CsrProcess
->ProcessHandle
= hProcess
;
760 CsrProcess
->ShutdownLevel
= 0x280;
762 /* Set the Priority to Background */
763 CsrSetBackgroundPriority(CsrProcess
);
765 /* Insert the Process */
766 CsrInsertProcess(NULL
, CurrentProcess
, CsrProcess
);
768 /* Release lock and return */
769 CsrReleaseProcessLock();
774 * @name CsrDebugProcess
777 * The CsrDebugProcess routine is deprecated in NT 5.1 and higher. It is
778 * exported only for compatibility with older CSR Server DLLs.
785 * @remarks Deprecated.
790 CsrDebugProcess(IN PCSR_PROCESS CsrProcess
)
792 /* CSR does not handle debugging anymore */
793 DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__
, CsrProcess
);
794 return STATUS_UNSUCCESSFUL
;
798 * @name CsrServerInitialization
801 * The CsrDebugProcessStop routine is deprecated in NT 5.1 and higher. It is
802 * exported only for compatibility with older CSR Server DLLs.
809 * @remarks Deprecated.
814 CsrDebugProcessStop(IN PCSR_PROCESS CsrProcess
)
816 /* CSR does not handle debugging anymore */
817 DPRINT("CSRSRV: %s(%08lx) called\n", __FUNCTION__
, CsrProcess
);
818 return STATUS_UNSUCCESSFUL
;
822 * @name CsrDereferenceProcess
825 * The CsrDereferenceProcess routine removes a reference from a CSR Process.
828 * Pointer to the CSR Process to dereference.
832 * @remarks If the reference count has reached zero (ie: the CSR Process has
833 * no more active references), it will be deleted.
838 CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess
)
842 /* Acquire process lock */
843 CsrAcquireProcessLock();
845 /* Decrease reference count */
846 LockCount
= --CsrProcess
->ReferenceCount
;
847 ASSERT(LockCount
>= 0);
850 /* Call the generic cleanup code */
851 CsrProcessRefcountZero(CsrProcess
);
855 /* Just release the lock */
856 CsrReleaseProcessLock();
861 * @name CsrDestroyProcess
864 * The CsrDestroyProcess routine destroys the CSR Process corresponding to
868 * Pointer to the Client ID Structure corresponding to the CSR
869 * Process which is about to be destroyed.
874 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
875 * if the CSR Process is already terminating.
882 CsrDestroyProcess(IN PCLIENT_ID Cid
,
883 IN NTSTATUS ExitStatus
)
885 PCSR_THREAD CsrThread
;
886 PCSR_PROCESS CsrProcess
;
887 CLIENT_ID ClientId
= *Cid
;
888 PLIST_ENTRY NextEntry
;
891 CsrAcquireProcessLock();
893 /* Find the thread */
894 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
, &ClientId
);
896 /* Make sure we got one back, and that it's not already gone */
897 if (!(CsrThread
) || (CsrProcess
->Flags
& CsrProcessTerminating
))
899 /* Release the lock and return failure */
900 CsrReleaseProcessLock();
901 return STATUS_THREAD_IS_TERMINATING
;
904 /* Set the terminated flag */
905 CsrProcess
->Flags
|= CsrProcessTerminating
;
907 /* Get the List Pointers */
908 NextEntry
= CsrProcess
->ThreadList
.Flink
;
909 while (NextEntry
!= &CsrProcess
->ThreadList
)
911 /* Get the current thread entry */
912 CsrThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
914 /* Make sure the thread isn't already dead */
915 if (CsrThread
->Flags
& CsrThreadTerminated
)
917 NextEntry
= NextEntry
->Flink
;
921 /* Set the Terminated flag */
922 CsrThread
->Flags
|= CsrThreadTerminated
;
924 /* Acquire the Wait Lock */
925 CsrAcquireWaitLock();
927 /* Do we have an active wait block? */
928 if (CsrThread
->WaitBlock
)
930 /* Notify waiters of termination */
931 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
935 CsrProcessTerminating
,
939 /* Release the Wait Lock */
940 CsrReleaseWaitLock();
942 /* Dereference the thread */
943 CsrLockedDereferenceThread(CsrThread
);
944 NextEntry
= CsrProcess
->ThreadList
.Flink
;
947 /* Release the Process Lock and return success */
948 CsrReleaseProcessLock();
949 return STATUS_SUCCESS
;
953 * @name CsrGetProcessLuid
956 * Do nothing for 500ms.
959 * Optional handle to the process whose LUID should be returned.
962 * Pointer to a LUID Pointer which will receive the CSR Process' LUID
964 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
967 * @remarks If hProcess is not supplied, then the current thread's token will
968 * be used. If that too is missing, then the current process' token
974 CsrGetProcessLuid(HANDLE hProcess OPTIONAL
,
977 HANDLE hToken
= NULL
;
980 PTOKEN_STATISTICS TokenStats
;
982 /* Check if we have a handle to a CSR Process */
985 /* We don't, so try opening the Thread's Token */
986 Status
= NtOpenThreadToken(NtCurrentThread(),
991 /* Check for success */
992 if (!NT_SUCCESS(Status
))
994 /* If we got some other failure, then return and quit */
995 if (Status
!= STATUS_NO_TOKEN
) return Status
;
997 /* We don't have a Thread Token, use a Process Token */
998 hProcess
= NtCurrentProcess();
1003 /* Check if we have a token by now */
1006 /* No token yet, so open the Process Token */
1007 Status
= NtOpenProcessToken(hProcess
,
1010 if (!NT_SUCCESS(Status
)) return Status
;
1013 /* Now get the size we'll need for the Token Information */
1014 Status
= NtQueryInformationToken(hToken
,
1020 /* Allocate memory for the Token Info */
1021 TokenStats
= RtlAllocateHeap(CsrHeap
, 0, Length
);
1024 /* Fail and close the token */
1026 return STATUS_NO_MEMORY
;
1029 /* Now query the information */
1030 Status
= NtQueryInformationToken(hToken
,
1036 /* Close the handle */
1039 /* Check for success to return the LUID */
1040 if (NT_SUCCESS(Status
)) *Luid
= TokenStats
->AuthenticationId
;
1042 /* Free the query information */
1043 RtlFreeHeap(CsrHeap
, 0, TokenStats
);
1045 /* Return the Status */
1050 * @name CsrLockProcessByClientId
1053 * The CsrLockProcessByClientId routine locks the CSR Process corresponding
1054 * to the given Process ID and optionally returns it.
1057 * Process ID corresponding to the CSR Process which will be locked.
1060 * Optional pointer to a CSR Process pointer which will hold the
1061 * CSR Process corresponding to the given Process ID.
1063 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1066 * @remarks Locking a CSR Process is defined as acquiring an extra
1067 * reference to it and returning with the Process Lock held.
1072 CsrLockProcessByClientId(IN HANDLE Pid
,
1073 OUT PCSR_PROCESS
*CsrProcess
)
1075 PLIST_ENTRY NextEntry
;
1076 PCSR_PROCESS CurrentProcess
= NULL
;
1079 /* Acquire the lock */
1080 CsrAcquireProcessLock();
1082 /* Assume failure */
1083 ASSERT(CsrProcess
!= NULL
);
1086 /* Setup the List Pointers */
1087 NextEntry
= &CsrRootProcess
->ListLink
;
1090 /* Get the Process */
1091 CurrentProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
1093 /* Check for PID Match */
1094 if (CurrentProcess
->ClientId
.UniqueProcess
== Pid
)
1096 Status
= STATUS_SUCCESS
;
1101 NextEntry
= NextEntry
->Flink
;
1102 } while (NextEntry
!= &CsrRootProcess
->ListLink
);
1104 /* Check if we didn't find it in the list */
1105 if (!NT_SUCCESS(Status
))
1107 /* Nothing found, release the lock */
1108 CsrReleaseProcessLock();
1112 /* Lock the found process and return it */
1113 CsrLockedReferenceProcess(CurrentProcess
);
1114 *CsrProcess
= CurrentProcess
;
1117 /* Return the result */
1122 * @name CsrSetForegroundPriority
1125 * The CsrSetForegroundPriority routine sets the priority for the given CSR
1126 * Process as a Foreground priority.
1129 * Pointer to the CSR Process whose priority will be modified.
1138 CsrSetForegroundPriority(IN PCSR_PROCESS CsrProcess
)
1140 PROCESS_PRIORITY_CLASS PriorityClass
;
1142 /* Set the Foreground bit on */
1143 PriorityClass
.Foreground
= TRUE
;
1145 /* Set the new Priority */
1146 NtSetInformationProcess(CsrProcess
->ProcessHandle
,
1147 ProcessPriorityClass
,
1149 sizeof(PriorityClass
));
1153 * @name CsrSetBackgroundPriority
1156 * The CsrSetBackgroundPriority routine sets the priority for the given CSR
1157 * Process as a Background priority.
1160 * Pointer to the CSR Process whose priority will be modified.
1169 CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess
)
1171 PROCESS_PRIORITY_CLASS PriorityClass
;
1173 /* Set the Foreground bit off */
1174 PriorityClass
.Foreground
= FALSE
;
1176 /* Set the new Priority */
1177 NtSetInformationProcess(CsrProcess
->ProcessHandle
,
1178 ProcessPriorityClass
,
1180 sizeof(PriorityClass
));
1184 * @name CsrShutdownProcesses
1187 * The CsrShutdownProcesses routine shuts down every CSR Process possible
1188 * and calls each Server DLL's shutdown notification.
1191 * Pointer to the LUID of the CSR Process that is ordering the
1195 * Flags to send to the shutdown notification routine.
1197 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1205 CsrShutdownProcesses(IN PLUID CallerLuid
,
1208 PLIST_ENTRY NextEntry
;
1209 PCSR_PROCESS CsrProcess
;
1213 PCSR_SERVER_DLL ServerDll
;
1214 ULONG Result
= 0; /* Intentionally invalid enumeratee to silence compiler warning */
1216 /* Acquire process lock */
1217 CsrAcquireProcessLock();
1219 /* Add shutdown flag */
1220 CsrRootProcess
->ShutdownFlags
|= CsrShutdownSystem
;
1222 /* Get the list pointers */
1223 NextEntry
= CsrRootProcess
->ListLink
.Flink
;
1224 while (NextEntry
!= &CsrRootProcess
->ListLink
)
1226 /* Get the Process */
1227 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
1229 /* Remove the skip flag, set shutdown flags to 0*/
1230 CsrProcess
->Flags
&= ~CsrProcessSkipShutdown
;
1231 CsrProcess
->ShutdownFlags
= 0;
1233 /* Move to the next */
1234 NextEntry
= NextEntry
->Flink
;
1237 /* Set shudown Priority */
1238 CsrpSetToShutdownPriority();
1243 /* Find the next process to shutdown */
1244 CsrProcess
= FindProcessForShutdown(CallerLuid
);
1245 if (!CsrProcess
) break;
1247 /* Increase reference to process */
1248 CsrProcess
->ReferenceCount
++;
1253 /* Loop all the servers */
1254 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1256 /* Get the current server */
1257 ServerDll
= CsrLoadedServerDll
[i
];
1258 if ((ServerDll
) && (ServerDll
->ShutdownProcessCallback
))
1260 /* Release the lock, make the callback, and acquire it back */
1261 CsrReleaseProcessLock();
1262 Result
= ServerDll
->ShutdownProcessCallback(CsrProcess
,
1265 CsrAcquireProcessLock();
1267 /* Check the result */
1268 if (Result
== CsrShutdownCsrProcess
)
1270 /* The callback unlocked the process */
1273 else if (Result
== CsrShutdownCancelled
)
1275 /* Check if this was a forced shutdown */
1276 if (Flags
& EWX_FORCE
)
1278 DPRINT1("Process %x cancelled forced shutdown (Dll = %d)\n",
1279 CsrProcess
->ClientId
.UniqueProcess
, i
);
1283 /* Shutdown was cancelled, unlock and exit */
1284 CsrReleaseProcessLock();
1285 Status
= STATUS_CANCELLED
;
1291 /* No matches during the first try, so loop again */
1292 if ((FirstTry
) && (Result
== CsrShutdownNonCsrProcess
))
1298 /* Second try, break out */
1302 /* We've reached the final loop here, so dereference */
1303 if (i
== CSR_SERVER_DLL_MAX
) CsrLockedDereferenceProcess(CsrProcess
);
1307 CsrReleaseProcessLock();
1308 Status
= STATUS_SUCCESS
;
1311 /* Return to normal priority */
1312 CsrpSetToNormalPriority();
1317 * @name CsrUnlockProcess
1320 * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
1323 * Pointer to a previously locked CSR Process.
1325 * @return STATUS_SUCCESS.
1327 * @remarks This routine must be called with the Process Lock held.
1332 CsrUnlockProcess(IN PCSR_PROCESS CsrProcess
)
1334 /* Dereference the process */
1335 CsrLockedDereferenceProcess(CsrProcess
);
1337 /* Release the lock and return */
1338 CsrReleaseProcessLock();
1339 return STATUS_SUCCESS
;