Beispiel #1
0
NTSTATUS
DbgSspCreateProcess (
    IN PDBGSS_CONTINUE_KEY ContinueKey,
    IN PCLIENT_ID AppClientId,
    IN PCLIENT_ID DebugUiClientId,
    IN PDBGKM_CREATE_PROCESS NewProcess
    )

/*++

Routine Description:

    This function is called by emulation subsystems to report the
    creation of a new process to the Dbg subsystem.  It is the
    responsibility of individual subsystems to track a process and its
    controlling DebugUi.

Arguments:

    ContinueKey - Supplies the captured DbgKm API message that needs a reply
        should this API complete successfully.

    AppClientId - Supplies the address of the new thread's ClientId.

    DebugUiClientId - Supplies the address of the ClientId of the user
        interface controlling the new thread.

    NewProcess - Supplies the address of the NewProcess message as sent through
        the applications DebugPort. The calling subsystem may modify the
        SubSystemKey fields of this message.

Return Value:

    TBD

--*/

{

    NTSTATUS st;
    DBGSS_APIMSG ApiMsg;

    PDBGSS_CREATE_PROCESS args;

    args = &ApiMsg.u.CreateProcessInfo;

    DBGSS_FORMAT_API_MSG(ApiMsg,DbgSsCreateProcessApi,sizeof(*args),AppClientId,ContinueKey);

    args->DebugUiClientId = *DebugUiClientId;
    args->NewProcess = *NewProcess;

    st = NtRequestPort(DbgSspApiPort, (PPORT_MESSAGE) &ApiMsg);

    return st;

}
Beispiel #2
0
NTSTATUS
DbgSspException (
    IN PDBGSS_CONTINUE_KEY ContinueKey,
    IN PCLIENT_ID AppClientId,
    IN PDBGKM_EXCEPTION Exception
    )

/*++

Routine Description:

    This function is called by emulation subsystems to report that
    an exception occured in a thread.

Arguments:

    ContinueKey - Supplies the captured DbgKm API message that needs a reply
        should this API complete successfully.

    AppClientId - Supplies the address of the ClientId of the thread that
        encountered an exception.

    Exception - Supplies the address of the Exception message as sent
        through the applications DebugPort.

Return Value:

    TBD

--*/

{

    NTSTATUS st;
    DBGSS_APIMSG ApiMsg;

    PDBGKM_EXCEPTION args;

    args = &ApiMsg.u.Exception;

    DBGSS_FORMAT_API_MSG(ApiMsg,DbgSsExceptionApi,sizeof(*args),AppClientId,ContinueKey);

    *args = *Exception;

    st = NtRequestPort(DbgSspApiPort, (PPORT_MESSAGE) &ApiMsg);

    return st;
}
Beispiel #3
0
NTSTATUS
DbgSspUnloadDll (
    IN PDBGSS_CONTINUE_KEY ContinueKey,
    IN PCLIENT_ID AppClientId,
    IN PDBGKM_UNLOAD_DLL UnloadDll
    )

/*++

Routine Description:

    This function is called by emulation subsystems to report that
    a a process has un-mapped a view of a section

Arguments:

    ContinueKey - Supplies the captured DbgKm API message that needs a reply
        should this API complete successfully.

    AppClientId - Supplies the address of the ClientId of the thread
        that mapped the section.

    UnloadDll - Supplies the address of the UnloadDll message as sent
        through the applications DebugPort.

Return Value:

    TBD

--*/

{

    NTSTATUS st;
    DBGSS_APIMSG ApiMsg;

    PDBGKM_UNLOAD_DLL args;

    args = &ApiMsg.u.UnloadDll;

    DBGSS_FORMAT_API_MSG(ApiMsg,DbgSsUnloadDllApi,sizeof(*args),AppClientId,ContinueKey);

    *args = *UnloadDll;

    st = NtRequestPort(DbgSspApiPort, (PPORT_MESSAGE) &ApiMsg);

    return st;
}
Beispiel #4
0
NTSTATUS
DbgSspExitProcess (
    IN PDBGSS_CONTINUE_KEY ContinueKey,
    IN PCLIENT_ID AppClientId,
    IN PDBGKM_EXIT_PROCESS ExitProcess
    )

