mirror of https://github.com/lianthony/NT4.0
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.
546 lines
15 KiB
546 lines
15 KiB
|
|
|
|
|
|
#include "windef.h"
|
|
#include "mcx.h"
|
|
|
|
//
|
|
// DTR Control Flow Values.
|
|
//
|
|
#define DTR_CONTROL_DISABLE 0x00
|
|
#define DTR_CONTROL_ENABLE 0x01
|
|
#define DTR_CONTROL_HANDSHAKE 0x02
|
|
|
|
//
|
|
// RTS Control Flow Values
|
|
//
|
|
#define RTS_CONTROL_DISABLE 0x00
|
|
#define RTS_CONTROL_ENABLE 0x01
|
|
#define RTS_CONTROL_HANDSHAKE 0x02
|
|
#define RTS_CONTROL_TOGGLE 0x03
|
|
|
|
typedef struct _DCB {
|
|
DWORD DCBlength; /* sizeof(DCB) */
|
|
DWORD BaudRate; /* Baudrate at which running */
|
|
DWORD fBinary: 1; /* Binary Mode (skip EOF check) */
|
|
DWORD fParity: 1; /* Enable parity checking */
|
|
DWORD fOutxCtsFlow:1; /* CTS handshaking on output */
|
|
DWORD fOutxDsrFlow:1; /* DSR handshaking on output */
|
|
DWORD fDtrControl:2; /* DTR Flow control */
|
|
DWORD fDsrSensitivity:1; /* DSR Sensitivity */
|
|
DWORD fTXContinueOnXoff: 1; /* Continue TX when Xoff sent */
|
|
DWORD fOutX: 1; /* Enable output X-ON/X-OFF */
|
|
DWORD fInX: 1; /* Enable input X-ON/X-OFF */
|
|
DWORD fErrorChar: 1; /* Enable Err Replacement */
|
|
DWORD fNull: 1; /* Enable Null stripping */
|
|
DWORD fRtsControl:2; /* Rts Flow control */
|
|
DWORD fAbortOnError:1; /* Abort all reads and writes on Error */
|
|
DWORD fDummy2:17; /* Reserved */
|
|
WORD wReserved; /* Not currently used */
|
|
WORD XonLim; /* Transmit X-ON threshold */
|
|
WORD XoffLim; /* Transmit X-OFF threshold */
|
|
BYTE ByteSize; /* Number of bits/byte, 4-8 */
|
|
BYTE Parity; /* 0-4=None,Odd,Even,Mark,Space */
|
|
BYTE StopBits; /* 0,1,2 = 1, 1.5, 2 */
|
|
char XonChar; /* Tx and Rx X-ON character */
|
|
char XoffChar; /* Tx and Rx X-OFF character */
|
|
char ErrorChar; /* Error replacement char */
|
|
char EofChar; /* End of Input character */
|
|
char EvtChar; /* Received Event character */
|
|
WORD wReserved1; /* Fill for now. */
|
|
} DCB, *LPDCB;
|
|
|
|
typedef struct _COMMCONFIG {
|
|
DWORD dwSize; /* Size of the entire struct */
|
|
WORD wVersion; /* version of the structure */
|
|
WORD wReserved; /* alignment */
|
|
DCB dcb; /* device control block */
|
|
DWORD dwProviderSubType; /* ordinal value for identifying
|
|
provider-defined data structure format*/
|
|
DWORD dwProviderOffset; /* Specifies the offset of provider specific
|
|
data field in bytes from the start */
|
|
DWORD dwProviderSize; /* size of the provider-specific data field */
|
|
WCHAR wcProviderData[1]; /* provider-specific data */
|
|
} COMMCONFIG,*LPCOMMCONFIG;
|
|
|
|
typedef struct _MODEM_REG_PROP {
|
|
DWORD dwDialOptions; // bitmap of supported options
|
|
DWORD dwCallSetupFailTimer; // Maximum value in seconds
|
|
DWORD dwInactivityTimeout; // Maximum value in units specific by InactivityScale
|
|
DWORD dwSpeakerVolume; // bitmap of supported values
|
|
DWORD dwSpeakerMode; // bitmap of supported values
|
|
DWORD dwModemOptions; // bitmap of supported values
|
|
DWORD dwMaxDTERate; // Maximum value in bit/s
|
|
DWORD dwMaxDCERate; // Maximum value in bit/s
|
|
} MODEM_REG_PROP;
|
|
|
|
typedef struct _MODEM_REG_DEFAULT {
|
|
DWORD dwCallSetupFailTimer; // seconds
|
|
DWORD dwInactivityTimeout; // units specific by InactivityScale
|
|
DWORD dwSpeakerVolume; // level
|
|
DWORD dwSpeakerMode; // mode
|
|
DWORD dwPreferredModemOptions; // bitmap
|
|
} MODEM_REG_DEFAULT;
|
|
|
|
#ifdef POOL_TAGGING
|
|
#undef ExAllocatePool
|
|
#undef ExAllocatePoolWithQuota
|
|
#define ExAllocatePool(a,b) ExAllocatePoolWithTag(a,b,'MDMU')
|
|
#define ExAllocatePoolWithQuota(a,b) ExAllocatePoolWithQuotaTag(a,b,'MDMU')
|
|
#endif
|
|
|
|
|
|
#if DBG
|
|
#define UNIDIAG1 ((ULONG)0x00000001)
|
|
#define UNIDIAG2 ((ULONG)0x00000002)
|
|
#define UNIDIAG3 ((ULONG)0x00000004)
|
|
#define UNIDIAG4 ((ULONG)0x00000008)
|
|
#define UNIDIAG5 ((ULONG)0x00000010)
|
|
#define UNIERRORS ((ULONG)0x00000020)
|
|
#define UNIBUGCHECK ((ULONG)0x80000000)
|
|
extern ULONG UniDebugLevel;
|
|
#define UniDump(LEVEL,STRING) \
|
|
do { \
|
|
ULONG _level = (LEVEL); \
|
|
if (UniDebugLevel & _level) { \
|
|
DbgPrint STRING; \
|
|
} \
|
|
if (_level == UNIBUGCHECK) { \
|
|
ASSERT(FALSE); \
|
|
} \
|
|
} while (0)
|
|
#else
|
|
#define UniDump(LEVEL,STRING) do {NOTHING;} while (0)
|
|
#endif
|
|
|
|
#define OBJECT_DIRECTORY L"\\DosDevices\\"
|
|
|
|
typedef struct _CONFIG_DATA {
|
|
|
|
LIST_ENTRY ConfigList;
|
|
UNICODE_STRING NtNameForPort;
|
|
UNICODE_STRING FriendlyName;
|
|
ULONG DeviceInstance;
|
|
|
|
} CONFIG_DATA,*PCONFIG_DATA;
|
|
|
|
|
|
//
|
|
// Values define the reference bits kept in the irps.
|
|
//
|
|
|
|
#define UNI_REFERENCE_NORMAL_PATH 0x00000001
|
|
#define UNI_REFERENCE_CANCEL_PATH 0x00000002
|
|
|
|
#define CLIENT_HANDLE 0
|
|
#define CONTROL_HANDLE 1
|
|
|
|
struct _DEVICE_EXTENSION;
|
|
|
|
typedef struct _MASKSTATE {
|
|
|
|
//
|
|
// Helpful when this is passed as context to a completion routine.
|
|
//
|
|
struct _DEVICE_EXTENSION *Extension;
|
|
|
|
//
|
|
// Pointer to the complementry mask state.
|
|
//
|
|
struct _MASKSTATE *OtherState;
|
|
|
|
//
|
|
// Counts the number of setmasks for the current client or
|
|
// control wait.
|
|
//
|
|
ULONG SetMaskCount;
|
|
|
|
//
|
|
// This counts the number of setmask that have actually been
|
|
// passed down to a lower level serial driver. This helps
|
|
// us on not starting waits that will die soon enough.
|
|
//
|
|
ULONG SentDownSetMasks;
|
|
|
|
//
|
|
// Holds the value of the last successful setmask for the client
|
|
// or the control.
|
|
//
|
|
ULONG Mask;
|
|
|
|
//
|
|
// Holds the value of the above mask with whatever was last seen
|
|
// by a successful wait from any handle.
|
|
//
|
|
ULONG HistoryMask;
|
|
|
|
//
|
|
// Points to the wait operation shuttled aside for the client
|
|
// or control.
|
|
//
|
|
PIRP ShuttledWait;
|
|
|
|
//
|
|
// Points to the wait operation sent down to a lower level serial
|
|
// driver
|
|
//
|
|
PIRP PassedDownWait;
|
|
|
|
//
|
|
// Used to denote that a passed down wait should be completed because
|
|
// of a subsequent setmask operation.
|
|
//
|
|
BOOLEAN CompletePassedDownWait;
|
|
|
|
} MASKSTATE,*PMASKSTATE;
|
|
|
|
//
|
|
// Scads of little macros to manipulate our stack location.
|
|
//
|
|
|
|
#define UNI_INIT_REFERENCE(Irp) { \
|
|
ASSERT(sizeof(LONG) <= sizeof(PVOID)); \
|
|
IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4 = NULL; \
|
|
}
|
|
|
|
#define UNI_SET_REFERENCE(Irp,RefType) \
|
|
do { \
|
|
LONG _refType = (RefType); \
|
|
PLONG _arg4 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4; \
|
|
ASSERT(!(*_arg4 & _refType)); \
|
|
*_arg4 |= _refType; \
|
|
} while (0)
|
|
|
|
#define UNI_CLEAR_REFERENCE(Irp,RefType) \
|
|
do { \
|
|
LONG _refType = (RefType); \
|
|
PLONG _arg4 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4; \
|
|
ASSERT(*_arg4 & _refType); \
|
|
*_arg4 &= ~_refType; \
|
|
} while (0)
|
|
|
|
#define UNI_REFERENCE_COUNT(Irp) \
|
|
((LONG)((IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument4)))
|
|
|
|
#define UNI_SAVE_STATE_IN_IRP(Irp,MaskState) \
|
|
do { \
|
|
PMASKSTATE _maskState = (MaskState); \
|
|
PMASKSTATE *_arg3 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument3; \
|
|
*_arg3 = _maskState; \
|
|
} while (0)
|
|
|
|
#define UNI_CLEAR_STATE_IN_IRP(Irp) \
|
|
do { \
|
|
PMASKSTATE *_arg3 = (PVOID)&IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument3; \
|
|
ASSERT(*_arg3); \
|
|
*((PULONG)_arg3) = IOCTL_SERIAL_WAIT_ON_MASK; \
|
|
} while (0)
|
|
|
|
#define UNI_SAVE_OLD_SETMASK(Irp) \
|
|
do { \
|
|
PIRP _irp = (Irp); \
|
|
PULONG _arg3 = (PVOID)&IoGetCurrentIrpStackLocation(_irp)->Parameters.Others.Argument3; \
|
|
ASSERT(*_arg3 == IOCTL_SERIAL_SET_WAIT_MASK); \
|
|
*_arg3 = *((PULONG)_irp->AssociatedIrp.SystemBuffer); \
|
|
} while (0)
|
|
|
|
#define UNI_RESTORE_OLD_SETMASK(Irp) \
|
|
do { \
|
|
PIRP _irp = (Irp); \
|
|
PULONG _arg3 = (PVOID)&IoGetCurrentIrpStackLocation(_irp)->Parameters.Others.Argument3; \
|
|
*((PULONG)_irp->AssociatedIrp.SystemBuffer) = *_arg3; \
|
|
*_arg3 = IOCTL_SERIAL_WAIT_ON_MASK; \
|
|
} while (0)
|
|
|
|
|
|
#define UNI_GET_STATE_IN_IRP(Irp) \
|
|
((PMASKSTATE)((IoGetCurrentIrpStackLocation((Irp))->Parameters.Others.Argument3)))
|
|
|
|
#define UNI_ORIG_SYSTEM_BUFFER(Irp) \
|
|
((PVOID)((IoGetCurrentIrpStackLocation((Irp)))->Parameters.DeviceIoControl.IoControlCode))
|
|
|
|
#define UNI_RESTORE_IRP(Irp,Code) \
|
|
do { \
|
|
PIRP _irp = (Irp); \
|
|
ULONG _ccode = (Code); \
|
|
_irp->AssociatedIrp.SystemBuffer = \
|
|
(PVOID)(IoGetCurrentIrpStackLocation(_irp)->Parameters.DeviceIoControl.IoControlCode); \
|
|
IoGetCurrentIrpStackLocation(_irp)->Parameters.DeviceIoControl.IoControlCode = _ccode; \
|
|
} while (0)
|
|
|
|
#define UNI_SETUP_NEW_BUFFER(Irp) \
|
|
do { \
|
|
PIRP _irp = (Irp); \
|
|
PIO_STACK_LOCATION _irpSp = IoGetCurrentIrpStackLocation(_irp); \
|
|
*((PVOID *)(&_irpSp->Parameters.DeviceIoControl.IoControlCode)) = \
|
|
_irp->AssociatedIrp.SystemBuffer; \
|
|
_irp->AssociatedIrp.SystemBuffer = \
|
|
&_irpSp->Parameters.DeviceIoControl.Type3InputBuffer; \
|
|
} while (0)
|
|
|
|
typedef struct _DEVICE_EXTENSION {
|
|
|
|
//
|
|
// Points back to the device object that was created in
|
|
// conjunction with this device extension
|
|
//
|
|
PDEVICE_OBJECT DeviceObject;
|
|
|
|
//
|
|
// This string is generally the modem name, it might look
|
|
// like "Hayes Optimia 144". It was allocated at device object
|
|
// creation time and needs to be deleted before the device unloads.
|
|
//
|
|
UNICODE_STRING FullLinkName;
|
|
|
|
//
|
|
// The queue of device open close requests. It is synchronized
|
|
// using the DeviceLock spinlock.
|
|
//
|
|
LIST_ENTRY OpenClose;
|
|
PIRP CurrentOpenClose;
|
|
|
|
//
|
|
// The queue of passthrough state requests. It is synchronized
|
|
// using the DeviceLock spinlock.
|
|
//
|
|
LIST_ENTRY PassThroughQueue;
|
|
PIRP CurrentPassThrough;
|
|
|
|
//
|
|
// Keeps a count (synchronized by the DeviceLock) of the number
|
|
// of times the modem has been opened (and closed).
|
|
//
|
|
ULONG OpenCount;
|
|
|
|
//
|
|
// The address of the process that first opened us. The sharing
|
|
// semantics of the modem device are such that ONLY the first
|
|
// process that opened us can open us again. Dispense with all
|
|
// other access checks.
|
|
//
|
|
PEPROCESS ProcAddress;
|
|
|
|
//
|
|
// These to items were returned from the acquiring of the device
|
|
// object pointer to the lower level serial device.
|
|
//
|
|
PFILE_OBJECT AttachedFileObject;
|
|
PDEVICE_OBJECT AttachedDeviceObject;
|
|
|
|
//
|
|
// The general synchronization primative used by the modem driver.
|
|
//
|
|
KSPIN_LOCK DeviceLock;
|
|
|
|
//
|
|
// The state that the particular modem device is in. For definitions
|
|
// of the value, see the public header ntddmodm.h
|
|
//
|
|
ULONG PassThrough;
|
|
|
|
//
|
|
// The queue of mask operations. It is synchronized using the
|
|
// DeviceLock spinlock.
|
|
//
|
|
LIST_ENTRY MaskOps;
|
|
PIRP CurrentMaskOp;
|
|
|
|
//
|
|
// This points to an irp that we allocate at port open time.
|
|
// The irp will be used to look for dcd changes when a sniff
|
|
// request is given.
|
|
//
|
|
PIRP OurWaitIrp;
|
|
|
|
//
|
|
//
|
|
// Holds the states for both the client and the controlling handle.
|
|
//
|
|
MASKSTATE MaskStates[2];
|
|
|
|
//
|
|
// Holds the device instance (which is good for this boot
|
|
// only) that was used to create this device.
|
|
//
|
|
ULONG DeviceInstance;
|
|
MODEMDEVCAPS ModemDevCaps;
|
|
MODEMSETTINGS ModemSettings;
|
|
ULONG InactivityScale;
|
|
} DEVICE_EXTENSION,*PDEVICE_EXTENSION;
|
|
|
|
//
|
|
// Holds the service key name of the driver (i.e. CCS\Services\ServiceKeyName)
|
|
// The service key name is used to call IoQueryDeviceEnumInfo and
|
|
// IoOpenDeviceInstanceKey APIs. It is for SUR only.
|
|
//
|
|
|
|
extern UNICODE_STRING UniServiceKeyName;
|
|
|
|
NTSTATUS
|
|
UniOpen(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
VOID
|
|
UniLogError(
|
|
IN PDRIVER_OBJECT DriverObject,
|
|
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
|
IN ULONG SequenceNumber,
|
|
IN UCHAR MajorFunctionCode,
|
|
IN UCHAR RetryCount,
|
|
IN ULONG UniqueErrorValue,
|
|
IN NTSTATUS FinalStatus,
|
|
IN NTSTATUS SpecificIOStatus,
|
|
IN ULONG LengthOfInsert1,
|
|
IN PWCHAR Insert1,
|
|
IN ULONG LengthOfInsert2,
|
|
IN PWCHAR Insert2
|
|
);
|
|
|
|
NTSTATUS
|
|
UniIoControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniReadWrite(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniQueryInformationFile(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniSetInformationFile(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniSniffOwnerSettings(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniCheckPassThrough(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniNoCheckPassThrough(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
typedef
|
|
NTSTATUS
|
|
(*PUNI_START_ROUTINE) (
|
|
IN PDEVICE_EXTENSION Extension
|
|
);
|
|
|
|
typedef
|
|
VOID
|
|
(*PUNI_GET_NEXT_ROUTINE) (
|
|
IN PIRP *CurrentOpIrp,
|
|
IN PLIST_ENTRY QueueToProcess,
|
|
OUT PIRP *NewIrp,
|
|
IN BOOLEAN CompleteCurrent
|
|
);
|
|
|
|
NTSTATUS
|
|
UniStartOrQueue(
|
|
IN PDEVICE_EXTENSION Extension,
|
|
IN PKSPIN_LOCK QueueLock,
|
|
IN PIRP Irp,
|
|
IN PLIST_ENTRY QueueToExamine,
|
|
IN PIRP *CurrentOpIrp,
|
|
IN PUNI_START_ROUTINE Starter
|
|
);
|
|
|
|
VOID
|
|
UniGetNextIrp(
|
|
IN PKSPIN_LOCK QueueLock,
|
|
IN PIRP *CurrentOpIrp,
|
|
IN PLIST_ENTRY QueueToProcess,
|
|
OUT PIRP *NextIrp,
|
|
IN BOOLEAN CompleteCurrent
|
|
);
|
|
|
|
NTSTATUS
|
|
UniMaskStarter(
|
|
IN PDEVICE_EXTENSION Extension
|
|
);
|
|
|
|
NTSTATUS
|
|
UniGeneralMaskComplete(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
UniRundownShuttledWait(
|
|
IN PDEVICE_EXTENSION Extension,
|
|
IN PIRP *ShuttlePointer,
|
|
IN ULONG ReferenceMask,
|
|
IN PIRP IrpToRunDown,
|
|
IN KIRQL DeviceLockIrql,
|
|
IN NTSTATUS StatusToComplete,
|
|
IN ULONG MaskCompleteValue
|
|
);
|
|
|
|
VOID
|
|
UniCancelShuttledWait(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniGeneralWaitComplete(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp,
|
|
IN PVOID Context
|
|
);
|
|
|
|
VOID
|
|
UniChangeShuttledToPassDown(
|
|
IN PMASKSTATE ChangingState,
|
|
IN KIRQL OrigIrql
|
|
);
|
|
|
|
NTSTATUS
|
|
UniMakeIrpShuttledWait(
|
|
IN PMASKSTATE MaskState,
|
|
IN PIRP Irp,
|
|
IN KIRQL OrigIrql,
|
|
IN BOOLEAN GetNextIrpInQueue,
|
|
OUT PIRP *NewIrp
|
|
);
|
|
|
|
NTSTATUS
|
|
UniValidateNewCommConfig(
|
|
IN PDEVICE_EXTENSION Extension,
|
|
IN PIRP Irp,
|
|
IN BOOLEAN Owner
|
|
);
|
|
|
|
NTSTATUS
|
|
UniCleanup(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp
|
|
);
|