Windows NT 4.0 source code leak
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.

1565 lines
31 KiB

4 years ago
  1. #include "precomp.h"
  2. #pragma hdrstop
  3. //
  4. // Internal function definitions
  5. //
  6. ARC_STATUS
  7. AlpFreeComponents(
  8. IN PCHAR *EnvVarComponents
  9. );
  10. BOOLEAN
  11. AlpMatchComponent(
  12. IN PCHAR Value1,
  13. IN PCHAR Value2
  14. );
  15. //
  16. // Function implementations
  17. //
  18. ARC_STATUS
  19. AlGetEnvVarComponents (
  20. IN PCHAR EnvValue,
  21. OUT PCHAR **EnvVarComponents,
  22. OUT PULONG PNumComponents
  23. )
  24. /*++
  25. Routine Description:
  26. This routine takes an environment variable string and turns it into
  27. the constituent value strings:
  28. Example EnvValue = "Value1;Value2;Value3" is turned into:
  29. "Value1", "Value2", "Value3"
  30. The following are valid value strings:
  31. 1. " " :one null value is found
  32. 2. ";;;; " :five null values are found
  33. 3. " ;Value1 ; Value2;Value3;;;;;;; ;" :12 value strings are found,
  34. :9 of which are null
  35. If an invalid component (contains embedded white space) is found in the
  36. string then this routine attempts to resynch to the next value, no error
  37. is returned, and a the first part of the invalid value is returned for the
  38. bad component.
  39. 1. " Value1;Bad Value2; Value3" : 2 value strings are found
  40. The value strings returned suppress all whitespace before and after the
  41. value.
  42. Arguments:
  43. EnvValue: ptr to zero terminated environment value string
  44. EnvVarComponents: ptr to a PCHAR * variable to receive the buffer of
  45. ptrs to the constituent value strings.
  46. PNumComponents: ptr to a ULONG to receive the number of value strings found
  47. Return Value:
  48. The function returns the following error codes:
  49. EACCES if EnvValue is NULL
  50. ENOMEM if the memory allocation fails
  51. The function returns the following success codes:
  52. ESUCCESS.
  53. When the function returns ESUCCESS:
  54. - *PNumComponent field gets the number of value strings found
  55. - if the number is non zero the *EnvVarComponents field gets the
  56. ptr to the buffer containing ptrs to value strings
  57. --*/
  58. {
  59. PCHAR pchStart, pchEnd, pchNext;
  60. PCHAR pchComponents[MAX_COMPONENTS + 1];
  61. ULONG NumComponents, i;
  62. PCHAR pch;
  63. ULONG size;
  64. //
  65. // Validate the EnvValue
  66. //
  67. if (EnvValue == NULL) {
  68. return (EACCES);
  69. }
  70. //
  71. // Initialise the ptr array with nulls
  72. //
  73. for (i = 0; i < (MAX_COMPONENTS+1); i++) {
  74. pchComponents[i] = NULL;
  75. }
  76. //
  77. // Initialise ptrs to search components
  78. //
  79. pchStart = EnvValue;
  80. NumComponents = 0;
  81. //
  82. // search till either pchStart reaches the end or till max components
  83. // is reached, the below has been programmed from a dfsa.
  84. //
  85. while (*pchStart && NumComponents < MAX_COMPONENTS) {
  86. //
  87. // STATE 1: find the beginning of next variable value
  88. //
  89. while (*pchStart!=0 && isspace(*pchStart)) {
  90. pchStart++;
  91. }
  92. if (*pchStart == 0) {
  93. break;
  94. }
  95. //
  96. // STATE 2: In the midst of a value
  97. //
  98. pchEnd = pchStart;
  99. while (*pchEnd!=0 && !isspace(*pchEnd) && *pchEnd!=';') {
  100. pchEnd++;
  101. }
  102. //
  103. // STATE 3: spit out the value found
  104. //
  105. size = pchEnd - pchStart;
  106. if ((pch = AlAllocateHeap(size+1)) == NULL) {
  107. AlpFreeComponents(pchComponents);
  108. return (ENOMEM);
  109. }
  110. strncpy (pch, pchStart, size);
  111. pch[size]=0;
  112. pchComponents[NumComponents++]=pch;
  113. //
  114. // STATE 4: variable value end has been reached, find the beginning
  115. // of the next value
  116. //
  117. if ((pchNext = strchr(pchEnd, ';')) == NULL) {
  118. break; // out of the big while loop because we are done
  119. }
  120. //
  121. // Advance beyond the semicolon.
  122. //
  123. pchNext++;
  124. //
  125. // reinitialise to begin STATE 1
  126. //
  127. pchStart = pchNext;
  128. } // end while.
  129. //
  130. // Get memory to hold an environment pointer and return that
  131. //
  132. if ( NumComponents!=0 ) {
  133. PCHAR *pch;
  134. if ((pch = (PCHAR *)AlAllocateHeap((NumComponents+1)*sizeof(PCHAR))) == NULL) {
  135. AlpFreeComponents(pchComponents);
  136. return (ENOMEM);
  137. }
  138. //
  139. // the last one is NULL because we initialised the array with NULLs
  140. //
  141. for ( i = 0; i <= NumComponents; i++) {
  142. pch[i] = pchComponents[i];
  143. }
  144. *EnvVarComponents = pch;
  145. }
  146. //
  147. // Update the number of elements field and return success
  148. //
  149. *PNumComponents = NumComponents;
  150. return (ESUCCESS);
  151. }
  152. ARC_STATUS
  153. AlFreeEnvVarComponents (
  154. IN PCHAR *EnvVarComponents
  155. )
  156. /*++
  157. Routine Description:
  158. This routine frees up all the components in the ptr array and frees
  159. up the storage for the ptr array itself too
  160. Arguments:
  161. EnvVarComponents: the ptr to the PCHAR * Buffer
  162. Return Value:
  163. ESUCCESS if freeing successful
  164. EACCES if memory ptr invalid
  165. --*/
  166. {
  167. ARC_STATUS Status;
  168. //
  169. // if the pointer is NULL just return success
  170. //
  171. if (EnvVarComponents == NULL) {
  172. return (ESUCCESS);
  173. }
  174. //
  175. // free all the components first, if error in freeing return
  176. //
  177. Status = AlpFreeComponents(EnvVarComponents);
  178. if (Status != ESUCCESS) {
  179. return Status;
  180. }
  181. //
  182. // free the component holder too
  183. //
  184. if( AlDeallocateHeap(EnvVarComponents) != NULL) {
  185. return (EACCES);
  186. }
  187. else {
  188. return (ESUCCESS);
  189. }
  190. }
  191. ARC_STATUS
  192. AlpFreeComponents(
  193. IN PCHAR *EnvVarComponents
  194. )
  195. /*++
  196. Routine Description:
  197. This routine frees up only the components in the ptr array, but doesn't
  198. free the ptr array storage itself.
  199. Arguments:
  200. EnvVarComponents: the ptr to the PCHAR * Buffer
  201. Return Value:
  202. ESUCCESS if freeing successful
  203. EACCES if memory ptr invalid
  204. --*/
  205. {
  206. //
  207. // get all the components and free them
  208. //
  209. while (*EnvVarComponents != NULL) {
  210. if(AlDeallocateHeap(*EnvVarComponents++) != NULL) {
  211. return(EACCES);
  212. }
  213. }
  214. return(ESUCCESS);
  215. }
  216. BOOLEAN
  217. AlpMatchComponent(
  218. IN PCHAR Value1,
  219. IN PCHAR Value2
  220. )
  221. /*++
  222. Routine Description:
  223. This routine compares two components to see if they are equal. This is
  224. essentially comparing strings except that leading zeros are stripped from
  225. key values.
  226. Arguments:
  227. Value1 - Supplies a pointer to the first value to match.
  228. Value2 - Supplies a pointer to the second value to match.
  229. Return Value:
  230. If the components match, TRUE is returned, otherwise FALSE is returned.
  231. --*/
  232. {
  233. while ((*Value1 != 0) && (*Value2 != 0)) {
  234. if (tolower(*Value1) != tolower(*Value2)) {
  235. return FALSE;
  236. }
  237. if (*Value1 == '(') {
  238. do {
  239. *Value1++;
  240. } while (*Value1 == '0');
  241. } else {
  242. *Value1++;
  243. }
  244. if (*Value2 == '(') {
  245. do {
  246. *Value2++;
  247. } while (*Value2 == '0');
  248. } else {
  249. *Value2++;
  250. }
  251. }
  252. if ((*Value1 == 0) && (*Value2 == 0)) {
  253. return TRUE;
  254. }
  255. return FALSE;
  256. }
  257. BOOLEAN
  258. AlFindNextMatchComponent(
  259. IN PCHAR EnvValue,
  260. IN PCHAR MatchValue,
  261. IN ULONG StartComponent,
  262. OUT PULONG MatchComponent OPTIONAL
  263. )
  264. /*++
  265. Routine Description:
  266. This routine compares each component of EnvValue, starting with
  267. StartComponent, until a match is found or there are no more components.
  268. Arguments:
  269. EnvValue - Supplies a pointer to the environment variable value.
  270. MatchValue - Supplies a pointer to the value to match.
  271. StartComponent - Supplies the component number to start the match.
  272. MatchComponent - Supplies an optional pointer to a variable to receive
  273. the number of the component that matched.
  274. Return Value:
  275. If a match is found, TRUE is returned, otherwise FALSE is returned.
  276. --*/
  277. {
  278. ARC_STATUS Status;
  279. PCHAR *EnvVarComponents;
  280. ULONG NumComponents;
  281. ULONG Index;
  282. BOOLEAN Match;
  283. Status = AlGetEnvVarComponents(EnvValue, &EnvVarComponents, &NumComponents);
  284. if (Status != ESUCCESS) {
  285. return FALSE;
  286. }
  287. Match = FALSE;
  288. for (Index = StartComponent ; Index < NumComponents ; Index++ ) {
  289. if (AlpMatchComponent(EnvVarComponents[Index], MatchValue)) {
  290. Match = TRUE;
  291. break;
  292. }
  293. }
  294. if (ARGUMENT_PRESENT(MatchComponent)) {
  295. *MatchComponent = Index;
  296. }
  297. AlFreeEnvVarComponents(EnvVarComponents);
  298. return Match;
  299. }
  300. ARC_STATUS
  301. AlAddSystemPartition(
  302. IN PCHAR NewSystemPartition
  303. )
  304. /*++
  305. Routine Description:
  306. This routine adds a system partition to the SystemPartition environment
  307. variable, and updates the Osloader, OsloadPartition, OsloadFilename,
  308. and OsloadOptions variables.
  309. Arguments:
  310. SystemPartition - Supplies a pointer to the pathname of the system
  311. partition to add.
  312. Return Value:
  313. If the system partition was successfully added, ESUCCESS is returned,
  314. otherwise an error code is returned.
  315. BUGBUG - This program is simplistic and doesn't attempt to make sure all
  316. the variables are consistent. It also doesn't fail gracefully.
  317. --*/
  318. {
  319. ARC_STATUS Status;
  320. PCHAR SystemPartition;
  321. CHAR TempValue[MAXIMUM_ENVIRONMENT_VALUE];
  322. //PCHAR Osloader;
  323. //PCHAR OsloadPartition;
  324. //PCHAR OsloadFilename;
  325. //PCHAR OsloadOptions;
  326. //
  327. // Get the system partition environment variable.
  328. //
  329. SystemPartition = ArcGetEnvironmentVariable("SystemPartition");
  330. //
  331. // If the variable doesn't exist, add it and exit.
  332. //
  333. if (SystemPartition == NULL) {
  334. if(strlen(NewSystemPartition) < MAXIMUM_ENVIRONMENT_VALUE) {
  335. Status = ArcSetEnvironmentVariable("SystemPartition",
  336. NewSystemPartition);
  337. } else {
  338. Status = E2BIG;
  339. }
  340. return Status;
  341. }
  342. //
  343. // If the variable exists, add the new partition to the end.
  344. //
  345. if(strlen(SystemPartition)+strlen(NewSystemPartition)+2 > MAXIMUM_ENVIRONMENT_VALUE) {
  346. return(E2BIG);
  347. }
  348. strcpy(TempValue, SystemPartition);
  349. strcat(TempValue, ";");
  350. strcat(TempValue, NewSystemPartition);
  351. Status = ArcSetEnvironmentVariable("SystemPartition",
  352. TempValue);
  353. if (Status != ESUCCESS) {
  354. return Status;
  355. }
  356. #if 0
  357. //
  358. // Add semicolons to the end of each of the associated variables.
  359. // If they don't exist add them.
  360. //
  361. //
  362. // Get the Osloader environment variable and add a semicolon to the end.
  363. //
  364. Osloader = ArcGetEnvironmentVariable("Osloader");
  365. if (Osloader == NULL) {
  366. *TempValue = 0;
  367. } else {
  368. strcpy(TempValue, Osloader);
  369. }
  370. strcat(TempValue, ";");
  371. Status = ArcSetEnvironmentVariable("Osloader",TempValue);
  372. if (Status != ESUCCESS) {
  373. return Status;
  374. }
  375. //
  376. // Get the OsloadPartition environment variable and add a semicolon to the end.
  377. //
  378. OsloadPartition = ArcGetEnvironmentVariable("OsloadPartition");
  379. if (OsloadPartition == NULL) {
  380. *TempValue = 0;
  381. } else {
  382. strcpy(TempValue, OsloadPartition);
  383. }
  384. strcat(TempValue, ";");
  385. Status = ArcSetEnvironmentVariable("OsloadPartition",TempValue);
  386. if (Status != ESUCCESS) {
  387. return Status;
  388. }
  389. //
  390. // Get the OsloadFilename environment variable and add a semicolon to the end.
  391. //
  392. OsloadFilename = ArcGetEnvironmentVariable("OsloadFilename");
  393. if (OsloadFilename == NULL) {
  394. *TempValue = 0;
  395. } else {
  396. strcpy(TempValue, OsloadFilename);
  397. }
  398. strcat(TempValue, ";");
  399. Status = ArcSetEnvironmentVariable("OsloadFilename",TempValue);
  400. if (Status != ESUCCESS) {
  401. return Status;
  402. }
  403. //
  404. // Get the OsloadOptions environment variable and add a semicolon to the end.
  405. //
  406. OsloadOptions = ArcGetEnvironmentVariable("OsloadOptions");
  407. if (OsloadOptions == NULL) {
  408. *TempValue = 0;
  409. } else {
  410. strcpy(TempValue, OsloadOptions);
  411. }
  412. strcat(TempValue, ";");
  413. Status = ArcSetEnvironmentVariable("OsloadOptions",TempValue);
  414. #endif
  415. return Status;
  416. }
  417. typedef struct _tagMENUITEM {
  418. PCHAR Text;
  419. ULONG AssociatedData;
  420. } MENUITEM,*PMENUITEM;
  421. typedef struct _tagMENUCOOKIE {
  422. ULONG ItemCount;
  423. PMENUITEM Items;
  424. } MENUCOOKIE,*PMENUCOOKIE;
  425. // indent for menus, status, etc.
  426. char MARGIN[] = " ";
  427. char MSGMARGIN[] = " ";
  428. // special constants used when fetching keystrokes
  429. #define KEY_UP 1
  430. #define KEY_DOWN 2
  431. VOID
  432. MarkLine(
  433. ULONG Line,
  434. BOOLEAN Selected,
  435. PCHAR String
  436. );
  437. BOOLEAN
  438. CommonMenuDisplay(
  439. PMENUCOOKIE Menu,
  440. BOOLEAN StaticMenu,
  441. PCHAR Items[],
  442. ULONG ItemCount,
  443. BOOLEAN PrintOnly,
  444. ULONG AssociatedDataOfDefaultChoice,
  445. ULONG *AssociatedDataOfChoice,
  446. PCHAR MenuName,
  447. ULONG Row
  448. );
  449. char
  450. GetChar(
  451. VOID
  452. );
  453. BOOLEAN
  454. AlInitializeMenuPackage(
  455. VOID
  456. )
  457. {
  458. return(TRUE);
  459. }
  460. ULONG
  461. AlGetMenuNumberItems(
  462. PVOID MenuID
  463. )
  464. {
  465. return(((PMENUCOOKIE)MenuID)->ItemCount);
  466. }
  467. ULONG
  468. AlGetMenuAssociatedData(
  469. PVOID MenuID,
  470. ULONG n
  471. )
  472. {
  473. return(((PMENUCOOKIE)MenuID)->Items[n].AssociatedData);
  474. }
  475. BOOLEAN
  476. AlNewMenu(
  477. PVOID *MenuID
  478. )
  479. {
  480. PMENUCOOKIE p;
  481. if(!(p = AlAllocateHeap(sizeof(MENUCOOKIE)))) {
  482. return(FALSE);
  483. }
  484. p->ItemCount = 0;
  485. p->Items = NULL;
  486. *MenuID = p;
  487. return(TRUE);
  488. }
  489. VOID
  490. AlFreeMenu(
  491. PVOID MenuID
  492. )
  493. {
  494. PMENUCOOKIE p = MenuID;
  495. ULONG i;
  496. for(i=0; i<p->ItemCount; i++) {
  497. if(p->Items[i].Text != NULL) {
  498. AlDeallocateHeap(p->Items[i].Text);
  499. }
  500. }
  501. if(p->Items) {
  502. AlDeallocateHeap(p->Items);
  503. }
  504. AlDeallocateHeap(p);
  505. }
  506. BOOLEAN
  507. AlAddMenuItem(
  508. PVOID MenuID,
  509. PCHAR Text,
  510. ULONG AssociatedData,
  511. ULONG Attributes // unused
  512. )
  513. {
  514. PMENUCOOKIE Menu = MenuID;
  515. PMENUITEM p;
  516. DBG_UNREFERENCED_PARAMETER(Attributes);
  517. if(!Menu->ItemCount) {
  518. if((Menu->Items = AlAllocateHeap(sizeof(MENUITEM))) == NULL) {
  519. return(FALSE);
  520. }
  521. Menu->ItemCount = 1;
  522. p = Menu->Items;
  523. } else {
  524. if((p = AlReallocateHeap(Menu->Items,sizeof(MENUITEM)*(Menu->ItemCount+1))) == NULL) {
  525. return(FALSE);
  526. }
  527. Menu->Items = p;
  528. p = &Menu->Items[Menu->ItemCount++];
  529. }
  530. if((p->Text = AlAllocateHeap(strlen(Text)+1)) == NULL) {
  531. return(FALSE);
  532. }
  533. strcpy(p->Text,Text);
  534. p->AssociatedData = AssociatedData;
  535. return(TRUE);
  536. }
  537. BOOLEAN
  538. AlAddMenuItems(
  539. PVOID MenuID,
  540. PCHAR Text[],
  541. ULONG ItemCount
  542. )
  543. {
  544. ULONG base,i;
  545. base = AlGetMenuNumberItems(MenuID);
  546. for(i=0; i<ItemCount; i++) {
  547. if(!AlAddMenuItem(MenuID,Text[i],i+base,0)) {
  548. return(FALSE);
  549. }
  550. }
  551. return(TRUE);
  552. }
  553. BOOLEAN
  554. AlDisplayMenu(
  555. PVOID MenuID,
  556. BOOLEAN PrintOnly,
  557. ULONG AssociatedDataOfDefaultChoice,
  558. ULONG *AssociatedDataOfChoice,
  559. ULONG Row,
  560. PCHAR MenuName
  561. )
  562. {
  563. return(CommonMenuDisplay((PMENUCOOKIE)MenuID,
  564. FALSE,
  565. NULL,
  566. ((PMENUCOOKIE)MenuID)->ItemCount,
  567. PrintOnly,
  568. AssociatedDataOfDefaultChoice,
  569. AssociatedDataOfChoice,
  570. MenuName,
  571. Row
  572. )
  573. );
  574. }
  575. BOOLEAN
  576. AlDisplayStaticMenu(
  577. PCHAR Items[],
  578. ULONG ItemCount,
  579. ULONG DefaultChoice,
  580. ULONG Row,
  581. ULONG *IndexOfChoice
  582. )
  583. {
  584. return(CommonMenuDisplay(NULL,
  585. TRUE,
  586. Items,
  587. ItemCount,
  588. FALSE,
  589. DefaultChoice,
  590. IndexOfChoice,
  591. NULL,
  592. Row
  593. )
  594. );
  595. }
  596. BOOLEAN
  597. CommonMenuDisplay(
  598. PMENUCOOKIE Menu,
  599. BOOLEAN StaticMenu,
  600. PCHAR Items[],
  601. ULONG ItemCount,
  602. BOOLEAN PrintOnly,
  603. ULONG AssociatedDataOfDefaultChoice,
  604. ULONG *AssociatedDataOfChoice,
  605. PCHAR MenuName,
  606. ULONG Row
  607. )
  608. {
  609. // ULONG x;
  610. ULONG i,MenuBaseLine,Selection;
  611. char c;
  612. PCHAR String;
  613. AlSetPosition(Row,0);
  614. AlPrint("%cJ",ASCI_CSI); // clear to end of screen.
  615. MenuBaseLine = Row;
  616. AlSetScreenColor(7,4); // white on blue
  617. // if(MenuName) {
  618. // AlPrint("%s%s\r\n%s",MARGIN,MenuName,MARGIN);
  619. // x = strlen(MenuName);
  620. // for(i=0; i<x; i++) {
  621. // AlPrint("-");
  622. // }
  623. // AlPrint("\r\n\r\n");
  624. // MenuBaseLine += 3;
  625. // }
  626. for(i=0; i<ItemCount; i++) {
  627. AlSetScreenAttributes(1,0,0); // hi intensity
  628. AlPrint("%s%s\r\n",MARGIN,StaticMenu ? Items[i] : Menu->Items[i].Text);
  629. }
  630. if(PrintOnly) {
  631. char dummy;
  632. AlPrint("\r\nPress any key to continue.");
  633. AlGetString(&dummy,0);
  634. } else {
  635. // AlPrint("\r\n%sMake Selection using arrow keys and return,\r\n%sor escape to cancel",MARGIN,MARGIN);
  636. Selection = 0;
  637. if(StaticMenu) {
  638. Selection = AssociatedDataOfDefaultChoice;
  639. } else {
  640. for(i=0; i<ItemCount; i++) {
  641. if(Menu->Items[i].AssociatedData == AssociatedDataOfDefaultChoice) {
  642. Selection = i;
  643. break;
  644. }
  645. }
  646. }
  647. String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
  648. MarkLine(MenuBaseLine+Selection,TRUE, String);
  649. while(((c = GetChar()) != ASCI_ESC) && (c != ASCI_LF) && (c != ASCI_CR)) {
  650. String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
  651. MarkLine(MenuBaseLine+Selection,FALSE,String);
  652. if(c == KEY_UP) {
  653. if(!Selection--) {
  654. Selection = ItemCount - 1;
  655. }
  656. } else if(c == KEY_DOWN) {
  657. if(++Selection == ItemCount) {
  658. Selection = 0;
  659. }
  660. }
  661. String = StaticMenu ? Items[Selection] : Menu->Items[Selection].Text;
  662. MarkLine(MenuBaseLine+Selection,TRUE,String);
  663. }
  664. // set cursor to a free place on the screen.
  665. AlSetPosition(MenuBaseLine + ItemCount + 4,0);
  666. if(c == ASCI_ESC) {
  667. return(FALSE);
  668. }
  669. *AssociatedDataOfChoice = StaticMenu ? Selection : Menu->Items[Selection].AssociatedData;
  670. }
  671. return(TRUE);
  672. }
  673. VOID
  674. MarkLine(
  675. ULONG Line,
  676. BOOLEAN Selected,
  677. PCHAR String
  678. )
  679. {
  680. AlSetPosition(Line,sizeof(MARGIN));
  681. if (Selected) {
  682. AlSetScreenAttributes(1,0,1); // hi intensity, Reverse Video
  683. }
  684. AlPrint("%s\r\n", String);
  685. AlSetScreenAttributes(1,0,0); // hi intensity
  686. }
  687. char
  688. GetChar(
  689. VOID
  690. )
  691. {
  692. UCHAR c;
  693. ULONG count;
  694. ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
  695. switch(c) {
  696. // case ASCI_ESC:
  697. // ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
  698. // if(c != '[') {
  699. // break;
  700. // }
  701. case ASCI_CSI:
  702. ArcRead(ARC_CONSOLE_INPUT,&c,1,&count);
  703. switch(c) {
  704. case 'A':
  705. case 'D':
  706. return(KEY_UP);
  707. case 'B':
  708. case 'C':
  709. return(KEY_DOWN);
  710. }
  711. default:
  712. return(c);
  713. }
  714. }
  715. VOID
  716. AlWaitKey(
  717. PCHAR Prompt
  718. )
  719. {
  720. char buff[1];
  721. AlPrint(MSGMARGIN);
  722. AlPrint(Prompt ? Prompt : "Press any key to continue...");
  723. AlGetString(buff,0);
  724. }
  725. VOID
  726. vAlStatusMsg(
  727. IN ULONG Row,
  728. IN BOOLEAN Error,
  729. IN PCHAR FormatString,
  730. IN va_list ArgumentList
  731. )
  732. {
  733. char text[256];
  734. ULONG Length,Count;
  735. AlSetPosition(Row,0);
  736. AlPrint(MSGMARGIN);
  737. Length = vsprintf(text,FormatString,ArgumentList);
  738. if(Error) {
  739. AlSetScreenColor(1,4); // red on blue
  740. } else {
  741. AlSetScreenColor(3,4); // yellow on blue
  742. }
  743. AlSetScreenAttributes(1,0,0); // hi intensity
  744. ArcWrite(ARC_CONSOLE_OUTPUT,text,Length,&Count);
  745. AlPrint("\r\n");
  746. AlSetScreenColor(7,4); // white on blue
  747. AlSetScreenAttributes(1,0,0); // hi intensity
  748. }
  749. VOID
  750. AlStatusMsg(
  751. IN ULONG TopRow,
  752. IN ULONG BottomRow,
  753. IN BOOLEAN Error,
  754. IN PCHAR FormatString,
  755. ...
  756. )
  757. {
  758. va_list ArgList;
  759. va_start(ArgList,FormatString);
  760. vAlStatusMsg(TopRow,Error,FormatString,ArgList);
  761. AlWaitKey(NULL);
  762. AlClearStatusArea(TopRow,BottomRow);
  763. }
  764. VOID
  765. AlStatusMsgNoWait(
  766. IN ULONG TopRow,
  767. IN ULONG BottomRow,
  768. IN BOOLEAN Error,
  769. IN PCHAR FormatString,
  770. ...
  771. )
  772. {
  773. va_list ArgList;
  774. AlClearStatusArea(TopRow,BottomRow);
  775. va_start(ArgList,FormatString);
  776. vAlStatusMsg(TopRow,Error,FormatString,ArgList);
  777. }
  778. VOID
  779. AlClearStatusArea(
  780. IN ULONG TopRow,
  781. IN ULONG BottomRow
  782. )
  783. {
  784. ULONG i;
  785. for(i=BottomRow; i>=TopRow; --i) {
  786. AlSetPosition(i,0);
  787. AlClearLine();
  788. }
  789. }
  790. ARC_STATUS
  791. AlGetMenuSelection(
  792. IN PCHAR szTitle,
  793. IN PCHAR *rgszSelections,
  794. IN ULONG crgsz,
  795. IN ULONG crow,
  796. IN ULONG irgszDefault,
  797. OUT PULONG pirgsz,
  798. OUT PCHAR *pszSelection
  799. )
  800. /*++
  801. Routine Description:
  802. This routine takes an array of strings, turns them into a menu
  803. and gets a selection. If ESC hit then ESUCCESS is returned with
  804. the *pszSelection NULL.
  805. crgsz is assume to be 1 or greater.
  806. Arguments:
  807. szTitle - Pointer to menu title to pass to AlDisplayMenu
  808. prgszSelection - pointer to an array of strings for menu
  809. crgsz - count of strings
  810. irgszDefault - index in rgszSelection to use as default selection
  811. Return Value:
  812. irgsz - index to selection
  813. pszSelection - pointer int rgszSelection for selection. Note that
  814. this is not a dup and should not be freed seperately
  815. then rgszSelections.
  816. Note: if ARC_STATUS == ESUCCESS and pszSelection == NULL then the
  817. menu was successfully displayed but the user hit ESC to select
  818. nothing from the menu.
  819. --*/
  820. {
  821. PVOID hdMenuId;
  822. *pszSelection = NULL;
  823. if (!AlNewMenu(&hdMenuId)) {
  824. return( ENOMEM );
  825. }
  826. //
  827. // BUGBUG for now 1 selection will also build a menu, in the
  828. // future once this is working we should just return that selection
  829. //
  830. if (!AlAddMenuItems(hdMenuId, rgszSelections, crgsz)) {
  831. AlFreeMenu(hdMenuId);
  832. return( ENOMEM );
  833. }
  834. if (!AlDisplayMenu(hdMenuId,
  835. FALSE,
  836. irgszDefault,
  837. pirgsz,
  838. crow,
  839. szTitle)) {
  840. //
  841. // User did not pick a system partition. return NULL
  842. // can caller should abort
  843. //
  844. AlFreeMenu(hdMenuId);
  845. return( ESUCCESS );
  846. }
  847. AlFreeMenu(hdMenuId);
  848. *pszSelection = rgszSelections[*pirgsz];
  849. return( ESUCCESS );
  850. }
  851. PCHAR
  852. AlStrDup(
  853. IN PCHAR szString
  854. )
  855. /*++
  856. Routine Description:
  857. This routine makes a copy of the passed in string. I do not use
  858. the CRT strdup since it uses malloc.
  859. Arguments:
  860. szString - pointer of string to dup.
  861. Return Value:
  862. pointer to dup'd string. NULL if could not allocate
  863. --*/
  864. {
  865. PCHAR szT;
  866. if (szT = AlAllocateHeap(strlen(szString) + 1)) {
  867. strcpy(szT, szString);
  868. return(szT);
  869. }
  870. return( NULL );
  871. }
  872. PCHAR
  873. AlCombinePaths (
  874. IN PCHAR szPath1,
  875. IN PCHAR szPath2
  876. )
  877. /*++
  878. Routine Description:
  879. This routine combines to strings. It allocate a new string
  880. to hold both strings.
  881. Arguments:
  882. pointer to combined path. NULL if failed to allocate.
  883. Return Value:
  884. --*/
  885. {
  886. PCHAR szT;
  887. if (szT = AlAllocateHeap(strlen(szPath1) + strlen(szPath2) + 1)) {
  888. strcpy(szT, szPath1);
  889. strcat(szT, szPath2);
  890. return( szT );
  891. } else {
  892. return ( NULL );
  893. }
  894. }
  895. VOID
  896. AlFreeArray (
  897. IN BOOLEAN fFreeArray,
  898. IN PCHAR *rgsz,
  899. IN ULONG csz
  900. )
  901. /*++
  902. Routine Description:
  903. This routine iterates through an array of pointers to strings freeing
  904. each string and finally the array itself.
  905. Arguments:
  906. fFreeArray - flag wither to free the array itself.
  907. rgsz - pointer to array of strings.
  908. csz - size of array.
  909. Return Value:
  910. --*/
  911. {
  912. ULONG irgsz;
  913. if (!csz) {
  914. return;
  915. }
  916. for( irgsz = 0; irgsz < csz; irgsz++ ) {
  917. if (rgsz[irgsz]) {
  918. AlDeallocateHeap(rgsz[irgsz]);
  919. } else {
  920. break;
  921. }
  922. }
  923. if (fFreeArray) {
  924. AlDeallocateHeap( rgsz );
  925. }
  926. }
  927. ARC_STATUS
  928. AlGetBase (
  929. IN PCHAR szPath,
  930. OUT PCHAR *pszBase
  931. )
  932. /*++
  933. Routine Description:
  934. This routine strips the filename off a path.
  935. Arguments:
  936. szPath - path to strip.
  937. Return Value:
  938. pszBaseh - pointer to buffer holding new base. (this is a copy)
  939. --*/
  940. {
  941. PCHAR szPathT;
  942. //
  943. // Make local copy of szArcInstPath so we can alter it
  944. //
  945. *pszBase = AlStrDup(szPath);
  946. if ( *pszBase == NULL ) {
  947. return( ENOMEM );
  948. }
  949. //
  950. // The start of the path part should be either a \ or a ) where
  951. // ) is the end of the arc name
  952. //
  953. if ((szPathT = strrchr(*pszBase,'\\')) == 0) {
  954. if ((szPathT = strrchr(*pszBase, ')')) == 0) {
  955. AlDeallocateHeap(*pszBase);
  956. return( EBADSYNTAX );
  957. }
  958. }
  959. //
  960. // Cut filename out
  961. //
  962. // szPath points to either ')' or '\' so need to move over that
  963. // onto actual name
  964. //
  965. *(szPathT + 1) = 0;
  966. return( ESUCCESS );
  967. }
  968. //
  969. // Define static data.
  970. //
  971. PCHAR AdapterTypes[AdapterMaximum + 1] = {"eisa","scsi", "multi", NULL};
  972. PCHAR ControllerTypes[ControllerMaximum + 1] = {"cdrom", "disk", NULL};
  973. PCHAR PeripheralTypes[PeripheralMaximum + 1] = {"rdisk", "fdisk", NULL};
  974. PCHAR
  975. AlGetNextArcNamToken (
  976. IN PCHAR TokenString,
  977. OUT PCHAR OutputToken,
  978. OUT PULONG UnitNumber
  979. )
  980. /*++
  981. Routine Description:
  982. This routine scans the specified token string for the next token and
  983. unit number. The token format is:
  984. name[(unit)]
  985. Arguments:
  986. TokenString - Supplies a pointer to a zero terminated token string.
  987. OutputToken - Supplies a pointer to a variable that receives the next
  988. token.
  989. UnitNumber - Supplies a pointer to a variable that receives the unit
  990. number.
  991. Return Value:
  992. If another token exists in the token string, then a pointer to the
  993. start of the next token is returned. Otherwise, a value of NULL is
  994. returned.
  995. --*/
  996. {
  997. //
  998. // If there are more characters in the token string, then parse the
  999. // next token. Otherwise, return a value of NULL.
  1000. //
  1001. if (*TokenString == '\0') {
  1002. return NULL;
  1003. } else {
  1004. while ((*TokenString != '\0') && (*TokenString != '(')) {
  1005. *OutputToken++ = *TokenString++;
  1006. }
  1007. *OutputToken = '\0';
  1008. //
  1009. // If a unit number is specified, then convert it to binary.
  1010. // Otherwise, default the unit number to zero.
  1011. //
  1012. *UnitNumber = 0;
  1013. if (*TokenString == '(') {
  1014. TokenString += 1;
  1015. while ((*TokenString != '\0') && (*TokenString != ')')) {
  1016. *UnitNumber = (*UnitNumber * 10) + (*TokenString++ - '0');
  1017. }
  1018. if (*TokenString == ')') {
  1019. TokenString += 1;
  1020. }
  1021. }
  1022. }
  1023. return TokenString;
  1024. }
  1025. ULONG
  1026. AlMatchArcNamToken (
  1027. IN PCHAR TokenValue,
  1028. IN TOKEN_TYPE TokenType
  1029. )
  1030. /*++
  1031. Routine Description:
  1032. This routine attempts to match a token with an array of possible
  1033. values.
  1034. Arguments:
  1035. TokenValue - Supplies a pointer to a zero terminated token value.
  1036. TokenType - Indicates which type of token we are dealing with
  1037. (AdapterType/ControllerType/PeripheralType)
  1038. Return Value:
  1039. If the token type is invalid, INVALID_TOKEN_TYPE is returned.
  1040. If a token match is not located, then a value INVALID_TOKEN_VALUE
  1041. is returned.
  1042. If a token match is located, then the ENUM value of the token is
  1043. returned.
  1044. --*/
  1045. {
  1046. ULONG Index;
  1047. PCHAR MatchString;
  1048. PCHAR TokenString;
  1049. PCHAR *TokenArray;
  1050. BOOLEAN Found;
  1051. //
  1052. // Depending on token type choose the appropriate token string array
  1053. //
  1054. switch (TokenType) {
  1055. case AdapterType:
  1056. TokenArray = AdapterTypes;
  1057. break;
  1058. case ControllerType:
  1059. TokenArray = ControllerTypes;
  1060. break;
  1061. case PeripheralType:
  1062. TokenArray = PeripheralTypes;
  1063. break;
  1064. default:
  1065. return ((ULONG)INVALID_TOKEN_TYPE);
  1066. }
  1067. //
  1068. // Scan the match array until either a match is found or all of
  1069. // the match strings have been scanned.
  1070. //
  1071. // BUGBUG** The code below can be easily implemented using _strcmpi.
  1072. //
  1073. Index = 0;
  1074. Found = FALSE;
  1075. while (TokenArray[Index] != NULL) {
  1076. MatchString = TokenArray[Index];
  1077. TokenString = TokenValue;
  1078. while ((*MatchString != '\0') && (*TokenString != '\0')) {
  1079. if (toupper(*MatchString) != toupper(*TokenString)) {
  1080. break;
  1081. }
  1082. MatchString += 1;
  1083. TokenString += 1;
  1084. }
  1085. if ((*MatchString == '\0') && (*TokenString == '\0')) {
  1086. Found = TRUE;
  1087. break;
  1088. }
  1089. Index += 1;
  1090. }
  1091. return (Found ? Index : INVALID_TOKEN_VALUE);
  1092. }
  1093. ULONG
  1094. AlPrint (
  1095. PCHAR Format,
  1096. ...
  1097. )
  1098. {
  1099. va_list arglist;
  1100. UCHAR Buffer[256];
  1101. ULONG Count;
  1102. ULONG Length;
  1103. //
  1104. // Format the output into a buffer and then print it.
  1105. //
  1106. va_start(arglist, Format);
  1107. Length = vsprintf(Buffer, Format, arglist);
  1108. ArcWrite( ARC_CONSOLE_OUTPUT, Buffer, Length, &Count);
  1109. va_end(arglist);
  1110. return 0;
  1111. }
  1112. BOOLEAN
  1113. AlGetString(
  1114. OUT PCHAR String,
  1115. IN ULONG StringLength
  1116. )
  1117. /*++
  1118. Routine Description:
  1119. This routine reads a string from standardin until a
  1120. carriage return or escape is found or StringLength is reached.
  1121. Arguments:
  1122. String - Supplies a pointer to where the string will be stored.
  1123. StringLength - Supplies the Max Length to read.
  1124. Return Value:
  1125. FALSE if user pressed esc, TRUE otherwise.
  1126. --*/
  1127. {
  1128. CHAR c;
  1129. ULONG Count;
  1130. PCHAR Buffer;
  1131. Buffer = String;
  1132. while (ArcRead(ARC_CONSOLE_INPUT,&c,1,&Count)==ESUCCESS) {
  1133. if(c == ASCI_ESC) {
  1134. return(FALSE);
  1135. }
  1136. if ((c=='\r') || (c=='\n') || ((ULONG)(Buffer-String) == StringLength)) {
  1137. *Buffer='\0';
  1138. ArcWrite(ARC_CONSOLE_OUTPUT,"\r\n",2,&Count);
  1139. return(TRUE);
  1140. }
  1141. //
  1142. // Check for backspace;
  1143. //
  1144. if (c=='\b') {
  1145. if (((ULONG)Buffer > (ULONG)String)) {
  1146. Buffer--;
  1147. ArcWrite(ARC_CONSOLE_OUTPUT,"\b \b",3,&Count);
  1148. }
  1149. } else {
  1150. //
  1151. // If it's a printable char store it and display it.
  1152. //
  1153. if (isprint(c)) {
  1154. *Buffer++ = c;
  1155. ArcWrite(ARC_CONSOLE_OUTPUT,&c,1,&Count);
  1156. }
  1157. }
  1158. }
  1159. }