windows-nt/Source/XPSP1/NT/base/win32/client/blddcb.c
2020-09-26 16:20:57 +08:00

1605 lines
31 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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
);
}