mirror of https://github.com/tongzx/nt5src
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.
1604 lines
31 KiB
1604 lines
31 KiB
/*++
|
|
|
|
Copyright (c) 1992 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
blddcb.c
|
|
|
|
Abstract:
|
|
|
|
This module implements Win32 comm api buildcommdcb
|
|
|
|
Author:
|
|
|
|
Anthony V. Ercolano (tonye) 10-March-1992
|
|
|
|
Actually this code was generously donated by
|
|
ramonsa. It is basically the code used for
|
|
the mode command.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include <basedll.h>
|
|
|
|
typedef struct _PARSE_CONTEXT {
|
|
PSTR CharIndex;
|
|
PSTR AdvanceIndex;
|
|
PSTR MatchBegin;
|
|
PSTR MatchEnd;
|
|
} PARSE_CONTEXT,*PPARSE_CONTEXT;
|
|
|
|
static
|
|
BOOL
|
|
BuildDcb (
|
|
LPCSTR L,
|
|
LPDCB Dcb,
|
|
LPCOMMTIMEOUTS To
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
Match(
|
|
PPARSE_CONTEXT C,
|
|
PSTR Pattern
|
|
);
|
|
|
|
static
|
|
VOID
|
|
Advance(
|
|
PPARSE_CONTEXT C
|
|
);
|
|
|
|
static
|
|
DWORD
|
|
GetNumber(
|
|
PPARSE_CONTEXT C
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertBaudRate (
|
|
DWORD BaudIn,
|
|
PDWORD BaudRate
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertDataBits (
|
|
DWORD DataBitsIn,
|
|
PBYTE DataBitsOut
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertStopBits (
|
|
DWORD StopBitsIn,
|
|
PBYTE StopBits
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertParity (
|
|
CHAR ParityIn,
|
|
PBYTE Parity
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertDtrControl (
|
|
PSTR IdxBegin,
|
|
PSTR IdxEnd,
|
|
PBYTE DtrControl
|
|
);
|
|
|
|
static
|
|
BOOL
|
|
ConvertRtsControl (
|
|
PSTR IdxBegin,
|
|
PSTR IdxEnd,
|
|
PBYTE RtsControl
|
|
);
|
|
|
|
static
|
|
VOID
|
|
IgnoreDeviceName(
|
|
IN PPARSE_CONTEXT C
|
|
);
|
|
|
|
static
|
|
NTSTATUS
|
|
DeviceNameCompare(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
);
|
|
|
|
|
|
BOOL
|
|
BuildCommDCBAndTimeoutsW(
|
|
LPCWSTR lpDef,
|
|
LPDCB lpDCB,
|
|
LPCOMMTIMEOUTS lpCommTimeouts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the definition string specified by the
|
|
lpDef parameter into appropriate device-control block codes and
|
|
places these codes into the block pointed to by the lpDCB parameter.
|
|
It also sets the timeouts if specified.
|
|
|
|
Arguments:
|
|
|
|
lpDef - Points to a null terminated character string that specifies
|
|
the device control information for the device.
|
|
|
|
lpDCB - Points to the DCB data structure that is to receive the
|
|
translated string.. The structure defines the control
|
|
settings for the serial communications device.
|
|
|
|
lpCommTimeouts - It "TO" included, it will set the timeouts.
|
|
|
|
Return Value:
|
|
|
|
The return value is TRUE if the function is successful or FALSE
|
|
if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UNICODE_STRING Unicode;
|
|
ANSI_STRING Ansi;
|
|
NTSTATUS Status;
|
|
BOOL AnsiBool;
|
|
|
|
RtlInitUnicodeString(
|
|
&Unicode,
|
|
lpDef
|
|
);
|
|
|
|
Status = RtlUnicodeStringToAnsiString(
|
|
&Ansi,
|
|
&Unicode,
|
|
TRUE
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
BaseSetLastNTError(Status);
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
AnsiBool = BuildCommDCBAndTimeoutsA(
|
|
(LPCSTR)Ansi.Buffer,
|
|
lpDCB,
|
|
lpCommTimeouts
|
|
);
|
|
|
|
RtlFreeAnsiString(&Ansi);
|
|
return AnsiBool;
|
|
|
|
}
|
|
|
|
BOOL
|
|
BuildCommDCBAndTimeoutsA(
|
|
LPCSTR lpDef,
|
|
LPDCB lpDCB,
|
|
LPCOMMTIMEOUTS lpCommTimeouts
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the definition string specified by the
|
|
lpDef parameter into appropriate device-control block codes and
|
|
places these codes into the block pointed to by the lpDCB parameter.
|
|
It can also set the timeout value.
|
|
|
|
Arguments:
|
|
|
|
lpDef - Points to a null terminated character string that specifies
|
|
the device control information for the device.
|
|
|
|
lpDCB - Points to the DCB data structure that is to receive the
|
|
translated string.. The structure defines the control
|
|
settings for the serial communications device.
|
|
|
|
lpCommTimeouts - If TO included in string then timeouts are also set.
|
|
|
|
Return Value:
|
|
|
|
The return value is TRUE if the function is successful or FALSE
|
|
if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
if (!BuildDcb(
|
|
lpDef,
|
|
lpDCB,
|
|
lpCommTimeouts
|
|
)) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
BOOL
|
|
BuildCommDCBW(
|
|
LPCWSTR lpDef,
|
|
LPDCB lpDCB
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the definition string specified by the
|
|
lpDef parameter into appropriate device-control block codes and
|
|
places these codes into the block pointed to by the lpDCB parameter.
|
|
|
|
Arguments:
|
|
|
|
lpDef - Points to a null terminated character string that specifies
|
|
the device control information for the device.
|
|
|
|
lpDCB - Points to the DCB data structure that is to receive the
|
|
translated string.. The structure defines the control
|
|
settings for the serial communications device.
|
|
|
|
Return Value:
|
|
|
|
The return value is TRUE if the function is successful or FALSE
|
|
if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
UNICODE_STRING Unicode;
|
|
ANSI_STRING Ansi;
|
|
NTSTATUS Status;
|
|
BOOL AnsiBool;
|
|
|
|
RtlInitUnicodeString(
|
|
&Unicode,
|
|
lpDef
|
|
);
|
|
|
|
Status = RtlUnicodeStringToAnsiString(
|
|
&Ansi,
|
|
&Unicode,
|
|
TRUE
|
|
);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
BaseSetLastNTError(Status);
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
AnsiBool = BuildCommDCBA(
|
|
(LPCSTR)Ansi.Buffer,
|
|
lpDCB
|
|
);
|
|
|
|
RtlFreeAnsiString(&Ansi);
|
|
return AnsiBool;
|
|
|
|
}
|
|
|
|
BOOL
|
|
BuildCommDCBA(
|
|
LPCSTR lpDef,
|
|
LPDCB lpDCB
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function translates the definition string specified by the
|
|
lpDef parameter into appropriate device-control block codes and
|
|
places these codes into the block pointed to by the lpDCB parameter.
|
|
|
|
Arguments:
|
|
|
|
lpDef - Points to a null terminated character string that specifies
|
|
the device control information for the device.
|
|
|
|
lpDCB - Points to the DCB data structure that is to receive the
|
|
translated string.. The structure defines the control
|
|
settings for the serial communications device.
|
|
|
|
Return Value:
|
|
|
|
The return value is TRUE if the function is successful or FALSE
|
|
if an error occurs.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
COMMTIMEOUTS JunkTimeouts;
|
|
|
|
if (!BuildDcb(
|
|
lpDef,
|
|
lpDCB,
|
|
&JunkTimeouts
|
|
)) {
|
|
|
|
SetLastError(ERROR_INVALID_PARAMETER);
|
|
return FALSE;
|
|
|
|
} else {
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
BuildDcb (
|
|
LPCSTR L,
|
|
LPDCB Dcb,
|
|
LPCOMMTIMEOUTS To
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
L - A pointer to the string to convert to a DCB.
|
|
Dcb - The dcb to fill in.
|
|
|
|
Return Value:
|
|
|
|
FALSE if the string has some error, TRUE otherwise.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
BOOL SetBaud = FALSE;
|
|
BOOL SetDataBits = FALSE;
|
|
BOOL SetStopBits = FALSE;
|
|
BOOL SetParity = FALSE;
|
|
BOOL SetRetry = FALSE;
|
|
BOOL SetTimeOut = FALSE;
|
|
BOOL SetXon = FALSE;
|
|
BOOL SetOdsr = FALSE;
|
|
BOOL SetIdsr = FALSE;
|
|
BOOL SetOcts = FALSE;
|
|
BOOL SetDtrControl = FALSE;
|
|
BOOL SetRtsControl = FALSE;
|
|
|
|
DWORD Baud;
|
|
BYTE DataBits;
|
|
BYTE StopBits;
|
|
BYTE Parity;
|
|
BOOL TimeOut;
|
|
BOOL Xon;
|
|
BOOL Odsr;
|
|
BOOL Idsr;
|
|
BOOL Octs;
|
|
BYTE DtrControl;
|
|
BYTE RtsControl;
|
|
PARSE_CONTEXT C = {0};
|
|
|
|
C.CharIndex = C.AdvanceIndex = (PSTR)L;
|
|
|
|
//
|
|
// This following call will query all of the *current* serial
|
|
// provider names. If it finds that the argurment string
|
|
// contains the name (with an optional :) it will simply
|
|
// advance past it.
|
|
//
|
|
|
|
IgnoreDeviceName(&C);
|
|
|
|
if ( Match(&C, "#" ) ) {
|
|
|
|
//
|
|
// Old syntax, where parameter are positional and comma-delimited.
|
|
//
|
|
// We will use the following automata for parsing the input
|
|
// (eoi = end of input):
|
|
//
|
|
// eoi
|
|
// [Baud]------------->[End]
|
|
// | ^
|
|
// |, |eoi
|
|
// v |
|
|
// [a]-----------+
|
|
// | ^
|
|
// | @ |eoi
|
|
// +-->[Parity]-+
|
|
// | | ^
|
|
// | |, |
|
|
// |<----+ |
|
|
// | |
|
|
// |, |eoi
|
|
// | |
|
|
// v |
|
|
// [b]-----------+
|
|
// | ^
|
|
// | # |eoi
|
|
// +-->[Data]---+
|
|
// | | ^
|
|
// | |, |
|
|
// |<----+ |
|
|
// | |
|
|
// |, |eoi
|
|
// v |
|
|
// [c]-----------+
|
|
// | ^
|
|
// | # |eoi
|
|
// +-->[Stop]---+
|
|
//
|
|
|
|
//
|
|
// Assume xon=off
|
|
//
|
|
|
|
SetXon = TRUE;
|
|
SetOdsr = TRUE;
|
|
SetOcts = TRUE;
|
|
SetDtrControl = TRUE;
|
|
SetRtsControl = TRUE;
|
|
Xon = FALSE;
|
|
Odsr = FALSE;
|
|
Octs = FALSE;
|
|
DtrControl = DTR_CONTROL_ENABLE;
|
|
RtsControl = RTS_CONTROL_ENABLE;
|
|
|
|
if (!ConvertBaudRate( GetNumber(&C), &Baud )) {
|
|
return FALSE;
|
|
}
|
|
SetBaud = TRUE;
|
|
Advance(&C);
|
|
|
|
//
|
|
// A:
|
|
//
|
|
if ( !Match(&C, "," ) ) {
|
|
goto Eoi;
|
|
}
|
|
Advance(&C);
|
|
|
|
if ( !Match(&C, "," ) && Match(&C, "@" ) ) {
|
|
|
|
//
|
|
// Parity
|
|
//
|
|
if (!ConvertParity( *C.MatchBegin,&Parity )) {
|
|
return FALSE;
|
|
}
|
|
SetParity = TRUE;
|
|
Advance(&C);
|
|
}
|
|
|
|
//
|
|
// B:
|
|
//
|
|
if ( !Match(&C, "," )) {
|
|
goto Eoi;
|
|
}
|
|
Advance(&C);
|
|
|
|
if ( Match(&C, "#" )) {
|
|
|
|
//
|
|
// Data bits
|
|
//
|
|
if (!ConvertDataBits( GetNumber(&C),&DataBits )) {
|
|
return FALSE;
|
|
}
|
|
SetDataBits = TRUE;
|
|
Advance(&C);
|
|
}
|
|
|
|
//
|
|
// C:
|
|
//
|
|
if ( !Match(&C, "," )) {
|
|
goto Eoi;
|
|
}
|
|
Advance(&C);
|
|
|
|
if ( Match(&C, "1.5" ) ) {
|
|
StopBits = ONE5STOPBITS;
|
|
SetStopBits = TRUE;
|
|
Advance(&C);
|
|
} else if ( Match(&C, "#" ) ) {
|
|
if (!ConvertStopBits( GetNumber(&C),&StopBits)) {
|
|
return FALSE;
|
|
}
|
|
SetStopBits = TRUE;
|
|
Advance(&C);
|
|
}
|
|
|
|
if ( !Match(&C, "," )) {
|
|
goto Eoi;
|
|
}
|
|
|
|
Advance(&C);
|
|
|
|
if ( Match(&C, "x" ) ) {
|
|
|
|
//
|
|
// XON=ON
|
|
//
|
|
SetXon = TRUE;
|
|
SetOdsr = TRUE;
|
|
SetOcts = TRUE;
|
|
SetDtrControl = TRUE;
|
|
SetRtsControl = TRUE;
|
|
Xon = TRUE;
|
|
Odsr = FALSE;
|
|
Octs = FALSE;
|
|
DtrControl = DTR_CONTROL_ENABLE;
|
|
RtsControl = RTS_CONTROL_ENABLE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "p" ) ) {
|
|
|
|
//
|
|
// Permanent retry - Hardware handshaking
|
|
//
|
|
|
|
SetXon = TRUE;
|
|
SetOdsr = TRUE;
|
|
SetOcts = TRUE;
|
|
SetDtrControl = TRUE;
|
|
SetRtsControl = TRUE;
|
|
Xon = FALSE;
|
|
Odsr = TRUE;
|
|
Octs = TRUE;
|
|
DtrControl = DTR_CONTROL_HANDSHAKE;
|
|
RtsControl = RTS_CONTROL_HANDSHAKE;
|
|
Advance(&C);
|
|
|
|
} else {
|
|
|
|
//
|
|
// XON=OFF
|
|
//
|
|
SetXon = TRUE;
|
|
SetOdsr = TRUE;
|
|
SetOcts = TRUE;
|
|
SetDtrControl = TRUE;
|
|
SetRtsControl = TRUE;
|
|
Xon = FALSE;
|
|
Odsr = FALSE;
|
|
Octs = FALSE;
|
|
DtrControl = DTR_CONTROL_ENABLE;
|
|
RtsControl = RTS_CONTROL_ENABLE;
|
|
}
|
|
|
|
Eoi:
|
|
if ( *C.CharIndex != '\0' ) {
|
|
|
|
//
|
|
// Error
|
|
//
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// New Form
|
|
//
|
|
|
|
while ( *C.CharIndex != '\0' ) {
|
|
|
|
if ( Match(&C, "BAUD=#" ) ) {
|
|
//
|
|
// BAUD=
|
|
//
|
|
if ( !ConvertBaudRate(GetNumber(&C), &Baud ) ) {
|
|
return FALSE;
|
|
}
|
|
SetBaud = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "PARITY=@" ) ) {
|
|
//
|
|
// PARITY=
|
|
//
|
|
if ( !ConvertParity( *C.MatchBegin, &Parity ) ) {
|
|
return FALSE;
|
|
}
|
|
SetParity = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "DATA=#" ) ) {
|
|
//
|
|
// DATA=
|
|
//
|
|
if ( !ConvertDataBits(GetNumber(&C), &DataBits ) ) {
|
|
return FALSE;
|
|
}
|
|
SetDataBits = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "STOP=1.5" ) ) {
|
|
//
|
|
// STOP=1.5
|
|
//
|
|
StopBits = ONE5STOPBITS;
|
|
SetStopBits = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "STOP=#" ) ) {
|
|
//
|
|
// STOP=
|
|
//
|
|
if ( !ConvertStopBits(GetNumber(&C), &StopBits ) ) {
|
|
return FALSE;
|
|
}
|
|
SetStopBits = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "TO=ON" ) ) {
|
|
//
|
|
// TO=ON
|
|
//
|
|
SetTimeOut = TRUE;
|
|
TimeOut = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "TO=OFF" ) ) {
|
|
//
|
|
// TO=ON
|
|
//
|
|
SetTimeOut = TRUE;
|
|
TimeOut = FALSE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "XON=ON" ) ) {
|
|
//
|
|
// XON=ON
|
|
//
|
|
SetXon = TRUE;
|
|
Xon = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "XON=OFF" ) ) {
|
|
//
|
|
// XON=OFF
|
|
//
|
|
SetXon = TRUE;
|
|
Xon = FALSE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "ODSR=ON" ) ) {
|
|
//
|
|
// ODSR=ON
|
|
//
|
|
SetOdsr = TRUE;
|
|
Odsr = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "ODSR=OFF" ) ) {
|
|
//
|
|
// ODSR=OFF
|
|
//
|
|
SetOdsr = TRUE;
|
|
Odsr = FALSE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "IDSR=ON" ) ) {
|
|
//
|
|
// IDSR=ON
|
|
//
|
|
SetIdsr = TRUE;
|
|
Idsr = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "IDSR=OFF" ) ) {
|
|
//
|
|
// IDSR=OFF
|
|
//
|
|
SetIdsr = TRUE;
|
|
Idsr = FALSE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "OCTS=ON" ) ) {
|
|
//
|
|
// OCS=ON
|
|
//
|
|
SetOcts = TRUE;
|
|
Octs = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "OCTS=OFF" ) ) {
|
|
//
|
|
// OCS=OFF
|
|
//
|
|
SetOcts = TRUE;
|
|
Octs = FALSE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "DTR=*" ) ) {
|
|
//
|
|
// DTR=
|
|
//
|
|
if ( !ConvertDtrControl(C.MatchBegin, C.MatchEnd, &DtrControl ) ) {
|
|
return FALSE;
|
|
}
|
|
SetDtrControl = TRUE;
|
|
Advance(&C);
|
|
|
|
} else if ( Match(&C, "RTS=*" ) ) {
|
|
//
|
|
// RTS=
|
|
//
|
|
if ( !ConvertRtsControl(C.MatchBegin, C.MatchEnd, &RtsControl ) ) {
|
|
return FALSE;
|
|
}
|
|
SetRtsControl = TRUE;
|
|
Advance(&C);
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if ( SetBaud ) {
|
|
Dcb->BaudRate = Baud;
|
|
}
|
|
|
|
if ( SetDataBits ) {
|
|
Dcb->ByteSize = DataBits;
|
|
}
|
|
|
|
if ( SetStopBits ) {
|
|
Dcb->StopBits = StopBits;
|
|
} else if ( SetBaud && (Baud == 110) ) {
|
|
Dcb->StopBits = TWOSTOPBITS;
|
|
} else {
|
|
Dcb->StopBits = ONESTOPBIT;
|
|
}
|
|
|
|
if ( SetParity ) {
|
|
Dcb->Parity = Parity;
|
|
}
|
|
|
|
if ( SetXon ) {
|
|
if ( Xon ) {
|
|
Dcb->fInX = TRUE;
|
|
Dcb->fOutX = TRUE;
|
|
} else {
|
|
Dcb->fInX = FALSE;
|
|
Dcb->fOutX = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( SetOcts ) {
|
|
|
|
if ( Octs ) {
|
|
Dcb->fOutxCtsFlow = TRUE;
|
|
} else {
|
|
Dcb->fOutxCtsFlow = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if ( SetOdsr ) {
|
|
if ( Odsr ) {
|
|
Dcb->fOutxDsrFlow = TRUE;
|
|
} else {
|
|
Dcb->fOutxDsrFlow = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( SetIdsr ) {
|
|
if ( Idsr ) {
|
|
Dcb->fDsrSensitivity = TRUE;
|
|
} else {
|
|
Dcb->fDsrSensitivity = FALSE;
|
|
}
|
|
}
|
|
|
|
if ( SetDtrControl ) {
|
|
Dcb->fDtrControl = DtrControl;
|
|
}
|
|
|
|
if ( SetRtsControl ) {
|
|
Dcb->fRtsControl = RtsControl;
|
|
}
|
|
|
|
if ( SetTimeOut ) {
|
|
if (TimeOut) {
|
|
To->ReadIntervalTimeout = 0;
|
|
To->ReadTotalTimeoutMultiplier = 0;
|
|
To->ReadTotalTimeoutConstant = 0;
|
|
To->WriteTotalTimeoutMultiplier = 0;
|
|
To->WriteTotalTimeoutConstant = 60000;
|
|
} else {
|
|
To->ReadIntervalTimeout = 0;
|
|
To->ReadTotalTimeoutMultiplier = 0;
|
|
To->ReadTotalTimeoutConstant = 0;
|
|
To->WriteTotalTimeoutMultiplier = 0;
|
|
To->WriteTotalTimeoutConstant = 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
Match(
|
|
PPARSE_CONTEXT C,
|
|
PSTR Pattern
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function matches a pattern against whatever
|
|
is in the command line at the current position.
|
|
|
|
Note that this does not advance our current position
|
|
within the command line.
|
|
|
|
If the pattern has a magic character, then the
|
|
variables C->MatchBegin and C->MatchEnd delimit the
|
|
substring of the command line that matched that
|
|
magic character.
|
|
|
|
Arguments:
|
|
|
|
C - The parse context.
|
|
Pattern - Supplies pointer to the pattern to match
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN - TRUE if the pattern matched, FALSE otherwise
|
|
|
|
Notes:
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PSTR CmdIndex; // Index within command line
|
|
PSTR PatternIndex; // Index within pattern
|
|
CHAR PatternChar; // Character in pattern
|
|
CHAR CmdChar; // Character in command line;
|
|
|
|
CmdIndex = C->CharIndex;
|
|
PatternIndex = Pattern;
|
|
|
|
while ( (PatternChar = *PatternIndex) != '\0' ) {
|
|
|
|
switch ( PatternChar ) {
|
|
|
|
case '#':
|
|
|
|
//
|
|
// Match a number
|
|
//
|
|
C->MatchBegin = CmdIndex;
|
|
C->MatchEnd = C->MatchBegin;
|
|
|
|
//
|
|
// Get all consecutive digits
|
|
//
|
|
while ( ((CmdChar = *C->MatchEnd) != '\0') &&
|
|
isdigit( (char)CmdChar ) ) {
|
|
C->MatchEnd++;
|
|
}
|
|
C->MatchEnd--;
|
|
|
|
if ( C->MatchBegin > C->MatchEnd ) {
|
|
//
|
|
// No number
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
CmdIndex = C->MatchEnd + 1;
|
|
PatternIndex++;
|
|
|
|
break;
|
|
|
|
|
|
case '@':
|
|
|
|
//
|
|
// Match one character
|
|
//
|
|
if ( *CmdIndex == '\0' ) {
|
|
return FALSE;
|
|
}
|
|
|
|
C->MatchBegin = C->MatchEnd = CmdIndex;
|
|
CmdIndex++;
|
|
PatternIndex++;
|
|
|
|
break;
|
|
|
|
|
|
case '*':
|
|
|
|
//
|
|
// Match everything up to next blank (or end of input)
|
|
//
|
|
C->MatchBegin = CmdIndex;
|
|
C->MatchEnd = C->MatchBegin;
|
|
|
|
while ( ( (CmdChar = *C->MatchEnd ) != '\0' ) &&
|
|
( CmdChar != ' ' ) ) {
|
|
|
|
C->MatchEnd++;
|
|
}
|
|
C->MatchEnd--;
|
|
|
|
CmdIndex = C->MatchEnd+1;
|
|
PatternIndex++;
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
//
|
|
// Optional sequence
|
|
//
|
|
PatternIndex++;
|
|
|
|
PatternChar = *PatternIndex;
|
|
CmdChar = *CmdIndex;
|
|
|
|
//
|
|
// If the first charcter in the input does not match the
|
|
// first character in the optional sequence, we just
|
|
// skip the optional sequence.
|
|
//
|
|
if ( ( CmdChar == '\0' ) ||
|
|
( CmdChar == ' ') ||
|
|
( toupper(CmdChar) != toupper(PatternChar) ) ) {
|
|
|
|
while ( PatternChar != ']' ) {
|
|
PatternIndex++;
|
|
PatternChar = *PatternIndex;
|
|
}
|
|
PatternIndex++;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Since the first character in the sequence matched, now
|
|
// everything must match.
|
|
//
|
|
while ( PatternChar != ']' ) {
|
|
|
|
if ( toupper(PatternChar) != toupper(CmdChar) ) {
|
|
return FALSE;
|
|
}
|
|
CmdIndex++;
|
|
PatternIndex++;
|
|
CmdChar = *CmdIndex;
|
|
PatternChar = *PatternIndex;
|
|
}
|
|
|
|
PatternIndex++;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Both characters must match
|
|
//
|
|
CmdChar = *CmdIndex;
|
|
|
|
if ( ( CmdChar == '\0' ) ||
|
|
( toupper(CmdChar) != toupper(PatternChar) ) ) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
CmdIndex++;
|
|
PatternIndex++;
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
C->AdvanceIndex = CmdIndex;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static
|
|
VOID
|
|
Advance(
|
|
PPARSE_CONTEXT C
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Advances our pointers to the beginning of the next lexeme
|
|
|
|
Arguments:
|
|
|
|
C - The parse context.
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
C->CharIndex = C->AdvanceIndex;
|
|
|
|
//
|
|
// Skip blank space
|
|
//
|
|
if ( *C->CharIndex == ' ' ) {
|
|
|
|
while ( *C->CharIndex == ' ' ) {
|
|
|
|
C->CharIndex++;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
static
|
|
DWORD
|
|
GetNumber(
|
|
PPARSE_CONTEXT C
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts the substring delimited by C->MatchBegin and C->MatchEnd into
|
|
a number.
|
|
|
|
Arguments:
|
|
|
|
C - The parse context
|
|
|
|
Return Value:
|
|
|
|
ULONG - The matched string converted to a number
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD Number;
|
|
CHAR c;
|
|
PSTR p = C->MatchEnd+1;
|
|
|
|
c = *p;
|
|
// *p = '\0';
|
|
//intf( "Making number: %s\n", C->MatchBegin );
|
|
Number = atol( C->MatchBegin );
|
|
// *p = c;
|
|
|
|
return Number;
|
|
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertBaudRate (
|
|
DWORD BaudIn,
|
|
PDWORD BaudRate
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates a baud rate given as an argument to the program, and converts
|
|
it to something that the COMM_DEVICE understands.
|
|
|
|
Arguments:
|
|
|
|
BaudIn - Supplies the baud rate given by the user
|
|
BaudRate - if returning TRUE then the baud rate to use.
|
|
|
|
Return Value:
|
|
|
|
If a valid baud rate then returns TRUE, otherwise FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
switch ( BaudIn ) {
|
|
|
|
case 11:
|
|
case 110:
|
|
*BaudRate = 110;
|
|
break;
|
|
|
|
case 15:
|
|
case 150:
|
|
*BaudRate = 150;
|
|
break;
|
|
|
|
case 30:
|
|
case 300:
|
|
*BaudRate = 300;
|
|
break;
|
|
|
|
case 60:
|
|
case 600:
|
|
*BaudRate = 600;
|
|
break;
|
|
|
|
case 12:
|
|
case 1200:
|
|
*BaudRate = 1200;
|
|
break;
|
|
|
|
case 24:
|
|
case 2400:
|
|
*BaudRate = 2400;
|
|
break;
|
|
|
|
case 48:
|
|
case 4800:
|
|
*BaudRate = 4800;
|
|
break;
|
|
|
|
case 96:
|
|
case 9600:
|
|
*BaudRate = 9600;
|
|
break;
|
|
|
|
case 19:
|
|
case 19200:
|
|
*BaudRate = 19200;
|
|
break;
|
|
|
|
default:
|
|
|
|
*BaudRate = BaudIn;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertDataBits (
|
|
DWORD DataBitsIn,
|
|
PBYTE DataBitsOut
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates the number of data bits given as an argument to the program,
|
|
and converts it to something that the COMM_DEVICE understands.
|
|
|
|
Arguments:
|
|
|
|
DataBitsIn - Supplies the number given by the user
|
|
DataBitsOut - if returning TRUE, then the number of data bits.
|
|
|
|
Return Value:
|
|
|
|
If a valid data bits then TRUE, otherwise FALSE.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
if ( ( DataBitsIn != 5 ) &&
|
|
( DataBitsIn != 6 ) &&
|
|
( DataBitsIn != 7 ) &&
|
|
( DataBitsIn != 8 ) ) {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
*DataBitsOut = (BYTE)DataBitsIn;
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertStopBits (
|
|
DWORD StopBitsIn,
|
|
PBYTE StopBits
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates a number of stop bits given as an argument to the program,
|
|
and converts it to something that the COMM_DEVICE understands.
|
|
|
|
Arguments:
|
|
|
|
StopBitsIn - Supplies the number given by the user
|
|
StopBits - If returning true then a valid stop bits setting.
|
|
|
|
Return Value:
|
|
|
|
If a valid stop bits setting then TRUE, otherwise false.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
switch ( StopBitsIn ) {
|
|
|
|
case 1:
|
|
*StopBits = ONESTOPBIT;
|
|
break;
|
|
|
|
case 2:
|
|
*StopBits = TWOSTOPBITS;
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertParity (
|
|
CHAR ParityIn,
|
|
PBYTE Parity
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates a parity given as an argument to the program, and converts
|
|
it to something that the COMM_DEVICE understands.
|
|
|
|
Arguments:
|
|
|
|
ParityIn - Supplies the baud rate given by the user
|
|
Parity - The valid parity if return true.
|
|
|
|
Return Value:
|
|
|
|
If a valid parity setting then TRUE otherwise false.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
//
|
|
// Set the correct parity value depending on the character.
|
|
//
|
|
switch ( tolower(ParityIn) ) {
|
|
|
|
case 'n':
|
|
*Parity = NOPARITY;
|
|
break;
|
|
|
|
case 'o':
|
|
*Parity = ODDPARITY;
|
|
break;
|
|
|
|
case 'e':
|
|
*Parity = EVENPARITY;
|
|
break;
|
|
|
|
case 'm':
|
|
*Parity = MARKPARITY;
|
|
break;
|
|
|
|
case 's':
|
|
*Parity = SPACEPARITY;
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertDtrControl (
|
|
PSTR IdxBegin,
|
|
PSTR IdxEnd,
|
|
PBYTE DtrControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates a DTR control value given as an argument to the
|
|
program, and converts it to something that the COMM_DEVICE
|
|
understands.
|
|
|
|
Arguments:
|
|
|
|
IdxBegin - Supplies Index of first character
|
|
IdxEnd - Supplies Index of last character
|
|
DtrControl - If returning true, the valid dtr setting.
|
|
|
|
Return Value:
|
|
|
|
DTR_CONTROL - The DTR control value
|
|
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PSTR p;
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'o' ) &&
|
|
p++ &&
|
|
(tolower(*p) == 'n' ) &&
|
|
(IdxEnd == p)) {
|
|
|
|
|
|
*DtrControl = DTR_CONTROL_ENABLE;
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'o') &&
|
|
p++ &&
|
|
(tolower(*p) == 'f') &&
|
|
p++ &&
|
|
(tolower(*p) == 'f') &&
|
|
(IdxEnd == p ) ) {
|
|
|
|
*DtrControl = DTR_CONTROL_DISABLE;
|
|
return TRUE;
|
|
}
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'h') &&
|
|
p++ &&
|
|
(tolower(*p++) == 's') &&
|
|
(IdxEnd == p ) ) {
|
|
|
|
*DtrControl = DTR_CONTROL_HANDSHAKE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static
|
|
BOOL
|
|
ConvertRtsControl (
|
|
PSTR IdxBegin,
|
|
PSTR IdxEnd,
|
|
PBYTE RtsControl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates a RTS control value given as an argument to the
|
|
program, and converts it to something that the COMM_DEVICE
|
|
understands.
|
|
|
|
Arguments:
|
|
|
|
IdxBegin - Supplies Index of first character
|
|
IdxEnd - Supplies Index of last character
|
|
RtsControl - If returning true, the valid rts setting.
|
|
|
|
Return Value:
|
|
|
|
RTS_CONTROL - The RTS control value
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PSTR p;
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'o' ) &&
|
|
p++ &&
|
|
(tolower(*p) == 'n' ) &&
|
|
(IdxEnd == p)) {
|
|
|
|
|
|
*RtsControl = RTS_CONTROL_ENABLE;
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'o') &&
|
|
p++ &&
|
|
(tolower(*p) == 'f') &&
|
|
p++ &&
|
|
(tolower(*p) == 'f') &&
|
|
(IdxEnd == p ) ) {
|
|
|
|
*RtsControl = RTS_CONTROL_DISABLE;
|
|
return TRUE;
|
|
}
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 'h') &&
|
|
p++ &&
|
|
(tolower(*p++) == 's') &&
|
|
(IdxEnd == p ) ) {
|
|
|
|
*RtsControl = RTS_CONTROL_HANDSHAKE;
|
|
return TRUE;
|
|
}
|
|
|
|
p = IdxBegin;
|
|
if ( (tolower(*p) == 't') &&
|
|
p++ &&
|
|
(tolower(*p++) == 'g') &&
|
|
(IdxEnd == p ) ) {
|
|
|
|
*RtsControl = RTS_CONTROL_TOGGLE;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
static
|
|
NTSTATUS
|
|
DeviceNameCompare(
|
|
IN PWSTR ValueName,
|
|
IN ULONG ValueType,
|
|
IN PVOID ValueData,
|
|
IN ULONG ValueLength,
|
|
IN PVOID Context,
|
|
IN PVOID EntryContext
|
|
)
|
|
|
|
{
|
|
|
|
PPARSE_CONTEXT C = EntryContext;
|
|
UNICODE_STRING uniName;
|
|
ANSI_STRING ansiName;
|
|
|
|
RtlInitUnicodeString(
|
|
&uniName,
|
|
ValueData
|
|
);
|
|
|
|
if (!NT_SUCCESS(RtlUnicodeStringToAnsiString(
|
|
&ansiName,
|
|
&uniName,
|
|
TRUE
|
|
))) {
|
|
|
|
//
|
|
// Oh well, couldn't form the name. Just get out.
|
|
//
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
//
|
|
// See if we got a name match.
|
|
//
|
|
|
|
if (Match(C,ansiName.Buffer)) {
|
|
|
|
//
|
|
// Ok, got a name match, advance past it.
|
|
//
|
|
|
|
Advance(C);
|
|
|
|
//
|
|
// See if they've got the optional : following the
|
|
// device name.
|
|
//
|
|
|
|
if (Match(C,":")) {
|
|
|
|
//
|
|
// Go past it.
|
|
//
|
|
|
|
Advance(C);
|
|
|
|
}
|
|
|
|
}
|
|
RtlFreeAnsiString(&ansiName);
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
static
|
|
VOID
|
|
IgnoreDeviceName(
|
|
IN PPARSE_CONTEXT C
|
|
)
|
|
|
|
{
|
|
|
|
RTL_QUERY_REGISTRY_TABLE qTable[2] = {0};
|
|
|
|
//
|
|
// Build the query table.
|
|
//
|
|
|
|
qTable[0].QueryRoutine = DeviceNameCompare;
|
|
qTable[0].EntryContext = C;
|
|
|
|
RtlQueryRegistryValues(
|
|
RTL_REGISTRY_DEVICEMAP,
|
|
L"SERIALCOMM",
|
|
&qTable[0],
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
}
|