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