Leaked source code of windows server 2003
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.

1219 lines
24 KiB

  1. /*++
  2. Copyright (c) 1990-2000 Microsoft Corporation
  3. Module Name:
  4. Com
  5. Abstract:
  6. Takes care of request involving a COM device
  7. Author:
  8. Ramon Juan San Andres (ramonsa) 26-Jun-1991
  9. Revision History:
  10. --*/
  11. #include "mode.hxx"
  12. #include "com.hxx"
  13. #include "array.hxx"
  14. #include "arrayit.hxx"
  15. #include "file.hxx"
  16. #include "path.hxx"
  17. #include "registry.hxx"
  18. #include "regvalue.hxx"
  19. #define DEFAULT_PARITY COMM_PARITY_EVEN
  20. #define DEFAULT_DATA_BITS 7
  21. //
  22. // Local prototypes
  23. //
  24. BOOLEAN
  25. ComStatus(
  26. IN PCPATH DevicePath,
  27. IN PREQUEST_HEADER Request
  28. );
  29. BOOLEAN
  30. ComSetup(
  31. IN PCPATH DevicePath,
  32. IN PREQUEST_HEADER Request
  33. );
  34. BOOLEAN
  35. IsAValidCommDevice (
  36. IN DEVICE_TTYPE DeviceType,
  37. IN ULONG DeviceNumber,
  38. OUT PPATH *DevicePathPointer
  39. );
  40. BOOLEAN
  41. ComAllocateStuff(
  42. )
  43. /*++
  44. Routine Description:
  45. Initializes Data Structures used for COMM processing.
  46. Arguments:
  47. nonde
  48. Return Value:
  49. BOOLEAN - TRUE if global data initialized, FALSE otherwise
  50. Notes:
  51. --*/
  52. {
  53. return TRUE;
  54. }
  55. BOOLEAN
  56. ComDeAllocateStuff(
  57. )
  58. /*++
  59. Routine Description:
  60. Deallocates the stuff allocated by ComAllocateStuff.
  61. Arguments:
  62. nonde
  63. Return Value:
  64. BOOLEAN - TRUE if global data de-initialized, FALSE otherwise
  65. Notes:
  66. --*/
  67. {
  68. return TRUE;
  69. }
  70. BOOLEAN
  71. ComHandler(
  72. IN PREQUEST_HEADER Request
  73. )
  74. /*++
  75. Routine Description:
  76. Handles serial port requests.
  77. Arguments:
  78. Request - Supplies pointer to request
  79. Return Value:
  80. BOOLEAN - TRUE if request serviced,
  81. FALSE otherwise.
  82. Notes:
  83. --*/
  84. {
  85. PPATH DevicePath; // Name of Device
  86. BOOLEAN Served = TRUE; // TRUE if request served OK.
  87. DebugPtrAssert( Request );
  88. DebugAssert( Request->DeviceType == DEVICE_TYPE_COM );
  89. //
  90. // Make sure that the device exists, and at the same time get its
  91. // name ( For calling APIs ).
  92. //
  93. if ( Request->DeviceName ) {
  94. if (!(DevicePath = NEW PATH)) {
  95. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  96. NULL,
  97. (ULONG)EXIT_ERROR );
  98. return FALSE; // help lint
  99. }
  100. DevicePath->Initialize( Request->DeviceName );
  101. } else {
  102. if ( !IsAValidCommDevice( Request->DeviceType, Request->DeviceNumber, &DevicePath )) {
  103. DisplayMessageAndExit( MODE_ERROR_INVALID_DEVICE_NAME,
  104. DevicePath->GetPathString(),
  105. (ULONG)EXIT_ERROR );
  106. } else if ( !IsAValidDevice( Request->DeviceType, Request->DeviceNumber, NULL ) ) {
  107. DisplayMessageAndExit( MODE_ERROR_DEVICE_UNAVAILABLE,
  108. DevicePath->GetPathString(),
  109. (ULONG)EXIT_ERROR );
  110. }
  111. }
  112. //
  113. // So the device is valid. Now serve the request
  114. //
  115. switch( Request->RequestType ) {
  116. case REQUEST_TYPE_STATUS:
  117. //
  118. // Display state of COM device
  119. //
  120. Served = ComStatus( DevicePath, Request );
  121. break;
  122. case REQUEST_TYPE_COM_SET:
  123. //
  124. // Set state of COM device
  125. //
  126. Served = ComSetup( DevicePath, Request );
  127. break;
  128. default:
  129. DebugAssert( FALSE );
  130. }
  131. DELETE( DevicePath );
  132. return Served;
  133. }
  134. BOOLEAN
  135. ComStatus(
  136. IN PCPATH DevicePath,
  137. IN PREQUEST_HEADER Request
  138. )
  139. /*++
  140. Routine Description:
  141. Displays status if a COM device
  142. Arguments:
  143. DevicePath - Supplies pointer to path of device
  144. Request - Supplies pointer to request
  145. Return Value:
  146. BOOLEAN - TRUE if status displayed successfully,
  147. FALSE otherwise
  148. Notes:
  149. --*/
  150. {
  151. DSTRING Data;
  152. COMM_DEVICE CommDevice; // Comm object of the device.
  153. BOOLEAN OpenError;
  154. BOOLEAN Status;
  155. DebugPtrAssert( DevicePath );
  156. DebugPtrAssert( Request );
  157. //
  158. // Initialize the Comm object
  159. //
  160. Status = CommDevice.Initialize( DevicePath, &OpenError);
  161. if ( Status ) {
  162. //
  163. // Write the Header
  164. //
  165. WriteStatusHeader( DevicePath );
  166. //
  167. // Baud rate
  168. //
  169. Data.Initialize( (ULONG)CommDevice.QueryBaudRate() );
  170. DisplayMessage( MODE_MESSAGE_STATUS_BAUD, &Data );
  171. //
  172. // Parity
  173. //
  174. switch ( CommDevice.QueryParity() ) {
  175. case COMM_PARITY_NONE:
  176. Data.Initialize( "None" );
  177. break;
  178. case COMM_PARITY_ODD:
  179. Data.Initialize( "Odd" );
  180. break;
  181. case COMM_PARITY_EVEN:
  182. Data.Initialize( "Even" );
  183. break;
  184. case COMM_PARITY_MARK:
  185. Data.Initialize( "Mark" );
  186. break;
  187. case COMM_PARITY_SPACE:
  188. Data.Initialize( "Space" );
  189. break;
  190. default:
  191. DebugAssert( FALSE );
  192. }
  193. DisplayMessage( MODE_MESSAGE_STATUS_PARITY, &Data );
  194. //
  195. // Data bits
  196. //
  197. Data.Initialize( (ULONG)CommDevice.QueryDataBits() );
  198. DisplayMessage( MODE_MESSAGE_STATUS_DATA, &Data );
  199. //
  200. // Stop bits
  201. //
  202. switch ( CommDevice.QueryStopBits() ) {
  203. case COMM_STOPBITS_15:
  204. Data.Initialize( "1.5" );
  205. break;
  206. case COMM_STOPBITS_1:
  207. Data.Initialize( 1 );
  208. break;
  209. case COMM_STOPBITS_2:
  210. Data.Initialize( 2 );
  211. break;
  212. default:
  213. DebugAssert( FALSE );
  214. }
  215. DisplayMessage( MODE_MESSAGE_STATUS_STOP, &Data );
  216. //
  217. // TimeOut
  218. //
  219. if ( CommDevice.QueryTimeOut() ) {
  220. //
  221. // TRUE means infinite timeout == no timeout
  222. //
  223. Data.Initialize( "OFF" );
  224. } else {
  225. Data.Initialize( "ON" );
  226. }
  227. DisplayMessage( MODE_MESSAGE_STATUS_TIMEOUT, &Data );
  228. //
  229. // XON/XOFF
  230. //
  231. if ( CommDevice.QueryXon() ) {
  232. Data.Initialize( "ON" );
  233. } else {
  234. Data.Initialize( "OFF" );
  235. }
  236. DisplayMessage( MODE_MESSAGE_STATUS_XON, &Data );
  237. //
  238. // CTS
  239. //
  240. if ( CommDevice.QueryOcts() ) {
  241. Data.Initialize( "ON" );
  242. } else {
  243. Data.Initialize( "OFF" );
  244. }
  245. DisplayMessage( MODE_MESSAGE_STATUS_OCTS, &Data );
  246. //
  247. // DSR handshaking
  248. //
  249. if ( CommDevice.QueryOdsr() ) {
  250. Data.Initialize( "ON" );
  251. } else {
  252. Data.Initialize( "OFF" );
  253. }
  254. DisplayMessage( MODE_MESSAGE_STATUS_ODSR, &Data );
  255. //
  256. // DSR sensitivity
  257. //
  258. if ( CommDevice.QueryIdsr() ) {
  259. Data.Initialize( "ON" );
  260. } else {
  261. Data.Initialize( "OFF" );
  262. }
  263. DisplayMessage( MODE_MESSAGE_STATUS_IDSR, &Data );
  264. //
  265. // DTR
  266. //
  267. switch( CommDevice.QueryDtrControl() ) {
  268. case DTR_ENABLE:
  269. Data.Initialize( "ON" );
  270. break;
  271. case DTR_DISABLE:
  272. Data.Initialize( "OFF" );
  273. break;
  274. case DTR_HANDSHAKE:
  275. Data.Initialize( "HANDSHAKE" );
  276. break;
  277. default:
  278. Data.Initialize( "UNKNOWN" );
  279. break;
  280. }
  281. DisplayMessage( MODE_MESSAGE_STATUS_DTR, &Data );
  282. //
  283. // RTS
  284. //
  285. switch( CommDevice.QueryRtsControl() ) {
  286. case RTS_ENABLE:
  287. Data.Initialize( "ON" );
  288. break;
  289. case RTS_DISABLE:
  290. Data.Initialize( "OFF" );
  291. break;
  292. case RTS_HANDSHAKE:
  293. Data.Initialize( "HANDSHAKE" );
  294. break;
  295. case RTS_TOGGLE:
  296. Data.Initialize( "TOGGLE" );
  297. break;
  298. default:
  299. Data.Initialize( "UNKNOWN" );
  300. break;
  301. }
  302. DisplayMessage( MODE_MESSAGE_STATUS_RTS, &Data );
  303. Get_Standard_Output_Stream()->WriteChar( '\r' );
  304. Get_Standard_Output_Stream()->WriteChar( '\n' );
  305. } else if ( !OpenError ) {
  306. DisplayMessage( MODE_ERROR_CANNOT_ACCESS_DEVICE,
  307. DevicePath->GetPathString() );
  308. Status = TRUE;
  309. }
  310. return Status;
  311. }
  312. BOOLEAN
  313. ComSetup(
  314. IN PCPATH DevicePath,
  315. IN PREQUEST_HEADER Request
  316. )
  317. /*++
  318. Routine Description:
  319. Sets the state of a COM port
  320. Arguments:
  321. DevicePath - Supplies pointer to path of device
  322. Request - Supplies pointer to request
  323. Return Value:
  324. BOOLEAN - TRUE if state set successfully,
  325. FALSE otherwise
  326. Notes:
  327. --*/
  328. {
  329. PCOMM_DEVICE CommDevice; // Comm object of the device.
  330. BOOLEAN Status = FALSE; // Indicates success or failure
  331. PREQUEST_DATA_COM_SET Data; // Request data
  332. BOOLEAN OpenError;
  333. DSTRING Number;
  334. DebugPtrAssert( DevicePath );
  335. DebugPtrAssert( Request );
  336. //
  337. // Initialize the Comm object
  338. //
  339. CommDevice = NEW COMM_DEVICE;
  340. if ( !CommDevice ) {
  341. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY, NULL, (ULONG)EXIT_ERROR );
  342. return FALSE; // help lint
  343. }
  344. Status = CommDevice->Initialize( DevicePath, &OpenError );
  345. if ( Status ) {
  346. //
  347. // We have the Comm object. Set the state according to
  348. // the request.
  349. //
  350. Data = &(((PCOM_REQUEST)Request)->Data.Set);
  351. //
  352. // Baud rate
  353. //
  354. if ( Data->SetBaud ) {
  355. CommDevice->SetBaudRate( Data->Baud );
  356. }
  357. //
  358. // Data Bits
  359. //
  360. if ( Data->SetDataBits ) {
  361. CommDevice->SetDataBits( Data->DataBits );
  362. } else {
  363. //
  364. // Set default
  365. //
  366. if ( CommDevice->QueryDataBits() != DEFAULT_DATA_BITS ) {
  367. CommDevice->SetDataBits( DEFAULT_DATA_BITS );
  368. Number.Initialize( DEFAULT_DATA_BITS );
  369. DisplayMessage( MODE_MESSAGE_USED_DEFAULT_DATA, &Number );
  370. }
  371. }
  372. //
  373. // Stop Bits
  374. //
  375. if ( Data->SetStopBits ) {
  376. CommDevice->SetStopBits( Data->StopBits );
  377. } else {
  378. //
  379. // Set default
  380. //
  381. if ( CommDevice->QueryBaudRate() == 110 ) {
  382. if ( CommDevice->QueryStopBits() != COMM_STOPBITS_2 ) {
  383. CommDevice->SetStopBits( COMM_STOPBITS_2 );
  384. Number.Initialize( 2 );
  385. DisplayMessage( MODE_MESSAGE_USED_DEFAULT_STOP, &Number );
  386. }
  387. } else {
  388. if ( CommDevice->QueryStopBits() != COMM_STOPBITS_1 ) {
  389. CommDevice->SetStopBits( COMM_STOPBITS_1 );
  390. Number.Initialize( 1 );
  391. DisplayMessage( MODE_MESSAGE_USED_DEFAULT_STOP, &Number );
  392. }
  393. }
  394. }
  395. //
  396. // Parity
  397. //
  398. if ( Data->SetParity ) {
  399. CommDevice->SetParity( Data->Parity );
  400. } else {
  401. //
  402. // Set default
  403. //
  404. if ( CommDevice->QueryParity() != DEFAULT_PARITY ) {
  405. CommDevice->SetParity( DEFAULT_PARITY );
  406. DisplayMessage( MODE_MESSAGE_USED_DEFAULT_PARITY, NULL );
  407. }
  408. }
  409. //
  410. // Timeout
  411. //
  412. if ( Data->SetTimeOut ) {
  413. CommDevice->SetTimeOut( Data->TimeOut );
  414. }
  415. //
  416. // XON/XOFF
  417. //
  418. if ( Data->SetXon) {
  419. CommDevice->SetXon( Data->Xon );
  420. }
  421. //
  422. // CTS
  423. //
  424. if ( Data->SetOcts ) {
  425. CommDevice->SetOcts( Data->Octs );
  426. }
  427. //
  428. // DSR handshaking
  429. //
  430. if ( Data->SetOdsr ) {
  431. CommDevice->SetOdsr( Data->Odsr );
  432. }
  433. //
  434. // DSR sensitivity
  435. //
  436. if ( Data->SetIdsr ) {
  437. CommDevice->SetIdsr( Data->Idsr );
  438. }
  439. //
  440. // DTR
  441. //
  442. if ( Data->SetDtrControl ) {
  443. CommDevice->SetDtrControl( Data->DtrControl );
  444. }
  445. //
  446. // RTS
  447. //
  448. if ( Data->SetRtsControl ) {
  449. CommDevice->SetRtsControl( Data->RtsControl );
  450. }
  451. //
  452. // Now Commit the changes
  453. //
  454. if ( !CommDevice->CommitState() ) {
  455. DisplayMessage( MODE_ERROR_SERIAL_OPTIONS_NOT_SUPPORTED, NULL );
  456. DisplayMessageAndExit( MODE_MESSAGE_COM_NO_CHANGE,
  457. NULL,
  458. (ULONG)EXIT_ERROR );
  459. }
  460. } else if ( !OpenError ) {
  461. DisplayMessageAndExit( MODE_ERROR_CANNOT_ACCESS_DEVICE,
  462. DevicePath->GetPathString(),
  463. (ULONG)EXIT_ERROR );
  464. }
  465. DELETE( CommDevice );
  466. if ( Status ) {
  467. //
  468. // Display the status of the port (as confirmation ).
  469. //
  470. ComStatus( DevicePath, Request );
  471. }
  472. return Status;
  473. }
  474. LONG
  475. ConvertBaudRate (
  476. IN LONG BaudIn
  477. )
  478. /*++
  479. Routine Description:
  480. Validates a baud rate given as an argument to the program, and converts
  481. it to something that the COMM_DEVICE understands.
  482. Arguments:
  483. BaudIn - Supplies the baud rate given by the user
  484. Return Value:
  485. LONG - The baud rate
  486. --*/
  487. {
  488. LONG BaudRate;
  489. switch ( BaudIn ) {
  490. case 11:
  491. case 110:
  492. BaudRate = 110;
  493. break;
  494. case 15:
  495. case 150:
  496. BaudRate = 150;
  497. break;
  498. case 30:
  499. case 300:
  500. BaudRate = 300;
  501. break;
  502. case 60:
  503. case 600:
  504. BaudRate = 600;
  505. break;
  506. case 12:
  507. case 1200:
  508. BaudRate = 1200;
  509. break;
  510. case 24:
  511. case 2400:
  512. BaudRate = 2400;
  513. break;
  514. case 48:
  515. case 4800:
  516. BaudRate = 4800;
  517. break;
  518. case 96:
  519. case 9600:
  520. BaudRate = 9600;
  521. break;
  522. case 19:
  523. case 19200:
  524. BaudRate = 19200;
  525. break;
  526. default:
  527. BaudRate = BaudIn;
  528. }
  529. return BaudRate;
  530. }
  531. LONG
  532. ConvertDataBits (
  533. IN LONG DataBitsIn
  534. )
  535. /*++
  536. Routine Description:
  537. Validates the number of data bits given as an argument to the program,
  538. and converts it to something that the COMM_DEVICE understands.
  539. Arguments:
  540. DataBitsIn - Supplies the number given by the user
  541. Return Value:
  542. LONG - The number of data bits
  543. --*/
  544. {
  545. if ( ( DataBitsIn != 5 ) &&
  546. ( DataBitsIn != 6 ) &&
  547. ( DataBitsIn != 7 ) &&
  548. ( DataBitsIn != 8 ) ) {
  549. ParseError();
  550. }
  551. return DataBitsIn;
  552. }
  553. STOPBITS
  554. ConvertStopBits (
  555. IN LONG StopBitsIn
  556. )
  557. /*++
  558. Routine Description:
  559. Validates a number of stop bits given as an argument to the program,
  560. and converts it to something that the COMM_DEVICE understands.
  561. Arguments:
  562. StopBitsIn - Supplies the number given by the user
  563. Return Value:
  564. STOPBITS - The number of stop bits
  565. --*/
  566. {
  567. STOPBITS StopBits;
  568. switch ( StopBitsIn ) {
  569. case 1:
  570. StopBits = COMM_STOPBITS_1;
  571. break;
  572. case 2:
  573. StopBits = COMM_STOPBITS_2;
  574. break;
  575. default:
  576. ParseError();
  577. }
  578. return StopBits;
  579. }
  580. PARITY
  581. ConvertParity (
  582. IN WCHAR ParityIn
  583. )
  584. /*++
  585. Routine Description:
  586. Validates a parity given as an argument to the program, and converts
  587. it to something that the COMM_DEVICE understands.
  588. Arguments:
  589. ParityIn - Supplies the baud rate given by the user
  590. Return Value:
  591. PARITY - The parity
  592. --*/
  593. {
  594. DSTRING ParityString;;
  595. WCHAR Par;
  596. PARITY Parity;
  597. //
  598. // Get the character that specifies parity. We lowercase it
  599. //
  600. ParityString.Initialize( " " );
  601. ParityString.SetChAt( ParityIn, 0 );
  602. ParityString.Strlwr();
  603. Par = ParityString.QueryChAt( 0 );
  604. //
  605. // Set the correct parity value depending on the character.
  606. //
  607. switch ( Par ) {
  608. case 'n':
  609. Parity = COMM_PARITY_NONE;
  610. break;
  611. case 'o':
  612. Parity = COMM_PARITY_ODD;
  613. break;
  614. case 'e':
  615. Parity = COMM_PARITY_EVEN;
  616. break;
  617. case 'm':
  618. Parity = COMM_PARITY_MARK;
  619. break;
  620. case 's':
  621. Parity = COMM_PARITY_SPACE;
  622. break;
  623. default:
  624. ParseError();
  625. }
  626. return Parity;
  627. }
  628. WCHAR
  629. ConvertRetry (
  630. IN WCHAR RetryIn
  631. )
  632. /*++
  633. Routine Description:
  634. Validates a retry value given as an argument to the program, and
  635. converts it to something that the COMM_DEVICE understands.
  636. Arguments:
  637. RetryIn - Supplies the retry value given by the user
  638. Return Value:
  639. WCHAR - The retry value
  640. --*/
  641. {
  642. return RetryIn;
  643. }
  644. DTR_CONTROL
  645. ConvertDtrControl (
  646. IN PCWSTRING CmdLine,
  647. IN CHNUM IdxBegin,
  648. IN CHNUM IdxEnd
  649. )
  650. /*++
  651. Routine Description:
  652. Validates a DTR control value given as an argument to the
  653. program, and converts it to something that the COMM_DEVICE
  654. understands.
  655. Arguments:
  656. CmdLine - Supplies the command line
  657. IdxBegin - Supplies Index of first character
  658. IdxEnd - Supplies Index of last character
  659. Return Value:
  660. DTR_CONTROL - The DTR control value
  661. --*/
  662. {
  663. DSTRING On;
  664. DSTRING Off;
  665. DSTRING Hs;
  666. if ( On.Initialize( "ON" ) &&
  667. Off.Initialize( "OFF" ) &&
  668. Hs.Initialize( "HS" ) ) {
  669. if ( !CmdLine->Stricmp( &On,
  670. IdxBegin,
  671. IdxEnd-IdxBegin+1,
  672. 0,
  673. On.QueryChCount() ) ) {
  674. return DTR_ENABLE;
  675. }
  676. if ( !CmdLine->Stricmp( &Off,
  677. IdxBegin,
  678. IdxEnd-IdxBegin+1,
  679. 0,
  680. Off.QueryChCount() ) ) {
  681. return DTR_DISABLE;
  682. }
  683. if ( !CmdLine->Stricmp( &Hs,
  684. IdxBegin,
  685. IdxEnd-IdxBegin+1,
  686. 0,
  687. Hs.QueryChCount() ) ) {
  688. return DTR_HANDSHAKE;
  689. }
  690. }
  691. ParseError();
  692. return (DTR_CONTROL)-1;
  693. }
  694. RTS_CONTROL
  695. ConvertRtsControl (
  696. IN PCWSTRING CmdLine,
  697. IN CHNUM IdxBegin,
  698. IN CHNUM IdxEnd
  699. )
  700. /*++
  701. Routine Description:
  702. Validates a RTS control value given as an argument to the
  703. program, and converts it to something that the COMM_DEVICE
  704. understands.
  705. Arguments:
  706. CmdLine - Supplies the command line
  707. IdxBegin - Supplies Index of first character
  708. IdxEnd - Supplies Index of last character
  709. Return Value:
  710. RTS_CONTROL - The RTS control value
  711. --*/
  712. {
  713. DSTRING On;
  714. DSTRING Off;
  715. DSTRING Hs;
  716. DSTRING Tg;
  717. if ( On.Initialize( "ON" ) &&
  718. Off.Initialize( "OFF" ) &&
  719. Hs.Initialize( "HS" ) &&
  720. Tg.Initialize( "TG" )
  721. ) {
  722. if ( !CmdLine->Stricmp( &On,
  723. IdxBegin,
  724. IdxEnd-IdxBegin+1,
  725. 0,
  726. On.QueryChCount() ) ) {
  727. return RTS_ENABLE;
  728. }
  729. if ( !CmdLine->Stricmp( &Off,
  730. IdxBegin,
  731. IdxEnd-IdxBegin+1,
  732. 0,
  733. Off.QueryChCount() ) ) {
  734. return RTS_DISABLE;
  735. }
  736. if ( !CmdLine->Stricmp( &Hs,
  737. IdxBegin,
  738. IdxEnd-IdxBegin+1,
  739. 0,
  740. Hs.QueryChCount() ) ) {
  741. return RTS_HANDSHAKE;
  742. }
  743. if ( !CmdLine->Stricmp( &Tg,
  744. IdxBegin,
  745. IdxEnd-IdxBegin+1,
  746. 0,
  747. Tg.QueryChCount() ) ) {
  748. return RTS_TOGGLE;
  749. }
  750. }
  751. ParseError();
  752. return (RTS_CONTROL)-1;
  753. }
  754. BOOLEAN
  755. IsAValidCommDevice (
  756. IN DEVICE_TTYPE DeviceType,
  757. IN ULONG DeviceNumber,
  758. OUT PPATH *DevicePathPointer
  759. )
  760. /*++
  761. Routine Description:
  762. Determines if a certain comm device exists and optionally
  763. creates a path for it.
  764. Arguments:
  765. DeviceType - Supplies the type of device
  766. DeviceNumber - Supplies the device number
  767. DeviceName - Supplies a pointer to a pointer to the path for
  768. the device.
  769. Return Value:
  770. BOOLEAN - TRUE if the device exists,
  771. FALSE otherwise.
  772. Notes:
  773. --*/
  774. {
  775. DSTRING DeviceName;
  776. DSTRING Number;
  777. BOOLEAN Valid = FALSE;
  778. REGISTRY Registry;
  779. DSTRING ParentName;
  780. DSTRING KeyName;
  781. ARRAY ValueArray;
  782. PARRAY_ITERATOR Iterator;
  783. ULONG ErrorCode;
  784. PCBYTE Data;
  785. DSTRING PortName;
  786. PREGISTRY_VALUE_ENTRY Value;
  787. UNREFERENCED_PARAMETER( DeviceType );
  788. if ( DeviceName.Initialize( (LPWSTR)L"COM" )&&
  789. Number.Initialize( DeviceNumber ) &&
  790. DeviceName.Strcat( &Number ) &&
  791. ParentName.Initialize( "" ) &&
  792. KeyName.Initialize( COMM_KEY_NAME ) &&
  793. ValueArray.Initialize() &&
  794. Registry.Initialize()
  795. ) {
  796. //
  797. // Get the names of all the serial ports
  798. //
  799. if ( Registry.QueryValues(
  800. PREDEFINED_KEY_LOCAL_MACHINE,
  801. &ParentName,
  802. &KeyName,
  803. &ValueArray,
  804. &ErrorCode
  805. ) ) {
  806. //
  807. // See if the given name matches any of the serial ports
  808. //
  809. if ( Iterator = (PARRAY_ITERATOR)ValueArray.QueryIterator() ) {
  810. while ( Value = (PREGISTRY_VALUE_ENTRY)(Iterator->GetNext() ) ) {
  811. if ( Value->GetData( &Data ) ) {
  812. if ( PortName.Initialize( (PWSTR)Data ) ) {
  813. if ( !DeviceName.Stricmp( &PortName ) ) {
  814. Valid = TRUE;
  815. break;
  816. }
  817. }
  818. }
  819. }
  820. DELETE( Iterator );
  821. }
  822. }
  823. if ( DevicePathPointer ) {
  824. if (!(*DevicePathPointer = NEW PATH)) {
  825. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  826. NULL,
  827. (ULONG)EXIT_ERROR );
  828. return FALSE; // help lint
  829. }
  830. (*DevicePathPointer)->Initialize( &DeviceName );
  831. }
  832. }
  833. return Valid;
  834. }