2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsystems/win32/csrss/csrsrv/procsup.c
5 * PURPOSE: CSR Process Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
10 /* INCLUDES *******************************************************************/
17 /* GLOBALS ********************************************************************/
19 RTL_CRITICAL_SECTION ProcessDataLock
;
20 PCSR_PROCESS CsrRootProcess
= NULL
;
21 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos
=
23 sizeof(SECURITY_QUALITY_OF_SERVICE
),
24 SecurityImpersonation
,
25 SECURITY_STATIC_TRACKING
,
28 ULONG CsrProcessSequenceCount
= 5;
29 extern ULONG CsrTotalPerProcessDataLength
;
31 /* FUNCTIONS ******************************************************************/
35 CsrSetToNormalPriority(VOID
)
37 KPRIORITY BasePriority
= (8 + 1) + 4;
39 /* Set the Priority */
40 NtSetInformationProcess(NtCurrentProcess(),
48 CsrSetToShutdownPriority(VOID
)
50 KPRIORITY SetBasePriority
= (8 + 1) + 6;
53 /* Get the shutdown privilege */
54 if (NT_SUCCESS(RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE
,
59 /* Set the Priority */
60 NtSetInformationProcess(NtCurrentProcess(),
68 * @name CsrGetProcessLuid
71 * Do nothing for 500ms.
74 * Optional handle to the process whose LUID should be returned.
77 * Pointer to a LUID Pointer which will receive the CSR Process' LUID
79 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
82 * @remarks If hProcess is not supplied, then the current thread's token will
83 * be used. If that too is missing, then the current process' token
89 CsrGetProcessLuid(HANDLE hProcess OPTIONAL
,
95 PTOKEN_STATISTICS TokenStats
;
97 /* Check if we have a handle to a CSR Process */
100 /* We don't, so try opening the Thread's Token */
101 Status
= NtOpenThreadToken(NtCurrentThread(),
106 /* Check for success */
107 if (!NT_SUCCESS(Status
))
109 /* If we got some other failure, then return and quit */
110 if (Status
!= STATUS_NO_TOKEN
) return Status
;
112 /* We don't have a Thread Token, use a Process Token */
113 hProcess
= NtCurrentProcess();
118 /* Check if we have a token by now */
121 /* No token yet, so open the Process Token */
122 Status
= NtOpenProcessToken(hProcess
,
125 if (!NT_SUCCESS(Status
))
127 /* Still no token, return the error */
132 /* Now get the size we'll need for the Token Information */
133 Status
= NtQueryInformationToken(hToken
,
139 /* Allocate memory for the Token Info */
140 if (!(TokenStats
= RtlAllocateHeap(CsrHeap
, 0, Length
)))
142 /* Fail and close the token */
144 return STATUS_NO_MEMORY
;
147 /* Now query the information */
148 Status
= NtQueryInformationToken(hToken
,
154 /* Close the handle */
157 /* Check for success */
158 if (NT_SUCCESS(Status
))
160 /* Return the LUID */
161 *Luid
= TokenStats
->AuthenticationId
;
164 /* Free the query information */
165 RtlFreeHeap(CsrHeap
, 0, TokenStats
);
167 /* Return the Status */
172 * @name CsrImpersonateClient
175 * The CsrImpersonateClient will impersonate the given CSR Thread.
178 * Pointer to the CSR Thread to impersonate.
180 * @return TRUE if impersionation suceeded, false otherwise.
182 * @remarks Impersonation can be recursive.
187 CsrImpersonateClient(IN PCSR_THREAD CsrThread
)
190 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
192 /* Use the current thread if none given */
193 if (!CsrThread
) CsrThread
= CurrentThread
;
195 /* Still no thread, something is wrong */
203 Status
= NtImpersonateThread(NtCurrentThread(),
204 CsrThread
->ThreadHandle
,
207 if (!NT_SUCCESS(Status
))
211 DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status);
212 if (Status != STATUS_BAD_IMPERSONATION_LEVEL) DbgBreakPoint();
217 /* Increase the impersonation count for the current thread */
218 if (CurrentThread
) ++CurrentThread
->ImpersonationCount
;
225 * @name CsrRevertToSelf
228 * The CsrRevertToSelf routine will attempt to remove an active impersonation.
232 * @return TRUE if the reversion was succesful, false otherwise.
234 * @remarks Impersonation can be recursive; as such, the impersonation token
235 * will only be deleted once the CSR Thread's impersonaton count
241 CsrRevertToSelf(VOID
)
244 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
245 HANDLE ImpersonationToken
= NULL
;
247 /* Check if we have a Current Thread */
250 /* Make sure impersonation is on */
251 if (!CurrentThread
->ImpersonationCount
)
253 // DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n");
256 else if (--CurrentThread
->ImpersonationCount
> 0)
258 /* Success; impersonation count decreased but still not zero */
263 /* Impersonation has been totally removed, revert to ourselves */
264 Status
= NtSetInformationThread(NtCurrentThread(),
265 ThreadImpersonationToken
,
269 /* Return TRUE or FALSE */
270 return NT_SUCCESS(Status
);
274 * @name FindProcessForShutdown
276 * The FindProcessForShutdown routine returns a CSR Process which is ready
277 * to be shutdown, and sets the appropriate shutdown flags for it.
280 * Pointer to the LUID of the CSR Process calling this routine.
282 * @return Pointer to a CSR Process which is ready to be shutdown.
289 FindProcessForShutdown(IN PLUID CallerLuid
)
291 PCSR_PROCESS CsrProcess
, ReturnCsrProcess
= NULL
;
292 // PCSR_THREAD CsrThread;
296 LUID SystemLuid
= SYSTEM_LUID
;
297 // BOOLEAN IsSystemLuid = FALSE, IsOurLuid = FALSE;
298 PLIST_ENTRY NextEntry
;
300 /* Set the List Pointers */
301 NextEntry
= CsrRootProcess
->ListLink
.Flink
;
302 while (NextEntry
!= &CsrRootProcess
->ListLink
)
304 /* Get the process */
305 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
307 /* Move to the next entry */
308 NextEntry
= NextEntry
->Flink
;
310 /* Skip this process if it's already been processed */
311 if (CsrProcess
->Flags
& CsrProcessSkipShutdown
) continue;
313 /* Get the LUID of this Process */
314 Status
= CsrGetProcessLuid(CsrProcess
->ProcessHandle
, &ProcessLuid
);
316 /* Check if we didn't get access to the LUID */
317 if (Status
== STATUS_ACCESS_DENIED
)
319 /* FIXME:Check if we have any threads */
321 if (CsrProcess->ThreadCount)
323 /\* Impersonate one of the threads and retry *\/
324 CsrThread = CONTAINING_RECORD(CsrProcess->ThreadList.Flink,
327 CsrImpersonateClient(CsrThread);
328 Status = CsrGetProcessLuid(NULL, &ProcessLuid);
334 if (!NT_SUCCESS(Status
))
336 /* We didn't have access, so skip it */
337 CsrProcess
->Flags
|= CsrProcessSkipShutdown
;
341 /* Check if this is the System LUID */
342 if ((/*IsSystemLuid =*/ RtlEqualLuid(&ProcessLuid
, &SystemLuid
)))
344 /* Mark this process */
345 CsrProcess
->ShutdownFlags
|= CsrShutdownSystem
;
347 else if (!(/*IsOurLuid =*/ RtlEqualLuid(&ProcessLuid
, CallerLuid
)))
349 /* Our LUID doesn't match with the caller's */
350 CsrProcess
->ShutdownFlags
|= CsrShutdownOther
;
353 /* Check if we're past the previous level */
354 if (CsrProcess
->ShutdownLevel
> Level
/* || !ReturnCsrProcess */)
356 /* Update the level */
357 Level
= CsrProcess
->ShutdownLevel
;
359 /* Set the final process */
360 ReturnCsrProcess
= CsrProcess
;
364 /* Check if we found a process */
365 if (ReturnCsrProcess
)
367 /* Skip this one next time */
368 ReturnCsrProcess
->Flags
|= CsrProcessSkipShutdown
;
371 return ReturnCsrProcess
;
374 /* This is really "CsrShutdownProcess", mostly */
377 CsrEnumProcesses(IN CSRSS_ENUM_PROCESS_PROC EnumProc
,
380 PVOID
* RealContext
= (PVOID
*)Context
;
381 PLUID CallerLuid
= RealContext
[0];
382 PCSR_PROCESS CsrProcess
= NULL
;
383 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
385 PLIST_ENTRY NextEntry
;
388 /* Acquire process lock */
389 CsrAcquireProcessLock();
391 /* Get the list pointers */
392 NextEntry
= CsrRootProcess
->ListLink
.Flink
;
393 while (NextEntry
!= &CsrRootProcess
->ListLink
)
395 /* Get the Process */
396 CsrProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
398 /* Remove the skip flag, set shutdown flags to 0*/
399 CsrProcess
->Flags
&= ~CsrProcessSkipShutdown
;
400 CsrProcess
->ShutdownFlags
= 0;
402 /* Move to the next */
403 NextEntry
= NextEntry
->Flink
;
406 /* Set shudown Priority */
407 CsrSetToShutdownPriority();
409 /* Loop all processes */
410 //DPRINT1("Enumerating for LUID: %lx %lx\n", CallerLuid->HighPart, CallerLuid->LowPart);
415 /* Find the next process to shutdown */
417 if (!(CsrProcess
= FindProcessForShutdown(CallerLuid
)))
420 CsrReleaseProcessLock();
421 Status
= STATUS_SUCCESS
;
426 /* Release the lock, make the callback, and acquire it back */
427 //DPRINT1("Found process: %lx\n", CsrProcess->ClientId.UniqueProcess);
428 CsrReleaseProcessLock();
429 Result
= (ULONG
)EnumProc(CsrProcess
, (PVOID
)((ULONG_PTR
)Context
| FirstTry
));
430 CsrAcquireProcessLock();
432 /* Check the result */
433 //DPRINT1("Result: %d\n", Result);
434 if (Result
== CsrShutdownCsrProcess
)
436 /* The callback unlocked the process */
439 else if (Result
== CsrShutdownNonCsrProcess
)
441 /* A non-CSR process, the callback didn't touch it */
444 else if (Result
== CsrShutdownCancelled
)
446 /* Shutdown was cancelled, unlock and exit */
447 CsrReleaseProcessLock();
448 Status
= STATUS_CANCELLED
;
452 /* No matches during the first try, so loop again */
453 if (FirstTry
&& Result
== CsrShutdownNonCsrProcess
)
461 /* Return to normal priority */
462 CsrSetToNormalPriority();
467 * @name CsrProcessRefcountZero
469 * The CsrProcessRefcountZero routine is executed when a CSR Process has lost
470 * all its active references. It removes and de-allocates the CSR Process.
473 * Pointer to the CSR Process that is to be deleted.
477 * @remarks Do not call this routine. It is reserved for the internal
478 * thread management routines when a CSR Process has lost all
481 * This routine is called with the Process Lock held.
486 CsrProcessRefcountZero(IN PCSR_PROCESS CsrProcess
)
488 ASSERT(ProcessStructureListLocked());
490 /* Remove the Process from the list */
491 CsrRemoveProcess(CsrProcess
);
493 /* Check if there's a session */
494 if (CsrProcess
->NtSession
)
496 /* Dereference the Session */
497 CsrDereferenceNtSession(CsrProcess
->NtSession
, 0);
500 /* Close the Client Port if there is one */
501 if (CsrProcess
->ClientPort
) NtClose(CsrProcess
->ClientPort
);
503 /* Close the process handle */
504 NtClose(CsrProcess
->ProcessHandle
);
506 /* Free the Proces Object */
507 CsrDeallocateProcess(CsrProcess
);
511 * @name CsrLockedDereferenceProcess
513 * The CsrLockedDereferenceProcess dereferences a CSR Process while the
514 * Process Lock is already being held.
517 * Pointer to the CSR Process to be dereferenced.
521 * @remarks This routine will return with the Process Lock held.
526 CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess
)
530 /* Decrease reference count */
531 LockCount
= --CsrProcess
->ReferenceCount
;
532 ASSERT(LockCount
>= 0);
535 /* Call the generic cleanup code */
536 DPRINT1("Should kill process: %p\n", CsrProcess
);
537 CsrProcessRefcountZero(CsrProcess
);
538 CsrAcquireProcessLock();
543 * @name CsrDereferenceProcess
546 * The CsrDereferenceProcess routine removes a reference from a CSR Process.
549 * Pointer to the CSR Process to dereference.
553 * @remarks If the reference count has reached zero (ie: the CSR Process has
554 * no more active references), it will be deleted.
559 CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess
)
563 /* Acquire process lock */
564 CsrAcquireProcessLock();
566 /* Decrease reference count */
567 LockCount
= --CsrProcess
->ReferenceCount
;
568 ASSERT(LockCount
>= 0);
571 /* Call the generic cleanup code */
572 CsrProcessRefcountZero(CsrProcess
);
576 /* Just release the lock */
577 CsrReleaseProcessLock();
582 * @name CsrDestroyProcess
585 * The CsrDestroyProcess routine destroys the CSR Process corresponding to
589 * Pointer to the Client ID Structure corresponding to the CSR
590 * Process which is about to be destroyed.
595 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
596 * if the CSR Process is already terminating.
603 CsrDestroyProcess(IN PCLIENT_ID Cid
,
604 IN NTSTATUS ExitStatus
)
606 PCSR_THREAD CsrThread
;
607 PCSR_PROCESS CsrProcess
;
608 CLIENT_ID ClientId
= *Cid
;
609 PLIST_ENTRY NextEntry
;
612 CsrAcquireProcessLock();
614 /* Find the thread */
615 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
, &ClientId
);
617 /* Make sure we got one back, and that it's not already gone */
618 if (!(CsrThread
) || (CsrProcess
->Flags
& CsrProcessTerminating
))
620 /* Release the lock and return failure */
621 CsrReleaseProcessLock();
622 return STATUS_THREAD_IS_TERMINATING
;
625 /* Set the terminated flag */
626 CsrProcess
->Flags
|= CsrProcessTerminating
;
628 /* Get the List Pointers */
629 NextEntry
= CsrProcess
->ThreadList
.Flink
;
630 while (NextEntry
!= &CsrProcess
->ThreadList
)
632 /* Get the current thread entry */
633 CsrThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
635 /* Make sure the thread isn't already dead */
636 if (CsrThread
->Flags
& CsrThreadTerminated
)
638 NextEntry
= NextEntry
->Flink
;
642 /* Set the Terminated flag */
643 CsrThread
->Flags
|= CsrThreadTerminated
;
645 /* Acquire the Wait Lock */
646 CsrAcquireWaitLock();
648 /* Do we have an active wait block? */
649 if (CsrThread
->WaitBlock
)
651 /* Notify waiters of termination */
652 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
656 CsrProcessTerminating
,
660 /* Release the Wait Lock */
661 CsrReleaseWaitLock();
663 /* Dereference the thread */
664 CsrLockedDereferenceThread(CsrThread
);
665 NextEntry
= CsrProcess
->ThreadList
.Flink
;
668 /* Release the Process Lock and return success */
669 CsrReleaseProcessLock();
670 return STATUS_SUCCESS
;
674 * @name CsrCreateProcess
677 * Do nothing for 500ms.
679 * @param ArgumentCount
680 * Description of the parameter. Wrapped to more lines on ~70th
684 * Description of the parameter. Wrapped to more lines on ~70th
687 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
695 CsrCreateProcess(IN HANDLE hProcess
,
697 IN PCLIENT_ID ClientId
,
698 IN PCSR_NT_SESSION NtSession
,
700 IN PCLIENT_ID DebugCid
)
702 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
703 CLIENT_ID CurrentCid
;
704 PCSR_PROCESS CurrentProcess
;
705 // PVOID ProcessData;
707 PCSR_PROCESS CsrProcess
;
709 PCSR_THREAD CsrThread
;
710 KERNEL_USER_TIMES KernelTimes
;
712 /* Get the current CID and lock Processes */
713 CurrentCid
= CurrentThread
->ClientId
;
714 CsrAcquireProcessLock();
716 /* Get the current CSR Thread */
717 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
720 /* We've failed to locate the thread */
721 CsrReleaseProcessLock();
722 return STATUS_THREAD_IS_TERMINATING
;
725 /* Allocate a new Process Object */
726 CsrProcess
= CsrAllocateProcess();
729 /* Couldn't allocate Process */
730 CsrReleaseProcessLock();
731 return STATUS_NO_MEMORY
;
735 /* Inherit the Process Data */
736 CurrentProcess
= CurrentThread
->Process
;
737 ProcessData
= &CurrentProcess
->ServerData
[CSR_SERVER_DLL_MAX
];
738 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
740 /* Check if the DLL is Loaded and has Per Process Data */
741 if ((CsrLoadedServerDll
[i
]) && (CsrLoadedServerDll
[i
]->SizeOfProcessData
))
743 /* Set the pointer */
744 CsrProcess
->ServerData
[i
] = ProcessData
;
747 RtlMoveMemory(ProcessData
,
748 CurrentProcess
->ServerData
[i
],
749 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
751 /* Update next data pointer */
752 ProcessData
= (PVOID
)((ULONG_PTR
)ProcessData
+
753 CsrLoadedServerDll
[i
]->SizeOfProcessData
);
757 /* No data for this Server */
758 CsrProcess
->ServerData
[i
] = NULL
;
763 /* Set the Exception port to us */
764 Status
= NtSetInformationProcess(hProcess
,
765 ProcessExceptionPort
,
768 if (!NT_SUCCESS(Status
))
771 CsrDeallocateProcess(CsrProcess
);
772 CsrReleaseProcessLock();
773 return STATUS_NO_MEMORY
;
776 /* If Check if CreateProcess got CREATE_NEW_PROCESS_GROUP */
777 if (!(Flags
& CsrProcessCreateNewGroup
))
779 /* Create new data */
780 CsrProcess
->ProcessGroupId
= HandleToUlong(ClientId
->UniqueProcess
);
781 CsrProcess
->ProcessGroupSequence
= CsrProcess
->SequenceNumber
;
785 /* Copy it from the current process */
786 CsrProcess
->ProcessGroupId
= CurrentProcess
->ProcessGroupId
;
787 CsrProcess
->ProcessGroupSequence
= CurrentProcess
->ProcessGroupSequence
;
790 /* Check if this is a console process */
791 if (Flags
& CsrProcessIsConsoleApp
) CsrProcess
->Flags
|= CsrProcessIsConsoleApp
;
793 /* Mask out non-debug flags */
794 Flags
&= ~(CsrProcessIsConsoleApp
| CsrProcessCreateNewGroup
| CsrProcessPriorityFlags
);
796 /* Check if every process will be debugged */
797 if (!(Flags
) && (CurrentProcess
->DebugFlags
& CsrDebugProcessChildren
))
799 /* Pass it on to the current process */
800 CsrProcess
->DebugFlags
= CsrDebugProcessChildren
;
801 CsrProcess
->DebugCid
= CurrentProcess
->DebugCid
;
804 /* Check if Debugging was used on this process */
805 if ((Flags
& (CsrDebugOnlyThisProcess
| CsrDebugProcessChildren
)) && (DebugCid
))
807 /* Save the debug flag used */
808 CsrProcess
->DebugFlags
= Flags
;
811 CsrProcess
->DebugCid
= *DebugCid
;
814 /* Check if we debugging is enabled */
815 if (CsrProcess
->DebugFlags
)
817 /* Set the Debug Port to us */
818 Status
= NtSetInformationProcess(hProcess
,
822 ASSERT(NT_SUCCESS(Status
));
823 if (!NT_SUCCESS(Status
))
826 CsrDeallocateProcess(CsrProcess
);
827 CsrReleaseProcessLock();
828 return STATUS_NO_MEMORY
;
832 /* Get the Thread Create Time */
833 Status
= NtQueryInformationThread(hThread
,
838 if (!NT_SUCCESS(Status
))
841 CsrDeallocateProcess(CsrProcess
);
842 CsrReleaseProcessLock();
843 return STATUS_NO_MEMORY
;
846 /* Allocate a CSR Thread Structure */
847 CsrThread
= CsrAllocateThread(CsrProcess
);
851 CsrDeallocateProcess(CsrProcess
);
852 CsrReleaseProcessLock();
853 return STATUS_NO_MEMORY
;
856 /* Save the data we have */
857 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
858 CsrThread
->ClientId
= *ClientId
;
859 CsrThread
->ThreadHandle
= hThread
;
860 ProtectHandle(hThread
);
861 CsrThread
->Flags
= 0;
863 /* Insert the Thread into the Process */
864 CsrInsertThread(CsrProcess
, CsrThread
);
866 /* Reference the session */
867 CsrReferenceNtSession(NtSession
);
868 CsrProcess
->NtSession
= NtSession
;
870 /* Setup Process Data */
871 CsrProcess
->ClientId
= *ClientId
;
872 CsrProcess
->ProcessHandle
= hProcess
;
873 CsrProcess
->ShutdownLevel
= 0x280;
875 /* Set the Priority to Background */
876 CsrSetBackgroundPriority(CsrProcess
);
878 /* Insert the Process */
879 CsrInsertProcess(NULL
, CurrentProcess
, CsrProcess
);
881 /* Release lock and return */
882 CsrReleaseProcessLock();
887 * @name CsrUnlockProcess
890 * The CsrUnlockProcess undoes a previous CsrLockProcessByClientId operation.
893 * Pointer to a previously locked CSR Process.
895 * @return STATUS_SUCCESS.
897 * @remarks This routine must be called with the Process Lock held.
902 CsrUnlockProcess(IN PCSR_PROCESS CsrProcess
)
904 /* Dereference the process */
905 CsrLockedDereferenceProcess(CsrProcess
);
907 /* Release the lock and return */
908 CsrReleaseProcessLock();
909 return STATUS_SUCCESS
;
913 * @name CsrSetBackgroundPriority
916 * The CsrSetBackgroundPriority routine sets the priority for the given CSR
917 * Process as a Background priority.
920 * Pointer to the CSR Process whose priority will be modified.
929 CsrSetBackgroundPriority(IN PCSR_PROCESS CsrProcess
)
931 PROCESS_PRIORITY_CLASS PriorityClass
;
933 /* Set the Foreground bit off */
934 PriorityClass
.Foreground
= FALSE
;
936 /* Set the new Priority */
937 NtSetInformationProcess(CsrProcess
->ProcessHandle
,
938 ProcessPriorityClass
,
940 sizeof(PriorityClass
));
944 * @name CsrAllocateProcess
947 * The CsrAllocateProcess routine allocates a new CSR Process object.
949 * @return Pointer to the newly allocated CSR Process.
956 CsrAllocateProcess(VOID
)
958 PCSR_PROCESS CsrProcess
;
961 /* Calculate the amount of memory this should take */
962 TotalSize
= sizeof(CSR_PROCESS
) +
963 (CSR_SERVER_DLL_MAX
* sizeof(PVOID
)) +
964 CsrTotalPerProcessDataLength
;
966 /* Allocate a Process */
967 CsrProcess
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, TotalSize
);
968 if (!CsrProcess
) return NULL
;
970 /* Handle the Sequence Number and protect against overflow */
971 CsrProcess
->SequenceNumber
= CsrProcessSequenceCount
++;
972 if (CsrProcessSequenceCount
< 5) CsrProcessSequenceCount
= 5;
974 /* Increase the reference count */
975 CsrProcess
->ReferenceCount
++;
977 /* Initialize the Thread List */
978 InitializeListHead(&CsrProcess
->ThreadList
);
980 /* Return the Process */
985 * @name CsrLockedReferenceProcess
987 * The CsrLockedReferenceProcess references a CSR Process while the
988 * Process Lock is already being held.
991 * Pointer to the CSR Process to be referenced.
995 * @remarks This routine will return with the Process Lock held.
1000 CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess
)
1002 /* Increment the reference count */
1003 ++CsrProcess
->ReferenceCount
;
1007 * @name CsrInitializeProcessStructure
1010 * The CsrInitializeProcessStructure routine sets up support for CSR Processes
1015 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1023 CsrInitializeProcessStructure(VOID
)
1028 /* Initialize the Lock */
1029 Status
= RtlInitializeCriticalSection(&ProcessDataLock
);
1030 if (!NT_SUCCESS(Status
)) return Status
;
1032 /* Set up the Root Process */
1033 CsrRootProcess
= CsrAllocateProcess();
1034 if (!CsrRootProcess
) return STATUS_NO_MEMORY
;
1036 /* Set up the minimal information for it */
1037 InitializeListHead(&CsrRootProcess
->ListLink
);
1038 CsrRootProcess
->ProcessHandle
= (HANDLE
)-1;
1039 CsrRootProcess
->ClientId
= NtCurrentTeb()->ClientId
;
1041 /* Initialize the Thread Hash List */
1042 for (i
= 0; i
< 256; i
++) InitializeListHead(&CsrThreadHashTable
[i
]);
1044 /* Initialize the Wait Lock */
1045 return RtlInitializeCriticalSection(&CsrWaitListsLock
);
1049 * @name CsrDeallocateProcess
1051 * The CsrDeallocateProcess frees the memory associated with a CSR Process.
1054 * Pointer to the CSR Process to be freed.
1058 * @remarks Do not call this routine. It is reserved for the internal
1059 * thread management routines when a CSR Process has been cleanly
1060 * dereferenced and killed.
1065 CsrDeallocateProcess(IN PCSR_PROCESS CsrProcess
)
1067 /* Free the process object from the heap */
1068 RtlFreeHeap(CsrHeap
, 0, CsrProcess
);
1072 * @name CsrRemoveProcess
1074 * The CsrRemoveProcess function undoes a CsrInsertProcess operation and
1075 * removes the CSR Process from the Process List and notifies Server DLLs
1079 * Pointer to the CSR Process to remove.
1088 CsrRemoveProcess(IN PCSR_PROCESS CsrProcess
)
1090 PCSR_SERVER_DLL ServerDll
;
1092 ASSERT(ProcessStructureListLocked());
1094 /* Remove us from the Process List */
1095 RemoveEntryList(&CsrProcess
->ListLink
);
1097 /* Release the lock */
1098 CsrReleaseProcessLock();
1100 /* Loop every Server DLL */
1101 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1103 /* Get the Server DLL */
1104 ServerDll
= CsrLoadedServerDll
[i
];
1106 /* Check if it's valid and if it has a Disconnect Callback */
1107 if ((ServerDll
) && (ServerDll
->DisconnectCallback
))
1110 ServerDll
->DisconnectCallback(CsrProcess
);
1116 * @name CsrInsertProcess
1118 * The CsrInsertProcess routine inserts a CSR Process into the Process List
1119 * and notifies Server DLLs of the creation of a new CSR Process.
1122 * Optional pointer to the CSR Process creating this CSR Process.
1124 * @param CurrentProcess
1125 * Optional pointer to the current CSR Process.
1128 * Pointer to the CSR Process which is to be inserted.
1137 CsrInsertProcess(IN PCSR_PROCESS Parent OPTIONAL
,
1138 IN PCSR_PROCESS CurrentProcess OPTIONAL
,
1139 IN PCSR_PROCESS CsrProcess
)
1142 PCSR_SERVER_DLL ServerDll
;
1145 ASSERT(ProcessStructureListLocked());
1147 /* Set the parent */
1148 CsrProcess
->Parent
= Parent
;
1150 /* Insert it into the Root List */
1151 InsertTailList(&CsrRootProcess
->ListLink
, &CsrProcess
->ListLink
);
1153 /* Notify the Server DLLs */
1154 for (i
= 0; i
< CSR_SERVER_DLL_MAX
; i
++)
1156 /* Get the current Server DLL */
1157 ServerDll
= CsrLoadedServerDll
[i
];
1159 /* Make sure it's valid and that it has callback */
1160 if ((ServerDll
) && (ServerDll
->NewProcessCallback
))
1162 ServerDll
->NewProcessCallback(CurrentProcess
, CsrProcess
);
1169 * @name CsrLockProcessByClientId
1172 * The CsrLockProcessByClientId routine locks the CSR Process corresponding
1173 * to the given Process ID and optionally returns it.
1176 * Process ID corresponding to the CSR Process which will be locked.
1179 * Optional pointer to a CSR Process pointer which will hold the
1180 * CSR Process corresponding to the given Process ID.
1182 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
1185 * @remarks Locking a CSR Process is defined as acquiring an extra
1186 * reference to it and returning with the Process Lock held.
1191 CsrLockProcessByClientId(IN HANDLE Pid
,
1192 OUT PCSR_PROCESS
*CsrProcess
)
1194 PLIST_ENTRY NextEntry
;
1195 PCSR_PROCESS CurrentProcess
= NULL
;
1198 /* Acquire the lock */
1199 CsrAcquireProcessLock();
1201 /* Assume failure */
1202 ASSERT(CsrProcess
!= NULL
);
1205 /* Setup the List Pointers */
1206 NextEntry
= &CsrRootProcess
->ListLink
;
1209 /* Get the Process */
1210 CurrentProcess
= CONTAINING_RECORD(NextEntry
, CSR_PROCESS
, ListLink
);
1212 /* Check for PID Match */
1213 if (CurrentProcess
->ClientId
.UniqueProcess
== Pid
)
1215 Status
= STATUS_SUCCESS
;
1220 NextEntry
= NextEntry
->Flink
;
1221 } while (NextEntry
!= &CsrRootProcess
->ListLink
);
1223 /* Check if we didn't find it in the list */
1224 if (!NT_SUCCESS(Status
))
1226 /* Nothing found, release the lock */
1227 CsrReleaseProcessLock();
1231 /* Lock the found process and return it */
1232 CsrLockedReferenceProcess(CurrentProcess
);
1233 *CsrProcess
= CurrentProcess
;
1236 /* Return the result */