/*++

Routine Description:

    This function is called by emulation subsystems to report that
    a process is exiting.

Arguments:

    ContinueKey - Supplies the captured DbgKm API message that needs a reply
        should this API complete successfully.

    AppClientId - Supplies the address of the ClientId of the last thread
        in the process to exit.

    ExitProcess - Supplies the address of the ExitProcess message as sent
        through the applications DebugPort.

Return Value:

    TBD

--*/

{

    NTSTATUS st;
    DBGSS_APIMSG ApiMsg;

    PDBGKM_EXIT_PROCESS args;

    args = &ApiMsg.u.ExitProcess;

    DBGSS_FORMAT_API_MSG(ApiMsg,DbgSsExitProcessApi,sizeof(*args),AppClientId,ContinueKey);

    *args = *ExitProcess;

    st = NtRequestPort(DbgSspApiPort, (PPORT_MESSAGE) &ApiMsg);

    return st;
}
Beispiel #5
0
NTSTATUS
DbgSspCreateThread (
    IN PDBGSS_CONTINUE_KEY ContinueKey,
    IN PCLIENT_ID AppClientId,
    IN PDBGKM_CREATE_THREAD NewThread
    )

/*++

Routine Description:

    This function is called by emulation subsystems to report the
    creation of a new thread to the Dbg subsystem.

Arguments:

    ContinueKey - Supplies the captured DbgKm API message that needs a reply
        should this API complete successfully.

    AppClientId - Supplies the address of the new thread's ClientId.

    NewThread - Supplies the address of the NewThread message as sent through
        the applications DebugPort. The calling subsystem may modify the
        SubSystemKey field of this message.

Return Value:

    TBD

--*/

