ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

thread.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         ReactOS CSR Sub System
00004  * FILE:            subsys/csr/csrsrv/thread.c
00005  * PURPOSE:         CSR Server DLL Thread Implementation
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  */
00008 
00009 /* INCLUDES ******************************************************************/
00010 
00011 #include "srv.h"
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* DATA **********************************************************************/
00017 
00018 LIST_ENTRY CsrThreadHashTable[256];
00019 SECURITY_QUALITY_OF_SERVICE CsrSecurityQos =
00020 {
00021     sizeof(SECURITY_QUALITY_OF_SERVICE),
00022     SecurityImpersonation,
00023     SECURITY_STATIC_TRACKING,
00024     FALSE
00025 };
00026 
00027 /* PRIVATE FUNCTIONS *********************************************************/
00028 
00029 /*++
00030  * @name CsrAllocateThread
00031  *
00032  * The CsrAllocateThread routine allocates a new CSR Thread object.
00033  *
00034  * @param CsrProcess
00035  *        Pointer to the CSR Process which will contain this CSR Thread.
00036  *
00037  * @return Pointer to the newly allocated CSR Thread.
00038  *
00039  * @remarks None.
00040  *
00041  *--*/
00042 PCSR_THREAD
00043 NTAPI
00044 CsrAllocateThread(IN PCSR_PROCESS CsrProcess)
00045 {
00046     PCSR_THREAD CsrThread;
00047 
00048     /* Allocate the structure */
00049     CsrThread = RtlAllocateHeap(CsrHeap, HEAP_ZERO_MEMORY, sizeof(CSR_THREAD));
00050     if (!CsrThread) return NULL;
00051 
00052     /* Reference the Thread and Process */
00053     CsrThread->ReferenceCount++;
00054     CsrProcess->ReferenceCount++;
00055 
00056     /* Set the Parent Process */
00057     CsrThread->Process = CsrProcess;
00058 
00059     /* Return Thread */
00060     return CsrThread;
00061 }
00062 
00063 /*++
00064  * @name CsrLocateThreadByClientId
00065  *
00066  * The CsrLocateThreadByClientId routine locates the CSR Thread and,
00067  * optionally, its parent CSR Process, corresponding to a Client ID.
00068  *
00069  * @param Process
00070  *        Optional pointer to a CSR Process pointer which will contain
00071  *        the CSR Thread's parent.
00072  *
00073  * @param ClientId
00074  *        Pointer to a Client ID structure containing the Unique Thread ID
00075  *        to look up.
00076  *
00077  * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
00078  *         none was found.
00079  *
00080  * @remarks None.
00081  *
00082  *--*/
00083 PCSR_THREAD
00084 NTAPI
00085 CsrLocateThreadByClientId(OUT PCSR_PROCESS *Process OPTIONAL,
00086                           IN PCLIENT_ID ClientId)
00087 {
00088     ULONG i;
00089     PLIST_ENTRY NextEntry;
00090     PCSR_THREAD FoundThread;
00091     ASSERT(ProcessStructureListLocked());
00092 
00093     /* Hash the Thread */
00094     i = CsrHashThread(ClientId->UniqueThread);
00095 
00096     /* Set the list pointers */
00097     NextEntry = CsrThreadHashTable[i].Flink;
00098 
00099     /* Star the loop */
00100     while (NextEntry != &CsrThreadHashTable[i])
00101     {
00102         /* Get the thread */
00103         FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
00104 
00105         /* Compare the CID */
00106         if (*(PULONGLONG)&FoundThread->ClientId == *(PULONGLONG)ClientId)
00107         {
00108             /* Match found, return the process */
00109             *Process = FoundThread->Process;
00110 
00111             /* Return thread too */
00112             return FoundThread;
00113         }
00114 
00115         /* Next */
00116         NextEntry = NextEntry->Flink;
00117     }
00118 
00119     /* Nothing found */
00120     return NULL;
00121 }
00122 
00123 /*++
00124  * @name CsrLocateThreadInProcess
00125  *
00126  * The CsrLocateThreadInProcess routine locates the CSR Thread
00127  * corresponding to a Client ID inside a specific CSR Process.
00128  *
00129  * @param Process
00130  *        Optional pointer to the CSR Process which contains the CSR Thread
00131  *        that will be looked up.
00132  *
00133  * @param ClientId
00134  *        Pointer to a Client ID structure containing the Unique Thread ID
00135  *        to look up.
00136  *
00137  * @return Pointer to the CSR Thread corresponding to this CID, or NULL if
00138  *         none was found.
00139  *
00140  * @remarks If the CsrProcess argument is NULL, the lookup will be done inside
00141  *          CsrRootProcess.
00142  *
00143  *--*/
00144 PCSR_THREAD
00145 NTAPI
00146 CsrLocateThreadInProcess(IN PCSR_PROCESS CsrProcess OPTIONAL,
00147                          IN PCLIENT_ID Cid)
00148 {
00149     PLIST_ENTRY NextEntry;
00150     PCSR_THREAD FoundThread = NULL;
00151 
00152     /* Use the Root Process if none was specified */
00153     if (!CsrProcess) CsrProcess = CsrRootProcess;
00154 
00155     /* Save the List pointers */
00156     NextEntry = CsrProcess->ThreadList.Flink;
00157 
00158     /* Start the Loop */
00159     while (NextEntry != &CsrProcess->ThreadList)
00160     {
00161         /* Get Thread Entry */
00162         FoundThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link);
00163 
00164         /* Check for TID Match */
00165         if (FoundThread->ClientId.UniqueThread == Cid->UniqueThread) break;
00166 
00167         /* Next entry */
00168         NextEntry = NextEntry->Flink;
00169     }
00170 
00171     /* Return what we found */
00172     return FoundThread;
00173 }
00174 
00175 /*++
00176  * @name CsrInsertThread
00177  *
00178  * The CsrInsertThread routine inserts a CSR Thread into its parent's
00179  * Thread List and into the Thread Hash Table.
00180  *
00181  * @param Process
00182  *        Pointer to the CSR Process containing this CSR Thread.
00183  *
00184  * @param Thread
00185  *        Pointer to the CSR Thread to be inserted.
00186  *
00187  * @return None.
00188  *
00189  * @remarks None.
00190  *
00191  *--*/
00192 VOID
00193 NTAPI
00194 CsrInsertThread(IN PCSR_PROCESS Process,
00195                 IN PCSR_THREAD Thread)
00196 {
00197     ULONG i;
00198     ASSERT(ProcessStructureListLocked());
00199 
00200     /* Insert it into the Regular List */
00201     InsertTailList(&Process->ThreadList, &Thread->Link);
00202 
00203     /* Increase Thread Count */
00204     Process->ThreadCount++;
00205 
00206     /* Hash the Thread */
00207     i = CsrHashThread(Thread->ClientId.UniqueThread);
00208 
00209     /* Insert it there too */
00210     InsertHeadList(&CsrThreadHashTable[i], &Thread->HashLinks);
00211 }
00212 
00213 /*++
00214  * @name CsrDeallocateThread
00215  *
00216  * The CsrDeallocateThread frees the memory associated with a CSR Thread.
00217  *
00218  * @param CsrThread
00219  *        Pointer to the CSR Thread to be freed.
00220  *
00221  * @return None.
00222  *
00223  * @remarks Do not call this routine. It is reserved for the internal
00224  *          thread management routines when a CSR Thread has been cleanly
00225  *          dereferenced and killed.
00226  *
00227  *--*/
00228 VOID
00229 NTAPI
00230 CsrDeallocateThread(IN PCSR_THREAD CsrThread)
00231 {
00232     /* Free the process object from the heap */
00233     ASSERT(CsrThread->WaitBlock == NULL);
00234     RtlFreeHeap(CsrHeap, 0, CsrThread);
00235 }
00236 
00237 /*++
00238  * @name CsrLockedReferenceThread
00239  *
00240  * The CsrLockedReferenceThread refences a CSR Thread while the
00241  * Process Lock is already being held.
00242  *
00243  * @param CsrThread
00244  *        Pointer to the CSR Thread to be referenced.
00245  *
00246  * @return None.
00247  *
00248  * @remarks This routine will return with the Process Lock held.
00249  *
00250  *--*/
00251 VOID
00252 NTAPI
00253 CsrLockedReferenceThread(IN PCSR_THREAD CsrThread)
00254 {
00255     /* Increment the reference count */
00256     ++CsrThread->ReferenceCount;
00257 }
00258 
00259 /*++
00260  * @name CsrLockedDereferenceThread
00261  *
00262  * The CsrLockedDereferenceThread derefences a CSR Thread while the
00263  * Process Lock is already being held.
00264  *
00265  * @param CsrThread
00266  *        Pointer to the CSR Thread to be dereferenced.
00267  *
00268  * @return None.
00269  *
00270  * @remarks This routine will return with the Process Lock held.
00271  *
00272  *--*/
00273 VOID
00274 NTAPI
00275 CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread)
00276 {
00277     LONG LockCount;
00278 
00279     /* Decrease reference count */
00280     LockCount = --CsrThread->ReferenceCount;
00281     ASSERT(LockCount >= 0);
00282     if (!LockCount)
00283     {
00284         /* Call the generic cleanup code */
00285         CsrThreadRefcountZero(CsrThread);
00286         CsrAcquireProcessLock();
00287     }
00288 }
00289 
00290 /*++
00291  * @name CsrRemoveThread
00292  *
00293  * The CsrRemoveThread function undoes a CsrInsertThread operation and
00294  * removes the CSR Thread from the the Hash Table and Thread List.
00295  *
00296  * @param CsrThread
00297  *        Pointer to the CSR Thread to remove.
00298  *
00299  * @return None.
00300  *
00301  * @remarks If this CSR Thread is the last one inside a CSR Process, the
00302  *          parent will be dereferenced and the CsrProcessLastThreadTerminated
00303  *          flag will be set.
00304  *
00305  *          After executing this routine, the CSR Thread will have the
00306  *          CsrThreadInTermination flag set.
00307  *
00308  *--*/
00309 VOID
00310 NTAPI
00311 CsrRemoveThread(IN PCSR_THREAD CsrThread)
00312 {
00313     ASSERT(ProcessStructureListLocked());
00314 
00315     /* Remove it from the List */
00316     RemoveEntryList(&CsrThread->Link);
00317 
00318     /* Decreate the thread count of the process */
00319     --CsrThread->Process->ThreadCount;
00320 
00321     /* Remove it from the Hash List as well */
00322     if (CsrThread->HashLinks.Flink) RemoveEntryList(&CsrThread->HashLinks);
00323 
00324     /* Check if this is the last Thread */
00325     if (!CsrThread->Process->ThreadCount)
00326     {
00327         /* Check if it's not already been marked for deletion */
00328         if (!(CsrThread->Process->Flags & CsrProcessLastThreadTerminated))
00329         {
00330             /* Let everyone know this process is about to lose the thread */
00331             CsrThread->Process->Flags |= CsrProcessLastThreadTerminated;
00332 
00333             /* Reference the Process */
00334             CsrLockedDereferenceProcess(CsrThread->Process);
00335         }
00336     }
00337 
00338     /* Mark the thread for deletion */
00339     CsrThread->Flags |= CsrThreadInTermination;
00340 }
00341 
00342 /*++
00343  * @name CsrThreadRefcountZero
00344  *
00345  * The CsrThreadRefcountZero routine is executed when a CSR Thread has lost
00346  * all its active references. It removes and de-allocates the CSR Thread.
00347  *
00348  * @param CsrThread
00349  *        Pointer to the CSR Thread that is to be deleted.
00350  *
00351  * @return None.
00352  *
00353  * @remarks Do not call this routine. It is reserved for the internal
00354  *          thread management routines when a CSR Thread has lost all
00355  *          its references.
00356  *
00357  *          This routine is called with the Process Lock held.
00358  *
00359  *--*/
00360 VOID
00361 NTAPI
00362 CsrThreadRefcountZero(IN PCSR_THREAD CsrThread)
00363 {
00364     PCSR_PROCESS CsrProcess = CsrThread->Process;
00365     NTSTATUS Status;
00366 
00367     /* Remove this thread */
00368     CsrRemoveThread(CsrThread);
00369 
00370     /* Release the Process Lock */
00371     CsrReleaseProcessLock();
00372 
00373     /* Close the NT Thread Handle */
00374     UnProtectHandle(CsrThread->ThreadHandle);
00375     Status = NtClose(CsrThread->ThreadHandle);
00376     ASSERT(NT_SUCCESS(Status));
00377 
00378     /* De-allocate the CSR Thread Object */
00379     CsrDeallocateThread(CsrThread);
00380 
00381     /* Remove a reference from the process */
00382     CsrDereferenceProcess(CsrProcess);
00383 }
00384 
00385 /* PUBLIC FUNCTIONS ***********************************************************/
00386 
00387 /*++
00388  * @name CsrAddStaticServerThread
00389  * @implemented NT4
00390  *
00391  * The CsrAddStaticServerThread routine adds a new CSR Thread to the
00392  * CSR Server Process (CsrRootProcess).
00393  *
00394  * @param hThread
00395  *        Handle to an existing NT Thread to which to associate this
00396  *        CSR Thread.
00397  *
00398  * @param ClientId
00399  *        Pointer to the Client ID structure of the NT Thread to associate
00400  *        with this CSR Thread.
00401  *
00402  * @param ThreadFlags
00403  *        Initial CSR Thread Flags to associate to this CSR Thread. Usually
00404  *        CsrThreadIsServerThread.
00405  *
00406  * @return Pointer to the newly allocated CSR Thread.
00407  *
00408  * @remarks None.
00409  *
00410  *--*/
00411 PCSR_THREAD
00412 NTAPI
00413 CsrAddStaticServerThread(IN HANDLE hThread,
00414                          IN PCLIENT_ID ClientId,
00415                          IN ULONG ThreadFlags)
00416 {
00417     PCSR_THREAD CsrThread;
00418 
00419     /* Get the Lock */
00420     CsrAcquireProcessLock();
00421 
00422     /* Allocate the Server Thread */
00423     CsrThread = CsrAllocateThread(CsrRootProcess);
00424     if (CsrThread)
00425     {
00426         /* Setup the Object */
00427         CsrThread->ThreadHandle = hThread;
00428         ProtectHandle(hThread);
00429         CsrThread->ClientId = *ClientId;
00430         CsrThread->Flags = ThreadFlags;
00431 
00432         /* Insert it into the Thread List */
00433         InsertTailList(&CsrRootProcess->ThreadList, &CsrThread->Link);
00434 
00435         /* Increment the thread count */
00436         CsrRootProcess->ThreadCount++;
00437     }
00438     else
00439     {
00440         DPRINT1("CsrAddStaticServerThread: alloc failed for thread 0x%x\n", hThread);
00441     }
00442 
00443     /* Release the Process Lock and return */
00444     CsrReleaseProcessLock();
00445     return CsrThread;
00446 }
00447 
00448 /*++
00449  * @name CsrCreateRemoteThread
00450  * @implemented NT4
00451  *
00452  * The CsrCreateRemoteThread routine creates a CSR Thread object for
00453  * an NT Thread which is not part of the current NT Process.
00454  *
00455  * @param hThread
00456  *        Handle to an existing NT Thread to which to associate this
00457  *        CSR Thread.
00458  *
00459  * @param ClientId
00460  *        Pointer to the Client ID structure of the NT Thread to associate
00461  *        with this CSR Thread.
00462  *
00463  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00464  *         othwerwise.
00465  *
00466  * @remarks None.
00467  *
00468  *--*/
00469 NTSTATUS
00470 NTAPI
00471 CsrCreateRemoteThread(IN HANDLE hThread,
00472                       IN PCLIENT_ID ClientId)
00473 {
00474     NTSTATUS Status;
00475     HANDLE ThreadHandle;
00476     PCSR_THREAD CsrThread;
00477     PCSR_PROCESS CsrProcess;
00478     KERNEL_USER_TIMES KernelTimes;
00479 
00480     DPRINT("CSRSRV: %s called\n", __FUNCTION__);
00481 
00482     /* Get the Thread Create Time */
00483     Status = NtQueryInformationThread(hThread,
00484                                       ThreadTimes,
00485                                       &KernelTimes,
00486                                       sizeof(KernelTimes),
00487                                       NULL);
00488     if (!NT_SUCCESS(Status)) return Status;
00489 
00490     /* Lock the Owner Process */
00491     Status = CsrLockProcessByClientId(&ClientId->UniqueProcess, &CsrProcess);
00492 
00493     /* Make sure the thread didn't terminate */
00494     if (KernelTimes.ExitTime.QuadPart)
00495     {
00496         /* Unlock the process and return */
00497         CsrUnlockProcess(CsrProcess);
00498         return STATUS_THREAD_IS_TERMINATING;
00499     }
00500 
00501     /* Allocate a CSR Thread Structure */
00502     CsrThread = CsrAllocateThread(CsrProcess);
00503     if (!CsrThread)
00504     {
00505         DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
00506         CsrUnlockProcess(CsrProcess);
00507         return STATUS_NO_MEMORY;
00508     }
00509 
00510     /* Duplicate the Thread Handle */
00511     Status = NtDuplicateObject(NtCurrentProcess(),
00512                                hThread,
00513                                NtCurrentProcess(),
00514                                &ThreadHandle,
00515                                0,
00516                                0,
00517                                DUPLICATE_SAME_ACCESS);
00518     /* Allow failure */
00519     if (!NT_SUCCESS(Status)) ThreadHandle = hThread;
00520 
00521     /* Save the data we have */
00522     CsrThread->CreateTime = KernelTimes.CreateTime;
00523     CsrThread->ClientId = *ClientId;
00524     CsrThread->ThreadHandle = ThreadHandle;
00525     ProtectHandle(ThreadHandle);
00526     CsrThread->Flags = 0;
00527 
00528     /* Insert the Thread into the Process */
00529     CsrInsertThread(CsrProcess, CsrThread);
00530 
00531     /* Release the lock and return */
00532     CsrUnlockProcess(CsrProcess);
00533     return STATUS_SUCCESS;
00534 }
00535 
00536 /*++
00537  * @name CsrCreateThread
00538  * @implemented NT4
00539  *
00540  * The CsrCreateThread routine creates a CSR Thread object for an NT Thread.
00541  *
00542  * @param CsrProcess
00543  *        Pointer to the CSR Process which will contain the CSR Thread.
00544  *
00545  * @param hThread
00546  *        Handle to an existing NT Thread to which to associate this
00547  *        CSR Thread.
00548  *
00549  * @param ClientId
00550  *        Pointer to the Client ID structure of the NT Thread to associate
00551  *        with this CSR Thread.
00552  *
00553  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00554  *         othwerwise.
00555  *
00556  * @remarks None.
00557  *
00558  *--*/
00559 NTSTATUS
00560 NTAPI
00561 CsrCreateThread(IN PCSR_PROCESS CsrProcess,
00562                 IN HANDLE hThread,
00563                 IN PCLIENT_ID ClientId,
00564                 IN BOOLEAN HaveClient)
00565 {
00566     NTSTATUS Status;
00567     PCSR_THREAD CsrThread, CurrentThread;
00568     PCSR_PROCESS CurrentProcess;
00569     CLIENT_ID CurrentCid;
00570     KERNEL_USER_TIMES KernelTimes;
00571     DPRINT("CSRSRV: %s called\n", __FUNCTION__);
00572 
00573     if (HaveClient)
00574     {
00575         /* Get the current thread and CID */
00576         CurrentThread = NtCurrentTeb()->CsrClientThread;
00577         CurrentCid = CurrentThread->ClientId;
00578 
00579         /* Acquire the Process Lock */
00580         CsrAcquireProcessLock();
00581 
00582         /* Get the current Process and make sure the Thread is valid with this CID */
00583         CurrentThread = CsrLocateThreadByClientId(&CurrentProcess, &CurrentCid);
00584         if (!CurrentThread)
00585         {
00586             DPRINT1("CSRSRV:%s: invalid thread!\n", __FUNCTION__);
00587             CsrReleaseProcessLock();
00588             return STATUS_THREAD_IS_TERMINATING;
00589         }
00590     }
00591     else
00592     {
00593         /* Acquire the Process Lock */
00594         CsrAcquireProcessLock();
00595     }
00596 
00597     /* Get the Thread Create Time */
00598     Status = NtQueryInformationThread(hThread,
00599                                       ThreadTimes,
00600                                       (PVOID)&KernelTimes,
00601                                       sizeof(KernelTimes),
00602                                       NULL);
00603     if (!NT_SUCCESS(Status))
00604     {
00605         CsrReleaseProcessLock();
00606         return Status;
00607     }
00608 
00609     /* Allocate a CSR Thread Structure */
00610     CsrThread = CsrAllocateThread(CsrProcess);
00611     if (!CsrThread)
00612     {
00613         DPRINT1("CSRSRV:%s: out of memory!\n", __FUNCTION__);
00614         CsrReleaseProcessLock();
00615         return STATUS_NO_MEMORY;
00616     }
00617 
00618     /* Save the data we have */
00619     CsrThread->CreateTime = KernelTimes.CreateTime;
00620     CsrThread->ClientId = *ClientId;
00621     CsrThread->ThreadHandle = hThread;
00622     ProtectHandle(hThread);
00623     CsrThread->Flags = 0;
00624 
00625     /* Insert the Thread into the Process */
00626     CsrInsertThread(CsrProcess, CsrThread);
00627 
00628     /* Release the lock and return */
00629     CsrReleaseProcessLock();
00630     return STATUS_SUCCESS;
00631 }
00632 
00633 /*++
00634  * @name CsrDereferenceThread
00635  * @implemented NT4
00636  *
00637  * The CsrDereferenceThread routine removes a reference from a CSR Thread.
00638  *
00639  * @param CsrThread
00640  *        Pointer to the CSR Thread to dereference.
00641  *
00642  * @return None.
00643  *
00644  * @remarks If the reference count has reached zero (ie: the CSR Thread has
00645  *          no more active references), it will be deleted.
00646  *
00647  *--*/
00648 VOID
00649 NTAPI
00650 CsrDereferenceThread(IN PCSR_THREAD CsrThread)
00651 {
00652     /* Acquire process lock */
00653     CsrAcquireProcessLock();
00654 
00655     /* Decrease reference count */
00656     ASSERT(CsrThread->ReferenceCount > 0);
00657     if (!(--CsrThread->ReferenceCount))
00658     {
00659         /* Call the generic cleanup code */
00660         CsrThreadRefcountZero(CsrThread);
00661     }
00662     else
00663     {
00664         /* Just release the lock */
00665         CsrReleaseProcessLock();
00666     }
00667 }
00668 
00669 /*++
00670  * @name CsrExecServerThread
00671  * @implemented NT4
00672  *
00673  * The CsrExecServerThread routine creates an NT Thread and then
00674  * initializes a CSR Thread for it.
00675  *
00676  * @param ThreadHandler
00677  *        Pointer to the thread's startup routine.
00678  *
00679  * @param Flags
00680  *        Initial CSR Thread Flags to set to the CSR Thread.
00681  *
00682  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00683  *         othwerwise.
00684  *
00685  * @remarks This routine is similar to CsrAddStaticServerThread, but it
00686  *          also creates an NT Thread instead of expecting one to already
00687  *          exist.
00688  *
00689  *--*/
00690 NTSTATUS
00691 NTAPI
00692 CsrExecServerThread(IN PVOID ThreadHandler,
00693                     IN ULONG Flags)
00694 {
00695     PCSR_THREAD CsrThread;
00696     HANDLE hThread;
00697     CLIENT_ID ClientId;
00698     NTSTATUS Status;
00699 
00700     /* Acquire process lock */
00701     CsrAcquireProcessLock();
00702 
00703     /* Allocate a CSR Thread in the Root Process */
00704     ASSERT(CsrRootProcess != NULL);
00705     CsrThread = CsrAllocateThread(CsrRootProcess);
00706     if (!CsrThread)
00707     {
00708         /* Fail */
00709         CsrReleaseProcessLock();
00710         return STATUS_NO_MEMORY;
00711     }
00712 
00713     /* Create the Thread */
00714     Status = RtlCreateUserThread(NtCurrentProcess(),
00715                                  NULL,
00716                                  FALSE,
00717                                  0,
00718                                  0,
00719                                  0,
00720                                  ThreadHandler,
00721                                  NULL,
00722                                  &hThread,
00723                                  &ClientId);
00724     if (!NT_SUCCESS(Status))
00725     {
00726         /* Fail */
00727         CsrDeallocateThread(CsrThread);
00728         CsrReleaseProcessLock();
00729         return Status;
00730     }
00731 
00732     /* Setup the Thread Object */
00733     CsrThread->ThreadHandle = hThread;
00734     ProtectHandle(hThread);
00735     CsrThread->ClientId = ClientId;
00736     CsrThread->Flags = Flags;
00737 
00738     /* Insert it into the Thread List */
00739     InsertHeadList(&CsrRootProcess->ThreadList, &CsrThread->Link);
00740 
00741     /* Increase the thread count */
00742     CsrRootProcess->ThreadCount++;
00743 
00744     /* Return */
00745     CsrReleaseProcessLock();
00746     return Status;
00747 }
00748 
00749 /*++
00750  * @name CsrDestroyThread
00751  * @implemented NT4
00752  *
00753  * The CsrDestroyThread routine destroys the CSR Thread corresponding to
00754  * a given Thread ID.
00755  *
00756  * @param Cid
00757  *        Pointer to the Client ID Structure corresponding to the CSR
00758  *        Thread which is about to be destroyed.
00759  *
00760  * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING
00761  *         if the CSR Thread is already terminating.
00762  *
00763  * @remarks None.
00764  *
00765  *--*/
00766 NTSTATUS
00767 NTAPI
00768 CsrDestroyThread(IN PCLIENT_ID Cid)
00769 {
00770     CLIENT_ID ClientId = *Cid;
00771     PCSR_THREAD CsrThread;
00772     PCSR_PROCESS CsrProcess;
00773 
00774     /* Acquire lock */
00775     CsrAcquireProcessLock();
00776 
00777     /* Find the thread */
00778     CsrThread = CsrLocateThreadByClientId(&CsrProcess,
00779                                           &ClientId);
00780 
00781     /* Make sure we got one back, and that it's not already gone */
00782     if (!CsrThread || CsrThread->Flags & CsrThreadTerminated)
00783     {
00784         /* Release the lock and return failure */
00785         CsrReleaseProcessLock();
00786         return STATUS_THREAD_IS_TERMINATING;
00787     }
00788 
00789     /* Set the terminated flag */
00790     CsrThread->Flags |= CsrThreadTerminated;
00791 
00792     /* Acquire the Wait Lock */
00793     CsrAcquireWaitLock();
00794 
00795     /* Do we have an active wait block? */
00796     if (CsrThread->WaitBlock)
00797     {
00798         /* Notify waiters of termination */
00799         CsrNotifyWaitBlock(CsrThread->WaitBlock,
00800                            NULL,
00801                            NULL,
00802                            NULL,
00803                            CsrProcessTerminating,
00804                            TRUE);
00805     }
00806 
00807     /* Release the Wait Lock */
00808     CsrReleaseWaitLock();
00809 
00810     /* Dereference the thread */
00811     CsrLockedDereferenceThread(CsrThread);
00812 
00813     /* Release the Process Lock and return success */
00814     CsrReleaseProcessLock();
00815     return STATUS_SUCCESS;
00816 }
00817 
00818 /*++
00819  * @name CsrImpersonateClient
00820  * @implemented NT4
00821  *
00822  * The CsrImpersonateClient will impersonate the given CSR Thread.
00823  *
00824  * @param CsrThread
00825  *        Pointer to the CSR Thread to impersonate.
00826  *
00827  * @return TRUE if impersionation suceeded, false otherwise.
00828  *
00829  * @remarks Impersonation can be recursive.
00830  *
00831  *--*/
00832 BOOLEAN
00833 NTAPI
00834 CsrImpersonateClient(IN PCSR_THREAD CsrThread)
00835 {
00836     NTSTATUS Status;
00837     PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
00838 
00839     /* Use the current thread if none given */
00840     if (!CsrThread) CsrThread = CurrentThread;
00841 
00842     /* Still no thread, something is wrong */
00843     if (!CsrThread) return FALSE;
00844 
00845     /* Make the call */
00846     Status = NtImpersonateThread(NtCurrentThread(),
00847                                  CsrThread->ThreadHandle,
00848                                  &CsrSecurityQos);
00849     if (!NT_SUCCESS(Status))
00850     {
00851         DPRINT1("CSRSS: Can't impersonate client thread - Status = %lx\n", Status);
00852         if (Status != STATUS_BAD_IMPERSONATION_LEVEL) DbgBreakPoint();
00853         return FALSE;
00854     }
00855 
00856     /* Increase the impersonation count for the current thread and return */
00857     if (CurrentThread) ++CurrentThread->ImpersonationCount;
00858     return TRUE;
00859 }
00860 
00861 /*++
00862  * @name CsrRevertToSelf
00863  * @implemented NT4
00864  *
00865  * The CsrRevertToSelf routine will attempt to remove an active impersonation.
00866  *
00867  * @param None.
00868  *
00869  * @return TRUE if the reversion was succesful, false otherwise.
00870  *
00871  * @remarks Impersonation can be recursive; as such, the impersonation token
00872  *          will only be deleted once the CSR Thread's impersonaton count
00873  *          has reached zero.
00874  *
00875  *--*/
00876 BOOLEAN
00877 NTAPI
00878 CsrRevertToSelf(VOID)
00879 {
00880     NTSTATUS Status;
00881     PCSR_THREAD CurrentThread = NtCurrentTeb()->CsrClientThread;
00882     HANDLE ImpersonationToken = NULL;
00883 
00884     /* Check if we have a Current Thread */
00885     if (CurrentThread)
00886     {
00887         /* Make sure impersonation is on */
00888         if (!CurrentThread->ImpersonationCount)
00889         {
00890             DPRINT1("CSRSS: CsrRevertToSelf called while not impersonating\n");
00891             DbgBreakPoint();
00892             return FALSE;
00893         }
00894         else if (--CurrentThread->ImpersonationCount > 0)
00895         {
00896             /* Success; impersonation count decreased but still not zero */
00897             return TRUE;
00898         }
00899     }
00900 
00901     /* Impersonation has been totally removed, revert to ourselves */
00902     Status = NtSetInformationThread(NtCurrentThread(),
00903                                     ThreadImpersonationToken,
00904                                     &ImpersonationToken,
00905                                     sizeof(HANDLE));
00906 
00907     /* Return TRUE or FALSE */
00908     ASSERT(NT_SUCCESS(Status));
00909     return NT_SUCCESS(Status);
00910 }
00911 
00912 /*++
00913  * @name CsrLockThreadByClientId
00914  * @implemented NT4
00915  *
00916  * The CsrLockThreadByClientId routine locks the CSR Thread corresponding
00917  * to the given Thread ID and optionally returns it.
00918  *
00919  * @param Tid
00920  *        Thread ID corresponding to the CSR Thread which will be locked.
00921  *
00922  * @param CsrThread
00923  *        Optional pointer to a CSR Thread pointer which will hold the
00924  *        CSR Thread corresponding to the given Thread ID.
00925  *
00926  * @return STATUS_SUCCESS in case of success, STATUS_UNSUCCESSFUL
00927  *         othwerwise.
00928  *
00929  * @remarks Locking a CSR Thread is defined as acquiring an extra
00930  *          reference to it and returning with the Process Lock held.
00931  *
00932  *--*/
00933 NTSTATUS
00934 NTAPI
00935 CsrLockThreadByClientId(IN HANDLE Tid,
00936                         OUT PCSR_THREAD *CsrThread)
00937 {
00938     PLIST_ENTRY NextEntry;
00939     PCSR_THREAD CurrentThread = NULL;
00940     NTSTATUS Status = STATUS_UNSUCCESSFUL;
00941     ULONG i;
00942 
00943     /* Acquire the lock */
00944     CsrAcquireProcessLock();
00945 
00946     /* Assume failure */
00947     ASSERT(CsrThread != NULL);
00948     *CsrThread = NULL;
00949 
00950     /* Convert to Hash */
00951     i = CsrHashThread(Tid);
00952 
00953     /* Setup the List Pointers */
00954     NextEntry = CsrThreadHashTable[i].Flink;
00955 
00956     /* Start Loop */
00957     while (NextEntry != &CsrThreadHashTable[i])
00958     {
00959         /* Get the Process */
00960         CurrentThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, HashLinks);
00961 
00962         /* Check for PID Match */
00963         if ((CurrentThread->ClientId.UniqueThread == Tid) &&
00964             !(CurrentThread->Flags & CsrThreadTerminated))
00965         {
00966             /* Get out of here */
00967             break;
00968         }
00969 
00970         /* Next entry */
00971         NextEntry = NextEntry->Flink;
00972     }
00973 
00974     /* Nothing found if we got back to the list */
00975     if (NextEntry == &CsrThreadHashTable[i]) CurrentThread = NULL;
00976 
00977     /* Did the loop find something? */
00978     if (CurrentThread)
00979     {
00980         /* Reference the found thread */
00981         Status = STATUS_SUCCESS;
00982         CurrentThread->ReferenceCount++;
00983         *CsrThread = CurrentThread;
00984     }
00985     else
00986     {
00987         /* Nothing found, release the lock */
00988         Status = STATUS_UNSUCCESSFUL;
00989         CsrReleaseProcessLock();
00990     }
00991 
00992     /* Return the status */
00993     return Status;
00994 }
00995 
00996 /*++
00997  * @name CsrReferenceThread
00998  * @implemented NT4
00999  *
01000  * The CsrReferenceThread routine increases the active reference count of
01001  * a CSR Thread.
01002  *
01003  * @param CsrThread
01004  *        Pointer to the CSR Thread whose reference count will be increased.
01005  *
01006  * @return None.
01007  *
01008  * @remarks Do not use this routine if the Process Lock is already held.
01009  *
01010  *--*/
01011 VOID
01012 NTAPI
01013 CsrReferenceThread(PCSR_THREAD CsrThread)
01014 {
01015     /* Acquire process lock */
01016     CsrAcquireProcessLock();
01017 
01018     /* Sanity checks */
01019     ASSERT(CsrThread->Flags & CsrThreadTerminated); // CSR_THREAD_DESTROYED in ASSERT
01020     ASSERT(CsrThread->ReferenceCount != 0);
01021 
01022     /* Increment reference count */
01023     CsrThread->ReferenceCount++;
01024 
01025     /* Release the lock */
01026     CsrReleaseProcessLock();
01027 }
01028 
01029 /*++
01030  * @name CsrUnlockThread
01031  * @implemented NT4
01032  *
01033  * The CsrUnlockThread undoes a previous CsrLockThreadByClientId operation.
01034  *
01035  * @param CsrThread
01036  *        Pointer to a previously locked CSR Thread.
01037  *
01038  * @return STATUS_SUCCESS.
01039  *
01040  * @remarks This routine must be called with the Process Lock held.
01041  *
01042  *--*/
01043 NTSTATUS
01044 NTAPI
01045 CsrUnlockThread(PCSR_THREAD CsrThread)
01046 {
01047     /* Dereference the Thread */
01048     ASSERT(ProcessStructureListLocked());
01049     CsrLockedDereferenceThread(CsrThread);
01050 
01051     /* Release the lock and return */
01052     CsrReleaseProcessLock();
01053     return STATUS_SUCCESS;
01054 }
01055 
01056 /* EOF */

Generated on Sat May 26 2012 04:23:03 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.