Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507/* * PROJECT: ReactOS Drivers * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: drivers/sac/driver/data.c * PURPOSE: Driver for the Server Administration Console (SAC) for EMS * PROGRAMMERS: ReactOS Portable Systems Group */
/* INCLUDES *******************************************************************/
#include "sacdrv.h"
/* GLOBALS ********************************************************************/
ULONG SACDebug = 0;BOOLEAN CommandConsoleLaunchingEnabled;BOOLEAN GlobalDataInitialized;KMUTEX SACCMDEventInfoMutex;BOOLEAN IoctlSubmitted;ULONG ProcessingType;PKEVENT SACEvent;HANDLE SACEventHandle;
/* FUNCTIONS ******************************************************************/
VOIDNTAPIWorkerProcessEvents(IN PSAC_DEVICE_EXTENSION DeviceExtension){ /* Call the worker function */ ConMgrWorkerProcessEvents(DeviceExtension);}
VOIDNTAPIWorkerThreadStartUp(IN PVOID Context){ /* Call the worker function */ WorkerProcessEvents((PSAC_DEVICE_EXTENSION)Context);}
NTSTATUSNTAPIBuildDeviceAcl(OUT PACL* Dacl){ /* TODO */ return STATUS_NOT_IMPLEMENTED;}
NTSTATUSNTAPICreateDeviceSecurityDescriptor(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;}
VOIDNTAPIFreeGlobalData(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");}
VOIDNTAPIFreeDeviceData(IN PDEVICE_OBJECT DeviceObject){ PSAC_DEVICE_EXTENSION DeviceExtension; NTSTATUS Status; KIRQL OldIrql; SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Entering.\n");
/* Get the device extension and see how far we had gotten */ DeviceExtension = (PSAC_DEVICE_EXTENSION)DeviceObject->DeviceExtension; if (!(GlobalDataInitialized) || !(DeviceExtension->Initialized)) { goto Exit; }
/* Attempt to rundown while holding the lock */ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql); while (DeviceExtension->RundownInProgress) { SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Waiting....\n");
/* Initiate and wait for rundown */ KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0); KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql); Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent, Executive, KernelMode, FALSE, NULL); ASSERT(Status == STATUS_SUCCESS);
/* Re-acquire the lock and check if rundown is done */ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql); }
/* Now set the rundown flag while we cancel the timer */ DeviceExtension->RundownInProgress = TRUE; KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);
/* Cancel it */ KeCancelTimer(&DeviceExtension->Timer);
/* Reacquire the lock*/ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql); DeviceExtension->RundownInProgress = FALSE;
/* Now do the last rundown attempt, we should be the only ones here */ KeInitializeEvent(&DeviceExtension->RundownEvent, SynchronizationEvent, 0); KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql); KeSetEvent(&DeviceExtension->Event, DeviceExtension->PriorityBoost, 0); Status = KeWaitForSingleObject(&DeviceExtension->RundownEvent, Executive, KernelMode, FALSE, NULL); ASSERT(Status == STATUS_SUCCESS);
/* We no longer care about shutdown */ IoUnregisterShutdownNotification(DeviceObject);
/* We are now fully uninitialized */ KeAcquireSpinLock(&DeviceExtension->Lock, &OldIrql); DeviceExtension->Initialized = FALSE; KeReleaseSpinLock(&DeviceExtension->Lock, OldIrql);Exit: SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC FreeDeviceData: Exiting.\n");}
BOOLEANNTAPIInitializeDeviceData(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, NULL); 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, NULL); 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;}
BOOLEANNTAPIInitializeGlobalData(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;}