Sync with trunk.
[reactos.git] / drivers / sac / driver / sacdrv.h
index 0936712..fef618c 100644 (file)
 /*
- * PROJECT:             ReactOS Boot Loader
- * LICENSE:             BSD - See COPYING.ARM in the top level directory
- * FILE:                drivers/sac/driver/sacdrv.h
- * PURPOSE:             Header for the Server Administration Console (SAC) for EMS
- * PROGRAMMERS:         ReactOS Portable Systems Group
+ * PROJECT:     ReactOS Drivers
+ * LICENSE:     BSD - See COPYING.ARM in the top level directory
+ * FILE:        drivers/sac/driver/sacdrv.h
+ * PURPOSE:     Driver for the Server Administration Console (SAC) for EMS
+ * PROGRAMMERS: ReactOS Portable Systems Group
  */
 
-/* INCLUDES *******************************************************************/
+/* INCLUDES ******************************************************************/
+
 #include <ntifs.h>
-#include <ntoskrnl/include/internal/hdl.h>
-
-#define SAC_DBG_ENTRY_EXIT             0x01
-#define SAC_DBG_INIT                   0x04
-#define SAC_DBG_MM                             0x1000
-
-#define SAC_DBG(x, ...)                                                \
-       if (SACDebug & x)                                               \
-       {                                                                               \
-               DbgPrint("SAC %s: ", __FUNCTION__);     \
-               DbgPrint(__VA_ARGS__);                          \
-       }
-
-#define CHECK_PARAMETER_WITH_STATUS(Parameter, Status) \
-{      \
-       ASSERT((Parameter)); \
-       if (!Parameter) \
-       {       \
-               return Status; \
-       }       \
+#include <intrin.h>
+#include <wchar.h>
+#include <ndk/obtypes.h>
+#include <ndk/exfuncs.h>
+#include <ndk/rtlfuncs.h>
+#include <../../../ntoskrnl/include/internal/hdl.h>
+#include <initguid.h>
+#include <sacmsg.h>
+
+/* DEFINES *******************************************************************/
+
+//
+// SAC Heap Allocator Macros
+//
+#define SacAllocatePool(Length, Tag)    \
+    MyAllocatePool(Length, Tag, __FILE__, __LINE__)
+#define SacFreePool(Pointer)            \
+    MyFreePool((PVOID*)(&Pointer))
+
+//
+// SAC Debugging Macro and Constants
+//
+#define SAC_DBG_ENTRY_EXIT                  0x01
+#define SAC_DBG_UTIL                        0x02
+#define SAC_DBG_INIT                        0x04
+#define SAC_DBG_MM                          0x1000
+#define SAC_DBG(x, ...)                     \
+    if (SACDebug & x)                       \
+    {                                       \
+        DbgPrint("SAC %s: ", __FUNCTION__); \
+        DbgPrint(__VA_ARGS__);              \
+    }
+
+//
+// SAC Parameter Checking Macros
+//
+#define CHECK_PARAMETER_WITH_STATUS(Parameter, Status)  \
+{   \
+    ASSERT(((PVOID)(Parameter)) != NULL);    \
+    if (((PVOID)(Parameter)) == NULL) \
+    {   \
+       return Status;  \
+    }   \
 }
-#define CHECK_PARAMETER(x)             \
-       CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER)
-#define CHECK_PARAMETER1(x)            \
-       CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_1)
-#define CHECK_PARAMETER2(x)            \
-       CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_2)
-#define CHECK_PARAMETER3(x)            \
-       CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_3)
-#define CHECK_ALLOCATION(x)            \
-       CHECK_PARAMETER_WITH_STATUS(x, STATUS_OUT_OF_MEMORY)
-       
-#define SacAllocatePool(Length, Tag)   \
-       MyAllocatePool(Length, Tag, __FILE__, __LINE__)
-
-#define ChannelLock(Channel, x)        \
-{      \
-       KeWaitForSingleObject(  \
-               &(Channel)->x.Lock,     \
-               Executive,      \
-               KernelMode,     \
-               FALSE,  \
-               NULL);  \
-       ASSERT((Channel)->x.RefCount == 0);     \
-       InterlockedIncrement(&(Channel)->x.RefCount);   \
+#define CHECK_PARAMETER(x)      \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER)
+#define CHECK_PARAMETER1(x)     \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_1)
+#define CHECK_PARAMETER2(x)     \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_2)
+#define CHECK_PARAMETER3(x)     \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_3)
+#define CHECK_PARAMETER4(x)     \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_INVALID_PARAMETER_4)
+#define CHECK_ALLOCATION(x)     \
+    CHECK_PARAMETER_WITH_STATUS(x, STATUS_NO_MEMORY)
+
+//
+// SAC Channel Event Macros
+//
+#define ChannelInitializeEvent(Channel, Attributes, x)  \
+{   \
+    PVOID Object, WaitObject;   \
+    if (Attributes->x)  \
+    {   \
+        if (!VerifyEventWaitable(Attributes->x, &Object, &WaitObject))  \
+        {   \
+            goto FailChannel;   \
+        } \
+        Channel->x = Attributes->x; \
+        Channel->x##ObjectBody = Object;    \
+        Channel->x##WaitObjectBody = WaitObject;    \
+    }   \
 }
-
-#define ChannelUnlock(Channel, x)      \
-{      \
-       ASSERT((Channel)->x.RefCount == 1);     \
-       InterlockedDecrement(&(Channel)->x.RefCount);   \
-       KeReleaseSemaphore(     \
-               &(Channel)->x.Lock,     \
-               SEMAPHORE_INCREMENT,    \
-               1,      \
-               FALSE); \
+#define ChannelUninitializeEvent(Channel, x, f)                     \
+{                                                                   \
+    ASSERT(ChannelGetFlags(Channel) & (f));                         \
+    ASSERT(Channel->x##ObjectBody);                                 \
+    ASSERT(Channel->x##WaitObjectBody);                             \
+    if (Channel->x##ObjectBody)                                     \
+    {                                                               \
+        ObDereferenceObject(Channel->x##ObjectBody);                \
+        Channel->Flags &= ~(f);                                     \
+        Channel->x = NULL;                                          \
+        Channel->x##ObjectBody = NULL;                              \
+        Channel->x##WaitObjectBody = NULL;                          \
+    }   \
 }
-
-#define ChannelLockOBuffer(Channel)                    ChannelLock(Channel, ChannelOBufferLock);
-#define ChannelUnlockOBuffer(Channel)          ChannelUnlock(Channel, ChannelOBufferLock);
-#define ChannelLockIBuffer(Channel)                    ChannelLock(Channel, ChannelIBufferLock);
-#define ChannelUnlockIBuffer(Channel)          ChannelUnlock(Channel, ChannelIBufferLock);
-#define ChannelLockAttributes(Channel)         ChannelLock(Channel, ChannelAttributesLock);
-#define ChannelUnlockAttributes(Channel)       ChannelUnlock(Channel, ChannelAttributesLock);
-
-#define ChannelInitializeEvent(Channel, Attributes, x) \
-{      \
-       PVOID Object, WaitObject;       \
-       if (Attributes->x)      \
-       {       \
-               if (!VerifyEventWaitable(Attributes->x, &Object, &WaitObject))  \
-               {       \
-                       goto FailChannel;       \
-               } \
-               Channel->x = Attributes->x;     \
-               Channel->x##ObjectBody = Object;        \
-               Channel->x##WaitObjectBody = WaitObject;        \
-       }       \
-}
-
-#define ChannelSetEvent(Channel, x)    \
-{      \
-       ASSERT(Channel->x);     \
-       ASSERT(Channel->x##ObjectBody); \
-       ASSERT(Channel->x##WaitObjectBody);     \
-       if (Channel->x) \
-       {       \
-               KeSetEvent(Channel->x, EVENT_INCREMENT, FALSE); \
-               Status = STATUS_SUCCESS;        \
-       }       \
-       else    \
-       {       \
-               Status = STATUS_UNSUCCESSFUL;   \
-       }       \
+#define ChannelSetEvent(Channel, x) \
+{   \
+    ASSERT(Channel->x); \
+    ASSERT(Channel->x##ObjectBody); \
+    ASSERT(Channel->x##WaitObjectBody); \
+    if (Channel->x##WaitObjectBody) \
+    {   \
+        KeSetEvent(Channel->x##WaitObjectBody, EVENT_INCREMENT, FALSE); \
+        Status = STATUS_SUCCESS;    \
+    }   \
+    else    \
+    {   \
+        Status = STATUS_UNSUCCESSFUL;   \
+    }   \
 }
-
-#define ChannelClearEvent(Channel, x)  \
-{      \
-       ASSERT(Channel->x);     \
-       ASSERT(Channel->x##ObjectBody); \
-       ASSERT(Channel->x##WaitObjectBody);     \
-       if (Channel->x) \
-       {       \
-               KeClearEvent(Channel->x);       \
-               Status = STATUS_SUCCESS;        \
-       }       \
-       else    \
-       {       \
-               Status = STATUS_UNSUCCESSFUL;   \
-       }       \
+#define ChannelClearEvent(Channel, x)   \
+{   \
+    ASSERT(Channel->x); \
+    ASSERT(Channel->x##ObjectBody); \
+    ASSERT(Channel->x##WaitObjectBody); \
+    if (Channel->x##WaitObjectBody) \
+    {   \
+       KeClearEvent(Channel->x##WaitObjectBody);   \
+       Status = STATUS_SUCCESS;    \
+    }   \
+    else    \
+    {   \
+       Status = STATUS_UNSUCCESSFUL;   \
+    }   \
 }
 
-//Rcp? - sacdrv.sys - SAC Driver (Headless)
-//RcpA - sacdrv.sys -     Internal memory mgr alloc block
-//RcpI - sacdrv.sys -     Internal memory mgr initial heap block
-//RcpS - sacdrv.sys -     Security related block
-#define GENERIC_TAG                            '?pcR'
-#define ALLOC_BLOCK_TAG                        'ApcR'
-#define INITIAL_BLOCK_TAG              'IpcR'
-#define SECURITY_BLOCK_TAG             'SpcR'
-#define FREE_POOL_TAG                  'FpcR'
-
-#define LOCAL_MEMORY_SIGNATURE         'SSEL'
-#define GLOBAL_MEMORY_SIGNATURE        'DAEH'
-
-#define SAC_MEMORY_LIST_SIZE   (1 * 1024 * 1024)
-
-#define SAC_OBUFFER_SIZE               (2 * 1024)
-
-#define SAC_CHANNEL_FLAG_CLOSE_EVENT           0x2
-#define SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT    0x4
-#define SAC_CHANNEL_FLAG_LOCK_EVENT                    0x8
-#define SAC_CHANNEL_FLAG_REDRAW_EVENT          0x10
+//
+// SAC Pool Tags, taken from pooltag.txt:
+//
+//  Rcp? - sacdrv.sys - SAC Driver (Headless)
+//  RcpA - sacdrv.sys -     Internal memory mgr alloc block
+//  RcpI - sacdrv.sys -     Internal memory mgr initial heap block
+//  RcpS - sacdrv.sys -     Security related block
+#define GENERIC_TAG                         '?pcR'
+#define ALLOC_BLOCK_TAG                     'ApcR'
+#define INITIAL_BLOCK_TAG                   'IpcR'
+#define SECURITY_BLOCK_TAG                  'SpcR'
+#define FREE_POOL_TAG                       'FpcR'
+#define GLOBAL_BLOCK_TAG                    'GpcR'
+#define CHANNEL_BLOCK_TAG                   'CpcR'
+#define LOCAL_MEMORY_SIGNATURE              'SSEL'
+#define GLOBAL_MEMORY_SIGNATURE                    'DAEH'
+
+//
+// Size Definitions
+//
+#define SAC_MEMORY_LIST_SIZE                (1 * 1024 * 1024)   // 1MB
+#define SAC_OBUFFER_SIZE                    (2 * 1024)          // 2KB
+#define SAC_CHANNEL_NAME_SIZE               64
+#define SAC_CHANNEL_DESCRIPTION_SIZE        256
+#define SAC_MAX_CHANNELS                    10
+#define SAC_SERIAL_PORT_BUFFER_SIZE         1024                // 1KB
+#define SAC_MAX_MESSAGES                    200
+
+//
+// Channel flags
+//
+#define SAC_CHANNEL_FLAG_INTERNAL           0x1
+#define SAC_CHANNEL_FLAG_CLOSE_EVENT        0x2
+#define SAC_CHANNEL_FLAG_HAS_NEW_DATA_EVENT 0x4
+#define SAC_CHANNEL_FLAG_LOCK_EVENT            0x8
+#define SAC_CHANNEL_FLAG_REDRAW_EVENT       0x10
+#define SAC_CHANNEL_FLAG_APPLICATION        0x20
+
+//
+// Forward definitions
+//
+struct _SAC_CHANNEL;
 
+//
+// Structures used by the SAC Heap Allocator
+//
 typedef struct _SAC_MEMORY_ENTRY
 {
-       ULONG Signature;
-       ULONG Tag;
-       ULONG Size;
+    ULONG Signature;
+    ULONG Tag;
+    ULONG Size;
 } SAC_MEMORY_ENTRY, *PSAC_MEMORY_ENTRY;
-
 typedef struct _SAC_MEMORY_LIST
 {
-       ULONG Signature;
-       PSAC_MEMORY_ENTRY LocalDescriptor;
-       ULONG Size;
-       struct _SAC_MEMORY_LIST* Next;
+    ULONG Signature;
+    PSAC_MEMORY_ENTRY LocalDescriptor;
+    ULONG Size;
+    struct _SAC_MEMORY_LIST* Next;
 } SAC_MEMORY_LIST, *PSAC_MEMORY_LIST;
 
+typedef struct _SAC_MESSAGE_ENTRY
+{
+    ULONG Index;
+    PWCHAR Buffer;
+} SAC_MESSAGE_ENTRY, *PSAC_MESSAGE_ENTRY;
+
+//
+// SAC supports 3 different channel output types
+//
 typedef enum _SAC_CHANNEL_TYPE
 {
-       VtUtf8,
-       Cmd,
-       Raw
+    VtUtf8,
+    Cmd,
+    Raw
 } SAC_CHANNEL_TYPE;
 
+//
+// A SAC channel can be active or inactive
+//
 typedef enum _SAC_CHANNEL_STATUS
 {
-       Inactive,
-       Active
+    Inactive,
+    Active
 } SAC_CHANNEL_STATUS, *PSAC_CHANNEL_STATUS;
 
+//
+// A SAC channel identifier
+//
 typedef struct _SAC_CHANNEL_ID
 {
-       GUID ChannelGuid;
-       ULONG ChannelId;
+    GUID ChannelGuid;
+    ULONG ChannelId;
 } SAC_CHANNEL_ID, *PSAC_CHANNEL_ID;
 
+//
+// Reference-counted SAC channel semaphore lock
+//
 typedef struct _SAC_CHANNEL_LOCK
 {
-       LONG RefCount;
-       KSEMAPHORE Lock;
+    LONG RefCount;
+    KSEMAPHORE Lock;
 } SAC_CHANNEL_LOCK, *PSAC_CHANNEL_LOCK;
 
-struct _SAC_CHANNEL;
-
+//
+// Channel callbacks
+//
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_CREATE)(
-       IN struct _SAC_CHANNEL* Channel
-       );
+(NTAPI *PSAC_CHANNEL_CREATE)(
+    IN struct _SAC_CHANNEL* Channel
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_DESTROY)(
-       IN struct _SAC_CHANNEL* Channel
-       );
+(NTAPI *PSAC_CHANNEL_DESTROY)(
+    IN struct _SAC_CHANNEL* Channel
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_OREAD)(
-       IN struct _SAC_CHANNEL* Channel,
-       IN PCHAR Buffer,
-       IN ULONG BufferSize,
-       OUT PULONG ByteCount
-       );
+(NTAPI *PSAC_CHANNEL_OREAD)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    OUT PULONG ByteCount
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_OECHO)(
-       IN struct _SAC_CHANNEL* Channel,
-       IN PWCHAR String,
-       IN ULONG Length
-       );
+(NTAPI *PSAC_CHANNEL_OECHO)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_OFLUSH)(
-       IN struct _SAC_CHANNEL* Channel
-       );
+(NTAPI *PSAC_CHANNEL_OFLUSH)(
+    IN struct _SAC_CHANNEL* Channel
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_OWRITE)(
-       IN struct _SAC_CHANNEL* Channel,
-       IN PWCHAR String,
-       IN ULONG Length
-       );
+(NTAPI *PSAC_CHANNEL_OWRITE)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_IREAD)(
-       IN struct _SAC_CHANNEL* Channel,
-       IN PWCHAR Buffer,
-       IN ULONG BufferSize,
-       IN PULONG ReturnBufferSize
-       );
+(NTAPI *PSAC_CHANNEL_IREAD)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    IN PULONG ReturnBufferSize
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_IBUFFER_FULL)(
-       IN struct _SAC_CHANNEL* Channel,
-       OUT PBOOLEAN BufferStatus
-       );
+(NTAPI *PSAC_CHANNEL_IBUFFER_FULL)(
+    IN struct _SAC_CHANNEL* Channel,
+    OUT PBOOLEAN BufferStatus
+);
 
 typedef
-NTSTATUS
-(*PSAC_CHANNEL_IBUFFER_LENGTH)(
-       IN struct _SAC_CHANNEL* Channel
-       );
+ULONG
+(NTAPI *PSAC_CHANNEL_IBUFFER_LENGTH)(
+    IN struct _SAC_CHANNEL* Channel
+);
 
 typedef
 CHAR
-(*PSAC_CHANNEL_IREAD_LAST)(
-       IN struct _SAC_CHANNEL* Channel
-       );
+(NTAPI *PSAC_CHANNEL_IREAD_LAST)(
+    IN struct _SAC_CHANNEL* Channel
+);
 
 typedef
 NTSTATUS
-(*PSAC_CHANNEL_IWRITE)(
-       IN struct _SAC_CHANNEL* Channel,
-       IN PCHAR Buffer,
-       IN ULONG BufferSize
-       );
+(NTAPI *PSAC_CHANNEL_IWRITE)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
 
+//
+// A channel and its attributes
+//
 typedef struct _SAC_CHANNEL
 {
-       ULONG Index;
-       SAC_CHANNEL_ID ChannelId;
-       HANDLE CloseEvent;
-       PVOID CloseEventObjectBody;
-       PKEVENT CloseEventWaitObjectBody;
-       HANDLE HasNewDataEvent;
-       PVOID HasNewDataEventObjectBody;
-       PKEVENT HasNewDataEventWaitObjectBody;
-       HANDLE LockEvent;
-       PVOID LockEventObjectBody;
-       PKEVENT LockEventWaitObjectBody;
-       HANDLE RedrawEvent;
-       PVOID RedrawEventObjectBody;
-       PKEVENT RedrawEventWaitObjectBody;
-       PFILE_OBJECT FileObject;
-       SAC_CHANNEL_TYPE ChannelType;
-       SAC_CHANNEL_STATUS ChannelStatus;
-       WCHAR NameBuffer[64 + 1];
-       WCHAR DescriptionBuffer[256 + 1];
-       ULONG Flags;
-       GUID ApplicationType;
-       BOOLEAN WriteEnabled;
-       ULONG IBufferIndex;
-       PVOID IBuffer;
-       BOOLEAN ChannelHasNewIBufferData;
-       UCHAR CursorRow;
-       UCHAR CursorCol;
-       UCHAR CursorY;
-       UCHAR CursorX;
-       UCHAR CursorVisible;
-       PVOID OBuffer;
-       ULONG OBufferIndex;
-       ULONG OBufferFirstGoodIndex;
-       BOOLEAN ChannelHasNewOBufferData;
-       PSAC_CHANNEL_CREATE ChannelCreate;
-       PSAC_CHANNEL_DESTROY ChannelDestroy;
-       PSAC_CHANNEL_OFLUSH OBufferFlush;
-       PSAC_CHANNEL_OECHO OBufferEcho;
-       PSAC_CHANNEL_OWRITE OBufferWrite;
-       PSAC_CHANNEL_OREAD OBufferRead;
-       PSAC_CHANNEL_OWRITE IBufferWrite;
-       PSAC_CHANNEL_IREAD IBufferRead;
-       PSAC_CHANNEL_IREAD_LAST IBufferReadLast;
-       PSAC_CHANNEL_IBUFFER_FULL IBufferIsFull;
-       PSAC_CHANNEL_IBUFFER_LENGTH IBufferLength;
-       SAC_CHANNEL_LOCK ChannelAttributeLock;
-       SAC_CHANNEL_LOCK ChannelOBufferLock;
-       SAC_CHANNEL_LOCK ChannelIBufferLock;
+    LONG Index;
+    SAC_CHANNEL_ID ChannelId;
+    HANDLE CloseEvent;
+    PVOID CloseEventObjectBody;
+    PKEVENT CloseEventWaitObjectBody;
+    HANDLE HasNewDataEvent;
+    PVOID HasNewDataEventObjectBody;
+    PKEVENT HasNewDataEventWaitObjectBody;
+    HANDLE LockEvent;
+    PVOID LockEventObjectBody;
+    PKEVENT LockEventWaitObjectBody;
+    HANDLE RedrawEvent;
+    PVOID RedrawEventObjectBody;
+    PKEVENT RedrawEventWaitObjectBody;
+    PFILE_OBJECT FileObject;
+    SAC_CHANNEL_TYPE ChannelType;
+    SAC_CHANNEL_STATUS ChannelStatus;
+    WCHAR NameBuffer[SAC_CHANNEL_NAME_SIZE + 1];
+    WCHAR DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE + 1];
+    ULONG Flags;
+    GUID ApplicationType;
+    LONG WriteEnabled;
+    ULONG IBufferIndex;
+    PCHAR IBuffer;
+    LONG ChannelHasNewIBufferData;
+    UCHAR CursorRow;
+    UCHAR CursorCol;
+    UCHAR CursorY;
+    UCHAR CursorX;
+    UCHAR CursorVisible;
+    PCHAR OBuffer;
+    ULONG OBufferIndex;
+    ULONG OBufferFirstGoodIndex;
+    LONG ChannelHasNewOBufferData;
+    PSAC_CHANNEL_CREATE ChannelCreate;
+    PSAC_CHANNEL_DESTROY ChannelDestroy;
+    PSAC_CHANNEL_OFLUSH ChannelOutputFlush;
+    PSAC_CHANNEL_OECHO ChannelOutputEcho;
+    PSAC_CHANNEL_OWRITE ChannelOutputWrite;
+    PSAC_CHANNEL_OREAD ChannelOutputRead;
+    PSAC_CHANNEL_IWRITE ChannelInputWrite;
+    PSAC_CHANNEL_IREAD ChannelInputRead;
+    PSAC_CHANNEL_IREAD_LAST ChannelInputReadLast;
+    PSAC_CHANNEL_IBUFFER_FULL ChannelInputBufferIsFull;
+    PSAC_CHANNEL_IBUFFER_LENGTH ChannelInputBufferLength;
+    SAC_CHANNEL_LOCK ChannelAttributeLock;
+    SAC_CHANNEL_LOCK ChannelOBufferLock;
+    SAC_CHANNEL_LOCK ChannelIBufferLock;
 } SAC_CHANNEL, *PSAC_CHANNEL;
 
-typedef struct _SAC_DEVICE_EXTENSION
-{
-       PDEVICE_OBJECT DeviceObject;
-       BOOLEAN Initialized;
-       BOOLEAN Rundown;
-       BOOLEAN PriorityFail;
-       KPRIORITY PriorityBoost;
-       PEPROCESS Process;
-       KSPIN_LOCK Lock;
-       KEVENT RundownEvent;
-       KEVENT Event;
-       HANDLE WorkerThreadHandle;
-       KEVENT WorkerThreadEvent;
-       KTIMER Timer;
-       KDPC Dpc;
-       LIST_ENTRY List;
-} SAC_DEVICE_EXTENSION, *PSAC_DEVICE_EXTENSION;
-
 typedef struct _SAC_CHANNEL_ATTRIBUTES
 {
-       SAC_CHANNEL_TYPE ChannelType;
-       WCHAR NameBuffer[64 + 1];
-       WCHAR DescriptionBuffer[256 + 1];
-       ULONG Flag;
-       PKEVENT CloseEvent;
-       PKEVENT HasNewDataEvent;
-       PKEVENT LockEvent;
-       PKEVENT RedrawEvent;
-       GUID ChannelId;
+    SAC_CHANNEL_TYPE ChannelType;
+    WCHAR NameBuffer[64 + 1];
+    WCHAR DescriptionBuffer[256 + 1];
+    ULONG Flag;
+    HANDLE CloseEvent;
+    HANDLE HasNewDataEvent;
+    HANDLE LockEvent;
+    HANDLE RedrawEvent;
+    GUID ChannelId;
 } SAC_CHANNEL_ATTRIBUTES, *PSAC_CHANNEL_ATTRIBUTES;
 
+//
+// Cached Machine Information
+//
+typedef struct _SAC_MACHINE_INFO
+{
+    PWCHAR MachineName;
+    PWCHAR MachineGuid;
+    PWCHAR ProcessorArchitecture;
+    PWCHAR MajorVersion;
+    PWCHAR BuildNumber;
+    PWCHAR ProductType;
+    PWCHAR ServicePack;
+} SAC_MACHINE_INFO, *PSAC_MACHINE_INFO;
+
+//
+// The device extension for the SAC
+//
+typedef struct _SAC_DEVICE_EXTENSION
+{
+    PDEVICE_OBJECT DeviceObject;
+    BOOLEAN Initialized;
+    BOOLEAN Rundown;
+    BOOLEAN PriorityFail;
+    BOOLEAN RundownInProgress;
+    KPRIORITY PriorityBoost;
+    PEPROCESS Process;
+    KSPIN_LOCK Lock;
+    KEVENT RundownEvent;
+    KEVENT Event;
+    HANDLE WorkerThreadHandle;
+    KEVENT WorkerThreadEvent;
+    KTIMER Timer;
+    KDPC Dpc;
+    LIST_ENTRY List;
+} SAC_DEVICE_EXTENSION, *PSAC_DEVICE_EXTENSION;
+
+//
+// Dispatch Routines
+//
 NTSTATUS
+NTAPI
 Dispatch(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
 );
 
 NTSTATUS
 NTAPI
 DispatchDeviceControl(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
 );
 
 NTSTATUS
+NTAPI
 DispatchShutdownControl(
-       IN PDEVICE_OBJECT DeviceObject,
-       IN PIRP Irp
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
 );
 
 VOID
+NTAPI
 UnloadHandler(
-       IN PDRIVER_OBJECT DriverObject
+    IN PDRIVER_OBJECT DriverObject
 );
 
+//
+// Initialization and shutdown routines
+//
 VOID
+NTAPI
 FreeGlobalData(
-       VOID
+    VOID
+);
+
+VOID
+NTAPI
+FreeDeviceData(
+    IN PDEVICE_OBJECT DeviceObject
 );
 
 BOOLEAN
+NTAPI
 InitializeDeviceData(
-       IN PDEVICE_OBJECT DeviceObject
+    IN PDEVICE_OBJECT DeviceObject
 );
 
 BOOLEAN
+NTAPI
 InitializeGlobalData(
-       IN PUNICODE_STRING RegistryPath,
-       IN PDRIVER_OBJECT DriverObject
+    IN PUNICODE_STRING RegistryPath,
+    IN PDRIVER_OBJECT DriverObject
+);
+
+BOOLEAN
+NTAPI
+InitializeMemoryManagement(
+    VOID
+);
+
+VOID
+NTAPI
+FreeMemoryManagement(
+    VOID
+);
+
+VOID
+NTAPI
+InitializeCmdEventInfo(
+    VOID
+);
+
+VOID
+NTAPI
+InitializeMachineInformation(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+PreloadGlobalMessageTable(
+    IN PVOID ImageBase
+);
+
+NTSTATUS
+NTAPI
+TearDownGlobalMessageTable(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+GetCommandConsoleLaunchingPermission(
+    OUT PBOOLEAN Permission
+);
+
+NTSTATUS
+NTAPI
+ImposeSacCmdServiceStartTypePolicy(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+RegisterBlueScreenMachineInformation(
+    VOID
+);
+
+VOID
+NTAPI
+FreeMachineInformation(
+    VOID
+);
+
+//
+// DPC, Timer, Thread Callbacks
+//
+VOID
+NTAPI
+TimerDpcRoutine(
+    IN PKDPC Dpc,
+    IN PVOID DeferredContext,
+    IN PVOID SystemArgument1,
+    IN PVOID SystemArgument2
+);
+
+//
+// Custom SAC Heap Allocator Routines
+//
+PVOID
+NTAPI
+MyAllocatePool(
+    IN SIZE_T PoolSize,
+    IN ULONG Tag,
+    IN PCHAR File,
+    IN ULONG Line
+);
+
+VOID
+NTAPI
+MyFreePool(
+    IN PVOID *Block
+);
+
+//
+// Connection Manager Routines
+//
+NTSTATUS
+NTAPI
+ConMgrInitialize(
+    VOID
+);
+
+VOID
+NTAPI
+ConMgrWorkerProcessEvents(
+    IN PSAC_DEVICE_EXTENSION DeviceExtension
+);
+
+NTSTATUS
+NTAPI
+ConMgrShutdown(
+    VOID
+);
+
+BOOLEAN
+NTAPI
+ConMgrSimpleEventMessage(
+    IN ULONG MessageIndex,
+    IN BOOLEAN LockHeld
+);
+
+BOOLEAN
+NTAPI
+SacPutSimpleMessage(
+    IN ULONG MessageIndex
+);
+
+VOID
+NTAPI
+SacPutString(
+    IN PWCHAR String
+);
+
+NTSTATUS
+NTAPI
+ConMgrWriteData(
+    IN PSAC_CHANNEL Channel,
+    IN PVOID Buffer,
+    IN ULONG BufferLength
+);
+
+NTSTATUS
+NTAPI
+ConMgrFlushData(
+    IN PSAC_CHANNEL Channel
+);
+
+BOOLEAN
+NTAPI
+ConMgrIsWriteEnabled(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ConMgrHandleEvent(
+    IN ULONG EventCode,
+    IN PSAC_CHANNEL Channel,
+    OUT PVOID Data
+);
+
+//
+// Channel Manager Routines
+//
+NTSTATUS
+NTAPI
+ChanMgrInitialize(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+ChanMgrShutdown(
+    VOID
+);
+
+NTSTATUS
+NTAPI
+ChanMgrCreateChannel(
+    OUT PSAC_CHANNEL *Channel,
+    IN PSAC_CHANNEL_ATTRIBUTES Attributes
+);
+
+NTSTATUS
+NTAPI
+ChanMgrGetByHandle(
+    IN SAC_CHANNEL_ID ChannelId,
+    OUT PSAC_CHANNEL* TargetChannel
+);
+
+NTSTATUS
+NTAPI
+ChanMgrReleaseChannel(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChanMgrGetNextActiveChannel(
+    IN PSAC_CHANNEL CurrentChannel,
+    IN PULONG TargetIndex,
+    OUT PSAC_CHANNEL *TargetChannel
+);
+
+NTSTATUS
+NTAPI
+ChanMgrCloseChannel(
+    IN PSAC_CHANNEL Channel
+);
+
+//
+// Channel Routines
+//
+NTSTATUS
+NTAPI
+ChannelClose(
+    IN PSAC_CHANNEL Channel
+);
+
+BOOLEAN
+NTAPI
+ChannelIsEqual(
+    IN PSAC_CHANNEL Channel,
+    IN PSAC_CHANNEL_ID ChannelId
+);
+
+NTSTATUS
+NTAPI
+ChannelOWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+NTSTATUS
+NTAPI
+ChannelOFlush(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChannelSetRedrawEvent(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChannelClearRedrawEvent(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChannelHasRedrawEvent(
+    IN PSAC_CHANNEL Channel,
+    OUT PBOOLEAN Present
+);
+
+BOOLEAN
+NTAPI
+ChannelIsActive(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChannelGetName(
+    IN PSAC_CHANNEL Channel,
+    OUT PWCHAR *Name
+);
+
+BOOLEAN
+NTAPI
+ChannelIsEqual(
+    IN PSAC_CHANNEL Channel,
+    IN PSAC_CHANNEL_ID ChannelId
+);
+
+NTSTATUS
+NTAPI
+ChannelCreate(
+    IN PSAC_CHANNEL Channel,
+    IN PSAC_CHANNEL_ATTRIBUTES Attributes,
+    IN SAC_CHANNEL_ID ChannelId
+);
+
+NTSTATUS
+NTAPI
+ChannelDestroy(
+    IN PSAC_CHANNEL Channel
+);
+
+//
+// RAW Channel Table
+//
+NTSTATUS
+NTAPI
+RawChannelCreate(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+RawChannelDestroy(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+RawChannelORead(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    OUT PULONG ByteCount
+);
+
+NTSTATUS
+NTAPI
+RawChannelOEcho(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+NTSTATUS
+NTAPI
+RawChannelOFlush(
+    IN PSAC_CHANNEL Channel
 );
 
+NTSTATUS
+NTAPI
+RawChannelOWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+NTSTATUS
+NTAPI
+RawChannelIRead(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    IN PULONG ReturnBufferSize
+);
+
+NTSTATUS
+NTAPI
+RawChannelIBufferIsFull(
+    IN PSAC_CHANNEL Channel,
+    OUT PBOOLEAN BufferStatus
+);
+
+ULONG
+NTAPI
+RawChannelIBufferLength(
+    IN PSAC_CHANNEL Channel
+);
+
+CHAR
+NTAPI
+RawChannelIReadLast(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+RawChannelIWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+//
+// Helper Routines
+//
+NTSTATUS
+NTAPI
+SerialBufferGetChar(
+    OUT PCHAR Char
+);
+
+NTSTATUS
+NTAPI
+UTF8EncodeAndSend(
+    IN PWCHAR String
+);
+
+NTSTATUS
+NTAPI
+TranslateMachineInformationXML(
+    IN PWCHAR *Buffer,
+    IN PWCHAR ExtraData
+);
+
+PWCHAR
+NTAPI
+GetMessage(
+    IN ULONG MessageIndex
+);
+
+BOOLEAN
+NTAPI
+VerifyEventWaitable(
+    IN HANDLE Handle,
+    OUT PVOID *WaitObject,
+    OUT PVOID *ActualWaitObject
+);
+
+//
+// SAC Command Functions
+//
+VOID
+NTAPI
+DoRebootCommand(
+    IN BOOLEAN Reboot
+);
+
+//
+// External data
+//
 extern ULONG SACDebug;
+extern PSAC_MESSAGE_ENTRY GlobalMessageTable;
+extern KMUTEX CurrentChannelLock;
+extern LONG CurrentChannelRefCount;
+extern PCHAR SerialPortBuffer;
+extern PCHAR Utf8ConversionBuffer;
+extern ULONG Utf8ConversionBufferSize;
+
+//
+// Function to initailize a SAC Semaphore Lock
+//
+FORCEINLINE
+VOID
+SacInitializeLock(IN PSAC_CHANNEL_LOCK Lock)
+{
+    KeInitializeSemaphore(&Lock->Lock, 1, 1);
+}
 
+//
+// Function to acquire a SAC Semaphore Lock
+//
+FORCEINLINE
+VOID
+SacAcquireLock(IN PSAC_CHANNEL_LOCK Lock)
+{
+    KeWaitForSingleObject(&Lock->Lock, Executive, KernelMode, FALSE, NULL);
+    ASSERT(Lock->RefCount == 0);
+    _InterlockedIncrement(&Lock->RefCount);
+}
+
+//
+// Function to release a SAC Semaphore Lock
+//
+FORCEINLINE
+VOID
+SacReleaseLock(IN PSAC_CHANNEL_LOCK Lock)
+{
+    ASSERT(Lock->RefCount == 1);
+    _InterlockedDecrement(&Lock->RefCount);
+    KeReleaseSemaphore(&Lock->Lock, SEMAPHORE_INCREMENT, 1, FALSE);
+}
+
+//
+// Function to check if the SAC Mutex Lock is held
+//
+FORCEINLINE
+VOID
+SacAssertMutexLockHeld(VOID)
+{
+    ASSERT(CurrentChannelRefCount == 1);
+    ASSERT(KeReadStateMutex(&CurrentChannelLock) == 0);
+}
+
+//
+// Function to check if the SAC Mutex Lock is held
+//
+FORCEINLINE
+VOID
+SacInitializeMutexLock(VOID)
+{
+    KeInitializeMutex(&CurrentChannelLock, 0);
+    CurrentChannelRefCount = 0;
+}
+
+//
+// Function to acquire the SAC Mutex Lock
+//
+FORCEINLINE
+VOID
+SacAcquireMutexLock(VOID)
+{
+    KeWaitForSingleObject(&CurrentChannelLock, Executive, KernelMode, FALSE, NULL);
+    ASSERT(CurrentChannelRefCount == 0);
+    _InterlockedIncrement(&CurrentChannelRefCount);
+}
+
+//
+// Function to release the SAC Mutex Lock
+//
+FORCEINLINE
+VOID
+SacReleaseMutexLock(VOID)
+{
+    ASSERT(CurrentChannelRefCount == 1);
+    _InterlockedDecrement(&CurrentChannelRefCount);
+    KeReleaseMutex(&CurrentChannelLock, FALSE);
+}
+
+//
+// Locking Macros
+//
+#define ChannelLockCreates()            SacAcquireLock(&ChannelCreateLock);
+#define ChannelUnlockCreates()          SacReleaseLock(&ChannelCreateLock);
+#define ChannelLockOBuffer(x)           SacAcquireLock(&x->ChannelOBufferLock);
+#define ChannelUnlockOBuffer(x)         SacReleaseLock(&x->ChannelOBufferLock);
+#define ChannelLockIBuffer(x)           SacAcquireLock(&x->ChannelIBufferLock);
+#define ChannelUnlockIBuffer(x)         SacReleaseLock(&x->ChannelIBufferLock);
+#define ChannelLockAttributes(x)        SacAcquireLock(&x->ChannelAttributeLock);
+#define ChannelUnlockAttributes(x)      SacReleaseLock(&x->ChannelAttributeLock);
+#define ChannelSlotLock(x)              SacAcquireLock(&ChannelSlotLock[x]);
+#define ChannelSlotUnlock(x)            SacReleaseLock(&ChannelSlotLock[x]);
+
+//
+// Channel Accessors
+//
+FORCEINLINE
+ULONG
+ChannelGetFlags(IN PSAC_CHANNEL Channel)
+{
+    return Channel->Flags;
+}
+
+FORCEINLINE
+LONG
+ChannelGetIndex(IN PSAC_CHANNEL Channel)
+{
+    /* Return the index of the channel */
+    return Channel->Index;
+}