/*++ * @name CsrDereferenceWait * @implemented NT4 * * The CsrDereferenceWait routine derefences a CSR Wait Block. * * @param WaitList * Pointer to the Wait List associated to the wait. * @return None. * * @remarks None. * *--*/ VOID NTAPI CsrDereferenceWait(IN PLIST_ENTRY WaitList) { PLIST_ENTRY NextEntry; PCSR_WAIT_BLOCK WaitBlock; /* Acquire the Process and Wait Locks */ CsrAcquireProcessLock(); CsrAcquireWaitLock(); /* Set the list pointers */ NextEntry = WaitList->Flink; /* Start the loop */ while (NextEntry != WaitList) { /* Get the wait block */ WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); /* Move to the next entry */ NextEntry = NextEntry->Flink; /* Check if there's no Wait Routine */ if (!WaitBlock->WaitFunction) { /* Remove it from the Wait List */ if (WaitBlock->WaitList.Flink) { RemoveEntryList(&WaitBlock->WaitList); } /* Remove it from the User Wait List */ if (WaitBlock->UserWaitList.Flink) { RemoveEntryList(&WaitBlock->UserWaitList); } /* Dereference the thread waiting on it */ CsrDereferenceThread(WaitBlock->WaitThread); /* Free the block */ RtlFreeHeap(CsrHeap, 0, WaitBlock); } } /* Release the locks */ CsrReleaseWaitLock(); CsrReleaseProcessLock(); }
/*++ * @name CsrNotifyWait * @implemented NT4 * * The CsrNotifyWait notifies a CSR Wait Block. * * @param WaitList * Pointer to the list entry for this wait. * * @param WaitType * Type of the wait to perform, either WaitAny or WaitAll. * * @param WaitArgument[1-2] * User-defined argument to pass on to the wait function. * * @return TRUE in case of success, FALSE othwerwise. * * @remarks None. * *--*/ BOOLEAN NTAPI CsrNotifyWait(IN PLIST_ENTRY WaitList, IN ULONG WaitType, IN PVOID WaitArgument1, IN PVOID WaitArgument2) { PLIST_ENTRY NextEntry; PCSR_WAIT_BLOCK WaitBlock; BOOLEAN NotifySuccess = FALSE; /* Acquire the Wait Lock */ CsrAcquireWaitLock(); /* Set the List pointers */ NextEntry = WaitList->Flink; /* Start looping */ while (NextEntry != WaitList) { /* Get the Wait block */ WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); /* Go to the next entry */ NextEntry = NextEntry->Flink; /* Check if there is a Wait Callback */ if (WaitBlock->WaitFunction) { /* Notify the Waiter */ NotifySuccess |= CsrNotifyWaitBlock(WaitBlock, WaitList, WaitArgument1, WaitArgument2, 0, FALSE); /* We've already done a wait, so leave unless this is a Wait All */ if (WaitType != WaitAll) break; } } /* Release the wait lock and return */ CsrReleaseWaitLock(); return NotifySuccess; }
/*++ * @name CsrCreateWait * @implemented NT4 * * The CsrCreateWait routine creates a CSR Wait. * * @param WaitList * Pointer to a list entry of the waits to associate. * * @param WaitFunction * Pointer to the function that will handle this wait. * * @param CsrWaitThread * Pointer to the CSR Thread that will perform the wait. * * @param WaitApiMessage * Pointer to the CSR API Message associated to this wait. * * @param WaitContext * Pointer to a user-defined parameter associated to this wait. * * @param UserWaitList * Pointer to a list entry of the user-defined waits to associate. * * @return TRUE in case of success, FALSE otherwise. * * @remarks None. * *--*/ BOOLEAN NTAPI CsrCreateWait(IN PLIST_ENTRY WaitList, IN CSR_WAIT_FUNCTION WaitFunction, IN PCSR_THREAD CsrWaitThread, IN OUT PCSR_API_MESSAGE WaitApiMessage, IN PVOID WaitContext, IN PLIST_ENTRY UserWaitList OPTIONAL) { PCSR_WAIT_BLOCK WaitBlock; /* Initialize the wait */ if (!CsrInitializeWait(WaitFunction, CsrWaitThread, WaitApiMessage, WaitContext, &WaitBlock)) { return FALSE; } /* Acquire the Wait Lock */ CsrAcquireWaitLock(); /* Make sure the thread wasn't destroyed */ if (CsrWaitThread->Flags & CsrThreadTerminated) { /* Fail the wait */ RtlFreeHeap(CsrHeap, 0, WaitBlock); CsrReleaseWaitLock(); return FALSE; } /* Insert the wait in the queue */ InsertTailList(WaitList, &WaitBlock->WaitList); /* Insert the User Wait too, if one was given */ if (UserWaitList) InsertTailList(UserWaitList, &WaitBlock->UserWaitList); /* Return */ CsrReleaseWaitLock(); return TRUE; }
/*++ * @name CsrMoveSatisfiedWait * @implemented NT5 * * The CsrMoveSatisfiedWait routine moves satisfied waits from a wait list * to another list entry. * * @param NewEntry * Pointer to a list entry where the satisfied waits will be added. * * @param WaitList * Pointer to a list entry to analyze for satisfied waits. * * @return None. * * @remarks None. * *--*/ VOID NTAPI CsrMoveSatisfiedWait(IN PLIST_ENTRY NewEntry, IN PLIST_ENTRY WaitList) { PLIST_ENTRY NextEntry; PCSR_WAIT_BLOCK WaitBlock; /* Acquire the Wait Lock */ CsrAcquireWaitLock(); /* Set the List pointers */ NextEntry = WaitList->Flink; /* Start looping */ while (NextEntry != WaitList) { /* Get the Wait block */ WaitBlock = CONTAINING_RECORD(NextEntry, CSR_WAIT_BLOCK, WaitList); /* Go to the next entry */ NextEntry = NextEntry->Flink; /* Check if there is a Wait Callback */ if (WaitBlock->WaitFunction) { /* Remove it from the Wait Block Queue */ RemoveEntryList(&WaitBlock->WaitList); /* Insert the new entry */ InsertTailList(&WaitBlock->WaitList, NewEntry); } } /* Release the wait lock */ CsrReleaseWaitLock(); }
/*++ * @name CsrDestroyProcess * @implemented NT4 * * The CsrDestroyProcess routine destroys the CSR Process corresponding to * a given Client ID. * * @param Cid * Pointer to the Client ID Structure corresponding to the CSR * Process which is about to be destroyed. * * @param ExitStatus * Unused. * * @return STATUS_SUCCESS in case of success, STATUS_THREAD_IS_TERMINATING * if the CSR Process is already terminating. * * @remarks None. * *--*/ NTSTATUS NTAPI CsrDestroyProcess(IN PCLIENT_ID Cid, IN NTSTATUS ExitStatus) { PCSR_THREAD CsrThread; PCSR_PROCESS CsrProcess; CLIENT_ID ClientId = *Cid; PLIST_ENTRY NextEntry; /* Acquire lock */ CsrAcquireProcessLock(); /* Find the thread */ CsrThread = CsrLocateThreadByClientId(&CsrProcess, &ClientId); /* Make sure we got one back, and that it's not already gone */ if (!(CsrThread) || (CsrProcess->Flags & CsrProcessTerminating)) { /* Release the lock and return failure */ CsrReleaseProcessLock(); return STATUS_THREAD_IS_TERMINATING; } /* Set the terminated flag */ CsrProcess->Flags |= CsrProcessTerminating; /* Get the List Pointers */ NextEntry = CsrProcess->ThreadList.Flink; while (NextEntry != &CsrProcess->ThreadList) { /* Get the current thread entry */ CsrThread = CONTAINING_RECORD(NextEntry, CSR_THREAD, Link); /* Move to the next entry */ NextEntry = NextEntry->Flink; /* Make sure the thread isn't already dead */ if (CsrThread->Flags & CsrThreadTerminated) { /* Go the the next thread */ continue; } /* Set the Terminated flag */ CsrThread->Flags |= CsrThreadTerminated; /* Acquire the Wait Lock */ CsrAcquireWaitLock(); /* Do we have an active wait block? */ if (CsrThread->WaitBlock) { /* Notify waiters of termination */ CsrNotifyWaitBlock(CsrThread->WaitBlock, NULL, NULL, NULL, CsrProcessTerminating, TRUE); } /* Release the Wait Lock */ CsrReleaseWaitLock(); /* Dereference the thread */ CsrLockedDereferenceThread(CsrThread); } /* Release the Process Lock and return success */ CsrReleaseProcessLock(); return STATUS_SUCCESS; }