2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS CSR Sub System
4 * FILE: subsys/csr/csrsrv/thread.c
5 * PURPOSE: CSR Server DLL Thread Implementation
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
9 /* INCLUDES ******************************************************************/
16 /* DATA **********************************************************************/
18 LIST_ENTRY CsrThreadHashTable
[256];
19 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos
=
21 sizeof(SECURITY_QUALITY_OF_SERVICE
),
22 SecurityImpersonation
,
23 SECURITY_STATIC_TRACKING
,
27 /* PRIVATE FUNCTIONS *********************************************************/
30 * @name CsrAllocateThread
32 * The CsrAllocateThread routine allocates a new CSR Thread object.
35 * Pointer to the CSR Process which will contain this CSR Thread.
37 * @return Pointer to the newly allocated CSR Thread.
44 CsrAllocateThread(IN PCSR_PROCESS CsrProcess
)
46 PCSR_THREAD CsrThread
;
48 /* Allocate the structure */
49 CsrThread
= RtlAllocateHeap(CsrHeap
, HEAP_ZERO_MEMORY
, sizeof(CSR_THREAD
));
50 if (!CsrThread
) return NULL
;
52 /* Reference the Thread and Process */
53 CsrThread
->ReferenceCount
++;
54 CsrProcess
->ReferenceCount
++;
56 /* Set the Parent Process */
57 CsrThread
->Process
= CsrProcess
;
64 * @name CsrLocateThreadByClientId
66 * The CsrLocateThreadByClientId routine locates the CSR Thread and,
67 * optionally, its parent CSR Process, corresponding to a Client ID.
70 * Optional pointer to a CSR Process pointer which will contain
71 * the CSR Thread's parent.
74 * Pointer to a Client ID structure containing the Unique Thread ID
77 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
85 CsrLocateThreadByClientId(OUT PCSR_PROCESS
*Process OPTIONAL
,
86 IN PCLIENT_ID ClientId
)
89 PLIST_ENTRY NextEntry
;
90 PCSR_THREAD FoundThread
;
91 ASSERT(ProcessStructureListLocked());
94 i
= CsrHashThread(ClientId
->UniqueThread
);
96 /* Set the list pointers */
97 NextEntry
= CsrThreadHashTable
[i
].Flink
;
100 while (NextEntry
!= &CsrThreadHashTable
[i
])
103 FoundThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
105 /* Compare the CID */
106 if (*(PULONGLONG
)&FoundThread
->ClientId
== *(PULONGLONG
)ClientId
)
108 /* Match found, return the process */
109 *Process
= FoundThread
->Process
;
111 /* Return thread too */
116 NextEntry
= NextEntry
->Flink
;
124 * @name CsrLocateThreadInProcess
126 * The CsrLocateThreadInProcess routine locates the CSR Thread
127 * corresponding to a Client ID inside a specific CSR Process.
130 * Optional pointer to the CSR Process which contains the CSR Thread
131 * that will be looked up.
134 * Pointer to a Client ID structure containing the Unique Thread ID
137 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
140 * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
146 CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL
,
149 PLIST_ENTRY NextEntry
;
150 PCSR_THREAD FoundThread
= NULL
;
152 /* Use the Root Process if none was specified */
153 if (!CsrProcess
) CsrProcess
= CsrRootProcess
;
155 /* Save the List pointers */
156 NextEntry
= CsrProcess
->ThreadList
.Flink
;
159 while (NextEntry
!= &CsrProcess
->ThreadList
)
161 /* Get Thread Entry */
162 FoundThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, Link
);
164 /* Check for TID Match */
165 if (FoundThread
->ClientId
.UniqueThread
== Cid
->UniqueThread
) break;
168 NextEntry
= NextEntry
->Flink
;
171 /* Return what we found */
176 * @name CsrInsertThread
178 * The CsrInsertThread routine inserts a CSR Thread into its parent's
179 * Thread List and into the Thread Hash Table.
182 * Pointer to the CSR Process containing this CSR Thread.
185 * Pointer to the CSR Thread to be inserted.
194 CsrInsertThread(IN PCSR_PROCESS Process
,
195 IN PCSR_THREAD Thread
)
198 ASSERT(ProcessStructureListLocked());
200 /* Insert it into the Regular List */
201 InsertTailList(&Process
->ThreadList
, &Thread
->Link
);
203 /* Increase Thread Count */
204 Process
->ThreadCount
++;
206 /* Hash the Thread */
207 i
= CsrHashThread(Thread
->ClientId
.UniqueThread
);
209 /* Insert it there too */
210 InsertHeadList(&CsrThreadHashTable
[i
], &Thread
->HashLinks
);
214 * @name CsrDeallocateThread
216 * The CsrDeallocateThread frees the memory associated with a CSR Thread.
219 * Pointer to the CSR Thread to be freed.
223 * @remarks Do not call this routine. It is reserved for the internal
224 * thread management routines when a CSR Thread has been cleanly
225 * dereferenced and killed.
230 CsrDeallocateThread(IN PCSR_THREAD CsrThread
)
232 /* Free the process object from the heap */
233 ASSERT(CsrThread
->WaitBlock
== NULL
);
234 RtlFreeHeap(CsrHeap
, 0, CsrThread
);
238 * @name CsrLockedReferenceThread
240 * The CsrLockedReferenceThread refences a CSR Thread while the
241 * Process Lock is already being held.
244 * Pointer to the CSR Thread to be referenced.
248 * @remarks This routine will return with the Process Lock held.
253 CsrLockedReferenceThread(IN PCSR_THREAD CsrThread
)
255 /* Increment the reference count */
256 ++CsrThread
->ReferenceCount
;
260 * @name CsrLockedDereferenceThread
262 * The CsrLockedDereferenceThread derefences a CSR Thread while the
263 * Process Lock is already being held.
266 * Pointer to the CSR Thread to be dereferenced.
270 * @remarks This routine will return with the Process Lock held.
275 CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread
)
279 /* Decrease reference count */
280 LockCount
= --CsrThread
->ReferenceCount
;
281 ASSERT(LockCount
>= 0);
284 /* Call the generic cleanup code */
285 CsrThreadRefcountZero(CsrThread
);
286 CsrAcquireProcessLock();
291 * @name CsrRemoveThread
293 * The CsrRemoveThread function undoes a CsrInsertThread operation and
294 * removes the CSR Thread from the the Hash Table and Thread List.
297 * Pointer to the CSR Thread to remove.
301 * @remarks If this CSR Thread is the last one inside a CSR Process, the
302 * parent will be dereferenced and the CsrProcessLastThreadTerminated
305 * After executing this routine, the CSR Thread will have the
306 * CsrThreadInTermination flag set.
311 CsrRemoveThread(IN PCSR_THREAD CsrThread
)
313 ASSERT(ProcessStructureListLocked());
315 /* Remove it from the List */
316 RemoveEntryList(&CsrThread
->Link
);
318 /* Decreate the thread count of the process */
319 --CsrThread
->Process
->ThreadCount
;
321 /* Remove it from the Hash List as well */
322 if (CsrThread
->HashLinks
.Flink
) RemoveEntryList(&CsrThread
->HashLinks
);
324 /* Check if this is the last Thread */
325 if (!CsrThread
->Process
->ThreadCount
)
327 /* Check if it's not already been marked for deletion */
328 if (!(CsrThread
->Process
->Flags
& CsrProcessLastThreadTerminated
))
330 /* Let everyone know this process is about to lose the thread */
331 CsrThread
->Process
->Flags
|= CsrProcessLastThreadTerminated
;
333 /* Reference the Process */
334 CsrLockedDereferenceProcess(CsrThread
->Process
);
338 /* Mark the thread for deletion */
339 CsrThread
->Flags
|= CsrThreadInTermination
;
343 * @name CsrThreadRefcountZero
345 * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
346 * all its active references. It removes and de-allocates the CSR Thread.
349 * Pointer to the CSR Thread that is to be deleted.
353 * @remarks Do not call this routine. It is reserved for the internal
354 * thread management routines when a CSR Thread has lost all
357 * This routine is called with the Process Lock held.
362 CsrThreadRefcountZero(IN PCSR_THREAD CsrThread
)
364 PCSR_PROCESS CsrProcess
= CsrThread
->Process
;
367 /* Remove this thread */
368 CsrRemoveThread(CsrThread
);
370 /* Release the Process Lock */
371 CsrReleaseProcessLock();
373 /* Close the NT Thread Handle */
374 UnProtectHandle(CsrThread
->ThreadHandle
);
375 Status
= NtClose(CsrThread
->ThreadHandle
);
376 ASSERT(NT_SUCCESS(Status
));
378 /* De-allocate the CSR Thread Object */
379 CsrDeallocateThread(CsrThread
);
381 /* Remove a reference from the process */
382 CsrDereferenceProcess(CsrProcess
);
385 /* PUBLIC FUNCTIONS ***********************************************************/
388 * @name CsrAddStaticServerThread
391 * The CsrAddStaticServerThread routine adds a new CSR Thread to the
392 * CSR Server Process (CsrRootProcess).
395 * Handle to an existing NT Thread to which to associate this
399 * Pointer to the Client ID structure of the NT Thread to associate
400 * with this CSR Thread.
403 * Initial CSR Thread Flags to associate to this CSR Thread. Usually
404 * CsrThreadIsServerThread.
406 * @return Pointer to the newly allocated CSR Thread.
413 CsrAddStaticServerThread(IN HANDLE hThread
,
414 IN PCLIENT_ID ClientId
,
415 IN ULONG ThreadFlags
)
417 PCSR_THREAD CsrThread
;
420 CsrAcquireProcessLock();
422 /* Allocate the Server Thread */
423 CsrThread
= CsrAllocateThread(CsrRootProcess
);
426 /* Setup the Object */
427 CsrThread
->ThreadHandle
= hThread
;
428 ProtectHandle(hThread
);
429 CsrThread
->ClientId
= *ClientId
;
430 CsrThread
->Flags
= ThreadFlags
;
432 /* Insert it into the Thread List */
433 InsertTailList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
435 /* Increment the thread count */
436 CsrRootProcess
->ThreadCount
++;
440 DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread
);
443 /* Release the Process Lock and return */
444 CsrReleaseProcessLock();
449 * @name CsrCreateRemoteThread
452 * The CsrCreateRemoteThread routine creates a CSR Thread object for
453 * an NT Thread which is not part of the current NT Process.
456 * Handle to an existing NT Thread to which to associate this
460 * Pointer to the Client ID structure of the NT Thread to associate
461 * with this CSR Thread.
463 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
471 CsrCreateRemoteThread(IN HANDLE hThread
,
472 IN PCLIENT_ID ClientId
)
476 PCSR_THREAD CsrThread
;
477 PCSR_PROCESS CsrProcess
;
478 KERNEL_USER_TIMES KernelTimes
;
480 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
482 /* Get the Thread Create Time */
483 Status
= NtQueryInformationThread(hThread
,
488 if (!NT_SUCCESS(Status
)) return Status
;
490 /* Lock the Owner Process */
491 Status
= CsrLockProcessByClientId(&ClientId
->UniqueProcess
, &CsrProcess
);
493 /* Make sure the thread didn't terminate */
494 if (KernelTimes
.ExitTime
.QuadPart
)
496 /* Unlock the process and return */
497 CsrUnlockProcess(CsrProcess
);
498 return STATUS_THREAD_IS_TERMINATING
;
501 /* Allocate a CSR Thread Structure */
502 CsrThread
= CsrAllocateThread(CsrProcess
);
505 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__
);
506 CsrUnlockProcess(CsrProcess
);
507 return STATUS_NO_MEMORY
;
510 /* Duplicate the Thread Handle */
511 Status
= NtDuplicateObject(NtCurrentProcess(),
517 DUPLICATE_SAME_ACCESS
);
519 if (!NT_SUCCESS(Status
)) ThreadHandle
= hThread
;
521 /* Save the data we have */
522 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
523 CsrThread
->ClientId
= *ClientId
;
524 CsrThread
->ThreadHandle
= ThreadHandle
;
525 ProtectHandle(ThreadHandle
);
526 CsrThread
->Flags
= 0;
528 /* Insert the Thread into the Process */
529 CsrInsertThread(CsrProcess
, CsrThread
);
531 /* Release the lock and return */
532 CsrUnlockProcess(CsrProcess
);
533 return STATUS_SUCCESS
;
537 * @name CsrCreateThread
540 * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
543 * Pointer to the CSR Process which will contain the CSR Thread.
546 * Handle to an existing NT Thread to which to associate this
550 * Pointer to the Client ID structure of the NT Thread to associate
551 * with this CSR Thread.
553 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
561 CsrCreateThread(IN PCSR_PROCESS CsrProcess
,
563 IN PCLIENT_ID ClientId
,
564 IN BOOLEAN HaveClient
)
567 PCSR_THREAD CsrThread
, CurrentThread
;
568 PCSR_PROCESS CurrentProcess
;
569 CLIENT_ID CurrentCid
;
570 KERNEL_USER_TIMES KernelTimes
;
571 DPRINT("CSRSRV: %s called\n", __FUNCTION__
);
575 /* Get the current thread and CID */
576 CurrentThread
= NtCurrentTeb()->CsrClientThread
;
577 CurrentCid
= CurrentThread
->ClientId
;
579 /* Acquire the Process Lock */
580 CsrAcquireProcessLock();
582 /* Get the current Process and make sure the Thread is valid with this CID */
583 CurrentThread
= CsrLocateThreadByClientId(&CurrentProcess
, &CurrentCid
);
586 DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__
);
587 CsrReleaseProcessLock();
588 return STATUS_THREAD_IS_TERMINATING
;
593 /* Acquire the Process Lock */
594 CsrAcquireProcessLock();
597 /* Get the Thread Create Time */
598 Status
= NtQueryInformationThread(hThread
,
603 if (!NT_SUCCESS(Status
))
605 CsrReleaseProcessLock();
609 /* Allocate a CSR Thread Structure */
610 CsrThread
= CsrAllocateThread(CsrProcess
);
613 DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__
);
614 CsrReleaseProcessLock();
615 return STATUS_NO_MEMORY
;
618 /* Save the data we have */
619 CsrThread
->CreateTime
= KernelTimes
.CreateTime
;
620 CsrThread
->ClientId
= *ClientId
;
621 CsrThread
->ThreadHandle
= hThread
;
622 ProtectHandle(hThread
);
623 CsrThread
->Flags
= 0;
625 /* Insert the Thread into the Process */
626 CsrInsertThread(CsrProcess
, CsrThread
);
628 /* Release the lock and return */
629 CsrReleaseProcessLock();
630 return STATUS_SUCCESS
;
634 * @name CsrDereferenceThread
637 * The CsrDereferenceThread routine removes a reference from a CSR Thread.
640 * Pointer to the CSR Thread to dereference.
644 * @remarks If the reference count has reached zero (ie: the CSR Thread has
645 * no more active references), it will be deleted.
650 CsrDereferenceThread(IN PCSR_THREAD CsrThread
)
652 /* Acquire process lock */
653 CsrAcquireProcessLock();
655 /* Decrease reference count */
656 ASSERT(CsrThread
->ReferenceCount
> 0);
657 if (!(--CsrThread
->ReferenceCount
))
659 /* Call the generic cleanup code */
660 CsrThreadRefcountZero(CsrThread
);
664 /* Just release the lock */
665 CsrReleaseProcessLock();
670 * @name CsrExecServerThread
673 * The CsrExecServerThread routine creates an NT Thread and then
674 * initializes a CSR Thread for it.
676 * @param ThreadHandler
677 * Pointer to the thread's startup routine.
680 * Initial CSR Thread Flags to set to the CSR Thread.
682 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
685 * @remarks This routine is similar to CsrAddStaticServerThread, but it
686 * also creates an NT Thread instead of expecting one to already
692 CsrExecServerThread(IN PVOID ThreadHandler
,
695 PCSR_THREAD CsrThread
;
700 /* Acquire process lock */
701 CsrAcquireProcessLock();
703 /* Allocate a CSR Thread in the Root Process */
704 ASSERT(CsrRootProcess
!= NULL
);
705 CsrThread
= CsrAllocateThread(CsrRootProcess
);
709 CsrReleaseProcessLock();
710 return STATUS_NO_MEMORY
;
713 /* Create the Thread */
714 Status
= RtlCreateUserThread(NtCurrentProcess(),
724 if (!NT_SUCCESS(Status
))
727 CsrDeallocateThread(CsrThread
);
728 CsrReleaseProcessLock();
732 /* Setup the Thread Object */
733 CsrThread
->ThreadHandle
= hThread
;
734 ProtectHandle(hThread
);
735 CsrThread
->ClientId
= ClientId
;
736 CsrThread
->Flags
= Flags
;
738 /* Insert it into the Thread List */
739 InsertHeadList(&CsrRootProcess
->ThreadList
, &CsrThread
->Link
);
741 /* Increase the thread count */
742 CsrRootProcess
->ThreadCount
++;
745 CsrReleaseProcessLock();
750 * @name CsrDestroyThread
753 * The CsrDestroyThread routine destroys the CSR Thread corresponding to
757 * Pointer to the Client ID Structure corresponding to the CSR
758 * Thread which is about to be destroyed.
760 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
761 * if the CSR Thread is already terminating.
768 CsrDestroyThread(IN PCLIENT_ID Cid
)
770 CLIENT_ID ClientId
= *Cid
;
771 PCSR_THREAD CsrThread
;
772 PCSR_PROCESS CsrProcess
;
775 CsrAcquireProcessLock();
777 /* Find the thread */
778 CsrThread
= CsrLocateThreadByClientId(&CsrProcess
,
781 /* Make sure we got one back, and that it's not already gone */
782 if (!CsrThread
|| CsrThread
->Flags
& CsrThreadTerminated
)
784 /* Release the lock and return failure */
785 CsrReleaseProcessLock();
786 return STATUS_THREAD_IS_TERMINATING
;
789 /* Set the terminated flag */
790 CsrThread
->Flags
|= CsrThreadTerminated
;
792 /* Acquire the Wait Lock */
793 CsrAcquireWaitLock();
795 /* Do we have an active wait block? */
796 if (CsrThread
->WaitBlock
)
798 /* Notify waiters of termination */
799 CsrNotifyWaitBlock(CsrThread
->WaitBlock
,
803 CsrProcessTerminating
,
807 /* Release the Wait Lock */
808 CsrReleaseWaitLock();
810 /* Dereference the thread */
811 CsrLockedDereferenceThread(CsrThread
);
813 /* Release the Process Lock and return success */
814 CsrReleaseProcessLock();
815 return STATUS_SUCCESS
;
819 * @name CsrImpersonateClient
822 * The CsrImpersonateClient will impersonate the given CSR Thread.
825 * Pointer to the CSR Thread to impersonate.
827 * @return TRUE if impersionation suceeded, false otherwise.
829 * @remarks Impersonation can be recursive.
834 CsrImpersonateClient(IN PCSR_THREAD CsrThread
)
837 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
839 /* Use the current thread if none given */
840 if (!CsrThread
) CsrThread
= CurrentThread
;
842 /* Still no thread, something is wrong */
843 if (!CsrThread
) return FALSE
;
846 Status
= NtImpersonateThread(NtCurrentThread(),
847 CsrThread
->ThreadHandle
,
849 if (!NT_SUCCESS(Status
))
851 DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status
);
852 if (Status
!= STATUS_BAD_IMPERSONATION_LEVEL
) DbgBreakPoint();
856 /* Increase the impersonation count for the current thread and return */
857 if (CurrentThread
) ++CurrentThread
->ImpersonationCount
;
862 * @name CsrRevertToSelf
865 * The CsrRevertToSelf routine will attempt to remove an active impersonation.
869 * @return TRUE if the reversion was succesful, false otherwise.
871 * @remarks Impersonation can be recursive; as such, the impersonation token
872 * will only be deleted once the CSR Thread's impersonaton count
878 CsrRevertToSelf(VOID
)
881 PCSR_THREAD CurrentThread
= NtCurrentTeb()->CsrClientThread
;
882 HANDLE ImpersonationToken
= NULL
;
884 /* Check if we have a Current Thread */
887 /* Make sure impersonation is on */
888 if (!CurrentThread
->ImpersonationCount
)
890 DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n");
894 else if (--CurrentThread
->ImpersonationCount
> 0)
896 /* Success; impersonation count decreased but still not zero */
901 /* Impersonation has been totally removed, revert to ourselves */
902 Status
= NtSetInformationThread(NtCurrentThread(),
903 ThreadImpersonationToken
,
907 /* Return TRUE or FALSE */
908 ASSERT(NT_SUCCESS(Status
));
909 return NT_SUCCESS(Status
);
913 * @name CsrLockThreadByClientId
916 * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
917 * to the given Thread ID and optionally returns it.
920 * Thread ID corresponding to the CSR Thread which will be locked.
923 * Optional pointer to a CSR Thread pointer which will hold the
924 * CSR Thread corresponding to the given Thread ID.
926 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
929 * @remarks Locking a CSR Thread is defined as acquiring an extra
930 * reference to it and returning with the Process Lock held.
935 CsrLockThreadByClientId(IN HANDLE Tid
,
936 OUT PCSR_THREAD
*CsrThread
)
938 PLIST_ENTRY NextEntry
;
939 PCSR_THREAD CurrentThread
= NULL
;
940 NTSTATUS Status
= STATUS_UNSUCCESSFUL
;
943 /* Acquire the lock */
944 CsrAcquireProcessLock();
947 ASSERT(CsrThread
!= NULL
);
950 /* Convert to Hash */
951 i
= CsrHashThread(Tid
);
953 /* Setup the List Pointers */
954 NextEntry
= CsrThreadHashTable
[i
].Flink
;
957 while (NextEntry
!= &CsrThreadHashTable
[i
])
959 /* Get the Process */
960 CurrentThread
= CONTAINING_RECORD(NextEntry
, CSR_THREAD
, HashLinks
);
962 /* Check for PID Match */
963 if ((CurrentThread
->ClientId
.UniqueThread
== Tid
) &&
964 !(CurrentThread
->Flags
& CsrThreadTerminated
))
966 /* Get out of here */
971 NextEntry
= NextEntry
->Flink
;
974 /* Nothing found if we got back to the list */
975 if (NextEntry
== &CsrThreadHashTable
[i
]) CurrentThread
= NULL
;
977 /* Did the loop find something? */
980 /* Reference the found thread */
981 Status
= STATUS_SUCCESS
;
982 CurrentThread
->ReferenceCount
++;
983 *CsrThread
= CurrentThread
;
987 /* Nothing found, release the lock */
988 Status
= STATUS_UNSUCCESSFUL
;
989 CsrReleaseProcessLock();
992 /* Return the status */
997 * @name CsrReferenceThread
1000 * The CsrReferenceThread routine increases the active reference count of
1004 * Pointer to the CSR Thread whose reference count will be increased.
1008 * @remarks Do not use this routine if the Process Lock is already held.
1013 CsrReferenceThread(PCSR_THREAD CsrThread
)
1015 /* Acquire process lock */
1016 CsrAcquireProcessLock();
1019 ASSERT(CsrThread
->Flags
& CsrThreadTerminated
); // CSR_THREAD_DESTROYED in ASSERT
1020 ASSERT(CsrThread
->ReferenceCount
!= 0);
1022 /* Increment reference count */
1023 CsrThread
->ReferenceCount
++;
1025 /* Release the lock */
1026 CsrReleaseProcessLock();
1030 * @name CsrUnlockThread
1033 * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
1036 * Pointer to a previously locked CSR Thread.
1038 * @return STATUS_SUCCESS.
1040 * @remarks This routine must be called with the Process Lock held.
1045 CsrUnlockThread(PCSR_THREAD CsrThread
)
1047 /* Dereference the Thread */
1048 ASSERT(ProcessStructureListLocked());
1049 CsrLockedDereferenceThread(CsrThread
);
1051 /* Release the lock and return */
1052 CsrReleaseProcessLock();
1053 return STATUS_SUCCESS
;