diff --git a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c index 4b048ba8c09..481c451911c 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c +++ b/reactos/subsystems/win32/csrss/csrsrv/api/wapi.c @@ -1008,6 +1008,7 @@ ClientConnectionThread(IN PVOID Parameter) PCSR_THREAD ServerThread; ULONG MessageType; HANDLE ReplyPort; + PDBGKM_MSG DebugMessage; DPRINT("CSR: %s called\n", __FUNCTION__); @@ -1159,6 +1160,23 @@ ClientConnectionThread(IN PVOID Parameter) continue; } + /* If this was an exception, handle it */ + if (MessageType == LPC_EXCEPTION) + { + /* Kill the process */ + NtTerminateProcess(ProcessData->ProcessHandle, STATUS_ABANDONED); + + /* Destroy it from CSR */ + CsrDestroyProcess(&Request->Header.ClientId, STATUS_ABANDONED); + + /* Return a Debug Message */ + DebugMessage = (PDBGKM_MSG)&Request; + DebugMessage->ReturnedStatus = DBG_CONTINUE; + Reply = Request; + ReplyPort = CsrApiPort; + continue; + } + /* Check if we got a hard error */ if (MessageType == LPC_ERROR_EVENT) { diff --git a/reactos/subsystems/win32/csrss/csrsrv/procsup.c b/reactos/subsystems/win32/csrss/csrsrv/procsup.c index 2a3b23ad0d1..2b63e48e6e3 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/procsup.c +++ b/reactos/subsystems/win32/csrss/csrsrv/procsup.c @@ -497,6 +497,98 @@ CsrDereferenceProcess(IN PCSR_PROCESS CsrProcess) } } +/*++ + * @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); + + /* Make sure the thread isn't already dead */ + if (CsrThread->Flags & CsrThreadTerminated) + { + NextEntry = NextEntry->Flink; + 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); + NextEntry = CsrProcess->ThreadList.Flink; + } + + /* Release the Process Lock and return success */ + CsrReleaseProcessLock(); + return STATUS_SUCCESS; +} + /*++ * @name CsrCreateProcess * @implemented NT4 diff --git a/reactos/subsystems/win32/csrss/csrsrv/thredsup.c b/reactos/subsystems/win32/csrss/csrsrv/thredsup.c index d742b6a0be6..121d39bffd2 100644 --- a/reactos/subsystems/win32/csrss/csrsrv/thredsup.c +++ b/reactos/subsystems/win32/csrss/csrsrv/thredsup.c @@ -310,6 +310,37 @@ CsrThreadRefcountZero(IN PCSR_THREAD CsrThread) CsrDereferenceProcess(CsrProcess); } +/*++ + * @name CsrLockedDereferenceThread + * + * The CsrLockedDereferenceThread derefences a CSR Thread while the + * Process Lock is already being held. + * + * @param CsrThread + * Pointer to the CSR Thread to be dereferenced. + * + * @return None. + * + * @remarks This routine will return with the Process Lock held. + * + *--*/ +VOID +NTAPI +CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread) +{ + LONG LockCount; + + /* Decrease reference count */ + LockCount = --CsrThread->ReferenceCount; + ASSERT(LockCount >= 0); + if (!LockCount) + { + /* Call the generic cleanup code */ + CsrThreadRefcountZero(CsrThread); + CsrAcquireProcessLock(); + } +} + NTSTATUS NTAPI CsrCreateThread(IN PCSR_PROCESS CsrProcess, diff --git a/reactos/subsystems/win32/csrss/include/api.h b/reactos/subsystems/win32/csrss/include/api.h index f8beb873848..5e922caf263 100644 --- a/reactos/subsystems/win32/csrss/include/api.h +++ b/reactos/subsystems/win32/csrss/include/api.h @@ -415,6 +415,24 @@ CsrSrvSetPriorityClass( IN OUT PULONG Reply ); +NTSTATUS +NTAPI +CsrDestroyProcess(IN PCLIENT_ID Cid, +IN NTSTATUS ExitStatus); + +VOID +NTAPI +CsrLockedDereferenceThread(IN PCSR_THREAD CsrThread); + +BOOLEAN +NTAPI +CsrNotifyWaitBlock(IN PCSR_WAIT_BLOCK WaitBlock, + IN PLIST_ENTRY WaitList, + IN PVOID WaitArgument1, + IN PVOID WaitArgument2, + IN ULONG WaitFlags, + IN BOOLEAN DereferenceThread); + VOID NTAPI CsrReferenceNtSession(IN PCSR_NT_SESSION Session);