{

    NTSTATUS st;
    DBGSS_APIMSG ApiMsg;

    PDBGKM_CREATE_THREAD args;

    args = &ApiMsg.u.CreateThread;

    DBGSS_FORMAT_API_MSG(ApiMsg,DbgSsCreateThreadApi,sizeof(*args),AppClientId, ContinueKey);

    *args = *NewThread;

    st = NtRequestPort(DbgSspApiPort, (PPORT_MESSAGE) &ApiMsg);

    return st;
}
Beispiel #6
0
int main(int argc, char* argv[])
{
   UNICODE_STRING PortName = ROS_STRING_INITIALIZER(TEST_PORT_NAME_U);
   NTSTATUS Status;
   HANDLE PortHandle;
   LPC_MAX_MESSAGE Request;
   ULONG ConnectInfo;
   ULONG ConnectInfoLength = 0;
   SECURITY_QUALITY_OF_SERVICE Sqos;

   printf("%s: Lpc test client\n", MyName);

   printf("%s: Connecting to port \"%s\"...\n", MyName, TEST_PORT_NAME);
   ConnectInfoLength = 0;
   ZeroMemory (& Sqos, sizeof Sqos);
   Status = NtConnectPort(&PortHandle,
			  &PortName,
			  & Sqos,
			  0,
			  0,
			  0,
			  NULL,
			  &ConnectInfoLength);
   if (!NT_SUCCESS(Status))
     {
	printf("%s: NtConnectPort() failed with status = 0x%08X.\n", MyName, Status);
	return EXIT_FAILURE;
     }

   printf("%s: Connected to \"%s\" with anonymous port 0x%x.\n", MyName, TEST_PORT_NAME, PortHandle);

   ZeroMemory(& Request, sizeof Request);
   strcpy(Request.Data, GetCommandLineA());
   Request.Header.DataSize = strlen(Request.Data);
   Request.Header.MessageSize = sizeof(LPC_MESSAGE) +
     Request.Header.DataSize;

   printf("%s: Sending to port 0x%x message \"%s\"...\n",
          MyName,
          PortHandle,
	  (char *) Request.Data);
   Status = NtRequestPort(PortHandle,
			  &Request.Header);
   if (!NT_SUCCESS(Status))
     {
	printf("%s: NtRequestPort(0x%x) failed with status = 0x%8X.\n",
               MyName,
               PortHandle,
	       Status);
	return EXIT_FAILURE;
     }

   printf("%s: Sending datagram to port 0x%x succeeded.\n", MyName, PortHandle);

   Sleep(2000);

   printf("%s: Disconnecting...", MyName);
   NtClose (PortHandle);

   return EXIT_SUCCESS;
}
Beispiel #7
0
VOID
NTAPI
IopLogWorker(IN PVOID Parameter)
{
    PELF_API_MSG Message;
    PIO_ERROR_LOG_MESSAGE ErrorMessage;
    PLIST_ENTRY ListEntry;
    PERROR_LOG_ENTRY LogEntry;
    PIO_ERROR_LOG_PACKET Packet;
    PCHAR StringBuffer;
    ULONG RemainingLength;
    PDRIVER_OBJECT DriverObject;
    ULONG DriverNameLength = 0, DeviceNameLength;
    UNICODE_STRING DriverNameString;
    NTSTATUS Status;
    UCHAR Buffer[256];
    POBJECT_NAME_INFORMATION ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
    POBJECT_NAME_INFORMATION PoolObjectNameInfo = NULL;
    ULONG ReturnedLength, MessageLength;
    PWCHAR p;
    ULONG ExtraStringLength;
    PAGED_CODE();

    /* Connect to the port */
    if (!IopConnectLogPort()) return;

    /* Allocate the message */
    Message = ExAllocatePool(PagedPool, IO_ERROR_LOG_MESSAGE_LENGTH);
    if (!Message)
    {
        /* Couldn't allocate, try again */
        IopRestartLogWorker();
        return;
    }

    /* Copy the message */
    RtlZeroMemory(Message, sizeof(ELF_API_MSG));

    /* Get the actual I/O Structure */
    ErrorMessage = &Message->IoErrorMessage;

    /* Start loop */
    while (TRUE)
    {
        /* Get an entry */
        ListEntry = IopGetErrorLogEntry();
        if (!ListEntry) break;
        LogEntry = CONTAINING_RECORD(ListEntry, ERROR_LOG_ENTRY, ListEntry);

        /* Get pointer to the log packet */
        Packet = (PIO_ERROR_LOG_PACKET)((ULONG_PTR)LogEntry +
                                        sizeof(ERROR_LOG_ENTRY));

        /* Calculate the total length of the message only */
        MessageLength = sizeof(IO_ERROR_LOG_MESSAGE) -
                        sizeof(ERROR_LOG_ENTRY) -
                        sizeof(IO_ERROR_LOG_PACKET) +
                        LogEntry->Size;

        /* Copy the packet */
        RtlCopyMemory(&ErrorMessage->EntryData,
                      Packet,
                      LogEntry->Size - sizeof(ERROR_LOG_ENTRY));

        /* Set the timestamp and time */
        ErrorMessage->TimeStamp = LogEntry->TimeStamp;
        ErrorMessage->Type = IO_TYPE_ERROR_MESSAGE;

        /* Check if this message has any strings */
        if (Packet->NumberOfStrings)
        {
            /* String buffer is after the current strings */
            StringBuffer = (PCHAR)&ErrorMessage->EntryData +
                            Packet->StringOffset;
        }
        else
        {
            /* Otherwise, string buffer is at the end */
            StringBuffer = (PCHAR)ErrorMessage + MessageLength;
        }

        /* Align the buffer */
        StringBuffer = ALIGN_UP_POINTER(StringBuffer, WCHAR);

        /* Set the offset for the driver's name to the current buffer */
        ErrorMessage->DriverNameOffset = (ULONG)(StringBuffer -
                                                (PCHAR)ErrorMessage);

        /* Check how much space we have left for the device string */
        RemainingLength = (ULONG)((ULONG_PTR)Message +
                                  IO_ERROR_LOG_MESSAGE_LENGTH -
                                  (ULONG_PTR)StringBuffer);

        /* Now check if there is a driver object */
        DriverObject = LogEntry->DriverObject;
        if (DriverObject)
        {
            /* Check if the driver has a name */
            if (DriverObject->DriverName.Buffer)
            {
                /* Use its name */
                DriverNameString.Buffer = DriverObject->DriverName.Buffer;
                DriverNameLength = DriverObject->DriverName.Length;
            }
            else
                DriverNameString.Buffer = NULL;

            /* Check if there isn't a valid name*/
            if (!DriverNameLength)
            {
                /* Query the name directly */
                Status = ObQueryNameString(DriverObject,
                                           ObjectNameInfo,
                                           sizeof(Buffer),
                                           &ReturnedLength);
                if (!(NT_SUCCESS(Status)) || !(ObjectNameInfo->Name.Length))
                {
                    /* We don't have a name */
                    DriverNameLength = 0;
                }
            }
        }
        else
        {
            /* Use default name */
            DriverNameString.Buffer = L"Application Popup";
            DriverNameLength = (ULONG)wcslen(DriverNameString.Buffer) * sizeof(WCHAR);
        }

        /* Check if we have a driver name by here */
        if (DriverNameLength)
        {
            /* Skip to the end of the driver's name */
            p = &DriverNameString.Buffer[DriverNameLength / sizeof(WCHAR)];

            /* Now we'll walk backwards and assume the minimum size */
            DriverNameLength = sizeof(WCHAR);
            p--;
            while ((*p != L'\\') && (p != DriverNameString.Buffer))
            {
                /* No backslash found, keep going */
                p--;
                DriverNameLength += sizeof(WCHAR);
            }

            /* Now we probably hit the backslash itself, skip past it */
            if (*p == L'\\')
            {
                p++;
                DriverNameLength -= sizeof(WCHAR);
            }

            /*
             * Now make sure that the driver name fits in our buffer, minus 3
             * NULL chars, and copy the name in our string buffer
             */
            DriverNameLength = min(DriverNameLength,
                                   RemainingLength - 3 * sizeof(UNICODE_NULL));
            RtlCopyMemory(StringBuffer, p, DriverNameLength);
        }

        /* Null-terminate the driver name */
        *((PWSTR)(StringBuffer + DriverNameLength)) = L'\0';
        DriverNameLength += sizeof(WCHAR);

        /* Go to the next string buffer position */
        StringBuffer += DriverNameLength;
        RemainingLength -= DriverNameLength;

        /* Update the string offset and check if we have a device object */
        ErrorMessage->EntryData.StringOffset = (USHORT)
                                               ((ULONG_PTR)StringBuffer -
                                               (ULONG_PTR)ErrorMessage);
        if (LogEntry->DeviceObject)
        {
            /* We do, query its name */
            Status = ObQueryNameString(LogEntry->DeviceObject,
                                       ObjectNameInfo,
                                       sizeof(Buffer),
                                       &ReturnedLength);
            if (!NT_SUCCESS(Status) || (ObjectNameInfo->Name.Length == 0))
            {
                /* Setup an empty name */
                ObjectNameInfo->Name.Length = 0;
                ObjectNameInfo->Name.Buffer = L"";

                /* Check if we failed because our buffer wasn't large enough */
                if (Status == STATUS_INFO_LENGTH_MISMATCH)
                {
                    /* Then we'll allocate one... we really want this name! */
                    PoolObjectNameInfo = ExAllocatePoolWithTag(PagedPool,
                                                               ReturnedLength,
                                                               TAG_IO);
                    if (PoolObjectNameInfo)
                    {
                        /* Query it again */
                        ObjectNameInfo = PoolObjectNameInfo;
                        Status = ObQueryNameString(LogEntry->DeviceObject,
                                                   ObjectNameInfo,
                                                   ReturnedLength,
                                                   &ReturnedLength);
                        if (NT_SUCCESS(Status))
                        {
                            /* Success, update the information */
                            ObjectNameInfo->Name.Length =
                                100 - (USHORT)DriverNameLength;
                        }
                    }
                }
            }
        }
        else
        {
            /* No device object, setup an empty name */
            ObjectNameInfo->Name.Length = 0;
            ObjectNameInfo->Name.Buffer = L"";
        }

        /*
         * Now make sure that the device name fits in our buffer, minus 2
         * NULL chars, and copy the name in our string buffer
         */
        DeviceNameLength = min(ObjectNameInfo->Name.Length,
                               RemainingLength - 2 * sizeof(UNICODE_NULL));
        RtlCopyMemory(StringBuffer,
                      ObjectNameInfo->Name.Buffer,
                      DeviceNameLength);

        /* Null-terminate the device name */
        *((PWSTR)(StringBuffer + DeviceNameLength)) = L'\0';
        DeviceNameLength += sizeof(WCHAR);

        /* Free the buffer if we had one */
        if (PoolObjectNameInfo)
        {
            ExFreePool(PoolObjectNameInfo);
            PoolObjectNameInfo = NULL;
            ObjectNameInfo = (POBJECT_NAME_INFORMATION)&Buffer;
        }

        /* Go to the next string buffer position */
        ErrorMessage->EntryData.NumberOfStrings++;
        StringBuffer += DeviceNameLength;
        RemainingLength -= DeviceNameLength;

        /* Check if we have any extra strings */
        if (Packet->NumberOfStrings)
        {
            /* Find out the size of the extra strings */
            ExtraStringLength = LogEntry->Size -
                                sizeof(ERROR_LOG_ENTRY) -
                                Packet->StringOffset;

            /* Make sure that the extra strings fit in our buffer */
            if (ExtraStringLength > (RemainingLength - sizeof(UNICODE_NULL)))
            {
                /* They wouldn't, so set normalize the length */
                MessageLength -= ExtraStringLength - RemainingLength;
                ExtraStringLength = RemainingLength - sizeof(UNICODE_NULL);
            }

            /* Now copy the extra strings */
            RtlCopyMemory(StringBuffer,
                          (PCHAR)Packet + Packet->StringOffset,
                          ExtraStringLength);

            /* Null-terminate them */
            *((PWSTR)(StringBuffer + ExtraStringLength)) = L'\0';
        }

        /* Set the driver name length */
        ErrorMessage->DriverNameLength = (USHORT)DriverNameLength;

        /* Update the message length to include the device and driver names */
        MessageLength += DeviceNameLength + DriverNameLength;
        ErrorMessage->Size = (USHORT)MessageLength;

        /* Now update it again, internally, for the size of the actual LPC */
        MessageLength += (FIELD_OFFSET(ELF_API_MSG, IoErrorMessage) -
                          FIELD_OFFSET(ELF_API_MSG, Unknown[0]));

        /* Set the total and data lengths */
        Message->h.u1.s1.TotalLength = (USHORT)(sizeof(PORT_MESSAGE) +
                                                MessageLength);
        Message->h.u1.s1.DataLength = (USHORT)(MessageLength);

        /* Send the message */
        Status = NtRequestPort(IopLogPort, (PPORT_MESSAGE)Message);
        if (!NT_SUCCESS(Status))
        {
            /* Requeue log message and restart the worker */
            ExInterlockedInsertTailList(&IopErrorLogListHead,
                                        &LogEntry->ListEntry,
                                        &IopLogListLock);
            IopLogWorkerRunning = FALSE;
            IopRestartLogWorker();
            break;
        }

        /* Dereference the device object */
        if (LogEntry->DeviceObject) ObDereferenceObject(LogEntry->DeviceObject);
        if (DriverObject) ObDereferenceObject(LogEntry->DriverObject);

        /* Update size */
        InterlockedExchangeAdd(&IopTotalLogSize,
                               -(LONG)(LogEntry->Size -
                                       sizeof(ERROR_LOG_ENTRY)));
    }

    /* Free the LPC Message */
    ExFreePool(Message);
}
Beispiel #8
0
VOID
IopErrorLogThread(
    IN PVOID StartContext
    )

