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.

4192 lines
113 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. parse.c
  5. Abstract:
  6. This module contains UI code for the OS chooser
  7. Author:
  8. Adam Barr (adamba) 15-May-1997
  9. Revision History:
  10. Geoff Pease (GPease) 28 May 1998 - Major Overhaul to "OSCML" parser
  11. --*/
  12. #ifdef i386
  13. #include "bldrx86.h"
  14. #endif
  15. #if defined(_IA64_)
  16. #include "bldria64.h"
  17. #endif
  18. #include "ctype.h"
  19. #include "stdio.h"
  20. #include "string.h"
  21. #include <netfs.h>
  22. #include "oscheap.h"
  23. #include "parse.h"
  24. #include "hdlsterm.h"
  25. #if 0 && DBG==1
  26. #define _TRACE_FUNC_
  27. #endif
  28. #ifdef _TRACE_FUNC_
  29. #define TraceFunc( _func) { \
  30. CHAR FileLine[80]; \
  31. sprintf( FileLine, "%s(%u)", __FILE__, __LINE__ ); \
  32. DPRINT( OSC, ("%-55s: %s", FileLine, _func) ); \
  33. }
  34. #else
  35. #define TraceFunc( _func )
  36. #endif
  37. #define SCREEN_TOP 2
  38. #ifdef EFI
  39. #define SCREEN_BOTTOM 24
  40. #else
  41. #define SCREEN_BOTTOM 25
  42. #endif
  43. // Special translated character codes
  44. #define CHAR_NBSP ((CHAR)255)
  45. #define MAX_INPUT_BUFFER_LENGTH 1024
  46. #define PRINT(s,l) { ULONG privCount; ArcWrite(BlConsoleOutDeviceId, (s), (l), &privCount); }
  47. #define PRINTL(s) { ULONG privCount; ArcWrite(BlConsoleOutDeviceId, (s), _tcslen(s), &privCount); }
  48. #define BLINK_RATE 5
  49. #define BRACKETS 4 // left and right brackets w/one space each
  50. #define CT_TEXT 0x1
  51. #define CT_PASSWORD 0x2
  52. #define CT_RESET 0x4
  53. #define CT_SELECT 0x8
  54. #define CT_OPTION 0x10
  55. #define CT_LOCAL 0x20
  56. #define CT_VARIABLE 0x40
  57. enum ENCODETYPE {
  58. ET_NONE = 0,
  59. ET_OWF
  60. };
  61. typedef struct {
  62. enum ACTIONS Action;
  63. PCHAR ScreenName;
  64. } KEY_RESPONSE, *LPKEY_RESPONSE;
  65. typedef struct {
  66. void * Next;
  67. enum CONTROLTYPE Type;
  68. } CONTROLSTRUCT, *LPCONTROLSTRUCT;
  69. typedef struct {
  70. void * Next;
  71. int Type;
  72. enum ENCODETYPE Encoding;
  73. int Size;
  74. int MaxLength;
  75. int X;
  76. int Y;
  77. int CurrentPosition;
  78. int FirstVisibleChar;
  79. PCHAR Name;
  80. PCHAR Value;
  81. } INPUTSTRUCT, *LPINPUTSTRUCT;
  82. enum OPTIONFLAGS {
  83. OF_MULTIPLE = 0x01,
  84. OF_SELECTED = 0x02,
  85. };
  86. typedef struct {
  87. void * Next;
  88. enum CONTROLTYPE Type;
  89. enum OPTIONFLAGS Flags;
  90. PCHAR Value;
  91. PCHAR Displayed;
  92. PCHAR Tip;
  93. PCHAR EndTip;
  94. } OPTIONSTRUCT, * LPOPTIONSTRUCT;
  95. typedef struct {
  96. void * Next;
  97. enum CONTROLTYPE Type;
  98. enum OPTIONFLAGS Flags;
  99. int Size;
  100. int X;
  101. int Y;
  102. int Width;
  103. int Timeout;
  104. BOOLEAN AutoSelect;
  105. PCHAR Name;
  106. LPOPTIONSTRUCT FirstVisibleSelection;
  107. LPOPTIONSTRUCT CurrentSelection;
  108. } SELECTSTRUCT, * LPSELECTSTRUCT;
  109. typedef struct {
  110. int X;
  111. int Y;
  112. int LeftMargin;
  113. int RightMargin;
  114. int Size;
  115. } TIPAREA, *LPTIPAREA;
  116. extern const CHAR rghex[]; // "0123456789ABCDEF"
  117. //
  118. // Current Screen Paramaters
  119. //
  120. PCHAR ScreenAttributes;
  121. static CHAR WhiteOnBlueAttributes[] = ";44;37m"; // normal text, white on blue
  122. static CHAR BlackOnBlackAttributes[] = ";40;40m"; // normal text, black on black
  123. int ScreenX;
  124. int ScreenY;
  125. int ScreenBottom;
  126. int LeftMargin;
  127. int RightMargin;
  128. LPKEY_RESPONSE EnterKey;
  129. LPKEY_RESPONSE EscKey;
  130. LPKEY_RESPONSE F1Key;
  131. LPKEY_RESPONSE F3Key;
  132. BOOLEAN PreformattedMode;
  133. BOOLEAN LoginScreen;
  134. BOOLEAN AutoEnter;
  135. BOOLEAN InsertMode;
  136. void * ScreenControls;
  137. enum ACTIONS SpecialAction;
  138. LPTIPAREA TipArea;
  139. #if defined(PLEASE_WAIT)
  140. PCHAR PleaseWaitMsg;
  141. #endif
  142. // 80 spaces, for padding out menu bar highlights.
  143. static TCHAR SpaceString[] =
  144. TEXT(" ");
  145. //
  146. // used to track the type of authentication we should try.
  147. //
  148. ULONG AuthenticationType;
  149. VOID
  150. RomDumpRawData (
  151. IN PUCHAR DataStart,
  152. IN ULONG DataLength,
  153. IN ULONG Offset
  154. );
  155. //
  156. // From regboot.c -- Column and Row are 1-based
  157. //
  158. VOID
  159. BlpPositionCursor(
  160. IN ULONG Column,
  161. IN ULONG Row
  162. );
  163. VOID
  164. BlpClearScreen(
  165. VOID
  166. );
  167. //
  168. // End from regboot.c
  169. //
  170. //
  171. // Gets an integer, using PrevLoc and CurLoc as in BlProcessScreen.
  172. //
  173. UINT
  174. GetInteger(
  175. PCHAR * InputString
  176. )
  177. {
  178. UINT uint;
  179. PCHAR psz;
  180. TraceFunc( "BlpGetInteger()\n" );
  181. uint = 0;
  182. psz = *InputString;
  183. while ((*psz >= '0') && (*psz <= '9')) {
  184. uint = (uint*10) + *psz - '0';
  185. ++psz;
  186. }
  187. *InputString = psz;
  188. //DPRINT( OSC, ("Integer: '%u'\n", tmpInteger) );
  189. return uint;
  190. }
  191. #ifdef EFI
  192. BlpShowCursor(
  193. IN BOOLEAN ShowCursor,
  194. IN TCHAR UnderCharacter
  195. )
  196. {
  197. //bugbug handle "under character"
  198. BlEfiEnableCursor(ShowCursor);
  199. }
  200. VOID
  201. BlpSendEscape(
  202. PCHAR Escape
  203. )
  204. /*++
  205. Routine Description:
  206. Sends an escape to the screen.
  207. Arguments:
  208. None
  209. Return Value:
  210. None.
  211. --*/
  212. {
  213. BlEfiSetAttribute(DEFATT);
  214. BlEfiSetInverseMode(FALSE);
  215. }
  216. VOID
  217. BlpSendEscapeReverse(
  218. PCHAR Escape
  219. )
  220. /*++
  221. Routine Description:
  222. Sends an escape to the screen that reverses the foreground and
  223. background colors of the Escape sequence. All special codes are
  224. retained (codes not in the ranges of 30-37 and 40-47).
  225. Arguments:
  226. Escape - the escape sequence string.
  227. Return Value:
  228. None.
  229. --*/
  230. {
  231. BlEfiSetAttribute(INVATT);
  232. }
  233. VOID
  234. BlpSendEscapeBold(
  235. PCHAR Escape
  236. )
  237. /*++
  238. Routine Description:
  239. Sends an escape to the screen with the additional inverse code.
  240. Arguments:
  241. None
  242. Return Value:
  243. None.
  244. --*/
  245. {
  246. NOTHING;
  247. }
  248. VOID
  249. BlpSendEscapeFlash(
  250. PCHAR Escape
  251. )
  252. /*++
  253. Routine Description:
  254. Sends an escape to the screen with the additional flash code.
  255. Arguments:
  256. None
  257. Return Value:
  258. None.
  259. --*/
  260. {
  261. NOTHING; //there is no flash attribute available under EFI.
  262. }
  263. #else
  264. VOID
  265. BlpSendEscape(
  266. PCHAR Escape
  267. )
  268. /*++
  269. Routine Description:
  270. Sends an escape to the screen.
  271. Arguments:
  272. None
  273. Return Value:
  274. None.
  275. --*/
  276. {
  277. TCHAR Buffer[16];
  278. ULONG Count;
  279. #ifdef _TRACE_FUNC_
  280. TraceFunc("BlpSendEscape( ");
  281. DPRINT( OSC, ("Escape='%s' )\n", Escape) );
  282. #endif
  283. #ifdef UNICODE
  284. _stprintf(Buffer, TEXT("%s%S"), ASCI_CSI_OUT, Escape);
  285. #else
  286. _stprintf(Buffer, TEXT("%s%s"), ASCI_CSI_OUT, Escape);
  287. #endif
  288. PRINTL(Buffer);
  289. }
  290. VOID
  291. BlpSendEscapeReverse(
  292. PCHAR Escape
  293. )
  294. /*++
  295. Routine Description:
  296. Sends an escape to the screen that reverses the foreground and
  297. background colors of the Escape sequence. All special codes are
  298. retained (codes not in the ranges of 30-37 and 40-47).
  299. Arguments:
  300. Escape - the escape sequence string.
  301. Return Value:
  302. None.
  303. --*/
  304. {
  305. TCHAR Buffer[20];
  306. PCHAR CurLoc = Escape;
  307. int Color;
  308. #ifdef _TRACE_FUNC_
  309. TraceFunc( "BlpSendEscapeReverse( " );
  310. DPRINT( OSC, ("Escape='%s' )\n", Escape) );
  311. #endif
  312. if ( Escape == NULL ) {
  313. return; // abort
  314. }
  315. _tcscpy( Buffer, ASCI_CSI_OUT );
  316. //
  317. // Pre-pend the inverse video string for a vt100 terminal
  318. //
  319. if (BlIsTerminalConnected()) {
  320. _stprintf(Buffer, TEXT("%s7"), Buffer);
  321. }
  322. while ( *CurLoc && *CurLoc != 'm' ) {
  323. if ( !( *CurLoc >= '0' && *CurLoc <= '9' ) ) {
  324. CurLoc++;
  325. }
  326. Color = GetInteger( &CurLoc );
  327. if ( Color >=30 && Color <= 37) {
  328. Color += 10;
  329. } else if ( Color >= 40 && Color <= 47 ) {
  330. Color -= 10;
  331. }
  332. _stprintf( Buffer, TEXT("%s;%u"), Buffer, Color );
  333. }
  334. //
  335. // Add trailing 'm'
  336. //
  337. _stprintf( Buffer, TEXT("%sm"), Buffer );
  338. PRINTL( Buffer );
  339. }
  340. VOID
  341. BlpSendEscapeBold(
  342. PCHAR Escape
  343. )
  344. /*++
  345. Routine Description:
  346. Sends an escape to the screen with the additional inverse code.
  347. Arguments:
  348. None
  349. Return Value:
  350. None.
  351. --*/
  352. {
  353. TCHAR Buffer[20];
  354. #ifdef _TRACE_FUNC_
  355. TraceFunc( "BlpSendEscapeBold( " );
  356. DPRINT( OSC, ("Escape='%s' )\n", Escape) );
  357. #endif
  358. _stprintf(Buffer, TEXT("%s;1%s"), ASCI_CSI_OUT, Escape);
  359. PRINTL(Buffer);
  360. }
  361. VOID
  362. BlpSendEscapeFlash(
  363. PCHAR Escape
  364. )
  365. /*++
  366. Routine Description:
  367. Sends an escape to the screen with the additional flash code.
  368. Arguments:
  369. None
  370. Return Value:
  371. None.
  372. --*/
  373. {
  374. TCHAR Buffer[20];
  375. #ifdef _TRACE_FUNC_
  376. TraceFunc( "BlpSendEscapeFlash( " );
  377. DPRINT( OSC, ("Escape='%s' )\n", Escape) );
  378. #endif
  379. _stprintf(Buffer, TEXT("%s;5%s"), ASCI_CSI_OUT, Escape);
  380. PRINTL(Buffer);
  381. }
  382. //
  383. // BlpShowCursor( )
  384. //
  385. VOID
  386. BlpShowCursor(
  387. IN BOOLEAN ShowCursor,
  388. IN TCHAR UnderCharacter )
  389. {
  390. TCHAR Buffer[20];
  391. if (ShowCursor) {
  392. if(InsertMode){
  393. _stprintf(Buffer,TEXT("5%s"),ScreenAttributes);
  394. BlpSendEscapeReverse(Buffer);
  395. }
  396. else{
  397. _stprintf(Buffer,TEXT("5%s"),ScreenAttributes);
  398. BlpSendEscape(Buffer);
  399. }
  400. } else {
  401. _stprintf(Buffer,TEXT("0%s"),ScreenAttributes);
  402. BlpSendEscape(Buffer);
  403. }
  404. if (UnderCharacter) {
  405. PRINT( &UnderCharacter, sizeof(TCHAR));
  406. } else {
  407. if((InsertMode == FALSE )&& ShowCursor){
  408. PRINT(TEXT("_"),sizeof(TCHAR));
  409. return;
  410. }
  411. if(ShowCursor){
  412. PRINT(TEXT(""),sizeof(TCHAR));
  413. return;
  414. }
  415. PRINT(TEXT(" "),sizeof(TCHAR));
  416. }
  417. }
  418. #endif
  419. //
  420. // BlpGetKey()
  421. //
  422. // Calls BlGetKey(), but checks if this screen has "auto-enter"
  423. // turned on in which case it will return an enter key once.
  424. //
  425. ULONG
  426. BlpGetKey(
  427. VOID
  428. )
  429. {
  430. if (AutoEnter) {
  431. return ENTER_KEY;
  432. AutoEnter = FALSE; // only return it once per screen
  433. } else {
  434. return BlGetKey();
  435. }
  436. }
  437. //
  438. // BlpGetKeyWithBlink( )
  439. //
  440. // Displays a blinking cursor as the X,Y coordinates given and awaits
  441. // a key press.
  442. //
  443. ULONG
  444. BlpGetKeyWithBlink(
  445. IN ULONG XLocation,
  446. IN ULONG YLocation,
  447. IN TCHAR UnderCharacter
  448. )
  449. {
  450. ULONG Key = 0;
  451. TraceFunc("BlpGetKeyWithBlink()\n");
  452. BlpPositionCursor(XLocation, YLocation);
  453. BlpShowCursor( TRUE, UnderCharacter );
  454. do {
  455. Key = BlpGetKey();
  456. } while (Key == 0);
  457. BlpPositionCursor(XLocation, YLocation);
  458. BlpShowCursor( FALSE, UnderCharacter );
  459. return Key;
  460. }
  461. //
  462. // BlpPrintString( )
  463. //
  464. // Prints out a large string to the display. It also wraps the text as
  465. // needed.
  466. //
  467. void
  468. BlpPrintString(
  469. IN PCHAR Start,
  470. IN PCHAR End
  471. )
  472. {
  473. PTCHAR Scan;
  474. PTCHAR PrintBuf;
  475. PTCHAR pStart;
  476. PTCHAR pEnd;
  477. ULONG i;
  478. TCHAR TmpChar;
  479. int Length = 0;
  480. DPRINT( OSC, ("BlpPrintString: Start = 0x%08x, End = 0x%08x, Length = %d\n", Start, End, (ULONG)(End - Start)) );
  481. DPRINT( OSC, ("[BlockPrint, Length=%u] '%s'\n", (ULONG)(End - Start), Start) );
  482. while ( Start < End && *Start == 32 )
  483. Start++;
  484. if ( Start == End )
  485. return; // NOP
  486. // Copy the buffer so if something goes wrong, the orginal
  487. // screen will still be intact.
  488. Length = (int)(End - Start);
  489. PrintBuf = (PTCHAR)OscHeapAlloc( Length*sizeof(TCHAR) );
  490. if (!PrintBuf) {
  491. return;
  492. }
  493. for (i = 0; i < (ULONG)Length; i++) {
  494. PrintBuf[i] = (TCHAR)Start[i];
  495. if (PrintBuf[i] & 0x80) {
  496. DPRINT( OSC, ("BlpPrintString: covering non-printable character %04lx\r\n", (USHORT)PrintBuf[i]) );
  497. PrintBuf[i] = (TCHAR)32;
  498. }
  499. }
  500. pStart = PrintBuf;
  501. pEnd = pStart + Length;
  502. BlpPositionCursor( ScreenX, ScreenY );
  503. // See if it is short enough to do the quick route
  504. if ( Length + ScreenX <= RightMargin ) {
  505. #if DBG
  506. {
  507. TmpChar = *pEnd;
  508. *pEnd = 0;
  509. DPRINT( OSC, ("[BlockPrint, Short] '%s'\n", pStart) );
  510. *pEnd = TmpChar;
  511. }
  512. #endif
  513. PRINT( pStart, Length*sizeof(TCHAR) );
  514. ScreenX += Length;
  515. } else {
  516. while( (pStart < pEnd) && (ScreenY <= ScreenBottom) )
  517. {
  518. DPRINT(
  519. OSC,
  520. ("BlpPrintString: About to print a line.\r\n") );
  521. DPRINT(
  522. OSC,
  523. (" pStart: 0x%08lx pEnd: 0x%08lx PrintBuf: 0x%08lx\r\n",
  524. PtrToUint(pStart),
  525. PtrToUint(pEnd),
  526. PtrToUint(PrintBuf)) );
  527. //
  528. // Jump over NULL strings.
  529. //
  530. if( *pStart == TEXT('\0') ) {
  531. pStart++;
  532. break;
  533. }
  534. Length = (ULONG)(pEnd - pStart);
  535. DPRINT( OSC, ("BlpPrint: I think the length of this string is %d\n", Length) );
  536. // do nice wrapping
  537. if ( Length > RightMargin - ScreenX ) {
  538. Length = RightMargin - ScreenX;
  539. DPRINT( OSC, ("BlpPrint: I'm going to truncate the length because it's too big. Now it's %d\n", Length) );
  540. // try to find a "break" character
  541. while ( Length && pStart[Length] != (TCHAR)32 ) {
  542. Length--;
  543. }
  544. DPRINT( OSC, ("BlpPrint: After jumping over the whitespace, it's %d\n", Length) );
  545. // If we can't "break" it, just dump one line's worth
  546. if ( !Length ) {
  547. DPRINT( OSC, ("[BlockPrint Length == 0, Dumping a lines worth]\n") );
  548. Length = RightMargin - ScreenX;
  549. }
  550. }
  551. #if DBG
  552. {
  553. TmpChar = pStart[Length];
  554. pStart[Length] = 0;
  555. #ifdef UNICODE
  556. DPRINT( OSC, ("[BlockPrint, Length=%u] '%ws'\n", Length, pStart) );
  557. #else
  558. DPRINT( OSC, ("[BlockPrint, Length=%u] '%s'\n", Length, pStart) );
  559. #endif
  560. pStart[Length] = TmpChar;
  561. }
  562. #endif
  563. BlpPositionCursor( ScreenX, ScreenY );
  564. PRINT( pStart, Length*sizeof(TCHAR) );
  565. pStart += Length;
  566. while ( pStart <= pEnd && *pStart == 32 )
  567. pStart++;
  568. ScreenX = LeftMargin;
  569. ScreenY++;
  570. }
  571. ScreenY--;
  572. ScreenX += Length;
  573. if ( ScreenY > ScreenBottom ) {
  574. ScreenY = ScreenBottom;
  575. }
  576. }
  577. // If the copy buffer was allocated, free it.
  578. if ( PrintBuf != NULL ) {
  579. OscHeapFree( (PVOID)PrintBuf );
  580. }
  581. }
  582. // **************************************************************************
  583. //
  584. // Lex section
  585. //
  586. // **************************************************************************
  587. //
  588. // Token list for screen parser
  589. //
  590. enum TOKENS {
  591. TOKEN_ENDTAG = 0,
  592. TOKEN_QUOTE,
  593. TOKEN_HTML,
  594. TOKEN_ENDHTML,
  595. TOKEN_META,
  596. TOKEN_SERVER,
  597. TOKEN_KEY,
  598. TOKEN_ENTER,
  599. TOKEN_ESC,
  600. TOKEN_F1,
  601. TOKEN_F3,
  602. TOKEN_HREF,
  603. TOKEN_TITLE,
  604. TOKEN_ENDTITLE,
  605. TOKEN_FOOTER,
  606. TOKEN_ENDFOOTER,
  607. TOKEN_BODY,
  608. TOKEN_ENDBODY,
  609. TOKEN_PRE,
  610. TOKEN_ENDPRE,
  611. TOKEN_FORM,
  612. TOKEN_ENDFORM,
  613. TOKEN_ACTION,
  614. TOKEN_INPUT,
  615. TOKEN_NAME,
  616. TOKEN_INPUTTYPE,
  617. TOKEN_VALUE,
  618. TOKEN_SIZE,
  619. TOKEN_TIP,
  620. TOKEN_MAXLENGTH,
  621. TOKEN_ENCODE,
  622. TOKEN_SELECT,
  623. TOKEN_MULTIPLE,
  624. TOKEN_NOAUTO,
  625. TOKEN_ENDSELECT,
  626. TOKEN_OPTION,
  627. TOKEN_SELECTED,
  628. TOKEN_HELP,
  629. TOKEN_BREAK,
  630. TOKEN_BOLD,
  631. TOKEN_ENDBOLD,
  632. TOKEN_FLASH,
  633. TOKEN_ENDFLASH,
  634. TOKEN_LEFT,
  635. TOKEN_RIGHT,
  636. TOKEN_TIPAREA,
  637. TOKEN_PARAGRAPH,
  638. TOKEN_ENDPARA,
  639. #if defined(PLEASE_WAIT)
  640. TOKEN_WAITMSG,
  641. #endif
  642. TOKEN_INVALID, // end of parsable tokens
  643. TOKEN_TEXT,
  644. TOKEN_START,
  645. TOKEN_EOF, // End of file
  646. };
  647. static struct {
  648. PCHAR name;
  649. int length;
  650. } Tags[] = {
  651. { ">", 1 },
  652. { "\"", 1 },
  653. { "<OSCML", 0 },
  654. { "</OSCML>", 0 },
  655. { "<META", 0 },
  656. { "SERVER", 0 },
  657. { "KEY=", 0 },
  658. { "ENTER", 0 },
  659. { "ESC", 0 },
  660. { "F1", 0 },
  661. { "F3", 0 },
  662. { "HREF=", 0 },
  663. { "<TITLE", 0 },
  664. { "</TITLE>", 0 },
  665. { "<FOOTER", 0 },
  666. { "</FOOTER>", 0 },
  667. { "<BODY", 0 },
  668. { "</BODY>", 0 },
  669. { "<PRE", 0 },
  670. { "</PRE>", 0 },
  671. { "<FORM", 0 },
  672. { "</FORM>", 0 },
  673. { "ACTION=", 0 },
  674. { "<INPUT", 0 },
  675. { "NAME=", 0 },
  676. { "TYPE=", 0 },
  677. { "VALUE=", 0 },
  678. { "SIZE=", 0 },
  679. { "TIP=", 0 },
  680. { "MAXLENGTH=", 0 },
  681. { "ENCODE=", 0 },
  682. { "<SELECT", 0 },
  683. { "MULTIPLE", 0 },
  684. { "NOAUTO", 0 },
  685. { "</SELECT>", 0 },
  686. { "<OPTION", 0 },
  687. { "SELECTED", 0 },
  688. { "HELP=", 0 },
  689. { "<BR", 0 },
  690. { "<BOLD", 0 },
  691. { "</BOLD", 0 },
  692. { "<FLASH", 0 },
  693. { "</FLASH", 0 },
  694. { "LEFT=", 0 },
  695. { "RIGHT=", 0 },
  696. { "<TIPAREA", 0 },
  697. { "<P", 0 },
  698. { "</P", 0 },
  699. #if defined(PLEASE_WAIT)
  700. { "WAITMSG=", 0 },
  701. #endif
  702. { NULL, 0 }, // end of parsable tokens
  703. { "[TEXT]", 0 },
  704. { "[START]", 0 },
  705. { "[EOF]", 0 }
  706. };
  707. //
  708. // Lexstrcmpni( )
  709. //
  710. // Impliments strcmpni( ) for the Lexer.
  711. //
  712. int
  713. Lexstrcmpni(
  714. IN PCHAR pstr1,
  715. IN PCHAR pstr2,
  716. IN int iLength
  717. )
  718. {
  719. while ( iLength && *pstr1 && *pstr2 )
  720. {
  721. CHAR ch1 = *pstr1;
  722. CHAR ch2 = *pstr2;
  723. if ( islower( ch1 ) )
  724. {
  725. ch1 = (CHAR)toupper(ch1);
  726. }
  727. if ( islower( ch2 ) )
  728. {
  729. ch2 = (CHAR)toupper(ch2);
  730. }
  731. if ( ch1 < ch2 )
  732. return -1;
  733. if ( ch1 > ch2 )
  734. return 1;
  735. pstr1++;
  736. pstr2++;
  737. iLength--;
  738. }
  739. return 0;
  740. }
  741. //
  742. // ReplaceSpecialCharacters( &psz );
  743. //
  744. void
  745. ReplaceSpecialCharacters(
  746. IN PCHAR psz)
  747. {
  748. TraceFunc( "ReplaceSpecialCharacters( )\n" );
  749. if ( Lexstrcmpni( psz, "&NBSP", 5 ) == 0 ) {
  750. *psz = CHAR_NBSP; // replace
  751. memmove( psz + 1, psz + 5, strlen(psz) - 4 ); // shift
  752. }
  753. }
  754. #if DBG
  755. // #define LEX_SPEW
  756. #endif
  757. //
  758. // Lex( )
  759. //
  760. // Parses the screen data moving the "InputString" pointer forward and
  761. // returns the token for the text parsed. Spaces are ignored. Illegal
  762. // characters are removed from the screen data. CRs are turned into
  763. // spaces.
  764. //
  765. enum TOKENS
  766. Lex(
  767. IN PCHAR * InputString
  768. )
  769. {
  770. enum TOKENS Tag = TOKEN_TEXT;
  771. PCHAR psz = *InputString;
  772. int iCounter;
  773. #if defined(LEX_SPEW) && defined(_TRACE_FUNC_)
  774. TraceFunc( "Lex( " );
  775. DPRINT( OSC, ("InputString = 0x%08x )\n", *InputString) );
  776. #endif _TRACE_FUNC_
  777. // skip spaces and control characters
  778. if ( PreformattedMode == FALSE )
  779. {
  780. while ( *psz && *psz <= L' ' )
  781. {
  782. if (( *psz != 32 && *psz != '\n' )
  783. || ( psz != *InputString && (*(psz-1)) == 32 )) {
  784. // remove any CR or LFs and any bogus characters
  785. // also remove duplicate spaces in cases like:
  786. //
  787. // This is some text \n\r
  788. // and more text.
  789. //
  790. // If we left it alone it would be printed:
  791. //
  792. // This is some text and more text.
  793. //
  794. memmove( psz, psz + 1, strlen(psz) );
  795. } else {
  796. *psz = 32;
  797. psz++;
  798. }
  799. }
  800. }
  801. if ( *psz == '&' ) {
  802. ReplaceSpecialCharacters( psz );
  803. }
  804. if ( *psz ) {
  805. for ( iCounter = 0; Tags[iCounter].name; iCounter++ )
  806. {
  807. if ( !Tags[iCounter].length ) {
  808. Tags[iCounter].length = strlen( Tags[iCounter].name );
  809. }
  810. if ( Lexstrcmpni( psz, Tags[iCounter].name, Tags[iCounter].length ) == 0 ) {
  811. psz += Tags[iCounter].length;
  812. Tag = iCounter;
  813. break;
  814. }
  815. }
  816. if ( Tag == TOKEN_TEXT )
  817. psz++;
  818. } else {
  819. Tag = TOKEN_EOF;
  820. }
  821. #ifdef LEX_SPEW
  822. {
  823. CHAR tmp = *psz;
  824. *psz = '\0';
  825. DPRINT( OSC, ("[Lex] Parsed String: '%s' Result: %u - '%s'\n", *InputString, Tag, Tags[Tag].name) );
  826. *psz = tmp;
  827. }
  828. #endif
  829. *InputString = psz;
  830. return Tag;
  831. }
  832. //
  833. // GetString( )
  834. //
  835. // Finds and copies a string value from the screen data.
  836. //
  837. PCHAR
  838. GetString(
  839. IN PCHAR * InputString
  840. )
  841. {
  842. CHAR StopChar = 32;
  843. PCHAR ReturnString = NULL;
  844. PCHAR pszBegin = *InputString;
  845. PCHAR pszEnd;
  846. UINT Length;
  847. CHAR tmp;
  848. TraceFunc( "GetString( )\n" );
  849. if ( !pszBegin )
  850. goto e0;
  851. // skip spaces
  852. while ( *pszBegin == 32 )
  853. pszBegin++;
  854. // Check for quoted string
  855. if ( *pszBegin == '\"' ) {
  856. // find the end quote
  857. pszBegin++;
  858. pszEnd = strchr( pszBegin, '\"' );
  859. } else {
  860. // look for a break (space) or end token (">")
  861. PCHAR pszSpace = strchr( pszBegin, ' ' );
  862. PCHAR pszEndToken = strchr( pszBegin, '>' );
  863. if ( !pszSpace ) {
  864. pszEnd = pszEndToken;
  865. } else if ( !pszEndToken ) {
  866. pszEnd = pszSpace;
  867. } else if ( pszEndToken < pszSpace ) {
  868. pszEnd = pszEndToken;
  869. } else {
  870. pszEnd = pszSpace;
  871. }
  872. }
  873. if ( !pszEnd )
  874. goto e0;
  875. tmp = *pszEnd; // save
  876. *pszEnd = '\0'; // terminate
  877. Length = strlen( pszBegin ) + 1;
  878. ReturnString = OscHeapAlloc( Length );
  879. if ( ReturnString ) {
  880. strcpy( ReturnString, pszBegin );
  881. }
  882. *pszEnd = tmp; // restore
  883. DPRINT( OSC, ("[String] %s<-\n", ReturnString) );
  884. *InputString = pszEnd;
  885. e0:
  886. return ReturnString;
  887. }
  888. // **************************************************************************
  889. //
  890. // Parsing States Section
  891. //
  892. // **************************************************************************
  893. //
  894. // TitleTagState( )
  895. //
  896. enum TOKENS
  897. TitleTagState(
  898. IN PCHAR * InputString
  899. )
  900. {
  901. enum TOKENS Tag = TOKEN_START;
  902. PCHAR PageTitle = *InputString;
  903. TraceFunc( "TitleTagState( )\n" );
  904. // ignore tag arguments
  905. for( ; Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  906. PreformattedMode = TRUE;
  907. while ( Tag != TOKEN_EOF )
  908. {
  909. switch (Tag)
  910. {
  911. case TOKEN_EOF:
  912. // something went wrong, assume all this is text
  913. *InputString = PageTitle;
  914. PreformattedMode = FALSE;
  915. return TOKEN_TEXT;
  916. case TOKEN_ENDTAG:
  917. PageTitle = *InputString;
  918. break; // ignore
  919. case TOKEN_ENDTITLE:
  920. {
  921. PCHAR psz = *InputString;
  922. CHAR tmp;
  923. psz -= Tags[Tag].length;
  924. tmp = *psz;
  925. *psz = L'\0';
  926. BlpSendEscapeReverse(ScreenAttributes);
  927. BlpPositionCursor( 1, 1 );
  928. #ifdef _IN_OSDISP_
  929. PRINT( SpaceString, sizeof(SpaceString) - sizeof(TCHAR) );
  930. #else
  931. PRINT( SpaceString, sizeof(SpaceString) );
  932. #endif
  933. if ( PageTitle ) {
  934. BlpPositionCursor( 1, 1 );
  935. DPRINT( OSC, ("[Title] '%s'\n", PageTitle) );
  936. #ifdef UNICODE
  937. {
  938. ULONG i;
  939. WCHAR wc;
  940. for (i = 0; i < strlen(PageTitle) ; i++) {
  941. wc = (WCHAR)PageTitle[i];
  942. PRINT( &wc, sizeof(WCHAR));
  943. }
  944. }
  945. #else
  946. PRINTL( PageTitle );
  947. #endif
  948. }
  949. BlpSendEscape(ScreenAttributes);
  950. *psz = tmp;
  951. PreformattedMode = FALSE;
  952. return Tag; //exit state
  953. }
  954. break;
  955. }
  956. Tag = Lex( InputString );
  957. }
  958. PreformattedMode = FALSE;
  959. return Tag;
  960. }
  961. //
  962. // FooterTagState( )
  963. //
  964. enum TOKENS
  965. FooterTagState(
  966. IN PCHAR * InputString
  967. )
  968. {
  969. enum TOKENS Tag = TOKEN_START;
  970. PCHAR PageFooter = *InputString;
  971. TraceFunc( "FooterTagState( )\n" );
  972. // ignore tag arguments
  973. for( ; Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  974. PreformattedMode = TRUE;
  975. while ( Tag != TOKEN_EOF )
  976. {
  977. switch (Tag)
  978. {
  979. case TOKEN_EOF:
  980. // something went wrong, assume all this is text
  981. *InputString = PageFooter;
  982. PreformattedMode = FALSE;
  983. return TOKEN_TEXT;
  984. case TOKEN_ENDTAG:
  985. PageFooter = *InputString;
  986. break; // ignore
  987. case TOKEN_ENDFOOTER:
  988. {
  989. PCHAR psz = *InputString;
  990. CHAR tmp;
  991. psz -= Tags[Tag].length;
  992. tmp = *psz;
  993. *psz = L'\0';
  994. BlpSendEscapeReverse(ScreenAttributes);
  995. BlpPositionCursor( 1, ScreenBottom );
  996. #ifdef _IN_OSDISP_
  997. PRINT( SpaceString, sizeof(SpaceString) - sizeof(TCHAR) );
  998. #else
  999. //
  1000. // if we're writing to a terminal, we don't want to write into the lower
  1001. // right corner as this would make us scroll.
  1002. //
  1003. PRINT( SpaceString, BlTerminalConnected
  1004. ? (sizeof(SpaceString) - sizeof(TCHAR))
  1005. : sizeof(SpaceString) );
  1006. #endif
  1007. if ( PageFooter ) {
  1008. ULONG iLen;
  1009. BlpPositionCursor( 1, ScreenBottom );
  1010. DPRINT( OSC, ("[Footer] '%s'\n", PageFooter) );
  1011. iLen = strlen(PageFooter);
  1012. if (iLen > 79) {
  1013. iLen = 79;
  1014. }
  1015. #ifdef UNICODE
  1016. {
  1017. ULONG i;
  1018. WCHAR wc;
  1019. for (i = 0; i < iLen ; i++) {
  1020. wc = (WCHAR)PageFooter[i];
  1021. PRINT( &wc, sizeof(WCHAR));
  1022. }
  1023. }
  1024. #else
  1025. PRINT( PageFooter, iLen );
  1026. #endif
  1027. }
  1028. BlpSendEscape(ScreenAttributes);
  1029. *psz = tmp;
  1030. PreformattedMode = FALSE;
  1031. return Tag; //exit state
  1032. }
  1033. break;
  1034. }
  1035. Tag = Lex( InputString );
  1036. }
  1037. PreformattedMode = FALSE;
  1038. return Tag;
  1039. }
  1040. //
  1041. // InputTagState( )
  1042. //
  1043. enum TOKENS
  1044. InputTagState(
  1045. IN PCHAR * InputString
  1046. )
  1047. {
  1048. enum TOKENS Tag = TOKEN_INVALID;
  1049. LPINPUTSTRUCT Input;
  1050. TraceFunc( "InputTagState( )\n" );
  1051. Input = (LPINPUTSTRUCT) OscHeapAlloc( sizeof(INPUTSTRUCT) );
  1052. if ( !Input )
  1053. {
  1054. // get tag arguments
  1055. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  1056. return TOKEN_INVALID;
  1057. }
  1058. RtlZeroMemory( Input, sizeof(INPUTSTRUCT) );
  1059. Input->Type |= CT_TEXT;
  1060. Input->Encoding = ET_NONE;
  1061. Input->X = ScreenX;
  1062. Input->Y = ScreenY;
  1063. // get tag arguments
  1064. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1065. {
  1066. switch( Tag )
  1067. {
  1068. case TOKEN_NAME:
  1069. Input->Name = GetString( InputString );
  1070. if ( Input->Name )
  1071. DPRINT( OSC, ("[Input Name] %s\n", Input->Name) );
  1072. break;
  1073. case TOKEN_VALUE:
  1074. Input->Value = GetString( InputString );
  1075. if ( Input->Value )
  1076. DPRINT( OSC, ("[Input Value] %s\n", Input->Value) );
  1077. break;
  1078. case TOKEN_INPUTTYPE:
  1079. {
  1080. PCHAR pType = GetString( InputString );
  1081. if ( !pType )
  1082. break;
  1083. if ( Lexstrcmpni( pType, "PASSWORD", 8 ) == 0 ) {
  1084. Input->Type = CT_PASSWORD;
  1085. DPRINT( OSC, ("[Input Type] PASSWORD\n") );
  1086. } else if ( Lexstrcmpni( pType, "RESET", 5 ) == 0 ) {
  1087. Input->Type = CT_RESET;
  1088. DPRINT( OSC, ("[Input Type] RESET\n") );
  1089. } else if ( Lexstrcmpni( pType, "TEXT", 4 ) == 0 ) {
  1090. Input->Type = CT_TEXT;
  1091. DPRINT( OSC, ("[Input Type] TEXT\n") );
  1092. } else if ( Lexstrcmpni( pType, "LOCAL", 5 ) == 0 ) {
  1093. DPRINT( OSC, ("[Input Type] LOCAL\n") );
  1094. Input->Type = CT_LOCAL;
  1095. if ( Lexstrcmpni( pType + 5, "PASSWORD", 8 ) == 0 ) {
  1096. Input->Type |= CT_PASSWORD;
  1097. DPRINT( OSC, ("[Input Type] PASSWORD\n") );
  1098. } else if ( Lexstrcmpni( pType + 5, "RESET", 5 ) == 0 ) {
  1099. Input->Type |= CT_RESET;
  1100. DPRINT( OSC, ("[Input Type] RESET\n") );
  1101. } else if ( Lexstrcmpni( pType + 5, "TEXT", 4 ) == 0 ) {
  1102. Input->Type |= CT_TEXT;
  1103. DPRINT( OSC, ("[Input Type] TEXT\n") );
  1104. }
  1105. } else if ( Lexstrcmpni( pType, "VARIABLE", 8 ) == 0) {
  1106. Input->Type = CT_VARIABLE;
  1107. DPRINT( OSC, ("[Input Type] VARIABLE\n") );
  1108. }
  1109. OscHeapFree( pType );
  1110. }
  1111. break;
  1112. case TOKEN_SIZE:
  1113. {
  1114. PCHAR psz = GetString( InputString );
  1115. if ( psz ) {
  1116. PCHAR pszOld = psz; // save because GetInteger modifies
  1117. Input->Size = GetInteger( &psz );
  1118. OscHeapFree( pszOld );
  1119. DPRINT( OSC, ("[Input Size] %u\n", Input->Size) );
  1120. }
  1121. }
  1122. break;
  1123. case TOKEN_MAXLENGTH:
  1124. {
  1125. PCHAR psz = GetString( InputString );
  1126. if ( psz ) {
  1127. PUCHAR pTmpSz = psz;
  1128. Input->MaxLength = GetInteger( &pTmpSz );
  1129. if ( Input->MaxLength > MAX_INPUT_BUFFER_LENGTH - 1 ) {
  1130. Input->MaxLength = MAX_INPUT_BUFFER_LENGTH - 1;
  1131. }
  1132. OscHeapFree( psz );
  1133. DPRINT( OSC, ("[Input MaxLength] %u\n", Input->MaxLength) );
  1134. }
  1135. }
  1136. break;
  1137. case TOKEN_ENCODE:
  1138. {
  1139. PCHAR pType = GetString( InputString );
  1140. if ( !pType )
  1141. break;
  1142. if ( Lexstrcmpni( pType, "YES", 3 ) == 0 ) {
  1143. Input->Encoding = ET_OWF;
  1144. DPRINT( OSC, ("[Encoding Type] OWF\n") );
  1145. }
  1146. OscHeapFree( pType );
  1147. }
  1148. break;
  1149. case TOKEN_EOF:
  1150. return Tag;
  1151. }
  1152. }
  1153. // add the control to the list of controls
  1154. Input->Next = ScreenControls;
  1155. ScreenControls = Input;
  1156. if ( Input->Size + BRACKETS > RightMargin - ScreenX ) {
  1157. Input->Size = 0; // too big, so auto figure
  1158. }
  1159. // adjust screen coordinates
  1160. if ( !Input->Size && Input->MaxLength ) {
  1161. // figure out how much is left of the line, choose the smaller
  1162. Input->Size = ( (RightMargin - ScreenX) - BRACKETS < Input->MaxLength ?
  1163. (RightMargin - ScreenX) - BRACKETS : Input->MaxLength );
  1164. } else if ( !Input->Size ) {
  1165. // assume the input is going to take the whole line
  1166. Input->Size = (RightMargin - ScreenX) - BRACKETS;
  1167. }
  1168. if ( Input->Size > Input->MaxLength ) {
  1169. Input->Size = Input->MaxLength;
  1170. }
  1171. if ((Input->Type & CT_VARIABLE) == 0) {
  1172. ScreenX += Input->Size + BRACKETS + 1;
  1173. }
  1174. if ( ScreenX >= RightMargin ) {
  1175. ScreenX = LeftMargin;
  1176. ScreenY++;
  1177. }
  1178. if ( ScreenY > ScreenBottom )
  1179. ScreenY = ScreenBottom;
  1180. // display any predefined values
  1181. if ( Input->Value ) {
  1182. int Length = strlen(Input->Value);
  1183. if ((Input->Type & CT_VARIABLE) == 0) {
  1184. if ( Length > Input->Size ) {
  1185. Length = Input->Size;
  1186. }
  1187. if (Input->Type & CT_PASSWORD) {
  1188. int i;
  1189. BlpPositionCursor( Input->X + 2, Input->Y );
  1190. for( i = 0; i < Length; i ++ )
  1191. {
  1192. PRINT( TEXT("*"), 1*sizeof(TCHAR) );
  1193. }
  1194. } else {
  1195. BlpPositionCursor( Input->X + 2, Input->Y );
  1196. #ifdef UNICODE
  1197. {
  1198. int i;
  1199. WCHAR wc;
  1200. for (i = 0; i< Length; i++) {
  1201. wc = (WCHAR)(Input->Value)[i];
  1202. PRINT( &wc, 1*sizeof(WCHAR));
  1203. }
  1204. }
  1205. #else
  1206. PRINT( Input->Value, Length );
  1207. #endif
  1208. }
  1209. }
  1210. }
  1211. return Tag;
  1212. }
  1213. //
  1214. // OptionTagState( )
  1215. //
  1216. enum TOKENS
  1217. OptionTagState(
  1218. IN PCHAR * InputString
  1219. )
  1220. {
  1221. enum TOKENS Tag = TOKEN_INVALID;
  1222. LPOPTIONSTRUCT Option;
  1223. PCHAR pszBegin, pszEnd;
  1224. ULONG Length;
  1225. TraceFunc( "OptionTagState( )\n" );
  1226. Option = (LPOPTIONSTRUCT) OscHeapAlloc( sizeof(OPTIONSTRUCT) );
  1227. if ( !Option )
  1228. {
  1229. // get tag arguments
  1230. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  1231. return TOKEN_INVALID;
  1232. }
  1233. RtlZeroMemory( Option, sizeof(OPTIONSTRUCT) );
  1234. Option->Type |= CT_OPTION;
  1235. // get tag arguments
  1236. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1237. {
  1238. switch( Tag )
  1239. {
  1240. case TOKEN_VALUE:
  1241. Option->Value = GetString( InputString );
  1242. if ( Option->Value )
  1243. DPRINT( OSC, ("[Options Value] %s\n", Option->Value) );
  1244. break;
  1245. case TOKEN_SELECTED:
  1246. DPRINT( OSC, ("[Option] SELECTED\n") );
  1247. Option->Flags = OF_SELECTED;
  1248. break;
  1249. case TOKEN_TIP:
  1250. Option->Tip = GetString( InputString );
  1251. if ( Option->Tip ) {
  1252. PCHAR psz = Option->Tip;
  1253. Option->EndTip = &Option->Tip[strlen(Option->Tip)];
  1254. // strip CRs and LFs from tip
  1255. while ( psz < Option->EndTip )
  1256. {
  1257. if ( (*psz == '\r') ||
  1258. ((*psz < 32) && ((psz == Option->Tip) || (*(psz-1) == ' '))) )
  1259. { // remove control codes that follows spaces and all CRs
  1260. memmove( psz, psz+1, strlen(psz) );
  1261. Option->EndTip--;
  1262. }
  1263. else
  1264. {
  1265. if ( *psz < 32 )
  1266. { // turn control codes into spaces
  1267. *psz = 32;
  1268. }
  1269. psz++;
  1270. }
  1271. }
  1272. DPRINT( OSC, ("[Option Tip] %s\n", Option->Tip) );
  1273. }
  1274. break;
  1275. case TOKEN_EOF:
  1276. return Tag;
  1277. }
  1278. }
  1279. // get the option title - at this point Tag == TOKEN_ENDTAG
  1280. pszBegin = *InputString;
  1281. for(Tag = Lex( InputString ) ; Tag != TOKEN_EOF; Tag = Lex( InputString ) )
  1282. {
  1283. BOOLEAN ExitLoop = FALSE;
  1284. switch( Tag )
  1285. {
  1286. case TOKEN_HTML:
  1287. case TOKEN_ENDHTML:
  1288. case TOKEN_META:
  1289. case TOKEN_TITLE:
  1290. case TOKEN_ENDTITLE:
  1291. case TOKEN_FOOTER:
  1292. case TOKEN_ENDFOOTER:
  1293. case TOKEN_BODY:
  1294. case TOKEN_ENDBODY:
  1295. case TOKEN_PRE:
  1296. case TOKEN_ENDPRE:
  1297. case TOKEN_FORM:
  1298. case TOKEN_ENDFORM:
  1299. case TOKEN_INPUT:
  1300. case TOKEN_SELECT:
  1301. case TOKEN_ENDSELECT:
  1302. case TOKEN_OPTION:
  1303. case TOKEN_BREAK:
  1304. case TOKEN_TIPAREA:
  1305. case TOKEN_PARAGRAPH:
  1306. case TOKEN_ENDPARA:
  1307. case TOKEN_INVALID:
  1308. ExitLoop = TRUE;
  1309. break;
  1310. }
  1311. if ( ExitLoop == TRUE )
  1312. break;
  1313. }
  1314. pszEnd = (*InputString) - Tags[Tag].length;
  1315. // try to take the crud and extra spaces off the end
  1316. while ( pszEnd > pszBegin && *pszEnd <= 32 )
  1317. pszEnd--;
  1318. if ( pszEnd == pszBegin ) {
  1319. pszEnd = (*InputString) - Tags[Tag].length;
  1320. }
  1321. Length = PtrToUint((PVOID)(pszEnd - pszBegin));
  1322. Option->Displayed = OscHeapAlloc( Length + 1 );
  1323. if ( Option->Displayed ) {
  1324. CHAR tmp = *pszEnd; // save
  1325. *pszEnd = '\0'; // terminate
  1326. strcpy( Option->Displayed, pszBegin );
  1327. *pszEnd = tmp; // restore
  1328. DPRINT( OSC, ("[Option Name] %s\n", Option->Displayed) );
  1329. // add the control to the list of controls
  1330. Option->Next = ScreenControls;
  1331. ScreenControls = Option;
  1332. } else {
  1333. // remove it since there is nothing to display
  1334. if ( Option->Tip )
  1335. OscHeapFree( Option->Tip );
  1336. if ( Option->Value )
  1337. OscHeapFree( Option->Value );
  1338. OscHeapFree( (void *)Option );
  1339. }
  1340. return Tag;
  1341. }
  1342. //
  1343. // SelectTagState( )
  1344. //
  1345. enum TOKENS
  1346. SelectTagState(
  1347. IN PCHAR * InputString
  1348. )
  1349. {
  1350. enum TOKENS Tag = TOKEN_INVALID;
  1351. LPSELECTSTRUCT Select;
  1352. TraceFunc( "SelectTagState( )\n" );
  1353. Select = (LPSELECTSTRUCT) OscHeapAlloc( sizeof(SELECTSTRUCT) );
  1354. if ( !Select )
  1355. {
  1356. // get tag arguments
  1357. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  1358. return TOKEN_INVALID;
  1359. }
  1360. RtlZeroMemory( Select, sizeof(SELECTSTRUCT) );
  1361. Select->Type |= CT_SELECT;
  1362. Select->X = ScreenX;
  1363. Select->Y = ScreenY;
  1364. Select->Size = 1;
  1365. Select->AutoSelect = TRUE;
  1366. // get tag arguments
  1367. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1368. {
  1369. switch( Tag )
  1370. {
  1371. case TOKEN_NAME:
  1372. Select->Name = GetString( InputString );
  1373. if ( Select->Name )
  1374. DPRINT( OSC, ("[Select Name] %s\n", Select->Name) );
  1375. break;
  1376. case TOKEN_MULTIPLE:
  1377. DPRINT( OSC, ("[Select] MULTIPLE\n") );
  1378. Select->Flags = OF_MULTIPLE;
  1379. break;
  1380. case TOKEN_NOAUTO:
  1381. DPRINT( OSC, ("[Select] NOAUTO\n") );
  1382. Select->AutoSelect = FALSE;
  1383. break;
  1384. case TOKEN_SIZE:
  1385. {
  1386. PCHAR psz = GetString( InputString );
  1387. if ( psz ) {
  1388. PCHAR pszOld = psz; // save because GetInteger modifies
  1389. Select->Size = GetInteger( &psz );
  1390. OscHeapFree( pszOld );
  1391. DPRINT( OSC, ("[Select Size] %u\n", Select->Size) );
  1392. }
  1393. }
  1394. break;
  1395. case TOKEN_EOF:
  1396. return Tag;
  1397. }
  1398. }
  1399. // add the control to the list of controls
  1400. Select->Next = ScreenControls;
  1401. ScreenControls = Select;
  1402. while( Tag != TOKEN_ENDSELECT && Tag != TOKEN_EOF )
  1403. {
  1404. switch( Tag )
  1405. {
  1406. case TOKEN_OPTION:
  1407. {
  1408. LPOPTIONSTRUCT Option;
  1409. Tag = OptionTagState( InputString );
  1410. Option = ScreenControls;
  1411. if ( Option->Type & CT_OPTION ) {
  1412. if ( Option->Displayed ) {
  1413. int Length = strlen( Option->Displayed ) + 1;
  1414. if ( Select->Width < Length ) {
  1415. Select->Width = Length;
  1416. }
  1417. }
  1418. if ( Option->Flags == OF_SELECTED ) {
  1419. Select->CurrentSelection = Option;
  1420. if ( Select->Flags != OF_MULTIPLE )
  1421. {
  1422. Option->Flags = 0;
  1423. }
  1424. }
  1425. }
  1426. }
  1427. break;
  1428. default:
  1429. Tag = Lex( InputString );
  1430. }
  1431. }
  1432. // adjust screen coordinates
  1433. ScreenY += Select->Size;
  1434. if ( ScreenY > ScreenBottom ) {
  1435. Select->Size -= ScreenY - ScreenBottom;
  1436. ScreenY = ScreenBottom;
  1437. }
  1438. return Tag;
  1439. }
  1440. //
  1441. // PreformattedPrint( )
  1442. //
  1443. void
  1444. PreformattedPrint(
  1445. IN PCHAR Start,
  1446. IN PCHAR End
  1447. )
  1448. {
  1449. #ifdef _TRACE_FUNC_
  1450. TraceFunc( "PreformattedPrint( " );
  1451. DPRINT( OSC, ("Start = 0x%08x, End = 0x%08x )\n", Start, End) );
  1452. #endif
  1453. BlpPositionCursor( ScreenX, ScreenY );
  1454. while ( Start < End )
  1455. {
  1456. int Length, OldLength;
  1457. while ( Start < End && (*Start == '\r' || *Start == '\n') )
  1458. {
  1459. if ( *Start == '\r' ) {
  1460. ScreenX = LeftMargin;
  1461. }
  1462. if ( *Start == '\n' ) {
  1463. ScreenY++;
  1464. if ( ScreenY > ScreenBottom ) {
  1465. ScreenY = ScreenBottom;
  1466. }
  1467. }
  1468. Start++;
  1469. }
  1470. Length = PtrToUint((PVOID)(End - Start));
  1471. if ( !Length )
  1472. continue; // nothing to print
  1473. // trunk if needed
  1474. if ( Length > RightMargin - ScreenX ) {
  1475. Length = RightMargin - ScreenX;
  1476. }
  1477. // try to find a "break" character
  1478. OldLength = Length;
  1479. while ( Length && Start[Length] != '\r' && Start[Length] != '\n' )
  1480. Length--;
  1481. // If we can't "break" it, just dump one line's worth
  1482. if ( !Length ) {
  1483. DPRINT( OSC, ("[FormattedPrint, Length == 0, Dumping a lines worth]\n") );
  1484. Length = OldLength;
  1485. }
  1486. #if DBG
  1487. {
  1488. CHAR tmp = Start[Length];
  1489. Start[Length] = 0;
  1490. DPRINT( OSC, ("[FormattedPrint, Length=%u] '%s'\n", Length, Start) );
  1491. Start[Length] = tmp;
  1492. }
  1493. #endif
  1494. BlpPositionCursor( ScreenX, ScreenY );
  1495. #ifdef UNICODE
  1496. {
  1497. int i;
  1498. WCHAR wc;
  1499. for (i = 0; i < Length; i++) {
  1500. wc = (WCHAR) Start[i];
  1501. PRINT( &wc, 1*sizeof(WCHAR));
  1502. }
  1503. }
  1504. #else
  1505. PRINT( Start, Length );
  1506. #endif
  1507. ScreenX += Length;
  1508. while ( Start < End && *Start != '\r' && *Start != '\n' )
  1509. Start++;
  1510. }
  1511. }
  1512. //
  1513. // PreTagState( )
  1514. //
  1515. enum TOKENS
  1516. PreTagState(
  1517. IN PCHAR * InputString
  1518. )
  1519. {
  1520. enum TOKENS Tag = TOKEN_START;
  1521. PCHAR psz = *InputString;
  1522. TraceFunc( "PreTagState( )\n" );
  1523. // get tag arguments
  1524. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1525. {
  1526. switch( Tag )
  1527. {
  1528. case TOKEN_LEFT:
  1529. psz = *InputString;
  1530. // skip any spaces
  1531. while( *psz && *psz == 32 )
  1532. psz++;
  1533. *InputString = psz;
  1534. LeftMargin = GetInteger( InputString );
  1535. DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
  1536. break;
  1537. case TOKEN_RIGHT:
  1538. psz = *InputString;
  1539. // skip any spaces
  1540. while( *psz && *psz == 32 )
  1541. psz++;
  1542. *InputString = psz;
  1543. RightMargin = GetInteger( InputString );
  1544. DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
  1545. break;
  1546. case TOKEN_EOF:
  1547. return Tag;
  1548. }
  1549. }
  1550. if ( ScreenX >= RightMargin ) {
  1551. ScreenY++;
  1552. if ( ScreenY > ScreenBottom ) {
  1553. ScreenY = ScreenBottom;
  1554. }
  1555. }
  1556. if ( ScreenX >= RightMargin || ScreenX < LeftMargin ) {
  1557. ScreenX = LeftMargin;
  1558. }
  1559. PreformattedMode = TRUE;
  1560. psz = *InputString;
  1561. while ( Tag != TOKEN_EOF )
  1562. {
  1563. switch (Tag)
  1564. {
  1565. case TOKEN_ENDPRE:
  1566. case TOKEN_ENDHTML:
  1567. case TOKEN_ENDBODY:
  1568. PreformattedPrint( psz, (*InputString) - Tags[Tag].length );
  1569. PreformattedMode = FALSE;
  1570. return Tag; // exit state
  1571. // just print everything else
  1572. default:
  1573. PreformattedPrint( psz, *InputString );
  1574. psz = *InputString;
  1575. Tag = Lex( InputString );
  1576. break;
  1577. }
  1578. }
  1579. PreformattedMode = FALSE;
  1580. return Tag;
  1581. }
  1582. //
  1583. // TipAreaTagState( )
  1584. //
  1585. enum TOKENS
  1586. TipAreaTagState(
  1587. IN PCHAR * InputString
  1588. )
  1589. {
  1590. enum TOKENS Tag = TOKEN_START;
  1591. PCHAR psz = *InputString;
  1592. TraceFunc( "TipAreaTagState( )\n" );
  1593. if ( !TipArea ) {
  1594. TipArea = (LPTIPAREA) OscHeapAlloc( sizeof(TIPAREA) );
  1595. if ( !TipArea )
  1596. {
  1597. // get tag arguments
  1598. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
  1599. return TOKEN_INVALID;
  1600. }
  1601. }
  1602. TipArea->X = ScreenX;
  1603. TipArea->Y = ScreenY;
  1604. TipArea->LeftMargin = LeftMargin;
  1605. TipArea->RightMargin = RightMargin;
  1606. TipArea->Size = ScreenBottom - ScreenY;
  1607. // get tag arguments
  1608. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1609. {
  1610. switch( Tag )
  1611. {
  1612. case TOKEN_LEFT:
  1613. psz = *InputString;
  1614. // skip any spaces
  1615. while( *psz && *psz == 32 )
  1616. psz++;
  1617. *InputString = psz;
  1618. TipArea->LeftMargin = GetInteger( InputString );
  1619. DPRINT( OSC, ("[TipArea LeftMargin = %u]\n", TipArea->LeftMargin) );
  1620. break;
  1621. case TOKEN_RIGHT:
  1622. psz = *InputString;
  1623. // skip any spaces
  1624. while( *psz && *psz == 32 )
  1625. psz++;
  1626. *InputString = psz;
  1627. TipArea->RightMargin = GetInteger( InputString );
  1628. DPRINT( OSC, ("[TipArea RightMargin = %u]\n", TipArea->RightMargin) );
  1629. break;
  1630. case TOKEN_SIZE:
  1631. psz = *InputString;
  1632. // skip any spaces
  1633. while( *psz && *psz == 32 )
  1634. psz++;
  1635. *InputString = psz;
  1636. TipArea->Size = GetInteger( InputString ) - 1;
  1637. if ( TipArea->Size < 1 ) {
  1638. TipArea->Size = 1;
  1639. }
  1640. DPRINT( OSC, ("[TipArea Size = %u]\n", TipArea->Size) );
  1641. ScreenY += TipArea->Size;
  1642. break;
  1643. case TOKEN_EOF:
  1644. // imcomplete statement - so don't have a tiparea.
  1645. TipArea = NULL;
  1646. return Tag;
  1647. }
  1648. }
  1649. if ( ScreenY > ScreenBottom ) {
  1650. ScreenY = ScreenBottom;
  1651. }
  1652. return Tag;
  1653. }
  1654. int ParaOldLeftMargin = 0;
  1655. int ParaOldRightMargin = 0;
  1656. //
  1657. // ParagraphTagState( )
  1658. //
  1659. enum TOKENS
  1660. ParagraphTagState(
  1661. IN PCHAR * InputString
  1662. )
  1663. {
  1664. enum TOKENS Tag = TOKEN_START;
  1665. PCHAR psz;
  1666. TraceFunc( "ParagraphTagState( )\n" );
  1667. ParaOldLeftMargin = LeftMargin;
  1668. ParaOldRightMargin = RightMargin;
  1669. // get tag arguments
  1670. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1671. {
  1672. switch( Tag )
  1673. {
  1674. case TOKEN_LEFT:
  1675. psz = *InputString;
  1676. // skip any spaces
  1677. while( *psz && *psz == 32 )
  1678. psz++;
  1679. *InputString = psz;
  1680. LeftMargin = GetInteger( InputString );
  1681. DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
  1682. break;
  1683. case TOKEN_RIGHT:
  1684. psz = *InputString;
  1685. // skip any spaces
  1686. while( *psz && *psz == 32 )
  1687. psz++;
  1688. *InputString = psz;
  1689. RightMargin = GetInteger( InputString );
  1690. DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
  1691. break;
  1692. case TOKEN_EOF:
  1693. return Tag;
  1694. }
  1695. }
  1696. // always simulate a <BR>
  1697. ScreenY++;
  1698. if ( ScreenY > ScreenBottom ) {
  1699. ScreenY = ScreenBottom;
  1700. }
  1701. ScreenX = LeftMargin;
  1702. return Tag;
  1703. }
  1704. //
  1705. // FormTagState( )
  1706. //
  1707. enum TOKENS
  1708. FormTagState(
  1709. IN PCHAR * InputString
  1710. )
  1711. {
  1712. enum TOKENS Tag = TOKEN_START;
  1713. PCHAR psz;
  1714. TraceFunc( "FormTagState( )\n" );
  1715. // get tag arguments
  1716. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1717. {
  1718. switch( Tag )
  1719. {
  1720. case TOKEN_ACTION:
  1721. if ( !EnterKey ) {
  1722. EnterKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
  1723. }
  1724. if ( !EnterKey )
  1725. break;
  1726. EnterKey->Action = ACTION_JUMP;
  1727. EnterKey->ScreenName = GetString( InputString );
  1728. if ( EnterKey->ScreenName )
  1729. DPRINT( OSC, ("[Key Enter Action: JUMP to '%s.OSC']\n", EnterKey->ScreenName) );
  1730. break;
  1731. case TOKEN_EOF:
  1732. return Tag;
  1733. }
  1734. }
  1735. psz = *InputString;
  1736. while ( Tag != TOKEN_EOF && Tag != TOKEN_ENDFORM )
  1737. {
  1738. switch (Tag)
  1739. {
  1740. default:
  1741. if ( !psz ) {
  1742. psz = *InputString;
  1743. }
  1744. Tag = Lex( InputString );
  1745. break;
  1746. case TOKEN_SELECT:
  1747. case TOKEN_INPUT:
  1748. case TOKEN_PRE:
  1749. case TOKEN_BOLD:
  1750. case TOKEN_FLASH:
  1751. case TOKEN_ENDFLASH:
  1752. case TOKEN_ENDBOLD:
  1753. case TOKEN_BREAK:
  1754. case TOKEN_ENDBODY:
  1755. case TOKEN_FORM:
  1756. case TOKEN_TIPAREA:
  1757. case TOKEN_EOF:
  1758. case TOKEN_PARAGRAPH:
  1759. case TOKEN_ENDPARA:
  1760. if ( psz ) {
  1761. BlpPrintString( psz, (*InputString) - Tags[Tag].length );
  1762. psz = NULL; // reset
  1763. }
  1764. switch( Tag )
  1765. {
  1766. case TOKEN_SELECT:
  1767. Tag = SelectTagState( InputString );
  1768. break;
  1769. case TOKEN_INPUT:
  1770. Tag = InputTagState( InputString );
  1771. break;
  1772. case TOKEN_EOF:
  1773. return Tag;
  1774. case TOKEN_PRE:
  1775. Tag = PreTagState( InputString );
  1776. break;
  1777. case TOKEN_BOLD:
  1778. BlpSendEscapeBold(ScreenAttributes);
  1779. DPRINT( OSC, ("[Bold]\n") );
  1780. Tag = Lex( InputString );
  1781. break;
  1782. case TOKEN_FLASH:
  1783. BlpSendEscapeFlash(ScreenAttributes);
  1784. DPRINT( OSC, ("[Flash]\n") );
  1785. Tag = Lex( InputString );
  1786. break;
  1787. case TOKEN_ENDFLASH:
  1788. case TOKEN_ENDBOLD:
  1789. BlpSendEscape(ScreenAttributes);
  1790. DPRINT( OSC, ("[Normal]\n") );
  1791. Tag = Lex( InputString );
  1792. break;
  1793. case TOKEN_FORM:
  1794. // ignore it
  1795. Tag = Lex( InputString );
  1796. break;
  1797. case TOKEN_BREAK:
  1798. ScreenX = LeftMargin;
  1799. ScreenY++;
  1800. if ( ScreenY > ScreenBottom ) {
  1801. ScreenY = ScreenBottom;
  1802. }
  1803. Tag = Lex( InputString );
  1804. break;
  1805. case TOKEN_TIPAREA:
  1806. Tag = TipAreaTagState( InputString );
  1807. break;
  1808. case TOKEN_PARAGRAPH:
  1809. Tag = ParagraphTagState( InputString );
  1810. break;
  1811. case TOKEN_ENDPARA:
  1812. LeftMargin = ParaOldLeftMargin;
  1813. RightMargin = ParaOldRightMargin;
  1814. // Make sure the boundaries are realistic
  1815. if ( LeftMargin < 1 ) {
  1816. LeftMargin = 1;
  1817. }
  1818. if ( RightMargin <= LeftMargin ) {
  1819. RightMargin = LeftMargin + 1;
  1820. }
  1821. if ( RightMargin < 1 ) {
  1822. RightMargin = 80;
  1823. }
  1824. // always simulate a <BR>
  1825. ScreenY++;
  1826. if ( ScreenY > ScreenBottom ) {
  1827. ScreenY = ScreenBottom;
  1828. }
  1829. ScreenX = LeftMargin;
  1830. Tag = Lex( InputString );
  1831. break;
  1832. case TOKEN_ENDBODY:
  1833. return Tag; // exit state
  1834. }
  1835. break;
  1836. }
  1837. }
  1838. return Tag;
  1839. }
  1840. //
  1841. // ImpliedBodyTagState( )
  1842. //
  1843. enum TOKENS
  1844. ImpliedBodyTagState(
  1845. IN PCHAR * InputString
  1846. )
  1847. {
  1848. enum TOKENS Tag = TOKEN_START;
  1849. PCHAR psz = *InputString;
  1850. TraceFunc( "ImpliedBodyTagState( )\n" );
  1851. while ( TRUE )
  1852. {
  1853. // KB: All items in this switch statment must have Tag returned
  1854. // to them from a function call or must call Lex( ) to get
  1855. // the next Tag.
  1856. switch (Tag)
  1857. {
  1858. default:
  1859. if ( !psz ) {
  1860. psz = *InputString;
  1861. }
  1862. Tag = Lex( InputString );
  1863. break;
  1864. case TOKEN_PRE:
  1865. case TOKEN_BOLD:
  1866. case TOKEN_FLASH:
  1867. case TOKEN_ENDFLASH:
  1868. case TOKEN_ENDBOLD:
  1869. case TOKEN_BREAK:
  1870. case TOKEN_ENDBODY:
  1871. case TOKEN_FORM:
  1872. case TOKEN_TIPAREA:
  1873. case TOKEN_EOF:
  1874. case TOKEN_PARAGRAPH:
  1875. case TOKEN_ENDPARA:
  1876. if ( psz ) {
  1877. BlpPrintString( psz, (*InputString) - Tags[Tag].length );
  1878. psz = NULL; // reset
  1879. }
  1880. switch( Tag )
  1881. {
  1882. case TOKEN_EOF:
  1883. return Tag;
  1884. case TOKEN_PRE:
  1885. Tag = PreTagState( InputString );
  1886. break;
  1887. case TOKEN_BOLD:
  1888. BlpSendEscapeBold(ScreenAttributes);
  1889. DPRINT( OSC, ("[Bold]\n") );
  1890. Tag = Lex( InputString );
  1891. break;
  1892. case TOKEN_FLASH:
  1893. BlpSendEscapeFlash(ScreenAttributes);
  1894. DPRINT( OSC, ("[Flash]\n") );
  1895. Tag = Lex( InputString );
  1896. break;
  1897. case TOKEN_ENDFLASH:
  1898. case TOKEN_ENDBOLD:
  1899. BlpSendEscape(ScreenAttributes);
  1900. DPRINT( OSC, ("[Normal]\n") );
  1901. Tag = Lex( InputString );
  1902. break;
  1903. case TOKEN_FORM:
  1904. Tag = FormTagState( InputString );
  1905. break;
  1906. case TOKEN_BREAK:
  1907. ScreenX = LeftMargin;
  1908. ScreenY++;
  1909. if ( ScreenY > ScreenBottom ) {
  1910. ScreenY = ScreenBottom;
  1911. }
  1912. Tag = Lex( InputString );
  1913. break;
  1914. case TOKEN_TIPAREA:
  1915. Tag = TipAreaTagState( InputString );
  1916. break;
  1917. case TOKEN_PARAGRAPH:
  1918. Tag = ParagraphTagState( InputString );
  1919. break;
  1920. case TOKEN_ENDPARA:
  1921. LeftMargin = ParaOldLeftMargin;
  1922. RightMargin = ParaOldRightMargin;
  1923. // Make sure the boundaries are realistic
  1924. if ( LeftMargin < 1 ) {
  1925. LeftMargin = 1;
  1926. }
  1927. if ( RightMargin <= LeftMargin ) {
  1928. RightMargin = LeftMargin + 1;
  1929. }
  1930. if ( RightMargin < 1 ) {
  1931. RightMargin = 80;
  1932. }
  1933. // always simulate a <BR>
  1934. ScreenY++;
  1935. if ( ScreenY > ScreenBottom ) {
  1936. ScreenY = ScreenBottom;
  1937. }
  1938. ScreenX = LeftMargin;
  1939. Tag = Lex( InputString );
  1940. break;
  1941. case TOKEN_ENDBODY:
  1942. return Tag; // exit state
  1943. }
  1944. break;
  1945. }
  1946. }
  1947. return Tag;
  1948. }
  1949. //
  1950. // BodyTagState( )
  1951. //
  1952. enum TOKENS
  1953. BodyTagState(
  1954. IN PCHAR * InputString
  1955. )
  1956. {
  1957. enum TOKENS Tag = TOKEN_START;
  1958. PCHAR psz;
  1959. TraceFunc( "BodyTagState( )\n" );
  1960. // get tag arguments
  1961. for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  1962. {
  1963. switch( Tag )
  1964. {
  1965. case TOKEN_LEFT:
  1966. psz = *InputString;
  1967. // skip any spaces
  1968. while( *psz && *psz == 32 )
  1969. psz++;
  1970. *InputString = psz;
  1971. LeftMargin = GetInteger( InputString );
  1972. DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
  1973. break;
  1974. case TOKEN_RIGHT:
  1975. psz = *InputString;
  1976. // skip any spaces
  1977. while( *psz && *psz == 32 )
  1978. psz++;
  1979. *InputString = psz;
  1980. RightMargin = GetInteger( InputString );
  1981. DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
  1982. break;
  1983. case TOKEN_EOF:
  1984. return Tag;
  1985. }
  1986. }
  1987. if ( ScreenX >= RightMargin ) {
  1988. ScreenY++;
  1989. if ( ScreenY > ScreenBottom ) {
  1990. ScreenY = ScreenBottom;
  1991. }
  1992. }
  1993. if ( ScreenX >= RightMargin || ScreenX < LeftMargin ) {
  1994. ScreenX = LeftMargin;
  1995. }
  1996. return ImpliedBodyTagState( InputString );
  1997. }
  1998. //
  1999. // KeyTagState( )
  2000. //
  2001. enum TOKENS
  2002. KeyTagState(
  2003. IN PCHAR * InputString
  2004. )
  2005. {
  2006. enum TOKENS Tag = TOKEN_START;
  2007. LPKEY_RESPONSE Key = NULL;
  2008. PCHAR ScreenName = NULL;
  2009. TraceFunc( "KeyTagState( )\n" );
  2010. // get arguments
  2011. for ( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
  2012. {
  2013. switch (Tag)
  2014. {
  2015. case TOKEN_ENTER:
  2016. DPRINT( OSC, ("[Key Enter]\n") );
  2017. EnterKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
  2018. if ( !EnterKey )
  2019. break;
  2020. Key = EnterKey;
  2021. Key->ScreenName = NULL;
  2022. Key->Action = ACTION_NOP;
  2023. break;
  2024. case TOKEN_F1:
  2025. DPRINT( OSC, ("[Key F1]\n") );
  2026. F1Key = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
  2027. if ( !F1Key )
  2028. break;
  2029. Key = F1Key;
  2030. Key->ScreenName = NULL;
  2031. Key->Action = ACTION_NOP;
  2032. break;
  2033. case TOKEN_F3:
  2034. DPRINT( OSC, ("[Key F3]\n") );
  2035. F3Key = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
  2036. if ( !F3Key )
  2037. break;
  2038. Key = F3Key;
  2039. Key->ScreenName = NULL;
  2040. Key->Action = ACTION_NOP;
  2041. break;
  2042. case TOKEN_ESC:
  2043. DPRINT( OSC, ("[Key Escape]\n") );
  2044. EscKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
  2045. if ( !EscKey )
  2046. break;
  2047. Key = EscKey;
  2048. Key->ScreenName = NULL;
  2049. Key->Action = ACTION_NOP;
  2050. break;
  2051. case TOKEN_HREF:
  2052. if ( Key ) {
  2053. Key->Action = ACTION_JUMP;
  2054. Key->ScreenName = GetString( InputString );
  2055. if ( Key->ScreenName )
  2056. DPRINT( OSC, ("[Key Action: JUMP to '%s.OSC']\n", Key->ScreenName) );
  2057. }
  2058. break;
  2059. case TOKEN_ACTION:
  2060. if ( Key ) {
  2061. PCHAR pAction = GetString( InputString );
  2062. if ( !pAction )
  2063. break;
  2064. if ( Lexstrcmpni( pAction, "REBOOT", 6 ) == 0 ) {
  2065. DPRINT( OSC, ("[Key Action: REBOOT]\n") );
  2066. Key->Action = ACTION_REBOOT;
  2067. } else {
  2068. DPRINT( OSC, ("[Key Action?] %s\n", pAction) );
  2069. }
  2070. OscHeapFree( pAction );
  2071. }
  2072. break;
  2073. case TOKEN_EOF:
  2074. return Tag;
  2075. }
  2076. }
  2077. return Tag;
  2078. }
  2079. //
  2080. // MetaTagState( )
  2081. //
  2082. enum TOKENS
  2083. MetaTagState(
  2084. IN PCHAR * InputString
  2085. )
  2086. {
  2087. enum TOKENS Tag = TOKEN_START;
  2088. TraceFunc( "MetaTagState( )\n" );
  2089. // get tag arguments
  2090. while ( Tag != TOKEN_ENDTAG )
  2091. {
  2092. // KB: All items in this switch statment must have Tag returned
  2093. // to them from a function call or must call Lex( ) to get
  2094. // the next Tag.
  2095. switch (Tag)
  2096. {
  2097. case TOKEN_EOF:
  2098. return Tag;
  2099. case TOKEN_KEY:
  2100. Tag = KeyTagState( InputString );
  2101. break;
  2102. case TOKEN_SERVER:
  2103. DPRINT( OSC, ("[Server Meta - ignored]\n") );
  2104. // ignore server side METAs
  2105. while ( Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG )
  2106. {
  2107. Tag = Lex( InputString );
  2108. }
  2109. break;
  2110. #if defined(PLEASE_WAIT)
  2111. case TOKEN_WAITMSG:
  2112. {
  2113. if ( PleaseWaitMsg )
  2114. {
  2115. OscHeapFree( PleaseWaitMsg );
  2116. }
  2117. PleaseWaitMsg = GetString( InputString );
  2118. if ( !PleaseWaitMsg )
  2119. break;
  2120. Tag = Lex( InputString );
  2121. DPRINT( OSC, ("[WaitMsg: '%s'\n", PleaseWaitMsg ) );
  2122. }
  2123. break;
  2124. #endif
  2125. case TOKEN_ACTION:
  2126. {
  2127. PCHAR pAction = GetString( InputString );
  2128. if ( !pAction )
  2129. break;
  2130. if ( Lexstrcmpni( pAction, "LOGIN", 5 ) == 0 ) {
  2131. DPRINT( OSC, ("[Screen Action: LOGIN]\n") );
  2132. LoginScreen = TRUE;
  2133. } else if ( Lexstrcmpni( pAction, "AUTOENTER", 9 ) == 0 ) {
  2134. DPRINT( OSC, ("[Screen Action: AUTOENTER]\n") );
  2135. AutoEnter = TRUE;
  2136. } else {
  2137. DPRINT( OSC, ("[Screen Action?] %s\n", pAction) );
  2138. }
  2139. OscHeapFree( pAction );
  2140. }
  2141. // fall thru
  2142. default:
  2143. Tag = Lex( InputString );
  2144. break;
  2145. }
  2146. }
  2147. return Tag;
  2148. }
  2149. //
  2150. // OSCMLTagState( )
  2151. //
  2152. enum TOKENS
  2153. OSCMLTagState(
  2154. IN PCHAR * InputString
  2155. )
  2156. {
  2157. #ifdef HEADLESS_SRV
  2158. ULONG y;
  2159. #endif
  2160. enum TOKENS Tag = TOKEN_START;
  2161. TraceFunc( "OSCMLTagState( )\n" );
  2162. BlpSendEscape(ScreenAttributes);
  2163. BlpClearScreen();
  2164. ScreenX = LeftMargin;
  2165. ScreenY = SCREEN_TOP;
  2166. while ( Tag != TOKEN_EOF )
  2167. {
  2168. switch (Tag)
  2169. {
  2170. case TOKEN_TITLE:
  2171. Tag = TitleTagState( InputString );
  2172. break;
  2173. case TOKEN_FOOTER:
  2174. Tag = FooterTagState( InputString );
  2175. break;
  2176. case TOKEN_META:
  2177. Tag = MetaTagState( InputString );
  2178. break;
  2179. case TOKEN_BODY:
  2180. Tag = BodyTagState( InputString );
  2181. break;
  2182. case TOKEN_ENDHTML:
  2183. return Tag; // exit state
  2184. default:
  2185. Tag = Lex( InputString );
  2186. break;
  2187. }
  2188. }
  2189. return Tag;
  2190. }
  2191. // **************************************************************************
  2192. //
  2193. // "User" Section
  2194. //
  2195. // **************************************************************************
  2196. //
  2197. // ProcessEmptyScreen( )
  2198. //
  2199. // Process a screen that has no input controls
  2200. //
  2201. CHAR
  2202. ProcessEmptyScreen(
  2203. OUT PCHAR OutputString
  2204. )
  2205. {
  2206. ULONG Key;
  2207. UCHAR KeyAscii;
  2208. TraceFunc("ProcessEmptyScreen()\n");
  2209. while (TRUE) {
  2210. #ifdef EFI
  2211. //
  2212. // disable EFI watchdog when waiting for user response
  2213. //
  2214. DisableEFIWatchDog();
  2215. #endif
  2216. do {
  2217. Key = BlpGetKey();
  2218. } while (Key == 0);
  2219. #ifdef EFI
  2220. //
  2221. // reset efi watchdog
  2222. //
  2223. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  2224. #endif
  2225. KeyAscii = (UCHAR)(Key & (ULONG)0xff);
  2226. // If it is enter/esc/F1/F3, check if the screen expects that.
  2227. if ( Key == F1_KEY ) {
  2228. if ( F1Key ) {
  2229. SpecialAction = F1Key->Action;
  2230. if ( F1Key->ScreenName ) {
  2231. strcpy( OutputString, F1Key->ScreenName );
  2232. strcat( OutputString, "\n" );
  2233. }
  2234. return KeyAscii;
  2235. }
  2236. } else if ( Key == F3_KEY ) {
  2237. if ( F3Key ) {
  2238. SpecialAction = F3Key->Action;
  2239. if ( F3Key->ScreenName ) {
  2240. strcpy( OutputString, F3Key->ScreenName );
  2241. strcat( OutputString, "\n" );
  2242. }
  2243. return KeyAscii;
  2244. }
  2245. #if defined(_BUILDING_OSDISP_)
  2246. } else if ( Key == F5_KEY ) {
  2247. SpecialAction = ACTION_REFRESH;
  2248. return KeyAscii;
  2249. #endif
  2250. } else if ( KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF) ) {
  2251. if ( EscKey ) {
  2252. SpecialAction = EscKey->Action;
  2253. if ( EscKey->ScreenName ) {
  2254. strcpy( OutputString, EscKey->ScreenName );
  2255. strcat( OutputString, "\n" );
  2256. }
  2257. return KeyAscii;
  2258. }
  2259. } else {
  2260. // assume any other key is the Enter key
  2261. if ( EnterKey ) {
  2262. SpecialAction = EnterKey->Action;
  2263. if ( EnterKey->ScreenName ) {
  2264. strcpy( OutputString, EnterKey->ScreenName );
  2265. strcat( OutputString, "\n" );
  2266. }
  2267. return KeyAscii;
  2268. }
  2269. }
  2270. }
  2271. }
  2272. //
  2273. // ProcessInputControl( )
  2274. //
  2275. ULONG
  2276. ProcessInputControl(
  2277. LPINPUTSTRUCT Input
  2278. )
  2279. {
  2280. CHAR InputBuffer[ MAX_INPUT_BUFFER_LENGTH ];
  2281. int MaxLength;
  2282. int CurrentLength;
  2283. ULONG Key;
  2284. UCHAR KeyAscii;
  2285. TraceFunc("ProcessInputControl()\n");
  2286. //
  2287. // variable types are not actually printed or processed.
  2288. // return TAB_KEY to move to the next available input control
  2289. //
  2290. if ((Input->Type & CT_VARIABLE) == CT_VARIABLE) {
  2291. return TAB_KEY;
  2292. }
  2293. if ( Input->Value ) {
  2294. CurrentLength = strlen( Input->Value );
  2295. strcpy( InputBuffer, Input->Value );
  2296. OscHeapFree( Input->Value );
  2297. Input->Value = NULL;
  2298. } else {
  2299. CurrentLength = 0;
  2300. InputBuffer[0] = '\0';
  2301. }
  2302. MaxLength = Input->Size;
  2303. if ( Input->MaxLength ) {
  2304. MaxLength = Input->MaxLength;
  2305. }
  2306. // paranoid
  2307. if ( CurrentLength > MaxLength ) {
  2308. CurrentLength = MaxLength;
  2309. InputBuffer[CurrentLength] = '\0';
  2310. }
  2311. if (Input->CurrentPosition > CurrentLength ) {
  2312. Input->CurrentPosition = CurrentLength;
  2313. }
  2314. // paint the "[ .... ]"
  2315. BlpSendEscapeBold( ScreenAttributes );
  2316. BlpPositionCursor( Input->X, Input->Y );
  2317. PRINT(TEXT("["), 1*sizeof(TCHAR));
  2318. BlpPositionCursor( Input->X + Input->Size + BRACKETS, Input->Y );
  2319. PRINT(TEXT("]") ,1*sizeof(TCHAR));
  2320. BlpSendEscape( ScreenAttributes );
  2321. //
  2322. // Let the user type in a string, showing the text at the current
  2323. // location. Returns the key used to exit (so we can distinguish
  2324. // enter and tab).
  2325. //
  2326. #ifdef EFI
  2327. //
  2328. // disable efi watchdog
  2329. //
  2330. DisableEFIWatchDog();
  2331. #endif
  2332. while (TRUE) {
  2333. int DrawSize;
  2334. // Get a keystroke -- this returns (from exp.asm):
  2335. //
  2336. // If no key is available, returns 0 (which BlpGetKeyWithBlink hides)
  2337. //
  2338. // If ASCII character is available, LSB 0 is ASCII code
  2339. // LSB 1 is keyboard scan code
  2340. // If extended character is available, LSB 0 is extended ASCII code
  2341. // LSB 1 is keyboard scan code
  2342. //
  2343. // NOTE: For extended keys LSB 0 seems to be 0, not the ASCII code
  2344. // (which makes sense since they have no ASCII codes).
  2345. if ( (Input->Type & CT_PASSWORD) && InputBuffer[Input->CurrentPosition] )
  2346. {
  2347. Key = BlpGetKeyWithBlink( Input->X + Input->CurrentPosition + 2 - Input->FirstVisibleChar,
  2348. Input->Y,
  2349. '*' );
  2350. } else {
  2351. Key = BlpGetKeyWithBlink( Input->X + Input->CurrentPosition + 2 - Input->FirstVisibleChar,
  2352. Input->Y,
  2353. InputBuffer[Input->CurrentPosition] );
  2354. }
  2355. #if 0
  2356. // TEMP: Show value of any key pressed near the bottom of the screen
  2357. ARC_DISPLAY_INVERSE_VIDEO();
  2358. ARC_DISPLAY_POSITION_CURSOR(0, 20);
  2359. BlPrint(TEXT("%x\n"), Key);
  2360. ARC_DISPLAY_ATTRIBUTES_OFF();
  2361. #endif
  2362. KeyAscii = (UCHAR)(Key & (ULONG)0xff);
  2363. // If it is enter/esc/tab/backtab/F1/F3, then we are done.
  2364. if ((Key == BACKTAB_KEY) || (Key == F1_KEY) || (Key == F3_KEY) ||
  2365. (KeyAscii == ENTER_KEY) || (KeyAscii == TAB_KEY) ||
  2366. (KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF)) ||
  2367. (Key == DOWN_ARROW) || (Key == UP_ARROW) || (Key == F5_KEY)) {
  2368. break;
  2369. }
  2370. // If it is backspace, then go back one character.
  2371. if ( KeyAscii == (UCHAR)(BKSP_KEY & 0xFF)
  2372. && Input->CurrentPosition != 0
  2373. && CurrentLength != 0 ) {
  2374. Input->CurrentPosition--;
  2375. memcpy( &InputBuffer[Input->CurrentPosition],
  2376. &InputBuffer[Input->CurrentPosition+1],
  2377. CurrentLength - Input->CurrentPosition + 1 );
  2378. CurrentLength--;
  2379. if ( Input->CurrentPosition <= Input->FirstVisibleChar ) {
  2380. Input->FirstVisibleChar -= Input->Size / 2;
  2381. if ( Input->FirstVisibleChar < 0 ) {
  2382. Input->FirstVisibleChar = 0;
  2383. }
  2384. }
  2385. }
  2386. if ( Key == LEFT_KEY ) {
  2387. Input->CurrentPosition--;
  2388. if ( Input->CurrentPosition < 0 ) {
  2389. Input->CurrentPosition = 0;
  2390. }
  2391. }
  2392. if ( Key == RIGHT_KEY && Input->CurrentPosition < CurrentLength ) {
  2393. Input->CurrentPosition++;
  2394. }
  2395. if ( Key == END_KEY ) {
  2396. Input->CurrentPosition = CurrentLength;
  2397. }
  2398. if ( Key == HOME_KEY ) {
  2399. Input->CurrentPosition = 0;
  2400. }
  2401. if ( Key == DEL_KEY
  2402. && CurrentLength != 0
  2403. && Input->CurrentPosition != CurrentLength ) {
  2404. memcpy( &InputBuffer[Input->CurrentPosition],
  2405. &InputBuffer[Input->CurrentPosition+1],
  2406. CurrentLength - Input->CurrentPosition + 1 );
  2407. CurrentLength--;
  2408. }
  2409. if ( Key == INS_KEY ) {
  2410. InsertMode = 1 - InsertMode;
  2411. }
  2412. // For now allow any printable character
  2413. if ((KeyAscii >= ' ') && (KeyAscii <= '~')) {
  2414. //
  2415. // If we are at the maximum, then don't allow it.
  2416. //
  2417. if (Input->CurrentPosition > MaxLength || CurrentLength >= MaxLength ) {
  2418. continue;
  2419. }
  2420. if ( !InsertMode ) {
  2421. // add or replace a character
  2422. InputBuffer[Input->CurrentPosition] = KeyAscii;
  2423. Input->CurrentPosition++;
  2424. if ( Input->CurrentPosition > CurrentLength ) {
  2425. CurrentLength++;
  2426. InputBuffer[CurrentLength] = '\0';
  2427. }
  2428. } else {
  2429. // insert character
  2430. memmove( &InputBuffer[Input->CurrentPosition+1],
  2431. &InputBuffer[Input->CurrentPosition],
  2432. CurrentLength - Input->CurrentPosition );
  2433. CurrentLength++;
  2434. InputBuffer[CurrentLength] = '\0';
  2435. InputBuffer[Input->CurrentPosition] = KeyAscii;
  2436. Input->CurrentPosition++;
  2437. }
  2438. }
  2439. if ( Input->CurrentPosition > Input->FirstVisibleChar + Input->Size ) {
  2440. Input->FirstVisibleChar = Input->CurrentPosition - Input->Size;
  2441. }
  2442. //
  2443. // Scroll Adjuster Section
  2444. //
  2445. DrawSize = Input->Size + 1;
  2446. // Paranoid
  2447. if ( Input->CurrentPosition < Input->FirstVisibleChar ) {
  2448. Input->FirstVisibleChar = Input->CurrentPosition;
  2449. }
  2450. BlpPositionCursor( Input->X + 1, Input->Y );
  2451. if ( Input->FirstVisibleChar <= 0 ) {
  2452. Input->FirstVisibleChar = 0;
  2453. PRINT( SpaceString, 1*sizeof(TCHAR) );
  2454. } else {
  2455. PRINT( TEXT("<"), 1*sizeof(TCHAR) );
  2456. }
  2457. if ( DrawSize > CurrentLength - Input->FirstVisibleChar ) {
  2458. DrawSize = CurrentLength - Input->FirstVisibleChar;
  2459. }
  2460. DPRINT( OSC, ("CurrentPosition: %u\tFirstVisibleChar:%u\tCurrentLength:%u\tDrawSize:%u\n",
  2461. Input->CurrentPosition, Input->FirstVisibleChar, CurrentLength, DrawSize ) );
  2462. if ( Input->Type & CT_PASSWORD ) {
  2463. int i;
  2464. for( i = Input->FirstVisibleChar; i < Input->FirstVisibleChar + DrawSize; i++ )
  2465. {
  2466. PRINT( TEXT("*"), 1*sizeof(TCHAR) );
  2467. }
  2468. PRINT( SpaceString, 1*sizeof(TCHAR) );
  2469. } else {
  2470. #ifdef UNICODE
  2471. int i;
  2472. for (i = 0; i < DrawSize; i++) {
  2473. WCHAR wc = (WCHAR)InputBuffer[Input->FirstVisibleChar+i];
  2474. PRINT( &wc, 1*sizeof(WCHAR));
  2475. }
  2476. #else
  2477. PRINT( &InputBuffer[Input->FirstVisibleChar], DrawSize );
  2478. #endif
  2479. PRINT( SpaceString, 1*sizeof(TCHAR) );
  2480. break;
  2481. }
  2482. BlpPositionCursor( Input->X + Input->Size + BRACKETS - 1, Input->Y );
  2483. if ( Input->FirstVisibleChar + DrawSize < CurrentLength
  2484. && CurrentLength > Input->Size ) {
  2485. PRINT( TEXT(">"), 1*sizeof(TCHAR) );
  2486. } else {
  2487. PRINT( SpaceString, 1*sizeof(TCHAR) );
  2488. }
  2489. }
  2490. #ifdef EFI
  2491. //
  2492. // reset EFI watchdog
  2493. //
  2494. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  2495. #endif
  2496. // copy the buffer
  2497. Input->Value = OscHeapAlloc( CurrentLength + 1 );
  2498. if ( Input->Value ) {
  2499. memcpy( Input->Value, InputBuffer, CurrentLength + 1 );
  2500. }
  2501. // UN-paint the "[ .... ]"
  2502. BlpPositionCursor( Input->X, Input->Y );
  2503. PRINT(SpaceString, 1*sizeof(TCHAR));
  2504. BlpPositionCursor( Input->X + Input->Size + BRACKETS, Input->Y );
  2505. PRINT(TEXT(" ") ,1*sizeof(TCHAR));
  2506. // If we exited on a standard key return the ASCII value, otherwise
  2507. // the full key value.
  2508. if (KeyAscii != 0) {
  2509. return (ULONG)KeyAscii;
  2510. } else {
  2511. return Key;
  2512. }
  2513. }
  2514. //
  2515. // ShowSelectedOptions( )
  2516. //
  2517. void
  2518. ShowSelectedOptions(
  2519. LPSELECTSTRUCT Select,
  2520. LPOPTIONSTRUCT Option,
  2521. int YPosition,
  2522. BOOLEAN Hovering
  2523. )
  2524. {
  2525. TraceFunc( "ShowSelectedOptions( )\n" );
  2526. if ( Option->Flags == OF_SELECTED ) {
  2527. BlpSendEscapeBold( ScreenAttributes );
  2528. }
  2529. if ( Hovering == TRUE ) {
  2530. BlpSendEscapeReverse( ScreenAttributes );
  2531. }
  2532. // Erase
  2533. BlpPositionCursor( Select->X, YPosition );
  2534. PRINT( SpaceString, Select->Width*sizeof(TCHAR) );
  2535. // Draw
  2536. BlpPositionCursor( Select->X, YPosition );
  2537. if ( Option->Displayed )
  2538. #ifdef UNICODE
  2539. {
  2540. ULONG i;
  2541. WCHAR wc;
  2542. for (i = 0; i< strlen(Option->Displayed); i++) {
  2543. wc = (WCHAR)(Option->Displayed)[i];
  2544. PRINT( &wc, sizeof(WCHAR));
  2545. }
  2546. }
  2547. #else
  2548. PRINTL( Option->Displayed );
  2549. #endif
  2550. if ( Option->Value )
  2551. DPRINT( OSC, ("[Option Y=%u] %s %s\n", YPosition, Option->Value, (Hovering ? "HIGHLITED" : "")) );
  2552. BlpSendEscape( ScreenAttributes );
  2553. if ( TipArea && Hovering == TRUE ) {
  2554. // Draw help area
  2555. int SaveLeftMargin = LeftMargin;
  2556. int SaveRightMargin = RightMargin;
  2557. int SaveScreenY = ScreenY;
  2558. int SaveScreenX = ScreenX;
  2559. int SaveScreenBottom = ScreenBottom;
  2560. // Set the drawing area
  2561. ScreenX = TipArea->X;
  2562. ScreenY = TipArea->Y;
  2563. LeftMargin = TipArea->LeftMargin;
  2564. RightMargin = TipArea->RightMargin;
  2565. ScreenBottom = TipArea->Y + TipArea->Size;
  2566. // Clear the old help text out
  2567. BlpPositionCursor( TipArea->X, TipArea->Y );
  2568. PRINT( SpaceString, (TipArea->RightMargin - TipArea->X)*sizeof(TCHAR) );
  2569. for ( YPosition = TipArea->Y + 1; YPosition < ScreenBottom ; YPosition++ )
  2570. {
  2571. BlpPositionCursor( TipArea->LeftMargin, YPosition );
  2572. PRINT( SpaceString, (TipArea->RightMargin - TipArea->LeftMargin)*sizeof(TCHAR) );
  2573. }
  2574. // Print it!
  2575. DPRINT( OSC, ("[Options Tip X=%u Y=%u Left=%u Right=%u Bottom=%u] %s\n",
  2576. ScreenX, ScreenY, LeftMargin, RightMargin, ScreenBottom, Option->Tip) );
  2577. BlpPrintString( Option->Tip, Option->EndTip );
  2578. // Restore
  2579. ScreenX = SaveScreenX;
  2580. ScreenY = SaveScreenY;
  2581. RightMargin = SaveRightMargin;
  2582. LeftMargin = SaveLeftMargin;
  2583. ScreenBottom = SaveScreenBottom;;
  2584. }
  2585. }
  2586. //
  2587. // DrawSelectControl( )
  2588. //
  2589. // Select controls get drawn from the bottom up.
  2590. //
  2591. void
  2592. DrawSelectControl(
  2593. LPSELECTSTRUCT Select,
  2594. int OptionCount
  2595. )
  2596. {
  2597. LPOPTIONSTRUCT Option = Select->FirstVisibleSelection;
  2598. TraceFunc( "DrawSelectControl( )\n" );
  2599. ScreenY = Select->Y + ( OptionCount < Select->Size ? OptionCount : Select->Size ) - 1;
  2600. while ( Option )
  2601. {
  2602. if ( Option->Type & CT_OPTION ) {
  2603. BOOLEAN b = (Select->CurrentSelection == Option);
  2604. ShowSelectedOptions( Select, Option, ScreenY, b );
  2605. ScreenY--;
  2606. }
  2607. if ( ScreenY < Select->Y || Option->Next == Select )
  2608. break;
  2609. Option = Option->Next;
  2610. }
  2611. }
  2612. //
  2613. // ProcessSelectControl( )
  2614. //
  2615. ULONG
  2616. ProcessSelectControl(
  2617. LPSELECTSTRUCT Select
  2618. )
  2619. {
  2620. ULONG Key;
  2621. int OptionCount = 0;
  2622. LPOPTIONSTRUCT Option;
  2623. int fMultipleControls = FALSE;
  2624. TraceFunc("ProcessSelectControl()\n");
  2625. #ifdef EFI
  2626. //
  2627. // disable EFI watchdog
  2628. //
  2629. DisableEFIWatchDog();
  2630. #endif
  2631. // find out about the control
  2632. Option = ScreenControls;
  2633. while( Option )
  2634. {
  2635. if ( Option->Type & CT_OPTION ) {
  2636. OptionCount++;
  2637. } else if ( (Option->Type & CT_SELECT) == 0 ) {
  2638. // not the only control on the screen
  2639. DPRINT( OSC, ("[Select] Not the only control on the screen.\n") );
  2640. fMultipleControls = TRUE;
  2641. }
  2642. if ( Option->Next == Select )
  2643. break;
  2644. Option = Option->Next;
  2645. }
  2646. // if this is the first thru and nothing else
  2647. if ( !Select->CurrentSelection && Option ) {
  2648. DPRINT( OSC, ("[Select] Setting CurrentSelection to the first item '%s'\n", Option->Value) );
  2649. Select->CurrentSelection = Option;
  2650. }
  2651. // ensure the current selection is visible
  2652. EnsureSelectionVisible:
  2653. if ( Select->Size < 2 ) {
  2654. // single line - show the current selection
  2655. Select->FirstVisibleSelection = Select->CurrentSelection;
  2656. } else if ( OptionCount <= Select->Size ) {
  2657. // the number of options is less than or equal to the size
  2658. // of the dialog so simply set the first visible equal to
  2659. // the last OPTION in the list.
  2660. Select->FirstVisibleSelection = ScreenControls;
  2661. while ( Select->FirstVisibleSelection )
  2662. {
  2663. if ( Select->FirstVisibleSelection->Type & CT_OPTION )
  2664. break;
  2665. Select->FirstVisibleSelection = Select->FirstVisibleSelection->Next;
  2666. }
  2667. } else {
  2668. //
  2669. // The number of options is greater than the display size so we
  2670. // need to figure out the "best" bottom item.
  2671. //
  2672. ULONG Lines;
  2673. ULONG Count;
  2674. LPOPTIONSTRUCT TmpOption;
  2675. //
  2676. // Find the best FirstVisibleSelection if we already have previously chosen one.
  2677. //
  2678. Count = 0;
  2679. if (Select->FirstVisibleSelection != NULL) {
  2680. //
  2681. // This code checks to see if the current selection is visible with the
  2682. // current first visible selection.
  2683. //
  2684. TmpOption = ScreenControls;
  2685. while (TmpOption->Next != Select) {
  2686. if (TmpOption == Select->FirstVisibleSelection) {
  2687. Count++;
  2688. } else if (Count != 0) {
  2689. Count++;
  2690. }
  2691. if (TmpOption == Select->CurrentSelection) {
  2692. break;
  2693. }
  2694. TmpOption = TmpOption->Next;
  2695. }
  2696. if (TmpOption->Next == Select) {
  2697. Count++;
  2698. }
  2699. //
  2700. // It is, so just display the list.
  2701. //
  2702. if ((Count != 0) && (Count <= (ULONG)(Select->Size))) {
  2703. goto EndFindVisibleSelection;
  2704. }
  2705. //
  2706. // It is not visible, but since we have a FirstVisibleSelection, we can
  2707. // move that around to make it visible.
  2708. //
  2709. //
  2710. // The current selection comes before the first visible one, so move
  2711. // first visible to the current selection.
  2712. //
  2713. if (Count == 0) {
  2714. Select->FirstVisibleSelection = Select->CurrentSelection;
  2715. goto EndFindVisibleSelection;
  2716. }
  2717. //
  2718. // Count is greater than the screen size, so we move up First visible
  2719. // until count is the screen size.
  2720. //
  2721. TmpOption = ScreenControls;
  2722. while (TmpOption->Next != Select) {
  2723. if (TmpOption == Select->FirstVisibleSelection) {
  2724. Select->FirstVisibleSelection = TmpOption->Next;
  2725. Count--;
  2726. if (Count == (ULONG)(Select->Size)) {
  2727. break;
  2728. }
  2729. }
  2730. TmpOption = TmpOption->Next;
  2731. }
  2732. goto EndFindVisibleSelection;
  2733. }
  2734. //
  2735. // There is no FirstVisibleSelection, so we choose one that places the current
  2736. // selection near the top of the screen, displaying the first item, if possible.
  2737. //
  2738. TmpOption = Select->CurrentSelection;
  2739. Lines = 0;
  2740. Count = 0;
  2741. //
  2742. // Count the number of items before our current selection.
  2743. //
  2744. while (TmpOption->Next != Select) {
  2745. TmpOption = TmpOption->Next;
  2746. Lines++;
  2747. }
  2748. //
  2749. // Subtract off that many items from what is left for below the selection.
  2750. //
  2751. Lines = (ULONG)((Lines < (ULONG)(Select->Size)) ? Lines : Select->Size - 1);
  2752. Lines = Select->Size - Lines - 1;
  2753. //
  2754. // If more than a screen before, make this the bottom and move on.
  2755. //
  2756. if (Lines == 0) {
  2757. Select->FirstVisibleSelection = Select->CurrentSelection;
  2758. goto EndFindVisibleSelection;
  2759. }
  2760. TmpOption = ScreenControls;
  2761. //
  2762. // Count the number of items below the current selection
  2763. //
  2764. while (TmpOption != Select->CurrentSelection) {
  2765. TmpOption = TmpOption->Next;
  2766. Count++;
  2767. }
  2768. if (Count < Lines) {
  2769. //
  2770. // Not enough items to fill the screen, use the last item.
  2771. //
  2772. Select->FirstVisibleSelection = ScreenControls;
  2773. } else {
  2774. //
  2775. // Count back until we reach what will be our bottom item.
  2776. //
  2777. TmpOption = ScreenControls;
  2778. while (Count != Lines) {
  2779. TmpOption = TmpOption->Next;
  2780. Count--;
  2781. }
  2782. Select->FirstVisibleSelection = TmpOption;
  2783. }
  2784. }
  2785. EndFindVisibleSelection:
  2786. // paranoid
  2787. if ( !Select->FirstVisibleSelection ) {
  2788. Select->FirstVisibleSelection = ScreenControls;
  2789. }
  2790. while ( TRUE )
  2791. {
  2792. UCHAR KeyAscii = 0;
  2793. DrawSelectControl( Select, OptionCount );
  2794. Option = Select->CurrentSelection; // remember this
  2795. if ( OptionCount == 0
  2796. || ( Select->AutoSelect == FALSE && OptionCount == 1 ))
  2797. { // empty selection control or no AUTO select
  2798. do {
  2799. Key = BlpGetKey();
  2800. } while ( Key == 0 );
  2801. KeyAscii = (UCHAR)(Key & (ULONG)0xff);
  2802. }
  2803. else if ( OptionCount != 1 )
  2804. { // more than one choice... do the usual
  2805. ULONG CurrentTick, NewTick;
  2806. int TimeoutCounter = 0;
  2807. // Show any help for this choice
  2808. // BlpShowMenuHelp(psInfo, psInfo->Data[CurChoice].VariableName);
  2809. CurrentTick = GET_COUNTER();
  2810. do {
  2811. Key = BlpGetKey();
  2812. if ( Select->Timeout )
  2813. {
  2814. NewTick = GET_COUNTER();
  2815. if ((NewTick < CurrentTick) || ((NewTick - CurrentTick) >= BLINK_RATE))
  2816. {
  2817. CHAR Buffer[4];
  2818. CurrentTick = NewTick;
  2819. TimeoutCounter++;
  2820. //
  2821. // TODO: Update the timer value displayed
  2822. //
  2823. if ( TimeoutCounter >= Select->Timeout )
  2824. {
  2825. Key = ENTER_KEY; // fake return
  2826. break;
  2827. }
  2828. }
  2829. }
  2830. } while (Key == 0);
  2831. KeyAscii = (UCHAR)(Key & (ULONG)0xff);
  2832. //
  2833. // User pressed a key, so stop doing the timer
  2834. //
  2835. if ( Select->Timeout ) {
  2836. Select->Timeout = 0;
  2837. //
  2838. // TODO: Erase the timer
  2839. //
  2840. }
  2841. }
  2842. else if ( !fMultipleControls ) // && OptionCount == 1
  2843. { // only once choice... auto-accept it
  2844. //
  2845. // Fake return press....
  2846. //
  2847. DPRINT( OSC, ( "[Select] Auto accepting the only option available\n") );
  2848. Key = KeyAscii = ENTER_KEY;
  2849. }
  2850. if ( Select->Flags & OF_MULTIPLE ) {
  2851. if ( KeyAscii == 32 && Select->CurrentSelection) {
  2852. if ( Select->CurrentSelection->Flags & OF_SELECTED ) {
  2853. Select->CurrentSelection->Flags &= ~OF_SELECTED; // turn off
  2854. } else {
  2855. Select->CurrentSelection->Flags |= OF_SELECTED; // turn on
  2856. }
  2857. }
  2858. } else {
  2859. if ( KeyAscii == ENTER_KEY && Select->CurrentSelection ) {
  2860. Select->CurrentSelection->Flags |= OF_SELECTED; // turn on
  2861. }
  2862. }
  2863. if ((Key == BACKTAB_KEY) || (Key == F1_KEY) || (Key == F3_KEY) ||
  2864. (KeyAscii == ENTER_KEY) || (KeyAscii == TAB_KEY) ||
  2865. (KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF)) ||
  2866. (Key == F5_KEY)) {
  2867. // Undraw the selection bar to give user feedback that something has
  2868. // happened
  2869. Select->CurrentSelection = NULL;
  2870. DrawSelectControl( Select, OptionCount );
  2871. break;
  2872. }
  2873. if ( OptionCount ) {
  2874. if (Key == DOWN_ARROW) {
  2875. DPRINT( OSC, ("[KeyPress] DOWN_ARROW\n") );
  2876. Select->CurrentSelection = ScreenControls;
  2877. while ( Select->CurrentSelection && Select->CurrentSelection->Next != Option )
  2878. {
  2879. Select->CurrentSelection = Select->CurrentSelection ->Next;
  2880. }
  2881. if ( Select->CurrentSelection )
  2882. DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
  2883. // paranoid
  2884. if ( !Select->CurrentSelection )
  2885. Select->CurrentSelection = Option;
  2886. goto EnsureSelectionVisible;
  2887. } else if ( Key == UP_ARROW ) {
  2888. DPRINT( OSC, ("[KeyPress] UP_ARROW\n") );
  2889. if ( Select->CurrentSelection->Next != Select ) {
  2890. Select->CurrentSelection = Select->CurrentSelection->Next;
  2891. DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
  2892. }
  2893. // paranoid
  2894. if ( !Select->CurrentSelection )
  2895. Select->CurrentSelection = Option;
  2896. goto EnsureSelectionVisible;
  2897. } else if ( Key == END_KEY ) {
  2898. DPRINT( OSC, ("[KeyPress] END_KEY\n") );
  2899. Select->CurrentSelection = ScreenControls;
  2900. while( Select->CurrentSelection && (Select->CurrentSelection->Type & CT_OPTION) == 0 )
  2901. {
  2902. Select->CurrentSelection = Select->CurrentSelection->Next;
  2903. }
  2904. if ( Select->CurrentSelection )
  2905. DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
  2906. // paranoid
  2907. if ( !Select->CurrentSelection )
  2908. Select->CurrentSelection = Option;
  2909. goto EnsureSelectionVisible;
  2910. } else if ( Key == HOME_KEY ) {
  2911. DPRINT( OSC, ("[KeyPress] HOME_KEY\n") );
  2912. Select->CurrentSelection = ScreenControls;
  2913. while ( Select->CurrentSelection && Select->CurrentSelection->Next != Select )
  2914. {
  2915. Select->CurrentSelection = Select->CurrentSelection ->Next;
  2916. }
  2917. if ( Select->CurrentSelection )
  2918. DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
  2919. // paranoid
  2920. if ( !Select->CurrentSelection )
  2921. Select->CurrentSelection = Option;
  2922. goto EnsureSelectionVisible;
  2923. }
  2924. }
  2925. }
  2926. #ifdef EFI
  2927. //
  2928. // reset watchdog
  2929. //
  2930. SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
  2931. #endif
  2932. return Key;
  2933. }
  2934. //
  2935. // BlFixupLoginScreenInputs( )
  2936. //
  2937. // On an input screen, split a USERNAME that has an @ in it, keeping
  2938. // the part before the @ in USERNAME and moving the part after to
  2939. // USERDOMAIN.
  2940. //
  2941. void
  2942. BlFixupLoginScreenInputs(
  2943. )
  2944. {
  2945. LPCONTROLSTRUCT CurrentControl;
  2946. LPINPUTSTRUCT UserNameControl = NULL;
  2947. LPINPUTSTRUCT UserDomainControl = NULL;
  2948. PCHAR AtSign;
  2949. //
  2950. // First loop through and find the USERNAME and USERDOMAIN input
  2951. // controls.
  2952. //
  2953. CurrentControl = ScreenControls;
  2954. while( CurrentControl ) {
  2955. LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
  2956. if ( ( Input->Type & CT_TEXT ) && ( Input->Name != NULL ) ) {
  2957. if ( Lexstrcmpni( Input->Name, "USERNAME", 8 ) == 0 ) {
  2958. UserNameControl = Input;
  2959. } else if ( Lexstrcmpni( Input->Name, "USERDOMAIN", 10 ) == 0 ) {
  2960. UserDomainControl = Input;
  2961. }
  2962. }
  2963. CurrentControl = CurrentControl->Next;
  2964. }
  2965. //
  2966. // If we found them, fix them up if necessary.
  2967. //
  2968. if ( ( UserNameControl != NULL ) &&
  2969. ( UserNameControl->Value != NULL ) &&
  2970. ( UserDomainControl != NULL) ) {
  2971. AtSign = strchr(UserNameControl->Value, '@');
  2972. if (AtSign != NULL) {
  2973. *AtSign = '\0'; // terminate UserNameControl->Value before the @
  2974. if ( UserDomainControl->Value != NULL ) {
  2975. OscHeapFree( UserDomainControl->Value ); // throw away old domain
  2976. }
  2977. UserDomainControl->Value = OscHeapAlloc( strlen(AtSign+1) + 1 );
  2978. if ( UserDomainControl->Value != NULL ) {
  2979. strcpy(UserDomainControl->Value, AtSign+1); // copy part after the @
  2980. }
  2981. }
  2982. }
  2983. }
  2984. //
  2985. // ProcessControlResults( )
  2986. //
  2987. // Process a screen that has input controls
  2988. //
  2989. void
  2990. ProcessControlResults(
  2991. IN PCHAR OutputString
  2992. )
  2993. {
  2994. LPCONTROLSTRUCT CurrentControl;
  2995. LPCONTROLSTRUCT LastControl;
  2996. BOOLEAN CheckAdminPassword_AlreadyChecked = FALSE;
  2997. BOOLEAN CheckAdminPasswordConfirm_AlreadyChecked = FALSE;
  2998. // start clean
  2999. OutputString[0] = '\0';
  3000. if ( EnterKey ) {
  3001. SpecialAction = EnterKey->Action;
  3002. if ( EnterKey->ScreenName ) {
  3003. strcpy( OutputString, EnterKey->ScreenName );
  3004. strcat( OutputString, "\n" );
  3005. }
  3006. }
  3007. if ( LoginScreen == TRUE ) {
  3008. SpecialAction = ACTION_LOGIN;
  3009. UserName[0] = '\0';
  3010. Password[0] = '\0';
  3011. DomainName[0] = '\0';
  3012. BlFixupLoginScreenInputs(); // split username with @ in it
  3013. AuthenticationType = OSCHOICE_AUTHENETICATE_TYPE_NTLM_V1;
  3014. }
  3015. CurrentControl = ScreenControls;
  3016. while( CurrentControl ) {
  3017. BOOLEAN CheckAdminPasswordConfirm = FALSE;
  3018. BOOLEAN CheckAdminPassword = FALSE;
  3019. switch( CurrentControl->Type & (CT_TEXT | CT_PASSWORD | CT_RESET | CT_SELECT | CT_OPTION | CT_VARIABLE))
  3020. {
  3021. case CT_TEXT:
  3022. case CT_PASSWORD:
  3023. {
  3024. LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
  3025. BOOLEAN LocalOnly;
  3026. DPRINT( OSC, ("About to check a password.\n") );
  3027. if ( (Input->Type & (CT_PASSWORD)) &&
  3028. (Input->Type & (CT_LOCAL)) &&
  3029. Input->Name ) {
  3030. LocalOnly = TRUE;
  3031. if( _strnicmp(Input->Name, "*ADMINISTRATORPASSWORDCONFIRM", 29) == 0 ) {
  3032. CheckAdminPasswordConfirm = TRUE;
  3033. CheckAdminPasswordConfirm_AlreadyChecked = TRUE;
  3034. DPRINT( OSC, ("About to check the ADMINISTRATORPASSWORDCONFIRM\n") );
  3035. } else if( _strnicmp( Input->Name, "*ADMINISTRATORPASSWORD", 22) == 0 ) {
  3036. CheckAdminPassword = TRUE;
  3037. CheckAdminPassword_AlreadyChecked = TRUE;
  3038. DPRINT( OSC, ("About to check the ADMINISTRATORPASSWORD\n") );
  3039. } else {
  3040. DPRINT( OSC, ("It's a local password, but not Admin or AdminConfirm.\n") );
  3041. }
  3042. } else {
  3043. LocalOnly = FALSE;
  3044. DPRINT( OSC, ("It's NOT a local password.\n") );
  3045. }
  3046. DPRINT(
  3047. OSC,
  3048. ("variable %s will%sbe transmitted to the server.\n",
  3049. Input->Name,
  3050. LocalOnly ? " not " : " " ) );
  3051. if (Input->Name && !LocalOnly ) {
  3052. strcat( OutputString, Input->Name );
  3053. strcat( OutputString, "=" );
  3054. }
  3055. if ( (Input->Value) && (Input->Encoding == ET_OWF)) {
  3056. PCHAR TmpLmOwfPassword = NULL;
  3057. PCHAR TmpNtOwfPassword = NULL;
  3058. CHAR TmpHashedPW[(LM_OWF_PASSWORD_SIZE+NT_OWF_PASSWORD_SIZE+2)*2];
  3059. UNICODE_STRING TmpNtPassword;
  3060. PWCHAR UnicodePassword;
  3061. ULONG PasswordLen, i;
  3062. PCHAR OutputLoc;
  3063. CHAR c;
  3064. DPRINT( OSC, ("This entry has ET_OWF tagged.\n") );
  3065. PasswordLen = strlen(Input->Value);
  3066. UnicodePassword = (PWCHAR)OscHeapAlloc(PasswordLen * sizeof(WCHAR));
  3067. TmpLmOwfPassword = (PCHAR)OscHeapAlloc(LM_OWF_PASSWORD_SIZE);
  3068. TmpNtOwfPassword = (PCHAR)OscHeapAlloc(NT_OWF_PASSWORD_SIZE);
  3069. if( (UnicodePassword != NULL) &&
  3070. (TmpLmOwfPassword != NULL) &&
  3071. (TmpNtOwfPassword != NULL) ) {
  3072. //
  3073. // Do a quick conversion of the password to Unicode.
  3074. //
  3075. TmpNtPassword.Length = (USHORT)(PasswordLen * sizeof(WCHAR));
  3076. TmpNtPassword.MaximumLength = TmpNtPassword.Length;
  3077. TmpNtPassword.Buffer = UnicodePassword;
  3078. for (i = 0; i < PasswordLen; i++) {
  3079. UnicodePassword[i] = (WCHAR)(Input->Value[i]);
  3080. }
  3081. BlOwfPassword(Input->Value, &TmpNtPassword, TmpLmOwfPassword, TmpNtOwfPassword);
  3082. //
  3083. // Output the two OWF passwords as hex chars. If
  3084. // the value is the administrator password and
  3085. // should only be stored locally, then
  3086. // save it in our global variable. Otherwise put
  3087. // it in the output buffer.
  3088. //
  3089. OutputLoc = TmpHashedPW;
  3090. for (i = 0; i < LM_OWF_PASSWORD_SIZE; i++) {
  3091. c = TmpLmOwfPassword[i];
  3092. *(OutputLoc++) = rghex [(c >> 4) & 0x0F] ;
  3093. *(OutputLoc++) = rghex [c & 0x0F] ;
  3094. }
  3095. for (i = 0; i < NT_OWF_PASSWORD_SIZE; i++) {
  3096. c = TmpNtOwfPassword[i];
  3097. *(OutputLoc++) = rghex [(c >> 4) & 0x0F] ;
  3098. *(OutputLoc++) = rghex [c & 0x0F] ;
  3099. }
  3100. *OutputLoc = '\0';
  3101. DPRINT( OSC, ("Hashed Password: %s\n", TmpHashedPW) );
  3102. if (!LocalOnly) {
  3103. strcat(OutputString,TmpHashedPW);
  3104. } else {
  3105. if( CheckAdminPassword ) {
  3106. strcpy( AdministratorPassword, TmpHashedPW );
  3107. DPRINT( OSC, ("AdministratorPassword 1: %s\n", AdministratorPassword) );
  3108. }
  3109. if( CheckAdminPasswordConfirm ) {
  3110. strcpy( AdministratorPasswordConfirm, TmpHashedPW );
  3111. DPRINT( OSC, ("AdministratorPasswordConfirm 1: %s\n", AdministratorPasswordConfirm) );
  3112. }
  3113. #if 0
  3114. if (AdministratorPassword[0] != '\0') {
  3115. if (strcmp(
  3116. AdministratorPassword,
  3117. TmpHashedPW)) {
  3118. //
  3119. // the passwords didn't match. make the server
  3120. // display MATCHPW.OSC and reset the admin password
  3121. // for the next time around
  3122. //
  3123. DPRINT(
  3124. OSC,
  3125. ("Administrator passwords didn't match, force MATCHPW.OSC.\n" ) );
  3126. strcpy( OutputString, "MATCHPW\n" );
  3127. AdministratorPassword[0] = '\0';
  3128. } else {
  3129. strncpy(
  3130. AdministratorPassword,
  3131. TmpHashedPW,
  3132. sizeof(AdministratorPassword)-1 );
  3133. }
  3134. }
  3135. #endif
  3136. OutputLoc = OutputString + strlen(OutputString);
  3137. }
  3138. OscHeapFree((PCHAR)UnicodePassword);
  3139. OscHeapFree(TmpLmOwfPassword);
  3140. OscHeapFree(TmpNtOwfPassword);
  3141. }
  3142. } else {
  3143. DPRINT( OSC, ("This entry does NOT have ET_OWF tagged.\n") );
  3144. if( LocalOnly ) {
  3145. //
  3146. // Load the appropriate password.
  3147. //
  3148. if( CheckAdminPassword ) {
  3149. strcpy( AdministratorPassword, (Input->Value ? Input->Value : "") );
  3150. DPRINT( OSC, ("I'm setting the Administrator password to %s\n", AdministratorPassword) );
  3151. }
  3152. if( CheckAdminPasswordConfirm ) {
  3153. strcpy( AdministratorPasswordConfirm, (Input->Value ? Input->Value : "") );
  3154. DPRINT( OSC, ("I'm setting the AdministratorConfirm password to %s\n", AdministratorPasswordConfirm) );
  3155. }
  3156. } else {
  3157. strcat( OutputString, (Input->Value ? Input->Value : "") );
  3158. }
  3159. }
  3160. //
  3161. // If both passwords have been processed, check them to see if they match.
  3162. //
  3163. if( CheckAdminPassword_AlreadyChecked &&
  3164. CheckAdminPasswordConfirm_AlreadyChecked ) {
  3165. DPRINT( OSC, ("Both Admin and AdminConfirm passwords are set. About to check if they match.\n") );
  3166. if( strcmp( AdministratorPassword, AdministratorPasswordConfirm ) ) {
  3167. //
  3168. // the passwords didn't match. make the server
  3169. // display MATCHPW.OSC and reset the admin password
  3170. // for the next time around
  3171. //
  3172. DPRINT( OSC, ("Administrator passwords didn't match, force MATCHPW.OSC.\n" ) );
  3173. strcpy( OutputString, "MATCHPW\n" );
  3174. AdministratorPassword[0] = '\0';
  3175. AdministratorPasswordConfirm[0] = '\0';
  3176. } else {
  3177. DPRINT( OSC, ("Administrator passwords match.\n" ) );
  3178. //
  3179. // See if the Admin password is empty. If so, then put our
  3180. // super-secret tag on the end to show everyone that it's really
  3181. // empty, not just uninitialized.
  3182. //
  3183. if( AdministratorPassword[0] == '\0' ) {
  3184. DPRINT( OSC, ("Administrator password is empty, so set our 'it is null' flag.\n" ) );
  3185. AdministratorPassword[OSC_ADMIN_PASSWORD_LEN-1] = 0xFF;
  3186. }
  3187. }
  3188. }
  3189. if ( SpecialAction == ACTION_LOGIN
  3190. && (Input->Name != NULL)
  3191. && (Input->Value != NULL) ) {
  3192. if ( Lexstrcmpni( Input->Name, "USERNAME", 8 ) == 0 ) {
  3193. strncpy( UserName, Input->Value, sizeof(UserName)-1 );
  3194. UserName[sizeof(UserName)-1] = '\0';
  3195. } else if ( Lexstrcmpni( Input->Name, "*PASSWORD", 9 ) == 0 ) {
  3196. strncpy( Password, Input->Value, sizeof(Password)-1 );
  3197. Password[sizeof(Password)-1] = '\0';
  3198. } else if ( Lexstrcmpni( Input->Name, "USERDOMAIN", 10 ) == 0 ) {
  3199. strncpy( DomainName, Input->Value, sizeof(DomainName)-1 );
  3200. DomainName[sizeof(DomainName)-1] = '\0';
  3201. }
  3202. }
  3203. if (!LocalOnly) {
  3204. strcat( OutputString, "\n" );
  3205. }
  3206. }
  3207. break;
  3208. case CT_SELECT:
  3209. {
  3210. CHAR NotFirst = FALSE;
  3211. LPOPTIONSTRUCT Option = ScreenControls;
  3212. LPSELECTSTRUCT Select = (LPSELECTSTRUCT) CurrentControl;
  3213. if ( Select->Name ) {
  3214. strcat( OutputString, Select->Name );
  3215. strcat( OutputString, "=" );
  3216. }
  3217. while( Option && Option->Type == CT_OPTION )
  3218. {
  3219. if ( Option->Flags == OF_SELECTED ) {
  3220. if ( NotFirst ) {
  3221. strcat( OutputString, "+" );
  3222. }
  3223. if ( Option->Value ) {
  3224. strcat( OutputString, Option->Value );
  3225. NotFirst = TRUE;
  3226. }
  3227. }
  3228. Option = Option->Next;
  3229. }
  3230. strcat( OutputString, "\n" );
  3231. }
  3232. break;
  3233. case CT_VARIABLE:
  3234. {
  3235. LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
  3236. strcat( OutputString, Input->Name );
  3237. strcat( OutputString, "=" );
  3238. strcat( OutputString, Input->Value );
  3239. strcat( OutputString, "\n" );
  3240. if (SpecialAction == ACTION_LOGIN) {
  3241. //
  3242. // check if ntlm v2 is enabled on the server.
  3243. //
  3244. if ((strcmp(Input->Name,"NTLMV2Enabled") == 0) &&
  3245. (strcmp(Input->Value,"1") == 0)) {
  3246. AuthenticationType = OSCHOICE_AUTHENETICATE_TYPE_NTLM_V2;
  3247. }
  3248. //
  3249. // check if the server gave us the current file time
  3250. // we need this so that we can do ntlm v2 style
  3251. // authentication.
  3252. //
  3253. if (strcmp(Input->Name,"ServerUTCFileTime") == 0) {
  3254. SetFileTimeFromTimeString(
  3255. Input->Value,
  3256. &GlobalFileTime,
  3257. &ArcTimeForUTCTime);
  3258. }
  3259. }
  3260. }
  3261. break;
  3262. }
  3263. CurrentControl = CurrentControl->Next;
  3264. }
  3265. }
  3266. //
  3267. // ProcessScreenControls( )
  3268. //
  3269. // Process a screen that has input controls
  3270. //
  3271. CHAR
  3272. ProcessScreenControls(
  3273. OUT PCHAR OutputString
  3274. )
  3275. {
  3276. ULONG Key;
  3277. UCHAR KeyAscii;
  3278. LPCONTROLSTRUCT CurrentControl;
  3279. LPCONTROLSTRUCT LastControl;
  3280. TraceFunc("ProcessScreenControls()\n");
  3281. // find the first control
  3282. LastControl = ScreenControls;
  3283. CurrentControl = ScreenControls;
  3284. while( LastControl ) {
  3285. CurrentControl = LastControl;
  3286. LastControl = CurrentControl->Next;
  3287. }
  3288. while (TRUE) {
  3289. TopOfLoop:
  3290. // show activation on the control
  3291. switch( CurrentControl->Type & (CT_PASSWORD | CT_TEXT | CT_SELECT) )
  3292. {
  3293. case CT_PASSWORD:
  3294. case CT_TEXT:
  3295. Key = ProcessInputControl( (LPINPUTSTRUCT) CurrentControl );
  3296. break;
  3297. case CT_SELECT:
  3298. Key = ProcessSelectControl( (LPSELECTSTRUCT) CurrentControl );
  3299. break;
  3300. default:
  3301. // non-processing control - skip it
  3302. CurrentControl = CurrentControl->Next;
  3303. if ( !CurrentControl ) {
  3304. CurrentControl = ScreenControls;
  3305. }
  3306. goto TopOfLoop;
  3307. }
  3308. LastControl = CurrentControl;
  3309. KeyAscii = (UCHAR)(Key & (ULONG)0xff);
  3310. // If it is enter/esc/F1/F3, check if the screen expects that.
  3311. if ( Key == F1_KEY ) {
  3312. DPRINT( OSC, ("[KeyPress] F1_KEY\n") );
  3313. if ( F1Key ) {
  3314. SpecialAction = F1Key->Action;
  3315. if ( F1Key->ScreenName ) {
  3316. strcpy( OutputString, F1Key->ScreenName );
  3317. strcat( OutputString, "\n" );
  3318. }
  3319. return KeyAscii;
  3320. }
  3321. } else if ( Key == F3_KEY ) {
  3322. DPRINT( OSC, ("[KeyPress] F3_KEY\n") );
  3323. if ( F3Key ) {
  3324. SpecialAction = F3Key->Action;
  3325. if ( F3Key->ScreenName ) {
  3326. strcpy( OutputString, F3Key->ScreenName );
  3327. strcat( OutputString, "\n" );
  3328. }
  3329. return KeyAscii;
  3330. }
  3331. #if defined(_BUILDING_OSDISP_)
  3332. } else if ( Key == F5_KEY ) {
  3333. SpecialAction = ACTION_REFRESH;
  3334. return KeyAscii;
  3335. #endif
  3336. } else if ( KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF) ) {
  3337. DPRINT( OSC, ("[KeyPress] ESCAPE_KEY\n") );
  3338. if ( EscKey ) {
  3339. SpecialAction = EscKey->Action;
  3340. if ( EscKey->ScreenName ) {
  3341. strcpy( OutputString, EscKey->ScreenName );
  3342. strcat( OutputString, "\n" );
  3343. }
  3344. return KeyAscii;
  3345. }
  3346. } else if ( KeyAscii == TAB_KEY || Key == DOWN_ARROW ) {
  3347. DPRINT( OSC, ("[KeyPress] TAB_KEY or DOWN_ARROW\n") );
  3348. CurrentControl = ScreenControls;
  3349. while ( CurrentControl->Next != LastControl && // next is current one, so stop
  3350. CurrentControl->Next != NULL ) // at end of list, so we must have been at
  3351. // the start, so stop here to loop around
  3352. {
  3353. CurrentControl = CurrentControl->Next;
  3354. }
  3355. } else if ( Key == BACKTAB_KEY || Key == UP_ARROW ) {
  3356. DPRINT( OSC, ("[KeyPress] BACKTAB_KEY or UP_ARROW\n") );
  3357. CurrentControl = CurrentControl->Next;
  3358. if (!CurrentControl) {
  3359. CurrentControl = ScreenControls; // loop around if needed
  3360. }
  3361. } else if ( KeyAscii == ENTER_KEY ) {
  3362. DPRINT( OSC, ("[KeyPress] ENTER_KEY\n") );
  3363. ProcessControlResults( OutputString );
  3364. return KeyAscii;
  3365. }
  3366. if ( !CurrentControl ) {
  3367. CurrentControl = LastControl;
  3368. }
  3369. }
  3370. }
  3371. //
  3372. // BlProcessScreen( )
  3373. //
  3374. CHAR
  3375. BlProcessScreen(
  3376. IN PCHAR InputString,
  3377. OUT PCHAR OutputString
  3378. )
  3379. {
  3380. #ifdef HEADLESS_SRV
  3381. ULONG y;
  3382. #endif
  3383. CHAR chReturn;
  3384. enum TOKENS Tag;
  3385. #ifdef _TRACE_FUNC_
  3386. TraceFunc( "BlProcessScreen( " );
  3387. DPRINT( OSC, ("InputString = 0x%08x, OutputString = 0x%08x )\n", InputString, OutputString) );
  3388. #endif
  3389. // reset our "heap"
  3390. OscHeapInitialize( );
  3391. // reset the screen variables
  3392. ScreenAttributes = WhiteOnBlueAttributes;
  3393. SpecialAction = ACTION_NOP;
  3394. LeftMargin = 1;
  3395. RightMargin = 80;
  3396. ScreenX = LeftMargin;
  3397. ScreenY = SCREEN_TOP;
  3398. F1Key = NULL;
  3399. F3Key = NULL;
  3400. EnterKey = NULL;
  3401. EscKey = NULL;
  3402. ScreenControls = NULL;
  3403. PreformattedMode = FALSE;
  3404. LoginScreen = FALSE;
  3405. AutoEnter = FALSE;
  3406. InsertMode = FALSE;
  3407. TipArea = NULL;
  3408. if (BlIsTerminalConnected()) {
  3409. ScreenBottom = HEADLESS_SCREEN_HEIGHT;
  3410. } else {
  3411. ScreenBottom = SCREEN_BOTTOM;
  3412. }
  3413. #if defined(PLEASE_WAIT)
  3414. PleaseWaitMsg = NULL;
  3415. #endif
  3416. BlpSendEscape(ScreenAttributes);
  3417. BlpClearScreen();
  3418. Tag = Lex( &InputString );
  3419. while (Tag != TOKEN_EOF )
  3420. {
  3421. switch (Tag)
  3422. {
  3423. case TOKEN_HTML:
  3424. Tag = OSCMLTagState( &InputString );
  3425. break;
  3426. case TOKEN_ENDHTML:
  3427. Tag = TOKEN_EOF; // exit state
  3428. break;
  3429. default:
  3430. Tag = ImpliedBodyTagState( &InputString );
  3431. break;
  3432. }
  3433. }
  3434. // Remove any buffered keys to prevent blipping thru the screens.
  3435. // NOTE we call BlGetKey() directly, not BlpGetKey(), so we only
  3436. // remove real keystrokes, not the "auto-enter" keystroke.
  3437. while ( BlGetKey( ) != 0 )
  3438. ; // NOP on purpose
  3439. if ( ScreenControls ) {
  3440. chReturn = ProcessScreenControls( OutputString );
  3441. } else {
  3442. chReturn = ProcessEmptyScreen( OutputString );
  3443. }
  3444. // Erase footer to give user feedback that the screen is being
  3445. // processed.
  3446. BlpSendEscapeReverse(ScreenAttributes);
  3447. BlpPositionCursor( 1, ScreenBottom );
  3448. #ifdef _IN_OSDISP_
  3449. PRINT( SpaceString, 79*sizeof(TCHAR) );
  3450. #else
  3451. PRINT( SpaceString, BlTerminalConnected
  3452. ? 79*sizeof(TCHAR)
  3453. : 80*sizeof(TCHAR) );
  3454. #endif
  3455. #if defined(PLEASE_WAIT)
  3456. if ( PleaseWaitMsg ) {
  3457. BlpPositionCursor( 1, ScreenBottom );
  3458. #ifdef UNICODE
  3459. {
  3460. ULONG i;
  3461. WCHAR wc;
  3462. for (i = 0; i< strlen(PleaseWaitMsg);i++) {
  3463. wc = (WCHAR)PleaseWaitMsg[i];
  3464. PRINT( &wc, 1*sizeof(WCHAR));
  3465. }
  3466. }
  3467. #else
  3468. PRINTL( PleaseWaitMsg );
  3469. #endif
  3470. }
  3471. #endif
  3472. BlpSendEscape(ScreenAttributes);
  3473. return chReturn;
  3474. }