Пример #1
0
NTSTATUS
NTAPI
VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel)
{
    CHECK_PARAMETER(Channel);

    /* Free the buffer and then destroy the channel */
    if (Channel->OBuffer) SacFreePool(Channel->OBuffer);
    if (Channel->IBuffer) SacFreePool(Channel->IBuffer);
    return ChannelDestroy(Channel);
}
Пример #2
0
NTSTATUS
NTAPI
CreateDeviceSecurityDescriptor(IN PDEVICE_OBJECT *DeviceObject)
{
    NTSTATUS Status;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    BOOLEAN MemoryAllocated = FALSE;
    PACL Dacl = NULL;
    PVOID ObjectSecurityDescriptor = NULL;
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Entering.\n");

    /* Get the current SD of the device object */
    Status = ObGetObjectSecurity(*DeviceObject, &SecurityDescriptor, &MemoryAllocated);
    if (!NT_SUCCESS(Status))
    {
        SAC_DBG(SAC_DBG_INIT, "SAC: Unable to get security descriptor, error: %x\n", Status);
        NT_ASSERT(MemoryAllocated == FALSE);
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
        return Status;
    }

    /* Build a DACL for it */
    Status = BuildDeviceAcl(&Dacl);
    if (Status >= 0)
    {
        ASSERT(FALSE);
    }
    else
    {
        SAC_DBG(SAC_DBG_INIT, "SAC CreateDeviceSecurityDescriptor : Unable to create Raw ACL, error : %x\n", Status);
        /* FIXME: Temporary hack */
        Status = STATUS_SUCCESS;
        goto CleanupPath;
    }

CleanupPath:
    /* Release the SD we queried */
    ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);

    /* Free anything else we may have allocated */
    if (ObjectSecurityDescriptor) ExFreePool(ObjectSecurityDescriptor);
    if (Dacl) SacFreePool(Dacl);

    /* All done */
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
    return Status;
}
Пример #3
0
VOID
NTAPI
FreeGlobalData(VOID)
{
    UNICODE_STRING SymbolicLink;
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeGlobalData: Entering.\n");

    /* Only free if we allocated */
    if (GlobalDataInitialized)
    {
        /* Close the SAC event if we had created one */
        if (SACEvent)
        {
            ZwClose(SACEventHandle);
            SACEvent = NULL;
        }

        /* Destroy the cached messages */
        TearDownGlobalMessageTable();

        /* Delete the Win32 symbolic link */
        RtlInitUnicodeString(&SymbolicLink, L"\\DosDevices\\SAC");
        IoDeleteSymbolicLink(&SymbolicLink);

        /* Tear down connections */
        ConMgrShutdown();

        /* Tear down channels */
        ChanMgrShutdown();

        /* Free the serial port buffer */
        if (SerialPortBuffer) SacFreePool(SerialPortBuffer);

        /* Free cached machine information */
        FreeMachineInformation();

        /* Cleanup the custom heap allocator */
        FreeMemoryManagement();

        /* We're back to a virgin state */
        GlobalDataInitialized = FALSE;
    }

    /* All done */
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeGlobalData: Exiting.\n");
}
Пример #4
0
NTSTATUS
NTAPI
VTUTF8ChannelOFlush(IN PSAC_CHANNEL Channel)
{
    NTSTATUS Status;
    PSAC_VTUTF8_SCREEN Screen;
    INT Color[2], Position[2];
    ULONG Utf8ProcessedCount, Utf8Count, R, C, ForeColor, BackColor, Attribute;
    PWCHAR TmpBuffer;
    BOOLEAN Overflow = FALSE;
    CHECK_PARAMETER(Channel);

    /* Set the cell buffer position */
    Screen = (PSAC_VTUTF8_SCREEN)Channel->OBuffer;

    /* Allocate a temporary buffer */
    TmpBuffer = SacAllocatePool(40, GLOBAL_BLOCK_TAG);
    if (!TmpBuffer)
    {
        Status = STATUS_NO_MEMORY;
        goto Quickie;
    }

    /* First, clear the screen */
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiClearScreen,
                                       NULL,
                                       0);
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Next, reset the cursor position */
    Position[1] = 0;
    Position[0] = 0;
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiSetPosition,
                                       Position,
                                       sizeof(Position));
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Finally, reset the attributes */
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiClearAttributes,
                                       NULL,
                                       0);
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Now set the current cell attributes */
    Attribute = Channel->CellFlags;
    Status = VTUTF8ChannelProcessAttributes(Channel, Attribute);
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* And set the current cell colors */
    ForeColor = Channel->CellForeColor;
    BackColor = Channel->CellBackColor;
    Color[1] = BackColor;
    Color[0] = ForeColor;
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiSetColors,
                                       Color,
                                       sizeof(Color));
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Now loop all the characters in the cell buffer */
    for (R = 0; R < SAC_VTUTF8_ROW_HEIGHT; R++)
    {
        /* Across every row */
        for (C = 0; C < SAC_VTUTF8_COL_WIDTH; C++)
        {
            /* Check if there's been a change in colors */
            if ((Screen->Cell[R][C].CellBackColor != BackColor) ||
                (Screen->Cell[R][C].CellForeColor != ForeColor))
            {
                /* New colors are being drawn -- are we also on a new row now? */
                if (Overflow)
                {
                    /* Reposition the cursor correctly */
                    Position[1] = R;
                    Position[0] = C;
                    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                                       SacAnsiSetPosition,
                                                       Position,
                                                       sizeof(Position));
                    if (!NT_SUCCESS(Status)) goto Quickie;
                    Overflow = FALSE;
                }

                /* Cache the new colors */
                ForeColor = Screen->Cell[R][C].CellForeColor;
                BackColor = Screen->Cell[R][C].CellBackColor;

                /* Set them on the screen */
                Color[1] = BackColor;
                Color[0] = ForeColor;
                Status = VTUTF8ChannelAnsiDispatch(Channel,
                                                   SacAnsiSetColors,
                                                   Color,
                                                   sizeof(Color));
                if (!NT_SUCCESS(Status)) goto Quickie;
            }

            /* Check if there's been a change in attributes */
            if (Screen->Cell[R][C].CellFlags != Attribute)
            {
                /* Yep! Are we also on a new row now? */
                if (Overflow)
                {
                    /* Reposition the cursor correctly */
                    Position[1] = R;
                    Position[0] = C;
                    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                                       SacAnsiSetPosition,
                                                       Position,
                                                       sizeof(Position));
                    if (!NT_SUCCESS(Status)) goto Quickie;
                    Overflow = FALSE;
                }

                /* Set the new attributes on screen */
                Attribute = Screen->Cell[R][C].CellFlags;
                Status = VTUTF8ChannelProcessAttributes(Channel, Attribute);
                if (!NT_SUCCESS(Status)) goto Quickie;
            }

            /* Time to write the character -- are we on a new row now? */
            if (Overflow)
            {
                /* Reposition the cursor correctly */
                Position[1] = R;
                Position[0] = C;
                Status = VTUTF8ChannelAnsiDispatch(Channel,
                                                   SacAnsiSetPosition,
                                                   Position,
                                                   sizeof(Position));
                if (!NT_SUCCESS(Status)) goto Quickie;
                Overflow = FALSE;
            }

            /* Write the character into our temporary buffer */
            *TmpBuffer = Screen->Cell[R][C].Char;
            TmpBuffer[1] = UNICODE_NULL;

            /* Convert it to UTF-8 */
            if (!SacTranslateUnicodeToUtf8(TmpBuffer,
                                           1,
                                           Utf8ConversionBuffer,
                                           Utf8ConversionBufferSize,
                                           &Utf8Count,
                                           &Utf8ProcessedCount))
            {
                /* Bail out if this failed */
                Status = STATUS_UNSUCCESSFUL;
                goto Quickie;
            }

            /* Make sure we have a remaining valid character */
            if (Utf8Count)
            {
                /* Write it out on the wire */
                Status = ConMgrWriteData(Channel, Utf8ConversionBuffer, Utf8Count);
                if (!NT_SUCCESS(Status)) goto Quickie;
            }
        }

        /* All the characters on the row are done, indicate we need a reset */
        Overflow = TRUE;
    }

    /* Everything is done, set the positition one last time */
    Position[1] = Channel->CursorRow;
    Position[0] = Channel->CursorCol;
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiSetPosition,
                                       Position,
                                       sizeof(Position));
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Set the current attribute one last time */
    Status = VTUTF8ChannelProcessAttributes(Channel, Channel->CellFlags);
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Set the current colors one last time */
    Color[1] = Channel->CellBackColor;
    Color[0] = Channel->CellForeColor;
    Status = VTUTF8ChannelAnsiDispatch(Channel,
                                       SacAnsiSetColors,
                                       Color,
                                       sizeof(Color));
    if (!NT_SUCCESS(Status)) goto Quickie;

    /* Flush all the data out on the wire */
    Status = ConMgrFlushData(Channel);

