ReactOS  0.4.14-dev-57-g333b8f1
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);
129  CsrLockedReferenceProcess(CsrProcess);
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 */
255  if (!CsrProcess) CsrProcess = CsrRootProcess;
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 */
448  CsrDereferenceProcess(CsrProcess);
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 */
478  CsrThreadRefcountZero(CsrThread);
479  }
480 }
481 
482 
483 /* PUBLIC FUNCTIONS ***********************************************************/
484 
485 /*++
486  * @name CsrAddStaticServerThread
487  * @implemented NT4
488  *
489  * The CsrAddStaticServerThread routine adds a new CSR Thread to the
490  * CSR Server Process (CsrRootProcess).
491  *
492  * @param hThread
493  * Handle to an existing NT Thread to which to associate this
494  * CSR Thread.
495  *
496  * @param ClientId
497  * Pointer to the Client ID structure of the NT Thread to associate
498  * with this CSR Thread.
499  *
500  * @param ThreadFlags
501  * Initial CSR Thread Flags to associate to this CSR Thread. Usually
502  * CsrThreadIsServerThread.
503  *
504  * @return Pointer to the newly allocated CSR Thread.
505  *
506  * @remarks None.
507  *
508  *--*/
510 NTAPI
513  IN ULONG ThreadFlags)
514 {
515  PCSR_THREAD CsrThread;
516 
517  /* Get the Lock */
519 
520  /* Allocate the Server Thread */
521  CsrThread = CsrAllocateThread(CsrRootProcess);
522  if (CsrThread)
523  {
524  /* Setup the Object */
525  CsrThread->ThreadHandle = hThread;
527  CsrThread->ClientId = *ClientId;
528  CsrThread->Flags = ThreadFlags;
529 
530  /* Insert it into the Thread List */
532 
533  /* Increment the thread count */
535  }
536  else
537  {
538  DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread);
539  }
540 
541  /* Release the Process Lock and return */
543  return CsrThread;
544 }
545 
546 /*++
547  * @name CsrCreateRemoteThread
548  * @implemented NT4
549  *
550  * The CsrCreateRemoteThread routine creates a CSR Thread object for
551  * an NT Thread which is not part of the current NT Process.
552  *
553  * @param hThread
554  * Handle to an existing NT Thread to which to associate this
555  * CSR Thread.
556  *
557  * @param ClientId
558  * Pointer to the Client ID structure of the NT Thread to associate
559  * with this CSR Thread.
560  *
561  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
562  *
563  * @remarks None.
564  *
565  *--*/
566 NTSTATUS
567 NTAPI
570 {
572  HANDLE ThreadHandle;
573  PCSR_THREAD CsrThread;
574  PCSR_PROCESS CsrProcess;
575  KERNEL_USER_TIMES KernelTimes;
576 
577  /* Get the Thread Create Time */
579  ThreadTimes,
580  &KernelTimes,
581  sizeof(KernelTimes),
582  NULL);
583  if (!NT_SUCCESS(Status))
584  {
585  DPRINT1("Failed to query thread times: %lx\n", Status);
586  return Status;
587  }
588 
589  /* Lock the Owner Process */
591  if (!NT_SUCCESS(Status))
592  {
593  DPRINT1("No known process for %lx\n", ClientId->UniqueProcess);
594  return Status;
595  }
596 
597  /* Make sure the thread didn't terminate */
598  if (KernelTimes.ExitTime.QuadPart)
599  {
600  /* Unlock the process and return */
601  CsrUnlockProcess(CsrProcess);
602  DPRINT1("Dead thread: %I64x\n", KernelTimes.ExitTime.QuadPart);
604  }
605 
606  /* Allocate a CSR Thread Structure */
607  CsrThread = CsrAllocateThread(CsrProcess);
608  if (!CsrThread)
609  {
610  DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
611  CsrUnlockProcess(CsrProcess);
612  return STATUS_NO_MEMORY;
613  }
614 
615  /* Duplicate the Thread Handle */
617  hThread,
619  &ThreadHandle,
620  0,
621  0,
623  /* Allow failure */
624  if (!NT_SUCCESS(Status))
625  {
626  DPRINT1("Thread duplication failed: %lx\n", Status);
627  ThreadHandle = hThread;
628  }
629 
630  /* Save the data we have */
631  CsrThread->CreateTime = KernelTimes.CreateTime;
632  CsrThread->ClientId = *ClientId;
633  CsrThread->ThreadHandle = ThreadHandle;
634  ProtectHandle(ThreadHandle);
635  CsrThread->Flags = 0;
636 
637  /* Insert the Thread into the Process */
638  Status = CsrInsertThread(CsrProcess, CsrThread);
639  if (!NT_SUCCESS(Status))
640  {
641  /* Bail out */
642  if (CsrThread->ThreadHandle != hThread) NtClose(CsrThread->ThreadHandle);
643  CsrUnlockProcess(CsrProcess);
644  CsrDeallocateThread(CsrThread);
645  return Status;
646  }
647 
648  /* Release the lock and return */
649  CsrUnlockProcess(CsrProcess);
650  return STATUS_SUCCESS;
651 }
652 
653 /*++
654  * @name CsrCreateThread
655  * @implemented NT4
656  *
657  * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
658  *
659  * @param CsrProcess
660  * Pointer to the CSR Process which will contain the CSR Thread.
661  *
662  * @param hThread
663  * Handle to an existing NT Thread to which to associate this
664  * CSR Thread.
665  *
666  * @param ClientId
667  * Pointer to the Client ID structure of the NT Thread to associate
668  * with this CSR Thread.
669  *
670  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
671  *
672  * @remarks None.
673  *
674  *--*/
675 NTSTATUS
676 NTAPI
678  IN HANDLE hThread,
680  IN BOOLEAN HaveClient)
681 {
683  PCSR_THREAD CsrThread, CurrentThread;
685  CLIENT_ID CurrentCid;
686  KERNEL_USER_TIMES KernelTimes;
687 
688  if (HaveClient)
689  {
690  /* Get the current thread and CID */
691  CurrentThread = CsrGetClientThread();
692  CurrentCid = CurrentThread->ClientId;
693 
694  /* Acquire the Process Lock */
696 
697  /* Get the current Process and make sure the Thread is valid with this CID */
698  CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
699 
700  /* Something is wrong if we get an empty thread back */
701  if (!CurrentThread)
702  {
703  DPRINT1("CSRSRV: %s: invalid thread!\n", __FUNCTION__);
706  }
707  }
708  else
709  {
710  /* Acquire the Process Lock */
712  }
713 
714  /* Get the Thread Create Time */
716  ThreadTimes,
717  &KernelTimes,
718  sizeof(KernelTimes),
719  NULL);
720  if (!NT_SUCCESS(Status))
721  {
723  return Status;
724  }
725 
726  /* Allocate a CSR Thread Structure */
727  CsrThread = CsrAllocateThread(CsrProcess);
728  if (!CsrThread)
729  {
730  DPRINT1("CSRSRV: %s: out of memory!\n", __FUNCTION__);
732  return STATUS_NO_MEMORY;
733  }
734 
735  /* Save the data we have */
736  CsrThread->CreateTime = KernelTimes.CreateTime;
737  CsrThread->ClientId = *ClientId;
738  CsrThread->ThreadHandle = hThread;
740  CsrThread->Flags = 0;
741 
742  /* Insert the Thread into the Process */
743  Status = CsrInsertThread(CsrProcess, CsrThread);
744  if (!NT_SUCCESS(Status))
745  {
746  /* Bail out */
747  CsrUnlockProcess(CsrProcess);
748  CsrDeallocateThread(CsrThread);
749  return Status;
750  }
751 
752  /* Release the lock and return */
754 
755  return STATUS_SUCCESS;
756 }
757 
758 /*++
759  * @name CsrDereferenceThread
760  * @implemented NT4
761  *
762  * The CsrDereferenceThread routine removes a reference from a CSR Thread.
763  *
764  * @param CsrThread
765  * Pointer to the CSR Thread to dereference.
766  *
767  * @return None.
768  *
769  * @remarks If the reference count has reached zero (ie: the CSR Thread has
770  * no more active references), it will be deleted.
771  *
772  *--*/
773 VOID
774 NTAPI
776 {
777  /* Acquire process lock */
779 
780  /* Decrease reference count */
781  ASSERT(CsrThread->ReferenceCount > 0);
782  if ((--CsrThread->ReferenceCount) == 0)
783  {
784  /* Call the generic cleanup code */
785  CsrThreadRefcountZero(CsrThread);
786  }
787  else
788  {
789  /* Just release the lock */
791  }
792 }
793 
794 /*++
795  * @name CsrDestroyThread
796  * @implemented NT4
797  *
798  * The CsrDestroyThread routine destroys the CSR Thread corresponding to
799  * a given Thread ID.
800  *
801  * @param Cid
802  * Pointer to the Client ID Structure corresponding to the CSR
803  * Thread which is about to be destroyed.
804  *
805  * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
806  * if the CSR Thread is already terminating.
807  *
808  * @remarks None.
809  *
810  *--*/
811 NTSTATUS
812 NTAPI
814 {
815  CLIENT_ID ClientId = *Cid;
816  PCSR_THREAD CsrThread;
817  PCSR_PROCESS CsrProcess;
818 
819  /* Acquire lock */
821 
822  /* Find the thread */
823  CsrThread = CsrLocateThreadByClientId(&CsrProcess,
824  &ClientId);
825 
826  /* Make sure we got one back, and that it's not already gone */
827  if (!CsrThread || (CsrThread->Flags & CsrThreadTerminated))
828  {
829  /* Release the lock and return failure */
832  }
833 
834  /* Set the terminated flag */
835  CsrThread->Flags |= CsrThreadTerminated;
836 
837  /* Acquire the Wait Lock */
839 
840  /* Do we have an active wait block? */
841  if (CsrThread->WaitBlock)
842  {
843  /* Notify waiters of termination */
844  CsrNotifyWaitBlock(CsrThread->WaitBlock,
845  NULL,
846  NULL,
847  NULL,
849  TRUE);
850  }
851 
852  /* Release the Wait Lock */
854 
855  /* Dereference the thread */
856  CsrLockedDereferenceThread(CsrThread);
857 
858  /* Release the Process Lock and return success */
860  return STATUS_SUCCESS;
861 }
862 
863 /*++
864  * @name CsrExecServerThread
865  * @implemented NT4
866  *
867  * The CsrExecServerThread routine creates an NT Thread and then
868  * initializes a CSR Thread for it.
869  *
870  * @param ThreadHandler
871  * Pointer to the thread's startup routine.
872  *
873  * @param Flags
874  * Initial CSR Thread Flags to set to the CSR Thread.
875  *
876  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
877  *
878  * @remarks This routine is similar to CsrAddStaticServerThread, but it
879  * also creates an NT Thread instead of expecting one to already
880  * exist.
881  *
882  *--*/
883 NTSTATUS
884 NTAPI
886  IN ULONG Flags)
887 {
888  PCSR_THREAD CsrThread;
889  HANDLE hThread;
892 
893  /* Acquire process lock */
895 
896  /* Allocate a CSR Thread in the Root Process */
898  CsrThread = CsrAllocateThread(CsrRootProcess);
899  if (!CsrThread)
900  {
901  /* Fail */
903  return STATUS_NO_MEMORY;
904  }
905 
906  /* Create the Thread */
908  NULL,
909  FALSE,
910  0,
911  0,
912  0,
913  ThreadHandler,
914  NULL,
915  &hThread,
916  &ClientId);
917  if (!NT_SUCCESS(Status))
918  {
919  /* Fail */
920  CsrDeallocateThread(CsrThread);
922  return Status;
923  }
924 
925  /* Setup the Thread Object */
926  CsrThread->ThreadHandle = hThread;
928  CsrThread->ClientId = ClientId;
929  CsrThread->Flags = Flags;
930 
931  /* Insert it into the Thread List */
933 
934  /* Increase the thread count */
936 
937  /* Return */
939  return Status;
940 }
941 
942 /*++
943  * @name CsrLockThreadByClientId
944  * @implemented NT4
945  *
946  * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
947  * to the given Thread ID and optionally returns it.
948  *
949  * @param Tid
950  * Thread ID corresponding to the CSR Thread which will be locked.
951  *
952  * @param CsrThread
953  * Optional pointer to a CSR Thread pointer which will hold the
954  * CSR Thread corresponding to the given Thread ID.
955  *
956  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL otherwise.
957  *
958  * @remarks Locking a CSR Thread is defined as acquiring an extra
959  * reference to it and returning with the Process Lock held.
960  *
961  *--*/
962 NTSTATUS
963 NTAPI
965  OUT PCSR_THREAD *CsrThread)
966 {
967  PLIST_ENTRY NextEntry;
968  PCSR_THREAD CurrentThread = NULL;
970  ULONG i;
971 
972  /* Acquire the lock */
974 
975  /* Assume failure */
976  ASSERT(CsrThread != NULL);
977  *CsrThread = NULL;
978 
979  /* Convert to Hash */
980  i = CsrHashThread(Tid);
981 
982  /* Setup the List Pointers */
983  NextEntry = CsrThreadHashTable[i].Flink;
984 
985  /* Start Loop */
986  while (NextEntry != &CsrThreadHashTable[i])
987  {
988  /* Get the Thread */
989  CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
990 
991  /* Check for TID Match */
992  if ((CurrentThread->ClientId.UniqueThread == Tid) &&
993  (CurrentThread->Flags & CsrThreadTerminated) == 0)
994  {
995  /* Get out of here */
996  break;
997  }
998 
999  /* Move to the next entry */
1000  NextEntry = NextEntry->Flink;
1001  }
1002 
1003  /* Nothing found if we got back to the list */
1004  if (NextEntry == &CsrThreadHashTable[i]) CurrentThread = NULL;
1005 
1006  /* Did the loop find something? */
1007  if (CurrentThread)
1008  {
1009  /* Reference the found thread */
1011  CsrLockedReferenceThread(CurrentThread);
1012  *CsrThread = CurrentThread;
1013  }
1014  else
1015  {
1016  /* Nothing found, release the lock */
1019  }
1020 
1021  /* Return the status */
1022  return Status;
1023 }
1024 
1025 /*++
1026  * @name CsrReferenceThread
1027  * @implemented NT4
1028  *
1029  * The CsrReferenceThread routine increases the active reference count of
1030  * a CSR Thread.
1031  *
1032  * @param CsrThread
1033  * Pointer to the CSR Thread whose reference count will be increased.
1034  *
1035  * @return None.
1036  *
1037  * @remarks Do not use this routine if the Process Lock is already held.
1038  *
1039  *--*/
1040 VOID
1041 NTAPI
1043 {
1044  /* Acquire process lock */
1046 
1047  /* Sanity checks */
1048  ASSERT((CsrThread->Flags & CsrThreadTerminated) == 0);
1049  ASSERT(CsrThread->ReferenceCount != 0);
1050 
1051  /* Increment reference count */
1052  CsrThread->ReferenceCount++;
1053 
1054  /* Release the lock */
1056 }
1057 
1058 /*++
1059  * @name CsrUnlockThread
1060  * @implemented NT4
1061  *
1062  * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
1063  *
1064  * @param CsrThread
1065  * Pointer to a previously locked CSR Thread.
1066  *
1067  * @return STATUS_SUCCESS.
1068  *
1069  * @remarks This routine must be called with the Process Lock held.
1070  *
1071  *--*/
1072 NTSTATUS
1073 NTAPI
1075 {
1076  /* Dereference the Thread */
1078  CsrLockedDereferenceThread(CsrThread);
1079 
1080  /* Release the lock and return */
1082  return STATUS_SUCCESS;
1083 }
1084 
1085 /* EOF */
#define IN
Definition: typedefs.h:38
#define CsrGetClientThread()
Definition: csrsrv.h:77
#define TRUE
Definition: types.h:120
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
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:297
NTSTATUS NTAPI CsrLockThreadByClientId(IN HANDLE Tid, OUT PCSR_THREAD *CsrThread)
Definition: thredsup.c:964
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:690
NTSTATUS NTAPI CsrUnlockThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:1074
#define InsertTailList(ListHead, Entry)
HANDLE UniqueProcess
Definition: compat.h:474
#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:885
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
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
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
#define DUPLICATE_SAME_ACCESS
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp: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
smooth NULL
Definition: ftsmooth.c:416
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
struct _LIST_ENTRY * Flink
Definition: typedefs.h:119
ULONG CurrentProcess
Definition: shell.c:125
_Out_ PCLIENT_ID ClientId
Definition: kefuncs.h:1176
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:775
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:2653
NTSTATUS NTAPI NtQueryInformationThread(IN HANDLE ThreadHandle, IN THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL)
Definition: query.c:2497
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3399
HANDLE UniqueThread
Definition: compat.h:475
HANDLE ThreadHandle
Definition: csrsrv.h:71
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#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:117
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:1042
Status
Definition: gdiplustypes.h:24
#define NUMBER_THREAD_HASH_BUCKETS
Definition: api.h:44
#define CsrAcquireWaitLock()
Definition: api.h:21
struct _CSR_WAIT_BLOCK * WaitBlock
Definition: csrsrv.h:70
LIST_ENTRY ThreadList
Definition: csrsrv.h:40
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, IN HANDLE hThread, IN PCLIENT_ID ClientId, IN BOOLEAN HaveClient)
Definition: thredsup.c:677
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:813
#define HEAP_ZERO_MEMORY
Definition: compat.h:123
HANDLE hThread
Definition: wizard.c:27
#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:3407
#define OUT
Definition: typedefs.h:39
NTSTATUS NTAPI CsrCreateRemoteThread(IN HANDLE hThread, IN PCLIENT_ID ClientId)
Definition: thredsup.c:568
unsigned int ULONG
Definition: retypes.h:1
PCSR_THREAD NTAPI CsrAddStaticServerThread(IN HANDLE hThread, IN PCLIENT_ID ClientId, IN ULONG ThreadFlags)
Definition: thredsup.c:511
VOID NTAPI CsrLockedReferenceProcess(IN PCSR_PROCESS CsrProcess)
Definition: procsup.c:232
NTSTATUS NTAPI CsrInsertThread(IN PCSR_PROCESS Process, IN PCSR_THREAD Thread)
Definition: thredsup.c:297
ULONG Flags
Definition: csrsrv.h:72
HANDLE CsrHeap
Definition: init.c:25
return STATUS_SUCCESS
Definition: btrfs.c:2966
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:1398
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:112
VOID NTAPI CsrRemoveThread(IN PCSR_THREAD CsrThread)
Definition: thredsup.c:373
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68