ReactOS 0.4.16-dev-329-g9223134
thredsup.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Client/Server Runtime SubSystem
4 * FILE: subsystems/win32/csrsrv/thredsup.c
5 * PURPOSE: CSR Server DLL Thread Management
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 * Alex Ionescu (alex@relsoft.net)
8 */
9
10/* INCLUDES *******************************************************************/
11
12#include <srv.h>
13
14#define NDEBUG
15#include <debug.h>
16
17#define CsrHashThread(t) (HandleToUlong(t) % NUMBER_THREAD_HASH_BUCKETS)
18
19/* GLOBALS ********************************************************************/
20
22
23
24/* PRIVATE FUNCTIONS **********************************************************/
25
26/*++
27 * @name ProtectHandle
28 * @implemented NT5.2
29 *
30 * The ProtectHandle routine protects an object handle against closure.
31 *
32 * @return TRUE or FALSE.
33 *
34 * @remarks None.
35 *
36 *--*/
39ProtectHandle(IN HANDLE ObjectHandle)
40{
43
44 /* Query current state */
45 Status = NtQueryObject(ObjectHandle,
46 ObjectHandleFlagInformation,
47 &HandleInfo,
48 sizeof(HandleInfo),
49 NULL);
50 if (NT_SUCCESS(Status))
51 {
52 /* Enable protect from close */
53 HandleInfo.ProtectFromClose = TRUE;
54 Status = NtSetInformationObject(ObjectHandle,
55 ObjectHandleFlagInformation,
56 &HandleInfo,
57 sizeof(HandleInfo));
58 if (NT_SUCCESS(Status)) return TRUE;
59 }
60
61 /* We failed to or set the state */
62 return FALSE;
63}
64
65/*++
66 * @name UnProtectHandle
67 * @implemented NT5.2
68 *
69 * The UnProtectHandle routine unprotects an object handle against closure.
70 *
71 * @return TRUE or FALSE.
72 *
73 * @remarks None.
74 *
75 *--*/
79{
82
83 /* Query current state */
84 Status = NtQueryObject(ObjectHandle,
85 ObjectHandleFlagInformation,
86 &HandleInfo,
87 sizeof(HandleInfo),
88 NULL);
89 if (NT_SUCCESS(Status))
90 {
91 /* Disable protect from close */
92 HandleInfo.ProtectFromClose = FALSE;
93 Status = NtSetInformationObject(ObjectHandle,
94 ObjectHandleFlagInformation,
95 &HandleInfo,
96 sizeof(HandleInfo));
97 if (NT_SUCCESS(Status)) return TRUE;
98 }
99
100 /* We failed to or set the state */
101 return FALSE;
102}
103
104/*++
105 * @name CsrAllocateThread
106 *
107 * The CsrAllocateThread routine allocates a new CSR Thread object.
108 *
109 * @param CsrProcess
110 * Pointer to the CSR Process which will contain this CSR Thread.
111 *
112 * @return Pointer to the newly allocated CSR Thread.
113 *
114 * @remarks None.
115 *
116 *--*/
118NTAPI
120{
121 PCSR_THREAD CsrThread;
122
123 /* Allocate the structure */
124 CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
125 if (!CsrThread) return NULL;
126
127 /* Reference the Thread and Process */
128 CsrLockedReferenceThread(CsrThread);
130
131 /* Set the Parent Process */
132 CsrThread->Process = CsrProcess;
133
134 /* Return Thread */
135 return CsrThread;
136}
137
138/*++
139 * @name CsrLockedReferenceThread
140 *
141 * The CsrLockedReferenceThread references a CSR Thread while the
142 * Process Lock is already being held.
143 *
144 * @param CsrThread
145 * Pointer to the CSR Thread to be referenced.
146 *
147 * @return None.
148 *
149 * @remarks This routine will return with the Process Lock held.
150 *
151 *--*/
152VOID
153NTAPI
155{
156 /* Increment the reference count */
157 ++CsrThread->ReferenceCount;
158}
159
160/*++
161 * @name CsrLocateThreadByClientId
162 *
163 * The CsrLocateThreadByClientId routine locates the CSR Thread and,
164 * optionally, its parent CSR Process, corresponding to a Client ID.
165 *
166 * @param Process
167 * Optional pointer to a CSR Process pointer which will contain
168 * the CSR Thread's parent.
169 *
170 * @param ClientId
171 * Pointer to a Client ID structure containing the Unique Thread ID
172 * to look up.
173 *
174 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
175 * none was found.
176 *
177 * @remarks None.
178 *
179 *--*/
181NTAPI
184{
185 ULONG i;
186 PLIST_ENTRY ListHead, NextEntry;
187 PCSR_THREAD FoundThread;
188 // ASSERT(ProcessStructureListLocked());
189
190 if (Process) *Process = NULL;
191
192 /* Hash the Thread */
194
195 /* Set the list pointers */
196 ListHead = &CsrThreadHashTable[i];
197 NextEntry = ListHead->Flink;
198
199 /* Star the loop */
200 while (NextEntry != ListHead)
201 {
202 /* Get the thread */
203 FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
204
205 /* Move to the next entry */
206 NextEntry = NextEntry->Flink;
207
208 /* Compare the CID */
209 // if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
210 if ( FoundThread->ClientId.UniqueProcess == ClientId->UniqueProcess &&
211 FoundThread->ClientId.UniqueThread == ClientId->UniqueThread )
212 {
213 /* Match found, return the process */
214 if (Process) *Process = FoundThread->Process;
215
216 /* Return thread too */
217 return FoundThread;
218 }
219 }
220
221 /* Nothing found */
222 return NULL;
223}
224
225/*++
226 * @name CsrLocateThreadInProcess
227 *
228 * The CsrLocateThreadInProcess routine locates the CSR Thread
229 * corresponding to a Client ID inside a specific CSR Process.
230 *
231 * @param Process
232 * Optional pointer to the CSR Process which contains the CSR Thread
233 * that will be looked up.
234 *
235 * @param ClientId
236 * Pointer to a Client ID structure containing the Unique Thread ID
237 * to look up.
238 *
239 * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
240 * none was found.
241 *
242 * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
243 * CsrRootProcess.
244 *
245 *--*/
247NTAPI
249 IN PCLIENT_ID Cid)
250{
251 PLIST_ENTRY ListHead, NextEntry;
252 PCSR_THREAD FoundThread = NULL;
253
254 /* Use the Root Process if none was specified */
256
257 /* Save the List pointers */
258 ListHead = &CsrProcess->ThreadList;
259 NextEntry = ListHead->Flink;
260
261 /* Start the Loop */
262 while (NextEntry != ListHead)
263 {
264 /* Get Thread Entry */
265 FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
266
267 /* Check for TID Match */
268 if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
269
270 /* Move to the next entry */
271 NextEntry = NextEntry->Flink;
272 }
273
274 /* Return what we found */
275 return FoundThread;
276}
277
278/*++
279 * @name CsrInsertThread
280 *
281 * The CsrInsertThread routine inserts a CSR Thread into its parent's
282 * Thread List and into the Thread Hash Table.
283 *
284 * @param Process
285 * Pointer to the CSR Process containing this CSR Thread.
286 *
287 * @param Thread
288 * Pointer to the CSR Thread to be inserted.
289 *
290 * @return None.
291 *
292 * @remarks None.
293 *
294 *--*/
296NTAPI
299{
300 ULONG i;
303 // ASSERT(ProcessStructureListLocked());
304
305 /* Make sure the thread isn't already dead by the time we got this */
306 Status = NtQueryInformationThread(Thread->ThreadHandle,
308 &ThreadInfo,
309 sizeof(ThreadInfo),
310 NULL);
311 if (!NT_SUCCESS(Status)) return Status;
313
314 /* Insert it into the Regular List */
315 InsertTailList(&Process->ThreadList, &Thread->Link);
316
317 /* Increase Thread Count */
318 Process->ThreadCount++;
319
320 /* Hash the Thread */
321 i = CsrHashThread(Thread->ClientId.UniqueThread);
322
323 /* Insert it there too */
325 return STATUS_SUCCESS;
326}
327
328/*++
329 * @name CsrDeallocateThread
330 *
331 * The CsrDeallocateThread frees the memory associated with a CSR Thread.
332 *
333 * @param CsrThread
334 * Pointer to the CSR Thread to be freed.
335 *
336 * @return None.
337 *
338 * @remarks Do not call this routine. It is reserved for the internal
339 * thread management routines when a CSR Thread has been cleanly
340 * dereferenced and killed.
341 *
342 *--*/
343VOID
344NTAPI
346{
347 /* Free the process object from the heap */
348 // ASSERT(CsrThread->WaitBlock == NULL);
349 RtlFreeHeap(CsrHeap, 0, CsrThread);
350}
351
352/*++
353 * @name CsrRemoveThread
354 *
355 * The CsrRemoveThread function undoes a CsrInsertThread operation and
356 * removes the CSR Thread from the the Hash Table and Thread List.
357 *
358 * @param CsrThread
359 * Pointer to the CSR Thread to remove.
360 *
361 * @return None.
362 *
363 * @remarks If this CSR Thread is the last one inside a CSR Process, the
364 * parent will be dereferenced and the CsrProcessLastThreadTerminated
365 * flag will be set.
366 *
367 * After executing this routine, the CSR Thread will have the
368 * CsrThreadInTermination flag set.
369 *
370 *--*/
371VOID
372NTAPI
374{
376
377 /* Remove it from the List */
378 RemoveEntryList(&CsrThread->Link);
379
380 /* Decreate the thread count of the process */
381 CsrThread->Process->ThreadCount--;
382
383 /* Remove it from the Hash List as well */
384 if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
385
386 /* Check if this is the last Thread */
387 if (CsrThread->Process->ThreadCount == 0)
388 {
389 /* Check if it's not already been marked for deletion */
390 if ((CsrThread->Process->Flags & CsrProcessLastThreadTerminated) == 0)
391 {
392 /* Let everyone know this process is about to lose the thread */
393 CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
394
395 /* Reference the Process */
396 CsrLockedDereferenceProcess(CsrThread->Process);
397 }
398 }
399
400 /* Mark the thread for deletion */
401 CsrThread->Flags |= CsrThreadInTermination;
402}
403
404/*++
405 * @name CsrThreadRefcountZero
406 *
407 * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
408 * all its active references. It removes and de-allocates the CSR Thread.
409 *
410 * @param CsrThread
411 * Pointer to the CSR Thread that is to be deleted.
412 *
413 * @return None.
414 *
415 * @remarks Do not call this routine. It is reserved for the internal
416 * thread management routines when a CSR Thread has lost all
417 * its references.
418 *
419 * This routine is called with the Process Lock held.
420 *
421 *--*/
422VOID
423NTAPI
425{
426 PCSR_PROCESS CsrProcess = CsrThread->Process;
429
430 /* Remove this thread */
431 CsrRemoveThread(CsrThread);
432
433 /* Release the Process Lock */
435
436 /* Close the NT Thread Handle */
437 if (CsrThread->ThreadHandle)
438 {
439 UnProtectHandle(CsrThread->ThreadHandle);
440 Status = NtClose(CsrThread->ThreadHandle);
442 }
443
444 /* De-allocate the CSR Thread Object */
445 CsrDeallocateThread(CsrThread);
446
447 /* Remove a reference from the process */
449}
450
451/*++
452 * @name CsrLockedDereferenceThread
453 *
454 * The CsrLockedDereferenceThread dereferences a CSR Thread while the
455 * Process Lock is already being held.
456 *
457 * @param CsrThread
458 * Pointer to the CSR Thread to be dereferenced.
459 *
460 * @return None.
461 *
462 * @remarks This routine will return with the Process Lock held.
463 *
464 *--*/
465VOID
466NTAPI
468{
470
471 /* Decrease reference count */
472 LockCount = --CsrThread->ReferenceCount;
473 ASSERT(LockCount >= 0);
474 if (LockCount == 0)
475 {
476 /* Call the generic cleanup code */
477 CsrThreadRefcountZero(CsrThread);
478 /* Acquire the lock again, it was released by CsrThreadRefcountZero */
480 }
481}
482
483
484/* PUBLIC FUNCTIONS ***********************************************************/
485
486/*++
487 * @name CsrAddStaticServerThread
488 * @implemented NT4
489 *
490 * The CsrAddStaticServerThread routine adds a new CSR Thread to the
491 * CSR Server Process (CsrRootProcess).
492 *
493 * @param hThread
494 * Handle to an existing NT Thread to which to associate this
495 * CSR Thread.
496 *
497 * @param ClientId
498 * Pointer to the Client ID structure of the NT Thread to associate
499 * with this CSR Thread.
500 *
501 * @param ThreadFlags
502 * Initial CSR Thread Flags to associate to this CSR Thread. Usually
503 * CsrThreadIsServerThread.
504 *
505 * @return Pointer to the newly allocated CSR Thread.
506 *
507 * @remarks None.
508 *
509 *--*/
511NTAPI
514 IN ULONG ThreadFlags)
515{
516 PCSR_THREAD CsrThread;
517
518 /* Get the Lock */
520
521 /* Allocate the Server Thread */
523 if (CsrThread)
524 {
525 /* Setup the Object */
526 CsrThread->ThreadHandle = hThread;
528 CsrThread->ClientId = *ClientId;
529 CsrThread->Flags = ThreadFlags;
530
531 /* Insert it into the Thread List */
533
534 /* Increment the thread count */
536 }
537 else
538 {
539 DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread);
540 }
541
542 /* Release the Process Lock and return */
544 return CsrThread;
545}
546
547/*++
548 * @name CsrCreateRemoteThread
549 * @implemented NT4
550 *
551 * The CsrCreateRemoteThread routine creates a CSR Thread object for
552 * an NT Thread which is not part of the current NT Process.
553 *
554 * @param hThread
555 * Handle to an existing NT Thread to which to associate this
556 * CSR Thread.
557 *
558 * @param ClientId
559 * Pointer to the Client ID structure of the NT Thread to associate
560 * with this CSR Thread.
561 *
562 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
563 *
564 * @remarks None.
565 *
566 *--*/
568NTAPI
571{
573 HANDLE ThreadHandle;
574 PCSR_THREAD CsrThread;
576 KERNEL_USER_TIMES KernelTimes;
577
578 /* Get the Thread Create Time */
581 &KernelTimes,
582 sizeof(KernelTimes),
583 NULL);
584 if (!NT_SUCCESS(Status))
585 {
586 DPRINT1("Failed to query thread times: %lx\n", Status);
587 return Status;
588 }
589
590 /* Lock the Owner Process */
592 if (!NT_SUCCESS(Status))
593 {
594 DPRINT1("No known process for %lx\n", ClientId->UniqueProcess);
595 return Status;
596 }
597
598 /* Make sure the thread didn't terminate */
599 if (KernelTimes.ExitTime.QuadPart)
600 {
601 /* Unlock the process and return */
603 DPRINT1("Dead thread: %I64x\n", KernelTimes.ExitTime.QuadPart);
605 }
606
607 /* Allocate a CSR Thread Structure */
608 CsrThread = CsrAllocateThread(CsrProcess);
609 if (!CsrThread)
610 {
611 DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
613 return STATUS_NO_MEMORY;
614 }
615
616 /* Duplicate the Thread Handle */
618 hThread,
620 &ThreadHandle,
621 0,
622 0,
624 /* Allow failure */
625 if (!NT_SUCCESS(Status))
626 {
627 DPRINT1("Thread duplication failed: %lx\n", Status);
628 ThreadHandle = hThread;
629 }
630
631 /* Save the data we have */
632 CsrThread->CreateTime = KernelTimes.CreateTime;
633 CsrThread->ClientId = *ClientId;
634 CsrThread->ThreadHandle = ThreadHandle;
635 ProtectHandle(ThreadHandle);
636 CsrThread->Flags = 0;
637
638 /* Insert the Thread into the Process */
639 Status = CsrInsertThread(CsrProcess, CsrThread);
640 if (!NT_SUCCESS(Status))
641 {
642 /* Bail out */
643 if (CsrThread->ThreadHandle != hThread) NtClose(CsrThread->ThreadHandle);
645 CsrDeallocateThread(CsrThread);
646 return Status;
647 }
648
649 /* Release the lock and return */
651 return STATUS_SUCCESS;
652}
653
654/*++
655 * @name CsrCreateThread
656 * @implemented NT4
657 *
658 * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
659 *
660 * @param CsrProcess
661 * Pointer to the CSR Process which will contain the CSR Thread.
662 *
663 * @param hThread
664 * Handle to an existing NT Thread to which to associate this
665 * CSR Thread.
666 *
667 * @param ClientId
668 * Pointer to the Client ID structure of the NT Thread to associate
669 * with this CSR Thread.
670 *
671 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
672 *
673 * @remarks None.
674 *
675 *--*/
677NTAPI
681 IN BOOLEAN HaveClient)
682{
684 PCSR_THREAD CsrThread, CurrentThread;
685 PCSR_PROCESS CurrentProcess;
686 CLIENT_ID CurrentCid;
687 KERNEL_USER_TIMES KernelTimes;
688
689 if (HaveClient)
690 {
691 /* Get the current thread and CID */
692 CurrentThread = CsrGetClientThread();
693 CurrentCid = CurrentThread->ClientId;
694
695 /* Acquire the Process Lock */
697
698 /* Get the current Process and make sure the Thread is valid with this CID */
699 CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
700
701 /* Something is wrong if we get an empty thread back */
702 if (!CurrentThread)
703 {
704 DPRINT1("CSRSRV: %s: invalid thread!\n", __FUNCTION__);
707 }
708 }
709 else
710 {
711 /* Acquire the Process Lock */
713 }
714
715 /* Get the Thread Create Time */
718 &KernelTimes,
719 sizeof(KernelTimes),
720 NULL);
721 if (!NT_SUCCESS(Status))
722 {
724 return Status;
725 }
726
727 /* Allocate a CSR Thread Structure */
728 CsrThread = CsrAllocateThread(CsrProcess);
729 if (!CsrThread)
730 {
731 DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
733 return STATUS_NO_MEMORY;
734 }
735
736 /* Save the data we have */
737 CsrThread->CreateTime = KernelTimes.CreateTime;
738 CsrThread->ClientId = *ClientId;
739 CsrThread->ThreadHandle = hThread;
741 CsrThread->Flags = 0;
742
743 /* Insert the Thread into the Process */
744 Status = CsrInsertThread(CsrProcess, CsrThread);
745 if (!NT_SUCCESS(Status))
746 {
747 /* Bail out */
749 CsrDeallocateThread(CsrThread);
750 return Status;
751 }
752
753 /* Release the lock and return */
755
756 return STATUS_SUCCESS;
757}
758
759/*++
760 * @name CsrDereferenceThread
761 * @implemented NT4
762 *
763 * The CsrDereferenceThread routine removes a reference from a CSR Thread.
764 *
765 * @param CsrThread
766 * Pointer to the CSR Thread to dereference.
767 *
768 * @return None.
769 *
770 * @remarks If the reference count has reached zero (ie: the CSR Thread has
771 * no more active references), it will be deleted.
772 *
773 *--*/
774VOID
775NTAPI
777{
778 /* Acquire process lock */
780
781 /* Decrease reference count */
782 ASSERT(CsrThread->ReferenceCount > 0);
783 if ((--CsrThread->ReferenceCount) == 0)
784 {
785 /* Call the generic cleanup code */
786 CsrThreadRefcountZero(CsrThread);
787 }
788 else
789 {
790 /* Just release the lock */
792 }
793}
794
795/*++
796 * @name CsrDestroyThread
797 * @implemented NT4
798 *
799 * The CsrDestroyThread routine destroys the CSR Thread corresponding to
800 * a given Thread ID.
801 *
802 * @param Cid
803 * Pointer to the Client ID Structure corresponding to the CSR
804 * Thread which is about to be destroyed.
805 *
806 * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
807 * if the CSR Thread is already terminating.
808 *
809 * @remarks None.
810 *
811 *--*/
813NTAPI
815{
816 CLIENT_ID ClientId = *Cid;
817 PCSR_THREAD CsrThread;
819
820 /* Acquire lock */
822
823 /* Find the thread */
825 &ClientId);
826
827 /* Make sure we got one back, and that it's not already gone */
828 if (!CsrThread || (CsrThread->Flags & CsrThreadTerminated))
829 {
830 /* Release the lock and return failure */
833 }
834
835 /* Set the terminated flag */
836 CsrThread->Flags |= CsrThreadTerminated;
837
838 /* Acquire the Wait Lock */
840
841 /* Do we have an active wait block? */
842 if (CsrThread->WaitBlock)
843 {
844 /* Notify waiters of termination */
845 CsrNotifyWaitBlock(CsrThread->WaitBlock,
846 NULL,
847 NULL,
848 NULL,
850 TRUE);
851 }
852
853 /* Release the Wait Lock */
855
856 /* Dereference the thread */
858
859 /* Release the Process Lock and return success */
861 return STATUS_SUCCESS;
862}
863
864/*++
865 * @name CsrExecServerThread
866 * @implemented NT4
867 *
868 * The CsrExecServerThread routine creates an NT Thread and then
869 * initializes a CSR Thread for it.
870 *
871 * @param ThreadHandler
872 * Pointer to the thread's startup routine.
873 *
874 * @param Flags
875 * Initial CSR Thread Flags to set to the CSR Thread.
876 *
877 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
878 *
879 * @remarks This routine is similar to CsrAddStaticServerThread, but it
880 * also creates an NT Thread instead of expecting one to already
881 * exist.
882 *
883 *--*/
885NTAPI
887 IN ULONG Flags)
888{
889 PCSR_THREAD CsrThread;
893
894 /* Acquire process lock */
896
897 /* Allocate a CSR Thread in the Root Process */
900 if (!CsrThread)
901 {
902 /* Fail */
904 return STATUS_NO_MEMORY;
905 }
906
907 /* Create the Thread */
909 NULL,
910 FALSE,
911 0,
912 0,
913 0,
914 ThreadHandler,
915 NULL,
916 &hThread,
917 &ClientId);
918 if (!NT_SUCCESS(Status))
919 {
920 /* Fail */
921 CsrDeallocateThread(CsrThread);
923 return Status;
924 }
925
926 /* Setup the Thread Object */
927 CsrThread->ThreadHandle = hThread;
929 CsrThread->ClientId = ClientId;
930 CsrThread->Flags = Flags;
931
932 /* Insert it into the Thread List */
934
935 /* Increase the thread count */
937
938 /* Return */
940 return Status;
941}
942
943/*++
944 * @name CsrLockThreadByClientId
945 * @implemented NT4
946 *
947 * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
948 * to the given Thread ID and optionally returns it.
949 *
950 * @param Tid
951 * Thread ID corresponding to the CSR Thread which will be locked.
952 *
953 * @param CsrThread
954 * Optional pointer to a CSR Thread pointer which will hold the
955 * CSR Thread corresponding to the given Thread ID.
956 *
957 * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
958 *
959 * @remarks Locking a CSR Thread is defined as acquiring an extra
960 * reference to it and returning with the Process Lock held.
961 *
962 *--*/
964NTAPI
966 OUT PCSR_THREAD *CsrThread)
967{
968 PLIST_ENTRY NextEntry;
969 PCSR_THREAD CurrentThread = NULL;
971 ULONG i;
972
973 /* Acquire the lock */
975
976 /* Assume failure */
977 ASSERT(CsrThread != NULL);
978 *CsrThread = NULL;
979
980 /* Convert to Hash */
981 i = CsrHashThread(Tid);
982
983 /* Setup the List Pointers */
984 NextEntry = CsrThreadHashTable[i].Flink;
985
986 /* Start Loop */
987 while (NextEntry != &CsrThreadHashTable[i])
988 {
989 /* Get the Thread */
990 CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
991
992 /* Check for TID Match */
993 if ((CurrentThread->ClientId.UniqueThread == Tid) &&
994 (CurrentThread->Flags & CsrThreadTerminated) == 0)
995 {
996 /* Get out of here */
997 break;
998 }
999
1000 /* Move to the next entry */
1001 NextEntry = NextEntry->Flink;
1002 }
1003
1004 /* Nothing found if we got back to the list */
1005 if (NextEntry == &CsrThreadHashTable[i]) CurrentThread = NULL;
1006
1007 /* Did the loop find something? */
1008 if (CurrentThread)
1009 {
1010 /* Reference the found thread */
1012 CsrLockedReferenceThread(CurrentThread);
1013 *CsrThread = CurrentThread;
1014 }
1015 else
1016 {
1017 /* Nothing found, release the lock */
1020 }
1021
1022 /* Return the status */
1023 return Status;
1024}
1025
1026/*++
1027 * @name CsrReferenceThread
1028 * @implemented NT4
1029 *
1030 * The CsrReferenceThread routine increases the active reference count of
1031 * a CSR Thread.
1032 *
1033 * @param CsrThread
1034 * Pointer to the CSR Thread whose reference count will be increased.
1035 *
1036 * @return None.
1037 *
1038 * @remarks Do not use this routine if the Process Lock is already held.
1039 *
1040 *--*/
1041VOID
1042NTAPI
1044{
1045 /* Acquire process lock */
1047
1048 /* Sanity checks */
1049 ASSERT((CsrThread->Flags & CsrThreadTerminated) == 0);
1050 ASSERT(CsrThread->ReferenceCount != 0);
1051
1052 /* Increment reference count */
1053 CsrThread->ReferenceCount++;
1054
1055 /* Release the lock */
1057}
1058
1059/*++
1060 * @name CsrUnlockThread
1061 * @implemented NT4
1062 *
1063 * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
1064 *
1065 * @param CsrThread
1066 * Pointer to a previously locked CSR Thread.
1067 *
1068 * @return STATUS_SUCCESS.
1069 *
1070 * @remarks This routine must be called with the Process Lock held.
1071 *
1072 *--*/
1074NTAPI
1076{
1077 /* Dereference the Thread */
1079 CsrLockedDereferenceThread(CsrThread);
1080
1081 /* Release the lock and return */
1083 return STATUS_SUCCESS;
1084}
1085
1086/* EOF */
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
LONG LockCount
Definition: comsup.c:6
NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1410
#define CsrGetClientThread()
Definition: csrsrv.h:77
@ CsrProcessLastThreadTerminated
Definition: csrsrv.h:93
@ CsrProcessTerminating
Definition: csrsrv.h:85
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL)
@ CsrThreadTerminated
Definition: csrsrv.h:106
@ CsrThreadInTermination
Definition: csrsrv.h:105
VOID NTAPI CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:691
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
@ ThreadTimes
Definition: compat.h:936
@ ThreadIsTerminated
Definition: compat.h:955
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define __FUNCTION__
Definition: types.h:116
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define InsertHeadList(ListHead, Entry)
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _ThreadInfo ThreadInfo
#define ASSERT(a)
Definition: mode.c:44
NTSYSAPI NTSTATUS NTAPI RtlCreateUserThread(_In_ PVOID ThreadContext, _Out_ HANDLE *OutThreadHandle, _Reserved_ PVOID Reserved1, _Reserved_ PVOID Reserved2, _Reserved_ PVOID Reserved3, _Reserved_ PVOID Reserved4, _Reserved_ PVOID Reserved5, _Reserved_ PVOID Reserved6, _Reserved_ PVOID Reserved7, _Reserved_ PVOID Reserved8)
HANDLE hThread
Definition: wizard.c:28
#define NtCurrentProcess()
Definition: nt_native.h:1657
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
#define STATUS_THREAD_IS_TERMINATING
Definition: ntstatus.h:311
NTSTATUS NTAPI NtDuplicateObject(IN HANDLE SourceProcessHandle, IN HANDLE SourceHandle, IN HANDLE TargetProcessHandle OPTIONAL, OUT PHANDLE TargetHandle OPTIONAL, IN ACCESS_MASK DesiredAccess, IN ULONG HandleAttributes, IN ULONG Options)
Definition: obhandle.c:3410
NTSTATUS NTAPI NtSetInformationObject(IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, IN PVOID ObjectInformation, IN ULONG Length)
Definition: oblife.c:1824
long LONG
Definition: pedump.c:60
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
HANDLE UniqueThread
Definition: compat.h:826
HANDLE UniqueProcess
Definition: compat.h:825
ULONG ThreadCount
Definition: csrsrv.h:55
LIST_ENTRY ThreadList
Definition: csrsrv.h:40
ULONG Flags
Definition: csrsrv.h:72
LARGE_INTEGER CreateTime
Definition: csrsrv.h:65
struct _CSR_WAIT_BLOCK * WaitBlock
Definition: csrsrv.h:70
HANDLE ThreadHandle
Definition: csrsrv.h:71
CLIENT_ID ClientId
Definition: csrsrv.h:68
LIST_ENTRY Link
Definition: csrsrv.h:66
PCSR_PROCESS Process
Definition: csrsrv.h:69
LARGE_INTEGER CreateTime
Definition: winternl.h:1060
LARGE_INTEGER ExitTime
Definition: winternl.h:1061
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
PCSR_PROCESS CsrRootProcess
Definition: procsup.c:22
#define CsrAcquireWaitLock()
Definition: api.h:21
BOOLEAN NTAPI CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock, IN PLIST_ENTRY WaitList, IN PVOID WaitArgument1, IN PVOID WaitArgument2, IN ULONG WaitFlags, IN BOOLEAN DereferenceThread)
Definition: wait.c:120
VOID NTAPI CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:233
#define ProcessStructureListLocked()
Definition: api.h:18
#define CsrAcquireProcessLock()
Definition: api.h:12
HANDLE CsrHeap
Definition: init.c:25
#define CsrReleaseProcessLock()
Definition: api.h:15
#define CsrReleaseWaitLock()
Definition: api.h:24
VOID NTAPI CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
Definition: procsup.c:159
#define NUMBER_THREAD_HASH_BUCKETS
Definition: api.h:44
VOID NTAPI CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:154
NTSTATUS NTAPI CsrLockThreadByClientId(IN HANDLE Tid, OUT PCSR_THREAD *CsrThread)
Definition: thredsup.c:965
VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:424
VOID NTAPI CsrReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1043
NTSTATUS NTAPI CsrInsertThread(IN PCSR_PROCESS Process, IN PCSR_THREAD Thread)
Definition: thredsup.c:297
BOOLEAN NTAPI ProtectHandle(IN HANDLE ObjectHandle)
Definition: thredsup.c:39
NTSTATUS NTAPI CsrCreateRemoteThread(IN HANDLE hThread, IN PCLIENT_ID ClientId)
Definition: thredsup.c:569
VOID NTAPI CsrRemoveThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:373
#define CsrHashThread(t)
Definition: thredsup.c:17
BOOLEAN NTAPI UnProtectHandle(IN HANDLE ObjectHandle)
Definition: thredsup.c:78
NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId, IN BOOLEAN HaveClient)
Definition: thredsup.c:678
VOID NTAPI CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:467
NTSTATUS NTAPI CsrDestroyThread(IN PCLIENT_ID Cid)
Definition: thredsup.c:814
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:776
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags)
Definition: thredsup.c:512
VOID NTAPI CsrDeallocateThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:345
PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, IN PCLIENT_ID Cid)
Definition: thredsup.c:248
PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL, IN PCLIENT_ID ClientId)
Definition: thredsup.c:182
PCSR_THREAD NTAPI CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
Definition: thredsup.c:119
NTSTATUS NTAPI CsrUnlockThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1075
NTSTATUS NTAPI CsrExecServerThread(IN PVOID ThreadHandler, IN ULONG Flags)
Definition: thredsup.c:886
LIST_ENTRY CsrThreadHashTable[NUMBER_THREAD_HASH_BUCKETS]
Definition: thredsup.c:21
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
LONGLONG QuadPart
Definition: typedefs.h:114
static int Link(const char **args)
Definition: vfdcmd.c:2414
PKPROCESS CsrProcess
Definition: videoprt.c:39
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1151
#define DUPLICATE_SAME_ACCESS