Quickie:
    /* We're done, free the temporary buffer */
    if (TmpBuffer) SacFreePool(TmpBuffer);

    /* Indicate that all new data has been flushed now */
    if (NT_SUCCESS(Status))
    {
        _InterlockedExchange(&Channel->ChannelHasNewOBufferData, 0);
    }

    /* Return the result */
    return Status;
}
Пример #5
0
NTSTATUS
NTAPI
VTUTF8ChannelAnsiDispatch(IN PSAC_CHANNEL Channel,
                          IN SAC_ANSI_DISPATCH AnsiCode,
                          IN INT* Data,
                          IN ULONG Length)
{
    NTSTATUS Status = STATUS_SUCCESS;
    PCHAR LocalBuffer = NULL, Tmp;
    INT l;
    CHECK_PARAMETER1(Channel);

    /* Check which ANSI sequence we should output */
    switch (AnsiCode)
    {
        /* Send the [2J (Clear Screen and Reset Cursor) */
        case SacAnsiClearScreen:
            Tmp = "\x1B[2J";
            break;

        /* Send the [0J (Clear From Position Till End Of Screen) */
        case SacAnsiClearEndOfScreen:
            Tmp = "\x1B[0J";
            break;

        /* Send the [0K (Clear from Position Till End Of Line) */
        case SacAnsiClearEndOfLine:
            Tmp = "\x1B[0K";
            break;

        /* Send a combination of two [#m attribute changes */
        case SacAnsiSetColors:

            /* Allocate a small local buffer for it */
            LocalBuffer = SacAllocatePool(SAC_VTUTF8_COL_WIDTH, GLOBAL_BLOCK_TAG);
            CHECK_ALLOCATION(LocalBuffer);

            /* Caller should have sent two colors as two integers */
            if (!(Data) || (Length != 8))
            {
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            /* Create the escape sequence string */
            l = sprintf(LocalBuffer, "\x1B[%dm\x1B[%dm", Data[1], Data[0]);
            ASSERT((l + 1)*sizeof(UCHAR) < SAC_VTUTF8_COL_WIDTH);
            ASSERT(LocalBuffer);
            Tmp = LocalBuffer;
            break;

        /* Send the [#;#H (Cursor Position) sequence */
        case SacAnsiSetPosition:

            /* Allocate a small local buffer for it */
            LocalBuffer = SacAllocatePool(SAC_VTUTF8_COL_WIDTH, GLOBAL_BLOCK_TAG);
            CHECK_ALLOCATION(LocalBuffer);

            /* Caller should have sent the position as two integers */
            if (!(Data) || (Length != 8))
            {
                Status = STATUS_INVALID_PARAMETER;
                break;
            }

            /* Create the escape sequence string */
            l = sprintf(LocalBuffer, "\x1B[%d;%dH", Data[1] + 1, Data[0] + 1);
            ASSERT((l + 1)*sizeof(UCHAR) < SAC_VTUTF8_COL_WIDTH);
            ASSERT(LocalBuffer);
            Tmp = LocalBuffer;
            break;

        /* Send the [0m sequence (Set Attribute 0) */
        case SacAnsiClearAttributes:
            Tmp = "\x1B[0m";
            break;

        /* Send the [7m sequence (Set Attribute 7) */
        case SacAnsiSetInverseAttribute:
            Tmp = "\x1B[7m";
            break;

        /* Send the [27m sequence (Set Attribute 27) */
        case SacAnsiClearInverseAttribute:
            Tmp = "\x1B[27m";
            break;

        /* Send the [5m sequence (Set Attribute 5) */
        case SacAnsiSetBlinkAttribute:
            Tmp = "\x1B[5m";
            break;

        /* Send the [25m sequence (Set Attribute 25) */
        case SacAnsiClearBlinkAttribute:
            Tmp = "\x1B[25m";
            break;

        /* Send the [1m sequence (Set Attribute 1) */
        case SacAnsiSetBoldAttribute:
            Tmp = "\x1B[1m";
            break;

        /* Send the [22m sequence (Set Attribute 22) */
        case SacAnsiClearBoldAttribute:
            Tmp = "\x1B[22m";
            break;

        /* We don't recognize it */
        default:
            Status = STATUS_INVALID_PARAMETER;
            break;
    }

    /* Did everything work above? */
    if (NT_SUCCESS(Status))
    {
        /* Go write out the sequence */
        Status = ConMgrWriteData(Channel, Tmp, strlen(Tmp));
        if (NT_SUCCESS(Status))
        {
            /* Now flush it */
            Status = ConMgrFlushData(Channel);
        }
    }

    /* Free the temporary buffer, if any, and return the status */
    if (LocalBuffer) SacFreePool(LocalBuffer);
    return Status;
}
Пример #6
0
BOOLEAN
NTAPI
InitializeGlobalData(IN PUNICODE_STRING RegistryPath,
                     IN PDRIVER_OBJECT DriverObject)
{
    NTSTATUS Status;
    UNICODE_STRING LinkName;
    UNICODE_STRING DeviceName;
    UNICODE_STRING EventName;
    PAGED_CODE();
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");

    /* If we already did this, bail out */
    if (GlobalDataInitialized) goto SuccessExit;

    /* Setup the symbolic link for Win32 support */
    RtlInitUnicodeString(&LinkName, L"\\DosDevices\\SAC");
    RtlInitUnicodeString(&DeviceName, L"\\Device\\SAC");
    Status = IoCreateSymbolicLink(&LinkName, &DeviceName);
    if (!NT_SUCCESS(Status)) return FALSE;

    /* Initialize the internal heap manager */
    if (!InitializeMemoryManagement())
    {
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status FALSE\n");
        return FALSE;
    }

    /* Preload the messages in memory */
    Status = PreloadGlobalMessageTable(DriverObject->DriverStart);
    if (!NT_SUCCESS(Status))
    {
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_INIT, "unable to pre-load message table: %X\n", Status);
        return FALSE;
    }

    /* Check if the administrator enabled this */
    Status = GetCommandConsoleLaunchingPermission(&CommandConsoleLaunchingEnabled);
    if (!NT_SUCCESS(Status))
    {
        /* Is it enabled? */
        if (CommandConsoleLaunchingEnabled)
        {
            /* Set the service start type to the correct value */
            Status = ImposeSacCmdServiceStartTypePolicy();
            if (!NT_SUCCESS(Status))
            {
                SAC_DBG(SAC_DBG_INIT, "failed ImposeSacCmdServiceStartTypePolicy: %X\n", Status);
            }
        }

        /* We're going to keep going with the default */
        SAC_DBG(SAC_DBG_INIT, "failed GetCommandConsoleLaunchingPermission: %X\n", Status);
    }

    /* Allocate the UTF-8 Conversion Buffer */
    Utf8ConversionBuffer = SacAllocatePool(Utf8ConversionBufferSize, GLOBAL_BLOCK_TAG);
    if (!Utf8ConversionBuffer)
    {
        /* Handle failure case */
        TearDownGlobalMessageTable();
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_INIT, "unable to allocate memory for UTF8 translation\n");
        return FALSE;
    }

    /* Initialize the channel manager */
    Status = ChanMgrInitialize();
    if (!NT_SUCCESS(Status))
    {
        /* Handle failure case */
        SacFreePool(Utf8ConversionBuffer);
        TearDownGlobalMessageTable();
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_INIT, "Failed to create SAC Channel\n");
        return FALSE;
    }

    /* Allocate the serial port buffer */
    SerialPortBuffer = SacAllocatePool(SAC_SERIAL_PORT_BUFFER_SIZE, GLOBAL_BLOCK_TAG);
    if (!SerialPortBuffer)
    {
        /* Handle failure case */
        SacFreePool(Utf8ConversionBuffer);
        TearDownGlobalMessageTable();
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_INIT, "Failed to allocate Serial Port Buffer\n");
        return FALSE;
    }

    /* Zero it out */
    RtlZeroMemory(SerialPortBuffer, SAC_SERIAL_PORT_BUFFER_SIZE);

    /* Initialize command events. After this, driver data is good to go */
    KeInitializeMutex(&SACCMDEventInfoMutex, FALSE);
    InitializeCmdEventInfo();
    GlobalDataInitialized = TRUE;
    ProcessingType = 0;
    IoctlSubmitted = 0;

    /* Create the SAC event */
    RtlInitUnicodeString(&EventName, L"\\SACEvent");
    SACEvent = IoCreateSynchronizationEvent(&EventName, &SACEventHandle);
    if (!SACEvent)
    {
        /* Handle failure case */
        SacFreePool(Utf8ConversionBuffer);
        TearDownGlobalMessageTable();
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with event NULL\n");
        return FALSE;
    }

    /* Cache machine information */
    InitializeMachineInformation();

    /* Register it */
    Status = RegisterBlueScreenMachineInformation();
    if (!NT_SUCCESS(Status))
    {
        /* Handle failure case */
        SacFreePool(Utf8ConversionBuffer);
        TearDownGlobalMessageTable();
        IoDeleteSymbolicLink(&LinkName);
        SAC_DBG(SAC_DBG_INIT, "Failed to register blue screen machine info\n");
        return FALSE;
    }

