Indy
February 1st, 2011, 11:28
At the beginning of the exception is delivered to the debug port, then exception port(in KiDispatchException()).
Code:
BOOLEAN
DbgkForwardException(
    IN PEXCEPTION_RECORD ExceptionRecord,
    IN BOOLEAN DebugException,
    IN BOOLEAN SecondChance
    )
/*++
Routine Description:
    This function is called forward an exception to the calling process's
    debug or subsystem exception port.
Arguments:
    ExceptionRecord - Supplies a pointer to an exception record.
    DebugException - Supplies a boolean variable that specifies whether
        this exception is to be forwarded to the process's
        DebugPort(TRUE), or to its ExceptionPort(FALSE).
Return Value:
    TRUE - The process has a DebugPort or an ExceptionPort, and the reply
        received from the port indicated that the exception was handled.
    FALSE - The process either does not have a DebugPort or
        ExceptionPort, or the process has a port, but the reply received
        from the port indicated that the exception was not handled.
--*/
{
    PEPROCESS Process;
    PVOID Port;
    DBGKM_APIMSG m;
    PDBGKM_EXCEPTION args;
    NTSTATUS st;
    BOOLEAN LpcPort;
    PAGED_CODE();
    args = &m.u.Exception;
    //
    // Initialize the debug LPC message with default information.
    //
    DBGKM_FORMAT_API_MSG(m,DbgKmExceptionApi,sizeof(*args));
    //
    // Get the address of the destination LPC port.
    //
    Process = PsGetCurrentProcess();
    if (DebugException) {
        if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) {
            Port = NULL;
        } else {
            Port = Process->DebugPort;
        }
        LpcPort = FALSE;
    } else {
        Port = Process->ExceptionPort;
        m.h.u2.ZeroInit = LPC_EXCEPTION;
        LpcPort = TRUE;
    }
    //
    // If the destination LPC port address is NULL, then return FALSE.
    //
    if (Port == NULL) {
        return FALSE;
    }
    //
    // Fill in the remainder of the debug LPC message.
    //
    args->ExceptionRecord = *ExceptionRecord;
    args->FirstChance = !SecondChance;
    //
    // Send the debug message to the destination LPC port.
    //
    if (LpcPort) {
        st = DbgkpSendApiMessageLpc(&m,Port,DebugException);
    } else {
        st = DbgkpSendApiMessage(&m,DebugException);
    }
    //
    // If the send was not successful, then return a FALSE indicating that
    // the port did not handle the exception. Otherwise, if the debug port
    // is specified, then look at the return status in the message.
    //
    if (!NT_SUCCESS(st) ||
        ((DebugException) &&
        (m.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED || !NT_SUCCESS(m.ReturnedStatus)))) {
        return FALSE;
    } else {
        return TRUE;
    }
}
This type of lpc-messages LPC_EXCEPTION. Port handle can be passed to NtCreateProcess. Maybe one time set using NtSetInformationProcess(class:ProcessExceptionPort). The port is set in the notification csrss(\ApiPort):
Code:
CsrCreateProcess:
	...
	/* Set the Exception port to us */
	Status = NtSetInformationProcess(hProcess, ProcessExceptionPort, &CsrApiPort, sizeof(HANDLE));
http://doxygen.reactos.org/db/da3/subsystems_2csr_2csrsrv_2api_8c_source.html ("http://doxygen.reactos.org/db/da3/subsystems_2csr_2csrsrv_2api_8c_source.html")
http://doxygen.reactos.org/d1/d3c/subsystems_2csr_2csrsrv_2process_8c_source.html ("http://doxygen.reactos.org/d1/d3c/subsystems_2csr_2csrsrv_2process_8c_source.html")
Processing messages in CsrApiRequestThread() ^.