ReactOS  0.4.15-dev-3295-gaa8fc87
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  *--*/
37 BOOLEAN
38 NTAPI
39 ProtectHandle(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  *--*/
76 BOOLEAN
77 NTAPI
78 UnProtectHandle(IN HANDLE ObjectHandle)
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  *--*/
118 NTAPI
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  *--*/
152 VOID
153 NTAPI
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  *--*/
181 NTAPI
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  *--*/
247 NTAPI
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  *--*/
295 NTSTATUS
296 NTAPI
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 */
324  InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
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  *--*/
343 VOID
344 NTAPI
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  *--*/
371 VOID
372 NTAPI
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  *--*/
422 VOID
423 NTAPI
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  *--*/
465 VOID
466 NTAPI
468 {
469  LONG LockCount;
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  *--*/
511 NTAPI
514  IN ULONG ThreadFlags)
515 {
516  PCSR_THREAD CsrThread;
517 
518  /* Get the Lock */
520 
521  /* Allocate the Server Thread */
522  CsrThread = CsrAllocateThread(CsrRootProcess);
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  *--*/
567 NTSTATUS
568 NTAPI
571 {
573  HANDLE ThreadHandle;
574  PCSR_THREAD CsrThread;
576  KERNEL_USER_TIMES KernelTimes;
577 
578  /* Get the Thread Create Time */
580  ThreadTimes,
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  *--*/
676 NTSTATUS
677 NTAPI
679  IN HANDLE hThread,
681  IN BOOLEAN HaveClient)
682 {
684  PCSR_THREAD CsrThread, CurrentThread;
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 */
717  ThreadTimes,
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  *--*/
774 VOID
775 NTAPI
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  *--*/
812 NTSTATUS
813 NTAPI
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 */
857  CsrLockedDereferenceThread(CsrThread);
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  *--*/
884 NTSTATUS
885 NTAPI
887  IN ULONG Flags)
888 {
889  PCSR_THREAD CsrThread;
890  HANDLE hThread;
893 
894  /* Acquire process lock */
896 
897  /* Allocate a CSR Thread in the Root Process */
899  CsrThread = CsrAllocateThread(CsrRootProcess);
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  *--*/
963 NTSTATUS
964 NTAPI
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  *--*/
1041 VOID
1042 NTAPI
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  *--*/
1073 NTSTATUS
1074 NTAPI
1076 {
1077  /* Dereference the Thread */
1079  CsrLockedDereferenceThread(CsrThread);
1080 
1081  /* Release the lock and return */
1083  return STATUS_SUCCESS;
1084 }
1085 
1086 /* EOF */
#define IN
Definition: typedefs.h:39
#define CsrGetClientThread()
Definition: csrsrv.h:77
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 CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:154
#define TRUE
Definition: types.h:120
FORCEINLINE VOID InsertHeadList(_Inout_ PLIST_ENTRY ListHead, _Inout_ __drv_aliasesMem PLIST_ENTRY Entry)
Definition: rtlfuncs.h:201
#define STATUS_THREAD_IS_TERMINATING
Definition: ntstatus.h:311
NTSTATUS NTAPI CsrLockThreadByClientId(IN HANDLE Tid, OUT PCSR_THREAD *CsrThread)
Definition: thredsup.c:965
LONG NTSTATUS
Definition: precomp.h:26
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
PCSR_THREAD NTAPI CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL, IN PCLIENT_ID Cid)
Definition: thredsup.c:248
LIST_ENTRY Link
Definition: csrsrv.h:66
struct _ThreadInfo ThreadInfo
VOID NTAPI CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:691
PKPROCESS CsrProcess
Definition: videoprt.c:39
NTSTATUS NTAPI CsrUnlockThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1075
#define InsertTailList(ListHead, Entry)
HANDLE UniqueProcess
Definition: compat.h:684
#define CsrReleaseWaitLock()
Definition: api.h:24
#define CsrReleaseProcessLock()
Definition: api.h:15
static int Link(const char **args)
Definition: vfdcmd.c:2414
VOID NTAPI CsrDeallocateThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:345
NTSTATUS NTAPI CsrExecServerThread(IN PVOID ThreadHandler, IN ULONG Flags)
Definition: thredsup.c:886
LONG LockCount
Definition: comsup.c:6
LARGE_INTEGER ExitTime
Definition: winternl.h:1061
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
PCSR_PROCESS CsrRootProcess
Definition: procsup.c:22
PCSR_PROCESS Process
Definition: csrsrv.h:69
#define ProcessStructureListLocked()
Definition: api.h:18
#define DUPLICATE_SAME_ACCESS
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
long LONG
Definition: pedump.c:60
NTSTATUS NTAPI NtSetInformationObject(IN HANDLE ObjectHandle, IN OBJECT_INFORMATION_CLASS ObjectInformationClass, IN PVOID ObjectInformation, IN ULONG Length)
Definition: oblife.c:1735
VOID NTAPI CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:467
unsigned char BOOLEAN
VOID NTAPI CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:424
NTSTATUS NTAPI CsrLockProcessByClientId(IN HANDLE Pid, OUT PCSR_PROCESS *CsrProcess OPTIONAL)
ULONG ThreadCount
Definition: csrsrv.h:55
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define NtCurrentProcess()
Definition: nt_native.h:1657
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
ULONG CurrentProcess
Definition: shell.c:125
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1163
#define ASSERT(a)
Definition: mode.c:44
LARGE_INTEGER CreateTime
Definition: csrsrv.h:65
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
CLIENT_ID ClientId
Definition: csrsrv.h:68
NTSTATUS NtQueryObject(IN HANDLE Handle, IN OBJECT_INFO_CLASS ObjectInformationClass, OUT PVOID ObjectInformation, IN ULONG ObjectInformationLength, OUT PULONG ReturnLength)
VOID NTAPI CsrDereferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:776
LARGE_INTEGER CreateTime
Definition: winternl.h:1060
#define CsrHashThread(t)
Definition: thredsup.c:17
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2652
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2624
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
HANDLE UniqueThread
Definition: compat.h:685
HANDLE ThreadHandle
Definition: csrsrv.h:71
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define CsrAcquireProcessLock()
Definition: api.h:12
LIST_ENTRY CsrThreadHashTable[NUMBER_THREAD_HASH_BUCKETS]
Definition: thredsup.c:21
Definition: typedefs.h:119
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)
VOID NTAPI CsrReferenceThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1043
#define NUMBER_THREAD_HASH_BUCKETS
Definition: api.h:44
#define CsrAcquireWaitLock()
Definition: api.h:21
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 _CSR_WAIT_BLOCK * WaitBlock
Definition: csrsrv.h:70
LIST_ENTRY ThreadList
Definition: csrsrv.h:40
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId, IN BOOLEAN HaveClient)
Definition: thredsup.c:678
#define NULL
Definition: types.h:112
PCSR_THREAD NTAPI CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL, IN PCLIENT_ID ClientId)
Definition: thredsup.c:182
NTSTATUS NTAPI CsrDestroyThread(IN PCLIENT_ID Cid)
Definition: thredsup.c:814
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
HANDLE hThread
Definition: wizard.c:28
#define DPRINT1
Definition: precomp.h:8
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:219
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:3406
#define OUT
Definition: typedefs.h:40
NTSTATUS NTAPI CsrCreateRemoteThread(IN HANDLE hThread, IN PCLIENT_ID ClientId)
Definition: thredsup.c:569
unsigned int ULONG
Definition: retypes.h:1
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags)
Definition: thredsup.c:512
VOID NTAPI CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:233
NTSTATUS NTAPI CsrInsertThread(IN PCSR_PROCESS Process, IN PCSR_THREAD Thread)
Definition: thredsup.c:297
ULONG Flags
Definition: csrsrv.h:72
#define STATUS_SUCCESS
Definition: shellext.h:65
HANDLE CsrHeap
Definition: init.c:25
BOOLEAN NTAPI UnProtectHandle(IN HANDLE ObjectHandle)
Definition: thredsup.c:78
#define __FUNCTION__
Definition: types.h:112
VOID NTAPI CsrLockedDereferenceProcess(PCSR_PROCESS CsrProcess)
Definition: procsup.c:159
NTSTATUS NTAPI CsrUnlockProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:1410
BOOLEAN NTAPI ProtectHandle(IN HANDLE ObjectHandle)
Definition: thredsup.c:39
PCSR_THREAD NTAPI CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
Definition: thredsup.c:119
LONGLONG QuadPart
Definition: typedefs.h:114
VOID NTAPI CsrRemoveThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:373
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68