Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenthread.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
1.7.6.1
|