You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
611 lines
16 KiB
611 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 1989 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sac.h
|
|
|
|
Abstract:
|
|
|
|
This is the local header file for SAC. It includes all other
|
|
necessary header files for this driver.
|
|
|
|
Author:
|
|
|
|
Sean Selitrennikoff (v-seans) - Jan 11, 1999
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#ifndef _SACP_
|
|
#define _SACP_
|
|
|
|
#pragma warning(disable:4214) // bit field types other than int
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
#pragma warning(disable:4127) // condition expression is constant
|
|
#pragma warning(disable:4115) // named type definition in parentheses
|
|
//#pragma warning(disable:4206) // translation unit empty
|
|
//#pragma warning(disable:4706) // assignment within conditional
|
|
//#pragma warning(disable:4324) // structure was padded
|
|
//#pragma warning(disable:4328) // greater alignment than needed
|
|
|
|
#include <stdio.h>
|
|
#include <ntosp.h>
|
|
#include <zwapi.h>
|
|
#include <hdlsblk.h>
|
|
#include <hdlsterm.h>
|
|
|
|
#include "sacmsg.h"
|
|
#include <ntddsac.h>
|
|
|
|
//
|
|
// Debug spew control
|
|
//
|
|
#if DBG
|
|
extern ULONG SACDebug;
|
|
#define SAC_DEBUG_FUNC_TRACE 0x0001
|
|
#define SAC_DEBUG_FAILS 0x0004
|
|
#define SAC_DEBUG_RECEIVE 0x0008
|
|
#define SAC_DEBUG_FUNC_TRACE_LOUD 0x2000 // Warning! This could get loud!
|
|
#define SAC_DEBUG_MEM 0x1000 // Warning! This could get loud!
|
|
|
|
#define IF_SAC_DEBUG(x, y) if ((x) & SACDebug) { y; }
|
|
#else
|
|
#define IF_SAC_DEBUG(x, y)
|
|
#endif
|
|
|
|
#define ASSERT_STATUS(_C, _S)\
|
|
ASSERT((_C));\
|
|
if (!(_C)) {\
|
|
return(_S);\
|
|
}
|
|
|
|
#if 0
|
|
//
|
|
// General lock (mutex) management macros
|
|
//
|
|
typedef struct _SAC_LOCK {
|
|
|
|
ULONG RefCount;
|
|
KMUTEX Mutex;
|
|
|
|
} SAC_LOCK, *PSAC_LOCK;
|
|
|
|
#define INITIALIZE_LOCK(_l) \
|
|
KeInitializeMutex( \
|
|
&(_l.Mutex), \
|
|
0 \
|
|
); \
|
|
_l.RefCount = 0;
|
|
|
|
#define LOCK_IS_SIGNALED(_l) \
|
|
(KeReadStateMutex(&(_l.Mutex)) == 1 ? TRUE : FALSE)
|
|
|
|
#define LOCK_HAS_ZERO_REF_COUNT(_l) \
|
|
(_l.RefCount == 0 ? TRUE : FALSE)
|
|
|
|
#define ACQUIRE_LOCK(_l) \
|
|
KeWaitForMutexObject( \
|
|
&(_l.Mutex), \
|
|
Executive, \
|
|
KernelMode, \
|
|
FALSE, \
|
|
NULL \
|
|
); \
|
|
ASSERT(_l.RefCount == 0); \
|
|
InterlockedIncrement(&(_l.RefCount));
|
|
|
|
#define RELEASE_LOCK(_l) \
|
|
ASSERT(_l.RefCount == 1); \
|
|
InterlockedDecrement(&(_l.RefCount)); \
|
|
KeReleaseMutex( \
|
|
&(_l.Mutex), \
|
|
FALSE \
|
|
);
|
|
#else
|
|
//
|
|
// General lock (mutex) management macros
|
|
//
|
|
typedef struct _SAC_LOCK {
|
|
|
|
ULONG RefCount;
|
|
KSEMAPHORE Lock;
|
|
|
|
} SAC_LOCK, *PSAC_LOCK;
|
|
|
|
#define INITIALIZE_LOCK(_l) \
|
|
KeInitializeSemaphore( \
|
|
&(_l.Lock), \
|
|
1, \
|
|
1 \
|
|
); \
|
|
_l.RefCount = 0;
|
|
|
|
#define LOCK_IS_SIGNALED(_l) \
|
|
(KeReadStateSemaphore(&(_l.Lock)) == 1 ? TRUE : FALSE)
|
|
|
|
#define LOCK_HAS_ZERO_REF_COUNT(_l) \
|
|
(_l.RefCount == 0 ? TRUE : FALSE)
|
|
|
|
#define ACQUIRE_LOCK(_l) \
|
|
KeWaitForSingleObject( \
|
|
&(_l.Lock), \
|
|
Executive, \
|
|
KernelMode, \
|
|
FALSE, \
|
|
NULL \
|
|
); \
|
|
ASSERT(_l.RefCount == 0); \
|
|
InterlockedIncrement((volatile long *)&(_l.RefCount));
|
|
|
|
#define RELEASE_LOCK(_l) \
|
|
ASSERT(_l.RefCount == 1); \
|
|
InterlockedDecrement((volatile long *)&(_l.RefCount)); \
|
|
KeReleaseSemaphore( \
|
|
&(_l.Lock), \
|
|
IO_NO_INCREMENT, \
|
|
1, \
|
|
FALSE \
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// This really belongs in ntdef or someplace like that...
|
|
//
|
|
typedef CONST UCHAR *LPCUCHAR, *PCUCHAR;
|
|
|
|
#include "channel.h"
|
|
|
|
//
|
|
// this macro ensures that we assert if we buffer overrun during the swprintf
|
|
//
|
|
// NOTE: 1 is added to the length to acct for UNICODE_NULL
|
|
//
|
|
#define SAFE_SWPRINTF(_size, _p)\
|
|
{ \
|
|
ULONG l; \
|
|
l = swprintf _p; \
|
|
ASSERT(((l+1)*sizeof(WCHAR)) <= _size); \
|
|
}
|
|
|
|
//
|
|
// NOTE: 1 is added to the length to acct for UNICODE_NULL
|
|
//
|
|
#define SAFE_WCSCPY(_size, _d, _s) \
|
|
{ \
|
|
if (_size >= 2) { \
|
|
ULONG l; \
|
|
l = (ULONG)wcslen(_s); \
|
|
ASSERT(((l+1)*sizeof(WCHAR)) <= _size); \
|
|
wcsncpy(_d,_s,(_size / sizeof(WCHAR))); \
|
|
(_d)[(_size / sizeof(WCHAR)) - 1] = UNICODE_NULL; \
|
|
} else { \
|
|
ASSERT(0); \
|
|
} \
|
|
}
|
|
|
|
#ifndef max
|
|
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
#ifndef min
|
|
#define min(a,b) (((a) < (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
//
|
|
// Machine Information table and routines.
|
|
//
|
|
#define INIT_OBJA(Obja,UnicodeString,UnicodeText) \
|
|
\
|
|
RtlInitUnicodeString((UnicodeString),(UnicodeText)); \
|
|
\
|
|
InitializeObjectAttributes( \
|
|
(Obja), \
|
|
(UnicodeString), \
|
|
OBJ_CASE_INSENSITIVE, \
|
|
NULL, \
|
|
NULL \
|
|
)
|
|
|
|
//
|
|
// common xml header
|
|
//
|
|
#define XML_VERSION_HEADER L"<?xml version=\"1.0\"?>\r\n"
|
|
|
|
//
|
|
// Device name
|
|
//
|
|
#define SAC_DEVICE_NAME L"\\Device\\SAC"
|
|
#define SAC_DOSDEVICE_NAME L"\\DosDevices\\SAC"
|
|
|
|
//
|
|
// Memory tags
|
|
//
|
|
#define ALLOC_POOL_TAG ((ULONG)'ApcR')
|
|
#define INITIAL_POOL_TAG ((ULONG)'IpcR')
|
|
//#define IRP_POOL_TAG ((ULONG)'JpcR')
|
|
#define SECURITY_POOL_TAG ((ULONG)'SpcR')
|
|
|
|
//
|
|
// SAC internal Memory tags
|
|
//
|
|
#define FREE_POOL_TAG ((ULONG)'FpcR')
|
|
#define GENERAL_POOL_TAG ((ULONG)'GpcR')
|
|
#define CHANNEL_POOL_TAG ((ULONG)'CpcR')
|
|
|
|
//
|
|
// Other defines
|
|
//
|
|
|
|
#define MEMORY_INCREMENT 0x1000
|
|
|
|
#define DEFAULT_IRP_STACK_SIZE 16
|
|
#define DEFAULT_PRIORITY_BOOST 2
|
|
#define SAC_SUBMIT_IOCTL 1
|
|
#define SAC_PROCESS_INPUT 2
|
|
#define SAC_CHANGE_CHANNEL 3
|
|
#define SAC_DISPLAY_CHANNEL 4
|
|
#define SAC_NO_OP 0
|
|
#define SAC_RETRY_GAP 10
|
|
#define SAC_PROCESS_SERIAL_PORT_BUFFER 20
|
|
|
|
//
|
|
// Context for each device created
|
|
//
|
|
typedef struct _SAC_DEVICE_CONTEXT {
|
|
|
|
PDEVICE_OBJECT DeviceObject; // back pointer to the device object.
|
|
|
|
BOOLEAN InitializedAndReady; // Is this device ready to go?
|
|
BOOLEAN Processing; // Is something being processed on this device?
|
|
BOOLEAN ExitThread; // Should the worker thread exit?
|
|
|
|
CCHAR PriorityBoost; // boost to priority for completions.
|
|
PKPROCESS SystemProcess; // context for grabbing handles
|
|
PSECURITY_DESCRIPTOR AdminSecurityDescriptor;
|
|
KSPIN_LOCK SpinLock; // Used to lock this data structure for access.
|
|
KEVENT UnloadEvent; // Used to signal the thread trying to unload to continue processing.
|
|
KEVENT ProcessEvent; // Used to signal worker thread to process the next request.
|
|
|
|
HANDLE ThreadHandle; // Handle for the worker thread.
|
|
KEVENT ThreadExitEvent; // Used to main thread the worker thread is exiting.
|
|
|
|
KTIMER Timer; // Used to poll for user input.
|
|
KDPC Dpc; // Used with the above timer.
|
|
|
|
LIST_ENTRY IrpQueue; // List of IRPs to be processed.
|
|
|
|
} SAC_DEVICE_CONTEXT, * PSAC_DEVICE_CONTEXT;
|
|
|
|
//
|
|
// Structure to hold general machine information
|
|
//
|
|
typedef struct _MACHINE_INFORMATION {
|
|
|
|
PWSTR MachineName;
|
|
PWSTR GUID;
|
|
PWSTR ProcessorArchitecture;
|
|
PWSTR OSVersion;
|
|
PWSTR OSBuildNumber;
|
|
PWSTR OSProductType;
|
|
PWSTR OSServicePack;
|
|
|
|
} MACHINE_INFORMATION, *PMACHINE_INFORMATION;
|
|
|
|
//
|
|
// IoMgrHandleEvent event types
|
|
//
|
|
typedef enum _IO_MGR_EVENT {
|
|
|
|
IO_MGR_EVENT_CHANNEL_CREATE = 0,
|
|
IO_MGR_EVENT_CHANNEL_CLOSE,
|
|
IO_MGR_EVENT_CHANNEL_WRITE,
|
|
IO_MGR_EVENT_REGISTER_SAC_CMD_EVENT,
|
|
IO_MGR_EVENT_UNREGISTER_SAC_CMD_EVENT,
|
|
IO_MGR_EVENT_SHUTDOWN
|
|
|
|
} IO_MGR_EVENT;
|
|
|
|
//
|
|
// IO Manager function types
|
|
//
|
|
typedef NTSTATUS
|
|
(*IO_MGR_HANDLE_EVENT)(
|
|
IN IO_MGR_EVENT Event,
|
|
IN PSAC_CHANNEL Channel,
|
|
IN PVOID Data
|
|
);
|
|
|
|
typedef NTSTATUS
|
|
(*IO_MGR_INITITIALIZE)(
|
|
VOID
|
|
);
|
|
|
|
typedef NTSTATUS
|
|
(*IO_MGR_SHUTDOWN)(
|
|
VOID
|
|
);
|
|
|
|
typedef VOID
|
|
(*IO_MGR_WORKER)(
|
|
IN PSAC_DEVICE_CONTEXT DeviceContext
|
|
);
|
|
|
|
typedef BOOLEAN
|
|
(*IO_MGR_IS_WRITE_ENABLED)(
|
|
IN PSAC_CHANNEL Channel
|
|
);
|
|
|
|
typedef NTSTATUS
|
|
(*IO_MGR_WRITE_DATA)(
|
|
IN PSAC_CHANNEL Channel,
|
|
IN PCUCHAR Buffer,
|
|
IN ULONG BufferSize
|
|
);
|
|
|
|
typedef NTSTATUS
|
|
(*IO_MGR_FLUSH_DATA)(
|
|
IN PSAC_CHANNEL Channel
|
|
);
|
|
|
|
//
|
|
// Global data
|
|
//
|
|
|
|
//
|
|
// Function pointers to the routines that implement the I/O Manager behavior
|
|
//
|
|
extern IO_MGR_HANDLE_EVENT IoMgrHandleEvent;
|
|
extern IO_MGR_INITITIALIZE IoMgrInitialize;
|
|
extern IO_MGR_SHUTDOWN IoMgrShutdown;
|
|
extern IO_MGR_WORKER IoMgrWorkerProcessEvents;
|
|
extern IO_MGR_IS_WRITE_ENABLED IoMgrIsWriteEnabled;
|
|
extern IO_MGR_WRITE_DATA IoMgrWriteData;
|
|
extern IO_MGR_FLUSH_DATA IoMgrFlushData;
|
|
|
|
extern PMACHINE_INFORMATION MachineInformation;
|
|
extern BOOLEAN GlobalDataInitialized;
|
|
extern BOOLEAN GlobalPagingNeeded;
|
|
extern BOOLEAN IoctlSubmitted;
|
|
extern LONG ProcessingType;
|
|
extern HANDLE SACEventHandle;
|
|
extern PKEVENT SACEvent;
|
|
|
|
//
|
|
// Enable the ability to check that the process/service that
|
|
// registered is the one that is unregistering
|
|
//
|
|
#define ENABLE_SERVICE_FILE_OBJECT_CHECKING 1
|
|
|
|
//
|
|
// Enable user-specified feature control for cmd sessions
|
|
//
|
|
#define ENABLE_CMD_SESSION_PERMISSION_CHECKING 1
|
|
|
|
//
|
|
// Enable the ability to override the service start type
|
|
// based on the cmd session permissions
|
|
//
|
|
// Note: ENABLE_CMD_SESSION_PERMISSION_CHECKING must be 1
|
|
// for this feature to work
|
|
//
|
|
#define ENABLE_SACSVR_START_TYPE_OVERRIDE 1
|
|
|
|
//
|
|
// Globals controlling if command console channels may be launched
|
|
//
|
|
#if ENABLE_CMD_SESSION_PERMISSION_CHECKING
|
|
|
|
extern BOOLEAN CommandConsoleLaunchingEnabled;
|
|
|
|
#define IsCommandConsoleLaunchingEnabled() (CommandConsoleLaunchingEnabled)
|
|
|
|
#endif
|
|
|
|
//
|
|
// The UTF8 encoding buffer
|
|
//
|
|
// Note: this buffer used during driver initialization,
|
|
// the Console Manager and VTUTF8 channels.
|
|
// It is safe to do this because the writes of these
|
|
// modules never overlap.
|
|
// The console manager uses the CURRENT CHANNEL LOCK
|
|
// to ensure that no two modules write out at the same
|
|
// time.
|
|
//
|
|
extern PUCHAR Utf8ConversionBuffer;
|
|
extern ULONG Utf8ConversionBufferSize;
|
|
|
|
//
|
|
// Define the max # of Unicode chars that can be translated with the
|
|
// given size of the utf8 translation buffer
|
|
//
|
|
#define MAX_UTF8_ENCODE_BLOCK_LENGTH ((Utf8ConversionBufferSize / 3) - 1)
|
|
|
|
//
|
|
// Globals for managing incremental UTF8 encoding for VTUTF8 channels
|
|
//
|
|
// Note: it is safe to use this as a global because only
|
|
// one channel ever has the focus. Hence, no two threads
|
|
// should ever be decoding UFT8 at the same time.
|
|
//
|
|
extern WCHAR IncomingUnicodeValue;
|
|
extern UCHAR IncomingUtf8ConversionBuffer[3];
|
|
|
|
//
|
|
// Command console event info:
|
|
//
|
|
// Pointers to the event handles for the Command Console event service
|
|
//
|
|
extern PVOID RequestSacCmdEventObjectBody;
|
|
extern PVOID RequestSacCmdEventWaitObjectBody;
|
|
extern PVOID RequestSacCmdSuccessEventObjectBody;
|
|
extern PVOID RequestSacCmdSuccessEventWaitObjectBody;
|
|
extern PVOID RequestSacCmdFailureEventObjectBody;
|
|
extern PVOID RequestSacCmdFailureEventWaitObjectBody;
|
|
extern BOOLEAN HaveUserModeServiceCmdEventInfo;
|
|
extern KMUTEX SACCmdEventInfoMutex;
|
|
#if ENABLE_SERVICE_FILE_OBJECT_CHECKING
|
|
extern PFILE_OBJECT ServiceProcessFileObject;
|
|
#endif
|
|
|
|
//
|
|
// Has the user-mode service registered?
|
|
//
|
|
#define UserModeServiceHasRegisteredCmdEvent() (HaveUserModeServiceCmdEventInfo)
|
|
|
|
//
|
|
// Serial Port Buffer globals
|
|
//
|
|
|
|
//
|
|
// Size of the serial port buffer
|
|
//
|
|
#define SERIAL_PORT_BUFFER_LENGTH 1024
|
|
#define SERIAL_PORT_BUFFER_SIZE (SERIAL_PORT_BUFFER_LENGTH * sizeof(UCHAR))
|
|
|
|
//
|
|
// Serial port buffer and producer/consumer indices
|
|
//
|
|
// Note: there can be only one consumer
|
|
//
|
|
extern PUCHAR SerialPortBuffer;
|
|
extern ULONG SerialPortProducerIndex;
|
|
extern ULONG SerialPortConsumerIndex;
|
|
|
|
//
|
|
// Memory management routines
|
|
//
|
|
#define ALLOCATE_POOL(b,t) MyAllocatePool( b, t, __FILE__, __LINE__ )
|
|
#define SAFE_FREE_POOL(_b) \
|
|
if (*_b) { \
|
|
FREE_POOL(_b); \
|
|
}
|
|
#define FREE_POOL(b) MyFreePool( b )
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
BOOLEAN
|
|
InitializeMemoryManagement(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FreeMemoryManagement(
|
|
VOID
|
|
);
|
|
|
|
PVOID
|
|
MyAllocatePool(
|
|
IN SIZE_T NumberOfBytes,
|
|
IN ULONG Tag,
|
|
IN PCHAR FileName,
|
|
IN ULONG LineNumber
|
|
);
|
|
|
|
VOID
|
|
MyFreePool(
|
|
IN PVOID Pointer
|
|
);
|
|
|
|
//
|
|
// Initialization routines.
|
|
//
|
|
BOOLEAN
|
|
InitializeGlobalData(
|
|
IN PUNICODE_STRING RegistryPath,
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
VOID
|
|
FreeGlobalData(
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
InitializeDeviceData(
|
|
PDEVICE_OBJECT DeviceObject
|
|
);
|
|
|
|
VOID
|
|
FreeDeviceData(
|
|
PDEVICE_OBJECT DeviceContext
|
|
);
|
|
|
|
VOID
|
|
InitializeCmdEventInfo(
|
|
VOID
|
|
);
|
|
|
|
//
|
|
// Dispatch routines
|
|
//
|
|
NTSTATUS
|
|
Dispatch(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
DispatchDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
DispatchShutdownControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
VOID
|
|
UnloadHandler(
|
|
IN PDRIVER_OBJECT DriverObject
|
|
);
|
|
|
|
NTSTATUS
|
|
DispatchSend(
|
|
IN PSAC_DEVICE_CONTEXT DeviceContext
|
|
);
|
|
|
|
VOID
|
|
DoDeferred(
|
|
IN PSAC_DEVICE_CONTEXT DeviceContext
|
|
);
|
|
|
|
//
|
|
// Worker thread routines.
|
|
//
|
|
|
|
VOID
|
|
TimerDpcRoutine(
|
|
IN struct _KDPC *Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SystemArgument1,
|
|
IN PVOID SystemArgument2
|
|
);
|
|
|
|
VOID
|
|
WorkerProcessEvents(
|
|
IN PSAC_DEVICE_CONTEXT DeviceContext
|
|
);
|
|
|
|
#include "util.h"
|
|
|
|
//
|
|
// Channel routines
|
|
//
|
|
|
|
#include "xmlmgr.h"
|
|
#include "conmgr.h"
|
|
#include "chanmgr.h"
|
|
#include "vtutf8chan.h"
|
|
#include "rawchan.h"
|
|
#include "cmdchan.h"
|
|
|
|
#endif // ndef _SACP_
|
|
|