/*++

Routine Description:

    This is the main loop for the I/O error log thread which executes in the
    system process context.  This routine is started when the system is
    initialized.

Arguments:

    StartContext - Startup context; not used.

Return Value:

    None.

--*/

{
    PERROR_LOG_ENTRY errorLogEntry;
    UNICODE_STRING nameString;
    PLIST_ENTRY listEntry;
    PIO_ERROR_LOG_MESSAGE errorMessage;
    NTSTATUS status;
    PELF_PORT_MSG portMessage;
    PCHAR objectName;
    ULONG messageLength;
    ULONG driverNameLength;
    ULONG deviceNameLength;
    ULONG objectNameLength;
    ULONG remainingLength;
    ULONG stringLength;
    CHAR nameBuffer[IO_ERROR_NAME_LENGTH+sizeof( OBJECT_NAME_INFORMATION )];
    PDRIVER_OBJECT driverObject;
    POBJECT_NAME_INFORMATION nameInformation;
    PIO_ERROR_LOG_PACKET errorData;
    PWSTR string;

    PAGED_CODE();

    UNREFERENCED_PARAMETER( StartContext );

    //
    // Check to see whether a connection has been made to the error log
    // port.  If the port is not connected return.
    //

    if (!IopErrorLogConnectPort()) {

        //
        // The port could not be connected.  A timer was started that will
        // try again later.
        //

        return;
    }

    //
    // Allocate and zero the port message structure, include space for the
    // name of the device and driver.
    //

    messageLength = IO_ERROR_LOG_MESSAGE_LENGTH;
    portMessage = ExAllocatePool(PagedPool, messageLength);

    if (portMessage == NULL) {

        //
        // The message buffer could not be allocated. Request that
        // the error log thread routine be called again later.
        //

        IopErrorLogQueueRequest();
        return;
    }

    RtlZeroMemory( portMessage, sizeof( *portMessage ) );
    portMessage->MessageType = IO_ERROR_LOG;
    errorMessage = &portMessage->u.IoErrorLogMessage;

    nameInformation = (PVOID) &nameBuffer;

    //
    // Now enter the main loop for this thread.  This thread performs the
    // following operations:
    //
    //   1)  If a connection has been made to the error log port, dequeue a
    //       packet from the queue head and attempt to send it to the port.
    //
    //   2)  If the send works, loop sending packets until there are no more
    //       packets;  otherwise, indicate that the connection has been broken,
    //       cleanup, place the packet back onto the head of the queue and
    //       return.
    //
    //   3)  After all the packets are sent clear the pending variable and
    //       return.
    //

    for (;;) {

        //
        // Loop dequeueing  packets from the queue head and attempt to send
        // each to the port.
        //
        // If the send works, continue looping until there are no more packets.
        // Otherwise, indicate that the connection has been broken, cleanup,
        // place the packet back onto the head of the queue, and start from the
        // top of the loop again.
        //

        if (!(listEntry = IopErrorLogGetEntry())) {
            break;
        }

        errorLogEntry = CONTAINING_RECORD( listEntry,
                                           ERROR_LOG_ENTRY,
                                           ListEntry );

        //
        // The size of errorLogEntry is ERROR_LOG_ENTRY +
        // IO_ERROR_LOG_PACKET + (Extra Dump data).  The size of the
        // initial message length should be IO_ERROR_LOG_MESSAGE +
        // (Extra Dump data), since IO_ERROR_LOG_MESSAGE contains an
        // IO_ERROR_LOG_PACKET. Using the above calculations set the
        // message length.
        //

        messageLength = sizeof( IO_ERROR_LOG_MESSAGE ) -
            sizeof( ERROR_LOG_ENTRY ) - sizeof( IO_ERROR_LOG_PACKET ) +
            errorLogEntry->Size;

        errorData = (PIO_ERROR_LOG_PACKET) (errorLogEntry + 1);

        //
        // Copy the error log packet and the extra data to the message.
        //

        RtlMoveMemory( &errorMessage->EntryData,
                       errorData,
                       errorLogEntry->Size - sizeof( ERROR_LOG_ENTRY ) );

        errorMessage->TimeStamp = errorLogEntry->TimeStamp;
        errorMessage->Type = IO_TYPE_ERROR_MESSAGE;

        //
        // Add the driver and device name string.  These strings go
        // before the error log strings.  Just write over the current
        // strings and they will be recopied later.
        //

        if (errorData->NumberOfStrings != 0) {

            //
            // Start the driver and device strings where the current
            // strings start.
            //

            objectName = (PCHAR) (&errorMessage->EntryData) +
                                 errorData->StringOffset;

        } else {

            //
            // Put the driver and device strings at the end of the
            // data.
            //

            objectName = (PCHAR) errorMessage + messageLength;

        }

        //
        // Make sure the driver offset starts on an even bountry.
        //

        objectName = (PCHAR) ((ULONG_PTR) (objectName + sizeof(WCHAR) - 1) &
            ~(ULONG_PTR)(sizeof(WCHAR) - 1));

        errorMessage->DriverNameOffset = (ULONG)(objectName - (PCHAR) errorMessage);

        remainingLength = (ULONG)((PCHAR) portMessage + IO_ERROR_LOG_MESSAGE_LENGTH
                            - objectName);

        //
        // Calculate the length of the driver name and
        // the device name. If the driver object has a name then get
        // it from there; otherwise try to query the device object.
        //

        driverObject = errorLogEntry->DriverObject;
        driverNameLength = 0;

        if (driverObject != NULL) {
            if (driverObject->DriverName.Buffer != NULL) {

                nameString.Buffer = driverObject->DriverName.Buffer;
                driverNameLength = driverObject->DriverName.Length;
            }

            if (driverNameLength == 0) {

                //
                // Try to query the driver object for a name.
                //

                status = ObQueryNameString( driverObject,
                                            nameInformation,
                                            IO_ERROR_NAME_LENGTH + sizeof( OBJECT_NAME_INFORMATION ),
                                            &objectNameLength );

                if (!NT_SUCCESS( status ) || !nameInformation->Name.Length) {

                    //
                    // No driver name was available.
                    //

                    driverNameLength = 0;

                } else {
                    nameString = nameInformation->Name;
                }

            }

        } else {

            //
            // If no driver object, this message must be from the 
            // kernel.   We need to point the eventlog service to
            // an event message file containing ntstatus messages,
            // ie, ntdll, we do this by claiming this event is an
            // application popup.
            //

            nameString.Buffer = L"Application Popup";
            driverNameLength = wcslen(nameString.Buffer) * sizeof(WCHAR);
        }

        if (driverNameLength != 0 ) {

            //
            // Pick out the module name.
            //

            string = nameString.Buffer +
                (driverNameLength / sizeof(WCHAR));

            driverNameLength = sizeof(WCHAR);
            string--;
            while (*string != L'\\' && string != nameString.Buffer) {
                string--;
                driverNameLength += sizeof(WCHAR);
            }

            if (*string == L'\\') {
                string++;
                driverNameLength -= sizeof(WCHAR);
            }

            //
            // Ensure there is enough room for the driver name.
            // Save space for 3 NULLs one for the driver name,
            // one for the device name and one for strings.
            //

            if (driverNameLength > remainingLength - (3 * sizeof(WCHAR))) {
                driverNameLength = remainingLength - (3 * sizeof(WCHAR));
            }

            RtlMoveMemory(
                objectName,
                string,
                driverNameLength
                );

        }

        //
        // Add a null after the driver name even if there is no
        // driver name.
        //

       *((PWSTR) (objectName + driverNameLength)) = L'\0';
       driverNameLength += sizeof(WCHAR);

        //
        // Determine where the next string goes.
        //

        objectName += driverNameLength;
        remainingLength -= driverNameLength;

        errorMessage->EntryData.StringOffset = (USHORT)(objectName - (PCHAR) errorMessage);

        if (errorLogEntry->DeviceObject != NULL) {

            status = ObQueryNameString( errorLogEntry->DeviceObject,
                                        nameInformation,
                                        IO_ERROR_NAME_LENGTH + sizeof( OBJECT_NAME_INFORMATION ) - driverNameLength,
                                        &objectNameLength );

            if (!NT_SUCCESS( status ) || !nameInformation->Name.Length) {

                //
                // No device name was available. Add a Null string.
                //

                nameInformation->Name.Length = 0;
                nameInformation->Name.Buffer = L"\0";

            }

            //
            // No device name was available. Add a Null string.
            // Always add a device name string so that the
            // insertion string counts are correct.
            //

        } else {

                //
                // No device name was available. Add a Null string.
                // Always add a device name string so that the
                // insertion string counts are correct.
                //

                nameInformation->Name.Length = 0;
                nameInformation->Name.Buffer = L"\0";

        }

        deviceNameLength = nameInformation->Name.Length;

        //
        // Ensure there is enough room for the device name.
        // Save space for a NULL.
        //

        if (deviceNameLength > remainingLength - (2 * sizeof(WCHAR))) {

            deviceNameLength = remainingLength - (2 * sizeof(WCHAR));

        }

        RtlMoveMemory( objectName,
                       nameInformation->Name.Buffer,
                       deviceNameLength );

        //
        // Add a null after the device name even if there is no
        // device name.
        //

        *((PWSTR) (objectName + deviceNameLength)) = L'\0';
        deviceNameLength += sizeof(WCHAR);

        //
        // Update the string count for the device object.
        //

        errorMessage->EntryData.NumberOfStrings++;
        objectName += deviceNameLength;
        remainingLength -= deviceNameLength;

        if (errorData->NumberOfStrings) {

            stringLength = errorLogEntry->Size - sizeof( ERROR_LOG_ENTRY ) -
                            errorData->StringOffset;

            //
            // Ensure there is enough room for the strings.
            // Save space for a NULL.
            //

            if (stringLength > remainingLength - sizeof(WCHAR)) {


                messageLength -= stringLength - remainingLength;
                stringLength = remainingLength - sizeof(WCHAR);

            }

            //
            // Copy the strings to the end of the message.
            //

            RtlMoveMemory( objectName,
                           (PCHAR) errorData + errorData->StringOffset,
                           stringLength );

            //
            // Add a null after the strings
            //
            //

           *((PWSTR) (objectName + stringLength)) = L'\0';

        }

        //
        // Update the message length.
        //

        errorMessage->DriverNameLength = (USHORT) driverNameLength;
        messageLength += deviceNameLength + driverNameLength;
        errorMessage->Size = (USHORT) messageLength;

        messageLength += FIELD_OFFSET ( ELF_PORT_MSG, u ) -
            FIELD_OFFSET (ELF_PORT_MSG, MessageType);

        portMessage->PortMessage.u1.s1.TotalLength = (USHORT)
            (sizeof( PORT_MESSAGE ) + messageLength);
        portMessage->PortMessage.u1.s1.DataLength = (USHORT) (messageLength);
        status = NtRequestPort( ErrorLogPort, (PPORT_MESSAGE) portMessage );

        if (!NT_SUCCESS( status )) {

            //
            // The send failed.  Place the packet back onto the head of
            // the error log queue, forget the current connection since
            // it no longer works, and close the handle to the port.
            // Set a timer up for another attempt later.
            // Finally, exit the loop since there is no connection
            // to do any work on.
            //

            NtClose( ErrorLogPort );

            IopErrorLogRequeueEntry( &errorLogEntry->ListEntry );

            IopErrorLogQueueRequest();

            break;

        } else {

            //
            // The send worked fine.  Free the packet and the update
            // the allocation count.
            //

            ExInterlockedAddUlong( &IopErrorLogAllocation,
                                   (ULONG) ( -errorLogEntry->Size ),
                                   &IopErrorLogAllocationLock );

            //
            // Dereference the object pointers now that the name has been
            // captured.
            //


            if (errorLogEntry->DeviceObject != NULL) {
                ObDereferenceObject( errorLogEntry->DeviceObject );
            }

            if (driverObject != NULL) {
                ObDereferenceObject( errorLogEntry->DriverObject );
            }

            ExFreePool( errorLogEntry );

        } // if

    } // for

    //
    // Finally, free the message buffer and return.
    //

    ExFreePool(portMessage);

}