Source code of Windows XP (NT5)
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

  1. /*++
  2. Copyright (c) 1992 Microsoft Corporation
  3. Module Name:
  4. blddcb.c
  5. Abstract:
  6. This module implements Win32 comm api buildcommdcb
  7. Author:
  8. Anthony V. Ercolano (tonye) 10-March-1992
  9. Actually this code was generously donated by
  10. ramonsa. It is basically the code used for
  11. the mode command.
  12. Revision History:
  13. --*/
  14. #include <basedll.h>
  15. typedef struct _PARSE_CONTEXT {
  16. PSTR CharIndex;
  17. PSTR AdvanceIndex;
  18. PSTR MatchBegin;
  19. PSTR MatchEnd;
  20. } PARSE_CONTEXT,*PPARSE_CONTEXT;
  21. static
  22. BOOL
  23. BuildDcb (
  24. LPCSTR L,
  25. LPDCB Dcb,
  26. LPCOMMTIMEOUTS To
  27. );
  28. static
  29. BOOL
  30. Match(
  31. PPARSE_CONTEXT C,
  32. PSTR Pattern
  33. );
  34. static
  35. VOID
  36. Advance(
  37. PPARSE_CONTEXT C
  38. );
  39. static
  40. DWORD
  41. GetNumber(
  42. PPARSE_CONTEXT C
  43. );
  44. static
  45. BOOL
  46. ConvertBaudRate (
  47. DWORD BaudIn,
  48. PDWORD BaudRate
  49. );
  50. static
  51. BOOL
  52. ConvertDataBits (
  53. DWORD DataBitsIn,
  54. PBYTE DataBitsOut
  55. );
  56. static
  57. BOOL
  58. ConvertStopBits (
  59. DWORD StopBitsIn,
  60. PBYTE StopBits
  61. );
  62. static
  63. BOOL
  64. ConvertParity (
  65. CHAR ParityIn,
  66. PBYTE Parity
  67. );
  68. static
  69. BOOL
  70. ConvertDtrControl (
  71. PSTR IdxBegin,
  72. PSTR IdxEnd,
  73. PBYTE DtrControl
  74. );
  75. static
  76. BOOL
  77. ConvertRtsControl (
  78. PSTR IdxBegin,
  79. PSTR IdxEnd,
  80. PBYTE RtsControl
  81. );
  82. static
  83. VOID
  84. IgnoreDeviceName(
  85. IN PPARSE_CONTEXT C
  86. );
  87. static
  88. NTSTATUS
  89. DeviceNameCompare(
  90. IN PWSTR ValueName,
  91. IN ULONG ValueType,
  92. IN PVOID ValueData,
  93. IN ULONG ValueLength,
  94. IN PVOID Context,
  95. IN PVOID EntryContext
  96. );
  97. BOOL
  98. BuildCommDCBAndTimeoutsW(
  99. LPCWSTR lpDef,
  100. LPDCB lpDCB,
  101. LPCOMMTIMEOUTS lpCommTimeouts
  102. )
  103. /*++
  104. Routine Description:
  105. This function translates the definition string specified by the
  106. lpDef parameter into appropriate device-control block codes and
  107. places these codes into the block pointed to by the lpDCB parameter.
  108. It also sets the timeouts if specified.
  109. Arguments:
  110. lpDef - Points to a null terminated character string that specifies
  111. the device control information for the device.
  112. lpDCB - Points to the DCB data structure that is to receive the
  113. translated string.. The structure defines the control
  114. settings for the serial communications device.
  115. lpCommTimeouts - It "TO" included, it will set the timeouts.
  116. Return Value:
  117. The return value is TRUE if the function is successful or FALSE
  118. if an error occurs.
  119. --*/
  120. {
  121. UNICODE_STRING Unicode;
  122. ANSI_STRING Ansi;
  123. NTSTATUS Status;
  124. BOOL AnsiBool;
  125. RtlInitUnicodeString(
  126. &Unicode,
  127. lpDef
  128. );
  129. Status = RtlUnicodeStringToAnsiString(
  130. &Ansi,
  131. &Unicode,
  132. TRUE
  133. );
  134. if (!NT_SUCCESS(Status)) {
  135. BaseSetLastNTError(Status);
  136. return FALSE;
  137. }
  138. AnsiBool = BuildCommDCBAndTimeoutsA(
  139. (LPCSTR)Ansi.Buffer,
  140. lpDCB,
  141. lpCommTimeouts
  142. );
  143. RtlFreeAnsiString(&Ansi);
  144. return AnsiBool;
  145. }
  146. BOOL
  147. BuildCommDCBAndTimeoutsA(
  148. LPCSTR lpDef,
  149. LPDCB lpDCB,
  150. LPCOMMTIMEOUTS lpCommTimeouts
  151. )
  152. /*++
  153. Routine Description:
  154. This function translates the definition string specified by the
  155. lpDef parameter into appropriate device-control block codes and
  156. places these codes into the block pointed to by the lpDCB parameter.
  157. It can also set the timeout value.
  158. Arguments:
  159. lpDef - Points to a null terminated character string that specifies
  160. the device control information for the device.
  161. lpDCB - Points to the DCB data structure that is to receive the
  162. translated string.. The structure defines the control
  163. settings for the serial communications device.
  164. lpCommTimeouts - If TO included in string then timeouts are also set.
  165. Return Value:
  166. The return value is TRUE if the function is successful or FALSE
  167. if an error occurs.
  168. --*/
  169. {
  170. if (!BuildDcb(
  171. lpDef,
  172. lpDCB,
  173. lpCommTimeouts
  174. )) {
  175. SetLastError(ERROR_INVALID_PARAMETER);
  176. return FALSE;
  177. } else {
  178. return TRUE;
  179. }
  180. }
  181. BOOL
  182. BuildCommDCBW(
  183. LPCWSTR lpDef,
  184. LPDCB lpDCB
  185. )
  186. /*++
  187. Routine Description:
  188. This function translates the definition string specified by the
  189. lpDef parameter into appropriate device-control block codes and
  190. places these codes into the block pointed to by the lpDCB parameter.
  191. Arguments:
  192. lpDef - Points to a null terminated character string that specifies
  193. the device control information for the device.
  194. lpDCB - Points to the DCB data structure that is to receive the
  195. translated string.. The structure defines the control
  196. settings for the serial communications device.
  197. Return Value:
  198. The return value is TRUE if the function is successful or FALSE
  199. if an error occurs.
  200. --*/
  201. {
  202. UNICODE_STRING Unicode;
  203. ANSI_STRING Ansi;
  204. NTSTATUS Status;
  205. BOOL AnsiBool;
  206. RtlInitUnicodeString(
  207. &Unicode,
  208. lpDef
  209. );
  210. Status = RtlUnicodeStringToAnsiString(
  211. &Ansi,
  212. &Unicode,
  213. TRUE
  214. );
  215. if (!NT_SUCCESS(Status)) {
  216. BaseSetLastNTError(Status);
  217. return FALSE;
  218. }
  219. AnsiBool = BuildCommDCBA(
  220. (LPCSTR)Ansi.Buffer,
  221. lpDCB
  222. );
  223. RtlFreeAnsiString(&Ansi);
  224. return AnsiBool;
  225. }
  226. BOOL
  227. BuildCommDCBA(
  228. LPCSTR lpDef,
  229. LPDCB lpDCB
  230. )
  231. /*++
  232. Routine Description:
  233. This function translates the definition string specified by the
  234. lpDef parameter into appropriate device-control block codes and
  235. places these codes into the block pointed to by the lpDCB parameter.
  236. Arguments:
  237. lpDef - Points to a null terminated character string that specifies
  238. the device control information for the device.
  239. lpDCB - Points to the DCB data structure that is to receive the
  240. translated string.. The structure defines the control
  241. settings for the serial communications device.
  242. Return Value:
  243. The return value is TRUE if the function is successful or FALSE
  244. if an error occurs.
  245. --*/
  246. {
  247. COMMTIMEOUTS JunkTimeouts;
  248. if (!BuildDcb(
  249. lpDef,
  250. lpDCB,
  251. &JunkTimeouts
  252. )) {
  253. SetLastError(ERROR_INVALID_PARAMETER);
  254. return FALSE;
  255. } else {
  256. return TRUE;
  257. }
  258. }
  259. static
  260. BOOL
  261. BuildDcb (
  262. LPCSTR L,
  263. LPDCB Dcb,
  264. LPCOMMTIMEOUTS To
  265. )
  266. /*++
  267. Routine Description:
  268. Arguments:
  269. L - A pointer to the string to convert to a DCB.
  270. Dcb - The dcb to fill in.
  271. Return Value:
  272. FALSE if the string has some error, TRUE otherwise.
  273. --*/
  274. {
  275. BOOL SetBaud = FALSE;
  276. BOOL SetDataBits = FALSE;
  277. BOOL SetStopBits = FALSE;
  278. BOOL SetParity = FALSE;
  279. BOOL SetRetry = FALSE;
  280. BOOL SetTimeOut = FALSE;
  281. BOOL SetXon = FALSE;
  282. BOOL SetOdsr = FALSE;
  283. BOOL SetIdsr = FALSE;
  284. BOOL SetOcts = FALSE;
  285. BOOL SetDtrControl = FALSE;
  286. BOOL SetRtsControl = FALSE;
  287. DWORD Baud;
  288. BYTE DataBits;
  289. BYTE StopBits;
  290. BYTE Parity;
  291. BOOL TimeOut;
  292. BOOL Xon;
  293. BOOL Odsr;
  294. BOOL Idsr;
  295. BOOL Octs;
  296. BYTE DtrControl;
  297. BYTE RtsControl;
  298. PARSE_CONTEXT C = {0};
  299. C.CharIndex = C.AdvanceIndex = (PSTR)L;
  300. //
  301. // This following call will query all of the *current* serial
  302. // provider names. If it finds that the argurment string
  303. // contains the name (with an optional :) it will simply
  304. // advance past it.
  305. //
  306. IgnoreDeviceName(&C);
  307. if ( Match(&C, "#" ) ) {
  308. //
  309. // Old syntax, where parameter are positional and comma-delimited.
  310. //
  311. // We will use the following automata for parsing the input
  312. // (eoi = end of input):
  313. //
  314. // eoi
  315. // [Baud]------------->[End]
  316. // | ^
  317. // |, |eoi
  318. // v |
  319. // [a]-----------+
  320. // | ^
  321. // | @ |eoi
  322. // +-->[Parity]-+
  323. // | | ^
  324. // | |, |
  325. // |<----+ |
  326. // | |
  327. // |, |eoi
  328. // | |
  329. // v |
  330. // [b]-----------+
  331. // | ^
  332. // | # |eoi
  333. // +-->[Data]---+
  334. // | | ^
  335. // | |, |
  336. // |<----+ |
  337. // | |
  338. // |, |eoi
  339. // v |
  340. // [c]-----------+
  341. // | ^
  342. // | # |eoi
  343. // +-->[Stop]---+
  344. //
  345. //
  346. // Assume xon=off
  347. //
  348. SetXon = TRUE;
  349. SetOdsr = TRUE;
  350. SetOcts = TRUE;
  351. SetDtrControl = TRUE;
  352. SetRtsControl = TRUE;
  353. Xon = FALSE;
  354. Odsr = FALSE;
  355. Octs = FALSE;
  356. DtrControl = DTR_CONTROL_ENABLE;
  357. RtsControl = RTS_CONTROL_ENABLE;
  358. if (!ConvertBaudRate( GetNumber(&C), &Baud )) {
  359. return FALSE;
  360. }
  361. SetBaud = TRUE;
  362. Advance(&C);
  363. //
  364. // A:
  365. //
  366. if ( !Match(&C, "," ) ) {
  367. goto Eoi;
  368. }
  369. Advance(&C);
  370. if ( !Match(&C, "," ) && Match(&C, "@" ) ) {
  371. //
  372. // Parity
  373. //
  374. if (!ConvertParity( *C.MatchBegin,&Parity )) {
  375. return FALSE;
  376. }
  377. SetParity = TRUE;
  378. Advance(&C);
  379. }
  380. //
  381. // B:
  382. //
  383. if ( !Match(&C, "," )) {
  384. goto Eoi;
  385. }
  386. Advance(&C);
  387. if ( Match(&C, "#" )) {
  388. //
  389. // Data bits
  390. //
  391. if (!ConvertDataBits( GetNumber(&C),&DataBits )) {
  392. return FALSE;
  393. }
  394. SetDataBits = TRUE;
  395. Advance(&C);
  396. }
  397. //
  398. // C:
  399. //
  400. if ( !Match(&C, "," )) {
  401. goto Eoi;
  402. }
  403. Advance(&C);
  404. if ( Match(&C, "1.5" ) ) {
  405. StopBits = ONE5STOPBITS;
  406. SetStopBits = TRUE;
  407. Advance(&C);
  408. } else if ( Match(&C, "#" ) ) {
  409. if (!ConvertStopBits( GetNumber(&C),&StopBits)) {
  410. return FALSE;
  411. }
  412. SetStopBits = TRUE;
  413. Advance(&C);
  414. }
  415. if ( !Match(&C, "," )) {
  416. goto Eoi;
  417. }
  418. Advance(&C);
  419. if ( Match(&C, "x" ) ) {
  420. //
  421. // XON=ON
  422. //
  423. SetXon = TRUE;
  424. SetOdsr = TRUE;
  425. SetOcts = TRUE;
  426. SetDtrControl = TRUE;
  427. SetRtsControl = TRUE;
  428. Xon = TRUE;
  429. Odsr = FALSE;
  430. Octs = FALSE;
  431. DtrControl = DTR_CONTROL_ENABLE;
  432. RtsControl = RTS_CONTROL_ENABLE;
  433. Advance(&C);
  434. } else if ( Match(&C, "p" ) ) {
  435. //
  436. // Permanent retry - Hardware handshaking
  437. //
  438. SetXon = TRUE;
  439. SetOdsr = TRUE;
  440. SetOcts = TRUE;
  441. SetDtrControl = TRUE;
  442. SetRtsControl = TRUE;
  443. Xon = FALSE;
  444. Odsr = TRUE;
  445. Octs = TRUE;
  446. DtrControl = DTR_CONTROL_HANDSHAKE;
  447. RtsControl = RTS_CONTROL_HANDSHAKE;
  448. Advance(&C);
  449. } else {
  450. //
  451. // XON=OFF
  452. //
  453. SetXon = TRUE;
  454. SetOdsr = TRUE;
  455. SetOcts = TRUE;
  456. SetDtrControl = TRUE;
  457. SetRtsControl = TRUE;
  458. Xon = FALSE;
  459. Odsr = FALSE;
  460. Octs = FALSE;
  461. DtrControl = DTR_CONTROL_ENABLE;
  462. RtsControl = RTS_CONTROL_ENABLE;
  463. }
  464. Eoi:
  465. if ( *C.CharIndex != '\0' ) {
  466. //
  467. // Error
  468. //
  469. return FALSE;
  470. }
  471. } else {
  472. //
  473. // New Form
  474. //
  475. while ( *C.CharIndex != '\0' ) {
  476. if ( Match(&C, "BAUD=#" ) ) {
  477. //
  478. // BAUD=
  479. //
  480. if ( !ConvertBaudRate(GetNumber(&C), &Baud ) ) {
  481. return FALSE;
  482. }
  483. SetBaud = TRUE;
  484. Advance(&C);
  485. } else if ( Match(&C, "PARITY=@" ) ) {
  486. //
  487. // PARITY=
  488. //
  489. if ( !ConvertParity( *C.MatchBegin, &Parity ) ) {
  490. return FALSE;
  491. }
  492. SetParity = TRUE;
  493. Advance(&C);
  494. } else if ( Match(&C, "DATA=#" ) ) {
  495. //
  496. // DATA=
  497. //
  498. if ( !ConvertDataBits(GetNumber(&C), &DataBits ) ) {
  499. return FALSE;
  500. }
  501. SetDataBits = TRUE;
  502. Advance(&C);
  503. } else if ( Match(&C, "STOP=1.5" ) ) {
  504. //
  505. // STOP=1.5
  506. //
  507. StopBits = ONE5STOPBITS;
  508. SetStopBits = TRUE;
  509. Advance(&C);
  510. } else if ( Match(&C, "STOP=#" ) ) {
  511. //
  512. // STOP=
  513. //
  514. if ( !ConvertStopBits(GetNumber(&C), &StopBits ) ) {
  515. return FALSE;
  516. }
  517. SetStopBits = TRUE;
  518. Advance(&C);
  519. } else if ( Match(&C, "TO=ON" ) ) {
  520. //
  521. // TO=ON
  522. //
  523. SetTimeOut = TRUE;
  524. TimeOut = TRUE;
  525. Advance(&C);
  526. } else if ( Match(&C, "TO=OFF" ) ) {
  527. //
  528. // TO=ON
  529. //
  530. SetTimeOut = TRUE;
  531. TimeOut = FALSE;
  532. Advance(&C);
  533. } else if ( Match(&C, "XON=ON" ) ) {
  534. //
  535. // XON=ON
  536. //
  537. SetXon = TRUE;
  538. Xon = TRUE;
  539. Advance(&C);
  540. } else if ( Match(&C, "XON=OFF" ) ) {
  541. //
  542. // XON=OFF
  543. //
  544. SetXon = TRUE;
  545. Xon = FALSE;
  546. Advance(&C);
  547. } else if ( Match(&C, "ODSR=ON" ) ) {
  548. //
  549. // ODSR=ON
  550. //
  551. SetOdsr = TRUE;
  552. Odsr = TRUE;
  553. Advance(&C);
  554. } else if ( Match(&C, "ODSR=OFF" ) ) {
  555. //
  556. // ODSR=OFF
  557. //
  558. SetOdsr = TRUE;
  559. Odsr = FALSE;
  560. Advance(&C);
  561. } else if ( Match(&C, "IDSR=ON" ) ) {
  562. //
  563. // IDSR=ON
  564. //
  565. SetIdsr = TRUE;
  566. Idsr = TRUE;
  567. Advance(&C);
  568. } else if ( Match(&C, "IDSR=OFF" ) ) {
  569. //
  570. // IDSR=OFF
  571. //
  572. SetIdsr = TRUE;
  573. Idsr = FALSE;
  574. Advance(&C);
  575. } else if ( Match(&C, "OCTS=ON" ) ) {
  576. //
  577. // OCS=ON
  578. //
  579. SetOcts = TRUE;
  580. Octs = TRUE;
  581. Advance(&C);
  582. } else if ( Match(&C, "OCTS=OFF" ) ) {
  583. //
  584. // OCS=OFF
  585. //
  586. SetOcts = TRUE;
  587. Octs = FALSE;
  588. Advance(&C);
  589. } else if ( Match(&C, "DTR=*" ) ) {
  590. //
  591. // DTR=
  592. //
  593. if ( !ConvertDtrControl(C.MatchBegin, C.MatchEnd, &DtrControl ) ) {
  594. return FALSE;
  595. }
  596. SetDtrControl = TRUE;
  597. Advance(&C);
  598. } else if ( Match(&C, "RTS=*" ) ) {
  599. //
  600. // RTS=
  601. //
  602. if ( !ConvertRtsControl(C.MatchBegin, C.MatchEnd, &RtsControl ) ) {
  603. return FALSE;
  604. }
  605. SetRtsControl = TRUE;
  606. Advance(&C);
  607. } else {
  608. return FALSE;
  609. }
  610. }
  611. }
  612. if ( SetBaud ) {
  613. Dcb->BaudRate = Baud;
  614. }
  615. if ( SetDataBits ) {
  616. Dcb->ByteSize = DataBits;
  617. }
  618. if ( SetStopBits ) {
  619. Dcb->StopBits = StopBits;
  620. } else if ( SetBaud && (Baud == 110) ) {
  621. Dcb->StopBits = TWOSTOPBITS;
  622. } else {
  623. Dcb->StopBits = ONESTOPBIT;
  624. }
  625. if ( SetParity ) {
  626. Dcb->Parity = Parity;
  627. }
  628. if ( SetXon ) {
  629. if ( Xon ) {
  630. Dcb->fInX = TRUE;
  631. Dcb->fOutX = TRUE;
  632. } else {
  633. Dcb->fInX = FALSE;
  634. Dcb->fOutX = FALSE;
  635. }
  636. }
  637. if ( SetOcts ) {
  638. if ( Octs ) {
  639. Dcb->fOutxCtsFlow = TRUE;
  640. } else {
  641. Dcb->fOutxCtsFlow = FALSE;
  642. }
  643. }
  644. if ( SetOdsr ) {
  645. if ( Odsr ) {
  646. Dcb->fOutxDsrFlow = TRUE;
  647. } else {
  648. Dcb->fOutxDsrFlow = FALSE;
  649. }
  650. }
  651. if ( SetIdsr ) {
  652. if ( Idsr ) {
  653. Dcb->fDsrSensitivity = TRUE;
  654. } else {
  655. Dcb->fDsrSensitivity = FALSE;
  656. }
  657. }
  658. if ( SetDtrControl ) {
  659. Dcb->fDtrControl = DtrControl;
  660. }
  661. if ( SetRtsControl ) {
  662. Dcb->fRtsControl = RtsControl;
  663. }
  664. if ( SetTimeOut ) {
  665. if (TimeOut) {
  666. To->ReadIntervalTimeout = 0;
  667. To->ReadTotalTimeoutMultiplier = 0;
  668. To->ReadTotalTimeoutConstant = 0;
  669. To->WriteTotalTimeoutMultiplier = 0;
  670. To->WriteTotalTimeoutConstant = 60000;
  671. } else {
  672. To->ReadIntervalTimeout = 0;
  673. To->ReadTotalTimeoutMultiplier = 0;
  674. To->ReadTotalTimeoutConstant = 0;
  675. To->WriteTotalTimeoutMultiplier = 0;
  676. To->WriteTotalTimeoutConstant = 0;
  677. }
  678. }
  679. return TRUE;
  680. }
  681. static
  682. BOOL
  683. Match(
  684. PPARSE_CONTEXT C,
  685. PSTR Pattern
  686. )
  687. /*++
  688. Routine Description:
  689. This function matches a pattern against whatever
  690. is in the command line at the current position.
  691. Note that this does not advance our current position
  692. within the command line.
  693. If the pattern has a magic character, then the
  694. variables C->MatchBegin and C->MatchEnd delimit the
  695. substring of the command line that matched that
  696. magic character.
  697. Arguments:
  698. C - The parse context.
  699. Pattern - Supplies pointer to the pattern to match
  700. Return Value:
  701. BOOLEAN - TRUE if the pattern matched, FALSE otherwise
  702. Notes:
  703. --*/
  704. {
  705. PSTR CmdIndex; // Index within command line
  706. PSTR PatternIndex; // Index within pattern
  707. CHAR PatternChar; // Character in pattern
  708. CHAR CmdChar; // Character in command line;
  709. CmdIndex = C->CharIndex;
  710. PatternIndex = Pattern;
  711. while ( (PatternChar = *PatternIndex) != '\0' ) {
  712. switch ( PatternChar ) {
  713. case '#':
  714. //
  715. // Match a number
  716. //
  717. C->MatchBegin = CmdIndex;
  718. C->MatchEnd = C->MatchBegin;
  719. //
  720. // Get all consecutive digits
  721. //
  722. while ( ((CmdChar = *C->MatchEnd) != '\0') &&
  723. isdigit( (char)CmdChar ) ) {
  724. C->MatchEnd++;
  725. }
  726. C->MatchEnd--;
  727. if ( C->MatchBegin > C->MatchEnd ) {
  728. //
  729. // No number
  730. //
  731. return FALSE;
  732. }
  733. CmdIndex = C->MatchEnd + 1;
  734. PatternIndex++;
  735. break;
  736. case '@':
  737. //
  738. // Match one character
  739. //
  740. if ( *CmdIndex == '\0' ) {
  741. return FALSE;
  742. }
  743. C->MatchBegin = C->MatchEnd = CmdIndex;
  744. CmdIndex++;
  745. PatternIndex++;
  746. break;
  747. case '*':
  748. //
  749. // Match everything up to next blank (or end of input)
  750. //
  751. C->MatchBegin = CmdIndex;
  752. C->MatchEnd = C->MatchBegin;
  753. while ( ( (CmdChar = *C->MatchEnd ) != '\0' ) &&
  754. ( CmdChar != ' ' ) ) {
  755. C->MatchEnd++;
  756. }
  757. C->MatchEnd--;
  758. CmdIndex = C->MatchEnd+1;
  759. PatternIndex++;
  760. break;
  761. case '[':
  762. //
  763. // Optional sequence
  764. //
  765. PatternIndex++;
  766. PatternChar = *PatternIndex;
  767. CmdChar = *CmdIndex;
  768. //
  769. // If the first charcter in the input does not match the
  770. // first character in the optional sequence, we just
  771. // skip the optional sequence.
  772. //
  773. if ( ( CmdChar == '\0' ) ||
  774. ( CmdChar == ' ') ||
  775. ( toupper(CmdChar) != toupper(PatternChar) ) ) {
  776. while ( PatternChar != ']' ) {
  777. PatternIndex++;
  778. PatternChar = *PatternIndex;
  779. }
  780. PatternIndex++;
  781. } else {
  782. //
  783. // Since the first character in the sequence matched, now
  784. // everything must match.
  785. //
  786. while ( PatternChar != ']' ) {
  787. if ( toupper(PatternChar) != toupper(CmdChar) ) {
  788. return FALSE;
  789. }
  790. CmdIndex++;
  791. PatternIndex++;
  792. CmdChar = *CmdIndex;
  793. PatternChar = *PatternIndex;
  794. }
  795. PatternIndex++;
  796. }
  797. break;
  798. default:
  799. //
  800. // Both characters must match
  801. //
  802. CmdChar = *CmdIndex;
  803. if ( ( CmdChar == '\0' ) ||
  804. ( toupper(CmdChar) != toupper(PatternChar) ) ) {
  805. return FALSE;
  806. }
  807. CmdIndex++;
  808. PatternIndex++;
  809. break;
  810. }
  811. }
  812. C->AdvanceIndex = CmdIndex;
  813. return TRUE;
  814. }
  815. static
  816. VOID
  817. Advance(
  818. PPARSE_CONTEXT C
  819. )
  820. /*++
  821. Routine Description:
  822. Advances our pointers to the beginning of the next lexeme
  823. Arguments:
  824. C - The parse context.
  825. Return Value:
  826. None
  827. --*/
  828. {
  829. C->CharIndex = C->AdvanceIndex;
  830. //
  831. // Skip blank space
  832. //
  833. if ( *C->CharIndex == ' ' ) {
  834. while ( *C->CharIndex == ' ' ) {
  835. C->CharIndex++;
  836. }
  837. }
  838. }
  839. static
  840. DWORD
  841. GetNumber(
  842. PPARSE_CONTEXT C
  843. )
  844. /*++
  845. Routine Description:
  846. Converts the substring delimited by C->MatchBegin and C->MatchEnd into
  847. a number.
  848. Arguments:
  849. C - The parse context
  850. Return Value:
  851. ULONG - The matched string converted to a number
  852. --*/
  853. {
  854. DWORD Number;
  855. CHAR c;
  856. PSTR p = C->MatchEnd+1;
  857. c = *p;
  858. // *p = '\0';
  859. //intf( "Making number: %s\n", C->MatchBegin );
  860. Number = atol( C->MatchBegin );
  861. // *p = c;
  862. return Number;
  863. }
  864. static
  865. BOOL
  866. ConvertBaudRate (
  867. DWORD BaudIn,
  868. PDWORD BaudRate
  869. )
  870. /*++
  871. Routine Description:
  872. Validates a baud rate given as an argument to the program, and converts
  873. it to something that the COMM_DEVICE understands.
  874. Arguments:
  875. BaudIn - Supplies the baud rate given by the user
  876. BaudRate - if returning TRUE then the baud rate to use.
  877. Return Value:
  878. If a valid baud rate then returns TRUE, otherwise FALSE.
  879. --*/
  880. {
  881. switch ( BaudIn ) {
  882. case 11:
  883. case 110:
  884. *BaudRate = 110;
  885. break;
  886. case 15:
  887. case 150:
  888. *BaudRate = 150;
  889. break;
  890. case 30:
  891. case 300:
  892. *BaudRate = 300;
  893. break;
  894. case 60:
  895. case 600:
  896. *BaudRate = 600;
  897. break;
  898. case 12:
  899. case 1200:
  900. *BaudRate = 1200;
  901. break;
  902. case 24:
  903. case 2400:
  904. *BaudRate = 2400;
  905. break;
  906. case 48:
  907. case 4800:
  908. *BaudRate = 4800;
  909. break;
  910. case 96:
  911. case 9600:
  912. *BaudRate = 9600;
  913. break;
  914. case 19:
  915. case 19200:
  916. *BaudRate = 19200;
  917. break;
  918. default:
  919. *BaudRate = BaudIn;
  920. }
  921. return TRUE;
  922. }
  923. static
  924. BOOL
  925. ConvertDataBits (
  926. DWORD DataBitsIn,
  927. PBYTE DataBitsOut
  928. )
  929. /*++
  930. Routine Description:
  931. Validates the number of data bits given as an argument to the program,
  932. and converts it to something that the COMM_DEVICE understands.
  933. Arguments:
  934. DataBitsIn - Supplies the number given by the user
  935. DataBitsOut - if returning TRUE, then the number of data bits.
  936. Return Value:
  937. If a valid data bits then TRUE, otherwise FALSE.
  938. --*/
  939. {
  940. if ( ( DataBitsIn != 5 ) &&
  941. ( DataBitsIn != 6 ) &&
  942. ( DataBitsIn != 7 ) &&
  943. ( DataBitsIn != 8 ) ) {
  944. return FALSE;
  945. }
  946. *DataBitsOut = (BYTE)DataBitsIn;
  947. return TRUE;
  948. }
  949. static
  950. BOOL
  951. ConvertStopBits (
  952. DWORD StopBitsIn,
  953. PBYTE StopBits
  954. )
  955. /*++
  956. Routine Description:
  957. Validates a number of stop bits given as an argument to the program,
  958. and converts it to something that the COMM_DEVICE understands.
  959. Arguments:
  960. StopBitsIn - Supplies the number given by the user
  961. StopBits - If returning true then a valid stop bits setting.
  962. Return Value:
  963. If a valid stop bits setting then TRUE, otherwise false.
  964. --*/
  965. {
  966. switch ( StopBitsIn ) {
  967. case 1:
  968. *StopBits = ONESTOPBIT;
  969. break;
  970. case 2:
  971. *StopBits = TWOSTOPBITS;
  972. break;
  973. default:
  974. return FALSE;
  975. }
  976. return TRUE;
  977. }
  978. static
  979. BOOL
  980. ConvertParity (
  981. CHAR ParityIn,
  982. PBYTE Parity
  983. )
  984. /*++
  985. Routine Description:
  986. Validates a parity given as an argument to the program, and converts
  987. it to something that the COMM_DEVICE understands.
  988. Arguments:
  989. ParityIn - Supplies the baud rate given by the user
  990. Parity - The valid parity if return true.
  991. Return Value:
  992. If a valid parity setting then TRUE otherwise false.
  993. --*/
  994. {
  995. //
  996. // Set the correct parity value depending on the character.
  997. //
  998. switch ( tolower(ParityIn) ) {
  999. case 'n':
  1000. *Parity = NOPARITY;
  1001. break;
  1002. case 'o':
  1003. *Parity = ODDPARITY;
  1004. break;
  1005. case 'e':
  1006. *Parity = EVENPARITY;
  1007. break;
  1008. case 'm':
  1009. *Parity = MARKPARITY;
  1010. break;
  1011. case 's':
  1012. *Parity = SPACEPARITY;
  1013. break;
  1014. default:
  1015. return FALSE;
  1016. }
  1017. return TRUE;
  1018. }
  1019. static
  1020. BOOL
  1021. ConvertDtrControl (
  1022. PSTR IdxBegin,
  1023. PSTR IdxEnd,
  1024. PBYTE DtrControl
  1025. )
  1026. /*++
  1027. Routine Description:
  1028. Validates a DTR control value given as an argument to the
  1029. program, and converts it to something that the COMM_DEVICE
  1030. understands.
  1031. Arguments:
  1032. IdxBegin - Supplies Index of first character
  1033. IdxEnd - Supplies Index of last character
  1034. DtrControl - If returning true, the valid dtr setting.
  1035. Return Value:
  1036. DTR_CONTROL - The DTR control value
  1037. --*/
  1038. {
  1039. PSTR p;
  1040. p = IdxBegin;
  1041. if ( (tolower(*p) == 'o' ) &&
  1042. p++ &&
  1043. (tolower(*p) == 'n' ) &&
  1044. (IdxEnd == p)) {
  1045. *DtrControl = DTR_CONTROL_ENABLE;
  1046. return TRUE;
  1047. }
  1048. p = IdxBegin;
  1049. if ( (tolower(*p) == 'o') &&
  1050. p++ &&
  1051. (tolower(*p) == 'f') &&
  1052. p++ &&
  1053. (tolower(*p) == 'f') &&
  1054. (IdxEnd == p ) ) {
  1055. *DtrControl = DTR_CONTROL_DISABLE;
  1056. return TRUE;
  1057. }
  1058. p = IdxBegin;
  1059. if ( (tolower(*p) == 'h') &&
  1060. p++ &&
  1061. (tolower(*p++) == 's') &&
  1062. (IdxEnd == p ) ) {
  1063. *DtrControl = DTR_CONTROL_HANDSHAKE;
  1064. return TRUE;
  1065. }
  1066. return FALSE;
  1067. }
  1068. static
  1069. BOOL
  1070. ConvertRtsControl (
  1071. PSTR IdxBegin,
  1072. PSTR IdxEnd,
  1073. PBYTE RtsControl
  1074. )
  1075. /*++
  1076. Routine Description:
  1077. Validates a RTS control value given as an argument to the
  1078. program, and converts it to something that the COMM_DEVICE
  1079. understands.
  1080. Arguments:
  1081. IdxBegin - Supplies Index of first character
  1082. IdxEnd - Supplies Index of last character
  1083. RtsControl - If returning true, the valid rts setting.
  1084. Return Value:
  1085. RTS_CONTROL - The RTS control value
  1086. --*/
  1087. {
  1088. PSTR p;
  1089. p = IdxBegin;
  1090. if ( (tolower(*p) == 'o' ) &&
  1091. p++ &&
  1092. (tolower(*p) == 'n' ) &&
  1093. (IdxEnd == p)) {
  1094. *RtsControl = RTS_CONTROL_ENABLE;
  1095. return TRUE;
  1096. }
  1097. p = IdxBegin;
  1098. if ( (tolower(*p) == 'o') &&
  1099. p++ &&
  1100. (tolower(*p) == 'f') &&
  1101. p++ &&
  1102. (tolower(*p) == 'f') &&
  1103. (IdxEnd == p ) ) {
  1104. *RtsControl = RTS_CONTROL_DISABLE;
  1105. return TRUE;
  1106. }
  1107. p = IdxBegin;
  1108. if ( (tolower(*p) == 'h') &&
  1109. p++ &&
  1110. (tolower(*p++) == 's') &&
  1111. (IdxEnd == p ) ) {
  1112. *RtsControl = RTS_CONTROL_HANDSHAKE;
  1113. return TRUE;
  1114. }
  1115. p = IdxBegin;
  1116. if ( (tolower(*p) == 't') &&
  1117. p++ &&
  1118. (tolower(*p++) == 'g') &&
  1119. (IdxEnd == p ) ) {
  1120. *RtsControl = RTS_CONTROL_TOGGLE;
  1121. return TRUE;
  1122. }
  1123. return FALSE;
  1124. }
  1125. static
  1126. NTSTATUS
  1127. DeviceNameCompare(
  1128. IN PWSTR ValueName,
  1129. IN ULONG ValueType,
  1130. IN PVOID ValueData,
  1131. IN ULONG ValueLength,
  1132. IN PVOID Context,
  1133. IN PVOID EntryContext
  1134. )
  1135. {
  1136. PPARSE_CONTEXT C = EntryContext;
  1137. UNICODE_STRING uniName;
  1138. ANSI_STRING ansiName;
  1139. RtlInitUnicodeString(
  1140. &uniName,
  1141. ValueData
  1142. );
  1143. if (!NT_SUCCESS(RtlUnicodeStringToAnsiString(
  1144. &ansiName,
  1145. &uniName,
  1146. TRUE
  1147. ))) {
  1148. //
  1149. // Oh well, couldn't form the name. Just get out.
  1150. //
  1151. return STATUS_SUCCESS;
  1152. }
  1153. //
  1154. // See if we got a name match.
  1155. //
  1156. if (Match(C,ansiName.Buffer)) {
  1157. //
  1158. // Ok, got a name match, advance past it.
  1159. //
  1160. Advance(C);
  1161. //
  1162. // See if they've got the optional : following the
  1163. // device name.
  1164. //
  1165. if (Match(C,":")) {
  1166. //
  1167. // Go past it.
  1168. //
  1169. Advance(C);
  1170. }
  1171. }
  1172. RtlFreeAnsiString(&ansiName);
  1173. return STATUS_SUCCESS;
  1174. }
  1175. static
  1176. VOID
  1177. IgnoreDeviceName(
  1178. IN PPARSE_CONTEXT C
  1179. )
  1180. {
  1181. RTL_QUERY_REGISTRY_TABLE qTable[2] = {0};
  1182. //
  1183. // Build the query table.
  1184. //
  1185. qTable[0].QueryRoutine = DeviceNameCompare;
  1186. qTable[0].EntryContext = C;
  1187. RtlQueryRegistryValues(
  1188. RTL_REGISTRY_DEVICEMAP,
  1189. L"SERIALCOMM",
  1190. &qTable[0],
  1191. NULL,
  1192. NULL
  1193. );
  1194. }