Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / sac / driver / sacdrv.h
diff --git a/drivers/sac/driver/sacdrv.h b/drivers/sac/driver/sacdrv.h
new file mode 100644 (file)
index 0000000..602afd0
--- /dev/null
@@ -0,0 +1,1518 @@
+/*
+ * 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
+ */
+
+#ifndef _SACDRV_H_
+#define _SACDRV_H_
+
+/* INCLUDES *******************************************************************/
+
+#include <ntifs.h>
+#include <stdio.h>
+#include <ntoskrnl/include/internal/hdl.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_MACHINE                     0x2000
+#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_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 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 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##WaitObjectBody)                 \
+    {                                               \
+        KeClearEvent(Channel->x##WaitObjectBody);   \
+        Status = STATUS_SUCCESS;                    \
+    }                                               \
+    else                                            \
+    {                                               \
+        Status = STATUS_UNSUCCESSFUL;               \
+    }                                               \
+}
+
+//
+// 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
+#define SAC_VTUTF8_COL_WIDTH                80
+#define SAC_VTUTF8_COL_HEIGHT               25
+#define SAC_VTUTF8_ROW_HEIGHT               24
+#define MAX_UTF8_ENCODE_BLOCK_LENGTH        (Utf8ConversionBufferSize / 3 - 1)
+#define SAC_VTUTF8_OBUFFER_SIZE             0x2D00
+#define SAC_VTUTF8_IBUFFER_SIZE             0x2000
+#define SAC_RAW_OBUFFER_SIZE                0x2000
+#define SAC_RAW_IBUFFER_SIZE                0x2000
+
+//
+// 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
+
+//
+// Cell Flags
+//
+#define SAC_CELL_FLAG_BLINK                 1
+#define SAC_CELL_FLAG_BOLD                  2
+#define SAC_CELL_FLAG_INVERTED              4
+
+//
+// Forward definitions
+//
+struct _SAC_CHANNEL;
+
+//
+// Structures used by the SAC Heap Allocator
+//
+typedef struct _SAC_MEMORY_ENTRY
+{
+    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;
+} SAC_MEMORY_LIST, *PSAC_MEMORY_LIST;
+
+typedef struct _SAC_MESSAGE_ENTRY
+{
+    ULONG Index;
+    PWCHAR Buffer;
+} SAC_MESSAGE_ENTRY, *PSAC_MESSAGE_ENTRY;
+
+//
+// These are the VT-100/220/ANSI Escape Codes supported by SAC as input
+//
+typedef enum _SAC_ANSI_COMMANDS
+{
+    SacCursorUp,
+    SacCursorDown,
+    SacCursorRight,
+    SacCursorLeft,
+    SacFontNormal,
+    SacFontBlink,
+    SacFontBlinkOff,
+    SacFontBold,
+    SacFontBoldOff,
+    SacFontInverse,
+    SacFontInverseOff,
+    SacBackTab,
+    SacEraseEndOfLine,
+    SacEraseStartOfLine,
+    SacEraseLine,
+    SacEraseEndOfScreen,
+    SacEraseStartOfScreen,
+    SacEraseScreen,
+    SacSetCursorPosition,
+    SacSetScrollRegion,
+    SacSetColors,
+    SacSetBackgroundColor,
+    SacSetFontColor,
+    SacSetColorsAndAttributes
+} SAC_ANSI_COMMANDS;
+
+//
+// These are the VT-100/220/ANSI Escape Codes send by SAC as output
+//
+typedef enum _SAC_ANSI_DISPATCH
+{
+    SacAnsiClearScreen,
+    SacAnsiClearEndOfScreen,
+    SacAnsiClearEndOfLine,
+    SacAnsiSetColors,
+    SacAnsiSetPosition,
+    SacAnsiClearAttributes,
+    SacAnsiSetInverseAttribute,
+    SacAnsiClearInverseAttribute,
+    SacAnsiSetBlinkAttribute,
+    SacAnsiClearBlinkAttribute,
+    SacAnsiSetBoldAttribute,
+    SacAnsiClearBoldAttribute
+} SAC_ANSI_DISPATCH;
+
+//
+// Commands that the consumer and producer share
+//
+typedef enum _SAC_POST_COMMANDS
+{
+    Nothing,
+    Shutdown,
+    Close,
+    Restart
+} SAC_POST_COMMANDS;
+
+//
+// SAC supports 3 different channel output types
+//
+typedef enum _SAC_CHANNEL_TYPE
+{
+    VtUtf8,
+    Cmd,
+    Raw
+} SAC_CHANNEL_TYPE;
+
+//
+// A SAC channel can be active or inactive
+//
+typedef enum _SAC_CHANNEL_STATUS
+{
+    Inactive,
+    Active
+} SAC_CHANNEL_STATUS, *PSAC_CHANNEL_STATUS;
+
+//
+// A SAC channel identifier
+//
+typedef struct _SAC_CHANNEL_ID
+{
+    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;
+} SAC_CHANNEL_LOCK, *PSAC_CHANNEL_LOCK;
+
+//
+// Structure of the cell-buffer when in VT-UTF8 Mode
+//
+typedef struct _SAC_CELL_DATA
+{
+    UCHAR CellBackColor;
+    UCHAR CellForeColor;
+    UCHAR CellFlags;
+    WCHAR Char;
+} SAC_CELL_DATA, *PSAC_CELL_DATA;
+C_ASSERT(sizeof(SAC_CELL_DATA) == 6);
+
+//
+// Screen buffer when in VT-UTF8 Mode
+//
+typedef struct _SAC_VTUTF8_SCREEN
+{
+    SAC_CELL_DATA Cell[SAC_VTUTF8_ROW_HEIGHT][SAC_VTUTF8_COL_WIDTH];
+} SAC_VTUTF8_SCREEN, *PSAC_VTUTF8_SCREEN;
+
+//
+// Small optimization to easily recognize the most common VT-100/ANSI codes
+//
+typedef struct _SAC_STATIC_ESCAPE_STRING
+{
+    WCHAR Sequence[10];
+    ULONG Size;
+    ULONG Action;
+} SAC_STATIC_ESCAPE_STRING, *PSAC_STATIC_ESCAPE_STRING;
+
+//
+// Channel callbacks
+//
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_CREATE)(
+    IN struct _SAC_CHANNEL* Channel
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_DESTROY)(
+    IN struct _SAC_CHANNEL* Channel
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_OREAD)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    OUT PULONG ByteCount
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_OECHO)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_OFLUSH)(
+    IN struct _SAC_CHANNEL* Channel
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_OWRITE)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_IREAD)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    IN PULONG ReturnBufferSize
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_IBUFFER_FULL)(
+    IN struct _SAC_CHANNEL* Channel,
+    OUT PBOOLEAN BufferStatus
+);
+
+typedef
+ULONG
+(NTAPI *PSAC_CHANNEL_IBUFFER_LENGTH)(
+    IN struct _SAC_CHANNEL* Channel
+);
+
+typedef
+WCHAR
+(NTAPI *PSAC_CHANNEL_IREAD_LAST)(
+    IN struct _SAC_CHANNEL* Channel
+);
+
+typedef
+NTSTATUS
+(NTAPI *PSAC_CHANNEL_IWRITE)(
+    IN struct _SAC_CHANNEL* Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+//
+// A channel and its attributes
+//
+typedef struct _SAC_CHANNEL
+{
+    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 CellForeColor;
+    UCHAR CellBackColor;
+    UCHAR CellFlags;
+    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_CHANNEL_ATTRIBUTES
+{
+    SAC_CHANNEL_TYPE ChannelType;
+    WCHAR NameBuffer[SAC_CHANNEL_NAME_SIZE + 1];
+    WCHAR DescriptionBuffer[SAC_CHANNEL_DESCRIPTION_SIZE + 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
+);
+
+NTSTATUS
+NTAPI
+DispatchDeviceControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+);
+
+NTSTATUS
+NTAPI
+DispatchShutdownControl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp
+);
+
+VOID
+NTAPI
+UnloadHandler(
+    IN PDRIVER_OBJECT DriverObject
+);
+
+//
+// Initialization and shutdown routines
+//
+VOID
+NTAPI
+FreeGlobalData(
+    VOID
+);
+
+VOID
+NTAPI
+FreeDeviceData(
+    IN PDEVICE_OBJECT DeviceObject
+);
+
+BOOLEAN
+NTAPI
+InitializeDeviceData(
+    IN PDEVICE_OBJECT DeviceObject
+);
+
+BOOLEAN
+NTAPI
+InitializeGlobalData(
+    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
+);
+
+NTSTATUS
+NTAPI
+ChannelIWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+WCHAR
+NTAPI
+ChannelIReadLast(
+    IN PSAC_CHANNEL Channel
+);
+
+ULONG
+NTAPI
+ChannelIBufferLength(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+ChannelIRead(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    IN OUT PULONG ResultBufferSize
+);
+
+//
+// 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
+);
+
+WCHAR
+NTAPI
+RawChannelIReadLast(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+RawChannelIWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+//
+// VT-UTF8 Channel Table
+//
+NTSTATUS
+NTAPI
+VTUTF8ChannelCreate(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelDestroy(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelORead(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    OUT PULONG ByteCount
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelOEcho(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelOFlush(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelOWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR String,
+    IN ULONG Length
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelIRead(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize,
+    IN PULONG ReturnBufferSize
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelIBufferIsFull(
+    IN PSAC_CHANNEL Channel,
+    OUT PBOOLEAN BufferStatus
+);
+
+ULONG
+NTAPI
+VTUTF8ChannelIBufferLength(
+    IN PSAC_CHANNEL Channel
+);
+
+WCHAR
+NTAPI
+VTUTF8ChannelIReadLast(
+    IN PSAC_CHANNEL Channel
+);
+
+NTSTATUS
+NTAPI
+VTUTF8ChannelIWrite(
+    IN PSAC_CHANNEL Channel,
+    IN PCHAR Buffer,
+    IN ULONG BufferSize
+);
+
+
+//
+// Helper Routines
+//
+BOOLEAN
+NTAPI
+SacTranslateUtf8ToUnicode(
+    IN CHAR Utf8Char,
+    IN PCHAR Utf8Buffer,
+    OUT PWCHAR Utf8Value
+);
+
+ULONG
+NTAPI
+GetMessageLineCount(
+    IN ULONG MessageIndex
+);
+
+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
+);
+
+BOOLEAN
+NTAPI
+SacTranslateUnicodeToUtf8(
+    IN PWCHAR SourceBuffer,
+    IN ULONG SourceBufferLength,
+    OUT PCHAR DestinationBuffer,
+    IN ULONG DestinationBufferSize,
+    OUT PULONG UTF8Count,
+    OUT PULONG ProcessedCount
+);
+
+//
+// SAC Command Functions
+//
+VOID
+NTAPI
+DoRebootCommand(
+    IN BOOLEAN Reboot
+);
+
+VOID
+NTAPI
+DoFullInfoCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoPagingCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoSetTimeCommand(
+    IN PCHAR InputTime
+);
+
+VOID
+NTAPI
+DoKillCommand(
+    IN PCHAR KillString
+);
+
+VOID
+NTAPI
+DoLowerPriorityCommand(
+    IN PCHAR PrioString
+);
+
+VOID
+NTAPI
+DoRaisePriorityCommand(
+    IN PCHAR PrioString
+);
+
+VOID
+NTAPI
+DoLimitMemoryCommand(
+    IN PCHAR LimitString
+);
+
+VOID
+NTAPI
+DoCrashCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoMachineInformationCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoChannelCommand(
+    IN PCHAR ChannelString
+);
+
+VOID
+NTAPI
+DoCmdCommand(
+    IN PCHAR InputString
+);
+
+VOID
+NTAPI
+DoLockCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoHelpCommand(
+    VOID
+);
+
+VOID
+NTAPI
+DoGetNetInfo(
+    IN BOOLEAN DoPrint
+);
+
+VOID
+NTAPI
+DoSetIpAddressCommand(
+    IN PCHAR IpString
+);
+
+VOID
+NTAPI
+DoTlistCommand(
+    VOID
+);
+
+//
+// External data
+//
+extern ULONG SACDebug;
+extern PSAC_MESSAGE_ENTRY GlobalMessageTable;
+extern KMUTEX CurrentChannelLock;
+extern LONG CurrentChannelRefCount;
+extern PCHAR SerialPortBuffer;
+extern LONG SerialPortConsumerIndex, SerialPortProducerIndex;
+extern PCHAR Utf8ConversionBuffer;
+extern BOOLEAN GlobalPagingNeeded, GlobalDoThreads;
+extern ULONG Utf8ConversionBufferSize;
+extern BOOLEAN CommandConsoleLaunchingEnabled;
+
+//
+// Function to initialize 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;
+}
+
+FORCEINLINE
+BOOLEAN
+ChannelHasNewIBufferData(IN PSAC_CHANNEL Channel)
+{
+    /* Return if there's any new data in the input buffer */
+    return Channel->ChannelHasNewIBufferData;
+}
+
+//
+// FIXME: ANSI.H
+//
+//
+// Source: http://en.wikipedia.org/wiki/ANSI_escape_code
+//
+typedef enum _VT_ANSI_ATTRIBUTES
+{
+    //
+    // Attribute modifiers (mostly supported)
+    //
+    Normal,
+    Bold,
+    Faint,
+    Italic,
+    Underline,
+    SlowBlink,
+    FastBlink,
+    Inverse,
+    Conceal,
+    Strikethrough,
+
+    //
+    // Font selectors (not supported)
+    //
+    PrimaryFont,
+    AlternateFont1,
+    AlternateFont2,
+    AlternateFont3,
+    Alternatefont4,
+    AlternateFont5,
+    AlternateFont6,
+    AlternateFont7,
+    AlternateFont8,
+    AlternateFont9,
+
+    //
+    // Additional attributes (not supported)
+    //
+    Fraktur,
+    DoubleUnderline,
+
+    //
+    // Attribute Un-modifiers (mostly supported)
+    //
+    BoldOff,
+    ItalicOff,
+    UnderlineOff,
+    BlinkOff,
+    Reserved,
+    InverseOff,
+    ConcealOff,
+    StrikethroughOff,
+
+    //
+    // Standard Text Color
+    //
+    SetColorStart,
+    SetColorBlack = SetColorStart,
+    SetColorRed,
+    SetColorGreen,
+    SetColorYellow,
+    SetColorBlue,
+    SetcolorMAgent,
+    SetColorCyan,
+    SetColorWhite,
+    SetColorMax = SetColorWhite,
+
+    //
+    // Extended Text Color (not supported)
+    //
+    SetColor256,
+    SeTextColorDefault,
+
+    //
+    // Standard Background Color
+    //
+    SetBackColorStart,
+    SetBackColorBlack = SetBackColorStart,
+    SetBackColorRed,
+    SetBackColorGreen,
+    SetBackColorYellow,
+    SetBackColorBlue,
+    SetBackcolorMAgent,
+    SetBackColorCyan,
+    SetBackColorWhite,
+    SetBackColorMax = SetBackColorWhite,
+
+    //
+    // Extended Background Color (not supported)
+    //
+    SetBackColor256,
+    SetBackColorDefault,
+
+    //
+    // Extra Attributes (not supported)
+    //
+    Reserved1,
+    Framed,
+    Encircled,
+    Overlined,
+    FramedOff,
+    OverlinedOff,
+    Reserved2,
+    Reserved3,
+    Reserved4,
+    Reserved5
+
+    //
+    // Ideograms (not supported)
+    //
+} VT_ANSI_ATTRIBUTES;
+
+//
+// The following site is a good reference on VT100/ANSI escape codes
+// http://www.termsys.demon.co.uk/vtansi.htm
+//
+#define VT_ANSI_ESCAPE              L'\x1B'
+#define VT_ANSI_COMMAND             L'['
+
+#define VT_ANSI_CURSOR_UP_CHAR      L'A'
+#define VT_ANSI_CURSOR_UP           L"[A"
+
+#define VT_ANSI_CURSOR_DOWN_CHAR    L'B'
+#define VT_ANSI_CURSOR_DOWN         L"[B"
+
+#define VT_ANSI_CURSOR_RIGHT_CHAR   L'C'
+#define VT_ANSI_CURSOR_RIGHT        L"[C"
+
+#define VT_ANSI_CURSOR_LEFT_CHAR    L'D'
+#define VT_ANSI_CURSOR_LEFT         L"[D"
+
+#define VT_ANSI_ERASE_LINE_CHAR     L'K'
+#define VT_ANSI_ERASE_END_LINE      L"[K"
+#define VT_ANSI_ERASE_START_LINE    L"[1K"
+#define VT_ANSI_ERASE_ENTIRE_LINE   L"[2K"
+
+#define VT_ANSI_ERASE_SCREEN_CHAR   L'J'
+#define VT_ANSI_ERASE_DOWN_SCREEN   L"[J"
+#define VT_ANSI_ERASE_UP_SCREEN     L"[1J"
+#define VT_ANSI_ERASE_ENTIRE_SCREEN L"[2J"
+
+#define VT_ANSI_BACKTAB_CHAR        L'Z'
+#define VT_220_BACKTAB              L"[0Z"
+
+#define VT_ANSI_SET_ATTRIBUTE_CHAR  L'm'
+#define VT_ANSI_SEPARATOR_CHAR      L';'
+#define VT_ANSI_HVP_CURSOR_CHAR     L'f'
+#define VT_ANSI_CUP_CURSOR_CHAR     L'H'
+#define VT_ANSI_SCROLL_CHAR         L'r'
+
+#endif /* _SACDRV_H_ */