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.

1518 lines
30 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. Argument
  5. Abstract:
  6. Argument processing for the Mode utility. After parsing the
  7. arguments off the command line, a minimum verification is done and
  8. a request packet is formed and returned.
  9. The request packet is eventually routed to the handler for a specific
  10. device, which performs further verification and takes proper
  11. action.
  12. Author:
  13. Ramon Juan San Andres (ramonsa) 26-Jun-1991
  14. Notes:
  15. BUGBUG ramonsa 7/9/91
  16. The number of stop bits can be 1, 1.5 or 2, Currently the library will
  17. not support floating point operations, so there are no
  18. floating-point-number arguments. We use a flag argument to handle
  19. the 1.5 case. This should be fixed whenever the library supports
  20. floating point.
  21. The mode command-line can take any of the following forms:
  22. MODE [/?]
  23. MODE [device] [/STATUS]
  24. MODE device CP PREPARE=string
  25. MODE device CP REFRESH
  26. MODE device CP SELECT=codepage
  27. MODE device CP [/STATUS]
  28. MODE LPTn[:] [COLS=c] [LINES=l] [RETRY=r]
  29. MODE LPTn[:] = COMm[:]
  30. MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] [RETRY=r]
  31. MODE CON[:] [COLS=c] [LINES=l]
  32. MODE CON[:] [RATE=r DELAY=d]
  33. Revision History:
  34. --*/
  35. #include "mode.hxx"
  36. #include "arg.hxx"
  37. #include "array.hxx"
  38. #include "common.hxx"
  39. #include "lpt.hxx"
  40. #include "com.hxx"
  41. #include "con.hxx"
  42. //
  43. // BUGBUG all variables here should be static
  44. //
  45. PWSTRING LptPattern = NULL;
  46. PWSTRING LptColonPattern = NULL;
  47. PWSTRING ComPattern = NULL;
  48. PWSTRING ComColonPattern = NULL;
  49. PWSTRING ConPattern = NULL;
  50. PWSTRING ConColonPattern = NULL;
  51. PWSTRING StatusPattern = NULL;
  52. PWSTRING ColPattern = NULL;
  53. PWSTRING LinesPattern = NULL;
  54. PWSTRING CpPattern = NULL;
  55. PWSTRING PreparePattern = NULL;
  56. PWSTRING RetryPattern = NULL;
  57. PWSTRING EqualPattern = NULL;
  58. PWSTRING BaudPattern = NULL;
  59. PWSTRING ParityPattern = NULL;
  60. PWSTRING DataPattern = NULL;
  61. PWSTRING StopPattern = NULL;
  62. PWSTRING Stop15Pattern = NULL;
  63. PWSTRING SelectPattern = NULL;
  64. PWSTRING RefreshPattern = NULL;
  65. PWSTRING RatePattern = NULL;
  66. PWSTRING DelayPattern = NULL;
  67. PWSTRING HelpPattern = NULL;
  68. //
  69. // Parsing preferences
  70. //
  71. PWSTRING Switches = NULL;
  72. //
  73. // Arguments
  74. //
  75. PPATH_ARGUMENT ProgramNameArg;
  76. PLONG_ARGUMENT LptArg;
  77. PLONG_ARGUMENT LptColonArg;
  78. PLONG_ARGUMENT ComArg;
  79. PLONG_ARGUMENT ComColonArg;
  80. PFLAG_ARGUMENT ConArg;
  81. PFLAG_ARGUMENT ConColonArg;
  82. PSTRING_ARGUMENT StatusArg;
  83. PLONG_ARGUMENT ColArg;
  84. PLONG_ARGUMENT LinesArg;
  85. PFLAG_ARGUMENT CpArg;
  86. PSTRING_ARGUMENT PrepareArg;
  87. PSTRING_ARGUMENT RetryArg;
  88. PFLAG_ARGUMENT EqualArg;
  89. PLONG_ARGUMENT BaudArg;
  90. PSTRING_ARGUMENT ParityArg;
  91. PLONG_ARGUMENT DataArg;
  92. PLONG_ARGUMENT StopArg;
  93. PFLAG_ARGUMENT Stop15Arg;
  94. PLONG_ARGUMENT SelectArg;
  95. PFLAG_ARGUMENT RefreshArg;
  96. PLONG_ARGUMENT RateArg;
  97. PLONG_ARGUMENT DelayArg;
  98. PFLAG_ARGUMENT HelpArg;
  99. //
  100. // The Argument lexemizer and lexeme array.
  101. //
  102. PARGUMENT_LEXEMIZER ArgLex;
  103. PARRAY LexArray;
  104. //
  105. // Some device information so we don't have to be querying the arguments
  106. // all the time.
  107. //
  108. BOOLEAN LptSet;
  109. ULONG LptNumber;
  110. BOOLEAN ComSet;
  111. ULONG ComNumber;
  112. BOOLEAN ConSet;
  113. VOID
  114. AllocateStuff(
  115. );
  116. VOID
  117. DeallocateStuff(
  118. );
  119. PARRAY
  120. GetArgumentArray(
  121. );
  122. VOID
  123. ParseArguments(
  124. IN PARRAY ArgArray
  125. );
  126. PREQUEST_HEADER
  127. MakeRequest(
  128. );
  129. PREQUEST_HEADER
  130. MakeStatusRequest(
  131. );
  132. PREQUEST_HEADER
  133. MakeCodePageRequest(
  134. );
  135. PREQUEST_HEADER
  136. MakeLptRequest(
  137. );
  138. PREQUEST_HEADER
  139. MakeComRequest(
  140. );
  141. PREQUEST_HEADER
  142. MakeConRequest(
  143. );
  144. PREQUEST_HEADER
  145. GetRequest(
  146. )
  147. /*++
  148. Routine Description:
  149. Forms a device request based on the command line arguments.
  150. Arguments:
  151. None.
  152. Return Value:
  153. Pointer to the device request.
  154. Notes:
  155. --*/
  156. {
  157. PARRAY ArgArray;
  158. PREQUEST_HEADER Request;
  159. //
  160. // Get strings from resource messages
  161. //
  162. AllocateStuff();
  163. //
  164. // Get array of arguments
  165. //
  166. ArgArray = GetArgumentArray();
  167. DbgPtrAssert( ArgArray);
  168. //
  169. // Parse the arguments
  170. //
  171. ParseArguments( ArgArray );
  172. //
  173. // Verify the arguments and form a request packet
  174. //
  175. Request = MakeRequest();
  176. DbgPtrAssert( Request );
  177. //
  178. // Deallocate resources
  179. //
  180. DELETE( ArgArray );
  181. DeallocateStuff();
  182. return Request;
  183. }
  184. VOID
  185. AllocateStuff(
  186. )
  187. /*++
  188. Routine Description:
  189. Obtains all necessary strings (e.g. argument patterns, switches) from
  190. message.
  191. Arguments:
  192. None.
  193. Return Value:
  194. None
  195. Notes:
  196. --*/
  197. {
  198. //
  199. // Get strings from resource
  200. //
  201. if ( !( ( LptPattern = QueryMessageString( MODE_PATTERN_LPT )) &&
  202. ( LptColonPattern = QueryMessageString( MODE_PATTERN_LPTCOLON )) &&
  203. ( ComPattern = QueryMessageString( MODE_PATTERN_COM )) &&
  204. ( ComColonPattern = QueryMessageString( MODE_PATTERN_COMCOLON )) &&
  205. ( ConPattern = QueryMessageString( MODE_PATTERN_CON )) &&
  206. ( ConColonPattern = QueryMessageString( MODE_PATTERN_CONCOLON )) &&
  207. ( StatusPattern = QueryMessageString( MODE_PATTERN_STATUS )) &&
  208. ( ColPattern = QueryMessageString( MODE_PATTERN_COLUMNS )) &&
  209. ( LinesPattern = QueryMessageString( MODE_PATTERN_LINES )) &&
  210. ( CpPattern = QueryMessageString( MODE_PATTERN_CODEPAGE )) &&
  211. ( PreparePattern = QueryMessageString( MODE_PATTERN_PREPARE )) &&
  212. ( RetryPattern = QueryMessageString( MODE_PATTERN_RETRY )) &&
  213. ( EqualPattern = QueryMessageString( MODE_PATTERN_EQUAL )) &&
  214. ( BaudPattern = QueryMessageString( MODE_PATTERN_BAUD )) &&
  215. ( ParityPattern = QueryMessageString( MODE_PATTERN_PARITY )) &&
  216. ( DataPattern = QueryMessageString( MODE_PATTERN_DATA )) &&
  217. ( StopPattern = QueryMessageString( MODE_PATTERN_STOP )) &&
  218. ( Stop15Pattern = QueryMessageString( MODE_PATTERN_STOP_15 )) &&
  219. ( SelectPattern = QueryMessageString( MODE_PATTERN_SELECT )) &&
  220. ( RefreshPattern = QueryMessageString( MODE_PATTERN_REFRESH )) &&
  221. ( RatePattern = QueryMessageString( MODE_PATTERN_RATE )) &&
  222. ( DelayPattern = QueryMessageString( MODE_PATTERN_DELAY )) &&
  223. ( HelpPattern = QueryMessageString( MODE_PATTERN_HELP )) &&
  224. ( Switches = QueryMessageString( MODE_SWITCHES )) )) {
  225. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  226. NULL,
  227. EXIT_ERROR );
  228. }
  229. //
  230. // Get argument objects. These are not global because the Create
  231. // method would not be called on them.
  232. //
  233. if ( !( ProgramNameArg = NEW PATH_ARGUMENT) ||
  234. !( LptArg = NEW LONG_ARGUMENT) ||
  235. !( LptColonArg = NEW LONG_ARGUMENT) ||
  236. !( ComArg = NEW LONG_ARGUMENT) ||
  237. !( ComColonArg = NEW LONG_ARGUMENT) ||
  238. !( ConArg = NEW FLAG_ARGUMENT) ||
  239. !( ConColonArg = NEW FLAG_ARGUMENT) ||
  240. !( StatusArg = NEW STRING_ARGUMENT) ||
  241. !( ColArg = NEW LONG_ARGUMENT) ||
  242. !( LinesArg = NEW LONG_ARGUMENT) ||
  243. !( CpArg = NEW FLAG_ARGUMENT) ||
  244. !( PrepareArg = NEW STRING_ARGUMENT) ||
  245. !( RetryArg = NEW STRING_ARGUMENT) ||
  246. !( EqualArg = NEW FLAG_ARGUMENT) ||
  247. !( BaudArg = NEW LONG_ARGUMENT) ||
  248. !( ParityArg = NEW STRING_ARGUMENT) ||
  249. !( DataArg = NEW LONG_ARGUMENT) ||
  250. !( StopArg = NEW LONG_ARGUMENT) ||
  251. !( Stop15Arg = NEW FLAG_ARGUMENT) ||
  252. !( SelectArg = NEW LONG_ARGUMENT) ||
  253. !( RefreshArg = NEW FLAG_ARGUMENT) ||
  254. !( RateArg = NEW LONG_ARGUMENT) ||
  255. !( DelayArg = NEW LONG_ARGUMENT) ||
  256. !( HelpArg = NEW FLAG_ARGUMENT) ) {
  257. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  258. NULL,
  259. EXIT_ERROR );
  260. }
  261. //
  262. // Lexemizer stuff
  263. //
  264. if ( !( ArgLex = NEW ARGUMENT_LEXEMIZER) ||
  265. !( LexArray = NEW ARRAY) ) {
  266. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  267. NULL,
  268. EXIT_ERROR );
  269. }
  270. }
  271. VOID
  272. DeallocateStuff(
  273. )
  274. /*++
  275. Routine Description:
  276. Deletes all the allocated strings.
  277. Arguments:
  278. None.
  279. Return Value:
  280. None
  281. Notes:
  282. --*/
  283. {
  284. //
  285. // The string from the resource
  286. //
  287. DELETE( LptPattern );
  288. DELETE( LptColonPattern );
  289. DELETE( ComPattern );
  290. DELETE( ComColonPattern );
  291. DELETE( ConPattern );
  292. DELETE( ConColonPattern );
  293. DELETE( StatusPattern );
  294. DELETE( ColPattern );
  295. DELETE( LinesPattern );
  296. DELETE( CpPattern );
  297. DELETE( PreparePattern );
  298. DELETE( RetryPattern );
  299. DELETE( EqualPattern );
  300. DELETE( BaudPattern );
  301. DELETE( ParityPattern );
  302. DELETE( DataPattern );
  303. DELETE( StopPattern );
  304. DELETE( SelectPattern );
  305. DELETE( RefreshPattern );
  306. DELETE( RatePattern );
  307. DELETE( DelayPattern );
  308. DELETE( HelpPattern );
  309. DELETE( Switches );
  310. //
  311. // The arguments
  312. //
  313. DELETE( ProgramNameArg );
  314. DELETE( ProgramNameArg );
  315. DELETE( LptArg );
  316. DELETE( LptColonArg );
  317. DELETE( ComArg );
  318. DELETE( ComColonArg );
  319. DELETE( ConArg );
  320. DELETE( ConColonArg );
  321. DELETE( StatusArg );
  322. DELETE( ColArg );
  323. DELETE( LinesArg );
  324. DELETE( CpArg );
  325. DELETE( PrepareArg );
  326. DELETE( RetryArg );
  327. DELETE( EqualArg );
  328. DELETE( BaudArg );
  329. DELETE( ParityArg );
  330. DELETE( DataArg );
  331. DELETE( StopArg );
  332. DELETE( Stop15Arg );
  333. DELETE( SelectArg );
  334. DELETE( RefreshArg );
  335. DELETE( RateArg );
  336. DELETE( DelayArg );
  337. DELETE( HelpArg );
  338. //
  339. // The lexemizer stuff
  340. //
  341. DELETE( ArgLex );
  342. DELETE( LexArray );
  343. }
  344. PARRAY
  345. GetArgumentArray(
  346. )
  347. /*++
  348. Routine Description:
  349. Initializes all the arguments
  350. Arguments:
  351. None.
  352. Return Value:
  353. None
  354. Notes:
  355. --*/
  356. {
  357. PARRAY ArgArray;
  358. if ( !( ( ArgArray = NEW ARRAY ) &&
  359. ( ArgArray->Initialize( 22, 22, 0) ) &&
  360. ( ProgramNameArg->Initialize( "*" )) &&
  361. ( LptArg->Initialize( LptPattern )) &&
  362. ( LptColonArg->Initialize( LptColonPattern )) &&
  363. ( ComArg->Initialize( ComPattern )) &&
  364. ( ComColonArg->Initialize( ComColonPattern )) &&
  365. ( ConArg->Initialize( ConPattern )) &&
  366. ( ConColonArg->Initialize( ConColonPattern )) &&
  367. ( StatusArg->Initialize( StatusPattern )) &&
  368. ( ColArg->Initialize( ColPattern )) &&
  369. ( LinesArg->Initialize( LinesPattern )) &&
  370. ( CpArg->Initialize( CpPattern )) &&
  371. ( PrepareArg->Initialize( PreparePattern )) &&
  372. ( RetryArg->Initialize( RetryPattern )) &&
  373. ( EqualArg->Initialize( EqualPattern )) &&
  374. ( BaudArg->Initialize( BaudPattern )) &&
  375. ( ParityArg->Initialize( ParityPattern )) &&
  376. ( DataArg->Initialize( DataPattern )) &&
  377. ( StopArg->Initialize( StopPattern )) &&
  378. ( Stop15Arg->Initialize( Stop15Pattern )) &&
  379. ( SelectArg->Initialize( SelectPattern )) &&
  380. ( RefreshArg->Initialize( RefreshPattern )) &&
  381. ( RateArg->Initialize( RatePattern )) &&
  382. ( DelayArg->Initialize( DelayPattern )) &&
  383. ( HelpArg->Initialize( HelpPattern )) )) {
  384. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  385. NULL,
  386. EXIT_ERROR );
  387. }
  388. if ( !( ( ArgArray->Put( ProgramNameArg ) ) &&
  389. ( ArgArray->Put( LptColonArg ) ) &&
  390. ( ArgArray->Put( LptArg ) ) &&
  391. ( ArgArray->Put( ComColonArg ) ) &&
  392. ( ArgArray->Put( ComArg ) ) &&
  393. ( ArgArray->Put( ConColonArg ) ) &&
  394. ( ArgArray->Put( ConArg ) ) &&
  395. ( ArgArray->Put( StatusArg ) ) &&
  396. ( ArgArray->Put( ColArg ) ) &&
  397. ( ArgArray->Put( LinesArg ) ) &&
  398. ( ArgArray->Put( CpArg ) ) &&
  399. ( ArgArray->Put( PrepareArg ) ) &&
  400. ( ArgArray->Put( RetryArg ) ) &&
  401. ( ArgArray->Put( EqualArg ) ) &&
  402. ( ArgArray->Put( BaudArg ) ) &&
  403. ( ArgArray->Put( ParityArg ) ) &&
  404. ( ArgArray->Put( DataArg ) ) &&
  405. ( ArgArray->Put( Stop15Arg ) ) &&
  406. ( ArgArray->Put( StopArg ) ) &&
  407. ( ArgArray->Put( SelectArg ) ) &&
  408. ( ArgArray->Put( RefreshArg ) ) &&
  409. ( ArgArray->Put( RateArg ) ) &&
  410. ( ArgArray->Put( DelayArg ) ) &&
  411. ( ArgArray->Put( HelpArg ) ) ) ) {
  412. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  413. NULL,
  414. EXIT_ERROR );
  415. }
  416. return ArgArray;
  417. }
  418. VOID
  419. ParseArguments(
  420. IN PARRAY ArgArray
  421. )
  422. /*++
  423. Routine Description:
  424. Parses the command line
  425. Arguments:
  426. ArgArray - Supplies pointer to array of arguments
  427. Return Value:
  428. none
  429. Notes:
  430. --*/
  431. {
  432. WSTRING CmdLine;
  433. //
  434. // Initialize the argument lexemizer
  435. //
  436. if ( !( CmdLine.Initialize( GetCommandLine() ) &&
  437. LexArray->Initialize( 8, 8, 0) &&
  438. ArgLex->Initialize( LexArray ) ) ) {
  439. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  440. NULL,
  441. EXIT_ERROR );
  442. }
  443. //
  444. // Set our parsing preferences
  445. //
  446. ArgLex->PutSeparators( "," );
  447. ArgLex->PutSwitches( Switches );
  448. ArgLex->SetCaseSensitive( FALSE );
  449. //
  450. // Parse the arguments
  451. //
  452. if ( !(ArgLex->PrepareToParse( &CmdLine ))) {
  453. DisplayMessageAndExit( MODE_ERROR_PARSE,
  454. NULL,
  455. EXIT_ERROR );
  456. }
  457. if ( !ArgLex->DoParsing( ArgArray ) ) {
  458. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  459. ArgLex->QueryInvalidArgument(),
  460. EXIT_ERROR );
  461. }
  462. }
  463. PREQUEST_HEADER
  464. MakeRequest(
  465. )
  466. /*++
  467. Routine Description:
  468. Verifies the parameters and forms a device request.
  469. Arguments:
  470. None.
  471. Return Value:
  472. Pointer to the device request.
  473. Notes:
  474. --*/
  475. {
  476. //
  477. // See if Help requested
  478. //
  479. // MODE [/?]
  480. //
  481. if ( HelpArg->QueryFlag() ) {
  482. DisplayMessageAndExit( MODE_MESSAGE_HELP, NULL, EXIT_ERROR );
  483. }
  484. //
  485. // We cannot have LPT1 and LPT1: at the same time
  486. //
  487. if ( ( LptArg->IsValueSet() && LptColonArg->IsValueSet() ) ||
  488. ( ComArg->IsValueSet() && ComColonArg->IsValueSet() ) ||
  489. ( ConArg->IsValueSet() && ConColonArg->IsValueSet() ) ) {
  490. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  491. NULL,
  492. EXIT_ERROR );
  493. }
  494. //
  495. // Set the global device info. so we don't have to query the
  496. // arguments all the time.
  497. //
  498. if ( LptArg->IsValueSet() ) {
  499. LptSet = TRUE;
  500. LptNumber = (ULONG)LptArg->QueryLong();
  501. }
  502. if ( LptColonArg->IsValueSet() ) {
  503. LptSet = TRUE;
  504. LptNumber = (ULONG)LptColonArg->QueryLong();
  505. }
  506. if ( ComArg->IsValueSet() ) {
  507. ComSet = TRUE;
  508. ComNumber = (ULONG)ComArg->QueryLong();
  509. }
  510. if ( ComColonArg->IsValueSet() ) {
  511. ComSet = TRUE;
  512. ComNumber = (ULONG)ComColonArg->QueryLong();
  513. }
  514. ConSet = (BOOLEAN)(ConArg->IsValueSet() || ConColonArg->IsValueSet());
  515. //
  516. // See if codepage stuff requested
  517. //
  518. // MODE device CP [/STATUS]
  519. // MODE device CP PREPARE=string
  520. // MODE device CP REFRESH
  521. // MODE device CP SELECT=codepage
  522. //
  523. if ( CpArg->QueryFlag() ) {
  524. return MakeCodePageRequest();
  525. }
  526. //
  527. // See if Status requested
  528. //
  529. // MODE [device] [/STATUS]
  530. //
  531. if ( ( ArgLex->QueryConsumedCount() == 1 ) || StatusArg->IsValueSet() ) {
  532. return MakeStatusRequest();
  533. }
  534. //
  535. // See if LPT request
  536. //
  537. // MODE LPTn[:] [COLS=c] [LINES=l] [RETRY=r]
  538. // MODE LPTn[:] = COMm[:]
  539. //
  540. if ( LptSet ) {
  541. return MakeLptRequest();
  542. }
  543. //
  544. // See if COM request
  545. //
  546. // MODE COMm[:] [BAUD=b] [PARITY=p] [DATA=d] [STOP=s] [RETRY=r]
  547. //
  548. if ( ComSet ) {
  549. return MakeComRequest();
  550. }
  551. //
  552. // See if CON request
  553. //
  554. // MODE CON[:] [COLS=c] [LINES=l]
  555. //
  556. // MODE CON[:] [RATE=r DELAY=d]
  557. //
  558. if ( ConSet ) {
  559. return MakeConRequest();
  560. }
  561. //
  562. // The request is incorrect
  563. //
  564. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  565. (PWSTRING)(LexArray->GetAt( 1 )),
  566. EXIT_ERROR );
  567. //
  568. // To keep the compiler happy
  569. //
  570. return NULL;
  571. }
  572. PREQUEST_HEADER
  573. MakeStatusRequest(
  574. )
  575. /*++
  576. Routine Description:
  577. Verifies the parameters and forms a status request.
  578. Arguments:
  579. None.
  580. Return Value:
  581. Pointer to the device request.
  582. Notes:
  583. --*/
  584. {
  585. PREQUEST_HEADER Request;
  586. //
  587. // The maximum number of parameters is 3:
  588. //
  589. // MODE [device] /STATUS
  590. //
  591. if ( ArgLex->QueryConsumedCount() > 3 ) {
  592. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  593. NULL,
  594. EXIT_ERROR );
  595. }
  596. //
  597. // Allocate the request header
  598. //
  599. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) );
  600. DbgPtrAssert( Request );
  601. if ( !Request ) {
  602. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  603. NULL,
  604. EXIT_ERROR );
  605. }
  606. //
  607. // Now initialzie the request according to the device type
  608. //
  609. Request->RequestType = REQUEST_TYPE_STATUS;
  610. if ( LptSet ) {
  611. //
  612. // LPT Status request
  613. //
  614. Request->DeviceType = DEVICE_TYPE_LPT;
  615. Request->DeviceNumber = LptNumber;
  616. } else if ( ComSet ) {
  617. //
  618. // COM Status request
  619. //
  620. Request->DeviceType = DEVICE_TYPE_COM;
  621. Request->DeviceNumber = ComNumber;
  622. } else if ( ConSet ) {
  623. //
  624. // CON Status request
  625. //
  626. Request->DeviceType = DEVICE_TYPE_CON;
  627. Request->DeviceNumber = 0;
  628. } else {
  629. //
  630. // Everybody's status request
  631. //
  632. Request->DeviceType = DEVICE_TYPE_ALL;
  633. Request->DeviceNumber = ALL_DEVICES;
  634. }
  635. return Request;
  636. }
  637. PREQUEST_HEADER
  638. MakeCodePageRequest(
  639. )
  640. /*++
  641. Routine Description:
  642. Verifies the parameters and forms a codepage request.
  643. Arguments:
  644. None.
  645. Return Value:
  646. Pointer to the device request.
  647. Notes:
  648. --*/
  649. {
  650. PREQUEST_HEADER Request;
  651. PCON_REQUEST ConRequest;
  652. //
  653. // Only CON accepts codepage requests.
  654. //
  655. if ( LptSet || ComSet ) {
  656. DisplayMessageAndExit( MODE_ERROR_CODEPAGE_OPERATION_NOT_SUPPORTED,
  657. NULL,
  658. EXIT_ERROR );
  659. }
  660. if ( !ConSet ) {
  661. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  662. (PWSTRING)(LexArray->GetAt( 1 )),
  663. EXIT_ERROR );
  664. }
  665. //
  666. // Form the request depending on the Codepage option
  667. //
  668. if ( RefreshArg->IsValueSet() || PrepareArg->IsValueSet() ) {
  669. //
  670. // REFRESH - This is a NO-OP
  671. // PREPARE - This is a NO-OP
  672. //
  673. if ( ArgLex->QueryConsumedCount() != 4 ) {
  674. //
  675. // Must have 4 arguments:
  676. //
  677. // MODE CON: CP REFRESH
  678. //
  679. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  680. NULL,
  681. EXIT_ERROR );
  682. }
  683. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) );
  684. DbgPtrAssert( Request );
  685. if ( !Request ) {
  686. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  687. NULL,
  688. EXIT_ERROR );
  689. }
  690. Request->RequestType = REQUEST_TYPE_NULL;
  691. Request->DeviceType = DEVICE_TYPE_ALL;
  692. } else if ( SelectArg->IsValueSet() ) {
  693. //
  694. // SELECT
  695. //
  696. if ( ArgLex->QueryConsumedCount() != 4 ) {
  697. //
  698. // Must have 4 arguments:
  699. //
  700. // MODE CON: CP Select=codepage
  701. //
  702. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  703. NULL,
  704. EXIT_ERROR );
  705. }
  706. ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) );
  707. DbgPtrAssert( ConRequest );
  708. if ( !ConRequest ) {
  709. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  710. NULL,
  711. EXIT_ERROR );
  712. }
  713. Request = &(ConRequest->Header);
  714. Request->RequestType = REQUEST_TYPE_CODEPAGE_SELECT;
  715. Request->DeviceType = DEVICE_TYPE_CON;
  716. Request->DeviceNumber = 0;
  717. ConRequest->Data.CpSelect.Codepage = (ULONG)SelectArg->QueryLong();
  718. } else {
  719. //
  720. // STATUS
  721. //
  722. if ( ArgLex->QueryConsumedCount() != (ULONG)(StatusArg->IsValueSet() ? 4 : 3) ) {
  723. // Must have 3 or 4 arguments:
  724. //
  725. // MODE CON: CP [ /STATUS]
  726. //
  727. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  728. NULL,
  729. EXIT_ERROR );
  730. }
  731. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) );
  732. DbgPtrAssert( Request );
  733. if ( !Request ) {
  734. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  735. NULL,
  736. EXIT_ERROR );
  737. }
  738. Request->RequestType = REQUEST_TYPE_CODEPAGE_STATUS;
  739. Request->DeviceType = DEVICE_TYPE_CON;
  740. Request->DeviceNumber = 0;
  741. }
  742. return Request;
  743. }
  744. PREQUEST_HEADER
  745. MakeLptRequest(
  746. )
  747. /*++
  748. Routine Description:
  749. Verifies the parameters and forms an LPT request.
  750. Arguments:
  751. None.
  752. Return Value:
  753. Pointer to the device request.
  754. Notes:
  755. --*/
  756. {
  757. PREQUEST_HEADER Request;
  758. PLPT_REQUEST LptRequest;
  759. ULONG ArgCnt;
  760. //
  761. // Form the request depending on the argument line
  762. //
  763. if ( ArgLex->QueryConsumedCount() == 2 ) {
  764. //
  765. // STATUS
  766. //
  767. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER) );
  768. DbgPtrAssert( Request );
  769. if ( !Request ) {
  770. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  771. NULL,
  772. EXIT_ERROR );
  773. }
  774. Request->RequestType = REQUEST_TYPE_STATUS;
  775. Request->DeviceType = DEVICE_TYPE_LPT;
  776. Request->DeviceNumber = LptNumber;
  777. } else if ( EqualArg->IsValueSet() ) {
  778. //
  779. // REDIRECTION
  780. //
  781. // MODE LPTn[:] = COMm[:]
  782. if ( ArgLex->QueryConsumedCount() != 4 ) {
  783. //
  784. // Must have 4 arguments:
  785. //
  786. // MODE LPT1 = COM1
  787. //
  788. // BUGBUG What happens line is "LPT1=COM1" ?
  789. //
  790. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  791. NULL,
  792. EXIT_ERROR );
  793. }
  794. //
  795. // Can only redirect to COM
  796. //
  797. if ( !ComSet ) {
  798. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  799. (PWSTRING)(LexArray->GetAt( 1 )),
  800. EXIT_ERROR );
  801. }
  802. LptRequest = (PLPT_REQUEST)MALLOC( sizeof( LPT_REQUEST ) );
  803. DbgPtrAssert( LptRequest );
  804. if ( !LptRequest ) {
  805. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  806. NULL,
  807. EXIT_ERROR );
  808. }
  809. Request = &(LptRequest->Header);
  810. Request->RequestType = REQUEST_TYPE_LPT_REDIRECT;
  811. Request->DeviceType = DEVICE_TYPE_LPT;
  812. Request->DeviceNumber = LptNumber;
  813. LptRequest->Data.Redirect.DeviceType = DEVICE_TYPE_COM;
  814. LptRequest->Data.Redirect.DeviceNumber = ComNumber;
  815. } else if ( (ArgCnt = ( ColArg->IsValueSet() ? 1 : 0 ) +
  816. ( LinesArg->IsValueSet() ? 1 : 0 ) +
  817. ( RetryArg->IsValueSet() ? 1 : 0 )) > 0 ) {
  818. //
  819. // SET Lines & Columns
  820. //
  821. if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) {
  822. //
  823. // Must have 2 + ArgCnt arguments:
  824. //
  825. // MODE LPT1: [COLS=c] [LINES=l] [RETRY=r]
  826. //
  827. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  828. NULL,
  829. EXIT_ERROR );
  830. }
  831. LptRequest = (PLPT_REQUEST)MALLOC( sizeof( LPT_REQUEST ) );
  832. DbgPtrAssert( LptRequest );
  833. if ( !LptRequest ) {
  834. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  835. NULL,
  836. EXIT_ERROR );
  837. }
  838. Request = &(LptRequest->Header);
  839. Request->RequestType = REQUEST_TYPE_LPT_SETUP;
  840. Request->DeviceType = DEVICE_TYPE_LPT;
  841. Request->DeviceNumber = LptNumber;
  842. LptRequest->Data.Setup.SetCol = FALSE;
  843. LptRequest->Data.Setup.SetLines = FALSE;
  844. LptRequest->Data.Setup.SetRetry = FALSE;
  845. if ( ColArg->IsValueSet() ) {
  846. LptRequest->Data.Setup.SetCol = TRUE;
  847. LptRequest->Data.Setup.Col = ColArg->QueryLong();
  848. }
  849. if ( LinesArg->IsValueSet() ) {
  850. LptRequest->Data.Setup.SetLines = TRUE;
  851. LptRequest->Data.Setup.Lines = LinesArg->QueryLong();
  852. }
  853. if ( RetryArg->IsValueSet() ) {
  854. LptRequest->Data.Setup.SetRetry = TRUE;
  855. LptRequest->Data.Setup.Retry = 0;
  856. }
  857. } else {
  858. //
  859. // Invalid request
  860. //
  861. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  862. (PWSTRING)(LexArray->GetAt( 1 )),
  863. EXIT_ERROR );
  864. }
  865. return Request;
  866. }
  867. PREQUEST_HEADER
  868. MakeComRequest(
  869. )
  870. /*++
  871. Routine Description:
  872. Verifies the parameters and forms a COM request.
  873. Arguments:
  874. None.
  875. Return Value:
  876. Pointer to the device request.
  877. Notes:
  878. --*/
  879. {
  880. PREQUEST_HEADER Request;
  881. PCOM_REQUEST ComRequest;
  882. ULONG ArgCnt;
  883. if ( ArgLex->QueryConsumedCount() == 2 ) {
  884. //
  885. // Status request
  886. //
  887. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) );
  888. DbgPtrAssert( Request );
  889. if ( !Request ) {
  890. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  891. NULL,
  892. EXIT_ERROR );
  893. }
  894. Request->RequestType = REQUEST_TYPE_STATUS;
  895. Request->DeviceType = DEVICE_TYPE_COM;
  896. Request->DeviceNumber = ComNumber;
  897. } else if ( (ArgCnt = ( BaudArg->IsValueSet() ? 1 : 0 ) +
  898. ( ParityArg->IsValueSet() ? 1 : 0 ) +
  899. ( DataArg->IsValueSet() ? 1 : 0 ) +
  900. ( Stop15Arg->IsValueSet() ? 1 : 0 ) +
  901. ( StopArg->IsValueSet() ? 1 : 0 ) +
  902. ( RetryArg->IsValueSet() ? 1 : 0 )) > 0 ) {
  903. //
  904. // Set COM Configuration
  905. //
  906. if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) {
  907. //
  908. // Must have 2 + ArgCnt arguments:
  909. //
  910. // MODE COM1: [ all options ]
  911. //
  912. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  913. NULL,
  914. EXIT_ERROR );
  915. }
  916. ComRequest = (PCOM_REQUEST)MALLOC( sizeof( COM_REQUEST ) );
  917. DbgPtrAssert( ComRequest );
  918. if ( !ComRequest ) {
  919. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  920. NULL,
  921. EXIT_ERROR );
  922. }
  923. Request = &(ComRequest->Header);
  924. Request->RequestType = REQUEST_TYPE_COM_SET;
  925. Request->DeviceType = DEVICE_TYPE_COM;
  926. Request->DeviceNumber = ComNumber;
  927. ComRequest->Data.Set.SetBaud = FALSE;
  928. ComRequest->Data.Set.SetDataBits = FALSE;
  929. ComRequest->Data.Set.SetStopBits = FALSE;
  930. ComRequest->Data.Set.SetParity = FALSE;
  931. ComRequest->Data.Set.SetRetry = FALSE;
  932. if ( BaudArg->IsValueSet() ) {
  933. ComRequest->Data.Set.SetBaud = TRUE;
  934. ComRequest->Data.Set.Baud = ConvertBaudRate( BaudArg->QueryLong(), ArgLex->GetLexemeAt( BaudArg->GetLexemeIndex()) );
  935. }
  936. if ( DataArg->IsValueSet() ) {
  937. ComRequest->Data.Set.SetDataBits = TRUE;
  938. ComRequest->Data.Set.DataBits = ConvertDataBits( DataArg->QueryLong(), ArgLex->GetLexemeAt( DataArg->GetLexemeIndex()) );
  939. }
  940. if ( Stop15Arg->IsValueSet() ) {
  941. ComRequest->Data.Set.SetStopBits = TRUE;
  942. ComRequest->Data.Set.StopBits = STOPBITS_15;
  943. } else if ( StopArg->IsValueSet() ) {
  944. ComRequest->Data.Set.SetStopBits = TRUE;
  945. ComRequest->Data.Set.StopBits = ConvertStopBits( StopArg->QueryLong(), ArgLex->GetLexemeAt( StopArg->GetLexemeIndex()) );
  946. }
  947. if ( ParityArg->IsValueSet() ) {
  948. ComRequest->Data.Set.SetParity = TRUE;
  949. ComRequest->Data.Set.Parity = ConvertParity( ParityArg->GetString(), ArgLex->GetLexemeAt( ParityArg->GetLexemeIndex()) );
  950. }
  951. if ( RetryArg->IsValueSet() ) {
  952. ComRequest->Data.Set.SetRetry = TRUE;
  953. ComRequest->Data.Set.Retry = ConvertRetry( RetryArg->GetString(), ArgLex->GetLexemeAt( RetryArg->GetLexemeIndex()) );
  954. }
  955. } else {
  956. //
  957. // Invalid request
  958. //
  959. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  960. (PWSTRING)(LexArray->GetAt( 1 )),
  961. EXIT_ERROR );
  962. }
  963. return Request;
  964. }
  965. PREQUEST_HEADER
  966. MakeConRequest(
  967. )
  968. /*++
  969. Routine Description:
  970. Verifies the parameters and forms a CON request.
  971. Arguments:
  972. None.
  973. Return Value:
  974. Pointer to the device request.
  975. Notes:
  976. --*/
  977. {
  978. PREQUEST_HEADER Request;
  979. PCON_REQUEST ConRequest;
  980. ULONG ArgCnt;
  981. if ( ArgLex->QueryConsumedCount() == 2 ) {
  982. //
  983. // Status request
  984. //
  985. Request = (PREQUEST_HEADER)MALLOC( sizeof( REQUEST_HEADER ) );
  986. DbgPtrAssert( Request );
  987. if ( !Request ) {
  988. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  989. NULL,
  990. EXIT_ERROR );
  991. }
  992. Request->RequestType = REQUEST_TYPE_STATUS;
  993. Request->DeviceType = DEVICE_TYPE_CON;
  994. Request->DeviceNumber = 0;
  995. } else if ( (ArgCnt = ( ColArg->IsValueSet() ? 1 : 0 ) +
  996. ( LinesArg->IsValueSet() ? 1 : 0 )) > 0 ) {
  997. //
  998. // Set Lines and Columns
  999. //
  1000. if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) {
  1001. //
  1002. // Must have 2 + ArgCnt arguments:
  1003. //
  1004. // MODE CON: [COLS=c] [ LINES=l]
  1005. //
  1006. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  1007. NULL,
  1008. EXIT_ERROR );
  1009. }
  1010. ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) );
  1011. DbgPtrAssert( ConRequest );
  1012. if ( !ConRequest ) {
  1013. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  1014. NULL,
  1015. EXIT_ERROR );
  1016. }
  1017. Request = &(ConRequest->Header);
  1018. Request->RequestType = REQUEST_TYPE_CON_SET_ROWCOL;
  1019. Request->DeviceType = DEVICE_TYPE_CON;
  1020. Request->DeviceNumber = 0;
  1021. ConRequest->Data.RowCol.SetCol = FALSE;
  1022. ConRequest->Data.RowCol.SetLines = FALSE;
  1023. if ( ColArg->IsValueSet() ) {
  1024. ConRequest->Data.RowCol.SetCol = TRUE;
  1025. ConRequest->Data.RowCol.Col = ColArg->QueryLong();
  1026. }
  1027. if ( LinesArg->IsValueSet() ) {
  1028. ConRequest->Data.RowCol.SetLines = TRUE;
  1029. ConRequest->Data.RowCol.Lines = LinesArg->QueryLong();
  1030. }
  1031. } else if ( (ArgCnt = ( RateArg->IsValueSet() ? 1 : 0 ) +
  1032. ( DelayArg->IsValueSet() ? 1 : 0 )) > 0 ) {
  1033. //
  1034. // Set Typematic rate
  1035. //
  1036. if ( ArgLex->QueryConsumedCount() > (ULONG)(2 + ArgCnt) ) {
  1037. //
  1038. // Must have 2 + ArgCnt arguments:
  1039. //
  1040. // MODE CON: [RATE=r] [DELAY=d]
  1041. //
  1042. DisplayMessageAndExit( MODE_ERROR_INVALID_NUMBER_OF_PARAMETERS,
  1043. NULL,
  1044. EXIT_ERROR );
  1045. }
  1046. ConRequest = (PCON_REQUEST)MALLOC( sizeof( CON_REQUEST ) );
  1047. DbgPtrAssert( ConRequest );
  1048. if ( !ConRequest ) {
  1049. DisplayMessageAndExit( MODE_ERROR_NO_MEMORY,
  1050. NULL,
  1051. EXIT_ERROR );
  1052. }
  1053. Request = &(ConRequest->Header);
  1054. Request->RequestType = REQUEST_TYPE_CON_SET_TYPEMATIC;
  1055. Request->DeviceType = DEVICE_TYPE_CON;
  1056. Request->DeviceNumber = 0;
  1057. ConRequest->Data.Typematic.SetRate = FALSE;
  1058. ConRequest->Data.Typematic.SetDelay = FALSE;
  1059. if ( RateArg->IsValueSet() ) {
  1060. ConRequest->Data.Typematic.SetRate = TRUE;
  1061. ConRequest->Data.Typematic.Rate = RateArg->QueryLong();
  1062. }
  1063. if ( DelayArg->IsValueSet() ) {
  1064. ConRequest->Data.Typematic.SetDelay = TRUE;
  1065. ConRequest->Data.Typematic.Delay = DelayArg->QueryLong();
  1066. }
  1067. } else {
  1068. //
  1069. // Invalid request
  1070. //
  1071. DisplayMessageAndExit( MODE_ERROR_INVALID_PARAMETER,
  1072. (PWSTRING)(LexArray->GetAt( 1 )),
  1073. EXIT_ERROR );
  1074. }
  1075. return Request;
  1076. }
  1077. PREQUEST_HEADER
  1078. MakeRequest(
  1079. )
  1080. /*++
  1081. Routine Description:
  1082. Makes a request and initializes its header
  1083. Arguments:
  1084. None.
  1085. Return Value:
  1086. Pointer to the device request.
  1087. Notes:
  1088. --*/
  1089. {