SuccessExit:
    /* Success path -- everything worked */
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status TRUE\n");
    return TRUE;
}
Пример #7
0
BOOLEAN
NTAPI
InitializeDeviceData(IN PDEVICE_OBJECT DeviceObject)
{
    PSAC_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
    BOOLEAN EnableData;
    ULONG PriorityValue;
    NTSTATUS Status;
    LARGE_INTEGER DueTime;
    PWCHAR Message;
    PAGED_CODE();
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n");

    /* If we already did this, bail out */
    if (DeviceExtension->Initialized) goto SuccessExit;

    /* Setup the DO flags */
    DeviceObject->Flags |= DO_DIRECT_IO;
    DeviceObject->StackSize = 16;

    /* Setup the device extension */
    DeviceExtension->DeviceObject = DeviceObject;
    DeviceExtension->PriorityBoost = IO_SERIAL_INCREMENT;
    DeviceExtension->PriorityFail = 0;
    DeviceExtension->RundownInProgress = 0;

    /* Initialize locks, events, timers, DPCs, etc... */
    KeInitializeTimer(&DeviceExtension->Timer);
    KeInitializeDpc(&DeviceExtension->Dpc, TimerDpcRoutine, DeviceExtension);
    KeInitializeSpinLock(&DeviceExtension->Lock);
    KeInitializeEvent(&DeviceExtension->Event, SynchronizationEvent, FALSE);
    InitializeListHead(&DeviceExtension->List);

    /* Attempt to enable HDL support */
    EnableData = TRUE;
    Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
                              &EnableData,
                              sizeof(EnableData),
                              NULL,
                              0);
    if (!NT_SUCCESS(Status))
    {
        /* Bail out if we couldn't even get this far */
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (1) with status FALSE\n");
        return FALSE;
    }

    /* Remember which process we started in */
    DeviceExtension->Process = IoGetCurrentProcess();

    /* Protect the device against non-admins */
    Status = CreateDeviceSecurityDescriptor(&DeviceExtension->DeviceObject);
    if (!NT_SUCCESS(Status))
    {
        /* Write down why we failed */
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (2) with status FALSE\n");

        /* Disable the HDL terminal on failure */
        EnableData = FALSE;
        Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
                                  &EnableData,
                                  sizeof(EnableData),
                                  NULL,
                                  NULL);
        if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");

        /* Bail out */
        return FALSE;
    }

    /* Create the worker thread */
    Status = PsCreateSystemThread(&DeviceExtension->WorkerThreadHandle,
                                  THREAD_ALL_ACCESS,
                                  NULL,
                                  NULL,
                                  NULL,
                                  WorkerThreadStartUp,
                                  DeviceExtension);
    if (!NT_SUCCESS(Status))
    {
        /* Write down why we failed */
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (3) with status FALSE\n");

        /* Disable the HDL terminal on failure */
        EnableData = FALSE;
        Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
                                  &EnableData,
                                  sizeof(EnableData),
                                  NULL,
                                  NULL);
        if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");

        /* Bail out */
        return FALSE;
    }

    /* Set the priority of our thread to highest */
    PriorityValue = HIGH_PRIORITY;
    Status = NtSetInformationThread(DeviceExtension->WorkerThreadHandle,
                                    ThreadPriority,
                                    &PriorityValue,
                                    sizeof(PriorityValue));
    if (!NT_SUCCESS(Status))
    {
        /* For debugging, write down why we failed */
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting (6) with status FALSE\n");
        DeviceExtension->PriorityFail = TRUE;

        /* Initialize rundown and wait for the thread to do it */
        KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, FALSE);
        KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, FALSE);
        Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent,
                                       Executive,
                                       KernelMode,
                                       FALSE,
                                       NULL);
        ASSERT(Status == STATUS_SUCCESS);

        /* Disable the HDL terminal on failure */
        EnableData = FALSE;
        Status = HeadlessDispatch(HeadlessCmdEnableTerminal,
                                  &EnableData,
                                  sizeof(EnableData),
                                  NULL,
                                  0);
        if (!NT_SUCCESS(Status)) SAC_DBG(SAC_DBG_INIT, "Failed dispatch\n");

        /* Bail out */
        return FALSE;
    }

    /* The first "packet" is the machine information in XML... */
    Status = TranslateMachineInformationXML(&Message, NULL);
    if (NT_SUCCESS(Status))
    {
        /* Go ahead and send it */
        UTF8EncodeAndSend(L"<?xml version=\"1.0\"?>\r\n");
        UTF8EncodeAndSend(Message);

        /* Free the temporary buffer */
        SacFreePool(Message);
    }

    /* Finally, initialize the I/O Manager */
    Status = ConMgrInitialize();
    if (!NT_SUCCESS(Status)) return FALSE;

    /* Set the timer. Once this is done, the device is initialized */
    DueTime.QuadPart = -4000;
    KeSetTimerEx(&DeviceExtension->Timer, DueTime, 4, &DeviceExtension->Dpc);
    DeviceExtension->Initialized = TRUE;

SuccessExit:
    /* Success path -- everything worked */
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status TRUE\n");
    return TRUE;
}