NTSTATUS NTAPI ConMgrWriteData(IN PSAC_CHANNEL Channel, IN PVOID Buffer, IN ULONG BufferLength) { ULONG i; NTSTATUS Status; LARGE_INTEGER Interval; /* Loop up to 32 times */ for (i = 0; i < 32; i++) { /* Attempt sending the data */ Status = HeadlessDispatch(HeadlessCmdPutData, Buffer, BufferLength, NULL, NULL); if (Status != STATUS_UNSUCCESSFUL) break; /* Sending the data on the port failed, wait a second... */ Interval.HighPart = -1; Interval.LowPart = -100000; KeDelayExecutionThread(KernelMode, FALSE, &Interval); } /* After 32 attempts it should really have worked... */ ASSERT(NT_SUCCESS(Status)); return Status; }
BOOLEAN NTAPI InbvDisplayString(IN PCHAR String) { /* Make sure we own the display */ if (InbvDisplayState == INBV_DISPLAY_STATE_OWNED) { /* If we're not allowed, return success anyway */ if (!InbvDisplayDebugStrings) return TRUE; /* Check if a filter is installed */ if (InbvDisplayFilter) InbvDisplayFilter(&String); /* Acquire the lock */ InbvAcquireLock(); /* Make sure we're installed and display the string */ if (InbvBootDriverInstalled) VidDisplayString((PUCHAR)String); /* Print the string on the EMS port */ HeadlessDispatch(HeadlessCmdPutString, String, strlen(String) + sizeof(ANSI_NULL), NULL, NULL); /* Release the lock */ InbvReleaseLock(); /* All done */ return TRUE; } /* We don't own it, fail */ return FALSE; }
NTSTATUS NTAPI DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) { HEADLESS_RSP_QUERY_INFO HeadlessInformation; ULONG InfoSize = sizeof(HeadlessInformation); NTSTATUS Status; UNICODE_STRING DriverName; PDEVICE_OBJECT DeviceObject; PSAC_DEVICE_EXTENSION DeviceExtension; PAGED_CODE(); SAC_DBG(SAC_DBG_ENTRY_EXIT, "Entering.\n"); /* Check if EMS is enabled in the kernel */ HeadlessDispatch(HeadlessCmdQueryInformation, NULL, 0, &HeadlessInformation, &InfoSize); if ((HeadlessInformation.Serial.TerminalType != HeadlessUndefinedPortType) && ((HeadlessInformation.Serial.TerminalType != HeadlessSerialPort) || (HeadlessInformation.Serial.TerminalAttached))) { /* It is, so create the device */ RtlInitUnicodeString(&DriverName, L"\\Device\\SAC"); Status = IoCreateDevice(DriverObject, sizeof(SAC_DEVICE_EXTENSION), &DriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &DeviceObject); if (NT_SUCCESS(Status)) { /* Setup the device extension */ DeviceExtension = DeviceObject->DeviceExtension; DeviceExtension->Initialized = FALSE; /* Initialize the driver object */ RtlFillMemoryUlong(DriverObject->MajorFunction, RTL_NUMBER_OF(DriverObject->MajorFunction), (ULONG_PTR)Dispatch); DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl; DriverObject->MajorFunction[IRP_MJ_SHUTDOWN] = DispatchShutdownControl; DriverObject->FastIoDispatch = NULL; DriverObject->DriverUnload = UnloadHandler; /* Initialize driver data */ if (InitializeGlobalData(RegistryPath, DriverObject)) { /* Initialize device data */ if (InitializeDeviceData(DeviceObject)) { /* We're all good, register a shutdown notification */ IoRegisterShutdownNotification(DeviceObject); return Status; } } /* One of the initializations failed, bail out */ Status = STATUS_INSUFFICIENT_RESOURCES; } else { /* Print a debug statement if enabled */ SAC_DBG(SAC_DBG_INIT, "unable to create device object: %X\n", Status); } /* Free any data we may have allocated and exit with failure */ FreeGlobalData(); SAC_DBG(SAC_DBG_ENTRY_EXIT, "Exiting with status 0x%x\n", Status); return Status; } /* EMS is not enabled */ return STATUS_PORT_DISCONNECTED; }
VOID NTAPI ConMgrProcessInputLine(VOID) { BOOLEAN EnablePaging; NTSTATUS Status; SAC_DBG(4, "SAC Input Test: %s\n", InputBuffer); if (!strncmp(InputBuffer, "t", 1)) { DoTlistCommand(); } else if (!strncmp(InputBuffer, "?", 1)) { DoHelpCommand(); } else if (!strncmp(InputBuffer, "help", 4)) { DoHelpCommand(); } else if (!strncmp(InputBuffer, "f", 1)) { DoFullInfoCommand(); } else if (!strncmp(InputBuffer, "p", 1)) { DoPagingCommand(); } else if (!strncmp(InputBuffer, "id", 2)) { DoMachineInformationCommand(); } else if (!strncmp(InputBuffer, "crashdump", 9)) { DoCrashCommand(); } else if (!strncmp(InputBuffer, "lock", 4)) { DoLockCommand(); } else if (!strncmp(InputBuffer, "shutdown", 8)) { ExecutePostConsumerCommand = Shutdown; } else if (!strncmp(InputBuffer, "restart", 7)) { ExecutePostConsumerCommand = Restart; } else if (!strncmp(InputBuffer, "d", 1)) { EnablePaging = GlobalPagingNeeded; Status = HeadlessDispatch(HeadlessCmdDisplayLog, &EnablePaging, sizeof(EnablePaging), NULL, 0); if (!NT_SUCCESS(Status)) SAC_DBG(4, "SAC Display Log failed.\n"); } else if (!strncmp(InputBuffer, "cmd", 3)) { if (CommandConsoleLaunchingEnabled) { DoCmdCommand(InputBuffer); } else { SacPutSimpleMessage(148); } } else if (!(strncmp(InputBuffer, "ch", 2)) && (((strlen(InputBuffer) > 1) && (InputBuffer[2] == ' ')) || (strlen(InputBuffer) == 2))) { DoChannelCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "k", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoKillCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "l", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoLowerPriorityCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "r", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoRaisePriorityCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "m", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoLimitMemoryCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "s", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoSetTimeCommand(InputBuffer); } else if (!(strncmp(InputBuffer, "i", 1)) && (((strlen(InputBuffer) > 1) && (InputBuffer[1] == ' ')) || (strlen(InputBuffer) == 1))) { DoSetIpAddressCommand(InputBuffer); } else if ((InputBuffer[0] != '\n') && (InputBuffer[0] != ANSI_NULL)) { SacPutSimpleMessage(SAC_UNKNOWN_COMMAND); } }
NTSTATUS NTAPI ConMgrInitialize(VOID) { PWCHAR pcwch; PSAC_CHANNEL FoundChannel; SAC_CHANNEL_ATTRIBUTES SacChannelAttributes; NTSTATUS Status; /* Initialize the connection manager lock */ SacInitializeMutexLock(); SacAcquireMutexLock(); /* Setup the attributes for the raw SAC channel */ RtlZeroMemory(&SacChannelAttributes, sizeof(SacChannelAttributes)); SacChannelAttributes.ChannelType = VtUtf8; /* Get the right name for it */ pcwch = GetMessage(SAC_CHANNEL_NAME); ASSERT(pcwch); wcsncpy(SacChannelAttributes.NameBuffer, pcwch, SAC_CHANNEL_NAME_SIZE); SacChannelAttributes.NameBuffer[SAC_CHANNEL_NAME_SIZE] = ANSI_NULL; /* Get the right description for it */ pcwch = GetMessage(SAC_CHANNEL_DESCRIPTION); ASSERT(pcwch); wcsncpy(SacChannelAttributes.DescriptionBuffer, pcwch, SAC_CHANNEL_DESCRIPTION_SIZE); SacChannelAttributes.DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE] = ANSI_NULL; /* Set all the right flags */ SacChannelAttributes.Flag = SAC_CHANNEL_FLAG_APPLICATION | SAC_CHANNEL_FLAG_INTERNAL; SacChannelAttributes.CloseEvent = NULL; SacChannelAttributes.HasNewDataEvent = NULL; SacChannelAttributes.LockEvent = NULL; SacChannelAttributes.RedrawEvent = NULL; SacChannelAttributes.ChannelId = PRIMARY_SAC_CHANNEL_APPLICATION_GUID; /* Now create it */ Status = ChanMgrCreateChannel(&SacChannel, &SacChannelAttributes); if (NT_SUCCESS(Status)) { /* Try to get it back */ Status = ChanMgrGetByHandle(SacChannel->ChannelId, &FoundChannel); if (NT_SUCCESS(Status)) { /* Set it as the current and SAC channel */ SacChannel = CurrentChannel = FoundChannel; /* Diasable writes for now and clear the display */ _InterlockedExchange(&FoundChannel->WriteEnabled, FALSE); Status = HeadlessDispatch(HeadlessCmdClearDisplay, NULL, 0, NULL, NULL); if (!NT_SUCCESS(Status)) { SAC_DBG(SAC_DBG_INIT, "SAC ConMgrInitialize: Failed dispatch\n"); } /* Display the initial prompt */ SacPutSimpleMessage(SAC_NEWLINE); SacPutSimpleMessage(SAC_INIT_STATUS); SacPutSimpleMessage(SAC_NEWLINE); SacPutSimpleMessage(SAC_PROMPT); /* Display the current channel */ ConMgrDisplayCurrentChannel(); } } /* Release the channel lock */ SacReleaseMutexLock(); return STATUS_SUCCESS; }
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; }