Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

993 lines
26 KiB

  1. // Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. //
  3. // terminal.c
  4. // Remote Access Common Dialog APIs
  5. // Terminal dialogs
  6. //
  7. // 08/28/95 Steve Cobb
  8. #include "rasdlgp.h"
  9. #include "rasscrpt.h"
  10. #define WM_EOLFROMDEVICE (WM_USER+999)
  11. #define SECS_ReceiveTimeout 1
  12. #define SIZE_ReceiveBuf 1024
  13. #define SIZE_SendBuf 1
  14. //----------------------------------------------------------------------------
  15. // Help maps
  16. //----------------------------------------------------------------------------
  17. static DWORD g_adwItHelp[] =
  18. {
  19. CID_IT_EB_Screen, HID_IT_EB_Screen,
  20. CID_IT_ST_IpAddress, HID_IT_CC_IpAddress,
  21. CID_IT_CC_IpAddress, HID_IT_CC_IpAddress,
  22. IDOK, HID_IT_PB_Done,
  23. 0, 0
  24. };
  25. //----------------------------------------------------------------------------
  26. // Local datatypes (alphabetically)
  27. //----------------------------------------------------------------------------
  28. // Interactive terminal dialog argument block.
  29. //
  30. typedef struct
  31. _ITARGS
  32. {
  33. DWORD sidTitle;
  34. TCHAR* pszIpAddress;
  35. HRASCONN hrasconn;
  36. PBENTRY* pEntry;
  37. RASDIALPARAMS* pRdp;
  38. }
  39. ITARGS;
  40. // Interactive terminal dialog context block.
  41. //
  42. typedef struct
  43. _ITINFO
  44. {
  45. // Caller's arguments to the dialog.
  46. //
  47. ITARGS* pArgs;
  48. // Handle of this dialog and some of it's controls.
  49. //
  50. HWND hwndDlg;
  51. HWND hwndEbScreen;
  52. HWND hwndCcIpAddress;
  53. HWND hwndPbBogus;
  54. // Set when waiting for the thread to terminate.
  55. //
  56. BOOL fAbortReceiveLoop;
  57. // Original dialog and screen edit box window proc.
  58. //
  59. WNDPROC pOldWndProc;
  60. WNDPROC pOldEbScreenWndProc;
  61. // buffers for RasScriptSend/RasScriptReceive.
  62. //
  63. BYTE pbyteReceiveBuf[SIZE_ReceiveBuf];
  64. BYTE pbyteSendBuf[SIZE_SendBuf];
  65. // handle to active script on this connection
  66. //
  67. HANDLE hscript;
  68. // Screen edit box font and brush.
  69. //
  70. HFONT hfontEbScreen;
  71. HBRUSH hbrEbScreen;
  72. }
  73. ITINFO;
  74. //----------------------------------------------------------------------------
  75. // Local prototypes (alphabetically)
  76. //----------------------------------------------------------------------------
  77. INT_PTR CALLBACK
  78. ItDlgProc(
  79. IN HWND hwnd,
  80. IN UINT unMsg,
  81. IN WPARAM wparam,
  82. IN LPARAM lparam );
  83. BOOL
  84. ItCommand(
  85. IN ITINFO* pInfo,
  86. IN WORD wNotification,
  87. IN WORD wId,
  88. IN HWND hwndCtrl );
  89. LRESULT APIENTRY
  90. ItEbScreenWndProc(
  91. HWND hwnd,
  92. UINT unMsg,
  93. WPARAM wParam,
  94. LPARAM lParam );
  95. BOOL
  96. ItInit(
  97. IN HWND hwndDlg,
  98. IN ITARGS* pArgs );
  99. BOOL
  100. ItRasApiComplete(
  101. IN ITINFO* pInfo );
  102. DWORD
  103. ItReceiveMonitorThread(
  104. LPVOID pThreadArg );
  105. VOID
  106. ItTerm(
  107. IN HWND hwndDlg );
  108. VOID
  109. ItViewScriptLog(
  110. IN HWND hwndOwner );
  111. LRESULT APIENTRY
  112. ItWndProc(
  113. HWND hwnd,
  114. UINT unMsg,
  115. WPARAM wParam,
  116. LPARAM lParam );
  117. //----------------------------------------------------------------------------
  118. // Terminal dialog
  119. // Listed alphabetically following stub API and dialog proc
  120. //----------------------------------------------------------------------------
  121. BOOL
  122. TerminalDlg(
  123. IN PBENTRY* pEntry,
  124. IN RASDIALPARAMS* pRdp,
  125. IN HWND hwndOwner,
  126. IN HRASCONN hrasconn,
  127. IN DWORD sidTitle,
  128. IN OUT TCHAR* pszIpAddress )
  129. // Pops-up the Terminal dialog. 'HwndOwner' is the window owning the
  130. // dialog. 'Hrasconn' is the RAS connection handle to talk on.
  131. // 'SidTitle' is ID of the string displayed as the window caption.
  132. // 'PszIpAddress' is caller's buffer of at least 16 characters containing
  133. // the initial IP address on entry and the edited IP address on exit. If
  134. // 'pszIpAddress' is empty, no IP address field is displayed.
  135. //
  136. // Returns true if user pressed OK and succeeded, false if he pressed
  137. // Cancel or encountered an error.
  138. //
  139. {
  140. INT_PTR nStatus;
  141. INT nDlg;
  142. ITARGS args;
  143. TRACE( "TerminalDlg" );
  144. if (pszIpAddress && pszIpAddress[ 0 ])
  145. {
  146. InitCommonControls();
  147. IpAddrInit( g_hinstDll, SID_PopupTitle, SID_BadIpAddrRange );
  148. nDlg = DID_IT_SlipTerminal;
  149. }
  150. else
  151. {
  152. nDlg = DID_IT_Terminal;
  153. }
  154. args.pszIpAddress = pszIpAddress;
  155. args.sidTitle = sidTitle;
  156. args.hrasconn = hrasconn;
  157. args.pEntry = pEntry;
  158. args.pRdp = pRdp;
  159. nStatus =
  160. DialogBoxParam(
  161. g_hinstDll,
  162. MAKEINTRESOURCE( nDlg ),
  163. hwndOwner,
  164. ItDlgProc,
  165. (LPARAM )&args );
  166. if (nStatus == -1)
  167. {
  168. TRACE1("TerminalDlg: GLE=%d", GetLastError());
  169. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  170. nStatus = FALSE;
  171. }
  172. return (nStatus) ? TRUE : FALSE;
  173. }
  174. INT_PTR CALLBACK
  175. ItDlgProc(
  176. IN HWND hwnd,
  177. IN UINT unMsg,
  178. IN WPARAM wparam,
  179. IN LPARAM lparam )
  180. // DialogProc callback for the Interactive Terminal dialog. Parameters
  181. // and return value are as described for standard windows 'DialogProc's.
  182. //
  183. {
  184. #if 0
  185. TRACE4( "ItDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  186. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  187. #endif
  188. switch (unMsg)
  189. {
  190. case WM_INITDIALOG:
  191. {
  192. return ItInit( hwnd, (ITARGS* )lparam );
  193. }
  194. case WM_HELP:
  195. case WM_CONTEXTMENU:
  196. {
  197. ContextHelp( g_adwItHelp, hwnd, unMsg, wparam, lparam );
  198. break;
  199. }
  200. case WM_COMMAND:
  201. {
  202. ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  203. ASSERT(pInfo);
  204. return ItCommand(
  205. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  206. }
  207. case WM_RASAPICOMPLETE:
  208. {
  209. ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  210. ASSERT(pInfo);
  211. // The notification code from the scripting-thread is in 'lparam'
  212. //
  213. switch (lparam)
  214. {
  215. case SCRIPTCODE_Done:
  216. {
  217. EndDialog(hwnd, TRUE);
  218. return TRUE;
  219. }
  220. case SCRIPTCODE_Halted:
  221. {
  222. MSGARGS msg;
  223. // The script has halted programmatically, for instance
  224. // because of an explicit "halt" command. Show a popup
  225. // indicating things have stopped, but don't dismiss the
  226. // dialog.
  227. //
  228. ZeroMemory(&msg, sizeof(msg));
  229. msg.dwFlags = MB_OK | MB_ICONINFORMATION;
  230. MsgDlg( hwnd, SID_OP_ScriptHalted, &msg );
  231. return TRUE;
  232. }
  233. case SCRIPTCODE_HaltedOnError:
  234. {
  235. MSGARGS msg;
  236. INT nResponse;
  237. // There was an execution-error in the script; show a
  238. // popup asking if the user wants to view the errors, and
  239. // if the user clicks 'Yes' invoke Notepad on the file
  240. // %windir%\system32\ras\script.log. Since this is an
  241. // error condition, dismiss the dialog.
  242. //
  243. ZeroMemory(&msg, sizeof(msg));
  244. msg.dwFlags = MB_YESNO | MB_ICONQUESTION;
  245. nResponse = MsgDlg(
  246. hwnd, SID_OP_ScriptHaltedOnError, &msg );
  247. if (nResponse == IDYES)
  248. {
  249. ItViewScriptLog( hwnd );
  250. }
  251. EndDialog(hwnd, FALSE);
  252. return TRUE;
  253. }
  254. case SCRIPTCODE_KeyboardEnable:
  255. {
  256. // Allow keyboard input in the edit-box.
  257. //
  258. EnableWindow(pInfo->hwndEbScreen, TRUE);
  259. return TRUE;
  260. }
  261. case SCRIPTCODE_KeyboardDisable:
  262. {
  263. // Disallow keyboard input in the edit-box; if the
  264. // edit-box currently has the focus, we first set the
  265. // focus to the 'Done' button.
  266. //
  267. if (GetFocus() == pInfo->hwndEbScreen)
  268. {
  269. SetFocus( GetDlgItem (hwnd, IDOK ) );
  270. }
  271. EnableWindow( pInfo->hwndEbScreen, FALSE );
  272. return TRUE;
  273. }
  274. case SCRIPTCODE_IpAddressSet:
  275. {
  276. DWORD dwErr;
  277. CHAR szAddress[ RAS_MaxIpAddress + 1 ];
  278. // The script is notifying us that the IP address has been
  279. // changed programmatically.
  280. //
  281. // Get the new IP address.
  282. //
  283. dwErr = RasScriptGetIpAddress( pInfo->hscript, szAddress );
  284. if (dwErr == NO_ERROR)
  285. {
  286. TCHAR* psz;
  287. // Save the new IP address.
  288. //
  289. psz = StrDupTFromA(szAddress);
  290. if (NULL != psz)
  291. {
  292. // Whistler bug 224074 use only lstrcpyn's to
  293. // prevent maliciousness
  294. //
  295. lstrcpyn(
  296. pInfo->pArgs->pszIpAddress,
  297. psz,
  298. TERM_IpAddress);
  299. Free0(psz);
  300. }
  301. // Display it in the IP-address edit-box
  302. //
  303. if (pInfo->hwndCcIpAddress)
  304. {
  305. SetWindowText( pInfo->hwndCcIpAddress,
  306. pInfo->pArgs->pszIpAddress );
  307. }
  308. }
  309. return TRUE;
  310. }
  311. case SCRIPTCODE_InputNotify:
  312. {
  313. // Handle input-notification.
  314. //
  315. return ItRasApiComplete( pInfo );
  316. }
  317. return TRUE;
  318. }
  319. }
  320. case WM_DESTROY:
  321. {
  322. ItTerm( hwnd );
  323. break;
  324. }
  325. }
  326. return FALSE;
  327. }
  328. BOOL
  329. ItCommand(
  330. IN ITINFO* pInfo,
  331. IN WORD wNotification,
  332. IN WORD wId,
  333. IN HWND hwndCtrl )
  334. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  335. // is the notification code of the command. 'wId' is the control/menu
  336. // identifier of the command. 'HwndCtrl' is the control window handle of
  337. // the command.
  338. //
  339. // Returns true if processed message, false otherwise.
  340. //
  341. {
  342. TRACE3( "ItCommand(n=%d,i=%d,c=$%x)",
  343. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  344. switch (wId)
  345. {
  346. case CID_IT_EB_Screen:
  347. {
  348. // Turn off the default button whenever the terminal window
  349. // has the focus. Pressing [Return] in the terminal acts like
  350. // a normal terminal.
  351. //
  352. Button_MakeDefault( pInfo->hwndDlg, pInfo->hwndPbBogus );
  353. // Don't select the entire string on entry.
  354. //
  355. Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 );
  356. break;
  357. }
  358. case IDOK:
  359. {
  360. TRACE("OK pressed");
  361. if (pInfo->pArgs->pszIpAddress)
  362. {
  363. GetWindowText(
  364. pInfo->hwndCcIpAddress, pInfo->pArgs->pszIpAddress, 16 );
  365. }
  366. EndDialog( pInfo->hwndDlg, TRUE );
  367. return TRUE;
  368. }
  369. case IDCANCEL:
  370. TRACE("Cancel pressed");
  371. EndDialog( pInfo->hwndDlg, FALSE );
  372. return TRUE;
  373. }
  374. return FALSE;
  375. }
  376. LRESULT APIENTRY
  377. ItEbScreenWndProc(
  378. HWND hwnd,
  379. UINT unMsg,
  380. WPARAM wParam,
  381. LPARAM lParam )
  382. // Subclassed terminal edit box window procedure.
  383. //
  384. // Return value depends on message type.
  385. //
  386. {
  387. ITINFO* pInfo;
  388. BOOL fSend;
  389. BOOL fSendTab;
  390. fSend = fSendTab = FALSE;
  391. if (unMsg == WM_EOLFROMDEVICE)
  392. {
  393. // An end-of-line in the device input was received. Send a linefeed
  394. // character to the window.
  395. //
  396. wParam = '\n';
  397. unMsg = WM_CHAR;
  398. }
  399. else
  400. {
  401. BOOL fCtrlKeyDown = (GetKeyState( VK_CONTROL ) < 0);
  402. BOOL fShiftKeyDown = (GetKeyState( VK_SHIFT ) < 0);
  403. if (unMsg == WM_KEYDOWN)
  404. {
  405. // The key was pressed by the user.
  406. //
  407. if (wParam == VK_RETURN && !fCtrlKeyDown && !fShiftKeyDown)
  408. {
  409. // Enter key pressed without Shift or Ctrl is discarded. This
  410. // prevents Enter from being interpreted as "press default
  411. // button" when pressed in the edit box.
  412. //
  413. return 0;
  414. }
  415. if (fCtrlKeyDown && wParam == VK_TAB)
  416. {
  417. fSend = TRUE;
  418. fSendTab = TRUE;
  419. }
  420. }
  421. else if (unMsg == WM_CHAR)
  422. {
  423. // The character was typed by the user.
  424. //
  425. if (wParam == VK_TAB)
  426. {
  427. // Ignore tabs...Windows sends this message when Tab (leave
  428. // field) is pressed but not when Ctrl+Tab (insert a TAB
  429. // character) is pressed...weird.
  430. //
  431. return 0;
  432. }
  433. fSend = TRUE;
  434. }
  435. }
  436. pInfo = (ITINFO* )GetWindowLongPtr( GetParent( hwnd ), DWLP_USER );
  437. ASSERT(pInfo);
  438. if (fSend)
  439. {
  440. DWORD dwErr;
  441. pInfo->pbyteSendBuf[ 0 ] = (BYTE )wParam;
  442. dwErr = RasScriptSend(
  443. pInfo->hscript, pInfo->pbyteSendBuf, SIZE_SendBuf);
  444. if (dwErr != 0)
  445. {
  446. ErrorDlg( pInfo->hwndDlg, SID_OP_RasPortSend, dwErr, NULL );
  447. }
  448. if (!fSendTab)
  449. {
  450. return 0;
  451. }
  452. }
  453. // Call the previous window procedure for everything else.
  454. //
  455. return
  456. CallWindowProc(
  457. pInfo->pOldEbScreenWndProc, hwnd, unMsg, wParam, lParam );
  458. }
  459. BOOL
  460. ItInit(
  461. IN HWND hwndDlg,
  462. IN ITARGS* pArgs )
  463. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the phonebook
  464. // dialog window. 'pEntry' is caller's entry as passed to the stub API.
  465. //
  466. // Return false if focus was set, true otherwise, i.e. as defined for
  467. // WM_INITDIALOG.
  468. //
  469. {
  470. DWORD dwErr;
  471. ITINFO* pInfo;
  472. WORD wReceiveSize;
  473. WORD wSendSize;
  474. WORD wSize;
  475. DWORD dwThreadId;
  476. TRACE( "ItInit" );
  477. // Allocate the dialog context block. Initialize minimally for proper
  478. // cleanup, then attach to the dialog window.
  479. //
  480. {
  481. pInfo = Malloc( sizeof(*pInfo) );
  482. if (!pInfo)
  483. {
  484. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  485. EndDialog( hwndDlg, FALSE );
  486. return TRUE;
  487. }
  488. ZeroMemory( pInfo, sizeof(*pInfo) );
  489. pInfo->pArgs = pArgs;
  490. pInfo->hwndDlg = hwndDlg;
  491. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  492. TRACE( "Context set" );
  493. }
  494. pInfo->hwndEbScreen = GetDlgItem( hwndDlg, CID_IT_EB_Screen );
  495. ASSERT( pInfo->hwndEbScreen );
  496. pInfo->hwndPbBogus = GetDlgItem( hwndDlg, CID_IT_PB_BogusButton );
  497. ASSERT( pInfo->hwndPbBogus );
  498. if (pArgs->pszIpAddress && pArgs->pszIpAddress[0])
  499. {
  500. pInfo->hwndCcIpAddress = GetDlgItem( hwndDlg, CID_IT_CC_IpAddress );
  501. ASSERT( pInfo->hwndCcIpAddress );
  502. if (*pArgs->pszIpAddress)
  503. {
  504. SetWindowText( pInfo->hwndCcIpAddress, pArgs->pszIpAddress );
  505. }
  506. else
  507. {
  508. SetWindowText( pInfo->hwndCcIpAddress, TEXT("0.0.0.0") );
  509. }
  510. }
  511. // Set the dialog title.
  512. //
  513. {
  514. TCHAR* psz = PszFromId( g_hinstDll, pArgs->sidTitle );
  515. if (psz)
  516. {
  517. SetWindowText( hwndDlg, psz );
  518. Free( psz );
  519. }
  520. }
  521. // Subclass the dialog and screen edit box.
  522. //
  523. pInfo->pOldWndProc =
  524. (WNDPROC )SetWindowLongPtr(
  525. pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )ItWndProc );
  526. pInfo->pOldEbScreenWndProc =
  527. (WNDPROC )SetWindowLongPtr(
  528. pInfo->hwndEbScreen, GWLP_WNDPROC, (ULONG_PTR )ItEbScreenWndProc );
  529. // Prepare for special TTY-ish painting.
  530. //
  531. pInfo->hfontEbScreen =
  532. SetFont( pInfo->hwndEbScreen, TEXT("Courier New"),
  533. FIXED_PITCH | FF_MODERN, 9, FALSE, FALSE, FALSE, FALSE );
  534. pInfo->hbrEbScreen = (HBRUSH )GetStockObject( BLACK_BRUSH );
  535. // Initialize script-processing/data-receipt
  536. //
  537. {
  538. CHAR* pszUserName;
  539. CHAR* pszPassword;
  540. pszUserName = StrDupAFromT( pInfo->pArgs->pRdp->szUserName );
  541. // Whistler bug 254385 encode password when not being used
  542. // Assumed password was encoded by DpInteractive() -or- DwTerminalDlg()
  543. //
  544. DecodePassword( pInfo->pArgs->pRdp->szPassword );
  545. pszPassword = StrDupAFromT( pInfo->pArgs->pRdp->szPassword );
  546. EncodePassword( pInfo->pArgs->pRdp->szPassword );
  547. // Initialize the script. The script DLL is 'delayload' hence the
  548. // exception handling.
  549. //
  550. __try
  551. {
  552. dwErr = RasScriptInit(
  553. pInfo->pArgs->hrasconn, pInfo->pArgs->pEntry,
  554. pszUserName, pszPassword, RASSCRIPT_NotifyOnInput |
  555. RASSCRIPT_HwndNotify, (HANDLE)hwndDlg, &pInfo->hscript );
  556. TRACE1( "RasScriptInit(e=%d)", dwErr );
  557. }
  558. __except( EXCEPTION_EXECUTE_HANDLER )
  559. {
  560. ErrorDlg(
  561. hwndDlg, SID_OP_LoadDlg, STATUS_PROCEDURE_NOT_FOUND, NULL );
  562. EndDialog( hwndDlg, FALSE );
  563. return TRUE;
  564. }
  565. Free0( pszUserName );
  566. // Whistler bug 254385 encode password when not being used
  567. // Whistler bug 275526 NetVBL BVT Break: Routing BVT broken
  568. //
  569. if (pszPassword)
  570. {
  571. ZeroMemory( pszPassword, strlen(pszPassword) + 1 );
  572. Free( pszPassword );
  573. }
  574. // See whether anything went wrong in the script-initialization
  575. //
  576. if (dwErr == ERROR_SCRIPT_SYNTAX)
  577. {
  578. MSGARGS msg;
  579. INT nResponse;
  580. // There was a syntax error in the script; show a popup asking if
  581. // the user wants to view the errors, and if so bring up Notepad
  582. // on %windir%\system32\ras\script.log.
  583. //
  584. // Center the dialog on our parent rather than on the dialog,
  585. // since the dialog is not yet visible.
  586. //
  587. ZeroMemory(&msg, sizeof(msg));
  588. msg.dwFlags = MB_YESNO | MB_ICONQUESTION;
  589. nResponse = MsgDlg( GetParent( hwndDlg ),
  590. SID_ConfirmViewScriptLog, &msg );
  591. if (nResponse == IDYES)
  592. {
  593. ItViewScriptLog( hwndDlg );
  594. }
  595. // Terminate the dialog. This hangs up the connection.
  596. //
  597. EndDialog( hwndDlg, FALSE );
  598. return TRUE;
  599. }
  600. else if (dwErr != 0)
  601. {
  602. ErrorDlg( hwndDlg, SID_OP_LoadDlg, dwErr, NULL );
  603. EndDialog( hwndDlg, FALSE );
  604. return TRUE;
  605. }
  606. }
  607. // Center dialog on the owner window, and hide the owner window which is
  608. // currently assumed to be the dial progress dialog.
  609. //
  610. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  611. SetOffDesktop( GetParent( hwndDlg ), SOD_MoveOff, NULL );
  612. // Add context help button to title bar.
  613. //
  614. AddContextHelpButton( hwndDlg );
  615. // Set initial focus to the screen.
  616. //
  617. SetFocus( pInfo->hwndEbScreen );
  618. return FALSE;
  619. }
  620. BOOL
  621. ItRasApiComplete(
  622. IN ITINFO* pInfo )
  623. // Called on WM_RASAPICOMPLETE, i.e. an asynchronous RasPortReceive
  624. // completed. 'PInfo' is the dialog context block.
  625. //
  626. // Returns true if processed the message, false otherwise.
  627. //
  628. {
  629. DWORD dwErr;
  630. DWORD dwSize = SIZE_ReceiveBuf;
  631. RASMAN_INFO info;
  632. TRACE( "RasScriptReceive" );
  633. dwErr = RasScriptReceive(
  634. pInfo->hscript, pInfo->pbyteReceiveBuf, &dwSize);
  635. TRACE1( "RasScriptReceive=%d",dwErr );
  636. if (dwErr != 0)
  637. {
  638. ErrorDlg( pInfo->hwndDlg, SID_OP_RasGetInfo, dwErr, NULL );
  639. EndDialog( pInfo->hwndDlg, FALSE );
  640. return TRUE;
  641. }
  642. info.RI_BytesReceived = (WORD )dwSize;
  643. // Send the device talk to the terminal edit box.
  644. //
  645. if (info.RI_BytesReceived > 0)
  646. {
  647. CHAR szBuf[ SIZE_ReceiveBuf + 1 ];
  648. CHAR* pch = szBuf;
  649. WORD i;
  650. TRACE1( "Read %d", info.RI_BytesReceived );
  651. for (i = 0; i < info.RI_BytesReceived; ++i)
  652. {
  653. CHAR ch = pInfo->pbyteReceiveBuf[ i ];
  654. // Formatting: Converts CRs to LFs (there seems to be no VK_ for
  655. // LF) and throws away LFs. This prevents the user from exiting
  656. // the dialog when they press Enter (CR) in the terminal screen.
  657. // LF looks like CRLF in the edit box. Also, throw away TABs
  658. // because otherwise they change focus to the next control.
  659. //
  660. if (ch == VK_RETURN)
  661. {
  662. // Must send whenever end-of-line is encountered because
  663. // EM_REPLACESEL doesn't handle VK_RETURN characters well
  664. // (prints garbage).
  665. //
  666. *pch = '\0';
  667. // Turn off current selection, if any, and replace the null
  668. // selection with the current buffer. This has the effect of
  669. // adding the buffer at the caret. Finally, send the EOL to
  670. // the window which (unlike EM_REPLACESEL) handles it
  671. // correctly.
  672. //
  673. Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 );
  674. SendMessageA( pInfo->hwndEbScreen,
  675. EM_REPLACESEL, (WPARAM )0, (LPARAM )szBuf );
  676. SendMessage( pInfo->hwndEbScreen, WM_EOLFROMDEVICE, 0, 0 );
  677. // Start afresh on the output buffer.
  678. //
  679. pch = szBuf;
  680. continue;
  681. }
  682. else if (ch == '\n' || ch == VK_TAB)
  683. {
  684. continue;
  685. }
  686. *pch++ = ch;
  687. }
  688. *pch = '\0';
  689. if (pch != szBuf)
  690. {
  691. // Send the last remnant of the line.
  692. //
  693. Edit_SetSel( pInfo->hwndEbScreen, (UINT )-1, 0 );
  694. SendMessageA( pInfo->hwndEbScreen,
  695. EM_REPLACESEL, (WPARAM )0, (LPARAM )szBuf );
  696. }
  697. }
  698. return TRUE;
  699. }
  700. VOID
  701. ItTerm(
  702. IN HWND hwndDlg )
  703. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  704. //
  705. {
  706. ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  707. TRACE( "ItTerm" );
  708. if (pInfo)
  709. {
  710. // Close RAS script resources
  711. //
  712. if (pInfo->hscript)
  713. {
  714. TRACE( "Stop script processing" );
  715. // Shutdown script processing
  716. //
  717. TRACE( "RasScriptTerm" );
  718. RasScriptTerm( pInfo->hscript );
  719. TRACE( "RasScriptTerm done" );
  720. }
  721. // De-activate WndProc hooks.
  722. //
  723. if (pInfo->pOldEbScreenWndProc)
  724. {
  725. SetWindowLongPtr( pInfo->hwndEbScreen,
  726. GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldEbScreenWndProc );
  727. }
  728. if (pInfo->pOldWndProc)
  729. {
  730. SetWindowLongPtr( pInfo->hwndDlg,
  731. GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldWndProc );
  732. }
  733. if (pInfo->hfontEbScreen)
  734. {
  735. DeleteObject( (HGDIOBJ )pInfo->hfontEbScreen );
  736. }
  737. SetOffDesktop( GetParent( hwndDlg ), SOD_MoveBackFree, NULL );
  738. Free( pInfo );
  739. }
  740. }
  741. VOID
  742. ItViewScriptLog(
  743. IN HWND hwndOwner )
  744. // Starts notepad.exe on the script log file, script.log. 'HwndOwner' is
  745. // the window to center any error popup on.
  746. //
  747. {
  748. DWORD dwSize;
  749. TCHAR szCmd[ (MAX_PATH * 2) + 50 + 1 ];
  750. TCHAR* pszCmd;
  751. STARTUPINFO si;
  752. PROCESS_INFORMATION pi;
  753. BOOL f;
  754. // Format the command-line string invoking Notepad on the script-log; note
  755. // the double-quotes around the script-log's path, which are needed since
  756. // RASSCRIPT_LOG is %windir%\system32\ras\script.log and so the expanded
  757. // result may contain spaces.
  758. //
  759. wsprintf( szCmd, TEXT("notepad.exe \"%s\""), TEXT(RASSCRIPT_LOG) );
  760. // Get the size of the expanded command-line
  761. //
  762. dwSize = ExpandEnvironmentStrings(szCmd, NULL, 0);
  763. // Allocate enough space for the expanded command-line
  764. //
  765. pszCmd = Malloc( (dwSize + 1) * sizeof(TCHAR) );
  766. if (!pszCmd)
  767. {
  768. ErrorDlg( hwndOwner, SID_OP_LoadScriptLog, GetLastError(), NULL );
  769. return;
  770. }
  771. // Expand the command-line into the allocated space
  772. //
  773. ExpandEnvironmentStrings(szCmd, pszCmd, dwSize);
  774. // Initialize the startup-info structure
  775. //
  776. ZeroMemory( &si, sizeof(si) );
  777. si.cb = sizeof(si);
  778. // Launch Notepad on the script-log.
  779. //
  780. f = CreateProcess(
  781. NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi );
  782. Free(pszCmd);
  783. if (f)
  784. {
  785. CloseHandle( pi.hThread );
  786. CloseHandle( pi.hProcess );
  787. }
  788. else
  789. {
  790. ErrorDlg( hwndOwner, SID_OP_LoadScriptLog, GetLastError(), NULL );
  791. }
  792. }
  793. LRESULT APIENTRY
  794. ItWndProc(
  795. HWND hwnd,
  796. UINT unMsg,
  797. WPARAM wParam,
  798. LPARAM lParam )
  799. // Subclassed dialog window procedure.
  800. //
  801. // Return value depends on message type.
  802. //
  803. {
  804. ITINFO* pInfo = (ITINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  805. ASSERT(pInfo);
  806. #if 0
  807. TRACE4( "ItWndProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  808. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  809. #endif
  810. switch (unMsg)
  811. {
  812. case WM_CTLCOLOREDIT:
  813. {
  814. // Set terminal screen colors to TTY-ish green on black.
  815. //
  816. if (pInfo->hbrEbScreen)
  817. {
  818. SetBkColor( (HDC )wParam, RGB( 0, 0, 0 ) );
  819. SetTextColor( (HDC )wParam, RGB( 2, 208, 44 ) );
  820. return (LRESULT )pInfo->hbrEbScreen;
  821. }
  822. break;
  823. }
  824. }
  825. // Call the previous window procedure for everything else.
  826. //
  827. return
  828. CallWindowProc(
  829. pInfo->pOldWndProc, hwnd, unMsg, wParam, lParam );
  830. }