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.

10700 lines
287 KiB

  1. // Copyright (c) 1995, Microsoft Corporation, all rights reserved
  2. //
  3. // dial.c
  4. // Remote Access Common Dialog APIs
  5. // RasDialDlg APIs
  6. //
  7. // 11/19/95 Steve Cobb
  8. #include "rasdlgp.h"
  9. #include "raseapif.h"
  10. #include "inetcfgp.h"
  11. #include "netconp.h"
  12. // Posted message codes for tasks that should not or cannot occur in the
  13. // RasDial callback.
  14. //
  15. #define WM_RASEVENT 0xCCCC
  16. #define WM_RASERROR 0xCCCD
  17. #define WM_RASDIAL 0xCCCE
  18. #define WM_RASBUNDLEERROR 0xCCCF
  19. // Dialer dialog mode bits
  20. //
  21. #define DR_U 0x00000001 // Username and password present
  22. #define DR_D 0x00000002 // Domain present
  23. #define DR_N 0x00000004 // Phone number present
  24. #define DR_L 0x00000008 // Location controls present
  25. #define DR_I 0x00000010 // Eap identity dialog
  26. // Internal constants used by DrXxx routines to implement the "manual edit"
  27. // combo-box.
  28. //
  29. #define DR_WM_SETTEXT 0xCCC0
  30. #define DR_BOGUSWIDTH 19591
  31. #define EAP_RASTLS 13
  32. //----------------------------------------------------------------------------
  33. // Help maps
  34. //----------------------------------------------------------------------------
  35. static DWORD g_adwDrHelp[] =
  36. {
  37. CID_DR_BM_Useless, HID_DR_BM_Useless,
  38. CID_DR_ST_User, HID_DR_EB_User,
  39. CID_DR_EB_User, HID_DR_EB_User,
  40. CID_DR_ST_Password, HID_DR_EB_Password,
  41. CID_DR_EB_Password, HID_DR_EB_Password,
  42. CID_DR_ST_Domain, HID_DR_EB_Domain,
  43. CID_DR_EB_Domain, HID_DR_EB_Domain,
  44. CID_DR_CB_SavePassword, HID_DR_CB_SavePassword,
  45. CID_DR_ST_Numbers, HID_DR_CLB_Numbers,
  46. CID_DR_CLB_Numbers, HID_DR_CLB_Numbers,
  47. CID_DR_ST_Locations, HID_DR_LB_Locations,
  48. CID_DR_LB_Locations, HID_DR_LB_Locations,
  49. CID_DR_PB_Rules, HID_DR_PB_Rules,
  50. CID_DR_PB_Properties, HID_DR_PB_Properties,
  51. CID_DR_PB_DialConnect, HID_DR_PB_DialConnect,
  52. CID_DR_PB_Cancel, HID_DR_PB_Cancel,
  53. CID_DR_PB_Help, HID_DR_PB_Help,
  54. CID_DR_RB_SaveForMe, HID_DR_RB_SaveForMe,
  55. CID_DR_RB_SaveForEveryone, HID_DR_RB_SaveForEveryone,
  56. 0, 0
  57. };
  58. static DWORD g_adwCpHelp[] =
  59. {
  60. CID_CP_ST_Explain, HID_CP_ST_Explain,
  61. CID_CP_ST_OldPassword, HID_CP_EB_OldPassword,
  62. CID_CP_EB_OldPassword, HID_CP_EB_OldPassword,
  63. CID_CP_ST_Password, HID_CP_EB_Password,
  64. CID_CP_EB_Password, HID_CP_EB_Password,
  65. CID_CP_ST_ConfirmPassword, HID_CP_EB_ConfirmPassword,
  66. CID_CP_EB_ConfirmPassword, HID_CP_EB_ConfirmPassword,
  67. 0, 0
  68. };
  69. static DWORD g_adwDcHelp[] =
  70. {
  71. CID_DC_ST_Explain, HID_DC_ST_Explain,
  72. CID_DC_ST_Number, HID_DC_EB_Number,
  73. CID_DC_EB_Number, HID_DC_EB_Number,
  74. 0, 0
  75. };
  76. static DWORD g_adwDeHelp[] =
  77. {
  78. CID_DE_PB_More, HID_DE_PB_More,
  79. IDOK, HID_DE_PB_Redial,
  80. 0, 0
  81. };
  82. static DWORD g_adwPrHelp[] =
  83. {
  84. CID_PR_ST_Text, HID_PR_ST_Text,
  85. CID_PR_CB_DisableProtocols, CID_PR_CB_DisableProtocols,
  86. IDOK, HID_PR_PB_Accept,
  87. IDCANCEL, HID_PR_PB_HangUp,
  88. 0, 0
  89. };
  90. static DWORD g_adwUaHelp[] =
  91. {
  92. CID_UA_ST_UserName, HID_UA_EB_UserName,
  93. CID_UA_EB_UserName, HID_UA_EB_UserName,
  94. CID_UA_ST_Password, HID_UA_EB_Password,
  95. CID_UA_EB_Password, HID_UA_EB_Password,
  96. CID_UA_ST_Domain, HID_UA_EB_Domain,
  97. CID_UA_EB_Domain, HID_UA_EB_Domain,
  98. CID_UA_CB_SavePassword, HID_UA_CB_SavePassword,
  99. 0, 0
  100. };
  101. CONST WCHAR g_pszSavedPasswordToken[] = L"****************";
  102. #define g_dwSavedPasswordTokenLength \
  103. ( sizeof(g_pszSavedPasswordToken) / sizeof(TCHAR) )
  104. // Save password macro, determines if either User or Global password is saved
  105. // (p) must be a pointer to a DINFO struct (see dial.c)
  106. //
  107. // Whistler bug: 288234 When switching back and forth from "I connect" and
  108. // "Any user connects" password is not caching correctly
  109. //
  110. #define HaveSavedPw(p) \
  111. ((p)->fHaveSavedPwUser || (p)->fHaveSavedPwGlobal)
  112. //----------------------------------------------------------------------------
  113. // Local datatypes
  114. //----------------------------------------------------------------------------
  115. // Dial dialogs common context block. This block contains information common
  116. // to more than one dialog in the string of dial-related dialogs.
  117. //
  118. typedef struct
  119. _DINFO
  120. {
  121. // Caller's arguments to the RAS API. Outputs in 'pArgs' are visible to
  122. // the API which has the address of same. Careful using 'pszEntry' as
  123. // 'pEntry->pszEntryName' is generally more appropriate, the latter
  124. // reflecting the name of any prerequisite entry while the prequisite is
  125. // being dialed.
  126. //
  127. LPTSTR pszPhonebook;
  128. LPTSTR pszEntry;
  129. LPTSTR pszPhoneNumber;
  130. RASDIALDLG* pArgs;
  131. // Phonebook settings read from the phonebook file. All access should be
  132. // thru 'pFile'. 'PFile' is set to either '&filePrereq' or 'pFileMain'
  133. // depending on 'fFilePrereqOpen'. 'File' will only be used in cases
  134. // where the open phonebook is not passed thru the reserved word hack, and
  135. // in that case 'pFileMain' will point to it. 'FilePrereq' is the
  136. // phonebook file of the prequisite entry which may be different from the
  137. // main entry. During prerequisite dial 'pFile' points to 'filePrereq'
  138. // rather than 'file' and 'fFilePrereqOpen is true. Otherwise, 'pFile'
  139. // points to whatever 'pFileMain' points at.
  140. //
  141. PBFILE* pFile;
  142. PBFILE* pFileMain;
  143. PBFILE file;
  144. PBFILE filePrereq;
  145. BOOL fFilePrereqOpen;
  146. BOOL fIsPublicPbk;
  147. // Global preferences read via phonebook library. All access should be
  148. // thru 'pUser' as 'user' will only be used in cases where the preferences
  149. // are not passed thru the reserved word hack.
  150. //
  151. PBUSER* pUser;
  152. PBUSER user;
  153. // User credentials provided by API caller for "during logon" dialing
  154. // where there is no current user. If user changes the credentials
  155. // *pfNoUserChanged is set and the 'pNoUser' credentials updated.
  156. //
  157. RASNOUSER* pNoUser;
  158. BOOL* pfNoUserChanged;
  159. // Set if the call is unattended, i.e. a call by RASAUTO to redial a
  160. // failed link.
  161. //
  162. BOOL fUnattended;
  163. // Private flags from calling RAS API, the first informing us he wants to
  164. // be hidden off the desktop while we dial, and the second that he will
  165. // close if we return "connected" so we can avoid flicker and not bother
  166. // restoring him.
  167. //
  168. BOOL fMoveOwnerOffDesktop;
  169. BOOL fForceCloseOnDial;
  170. // Set when something occurs during dial that affects the phonebook entry.
  171. // The entry is re-read after a successful connection.
  172. //
  173. BOOL fResetAutoLogon;
  174. DWORD dwfExcludedProtocols;
  175. DTLLIST* pListPortsToDelete;
  176. // The entry node and a shortcut pointer to the entry inside.
  177. //
  178. DTLNODE* pNode;
  179. PBENTRY* pEntry;
  180. // The entry of the main entry that referred to any prerequisite entry
  181. // that might be contained by 'pEntry'. If no prerequisite entry is
  182. // involved this is the same as 'pEntry'.
  183. //
  184. PBENTRY* pEntryMain;
  185. // Set is admin has disabled the save password feature in the registry.
  186. //
  187. BOOL fDisableSavePw;
  188. // Set true if a cached password is available for the entry.
  189. //
  190. BOOL fHaveSavedPwUser; // whether there are saved per-user creds
  191. BOOL fHaveSavedPwGlobal; // whether there are saved per-connect creds
  192. // Set when the dial in progress is the prerequisite entry, rather than
  193. // the main entry.
  194. //
  195. BOOL fPrerequisiteDial;
  196. // Set when calling RasDial on a connected entry to add a reference only.
  197. // All interaction with user is skipped in this case. See bug 272794.
  198. //
  199. BOOL fDialForReferenceOnly;
  200. // The dial parameters used on this connection attempt. Initialized in
  201. // RasDialDlgW. Credentials are updated by DialerDlg. Callback number is
  202. // updated by DialProgressDlg.
  203. //
  204. RASDIALPARAMS rdp; // actual dial parameters passed to RasDial
  205. RASDIALPARAMS rdpu; // per-user credentials
  206. RASDIALPARAMS rdpg; // per-connection credentials
  207. // The dial parameter extensions used on this connection attempt. Set in
  208. // RasDialDlgW, except hwndOwner which is set in DialProgressDlg.
  209. //
  210. RASDIALEXTENSIONS rde;
  211. }
  212. DINFO;
  213. // Dialer dialogs argument block. Used for all 5 variations of the dialer.
  214. //
  215. typedef struct
  216. _DRARGS
  217. {
  218. DINFO* pDinfo;
  219. DWORD dwfMode;
  220. DWORD fReload;
  221. }
  222. DRARGS;
  223. // Dialer dialogs context block. Used for all 5 variations of the dialer.
  224. //
  225. typedef struct
  226. DRINFO
  227. {
  228. // Common dial context information including the RAS API arguments.
  229. //
  230. DRARGS* pArgs;
  231. // Handle of the dialog and some of it's controls.
  232. //
  233. HWND hwndDlg;
  234. HWND hwndEbUser;
  235. HWND hwndEbPw;
  236. HWND hwndEbDomain;
  237. HWND hwndCbSavePw;
  238. HWND hwndRbSaveForMe;
  239. HWND hwndRbSaveForEveryone;
  240. HWND hwndClbNumbers;
  241. HWND hwndStLocations;
  242. HWND hwndLbLocations;
  243. HWND hwndPbRules;
  244. HWND hwndPbProperties;
  245. HWND hwndBmDialer;
  246. // Whistler bug: 195480 Dial-up connection dialog - Number of
  247. // asterisks does not match the length of the password and causes
  248. // confusion
  249. //
  250. WCHAR szPasswordChar;
  251. HFONT hNormalFont;
  252. HFONT hItalicFont;
  253. // TAPI session handle.
  254. //
  255. HLINEAPP hlineapp;
  256. // The phonebook entry link containing the displayed phone number list.
  257. // Set up only when DR_N mode bit is set.
  258. //
  259. DTLNODE* pLinkNode;
  260. PBLINK* pLink;
  261. // The index of the item initially selected in the phone number list.
  262. //
  263. DWORD iFirstSelectedPhone;
  264. // Window handles and original window procedure of the subclassed
  265. // 'hwndClbNumbers' control's edit-box and list-box child windows.
  266. //
  267. HWND hwndClbNumbersEb;
  268. HWND hwndClbNumbersLb;
  269. WNDPROC wndprocClbNumbersEb;
  270. WNDPROC wndprocClbNumbersLb;
  271. INetConnectionUiUtilities * pNetConUtilities;
  272. // Set if COM has been initialized (necessary for calls to netshell).
  273. //
  274. BOOL fComInitialized;
  275. // Handle to the original bitmap for the dialer if it is modified
  276. // in DrSetBitmap
  277. //
  278. HBITMAP hbmOrig;
  279. }
  280. DRINFO;
  281. // Context of an item in the dialer's 'ClbNumbers' list.
  282. //
  283. typedef struct
  284. _DRNUMBERSITEM
  285. {
  286. TCHAR* pszNumber;
  287. PBPHONE* pPhone;
  288. }
  289. DRNUMBERSITEM;
  290. // Subentry state information.
  291. //
  292. typedef struct
  293. _DPSTATE
  294. {
  295. RASCONNSTATE state;
  296. DWORD dwError;
  297. DWORD dwExtendedError;
  298. TCHAR szExtendedError[ NETBIOS_NAME_LEN + 1 ];
  299. TCHAR* pszStatusArg;
  300. TCHAR* pszFormatArg;
  301. PBDEVICETYPE pbdt;
  302. DWORD sidState;
  303. DWORD sidFormatMsg;
  304. DWORD sidPrevState;
  305. BOOL fNotPreSwitch;
  306. HRASCONN hrasconnLink;
  307. }
  308. DPSTATE;
  309. // Dial Progress dialog context block.
  310. //
  311. typedef struct
  312. _DPINFO
  313. {
  314. // When the block is valid contains the value 0xC0BBC0DE, otherwise 0.
  315. // Used as a workaround until RasDial is fixed to stop calling
  316. // RasDialFunc2 after being told not to, see bug 49469.
  317. //
  318. DWORD dwValid;
  319. // RAS API arguments.
  320. //
  321. DINFO* pArgs;
  322. // Handle of this dialog and some of it's controls.
  323. //
  324. HWND hwndDlg;
  325. HWND hwndStState;
  326. // The saved username and password that authenticated but resulted in a
  327. // change password event. If the change password operation fails these
  328. // are restored to make the redial button work properly.
  329. //
  330. TCHAR* pszGoodUserName;
  331. TCHAR* pszGoodPassword;
  332. // The handle to the RAS connection being initiated.
  333. //
  334. HRASCONN hrasconn;
  335. // The original window proc we subclassed.
  336. //
  337. WNDPROC pOldWndProc;
  338. // Number of auto-redials not yet attempted on the connection.
  339. //
  340. DWORD dwRedialAttemptsLeft;
  341. // Array of RasDial states, one per subentry, set by DpRasDialFunc2 and
  342. // used by DpRasDialEvent.
  343. //
  344. DPSTATE* pStates;
  345. DWORD cStates;
  346. // The number of the most advanced subentry and the "latest" state it has
  347. // reached. Note that certain states, like RASCS_AuthNotify, are
  348. // revisited after reaching a "later" state. Such changes are ignored.
  349. //
  350. RASCONNSTATE state;
  351. DWORD dwSubEntry;
  352. // Flag indicating that RasDial callbacks are active. The callback
  353. // context must not be destroyed when this flag is set. Access to this
  354. // field is protected by 'g_hmutexCallbacks'. See DpCallbacksFlag().
  355. //
  356. BOOL fCallbacksActive;
  357. //Add a per-thread Terminate flag for whistler bug 277365,291613 gangz
  358. //
  359. BOOL fTerminateAsap;
  360. LONG ulCallbacksActive;
  361. //for whistler bug 381337
  362. //
  363. BOOL fCancelPressed;
  364. }
  365. DPINFO;
  366. // Dial Error dialog argument block.
  367. //
  368. typedef struct
  369. _DEARGS
  370. {
  371. TCHAR* pszEntry;
  372. DWORD dwError;
  373. DWORD sidState;
  374. TCHAR* pszStatusArg;
  375. DWORD sidFormatMsg;
  376. TCHAR* pszFormatArg;
  377. LONG lRedialCountdown;
  378. BOOL fPopupOnTop;
  379. }
  380. DEARGS;
  381. // Dial Error dialog context block.
  382. //
  383. typedef struct
  384. _DEINFO
  385. {
  386. // Caller's arguments to the stub API.
  387. //
  388. DEARGS* pArgs;
  389. // Handle of dialog and controls.
  390. //
  391. HWND hwndDlg;
  392. HWND hwndStText;
  393. HWND hwndPbRedial;
  394. HWND hwndPbCancel;
  395. HWND hwndPbMore;
  396. // Number of seconds remaining in "Redial=x" countdown or -1 if inactive.
  397. //
  398. LONG lRedialCountdown;
  399. }
  400. DEINFO;
  401. // Projection Result dialog argument block.
  402. //
  403. typedef struct
  404. _PRARGS
  405. {
  406. TCHAR* pszLines;
  407. BOOL* pfDisableFailedProtocols;
  408. }
  409. PRARGS;
  410. // Change Password dialog argument block.
  411. //
  412. typedef struct
  413. _CPARGS
  414. {
  415. BOOL fOldPassword;
  416. TCHAR* pszOldPassword;
  417. TCHAR* pszNewPassword;
  418. }
  419. CPARGS;
  420. // Change Password dialog context block.
  421. // (unconventional name because CPINFO conflicts with a system header)
  422. //
  423. typedef struct
  424. _CPWINFO
  425. {
  426. // Caller's arguments to the stub API.
  427. //
  428. CPARGS* pArgs;
  429. // Handle of dialog and controls.
  430. //
  431. HWND hwndDlg;
  432. HWND hwndEbOldPassword;
  433. HWND hwndEbNewPassword;
  434. HWND hwndEbNewPassword2;
  435. }
  436. CPWINFO;
  437. // Retry Authentication dialog context block.
  438. //
  439. typedef struct
  440. UAINFO
  441. {
  442. // Commond dial context including original RAS API arguments.
  443. //
  444. DINFO* pArgs;
  445. // Handle of this dialog and some of it's controls.
  446. //
  447. HWND hwndDlg;
  448. HWND hwndEbUserName;
  449. HWND hwndEbPassword;
  450. HWND hwndEbDomain;
  451. HWND hwndCbSavePw;
  452. // Set when the password field contains a phony password in place of the
  453. // "" one we don't really know.
  454. //
  455. BOOL fAutoLogonPassword;
  456. // Set when the Domain field is present.
  457. //
  458. BOOL fDomain;
  459. }
  460. UAINFO;
  461. //-----------------------------------------------------------------------------
  462. // Local prototypes (alphabetically)
  463. //-----------------------------------------------------------------------------
  464. BOOL
  465. BeCommand(
  466. IN HWND hwnd,
  467. IN WORD wNotification,
  468. IN WORD wId,
  469. IN HWND hwndCtrl );
  470. INT_PTR CALLBACK
  471. BeDlgProc(
  472. IN HWND hwnd,
  473. IN UINT unMsg,
  474. IN WPARAM wparam,
  475. IN LPARAM lparam );
  476. VOID
  477. BeFillLvErrors(
  478. IN HWND hwndLv,
  479. IN DPINFO* pInfo );
  480. TCHAR*
  481. BeGetErrorPsz(
  482. IN DWORD dwError );
  483. BOOL
  484. BeInit(
  485. IN HWND hwndDlg,
  486. IN DPINFO* pArgs );
  487. LVXDRAWINFO*
  488. BeLvErrorsCallback(
  489. IN HWND hwndLv,
  490. IN DWORD dwItem );
  491. BOOL
  492. BundlingErrorsDlg(
  493. IN OUT DPINFO* pInfo );
  494. BOOL
  495. ChangePasswordDlg(
  496. IN HWND hwndOwner,
  497. IN BOOL fOldPassword,
  498. OUT TCHAR* pszOldPassword,
  499. OUT TCHAR* pszNewPassword );
  500. BOOL
  501. CpCommand(
  502. IN HWND hwnd,
  503. IN WORD wNotification,
  504. IN WORD wId,
  505. IN HWND hwndCtrl );
  506. INT_PTR CALLBACK
  507. CpDlgProc(
  508. IN HWND hwnd,
  509. IN UINT unMsg,
  510. IN WPARAM wparam,
  511. IN LPARAM lparam );
  512. BOOL
  513. CpInit(
  514. IN HWND hwndDlg,
  515. IN CPARGS* pArgs );
  516. BOOL
  517. CcCommand(
  518. IN HWND hwnd,
  519. IN WORD wNotification,
  520. IN WORD wId,
  521. IN HWND hwndCtrl );
  522. INT_PTR CALLBACK
  523. CcDlgProc(
  524. IN HWND hwnd,
  525. IN UINT unMsg,
  526. IN WPARAM wparam,
  527. IN LPARAM lparam );
  528. BOOL
  529. CcInit(
  530. IN HWND hwndDlg,
  531. IN DINFO* pInfo );
  532. VOID
  533. ConnectCompleteDlg(
  534. IN HWND hwndOwner,
  535. IN DINFO* pInfo );
  536. BOOL
  537. DcCommand(
  538. IN HWND hwnd,
  539. IN WORD wNotification,
  540. IN WORD wId,
  541. IN HWND hwndCtrl );
  542. INT_PTR CALLBACK
  543. DcDlgProc(
  544. IN HWND hwnd,
  545. IN UINT unMsg,
  546. IN WPARAM wparam,
  547. IN LPARAM lparam );
  548. BOOL
  549. DcInit(
  550. IN HWND hwndDlg,
  551. IN TCHAR* pszNumber );
  552. VOID
  553. DeAdjustPbRedial(
  554. IN DEINFO* pInfo );
  555. BOOL
  556. DeCommand(
  557. IN HWND hwnd,
  558. IN WORD wNotification,
  559. IN WORD wId,
  560. IN HWND hwndCtrl );
  561. INT_PTR CALLBACK
  562. DeDlgProc(
  563. IN HWND hwnd,
  564. IN UINT unMsg,
  565. IN WPARAM wparam,
  566. IN LPARAM lparam );
  567. BOOL
  568. DeInit(
  569. IN HWND hwndDlg,
  570. IN DEARGS* pArgs );
  571. DWORD
  572. DeleteSavedCredentials(
  573. IN DINFO* pDinfo,
  574. IN HWND hwndDlg,
  575. IN BOOL fDefault,
  576. IN BOOL fDeleteIdentity );
  577. VOID
  578. DeTerm(
  579. IN HWND hwndDlg );
  580. BOOL
  581. DialCallbackDlg(
  582. IN HWND hwndOwner,
  583. IN OUT TCHAR* pszNumber );
  584. BOOL
  585. DialErrorDlg(
  586. IN HWND hwndOwner,
  587. IN TCHAR* pszEntry,
  588. IN DWORD dwError,
  589. IN DWORD sidState,
  590. IN TCHAR* pszStatusArg,
  591. IN DWORD sidFormatMsg,
  592. IN TCHAR* pszFormatArg,
  593. IN LONG lRedialCountdown,
  594. IN BOOL fPopupOnTop );
  595. BOOL
  596. DialerDlg(
  597. IN HWND hwndOwner,
  598. IN OUT DINFO* pInfo );
  599. BOOL
  600. DialProgressDlg(
  601. IN DINFO* pInfo );
  602. VOID
  603. DpAppendBlankLine(
  604. IN OUT TCHAR* pszLines );
  605. VOID
  606. DpAppendConnectErrorLine(
  607. IN OUT TCHAR* pszLines,
  608. IN DWORD sidProtocol,
  609. IN DWORD dwError );
  610. VOID
  611. DpAppendConnectOkLine(
  612. IN OUT TCHAR* pszLines,
  613. IN DWORD sidProtocol );
  614. VOID
  615. DpAppendFailCodeLine(
  616. IN OUT TCHAR* pszLines,
  617. IN DWORD dw );
  618. VOID
  619. DpAppendNameLine(
  620. IN OUT TCHAR* pszLines,
  621. IN TCHAR* psz );
  622. VOID
  623. DpAuthNotify(
  624. IN DPINFO* pInfo,
  625. IN DPSTATE* pState );
  626. VOID
  627. DpCallbackSetByCaller(
  628. IN DPINFO* pInfo,
  629. IN DPSTATE* pState );
  630. BOOL
  631. DpCallbacksFlag(
  632. IN DPINFO* pInfo,
  633. IN INT nSet );
  634. VOID
  635. DpCancel(
  636. IN DPINFO* pInfo );
  637. BOOL
  638. DpCommand(
  639. IN DPINFO* pInfo,
  640. IN WORD wNotification,
  641. IN WORD wId,
  642. IN HWND hwndCtrl );
  643. VOID
  644. DpConnectDevice(
  645. IN DPINFO* pInfo,
  646. IN DPSTATE* pState );
  647. VOID
  648. DpDeviceConnected(
  649. IN DPINFO* pInfo,
  650. IN DPSTATE* pState );
  651. VOID
  652. DpDial(
  653. IN DPINFO* pInfo,
  654. IN BOOL fPauseRestart );
  655. INT_PTR CALLBACK
  656. DpDlgProc(
  657. IN HWND hwnd,
  658. IN UINT unMsg,
  659. IN WPARAM wparam,
  660. IN LPARAM lparam );
  661. VOID
  662. DpError(
  663. IN DPINFO* pInfo,
  664. IN DPSTATE* pState );
  665. DWORD
  666. DpEvent(
  667. IN DPINFO* pInfo,
  668. IN DWORD dwSubEntry );
  669. BOOL
  670. DpInit(
  671. IN HWND hwndDlg,
  672. IN DINFO* pArgs );
  673. VOID
  674. DpInitStates(
  675. DPINFO* pInfo );
  676. BOOL
  677. DpInteractive(
  678. IN DPINFO* pInfo,
  679. IN DPSTATE* pState,
  680. OUT BOOL* pfChange );
  681. BOOL
  682. DpIsLaterState(
  683. IN RASCONNSTATE stateNew,
  684. IN RASCONNSTATE stateOld );
  685. BOOL
  686. DpPasswordExpired(
  687. IN DPINFO* pInfo,
  688. IN DPSTATE* pState );
  689. BOOL
  690. DpProjected(
  691. IN DPINFO* pInfo,
  692. IN DPSTATE* pState );
  693. BOOL
  694. DpProjectionError(
  695. IN RASPPPNBF* pnbf,
  696. IN RASPPPIPX* pipx,
  697. IN RASPPPIP* pip,
  698. OUT BOOL* pfIncomplete,
  699. OUT DWORD* pdwfFailedProtocols,
  700. OUT TCHAR** ppszLines,
  701. OUT DWORD* pdwError );
  702. DWORD WINAPI
  703. DpRasDialFunc2(
  704. ULONG_PTR dwCallbackId,
  705. DWORD dwSubEntry,
  706. HRASCONN hrasconn,
  707. UINT unMsg,
  708. RASCONNSTATE state,
  709. DWORD dwError,
  710. DWORD dwExtendedError );
  711. VOID
  712. DpTerm(
  713. IN HWND hwndDlg );
  714. INT_PTR CALLBACK
  715. DrDlgProc(
  716. IN HWND hwnd,
  717. IN UINT unMsg,
  718. IN WPARAM wparam,
  719. IN LPARAM lparam );
  720. BOOL CALLBACK
  721. DrClbNumbersEnumChildProc(
  722. IN HWND hwnd,
  723. IN LPARAM lparam );
  724. BOOL CALLBACK
  725. DrClbNumbersEnumWindowsProc(
  726. IN HWND hwnd,
  727. IN LPARAM lparam );
  728. BOOL
  729. DrCommand(
  730. IN DRINFO* pInfo,
  731. IN WORD wNotification,
  732. IN WORD wId,
  733. IN HWND hwndCtrl );
  734. VOID
  735. DrEditSelectedLocation(
  736. IN DRINFO* pInfo );
  737. DWORD
  738. DrFillLocationList(
  739. IN DRINFO* pInfo );
  740. VOID
  741. DrFillNumbersList(
  742. IN DRINFO* pInfo );
  743. DWORD
  744. DrFindAndSubclassClbNumbersControls(
  745. IN DRINFO* pInfo );
  746. VOID
  747. DrFreeClbNumbers(
  748. IN DRINFO* pInfo );
  749. BOOL
  750. DrInit(
  751. IN HWND hwndDlg,
  752. IN DRARGS* pArgs );
  753. VOID
  754. DrLocationsSelChange(
  755. IN DRINFO* pInfo );
  756. VOID
  757. DrNumbersSelChange(
  758. IN DRINFO* pInfo );
  759. DWORD
  760. DrPopulateIdentificationFields(
  761. IN DRINFO* pInfo,
  762. IN BOOL fForMe);
  763. DWORD
  764. DrPopulatePasswordField(
  765. IN DRINFO* pInfo,
  766. IN BOOL fInit,
  767. IN BOOL fDisable );
  768. VOID
  769. DrProperties(
  770. IN DRINFO* pInfo );
  771. VOID
  772. DrSave(
  773. IN DRINFO* pInfo );
  774. DWORD
  775. DrSetBitmap(
  776. IN DRINFO* pInfo);
  777. VOID
  778. DrSetClbNumbersText(
  779. IN DRINFO* pInfo,
  780. IN TCHAR* pszText );
  781. VOID
  782. DrTerm(
  783. IN HWND hwndDlg );
  784. LRESULT APIENTRY
  785. DpWndProc(
  786. HWND hwnd,
  787. UINT unMsg,
  788. WPARAM wParam,
  789. LPARAM lParam );
  790. DWORD
  791. FindEntryAndSetDialParams(
  792. IN DINFO* pInfo );
  793. INT_PTR CALLBACK
  794. PrDlgProc(
  795. IN HWND hwnd,
  796. IN UINT unMsg,
  797. IN WPARAM wparam,
  798. IN LPARAM lparam );
  799. BOOL
  800. PrCommand(
  801. IN HWND hwnd,
  802. IN WORD wNotification,
  803. IN WORD wId,
  804. IN HWND hwndCtrl );
  805. BOOL
  806. PrInit(
  807. IN HWND hwndDlg,
  808. IN PRARGS* pArgs );
  809. BOOL
  810. ProjectionResultDlg(
  811. IN HWND hwndOwner,
  812. IN TCHAR* pszLines,
  813. OUT BOOL* pfDisableFailedProtocols );
  814. BOOL
  815. RetryAuthenticationDlg(
  816. IN HWND hwndOwner,
  817. IN DINFO* pDinfo );
  818. INT_PTR CALLBACK
  819. UaDlgProc(
  820. IN HWND hwnd,
  821. IN UINT unMsg,
  822. IN WPARAM wparam,
  823. IN LPARAM lparam );
  824. BOOL
  825. UaCommand(
  826. IN UAINFO* pInfo,
  827. IN WORD wNotification,
  828. IN WORD wId,
  829. IN HWND hwndCtrl );
  830. BOOL
  831. UaInit(
  832. IN HWND hwndDlg,
  833. IN DINFO* pArgs );
  834. VOID
  835. UaSave(
  836. IN UAINFO* pInfo );
  837. VOID
  838. UaTerm(
  839. IN HWND hwndDlg );
  840. BOOL
  841. VpnDoubleDialDlg(
  842. IN HWND hwndOwner,
  843. IN DINFO* pInfo );
  844. INT_PTR CALLBACK
  845. ViDlgProc(
  846. IN HWND hwnd,
  847. IN UINT unMsg,
  848. IN WPARAM wparam,
  849. IN LPARAM lparam );
  850. BOOL
  851. ViCommand(
  852. IN HWND hwnd,
  853. IN WORD wNotification,
  854. IN WORD wId,
  855. IN HWND hwndCtrl );
  856. BOOL
  857. ViInit(
  858. IN HWND hwndDlg,
  859. IN DINFO* pInfo );
  860. //-----------------------------------------------------------------------------
  861. // External entry points
  862. //-----------------------------------------------------------------------------
  863. typedef struct EAPFREE_DATA {
  864. BOOL bInitialized;
  865. HINSTANCE hLib;
  866. RASEAPFREE pFreeFunc;
  867. } EAPFREE_DATA;
  868. //Add those OutputDebug_XXXX() functions for debug use when debugging 291613
  869. // gangz
  870. //
  871. void OutputDebug_DWCODE(DWORD dwCode)
  872. {
  873. WCHAR tmpBuf[100];
  874. wsprintf(tmpBuf,
  875. L"The dwCode returned is %x\n", dwCode);
  876. OutputDebugStringW(tmpBuf);
  877. }
  878. void OutputDebug_NumOfCallbacksActive(ULONG ulCallbacksActive)
  879. {
  880. WCHAR tmpBuf[100];
  881. wsprintf(tmpBuf,
  882. L"Current CallbacksActive is %x\n",
  883. ulCallbacksActive);
  884. OutputDebugStringW(tmpBuf);
  885. }
  886. void OutputDebug_ThreadId()
  887. {
  888. DWORD dwId;
  889. WCHAR tmpBuf[100];
  890. dwId = GetCurrentThreadId();
  891. wsprintf(tmpBuf, L"Current Thread is %x\n", dwId);
  892. OutputDebugStringW(tmpBuf);
  893. }
  894. void OutputDebug_ProcessThreadId()
  895. {
  896. DWORD dwIdProc, dwIdThread;
  897. WCHAR tmpBuf[100];
  898. dwIdProc = GetCurrentProcessId();
  899. dwIdThread = GetCurrentThreadId();
  900. wsprintf(tmpBuf, L"Current Proc is: %x , Thread is: %x\n", dwIdProc, dwIdThread);
  901. OutputDebugStringW(tmpBuf);
  902. }
  903. //
  904. // Raises the appriate eap indentity dialog
  905. //
  906. DWORD
  907. DialerDlgEap (
  908. IN HWND hwndOwner,
  909. IN PWCHAR lpszPhonebook,
  910. IN PWCHAR lpszEntry,
  911. IN PBENTRY * pEntry,
  912. IN DINFO *pInfo,
  913. OUT PBYTE * ppUserDataOut,
  914. OUT DWORD * lpdwSizeOfUserDataOut,
  915. OUT LPWSTR * lplpwszIdentity,
  916. OUT PHANDLE phFree
  917. )
  918. {
  919. DWORD dwErr, dwInSize = 0;
  920. PBYTE pbUserIn = NULL;
  921. HINSTANCE hLib = NULL;
  922. EAPFREE_DATA * pFreeData = NULL;
  923. DTLLIST * pListEaps = NULL;
  924. DTLNODE * pEapcfgNode = NULL;
  925. EAPCFG * pEapcfg = NULL;
  926. RASEAPFREE pFreeFunc = NULL;
  927. RASEAPGETIDENTITY pIdenFunc = NULL;
  928. DWORD dwFlags;
  929. DWORD cbData = 0;
  930. PBYTE pbData = NULL;
  931. // Initialize the free data handle we'll return
  932. pFreeData = Malloc ( sizeof(EAPFREE_DATA) );
  933. if (pFreeData == NULL)
  934. return ERROR_NOT_ENOUGH_MEMORY;
  935. ZeroMemory( pFreeData, sizeof(EAPFREE_DATA) );
  936. // Make sure we're configured with some list of
  937. // eap configuration options
  938. pListEaps = ReadEapcfgList( NULL );
  939. if (pListEaps == NULL)
  940. {
  941. Free(pFreeData);
  942. return ERROR_CAN_NOT_COMPLETE;
  943. }
  944. __try {
  945. // Find the eap node we're interested in
  946. pEapcfgNode = EapcfgNodeFromKey(
  947. pListEaps,
  948. pEntry->dwCustomAuthKey );
  949. if (pEapcfgNode)
  950. pEapcfg = (EAPCFG*)DtlGetData( pEapcfgNode );
  951. else
  952. return ERROR_CAN_NOT_COMPLETE;
  953. // Only call eap identity ui if we're told not to
  954. // get the user name through the standard credentials
  955. // dialog
  956. if (pEapcfg->dwStdCredentialFlags &
  957. EAPCFG_FLAG_RequireUsername)
  958. {
  959. return NO_ERROR;
  960. }
  961. if(!pInfo->pNoUser)
  962. {
  963. // Get the size of the input user data
  964. dwErr = RasGetEapUserData(
  965. NULL,
  966. lpszPhonebook,
  967. lpszEntry,
  968. NULL,
  969. &dwInSize);
  970. // Read in the user data
  971. if (dwErr != NO_ERROR) {
  972. if (dwErr == ERROR_BUFFER_TOO_SMALL) {
  973. if (dwInSize == 0)
  974. {
  975. pbUserIn = NULL;
  976. // return ERROR_CAN_NOT_COMPLETE;
  977. }
  978. else
  979. {
  980. // Allocate a blob to hold the data
  981. pbUserIn = Malloc (dwInSize);
  982. if (pbUserIn == NULL)
  983. return ERROR_NOT_ENOUGH_MEMORY;
  984. // Read in the new blob
  985. dwErr = RasGetEapUserData(
  986. NULL,
  987. lpszPhonebook,
  988. lpszEntry,
  989. pbUserIn,
  990. &dwInSize);
  991. if (dwErr != NO_ERROR)
  992. return dwErr;
  993. }
  994. }
  995. else
  996. return dwErr;
  997. }
  998. }
  999. else
  1000. {
  1001. INTERNALARGS *piargs;
  1002. piargs = (INTERNALARGS *) pInfo->pArgs->reserved;
  1003. if( (NULL != piargs)
  1004. && (NULL != piargs->pvEapInfo)
  1005. // pmay: 386489
  1006. //
  1007. && (pEntry->dwCustomAuthKey == EAPCFG_DefaultKey))
  1008. {
  1009. pbUserIn = (BYTE *) piargs->pvEapInfo;
  1010. dwInSize = ((EAPLOGONINFO *) piargs->pvEapInfo)->dwSize;
  1011. }
  1012. else
  1013. {
  1014. pbUserIn = NULL;
  1015. dwInSize = 0;
  1016. }
  1017. }
  1018. // Load the identity library
  1019. hLib = LoadLibrary (pEapcfg->pszIdentityDll);
  1020. if (hLib == NULL)
  1021. return GetLastError();
  1022. // Get pointers to the functions we'll be needing
  1023. pIdenFunc = (RASEAPGETIDENTITY)
  1024. GetProcAddress(hLib, "RasEapGetIdentity");
  1025. pFreeFunc = (RASEAPFREE) GetProcAddress(hLib, "RasEapFreeMemory");
  1026. if ( (pFreeFunc == NULL) || (pIdenFunc == NULL) )
  1027. return ERROR_CAN_NOT_COMPLETE;
  1028. dwFlags = (pInfo->pNoUser) ? RAS_EAP_FLAG_LOGON : 0;
  1029. if (!pEntry->fAutoLogon && pEntry->fPreviewUserPw)
  1030. {
  1031. dwFlags |= RAS_EAP_FLAG_PREVIEW;
  1032. }
  1033. if(pInfo->fUnattended)
  1034. {
  1035. dwFlags &= ~RAS_EAP_FLAG_PREVIEW;
  1036. }
  1037. dwErr = DwGetCustomAuthData(
  1038. pEntry,
  1039. &cbData,
  1040. &pbData);
  1041. if(ERROR_SUCCESS != dwErr)
  1042. {
  1043. return dwErr;
  1044. }
  1045. // Call the eap-provided identity UI
  1046. dwErr = (*(pIdenFunc))(
  1047. pEntry->dwCustomAuthKey,
  1048. hwndOwner,
  1049. dwFlags,
  1050. lpszPhonebook,
  1051. lpszEntry,
  1052. pbData,
  1053. cbData,
  1054. pbUserIn,
  1055. dwInSize,
  1056. ppUserDataOut,
  1057. lpdwSizeOfUserDataOut,
  1058. lplpwszIdentity);
  1059. if (dwErr != NO_ERROR)
  1060. return dwErr;
  1061. // Assign the data used to cleanup later
  1062. pFreeData->bInitialized = TRUE;
  1063. pFreeData->hLib = hLib;
  1064. pFreeData->pFreeFunc = pFreeFunc;
  1065. *phFree = (HANDLE)pFreeData;
  1066. }
  1067. __finally {
  1068. if (pListEaps)
  1069. DtlDestroyList(pListEaps, NULL);
  1070. if ( (!pInfo->pNoUser)
  1071. && (pbUserIn))
  1072. {
  1073. Free0(pbUserIn);
  1074. }
  1075. if ((pFreeData) && (!pFreeData->bInitialized))
  1076. {
  1077. Free(pFreeData);
  1078. if(NULL != hLib)
  1079. {
  1080. FreeLibrary(hLib);
  1081. }
  1082. }
  1083. }
  1084. return NO_ERROR;
  1085. }
  1086. DWORD
  1087. DialerEapCleanup (
  1088. IN HANDLE hEapFree,
  1089. IN PBYTE pUserDataOut,
  1090. IN LPWSTR lpwszIdentity)
  1091. {
  1092. EAPFREE_DATA * pFreeData = (EAPFREE_DATA*)hEapFree;
  1093. if (pFreeData == NULL)
  1094. return ERROR_INVALID_PARAMETER;
  1095. if (pFreeData->pFreeFunc) {
  1096. if (pUserDataOut)
  1097. (*(pFreeData->pFreeFunc))(pUserDataOut);
  1098. if (lpwszIdentity)
  1099. (*(pFreeData->pFreeFunc))((BYTE*)lpwszIdentity);
  1100. }
  1101. if (pFreeData->hLib)
  1102. FreeLibrary(pFreeData->hLib);
  1103. Free (pFreeData);
  1104. return NO_ERROR;
  1105. }
  1106. //
  1107. // Customizes the dialer flags for the eap provider
  1108. // of the given entry;
  1109. //
  1110. // TODO -- try to optimize this. The list of eaps
  1111. // may not need to be read if we keep enough state
  1112. // in the phonebook.
  1113. //
  1114. DWORD DialerEapAssignMode(
  1115. IN DINFO* pInfo,
  1116. OUT LPDWORD lpdwfMode)
  1117. {
  1118. DWORD dwfMode = *lpdwfMode;
  1119. DTLLIST * pListEaps;
  1120. DTLNODE * pEapcfgNode;
  1121. EAPCFG * pEapcfg;
  1122. // If eap is not used in this entry,
  1123. // then no action is required
  1124. if (! (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP))
  1125. return NO_ERROR;
  1126. // Make sure we're configured with some list of
  1127. // eap configuration options
  1128. pListEaps = ReadEapcfgList( NULL );
  1129. if (pListEaps == NULL)
  1130. return ERROR_CAN_NOT_COMPLETE;
  1131. // Find the eap node we're interested in
  1132. pEapcfgNode = EapcfgNodeFromKey(
  1133. pListEaps,
  1134. pInfo->pEntry->dwCustomAuthKey );
  1135. if (pEapcfgNode)
  1136. pEapcfg = (EAPCFG*)DtlGetData( pEapcfgNode );
  1137. else
  1138. {
  1139. if (pListEaps)
  1140. DtlDestroyList(pListEaps, NULL);
  1141. return ERROR_CAN_NOT_COMPLETE;
  1142. }
  1143. // If eap provider requests user name then
  1144. // request identity.
  1145. if (pEapcfg->dwStdCredentialFlags &
  1146. EAPCFG_FLAG_RequireUsername
  1147. )
  1148. {
  1149. // Use the "I" flavors if the eap wants a user
  1150. // name but no password.
  1151. //
  1152. if (!(pEapcfg->dwStdCredentialFlags &
  1153. EAPCFG_FLAG_RequirePassword)
  1154. )
  1155. {
  1156. // Clear the username+password property (DR_U) if it
  1157. // exists and replace it with the username property
  1158. // (DR_I). Only do this if DR_U is already set. It
  1159. // wont be set for autodial connections or for connections
  1160. // where that option was specifically disabled as can
  1161. // be seen in the DialerDlg function.
  1162. //
  1163. // See whistler bug 30841
  1164. //
  1165. if (dwfMode & DR_U)
  1166. {
  1167. dwfMode &= ~DR_U;
  1168. dwfMode |= DR_I;
  1169. }
  1170. }
  1171. }
  1172. else
  1173. {
  1174. // Otherwise, make sure that we request neither user name nor password
  1175. // Since domain cannot appear without username clear that also.
  1176. //
  1177. dwfMode &= ~(DR_U | DR_D);
  1178. }
  1179. // Cleanup
  1180. if (pListEaps)
  1181. DtlDestroyList(pListEaps, NULL);
  1182. // Assign the correct mode
  1183. *lpdwfMode = dwfMode;
  1184. return NO_ERROR;
  1185. }
  1186. BOOL APIENTRY
  1187. RasDialDlgA(
  1188. IN LPSTR lpszPhonebook,
  1189. IN LPSTR lpszEntry,
  1190. IN LPSTR lpszPhoneNumber,
  1191. IN OUT LPRASDIALDLG lpInfo )
  1192. // Win32 ANSI entrypoint that displays the dial progress and related
  1193. // dialogs, including authentication, error w/redial, callback, and retry
  1194. // authentication. 'LpszPhonebook' is the full path the phonebook or NULL
  1195. // indicating the default phonebook. 'LpszEntry' is the entry to dial.
  1196. // 'LpszPhoneNumber' is caller's override phone number or NULL to use the
  1197. // one in the entry. 'LpInfo' is caller's additional input/output
  1198. // parameters.
  1199. //
  1200. // Returns true if user establishes a connection, false otherwise.
  1201. //
  1202. {
  1203. WCHAR* pszPhonebookW;
  1204. WCHAR* pszEntryW;
  1205. WCHAR* pszPhoneNumberW;
  1206. BOOL fStatus;
  1207. TRACE( "RasDialDlgA" );
  1208. if (!lpInfo)
  1209. {
  1210. SetLastError( ERROR_INVALID_PARAMETER );
  1211. return FALSE;
  1212. }
  1213. if (!lpszEntry)
  1214. {
  1215. lpInfo->dwError = ERROR_INVALID_PARAMETER;
  1216. return FALSE;
  1217. }
  1218. if (lpInfo->dwSize != sizeof(RASDIALDLG))
  1219. {
  1220. lpInfo->dwError = ERROR_INVALID_SIZE;
  1221. return FALSE;
  1222. }
  1223. // Thunk "A" arguments to "W" arguments.
  1224. //
  1225. if (lpszPhonebook)
  1226. {
  1227. pszPhonebookW = StrDupTFromAUsingAnsiEncoding( lpszPhonebook );
  1228. if (!pszPhonebookW)
  1229. {
  1230. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  1231. return FALSE;
  1232. }
  1233. }
  1234. else
  1235. {
  1236. pszPhonebookW = NULL;
  1237. }
  1238. pszEntryW = StrDupTFromAUsingAnsiEncoding( lpszEntry );
  1239. if (!pszEntryW)
  1240. {
  1241. Free0( pszPhonebookW );
  1242. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  1243. return FALSE;
  1244. }
  1245. if (lpszPhoneNumber)
  1246. {
  1247. pszPhoneNumberW = StrDupTFromAUsingAnsiEncoding( lpszPhoneNumber );
  1248. if (!pszPhoneNumberW)
  1249. {
  1250. Free0( pszPhonebookW );
  1251. Free( pszEntryW );
  1252. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  1253. return FALSE;
  1254. }
  1255. }
  1256. else
  1257. {
  1258. pszPhoneNumberW = NULL;
  1259. }
  1260. // Thunk to the equivalent "W" API.
  1261. //
  1262. fStatus = RasDialDlgW( pszPhonebookW, pszEntryW, pszPhoneNumberW, lpInfo );
  1263. Free0( pszPhonebookW );
  1264. Free( pszEntryW );
  1265. return fStatus;
  1266. }
  1267. DWORD
  1268. DoEapProcessing(
  1269. LPRASDIALDLG lpInfo,
  1270. DINFO *pInfo,
  1271. PBYTE *ppbEapUserData,
  1272. WCHAR **ppwszEapIdentity,
  1273. HANDLE *phEapFree,
  1274. BOOL *pfStatus
  1275. )
  1276. {
  1277. // If this is an eap connection, then use the eap identity
  1278. // ui to get the user name and password.
  1279. //
  1280. DWORD dwSize = 0;
  1281. DWORD dwErr = NO_ERROR;
  1282. *pfStatus = TRUE;
  1283. // Bring up the Eap dialer dialog
  1284. dwErr = DialerDlgEap(
  1285. lpInfo->hwndOwner,
  1286. pInfo->pFile->pszPath,
  1287. pInfo->pEntry->pszEntryName,
  1288. pInfo->pEntry,
  1289. pInfo,
  1290. ppbEapUserData,
  1291. &dwSize,
  1292. ppwszEapIdentity,
  1293. phEapFree);
  1294. if (dwErr != NO_ERROR)
  1295. {
  1296. if (ERROR_CANCELLED == dwErr)
  1297. {
  1298. dwErr = NO_ERROR;
  1299. }
  1300. *pfStatus = FALSE;
  1301. goto done;
  1302. }
  1303. if(!pInfo->pNoUser)
  1304. {
  1305. // Set the extended dial params accordingly
  1306. pInfo->rde.RasEapInfo.dwSizeofEapInfo = dwSize;
  1307. pInfo->rde.RasEapInfo.pbEapInfo = *ppbEapUserData;
  1308. }
  1309. else if ( (*ppbEapUserData != NULL)
  1310. && (dwSize != 0))
  1311. {
  1312. pInfo->rde.RasEapInfo.dwSizeofEapInfo = dwSize;
  1313. pInfo->rde.RasEapInfo.pbEapInfo = *ppbEapUserData;
  1314. }
  1315. else
  1316. {
  1317. INTERNALARGS *piargs;
  1318. piargs = (INTERNALARGS *) (pInfo->pArgs->reserved);
  1319. if( (NULL != piargs)
  1320. && (NULL != piargs->pvEapInfo)
  1321. // pmay: 386489
  1322. //
  1323. && (pInfo->pEntry->dwCustomAuthKey == EAPCFG_DefaultKey))
  1324. {
  1325. pInfo->rde.RasEapInfo.dwSizeofEapInfo =
  1326. ((EAPLOGONINFO *) piargs->pvEapInfo)->dwSize;
  1327. pInfo->rde.RasEapInfo.pbEapInfo = (BYTE *) piargs->pvEapInfo;
  1328. }
  1329. else
  1330. {
  1331. pInfo->rde.RasEapInfo.dwSizeofEapInfo = 0;
  1332. pInfo->rde.RasEapInfo.pbEapInfo = NULL;
  1333. }
  1334. }
  1335. if (*ppwszEapIdentity)
  1336. {
  1337. DWORD dwSize =
  1338. sizeof(pInfo->rdp.szUserName) / sizeof(WCHAR);
  1339. wcsncpy(pInfo->rdp.szUserName, *ppwszEapIdentity,
  1340. dwSize - 1);
  1341. pInfo->rdp.szUserName[dwSize - 1] = 0;
  1342. // Ignore the domain setting if the EAP supplied the
  1343. // identity.
  1344. pInfo->rdp.szDomain[ 0 ] = L'\0';
  1345. }
  1346. done:
  1347. return dwErr;
  1348. }
  1349. INT
  1350. DialDlgDisplayError(
  1351. IN LPRASDIALDLG pInfo,
  1352. IN HWND hwndOwner,
  1353. IN DWORD dwSid,
  1354. IN DWORD dwError,
  1355. IN ERRORARGS* pArgs)
  1356. {
  1357. if (pInfo->dwFlags & RASDDFLAG_NoPrompt)
  1358. {
  1359. return 0;
  1360. }
  1361. return ErrorDlg(hwndOwner, dwSid, dwError, pArgs);
  1362. }
  1363. BOOL APIENTRY
  1364. RasDialDlgW(
  1365. IN LPWSTR lpszPhonebook,
  1366. IN LPWSTR lpszEntry,
  1367. IN LPWSTR lpszPhoneNumber,
  1368. IN OUT LPRASDIALDLG lpInfo )
  1369. // Win32 UNICODE entrypoint that displays the dial progress and related
  1370. // dialogs, including authentication, error w/redial, callback, and retry
  1371. // authentication. 'LpszPhonebook' is the full path the phonebook or NULL
  1372. // indicating the default phonebook. 'LpszEntry' is the entry to dial.
  1373. // 'LpszPhoneNumber' is caller's override phone number or NULL to use the
  1374. // one in the entry. 'LpInfo' is caller's additional input/output
  1375. // parameters.
  1376. //
  1377. // Returns true if user establishes a connection, false otherwise. If
  1378. // 'RASDDFLAG_AutoDialQueryOnly' is set, returns true if user pressed
  1379. // "Dial", false otherwise.
  1380. //
  1381. {
  1382. DWORD dwErr;
  1383. BOOL fStatus;
  1384. BOOL fFirstPass;
  1385. DINFO* pInfo;
  1386. LPWSTR pwszEapIdentity = NULL;
  1387. PBYTE pbEapUserData = NULL;
  1388. HANDLE hEapFree = NULL;
  1389. BOOL fCustom = FALSE;
  1390. PVOID pvInfo = NULL;
  1391. HRASCONN hrasconnPrereq = NULL;
  1392. TRACE( "RasDialDlgW" );
  1393. if (!lpInfo)
  1394. {
  1395. SetLastError( ERROR_INVALID_PARAMETER );
  1396. return FALSE;
  1397. }
  1398. if (!lpszEntry)
  1399. {
  1400. lpInfo->dwError = ERROR_INVALID_PARAMETER;
  1401. return FALSE;
  1402. }
  1403. if (lpInfo->dwSize != sizeof(RASDIALDLG))
  1404. {
  1405. lpInfo->dwError = ERROR_INVALID_SIZE;
  1406. return FALSE;
  1407. }
  1408. if (lpszPhoneNumber && lstrlen( lpszPhoneNumber ) > RAS_MaxPhoneNumber)
  1409. {
  1410. lpInfo->dwError = ERROR_INVALID_PARAMETER;
  1411. return FALSE;
  1412. }
  1413. // Load RAS DLL entrypoints which starts RASMAN, if necessary.
  1414. //
  1415. lpInfo->dwError = LoadRas( g_hinstDll, lpInfo->hwndOwner );
  1416. if (lpInfo->dwError != 0)
  1417. {
  1418. // Whistler bug 301784
  1419. //
  1420. // Check specifically for access denied.
  1421. //
  1422. if (lpInfo->dwError == ERROR_ACCESS_DENIED)
  1423. {
  1424. DialDlgDisplayError(
  1425. lpInfo,
  1426. lpInfo->hwndOwner,
  1427. SID_OP_LoadRasAccessDenied,
  1428. lpInfo->dwError,
  1429. NULL );
  1430. }
  1431. else
  1432. {
  1433. DialDlgDisplayError(
  1434. lpInfo,
  1435. lpInfo->hwndOwner,
  1436. SID_OP_LoadRas,
  1437. lpInfo->dwError,
  1438. NULL );
  1439. }
  1440. return FALSE;
  1441. }
  1442. // Allocate the context information block and initialize it enough so that
  1443. // it can be destroyed properly.
  1444. //
  1445. pInfo = Malloc( sizeof(*pInfo) );
  1446. if (!pInfo)
  1447. {
  1448. DialDlgDisplayError(
  1449. lpInfo,
  1450. lpInfo->hwndOwner,
  1451. SID_OP_LoadDlg,
  1452. ERROR_NOT_ENOUGH_MEMORY,
  1453. NULL );
  1454. lpInfo->dwError = ERROR_NOT_ENOUGH_MEMORY;
  1455. return FALSE;
  1456. }
  1457. ZeroMemory( pInfo, sizeof(*pInfo) );
  1458. pInfo->pszPhonebook = lpszPhonebook;
  1459. pInfo->pszEntry = lpszEntry;
  1460. pInfo->pszPhoneNumber = lpszPhoneNumber;
  1461. pInfo->pArgs = lpInfo;
  1462. fStatus = FALSE;
  1463. dwErr = 0;
  1464. do
  1465. {
  1466. // Load the phonebook file and user preferences, or figure out that
  1467. // caller has already loaded them.
  1468. //
  1469. if (lpInfo->reserved)
  1470. {
  1471. INTERNALARGS* piargs;
  1472. // We've received an open phonebook file and user preferences via
  1473. // the secret hack.
  1474. //
  1475. piargs = (INTERNALARGS* )lpInfo->reserved;
  1476. pInfo->pFile = pInfo->pFileMain = piargs->pFile;
  1477. pInfo->pUser = piargs->pUser;
  1478. pInfo->pNoUser = piargs->pNoUser;
  1479. pInfo->pfNoUserChanged = &piargs->fNoUserChanged;
  1480. pInfo->fMoveOwnerOffDesktop = piargs->fMoveOwnerOffDesktop;
  1481. pInfo->fForceCloseOnDial = piargs->fForceCloseOnDial;
  1482. }
  1483. else
  1484. {
  1485. // Read user preferences from registry.
  1486. //
  1487. dwErr = g_pGetUserPreferences( NULL, &pInfo->user, UPM_Normal );
  1488. if (dwErr != 0)
  1489. {
  1490. DialDlgDisplayError(
  1491. lpInfo,
  1492. lpInfo->hwndOwner,
  1493. SID_OP_LoadPrefs,
  1494. dwErr,
  1495. NULL );
  1496. break;
  1497. }
  1498. pInfo->pUser = &pInfo->user;
  1499. // Load and parse the phonebook file.
  1500. //
  1501. dwErr = ReadPhonebookFile(
  1502. lpszPhonebook, &pInfo->user, NULL, 0, &pInfo->file );
  1503. if (dwErr != 0)
  1504. {
  1505. DialDlgDisplayError(
  1506. lpInfo,
  1507. lpInfo->hwndOwner,
  1508. SID_OP_LoadPhonebook,
  1509. dwErr,
  1510. NULL );
  1511. break;
  1512. }
  1513. pInfo->pFile = pInfo->pFileMain = &pInfo->file;
  1514. }
  1515. // Record whether this is a for-all-users phonebook
  1516. //
  1517. // Whistler bug 288596 Autodial has wrong save password option marked -
  1518. // prompts user to save password for all users
  1519. //
  1520. pInfo->fIsPublicPbk =
  1521. (!pInfo->pszPhonebook) || IsPublicPhonebook(pInfo->pszPhonebook);
  1522. if (!pInfo->pNoUser)
  1523. {
  1524. DWORD dwErrR;
  1525. HKEY hkey;
  1526. // See if admin has disabled the "save password" feature.
  1527. //
  1528. pInfo->fDisableSavePw = FALSE;
  1529. dwErrR = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  1530. TEXT("SYSTEM\\CurrentControlSet\\Services\\RasMan\\Parameters"),
  1531. 0, KEY_READ, &hkey );
  1532. if (dwErrR == 0)
  1533. {
  1534. DWORD dwResult;
  1535. dwResult = (DWORD )pInfo->fDisableSavePw;
  1536. GetRegDword( hkey, TEXT("DisableSavePassword"), &dwResult );
  1537. pInfo->fDisableSavePw = (BOOL )dwResult;
  1538. RegCloseKey( hkey );
  1539. }
  1540. }
  1541. // Hide parent dialog when initiated by another RAS API that requests
  1542. // it. This is the first stage of "close on dial" behavior, allowing
  1543. // the parent to appear closed to user though, as owner, it must
  1544. // really stay open until the dial dialogs complete. At that point it
  1545. // can silently close or reappear as desired.
  1546. //
  1547. if (lpInfo->hwndOwner && pInfo->fMoveOwnerOffDesktop)
  1548. {
  1549. SetOffDesktop( lpInfo->hwndOwner, SOD_MoveOff, NULL );
  1550. }
  1551. // Set true initially, but will be set false by
  1552. // FindEntryAndSetDialParams if the entry has no "dial first" entry
  1553. // associated with it.
  1554. //
  1555. pInfo->fPrerequisiteDial = TRUE;
  1556. fFirstPass = TRUE;
  1557. for (;;)
  1558. {
  1559. pInfo->fDialForReferenceOnly = FALSE;
  1560. // Look up the entry and fill in the RASDIALPARAMS structure
  1561. // accordingly. This done as a routine so it can be re-done
  1562. // should user press the Properties button.
  1563. //
  1564. dwErr = FindEntryAndSetDialParams( pInfo );
  1565. if (dwErr != 0)
  1566. {
  1567. // we need to maintain 2 phonebooks
  1568. // but we need to do this in case we break existing
  1569. // apps which look specifically in system\ras dir.
  1570. // Feel free to rip this code off, if you feel
  1571. // strongly about it.
  1572. //
  1573. if( (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwErr)
  1574. && (NULL == lpszPhonebook))
  1575. {
  1576. DTLNODE *pNode;
  1577. //
  1578. // Close the all users phonebook file
  1579. //
  1580. ClosePhonebookFile(&pInfo->file);
  1581. dwErr = GetPbkAndEntryName(
  1582. lpszPhonebook,
  1583. lpszEntry,
  1584. 0,
  1585. &pInfo->file,
  1586. &pNode);
  1587. if( (NULL == pNode)
  1588. || (ERROR_SUCCESS != dwErr))
  1589. {
  1590. dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  1591. break;
  1592. }
  1593. pInfo->pFile = pInfo->pFileMain = &pInfo->file;
  1594. dwErr = FindEntryAndSetDialParams(pInfo);
  1595. if(dwErr != 0)
  1596. {
  1597. break;
  1598. }
  1599. }
  1600. else
  1601. {
  1602. break;
  1603. }
  1604. }
  1605. if(lpInfo->reserved)
  1606. {
  1607. INTERNALARGS *piargs = (INTERNALARGS *) lpInfo->reserved;
  1608. if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)
  1609. {
  1610. pvInfo = piargs->pvEapInfo;
  1611. }
  1612. else
  1613. {
  1614. pvInfo = piargs->pNoUser;
  1615. }
  1616. }
  1617. if(pInfo->fPrerequisiteDial
  1618. && (NULL != pInfo->pEntry->pszCustomDialerName)
  1619. && (TEXT('\0') != pInfo->pEntry->pszCustomDialerName[0]))
  1620. {
  1621. RASDIALDLG Info;
  1622. DWORD dwCustomFlags = 0;
  1623. RASNOUSER nouser, *pNoUser = NULL;
  1624. ZeroMemory(&Info, sizeof(RASDIALDLG));
  1625. ZeroMemory(&nouser, sizeof(RASNOUSER));
  1626. Info.dwSize = sizeof(RASDIALDLG);
  1627. Info.hwndOwner = lpInfo->hwndOwner;
  1628. Info.xDlg = lpInfo->xDlg;
  1629. Info.yDlg = lpInfo->yDlg;
  1630. fCustom = TRUE;
  1631. if(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)
  1632. {
  1633. dwCustomFlags |= RCD_Eap;
  1634. }
  1635. if( (NULL != pInfo->pNoUser)
  1636. && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags)
  1637. && ( (0 == (dwCustomFlags & RCD_Eap))
  1638. || (EAP_RASTLS != pInfo->pEntry->dwCustomAuthKey)
  1639. ))
  1640. {
  1641. CopyMemory(&nouser, pInfo->pNoUser, sizeof(RASNOUSER));
  1642. ZeroMemory(nouser.szPassword, (PWLEN+1) * sizeof(TCHAR));
  1643. pvInfo = &nouser;
  1644. }
  1645. // DwCustomDialDlg returns ERROR_SUCCESS if it handled
  1646. // the CustomRasDial. returns E_NOINTERFACE otherwise
  1647. // which implies that there is no custom dlg interface
  1648. // supported for this entry and the default dial should
  1649. // happen
  1650. //
  1651. // Whistler bug 314578 When connecting with CM via Winlogon I
  1652. // get the following error "Error 1: Incorrect function"
  1653. //
  1654. // This is a case where we call into a custom dialer, ie CM,
  1655. // and we are using creds that we got from winlogon. They are
  1656. // currently encoded and must be decoded before we call out.
  1657. // We have to assume that the Custom Dialer leaves the password
  1658. // un-encoded upon return.
  1659. //
  1660. if ( !(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) )
  1661. {
  1662. // pNoUser is used to encode/decode passwords. If this
  1663. // is an EAP connection, then pvInfo will point to an
  1664. // eap blob, not a "no user" blob.
  1665. //
  1666. pNoUser = pvInfo;
  1667. }
  1668. if ( pNoUser )
  1669. {
  1670. DecodePassword( pNoUser->szPassword );
  1671. }
  1672. if(pInfo->pNoUser)
  1673. {
  1674. dwCustomFlags |= RCD_Logon;
  1675. }
  1676. dwErr = DwCustomDialDlg(pInfo->pFile->pszPath,
  1677. pInfo->pEntry->pszEntryName,
  1678. NULL,
  1679. &Info,
  1680. dwCustomFlags,
  1681. &fStatus,
  1682. pvInfo,
  1683. pInfo->pEntry->pszCustomDialerName);
  1684. if ( pNoUser )
  1685. {
  1686. EncodePassword( pNoUser->szPassword );
  1687. }
  1688. if(!fStatus)
  1689. {
  1690. lpInfo->dwError = Info.dwError;
  1691. break;
  1692. }
  1693. else
  1694. {
  1695. pInfo->fPrerequisiteDial = FALSE;
  1696. fCustom = FALSE;
  1697. continue;
  1698. }
  1699. }
  1700. else if ((NULL != pInfo->pEntry->pszCustomDialerName)
  1701. && (TEXT('\0') != pInfo->pEntry->pszCustomDialerName[0]))
  1702. {
  1703. DWORD dwCustomFlags = 0;
  1704. RASNOUSER nouser, *pNoUser = NULL;
  1705. ZeroMemory(&nouser, sizeof(RASNOUSER));
  1706. if(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)
  1707. {
  1708. dwCustomFlags |= RCD_Eap;
  1709. }
  1710. if( (NULL != pInfo->pNoUser)
  1711. && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags)
  1712. && ( (0 == (dwCustomFlags & RCD_Eap))
  1713. || (EAP_RASTLS != pInfo->pEntry->dwCustomAuthKey))
  1714. )
  1715. {
  1716. CopyMemory(&nouser, pInfo->pNoUser, sizeof(RASNOUSER));
  1717. ZeroMemory(nouser.szPassword, (PWLEN+1) * sizeof(TCHAR));
  1718. pvInfo = &nouser;
  1719. }
  1720. fCustom = TRUE;
  1721. // DwCustomDialDlg returns ERROR_SUCCESS if it handled
  1722. // the CustomRasDial. returns E_NOINTERFACE otherwise
  1723. // which implies that there is no custom dlg interface
  1724. // supported for this entry and the default dial should
  1725. // happen
  1726. //
  1727. // Whistler bug 314578 When connecting with CM via Winlogon I
  1728. // get the following error "Error 1: Incorrect function"
  1729. //
  1730. // This is a case where we call into a custom dialer, ie CM,
  1731. // and we are using creds that we got from winlogon. They are
  1732. // currently encoded and must be decoded before we call out.
  1733. // We have to assume that the Custom Dialer leaves the password
  1734. // un-encoded upon return.
  1735. //
  1736. if ( !(pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP) )
  1737. {
  1738. // pNoUser is used to encode/decode passwords. If this
  1739. // is an EAP connection, then pvInfo will point to an
  1740. // eap blob, not a "no user" blob.
  1741. //
  1742. pNoUser = pvInfo;
  1743. }
  1744. if ( pNoUser )
  1745. {
  1746. DecodePassword( pNoUser->szPassword );
  1747. }
  1748. if(pInfo->pNoUser)
  1749. {
  1750. dwCustomFlags |= RCD_Logon;
  1751. }
  1752. dwErr = DwCustomDialDlg(lpszPhonebook,
  1753. lpszEntry,
  1754. lpszPhoneNumber,
  1755. lpInfo,
  1756. dwCustomFlags,
  1757. &fStatus,
  1758. pvInfo,
  1759. pInfo->pEntry->pszCustomDialerName);
  1760. if ( pNoUser )
  1761. {
  1762. EncodePassword( pNoUser->szPassword );
  1763. }
  1764. break;
  1765. }
  1766. // If a prerequisite entry is already connected, there's no need
  1767. // for any UI but the dial must occur to set the reference in the
  1768. // RASAPI level.
  1769. //
  1770. if (pInfo->fPrerequisiteDial
  1771. && HrasconnFromEntry(
  1772. pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName ))
  1773. {
  1774. pInfo->fDialForReferenceOnly = TRUE;
  1775. }
  1776. // Set up extension parameter block, except 'hwndOwner' which is
  1777. // set to the Dial Progress dialog window later.
  1778. //
  1779. {
  1780. RASDIALEXTENSIONS* prde = &pInfo->rde;
  1781. ZeroMemory( prde, sizeof(*prde) );
  1782. prde->dwSize = sizeof(*prde);
  1783. prde->dwfOptions = RDEOPT_PausedStates | RDEOPT_PauseOnScript;
  1784. if (pInfo->pNoUser)
  1785. {
  1786. prde->dwfOptions |= RDEOPT_NoUser;
  1787. }
  1788. if (!pInfo->pszPhoneNumber)
  1789. {
  1790. prde->dwfOptions |= RDEOPT_UsePrefixSuffix;
  1791. }
  1792. }
  1793. if ( (pInfo->fUnattended)
  1794. && ((HaveSavedPw( pInfo ))
  1795. || (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)))
  1796. {
  1797. // Popup the countdown to link failure redial version of the
  1798. // dial error dialog, which will lead to a dial unless user
  1799. // stops it.
  1800. //
  1801. fStatus = DialErrorDlg(
  1802. lpInfo->hwndOwner, pInfo->pEntry->pszEntryName,
  1803. 0, 0, NULL, 0, NULL,
  1804. GetOverridableParam(
  1805. pInfo->pUser, pInfo->pEntry, RASOR_RedialSeconds ),
  1806. GetOverridableParam(
  1807. pInfo->pUser, pInfo->pEntry,
  1808. RASOR_PopupOnTopWhenRedialing ) );
  1809. if(!fStatus)
  1810. {
  1811. break;
  1812. }
  1813. if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)
  1814. {
  1815. dwErr = DoEapProcessing(
  1816. lpInfo,
  1817. pInfo,
  1818. &pbEapUserData,
  1819. &pwszEapIdentity,
  1820. &hEapFree,
  1821. &fStatus);
  1822. if( (NO_ERROR != dwErr)
  1823. || (!fStatus))
  1824. {
  1825. break;
  1826. }
  1827. }
  1828. }
  1829. else if (!pInfo->fDialForReferenceOnly)
  1830. {
  1831. if (!pInfo->fUnattended && fFirstPass)
  1832. {
  1833. // Warn about active NWC LAN connections being blown away,
  1834. // if indicated.
  1835. //
  1836. if (!NwConnectionCheck(
  1837. lpInfo->hwndOwner,
  1838. (pInfo->pArgs->dwFlags & RASDDFLAG_PositionDlg),
  1839. pInfo->pArgs->xDlg, pInfo->pArgs->yDlg,
  1840. pInfo->pFile, pInfo->pEntry ))
  1841. {
  1842. break;
  1843. }
  1844. // Popup the double-dial help popup, if indicated.
  1845. //
  1846. if (!VpnDoubleDialDlg( lpInfo->hwndOwner, pInfo ))
  1847. {
  1848. break;
  1849. }
  1850. }
  1851. // Check to see if its smartcardlogon case and blank
  1852. // out the password if its not an eap tls connectoid
  1853. //
  1854. if( (NULL != pInfo->pNoUser)
  1855. && (RASNOUSER_SmartCard & pInfo->pNoUser->dwFlags)
  1856. && (pInfo->pEntry->dwCustomAuthKey != EAP_RASTLS))
  1857. {
  1858. ZeroMemory(pInfo->rdp.szPassword, (PWLEN+1) * sizeof(TCHAR));
  1859. }
  1860. // Prompt for credentials and/or phone number (or not)
  1861. // as configured in the entry properties.
  1862. //
  1863. if (!DialerDlg( lpInfo->hwndOwner, pInfo ))
  1864. {
  1865. if(!fFirstPass)
  1866. {
  1867. fStatus = FALSE;
  1868. }
  1869. break;
  1870. }
  1871. if (pInfo->pEntry->dwAuthRestrictions & AR_F_AuthEAP)
  1872. {
  1873. dwErr = DoEapProcessing(
  1874. lpInfo,
  1875. pInfo,
  1876. &pbEapUserData,
  1877. &pwszEapIdentity,
  1878. &hEapFree,
  1879. &fStatus);
  1880. if( (NO_ERROR != dwErr)
  1881. || (!fStatus))
  1882. {
  1883. break;
  1884. }
  1885. }
  1886. fStatus = TRUE;
  1887. }
  1888. else
  1889. {
  1890. fStatus = TRUE;
  1891. }
  1892. // Dial and show progress.
  1893. //
  1894. if (fStatus
  1895. && !fCustom)
  1896. {
  1897. // Clear this here because beyond this rasman
  1898. // will take care of dropping the prereq link
  1899. // since beyond this point rasdial api will get
  1900. // called. [raos]
  1901. //
  1902. hrasconnPrereq = NULL;
  1903. fStatus = DialProgressDlg( pInfo );
  1904. // Show connect complete dialog unless user has nixed it or
  1905. // it's a prerequisite dial.
  1906. // (AboladeG) Also suppress the dialog in no-prompt mode.
  1907. //
  1908. if (!pInfo->fPrerequisiteDial
  1909. && fStatus
  1910. && !pInfo->pUser->fSkipConnectComplete
  1911. && !(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt))
  1912. {
  1913. //For whistler bug 378078 gangz
  1914. //We will comment out this status explaination dialog
  1915. //box because some users complained that it is confusing
  1916. //
  1917. // ConnectCompleteDlg( lpInfo->hwndOwner, pInfo );
  1918. }
  1919. }
  1920. // Don't loop a second time to dial the main entry if the
  1921. // prerequisite dial failed.
  1922. //
  1923. if (!fStatus || !pInfo->fPrerequisiteDial)
  1924. {
  1925. break;
  1926. }
  1927. // Save the rasconn of the prereq dial in case we need to hang
  1928. // it up for the case where the vpn dialog fails before rasdial
  1929. // gets called. [raos]
  1930. //
  1931. if (pInfo->fPrerequisiteDial)
  1932. {
  1933. hrasconnPrereq = HrasconnFromEntry(
  1934. pInfo->pFile->pszPath, pInfo->pEntry->pszEntryName);
  1935. }
  1936. pInfo->fPrerequisiteDial = FALSE;
  1937. fFirstPass = FALSE;
  1938. // Cleanup eap stuff
  1939. if (hEapFree)
  1940. {
  1941. DialerEapCleanup(hEapFree, pbEapUserData, pwszEapIdentity);
  1942. hEapFree = NULL;
  1943. pbEapUserData = NULL;
  1944. pwszEapIdentity = NULL;
  1945. }
  1946. }
  1947. }
  1948. while (FALSE);
  1949. // Unhide parent dialog when initiated by another RAS API.
  1950. //
  1951. if (lpInfo->hwndOwner && pInfo->fMoveOwnerOffDesktop
  1952. && (!fStatus
  1953. || !(pInfo->pUser->fCloseOnDial || pInfo->fForceCloseOnDial)))
  1954. {
  1955. SetOffDesktop( lpInfo->hwndOwner, SOD_MoveBackFree, NULL );
  1956. }
  1957. if(!fCustom)
  1958. {
  1959. // Save the several little user preferences adjustments we may have made.
  1960. //
  1961. g_pSetUserPreferences(
  1962. NULL, pInfo->pUser, (pInfo->pNoUser) ? UPM_Logon : UPM_Normal );
  1963. // Report error, if any.
  1964. //
  1965. if (dwErr)
  1966. {
  1967. DialDlgDisplayError(
  1968. lpInfo,
  1969. lpInfo->hwndOwner,
  1970. SID_OP_LoadDlg,
  1971. dwErr,
  1972. NULL );
  1973. lpInfo->dwError = dwErr;
  1974. }
  1975. TRACE1("hrasconnPrereq=0x%x",hrasconnPrereq);
  1976. //
  1977. // Drop the connection if we failed to connect the vpn connection
  1978. //
  1979. if( !fStatus
  1980. && (NULL != hrasconnPrereq)
  1981. && (pInfo->pEntry)
  1982. && (pInfo->pEntry->pszPrerequisiteEntry)
  1983. && *(pInfo->pEntry->pszPrerequisiteEntry))
  1984. {
  1985. g_pRasHangUp(hrasconnPrereq);
  1986. }
  1987. }
  1988. // Clean up.
  1989. //
  1990. if (!lpInfo->reserved)
  1991. {
  1992. if (pInfo->pFileMain)
  1993. {
  1994. ClosePhonebookFile( pInfo->pFileMain );
  1995. }
  1996. if (pInfo->pUser)
  1997. {
  1998. DestroyUserPreferences( pInfo->pUser );
  1999. }
  2000. }
  2001. if (pInfo->fFilePrereqOpen)
  2002. {
  2003. ClosePhonebookFile( &pInfo->filePrereq );
  2004. }
  2005. ZeroMemory( pInfo->rdp.szPassword, sizeof(pInfo->rdp.szPassword) );
  2006. if (pInfo->pListPortsToDelete)
  2007. {
  2008. DtlDestroyList( pInfo->pListPortsToDelete, DestroyPszNode );
  2009. }
  2010. if (hEapFree)
  2011. DialerEapCleanup(hEapFree, pbEapUserData, pwszEapIdentity);
  2012. Free( pInfo );
  2013. return fStatus;
  2014. }
  2015. //----------------------------------------------------------------------------
  2016. // Local utilities
  2017. // Listed alphabetically
  2018. //----------------------------------------------------------------------------
  2019. DWORD
  2020. RasCredToDialParam(
  2021. IN TCHAR* pszDefaultUserName,
  2022. IN TCHAR* pszDefaultDomain,
  2023. IN RASCREDENTIALS* pCreds,
  2024. OUT RASDIALPARAMS* pParams)
  2025. {
  2026. TCHAR* pszComputer = NULL;
  2027. TCHAR* pszLogonDomain = NULL;
  2028. TCHAR* pszUser = NULL;
  2029. // Set the user name, defaulting it if needed
  2030. //
  2031. if (pCreds->dwMask & RASCM_UserName)
  2032. {
  2033. lstrcpyn(
  2034. pParams->szUserName,
  2035. pCreds->szUserName,
  2036. sizeof(pParams->szUserName) / sizeof(TCHAR));
  2037. }
  2038. else if (pszDefaultUserName)
  2039. {
  2040. lstrcpyn(
  2041. pParams->szUserName,
  2042. pszDefaultUserName,
  2043. sizeof(pParams->szUserName) / sizeof(TCHAR));
  2044. }
  2045. else
  2046. {
  2047. pszUser = GetLogonUser();
  2048. if (pszUser)
  2049. {
  2050. lstrcpyn(
  2051. pParams->szUserName,
  2052. pszUser,
  2053. sizeof(pParams->szUserName) / sizeof(TCHAR));
  2054. }
  2055. }
  2056. // Set the domain name, defaulting it if needed
  2057. //
  2058. if (pCreds->dwMask & RASCM_Domain)
  2059. {
  2060. lstrcpyn(
  2061. pParams->szDomain,
  2062. pCreds->szDomain,
  2063. sizeof(pParams->szDomain) / sizeof(TCHAR));
  2064. }
  2065. else if ( pszDefaultDomain )
  2066. {
  2067. lstrcpyn(
  2068. pParams->szDomain,
  2069. pszDefaultDomain,
  2070. sizeof(pParams->szDomain) / sizeof(TCHAR));
  2071. }
  2072. else
  2073. {
  2074. pszComputer = GetComputer();
  2075. pszLogonDomain = GetLogonDomain();
  2076. if ( (pszComputer) &&
  2077. (pszLogonDomain) &&
  2078. (lstrcmp( pszComputer, pszLogonDomain ) != 0))
  2079. {
  2080. lstrcpyn(
  2081. pParams->szDomain,
  2082. pszLogonDomain,
  2083. sizeof(pParams->szDomain) / sizeof(TCHAR));
  2084. }
  2085. }
  2086. // Fill in the password field
  2087. //
  2088. if (pCreds->dwMask & RASCM_Password)
  2089. {
  2090. // Whistler bug 254385 encode password when not being used
  2091. // Assumed password was encoded previously
  2092. //
  2093. DecodePassword( pCreds->szPassword );
  2094. lstrcpyn(
  2095. pParams->szPassword,
  2096. pCreds->szPassword,
  2097. sizeof(pParams->szPassword) / sizeof(TCHAR) );
  2098. EncodePassword( pCreds->szPassword );
  2099. EncodePassword( pParams->szPassword );
  2100. }
  2101. return NO_ERROR;
  2102. }
  2103. DWORD
  2104. FindEntryCredentials(
  2105. IN TCHAR* pszPath,
  2106. IN TCHAR* pszEntryName,
  2107. IN TCHAR* pszDefaultUserName,
  2108. IN TCHAR* pszDefaultDomain,
  2109. OUT RASDIALPARAMS* pUser, // per user credentials
  2110. OUT RASDIALPARAMS* pGlobal, // global credentials
  2111. OUT BOOL* pfUser, // set true if per user creds found
  2112. OUT BOOL* pfGlobal // set true if global creds found
  2113. )
  2114. // Loads the credentials for the given entry into memory. This routine
  2115. // determines whether per-user or per-connection credentials exist or
  2116. // both.
  2117. //
  2118. // The logic is a little complicated because RasGetCredentials had to
  2119. // support legacy usage of the API.
  2120. //
  2121. // Here's how it works. If only one set of credentials is stored for a
  2122. // connection, then RasGetCredentials will return that set regardless of
  2123. // whether the RASCM_DefalutCreds flag is set. If two sets of credentials
  2124. // are saved, then RasGetCredentials will return the per-user credentials
  2125. // if the RASCM_DefaultCreds bit is set, and the per-connection credentials
  2126. // otherwise.
  2127. //
  2128. // Here is the algorithm for loading the credentials
  2129. //
  2130. // 1. Call RasGetCredentials with the RASCM_DefaultCreds bit cleared
  2131. // 1a. If nothing is returned, no credentials are saved
  2132. // 1b. If the RASCM_DefaultCreds bit is set on return, then only
  2133. // global credentials are saved.
  2134. //
  2135. // 2. Call RasGetCredentials with the RASCM_DefaultCreds bit set
  2136. // 2a. If the RASCM_DefaultCreds bit is set on return, then
  2137. // both global and per-connection credentials are saved.
  2138. // 2b. Otherwise, only per-user credentials are saved.
  2139. //
  2140. {
  2141. DWORD dwErr;
  2142. RASCREDENTIALS rc1, rc2;
  2143. BOOL fUseLogonDomain;
  2144. TRACE( "FindEntryCredentials" );
  2145. // Initialize
  2146. //
  2147. *pfUser = FALSE;
  2148. *pfGlobal = FALSE;
  2149. ZeroMemory( &rc1, sizeof(rc1) );
  2150. ZeroMemory( &rc2, sizeof(rc2) );
  2151. rc1.dwSize = sizeof(rc1);
  2152. rc2.dwSize = sizeof(rc2);
  2153. do
  2154. {
  2155. // Look up per-user cached username, password, and domain.
  2156. // See comment '1.' in the function header
  2157. //
  2158. rc1.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain;
  2159. ASSERT( g_pRasGetCredentials );
  2160. TRACE( "RasGetCredentials per-user" );
  2161. dwErr = g_pRasGetCredentials(pszPath, pszEntryName, &rc1 );
  2162. TRACE2( "RasGetCredentials=%d,m=%d", dwErr, rc1.dwMask );
  2163. if (dwErr != NO_ERROR)
  2164. {
  2165. break;
  2166. }
  2167. // See 1a. in the function header comments
  2168. //
  2169. if (rc1.dwMask == 0)
  2170. {
  2171. dwErr = NO_ERROR;
  2172. break;
  2173. }
  2174. // See 1b. in the function header comments
  2175. //
  2176. else if (rc1.dwMask & RASCM_DefaultCreds)
  2177. {
  2178. *pfGlobal = TRUE;
  2179. // Whistler bug 254385 encode password when not being used
  2180. // Assumed password was not encoded by RasGetCredentials()
  2181. //
  2182. EncodePassword( rc1.szPassword );
  2183. RasCredToDialParam(
  2184. pszDefaultUserName,
  2185. pszDefaultDomain,
  2186. &rc1,
  2187. pGlobal );
  2188. dwErr = NO_ERROR;
  2189. break;
  2190. }
  2191. // Look up global per-user cached username, password, domain.
  2192. // See comment 2. in the function header
  2193. //
  2194. rc2.dwMask =
  2195. RASCM_UserName | RASCM_Password | RASCM_Domain | RASCM_DefaultCreds;
  2196. ASSERT( g_pRasGetCredentials );
  2197. TRACE( "RasGetCredentials global" );
  2198. dwErr = g_pRasGetCredentials(pszPath, pszEntryName, &rc2 );
  2199. TRACE2( "RasGetCredentials=%d,m=%d", dwErr, rc2.dwMask );
  2200. if (dwErr != NO_ERROR)
  2201. {
  2202. break;
  2203. }
  2204. // See 2a. in the function header comments
  2205. //
  2206. if (rc2.dwMask & RASCM_DefaultCreds)
  2207. {
  2208. *pfGlobal = TRUE;
  2209. if (rc1.dwMask & RASCM_Password)
  2210. {
  2211. *pfUser = TRUE;
  2212. }
  2213. // Whistler bug 254385 encode password when not being used
  2214. // Assumed password was not encoded by RasGetCredentials()
  2215. //
  2216. EncodePassword( rc1.szPassword );
  2217. RasCredToDialParam(
  2218. pszDefaultUserName,
  2219. pszDefaultDomain,
  2220. &rc1,
  2221. pUser );
  2222. EncodePassword( rc2.szPassword );
  2223. RasCredToDialParam(
  2224. pszDefaultUserName,
  2225. pszDefaultDomain,
  2226. &rc2,
  2227. pGlobal );
  2228. }
  2229. // See 2b. in the function header comments
  2230. //
  2231. else
  2232. {
  2233. if (rc1.dwMask & RASCM_Password)
  2234. {
  2235. *pfUser = TRUE;
  2236. }
  2237. // Whistler bug 254385 encode password when not being used
  2238. // Assumed password was not encoded by RasGetCredentials()
  2239. //
  2240. EncodePassword( rc1.szPassword );
  2241. RasCredToDialParam(
  2242. pszDefaultUserName,
  2243. pszDefaultDomain,
  2244. &rc1,
  2245. pUser );
  2246. }
  2247. }while (FALSE);
  2248. // Cleanup
  2249. //
  2250. {
  2251. // Whistler bug 254385 encode password when not being used
  2252. //
  2253. ZeroMemory( rc1.szPassword, sizeof(rc1.szPassword) );
  2254. ZeroMemory( rc2.szPassword, sizeof(rc2.szPassword) );
  2255. }
  2256. return dwErr;
  2257. }
  2258. DWORD
  2259. FindEntryAndSetDialParams(
  2260. IN DINFO* pInfo )
  2261. // Look up the entry and fill in the RASDIALPARAMS parameters accordingly.
  2262. // This routine contains all DINFO context initialization that can be
  2263. // affected by user actions on the property sheet. 'PInfo' is the
  2264. // partially initialized common dial dialog context.
  2265. //
  2266. // 'pInfo->fPrerequisiteDial'is set at entry if the prerequisite entry, if
  2267. // any, should be dialed first. If there is no prerequisite entry, the
  2268. // flag is cleared and the main entry dialed.
  2269. //
  2270. {
  2271. DWORD dwErr;
  2272. RASDIALPARAMS* prdp, *prdpu, *prdpg;
  2273. if (pInfo->fFilePrereqOpen)
  2274. {
  2275. ClosePhonebookFile( pInfo->pFile );
  2276. pInfo->pFile = pInfo->pFileMain;
  2277. pInfo->fFilePrereqOpen = FALSE;
  2278. }
  2279. // Lookup entry node specified by caller and save reference for
  2280. // convenience elsewhere.
  2281. //
  2282. pInfo->pNode = EntryNodeFromName(
  2283. pInfo->pFile->pdtllistEntries, pInfo->pszEntry );
  2284. if (!pInfo->pNode)
  2285. {
  2286. dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  2287. return dwErr;
  2288. }
  2289. pInfo->pEntry = pInfo->pEntryMain = (PBENTRY* )DtlGetData( pInfo->pNode );
  2290. ASSERT( pInfo->pEntry );
  2291. // Switch to the prerequisite entry, if indicated.
  2292. //
  2293. if (pInfo->fPrerequisiteDial)
  2294. {
  2295. if (pInfo->pEntry->pszPrerequisiteEntry
  2296. && *(pInfo->pEntry->pszPrerequisiteEntry))
  2297. {
  2298. ASSERT( !pInfo->fFilePrereqOpen );
  2299. // GetPbkAndEntryName first looks in the All Users phonebook file
  2300. // if a phonebook file is not specified. If the entry is not
  2301. // found there it looks in files present in the Users profile.
  2302. // This needs to be done since we are discontinuing the per-user
  2303. // pbk file being set through user preferences.
  2304. //
  2305. dwErr = GetPbkAndEntryName(
  2306. pInfo->pEntry->pszPrerequisitePbk,
  2307. pInfo->pEntry->pszPrerequisiteEntry,
  2308. 0,
  2309. &pInfo->filePrereq,
  2310. &pInfo->pNode);
  2311. if (dwErr != 0)
  2312. {
  2313. return dwErr;
  2314. }
  2315. pInfo->pFile = &pInfo->filePrereq;
  2316. pInfo->fFilePrereqOpen = TRUE;
  2317. pInfo->pEntry = (PBENTRY* )DtlGetData( pInfo->pNode );
  2318. ASSERT( pInfo->pEntry );
  2319. }
  2320. else
  2321. {
  2322. pInfo->fPrerequisiteDial = FALSE;
  2323. }
  2324. }
  2325. // Set up RasDial parameter blocks.
  2326. //
  2327. prdp = &pInfo->rdp;
  2328. prdpu = &pInfo->rdpu;
  2329. prdpg = &pInfo->rdpg;
  2330. ZeroMemory( prdp, sizeof(*prdp) );
  2331. pInfo->fUnattended = FALSE;
  2332. prdp->dwSize = sizeof(*prdp);
  2333. lstrcpyn(
  2334. prdp->szEntryName,
  2335. pInfo->pEntry->pszEntryName,
  2336. sizeof(prdp->szEntryName) / sizeof(TCHAR));
  2337. if (pInfo->pszPhoneNumber)
  2338. {
  2339. lstrcpyn(
  2340. prdp->szPhoneNumber,
  2341. pInfo->pszPhoneNumber,
  2342. RAS_MaxPhoneNumber + 1);
  2343. }
  2344. // Whistler bug 272819 Not prompted for callback number
  2345. // We must do this before the init of per-user and global variants
  2346. //
  2347. if (!pInfo->fUnattended)
  2348. {
  2349. // '*' means "behave as defined in user preferences", while leaving it
  2350. // zero would mean "don't request callback if server offers".
  2351. //
  2352. // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
  2353. //
  2354. lstrcpyn(
  2355. prdp->szCallbackNumber,
  2356. TEXT("*"),
  2357. sizeof(prdp->szCallbackNumber) / sizeof(TCHAR) );
  2358. }
  2359. // Initialze the per-user and global variants
  2360. //
  2361. CopyMemory(prdpu, prdp, sizeof(*prdp));
  2362. CopyMemory(prdpg, prdp, sizeof(*prdp));
  2363. // Set the subentry link to whatever the RasDialDlg caller specified. See
  2364. // bug 200351.
  2365. //
  2366. prdp->dwSubEntry = pInfo->pArgs->dwSubEntry;
  2367. // If running in "unattended" mode, i.e. called by RASAUTO to redial on
  2368. // link failure, read the user/password/domain and callback number used on
  2369. // the original call. (Actually found a use for the crappy
  2370. // RasGetEntryDialParams API)
  2371. //
  2372. if (pInfo->pArgs->dwFlags & RASDDFLAG_LinkFailure)
  2373. {
  2374. RASDIALPARAMS rdp;
  2375. BOOL fSavedPw = HaveSavedPw( pInfo );
  2376. ZeroMemory( &rdp, sizeof(rdp) );
  2377. rdp.dwSize = sizeof(rdp);
  2378. lstrcpyn(
  2379. rdp.szEntryName,
  2380. pInfo->pEntry->pszEntryName,
  2381. sizeof(rdp.szEntryName) / sizeof(TCHAR)
  2382. );
  2383. //For whistler bug 313509 gangz
  2384. //We use FindEntryCredentials() to get saved password perUser and
  2385. //perConnection inforation, use RasGetEntryDialParams() to get back
  2386. //Callback Numbers
  2387. //
  2388. {
  2389. RASDIALPARAMS rdTemp;
  2390. TCHAR * pszTempUser, * pszTempDomain;
  2391. DWORD dwErr = NO_ERROR;
  2392. pszTempUser = pszTempDomain = NULL;
  2393. dwErr = FindEntryCredentials(
  2394. pInfo->pFile->pszPath,
  2395. pInfo->pEntry->pszEntryName,
  2396. pszTempUser,
  2397. pszTempDomain,
  2398. &rdTemp,
  2399. &rdTemp,
  2400. &(pInfo->fHaveSavedPwUser),
  2401. &(pInfo->fHaveSavedPwGlobal));
  2402. ZeroMemory( &rdTemp, sizeof(rdTemp) );
  2403. Free0(pszTempUser);
  2404. Free0(pszTempDomain);
  2405. }
  2406. TRACE( "RasGetEntryDialParams" );
  2407. ASSERT( g_pRasGetEntryDialParams );
  2408. dwErr = g_pRasGetEntryDialParams(
  2409. pInfo->pFile->pszPath, &rdp, &fSavedPw );
  2410. TRACE2( "RasGetEntryDialParams=%d,f=%d", dwErr, &fSavedPw );
  2411. TRACEW1( "u=%s", rdp.szUserName );
  2412. //TRACEW1( "p=%s", rdp.szPassword );
  2413. TRACEW1( "d=%s", rdp.szDomain );
  2414. TRACEW1( "c=%s", rdp.szCallbackNumber );
  2415. if (dwErr == 0)
  2416. {
  2417. lstrcpyn(
  2418. prdp->szUserName,
  2419. rdp.szUserName,
  2420. sizeof(prdp->szUserName) / sizeof(TCHAR));
  2421. // Whistler bug 254385 encode password when not being used
  2422. // Assumed password was not encoded by RasGetEntryDialParams()
  2423. //
  2424. lstrcpyn(
  2425. prdp->szPassword,
  2426. rdp.szPassword,
  2427. sizeof(prdp->szPassword) / sizeof(TCHAR) );
  2428. EncodePassword( prdp->szPassword );
  2429. lstrcpyn(
  2430. prdp->szDomain,
  2431. rdp.szDomain,
  2432. sizeof(prdp->szDomain) / sizeof(TCHAR));
  2433. lstrcpyn(
  2434. prdp->szCallbackNumber,
  2435. rdp.szCallbackNumber,
  2436. sizeof(prdp->szCallbackNumber) / sizeof(TCHAR));
  2437. pInfo->fUnattended = TRUE;
  2438. }
  2439. ZeroMemory( rdp.szPassword, sizeof(rdp.szPassword) );
  2440. }
  2441. if (pInfo->pNoUser)
  2442. {
  2443. // Use the credentials we got from API caller, presumably the ones
  2444. // entered at Ctrl-Alt-Del.
  2445. //
  2446. lstrcpyn(
  2447. prdp->szUserName,
  2448. pInfo->pNoUser->szUserName,
  2449. sizeof(prdp->szUserName) / sizeof(TCHAR));
  2450. //
  2451. // Don't copy the password if its smartcard logon
  2452. // and the entry being used is a non-eap connectoid
  2453. //
  2454. // Whistler bug 254385 encode password when not being used
  2455. // Assumed password was encoded by caller of RasDialDlg()
  2456. //
  2457. DecodePassword( pInfo->pNoUser->szPassword );
  2458. lstrcpyn(
  2459. prdp->szPassword,
  2460. pInfo->pNoUser->szPassword,
  2461. sizeof(prdp->szPassword) / sizeof(TCHAR) );
  2462. EncodePassword( pInfo->pNoUser->szPassword );
  2463. EncodePassword( prdp->szPassword );
  2464. if (pInfo->pEntry->fPreviewDomain)
  2465. {
  2466. lstrcpyn(
  2467. prdp->szDomain,
  2468. pInfo->pNoUser->szDomain,
  2469. sizeof(prdp->szDomain) / sizeof(TCHAR));
  2470. }
  2471. else
  2472. {
  2473. // Don't use Winlogon domain unless "include domain" option is
  2474. // selected. See bug 387266.
  2475. //
  2476. // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
  2477. //
  2478. lstrcpyn(
  2479. prdp->szDomain,
  2480. TEXT(""),
  2481. sizeof(prdp->szDomain) / sizeof(TCHAR) );
  2482. }
  2483. }
  2484. else if (!pInfo->fUnattended)
  2485. {
  2486. DWORD dwErrRc;
  2487. BOOL fUseLogonDomain;
  2488. TCHAR* pszDefaultUser;
  2489. dwErrRc = FindEntryCredentials(
  2490. pInfo->pFile->pszPath,
  2491. pInfo->pEntry->pszEntryName,
  2492. pInfo->pEntry->pszOldUser,
  2493. pInfo->pEntry->pszOldDomain,
  2494. prdpu,
  2495. prdpg,
  2496. &(pInfo->fHaveSavedPwUser),
  2497. &(pInfo->fHaveSavedPwGlobal));
  2498. if (! pInfo->pEntry->fAutoLogon)
  2499. {
  2500. // If saved passwords are disabled, clear here
  2501. //
  2502. if (pInfo->fDisableSavePw)
  2503. {
  2504. pInfo->fHaveSavedPwUser = FALSE;
  2505. pInfo->fHaveSavedPwGlobal = FALSE;
  2506. ZeroMemory(prdp->szPassword, sizeof(prdp->szPassword));
  2507. ZeroMemory(prdpu->szPassword, sizeof(prdpu->szPassword));
  2508. ZeroMemory(prdpg->szPassword, sizeof(prdpg->szPassword));
  2509. }
  2510. // If including domains is disabled, clear here
  2511. //
  2512. if (! pInfo->pEntry->fPreviewDomain)
  2513. {
  2514. // (SteveC) Don't do this in the 'fAutoLogon' case. See bug
  2515. // 207611.
  2516. //
  2517. ZeroMemory(prdp->szDomain, sizeof(prdp->szDomain));
  2518. ZeroMemory(prdpu->szDomain, sizeof(prdpu->szDomain));
  2519. ZeroMemory(prdpg->szDomain, sizeof(prdpg->szDomain));
  2520. }
  2521. }
  2522. if(!pInfo->pEntry->fAutoLogon)
  2523. {
  2524. // Initialize the dial params that will be passed to RasDial.
  2525. //
  2526. // Note that per-user credentials are always used when both
  2527. // per-user and global credentials are saved. The per-user
  2528. // credentials should be copied even if there is no saved
  2529. // password since there may be a saved identity.
  2530. //
  2531. CopyMemory(prdp, prdpu, sizeof(*prdp));
  2532. if (pInfo->fHaveSavedPwGlobal && !pInfo->fHaveSavedPwUser)
  2533. {
  2534. CopyMemory(prdp, prdpg, sizeof(*prdp));
  2535. }
  2536. }
  2537. }
  2538. return 0;
  2539. }
  2540. //----------------------------------------------------------------------------
  2541. // Bundling Errors dialog
  2542. // Listed alphabetically following stub API and dialog proc
  2543. //----------------------------------------------------------------------------
  2544. BOOL
  2545. BundlingErrorsDlg(
  2546. IN OUT DPINFO* pInfo )
  2547. // Popup the Bundling Errors dialog. 'PInfo' is the dialing progress
  2548. // dialog context.
  2549. //
  2550. // Returns true if user chooses to accept the results or false if he
  2551. // chooses to hang up.
  2552. //
  2553. {
  2554. INT_PTR nStatus;
  2555. TRACE( "BundlingErrorsDlg" );
  2556. nStatus =
  2557. (BOOL )DialogBoxParam(
  2558. g_hinstDll,
  2559. MAKEINTRESOURCE( DID_BE_BundlingErrors ),
  2560. pInfo->hwndDlg,
  2561. BeDlgProc,
  2562. (LPARAM )pInfo );
  2563. if (nStatus == -1)
  2564. {
  2565. ErrorDlg( pInfo->hwndDlg, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  2566. nStatus = FALSE;
  2567. }
  2568. return (BOOL )nStatus;
  2569. }
  2570. INT_PTR CALLBACK
  2571. BeDlgProc(
  2572. IN HWND hwnd,
  2573. IN UINT unMsg,
  2574. IN WPARAM wparam,
  2575. IN LPARAM lparam )
  2576. // DialogProc callback for the Bundling Errors dialog. Parameters and
  2577. // return value are as described for standard windows 'DialogProc's.
  2578. //
  2579. {
  2580. #if 0
  2581. TRACE4( "BeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  2582. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  2583. #endif
  2584. if (ListView_OwnerHandler(
  2585. hwnd, unMsg, wparam, lparam, BeLvErrorsCallback ))
  2586. {
  2587. return TRUE;
  2588. }
  2589. switch (unMsg)
  2590. {
  2591. case WM_INITDIALOG:
  2592. {
  2593. return BeInit( hwnd, (DPINFO* )lparam );
  2594. }
  2595. case WM_COMMAND:
  2596. {
  2597. return BeCommand(
  2598. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  2599. }
  2600. }
  2601. return FALSE;
  2602. }
  2603. BOOL
  2604. BeCommand(
  2605. IN HWND hwnd,
  2606. IN WORD wNotification,
  2607. IN WORD wId,
  2608. IN HWND hwndCtrl )
  2609. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  2610. // the notification code of the command. 'wId' is the control/menu
  2611. // identifier of the command. 'HwndCtrl' is the control window handle of
  2612. // the command.
  2613. //
  2614. // Returns true if processed message, false otherwise.
  2615. //
  2616. {
  2617. DWORD dwErr;
  2618. TRACE3( "BeCommand(n=%d,i=%d,c=$%x)",
  2619. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  2620. switch (wId)
  2621. {
  2622. case IDOK:
  2623. case IDCANCEL:
  2624. {
  2625. TRACE1( "%s pressed", (wId==IDOK) ? "OK" : "Cancel" );
  2626. if (IsDlgButtonChecked( hwnd, CID_BE_CB_DisableLink ))
  2627. {
  2628. DWORD i;
  2629. DPINFO* pInfo;
  2630. DPSTATE* pState;
  2631. // Caller says to delete the links that failed in the entry.
  2632. // Create a list of Psz nodes containing the unique port name
  2633. // of each failed link so they can be removed after the state
  2634. // information is freed.
  2635. //
  2636. pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  2637. for (i = 0, pState = pInfo->pStates;
  2638. i < pInfo->cStates;
  2639. ++i, ++pState)
  2640. {
  2641. DTLNODE* pNode;
  2642. DTLNODE* pNodePtd;
  2643. PBLINK* pLink;
  2644. if (pState->dwError != 0)
  2645. {
  2646. if (!pInfo->pArgs->pListPortsToDelete)
  2647. {
  2648. pInfo->pArgs->pListPortsToDelete =
  2649. DtlCreateList( 0L );
  2650. if (!pInfo->pArgs->pListPortsToDelete)
  2651. {
  2652. continue;
  2653. }
  2654. }
  2655. pNode = DtlNodeFromIndex(
  2656. pInfo->pArgs->pEntry->pdtllistLinks, (LONG )i );
  2657. if (!pNode)
  2658. {
  2659. continue;
  2660. }
  2661. pLink = (PBLINK* )DtlGetData( pNode );
  2662. pNodePtd = CreatePszNode( pLink->pbport.pszPort );
  2663. if (!pNodePtd)
  2664. {
  2665. continue;
  2666. }
  2667. DtlAddNodeLast(
  2668. pInfo->pArgs->pListPortsToDelete, pNodePtd );
  2669. }
  2670. }
  2671. }
  2672. EndDialog( hwnd, (wId == IDOK) );
  2673. return TRUE;
  2674. }
  2675. }
  2676. return FALSE;
  2677. }
  2678. VOID
  2679. BeFillLvErrors(
  2680. IN HWND hwndLv,
  2681. IN DPINFO* pInfo )
  2682. // Fill the listview 'hwndLv' with devices and error strings and select
  2683. // the first item. 'PInfo' is the dialing progress dialog context.
  2684. //
  2685. {
  2686. INT iItem;
  2687. DWORD i;
  2688. DPSTATE* pState;
  2689. TRACE( "BeFillLvErrors" );
  2690. ListView_DeleteAllItems( hwndLv );
  2691. // Add columns.
  2692. //
  2693. {
  2694. LV_COLUMN col;
  2695. TCHAR* pszHeader0;
  2696. TCHAR* pszHeader1;
  2697. pszHeader0 = PszFromId( g_hinstDll, SID_DeviceColHead );
  2698. pszHeader1 = PszFromId( g_hinstDll, SID_StatusColHead );
  2699. ZeroMemory( &col, sizeof(col) );
  2700. col.mask = LVCF_FMT + LVCF_TEXT;
  2701. col.fmt = LVCFMT_LEFT;
  2702. col.pszText = (pszHeader0) ? pszHeader0 : TEXT("");
  2703. ListView_InsertColumn( hwndLv, 0, &col );
  2704. ZeroMemory( &col, sizeof(col) );
  2705. col.mask = LVCF_FMT + LVCF_SUBITEM + LVCF_TEXT;
  2706. col.fmt = LVCFMT_LEFT;
  2707. col.pszText = (pszHeader1) ? pszHeader1 : TEXT("");
  2708. col.iSubItem = 1;
  2709. ListView_InsertColumn( hwndLv, 1, &col );
  2710. Free0( pszHeader0 );
  2711. Free0( pszHeader1 );
  2712. }
  2713. // Add the modem and adapter images.
  2714. //
  2715. ListView_SetDeviceImageList( hwndLv, g_hinstDll );
  2716. // Load listview with device/status pairs.
  2717. //
  2718. iItem = 0;
  2719. for (i = 0, pState = pInfo->pStates; i < pInfo->cStates; ++i, ++pState)
  2720. {
  2721. LV_ITEM item;
  2722. DTLNODE* pNode;
  2723. PBLINK* pLink;
  2724. TCHAR* psz;
  2725. pNode = DtlNodeFromIndex(
  2726. pInfo->pArgs->pEntry->pdtllistLinks, (LONG )i );
  2727. if (pNode)
  2728. {
  2729. pLink = (PBLINK* )DtlGetData( pNode );
  2730. psz = DisplayPszFromDeviceAndPort(
  2731. pLink->pbport.pszDevice, pLink->pbport.pszPort );
  2732. if (psz)
  2733. {
  2734. ZeroMemory( &item, sizeof(item) );
  2735. item.mask = LVIF_TEXT + LVIF_IMAGE;
  2736. item.iItem = iItem;
  2737. item.pszText = psz;
  2738. item.iImage =
  2739. (pLink->pbport.pbdevicetype == PBDT_Modem)
  2740. ? DI_Modem : DI_Adapter;
  2741. ListView_InsertItem( hwndLv, &item );
  2742. Free( psz );
  2743. if (pState->dwError == 0)
  2744. {
  2745. psz = PszFromId( g_hinstDll, SID_Connected );
  2746. ListView_SetItemText( hwndLv, iItem, 1, psz );
  2747. Free( psz );
  2748. }
  2749. else
  2750. {
  2751. psz = BeGetErrorPsz( pState->dwError );
  2752. ListView_SetItemText( hwndLv, iItem, 1, psz );
  2753. LocalFree( psz );
  2754. }
  2755. ++iItem;
  2756. }
  2757. }
  2758. }
  2759. // Auto-size columns to look good with the text they contain.
  2760. //
  2761. ListView_SetColumnWidth( hwndLv, 0, LVSCW_AUTOSIZE_USEHEADER );
  2762. ListView_SetColumnWidth( hwndLv, 1, LVSCW_AUTOSIZE_USEHEADER );
  2763. // Select the first item.
  2764. //
  2765. ListView_SetItemState( hwndLv, 0, LVIS_SELECTED, LVIS_SELECTED );
  2766. }
  2767. TCHAR*
  2768. BeGetErrorPsz(
  2769. IN DWORD dwError )
  2770. // Returns a string suitable for the Status column with error 'dwError' or
  2771. // NULL on error. 'DwError' is assumed to be non-0. It is caller's
  2772. // responsiblility to LocalFree the returned string.
  2773. //
  2774. {
  2775. TCHAR* pszErrStr;
  2776. TCHAR szErrNumBuf[ MAXLTOTLEN + 1 ];
  2777. TCHAR* pszLineFormat;
  2778. TCHAR* pszLine;
  2779. TCHAR* apszArgs[ 2 ];
  2780. LToT( dwError, szErrNumBuf, 10 );
  2781. pszErrStr = NULL;
  2782. GetErrorText( dwError, &pszErrStr );
  2783. pszLine = NULL;
  2784. pszLineFormat = PszFromId( g_hinstDll, SID_FMT_Error );
  2785. if (pszLineFormat)
  2786. {
  2787. apszArgs[ 0 ] = szErrNumBuf;
  2788. apszArgs[ 1 ] = (pszErrStr) ? pszErrStr : TEXT("");
  2789. FormatMessage(
  2790. FORMAT_MESSAGE_FROM_STRING
  2791. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  2792. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  2793. pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1,
  2794. (va_list* )apszArgs );
  2795. Free( pszLineFormat );
  2796. }
  2797. Free0( pszErrStr );
  2798. return pszLine;
  2799. }
  2800. BOOL
  2801. BeInit(
  2802. IN HWND hwndDlg,
  2803. IN DPINFO* pArgs )
  2804. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  2805. // 'PArgs' is caller's arguments to the stub API.
  2806. //
  2807. // Return false if focus was set, true otherwise, i.e. as defined for
  2808. // WM_INITDIALOG.
  2809. //
  2810. {
  2811. DWORD dwErr;
  2812. HWND hwndLvErrors;
  2813. HWND hwndCbDisableLink;
  2814. TRACE( "BeInit" );
  2815. hwndLvErrors = GetDlgItem( hwndDlg, CID_BE_LV_Errors );
  2816. ASSERT( hwndLvErrors );
  2817. hwndCbDisableLink = GetDlgItem( hwndDlg, CID_BE_CB_DisableLink );
  2818. ASSERT( hwndCbDisableLink );
  2819. // Save Dial Progress context as dialog context.
  2820. //
  2821. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pArgs );
  2822. // Load listview with device/error information.
  2823. //
  2824. BeFillLvErrors( hwndLvErrors, pArgs );
  2825. // Display the finished window above all other windows. The window
  2826. // position is set to "topmost" then immediately set to "not topmost"
  2827. // because we want it on top but not always-on-top. Always-on-top alone
  2828. // is incredibly annoying, e.g. it is always on top of the on-line help if
  2829. // user presses the Help button.
  2830. //
  2831. SetWindowPos(
  2832. hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
  2833. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  2834. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  2835. ShowWindow( hwndDlg, SW_SHOW );
  2836. SetWindowPos(
  2837. hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
  2838. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  2839. SetFocus( hwndCbDisableLink );
  2840. return FALSE;
  2841. }
  2842. LVXDRAWINFO*
  2843. BeLvErrorsCallback(
  2844. IN HWND hwndLv,
  2845. IN DWORD dwItem )
  2846. // Enhanced list view callback to report drawing information. 'HwndLv' is
  2847. // the handle of the list view control. 'DwItem' is the index of the item
  2848. // being drawn.
  2849. //
  2850. // Returns the address of the column information.
  2851. //
  2852. {
  2853. // Use "wide selection bar" feature and the other recommended options.
  2854. //
  2855. // Fields are 'nCols', 'dxIndent', 'dwFlags', 'adwFlags[]'.
  2856. //
  2857. static LVXDRAWINFO info =
  2858. { 2, 0, LVXDI_Blend50Dis + LVXDI_DxFill, { 0, 0 } };
  2859. return &info;
  2860. }
  2861. //----------------------------------------------------------------------------
  2862. // Change Password dialog
  2863. // Listed alphabetically following stub API and dialog proc
  2864. //----------------------------------------------------------------------------
  2865. BOOL
  2866. ChangePasswordDlg(
  2867. IN HWND hwndOwner,
  2868. IN BOOL fOldPassword,
  2869. OUT TCHAR* pszOldPassword,
  2870. OUT TCHAR* pszNewPassword )
  2871. // Popup the Change Password dialog. 'HwndOwner' is the owning window.
  2872. // 'FOldPassword' is set true if user must supply an old password, false
  2873. // if no old password is required. 'PszOldPassword' and 'pszNewPassword'
  2874. // are caller's buffers for the returned passwords.
  2875. //
  2876. // Returns true if user presses OK and succeeds, false otherwise.
  2877. //
  2878. {
  2879. INT_PTR nStatus;
  2880. CPARGS args;
  2881. TRACE( "ChangePasswordDlg" );
  2882. args.fOldPassword = fOldPassword;
  2883. args.pszOldPassword = pszOldPassword;
  2884. args.pszNewPassword = pszNewPassword;
  2885. nStatus =
  2886. (BOOL )DialogBoxParam(
  2887. g_hinstDll,
  2888. (fOldPassword)
  2889. ? MAKEINTRESOURCE( DID_CP_ChangePassword2 )
  2890. : MAKEINTRESOURCE( DID_CP_ChangePassword ),
  2891. hwndOwner,
  2892. CpDlgProc,
  2893. (LPARAM )&args );
  2894. if (nStatus == -1)
  2895. {
  2896. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  2897. nStatus = FALSE;
  2898. }
  2899. return (BOOL )nStatus;
  2900. }
  2901. INT_PTR CALLBACK
  2902. CpDlgProc(
  2903. IN HWND hwnd,
  2904. IN UINT unMsg,
  2905. IN WPARAM wparam,
  2906. IN LPARAM lparam )
  2907. // DialogProc callback for the Change Password dialog. Parameters and
  2908. // return value are as described for standard windows 'DialogProc's.
  2909. //
  2910. {
  2911. #if 0
  2912. TRACE4( "CpDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  2913. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  2914. #endif
  2915. switch (unMsg)
  2916. {
  2917. case WM_INITDIALOG:
  2918. {
  2919. return CpInit( hwnd, (CPARGS* )lparam );
  2920. }
  2921. case WM_HELP:
  2922. case WM_CONTEXTMENU:
  2923. {
  2924. ContextHelp( g_adwCpHelp, hwnd, unMsg, wparam, lparam );
  2925. break;
  2926. }
  2927. case WM_COMMAND:
  2928. {
  2929. return CpCommand(
  2930. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  2931. }
  2932. }
  2933. return FALSE;
  2934. }
  2935. BOOL
  2936. CpCommand(
  2937. IN HWND hwnd,
  2938. IN WORD wNotification,
  2939. IN WORD wId,
  2940. IN HWND hwndCtrl )
  2941. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  2942. // the notification code of the command. 'wId' is the control/menu
  2943. // identifier of the command. 'HwndCtrl' is the control window handle of
  2944. // the command.
  2945. //
  2946. // Returns true if processed message, false otherwise.
  2947. //
  2948. {
  2949. DWORD dwErr;
  2950. TRACE3( "CpCommand(n=%d,i=%d,c=$%x)",
  2951. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  2952. switch (wId)
  2953. {
  2954. case IDOK:
  2955. {
  2956. CPWINFO* pInfo;
  2957. TCHAR szNewPassword[ PWLEN + 1 ];
  2958. TCHAR szNewPassword2[ PWLEN + 1 ];
  2959. TRACE( "OK pressed" );
  2960. pInfo = (CPWINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  2961. ASSERT( pInfo );
  2962. szNewPassword[ 0 ] = TEXT('\0');
  2963. GetWindowText(
  2964. pInfo->hwndEbNewPassword, szNewPassword, PWLEN + 1 );
  2965. szNewPassword2[ 0 ] = TEXT('\0');
  2966. GetWindowText(
  2967. pInfo->hwndEbNewPassword2, szNewPassword2, PWLEN + 1 );
  2968. if (lstrcmp( szNewPassword, szNewPassword2 ) != 0)
  2969. {
  2970. // The two passwords don't match, i.e. user made a typo. Make
  2971. // him re-enter.
  2972. //
  2973. MsgDlg( hwnd, SID_PasswordsDontMatch, NULL );
  2974. SetWindowText( pInfo->hwndEbNewPassword, TEXT("") );
  2975. SetWindowText( pInfo->hwndEbNewPassword2, TEXT("") );
  2976. SetFocus( pInfo->hwndEbNewPassword );
  2977. ZeroMemory( szNewPassword, sizeof(szNewPassword) );
  2978. ZeroMemory( szNewPassword2, sizeof(szNewPassword2) );
  2979. return TRUE;
  2980. }
  2981. if (pInfo->pArgs->fOldPassword)
  2982. {
  2983. pInfo->pArgs->pszOldPassword[ 0 ] = TEXT('\0');
  2984. // Whistler bug 254385 encode password when not being used
  2985. // Assumed password was not encoded by GetWindowText()
  2986. //
  2987. GetWindowText(
  2988. pInfo->hwndEbOldPassword,
  2989. pInfo->pArgs->pszOldPassword,
  2990. PWLEN + 1 );
  2991. EncodePassword( pInfo->pArgs->pszOldPassword );
  2992. }
  2993. // Whistler bug 224074 use only lstrcpyn's to prevent maliciousness
  2994. //
  2995. // pInfo->pArgs->pszNewPassword points back to RASDIALPARAMS->
  2996. // szPassword[ PWLEN + 1 ]
  2997. //
  2998. // Whistler bug 254385 encode password when not being used
  2999. // Assumed password was not encoded by GetWindowText()
  3000. //
  3001. lstrcpyn(
  3002. pInfo->pArgs->pszNewPassword,
  3003. szNewPassword,
  3004. PWLEN + 1 );
  3005. EncodePassword( pInfo->pArgs->pszNewPassword );
  3006. ZeroMemory( szNewPassword, sizeof(szNewPassword) );
  3007. ZeroMemory( szNewPassword2, sizeof(szNewPassword2) );
  3008. EndDialog( hwnd, TRUE );
  3009. return TRUE;
  3010. }
  3011. case IDCANCEL:
  3012. {
  3013. TRACE( "Cancel pressed" );
  3014. EndDialog( hwnd, FALSE );
  3015. return TRUE;
  3016. }
  3017. }
  3018. return FALSE;
  3019. }
  3020. BOOL
  3021. CpInit(
  3022. IN HWND hwndDlg,
  3023. IN CPARGS* pArgs )
  3024. // Called on WM_INITDIALOG. 'HwndDlg' is the handle of the dialog window.
  3025. // 'PArgs' is caller's arguments to the stub API.
  3026. //
  3027. // Return false if focus was set, true otherwise, i.e. as defined for
  3028. // WM_INITDIALOG.
  3029. //
  3030. {
  3031. DWORD dwErr;
  3032. CPWINFO* pInfo;
  3033. TRACE( "CpInit" );
  3034. // Allocate the dialog context block. Initialize minimally for proper
  3035. // cleanup, then attach to the dialog window.
  3036. //
  3037. {
  3038. pInfo = Malloc( sizeof(*pInfo) );
  3039. if (!pInfo)
  3040. {
  3041. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  3042. EndDialog( hwndDlg, FALSE );
  3043. return TRUE;
  3044. }
  3045. ZeroMemory( pInfo, sizeof(*pInfo) );
  3046. pInfo->pArgs = pArgs;
  3047. pInfo->hwndDlg = hwndDlg;
  3048. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  3049. TRACE( "Context set" );
  3050. }
  3051. if (pArgs->fOldPassword)
  3052. {
  3053. pInfo->hwndEbOldPassword =
  3054. GetDlgItem( hwndDlg, CID_CP_EB_OldPassword );
  3055. ASSERT( pInfo->hwndEbOldPassword );
  3056. Edit_LimitText( pInfo->hwndEbOldPassword, PWLEN );
  3057. }
  3058. pInfo->hwndEbNewPassword =
  3059. GetDlgItem( hwndDlg, CID_CP_EB_Password );
  3060. ASSERT( pInfo->hwndEbNewPassword );
  3061. Edit_LimitText( pInfo->hwndEbNewPassword, PWLEN );
  3062. pInfo->hwndEbNewPassword2 =
  3063. GetDlgItem( hwndDlg, CID_CP_EB_ConfirmPassword );
  3064. ASSERT( pInfo->hwndEbNewPassword2 );
  3065. Edit_LimitText( pInfo->hwndEbNewPassword2, PWLEN );
  3066. // Add context help button to title bar.
  3067. //
  3068. AddContextHelpButton( hwndDlg );
  3069. // Display finished window.
  3070. //
  3071. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  3072. SetForegroundWindow( hwndDlg );
  3073. return TRUE;
  3074. }
  3075. //----------------------------------------------------------------------------
  3076. // Connect Complete dialog
  3077. // Listed alphabetically following stub API and dialog proc
  3078. //----------------------------------------------------------------------------
  3079. VOID
  3080. ConnectCompleteDlg(
  3081. IN HWND hwndOwner,
  3082. IN DINFO* pInfo )
  3083. // Popup the connection complete dialog. 'HwndOwner' is the owning
  3084. // window. 'PUser' is the user preferences.
  3085. //
  3086. {
  3087. INT_PTR nStatus;
  3088. TRACE( "ConnectCompleteDlg" );
  3089. nStatus =
  3090. (BOOL )DialogBoxParam(
  3091. g_hinstDll,
  3092. MAKEINTRESOURCE( DID_CC_ConnectComplete ),
  3093. hwndOwner,
  3094. CcDlgProc,
  3095. (LPARAM )pInfo );
  3096. }
  3097. INT_PTR CALLBACK
  3098. CcDlgProc(
  3099. IN HWND hwnd,
  3100. IN UINT unMsg,
  3101. IN WPARAM wparam,
  3102. IN LPARAM lparam )
  3103. // DialogProc callback for the dialog. Parameters and return value are as
  3104. // described for standard windows 'DialogProc's.
  3105. //
  3106. {
  3107. #if 0
  3108. TRACE4( "CcDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  3109. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  3110. #endif
  3111. switch (unMsg)
  3112. {
  3113. case WM_INITDIALOG:
  3114. {
  3115. return CcInit( hwnd, (DINFO* )lparam );
  3116. }
  3117. case WM_COMMAND:
  3118. {
  3119. return CcCommand(
  3120. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  3121. }
  3122. case WM_DESTROY:
  3123. //For whistler bug 372078
  3124. //GetCurrentIconEntryType() loads Icon from netshell where the icon is loaded
  3125. //by LoadImage() without LR_SHARED, so I have to destroy it when we are done
  3126. //with it
  3127. //
  3128. {
  3129. HICON hIcon=NULL;
  3130. hIcon = (HICON)SendMessage( GetDlgItem( hwnd, CID_CC_I_Rasmon ),
  3131. STM_GETICON,
  3132. (WPARAM)0,
  3133. (LPARAM)0);
  3134. ASSERT(hIcon);
  3135. if( hIcon )
  3136. {
  3137. DestroyIcon(hIcon);
  3138. }
  3139. else
  3140. {
  3141. TRACE("CcDlgProc:Destroy Icon");
  3142. }
  3143. }
  3144. break;
  3145. }
  3146. return FALSE;
  3147. }
  3148. BOOL
  3149. CcCommand(
  3150. IN HWND hwnd,
  3151. IN WORD wNotification,
  3152. IN WORD wId,
  3153. IN HWND hwndCtrl )
  3154. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  3155. // the notification code of the command. 'wId' is the control/menu
  3156. // identifier of the command. 'HwndCtrl' is the control window handle of
  3157. // the command.
  3158. //
  3159. // Returns true if processed message, false otherwise.
  3160. //
  3161. {
  3162. TRACE3( "CcCommand(n=%d,i=%d,c=$%x)",
  3163. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  3164. switch (wId)
  3165. {
  3166. case IDOK:
  3167. {
  3168. DINFO * pInfo = (DINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  3169. PBUSER* pUser = pInfo->pUser;
  3170. ASSERT( pUser );
  3171. if (IsDlgButtonChecked( hwnd, CID_CC_CB_SkipMessage ))
  3172. {
  3173. pUser->fSkipConnectComplete = TRUE;
  3174. pUser->fDirty = TRUE;
  3175. }
  3176. }
  3177. // ...fall thru...
  3178. case IDCANCEL:
  3179. {
  3180. EndDialog( hwnd, TRUE );
  3181. return TRUE;
  3182. }
  3183. }
  3184. return FALSE;
  3185. }
  3186. BOOL
  3187. CcInit(
  3188. IN HWND hwndDlg,
  3189. IN DINFO* pInfo )
  3190. // Called on WM_INITDIALOG. 'HwndDlg' is the handle of dialog. 'PUser'
  3191. // is caller's argument to the stub API.
  3192. //
  3193. // Return false if focus was set, true otherwise, i.e. as defined for
  3194. // WM_INITDIALOG.
  3195. //
  3196. {
  3197. TRACE( "CcInit" );
  3198. // Set the dialog context.
  3199. //
  3200. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  3201. // Set the explanatory text.
  3202. //
  3203. {
  3204. MSGARGS msgargs;
  3205. ZeroMemory( &msgargs, sizeof(msgargs) );
  3206. msgargs.apszArgs[ 0 ] = pInfo->pEntry->pszEntryName;
  3207. msgargs.fStringOutput = TRUE;
  3208. MsgDlgUtil( NULL, SID_ConnectComplete, &msgargs, g_hinstDll, 0 );
  3209. if (msgargs.pszOutput)
  3210. {
  3211. SetDlgItemText( hwndDlg, CID_CC_ST_Text, msgargs.pszOutput );
  3212. Free( msgargs.pszOutput );
  3213. }
  3214. }
  3215. // Set the correct icon. For whistler bug 372078
  3216. //
  3217. SetIconFromEntryType(
  3218. GetDlgItem( hwndDlg, CID_CC_I_Rasmon ),
  3219. pInfo->pEntry->dwType,
  3220. FALSE); //FALSE means Large Icon
  3221. // Display finished window.
  3222. //
  3223. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  3224. SetForegroundWindow( hwndDlg );
  3225. return TRUE;
  3226. }
  3227. //----------------------------------------------------------------------------
  3228. // Dial Callback dialog
  3229. // Listed alphabetically following stub API and dialog proc
  3230. //----------------------------------------------------------------------------
  3231. BOOL
  3232. DialCallbackDlg(
  3233. IN HWND hwndOwner,
  3234. IN OUT TCHAR* pszNumber )
  3235. // Popup the Dial Callback dialog. 'HwndOwner' is the owning window.
  3236. // 'PszNumber' is caller's buffer for the number of the local machine that
  3237. // the server will be told to callback. It contains the default number on
  3238. // entry and the user-edited number on exit.
  3239. //
  3240. // Returns true if user OK and succeeds, false if Cancel or error.
  3241. //
  3242. {
  3243. INT_PTR nStatus;
  3244. TRACE( "DialCallbackDlg" );
  3245. nStatus =
  3246. (BOOL )DialogBoxParam(
  3247. g_hinstDll,
  3248. MAKEINTRESOURCE( DID_DC_DialCallback ),
  3249. hwndOwner,
  3250. DcDlgProc,
  3251. (LPARAM )pszNumber );
  3252. if (nStatus == -1)
  3253. {
  3254. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  3255. nStatus = FALSE;
  3256. }
  3257. return (BOOL )nStatus;
  3258. }
  3259. INT_PTR CALLBACK
  3260. DcDlgProc(
  3261. IN HWND hwnd,
  3262. IN UINT unMsg,
  3263. IN WPARAM wparam,
  3264. IN LPARAM lparam )
  3265. // DialogProc callback for the Dial Callback dialog. Parameters and
  3266. // return value are as described for standard windows 'DialogProc's.
  3267. //
  3268. {
  3269. #if 0
  3270. TRACE4( "DcDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  3271. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  3272. #endif
  3273. switch (unMsg)
  3274. {
  3275. case WM_INITDIALOG:
  3276. {
  3277. return DcInit( hwnd, (TCHAR* )lparam );
  3278. }
  3279. case WM_HELP:
  3280. case WM_CONTEXTMENU:
  3281. {
  3282. ContextHelp( g_adwDcHelp, hwnd, unMsg, wparam, lparam );
  3283. break;
  3284. }
  3285. case WM_COMMAND:
  3286. {
  3287. return DcCommand(
  3288. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  3289. }
  3290. }
  3291. return FALSE;
  3292. }
  3293. BOOL
  3294. DcCommand(
  3295. IN HWND hwnd,
  3296. IN WORD wNotification,
  3297. IN WORD wId,
  3298. IN HWND hwndCtrl )
  3299. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  3300. // the notification code of the command. 'wId' is the control/menu
  3301. // identifier of the command. 'HwndCtrl' is the control window handle of
  3302. // the command.
  3303. //
  3304. // Returns true if processed message, false otherwise.
  3305. //
  3306. {
  3307. DWORD dwErr;
  3308. TRACE3( "DcCommand(n=%d,i=%d,c=$%x)",
  3309. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  3310. switch (wId)
  3311. {
  3312. case IDOK:
  3313. {
  3314. BOOL fStatus;
  3315. HWND hwndEbNumber;
  3316. TCHAR* pszNumber;
  3317. TRACE( "OK pressed" );
  3318. hwndEbNumber = GetDlgItem( hwnd, CID_DC_EB_Number );
  3319. ASSERT( hwndEbNumber );
  3320. pszNumber = (TCHAR* )GetWindowLongPtr( hwnd, DWLP_USER );
  3321. ASSERT( pszNumber );
  3322. GetWindowText( hwndEbNumber, pszNumber, RAS_MaxCallbackNumber + 1 );
  3323. if (IsAllWhite( pszNumber ))
  3324. {
  3325. // OK with blank callback number is same as Cancel.
  3326. //
  3327. TRACE( "Blank number cancel" );
  3328. fStatus = FALSE;
  3329. }
  3330. else
  3331. {
  3332. fStatus = TRUE;
  3333. }
  3334. EndDialog( hwnd, fStatus );
  3335. return TRUE;
  3336. }
  3337. case IDCANCEL:
  3338. {
  3339. TRACE( "Cancel pressed" );
  3340. EndDialog( hwnd, FALSE );
  3341. return TRUE;
  3342. }
  3343. }
  3344. return FALSE;
  3345. }
  3346. BOOL
  3347. DcInit(
  3348. IN HWND hwndDlg,
  3349. IN TCHAR* pszNumber )
  3350. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  3351. // 'PszNumber' is the callback number.
  3352. //
  3353. // Return false if focus was set, true otherwise, i.e. as defined for
  3354. // WM_INITDIALOG.
  3355. //
  3356. {
  3357. DWORD dwErr;
  3358. HWND hwndEbNumber;
  3359. TRACE( "DcInit" );
  3360. // Stash address of caller's buffer for OK processing.
  3361. //
  3362. ASSERT( pszNumber );
  3363. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pszNumber );
  3364. // Initialize edit field to caller's default.
  3365. //
  3366. hwndEbNumber = GetDlgItem( hwndDlg, CID_DC_EB_Number );
  3367. ASSERT( hwndEbNumber );
  3368. Edit_LimitText( hwndEbNumber, RAS_MaxCallbackNumber );
  3369. SetWindowText( hwndEbNumber, pszNumber );
  3370. // Add context help button to title bar.
  3371. //
  3372. AddContextHelpButton( hwndDlg );
  3373. // Display finished window.
  3374. //
  3375. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  3376. SetForegroundWindow( hwndDlg );
  3377. return TRUE;
  3378. }
  3379. //----------------------------------------------------------------------------
  3380. // Dial Error dialog
  3381. // Listed alphabetically following stub API and dialog proc
  3382. //----------------------------------------------------------------------------
  3383. BOOL
  3384. DialErrorDlg(
  3385. IN HWND hwndOwner,
  3386. IN TCHAR* pszEntry,
  3387. IN DWORD dwError,
  3388. IN DWORD sidState,
  3389. IN TCHAR* pszStatusArg,
  3390. IN DWORD sidFormatMsg,
  3391. IN TCHAR* pszFormatArg,
  3392. IN LONG lRedialCountdown,
  3393. IN BOOL fPopupOnTop )
  3394. // Popup the Dial Error dialog. 'HwndOwner' is the owning window.
  3395. // 'PszEntry' is the entry being dialed. 'DwError' is the error that
  3396. // occurred or 0 if redialing after a link failure. 'sidStatusArg' is the
  3397. // argument to the 'sidState' 'SidState' is the string ID of the dial
  3398. // state executing when the error occurred. string or NULL if none.
  3399. // 'SidFormatMsg' is the string containing the format of the error message
  3400. // or 0 to use the default. 'PszFormatArg' is the additional argument to
  3401. // the format message or NULL if none. 'LRedialCountdown' is the number
  3402. // of seconds before auto-redial, or -1 to disable countdown, or -2 to
  3403. // hide the "Redial" button entirely. 'FPopupOnTop' indicates the status
  3404. // window should be brought to the front when redialing.
  3405. //
  3406. // Returns true if user chooses to redial or lets it timeout, false if
  3407. // cancels.
  3408. //
  3409. {
  3410. INT_PTR nStatus;
  3411. DEARGS args;
  3412. TRACE( "DialErrorDlg" );
  3413. args.pszEntry = pszEntry;
  3414. args.dwError = dwError;
  3415. args.sidState = sidState;
  3416. args.pszStatusArg = pszStatusArg;
  3417. args.sidFormatMsg = sidFormatMsg;
  3418. args.pszFormatArg = pszFormatArg;
  3419. args.lRedialCountdown = lRedialCountdown;
  3420. args.fPopupOnTop = fPopupOnTop;
  3421. nStatus =
  3422. (BOOL )DialogBoxParam(
  3423. g_hinstDll,
  3424. MAKEINTRESOURCE( DID_DE_DialError ),
  3425. hwndOwner,
  3426. DeDlgProc,
  3427. (LPARAM )&args );
  3428. if (nStatus == -1)
  3429. {
  3430. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  3431. nStatus = FALSE;
  3432. }
  3433. return (BOOL )nStatus;
  3434. }
  3435. INT_PTR CALLBACK
  3436. DeDlgProc(
  3437. IN HWND hwnd,
  3438. IN UINT unMsg,
  3439. IN WPARAM wparam,
  3440. IN LPARAM lparam )
  3441. // DialogProc callback for the Dial Error dialog. Parameters and return
  3442. // value are as described for standard windows 'DialogProc's.
  3443. //
  3444. {
  3445. #if 0
  3446. TRACE4( "DeDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  3447. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  3448. #endif
  3449. switch (unMsg)
  3450. {
  3451. case WM_INITDIALOG:
  3452. {
  3453. return DeInit( hwnd, (DEARGS* )lparam );
  3454. }
  3455. case WM_HELP:
  3456. case WM_CONTEXTMENU:
  3457. {
  3458. ContextHelp( g_adwDeHelp, hwnd, unMsg, wparam, lparam );
  3459. break;
  3460. }
  3461. case WM_COMMAND:
  3462. {
  3463. return DeCommand(
  3464. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  3465. }
  3466. case WM_TIMER:
  3467. {
  3468. DEINFO* pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  3469. ASSERT( pInfo );
  3470. KillTimer( pInfo->hwndDlg, 1 );
  3471. if (pInfo->lRedialCountdown > 0)
  3472. {
  3473. --pInfo->lRedialCountdown;
  3474. }
  3475. DeAdjustPbRedial( pInfo );
  3476. if (pInfo->lRedialCountdown == 0)
  3477. {
  3478. // Fake a press of the Redial button. Note that BM_CLICK
  3479. // cannot be used because it doesn't generate the WM_COMMAND
  3480. // when the thread is not the foreground window, due to
  3481. // SetCapture use and restriction.
  3482. //
  3483. SendMessage( pInfo->hwndDlg, WM_COMMAND,
  3484. MAKEWPARAM( IDOK, BN_CLICKED ),
  3485. (LPARAM )pInfo->hwndPbRedial );
  3486. }
  3487. else
  3488. {
  3489. SetTimer( pInfo->hwndDlg, 1, 1000L, NULL );
  3490. }
  3491. return TRUE;
  3492. }
  3493. case WM_DESTROY:
  3494. {
  3495. DeTerm( hwnd );
  3496. break;
  3497. }
  3498. }
  3499. return FALSE;
  3500. }
  3501. VOID
  3502. DeAdjustPbRedial(
  3503. IN DEINFO* pInfo )
  3504. // Set the label of the Redial button or disable it as indicated by the
  3505. // redial countdown. If enabled, the button shows the number of seconds
  3506. // to auto-redial unless this is not the final redial. 'PInfo' is the
  3507. // dialog context block.
  3508. //
  3509. {
  3510. TCHAR* psz;
  3511. if (pInfo->lRedialCountdown == -2)
  3512. {
  3513. // Redial button is to be hidden. See bug 230594.
  3514. //
  3515. SetFocus( pInfo->hwndPbCancel );
  3516. ShowWindow( pInfo->hwndPbRedial, SW_HIDE );
  3517. EnableWindow( pInfo->hwndPbRedial, FALSE );
  3518. }
  3519. else
  3520. {
  3521. // Go ahead and change the label "Redial" or "Redial=%d" as
  3522. // appropriate.
  3523. //
  3524. psz = PszFromId( g_hinstDll, SID_RedialLabel );
  3525. if (psz)
  3526. {
  3527. TCHAR szBuf[ 128 ];
  3528. lstrcpyn(
  3529. szBuf,
  3530. psz,
  3531. (sizeof(szBuf) / sizeof(TCHAR)) - 4);
  3532. Free( psz );
  3533. if (pInfo->lRedialCountdown >= 0)
  3534. {
  3535. TCHAR szNum[ MAXLTOTLEN + 1 ];
  3536. DWORD dwLen, dwSize = sizeof(szBuf)/sizeof(TCHAR);
  3537. LToT( pInfo->lRedialCountdown, szNum, 10 );
  3538. lstrcat( szBuf, TEXT(" = ") );
  3539. dwLen = lstrlen(szBuf) + 1;
  3540. lstrcpyn( szBuf + (dwLen - 1), szNum, dwSize - dwLen );
  3541. }
  3542. SetWindowText( pInfo->hwndPbRedial, szBuf );
  3543. }
  3544. }
  3545. }
  3546. BOOL
  3547. DeCommand(
  3548. IN HWND hwnd,
  3549. IN WORD wNotification,
  3550. IN WORD wId,
  3551. IN HWND hwndCtrl )
  3552. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  3553. // the notification code of the command. 'wId' is the control/menu
  3554. // identifier of the command. 'HwndCtrl' is the control window handle of
  3555. // the command.
  3556. //
  3557. // Returns true if processed message, false otherwise.
  3558. //
  3559. {
  3560. DWORD dwErr;
  3561. TRACE3( "DeCommand(n=%d,i=%d,c=$%x)",
  3562. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  3563. TRACE2("Current proces:(0x%d), Current Thread:(0x%d)",
  3564. GetCurrentProcessId(),
  3565. GetCurrentThreadId());
  3566. switch (wId)
  3567. {
  3568. case IDOK:
  3569. {
  3570. TRACE( "Redial pressed" );
  3571. EndDialog( hwnd, TRUE );
  3572. return TRUE;
  3573. }
  3574. case IDCANCEL:
  3575. {
  3576. TRACE( "Cancel pressed" );
  3577. EndDialog( hwnd, FALSE );
  3578. return TRUE;
  3579. }
  3580. case CID_DE_PB_More:
  3581. {
  3582. DEINFO* pInfo;
  3583. DWORD dwContext;
  3584. pInfo = (DEINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  3585. ASSERT( pInfo );
  3586. if (pInfo->pArgs->dwError >= RASBASE
  3587. && pInfo->pArgs->dwError <= RASBASEEND)
  3588. {
  3589. dwContext = HID_RASERRORBASE - RASBASE + pInfo->pArgs->dwError;
  3590. }
  3591. else if (pInfo->pArgs->dwError == 0)
  3592. {
  3593. dwContext = HID_RECONNECTING;
  3594. }
  3595. else
  3596. {
  3597. dwContext = HID_NONRASERROR;
  3598. }
  3599. WinHelp( hwnd, g_pszHelpFile, HELP_CONTEXTPOPUP, dwContext );
  3600. }
  3601. }
  3602. return FALSE;
  3603. }
  3604. BOOL
  3605. DeInit(
  3606. IN HWND hwndDlg,
  3607. IN DEARGS* pArgs )
  3608. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  3609. // 'PArgs' is caller's arguments to the stub API.
  3610. //
  3611. // Return false if focus was set, true otherwise, i.e. as defined for
  3612. // WM_INITDIALOG.
  3613. //
  3614. {
  3615. DWORD dwErr;
  3616. DEINFO* pInfo;
  3617. TRACE( "DeInit" );
  3618. // Allocate the dialog context block. Initialize minimally for proper
  3619. // cleanup, then attach to the dialog window.
  3620. //
  3621. {
  3622. pInfo = Malloc( sizeof(*pInfo) );
  3623. if (!pInfo)
  3624. {
  3625. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  3626. EndDialog( hwndDlg, FALSE );
  3627. return TRUE;
  3628. }
  3629. ZeroMemory( pInfo, sizeof(*pInfo) );
  3630. pInfo->pArgs = pArgs;
  3631. pInfo->hwndDlg = hwndDlg;
  3632. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  3633. TRACE( "Context set" );
  3634. }
  3635. pInfo->hwndStText = GetDlgItem( hwndDlg, CID_DE_ST_Text );
  3636. ASSERT( pInfo->hwndStText );
  3637. pInfo->hwndPbRedial = GetDlgItem( hwndDlg, IDOK );
  3638. ASSERT( pInfo->hwndPbRedial );
  3639. pInfo->hwndPbCancel = GetDlgItem( hwndDlg, IDCANCEL );
  3640. ASSERT( pInfo->hwndPbCancel );
  3641. pInfo->hwndPbMore = GetDlgItem( hwndDlg, CID_DE_PB_More );
  3642. ASSERT( pInfo->hwndPbMore );
  3643. // Hide/disable "more info" button if WinHelp won't work. See
  3644. // common\uiutil\ui.c.
  3645. //
  3646. {
  3647. extern BOOL g_fNoWinHelp;
  3648. if (g_fNoWinHelp)
  3649. {
  3650. ShowWindow( pInfo->hwndPbMore, SW_HIDE );
  3651. EnableWindow( pInfo->hwndPbMore, FALSE );
  3652. }
  3653. }
  3654. if (pArgs->dwError == 0)
  3655. {
  3656. TCHAR* pszFormat;
  3657. TCHAR* psz;
  3658. TCHAR* apszArgs[ 1 ];
  3659. // Redialing on link failure. Set title to "Dial-Up Networking".
  3660. //
  3661. psz = PszFromId( g_hinstDll, SID_PopupTitle );
  3662. if (psz)
  3663. {
  3664. SetWindowText( hwndDlg, psz );
  3665. Free( psz );
  3666. }
  3667. // Set static placeholder text control to "Link to <entry> failed.
  3668. // Reconnect pending...".
  3669. //
  3670. pszFormat = PszFromId( g_hinstDll, SID_DE_LinkFailed );
  3671. if (pszFormat)
  3672. {
  3673. apszArgs[ 0 ] = pArgs->pszEntry;
  3674. psz = NULL;
  3675. FormatMessage(
  3676. FORMAT_MESSAGE_FROM_STRING
  3677. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  3678. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3679. pszFormat, 0, 0, (LPTSTR )&psz, 1,
  3680. (va_list* )apszArgs );
  3681. Free( pszFormat );
  3682. if (psz)
  3683. {
  3684. SetWindowText( pInfo->hwndStText, psz );
  3685. LocalFree( psz );
  3686. }
  3687. }
  3688. }
  3689. else
  3690. {
  3691. TCHAR* pszTitleFormat;
  3692. TCHAR* pszTitle;
  3693. TCHAR* apszArgs[ 1 ];
  3694. ERRORARGS args;
  3695. // Set title to "Error Connecting to <entry>".
  3696. //
  3697. pszTitleFormat = GetText( hwndDlg );
  3698. if (pszTitleFormat)
  3699. {
  3700. apszArgs[ 0 ] = pArgs->pszEntry;
  3701. pszTitle = NULL;
  3702. FormatMessage(
  3703. FORMAT_MESSAGE_FROM_STRING
  3704. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  3705. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  3706. pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1,
  3707. (va_list* )apszArgs );
  3708. Free( pszTitleFormat );
  3709. if (pszTitle)
  3710. {
  3711. SetWindowText( hwndDlg, pszTitle );
  3712. LocalFree( pszTitle );
  3713. }
  3714. }
  3715. // Build the error text and load it into the placeholder text control.
  3716. //
  3717. ZeroMemory( &args, sizeof(args) );
  3718. if (pArgs->pszStatusArg)
  3719. args.apszOpArgs[ 0 ] = pArgs->pszStatusArg;
  3720. if (pArgs->pszFormatArg)
  3721. args.apszAuxFmtArgs[ 0 ] = pArgs->pszFormatArg;
  3722. args.fStringOutput = TRUE;
  3723. ErrorDlgUtil( hwndDlg,
  3724. pArgs->sidState, pArgs->dwError, &args, g_hinstDll, 0,
  3725. (pArgs->sidFormatMsg) ? pArgs->sidFormatMsg : SID_FMT_ErrorMsg );
  3726. if (args.pszOutput)
  3727. {
  3728. SetWindowText( pInfo->hwndStText, args.pszOutput );
  3729. LocalFree( args.pszOutput );
  3730. }
  3731. }
  3732. // Stretch the dialog window to a vertical size appropriate for the text
  3733. // we loaded.
  3734. //
  3735. {
  3736. HDC hdc;
  3737. RECT rect;
  3738. RECT rectNew;
  3739. HFONT hfont;
  3740. LONG dyGrow;
  3741. TCHAR* psz;
  3742. psz = GetText( pInfo->hwndStText );
  3743. if (psz)
  3744. {
  3745. GetClientRect( pInfo->hwndStText, &rect );
  3746. hdc = GetDC( pInfo->hwndStText );
  3747. if(NULL != hdc)
  3748. {
  3749. hfont = (HFONT )SendMessage( pInfo->hwndStText,
  3750. WM_GETFONT, 0, 0 );
  3751. if (hfont)
  3752. {
  3753. SelectObject( hdc, hfont );
  3754. }
  3755. rectNew = rect;
  3756. DrawText( hdc, psz, -1, &rectNew,
  3757. DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS | DT_NOPREFIX );
  3758. ReleaseDC( pInfo->hwndStText, hdc );
  3759. }
  3760. dyGrow = rectNew.bottom - rect.bottom;
  3761. ExpandWindow( pInfo->hwndDlg, 0, dyGrow );
  3762. ExpandWindow( pInfo->hwndStText, 0, dyGrow );
  3763. SlideWindow( pInfo->hwndPbRedial, pInfo->hwndDlg, 0, dyGrow );
  3764. SlideWindow( pInfo->hwndPbCancel, pInfo->hwndDlg, 0, dyGrow );
  3765. SlideWindow( pInfo->hwndPbMore, pInfo->hwndDlg, 0, dyGrow );
  3766. Free( psz );
  3767. }
  3768. }
  3769. // Set Redial button label or disable the button. Always choose to redial
  3770. // after 5 seconds for the biplex error, since this will normally solve
  3771. // the problem. Otherwise, no countdown is used.
  3772. //
  3773. if (pArgs->dwError == ERROR_BIPLEX_PORT_NOT_AVAILABLE)
  3774. {
  3775. pInfo->lRedialCountdown = 5;
  3776. }
  3777. else
  3778. {
  3779. pInfo->lRedialCountdown = pArgs->lRedialCountdown;
  3780. }
  3781. DeAdjustPbRedial( pInfo );
  3782. if (pInfo->lRedialCountdown >= 0)
  3783. {
  3784. SetTimer( pInfo->hwndDlg, 1, 1000L, NULL );
  3785. }
  3786. // Add context help button to title bar.
  3787. //
  3788. AddContextHelpButton( hwndDlg );
  3789. if (pArgs->fPopupOnTop)
  3790. {
  3791. // Display the finished window above all other windows. The window
  3792. // position is set to "topmost" then immediately set to "not topmost"
  3793. // because we want it on top but not always-on-top. Always-on-top
  3794. // alone is too annoying.
  3795. //
  3796. SetWindowPos(
  3797. hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
  3798. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  3799. }
  3800. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  3801. ShowWindow( hwndDlg, SW_SHOW );
  3802. if (pArgs->fPopupOnTop)
  3803. {
  3804. SetForegroundWindow( hwndDlg );
  3805. SetWindowPos(
  3806. hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
  3807. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  3808. }
  3809. return TRUE;
  3810. }
  3811. // Helper function to delete credentials
  3812. //
  3813. // fDeleteDefault specifies whether it is the default credentials that
  3814. // should be deleted.
  3815. //
  3816. // fDeleteIdentity specifies whether to delete the user and domain names
  3817. // in addition to the password.
  3818. //
  3819. DWORD
  3820. DeleteSavedCredentials(
  3821. IN DINFO* pDinfo,
  3822. IN HWND hwndDlg,
  3823. IN BOOL fDefault,
  3824. IN BOOL fDeleteIdentity )
  3825. {
  3826. RASCREDENTIALS rc;
  3827. DWORD dwErr = NO_ERROR;
  3828. TRACE2( "DeleteSavedCredentials: %d %d", fDefault, fDeleteIdentity );
  3829. ZeroMemory(&rc, sizeof(rc));
  3830. rc.dwSize = sizeof(RASCREDENTIALS);
  3831. rc.dwMask = RASCM_Password;
  3832. if (fDeleteIdentity)
  3833. {
  3834. rc.dwMask |= (RASCM_UserName | RASCM_Domain);
  3835. }
  3836. if ( (fDefault)
  3837. && (IsPublicPhonebook(pDinfo->pFile->pszPath)))
  3838. {
  3839. rc.dwMask |= RASCM_DefaultCreds;
  3840. }
  3841. dwErr = g_pRasSetCredentials(
  3842. pDinfo->pFile->pszPath,
  3843. pDinfo->pEntry->pszEntryName,
  3844. &rc,
  3845. TRUE );
  3846. if (dwErr != 0)
  3847. {
  3848. ErrorDlg( hwndDlg, SID_OP_UncachePw, dwErr, NULL );
  3849. }
  3850. TRACE1( "DeleteSavedCredentials: RasSetCredentials=%d", dwErr );
  3851. return dwErr;
  3852. }
  3853. VOID
  3854. DeTerm(
  3855. IN HWND hwndDlg )
  3856. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  3857. //
  3858. {
  3859. DEINFO* pInfo = (DEINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  3860. TRACE( "DeTerm" );
  3861. if (pInfo)
  3862. {
  3863. Free( pInfo );
  3864. }
  3865. }
  3866. //----------------------------------------------------------------------------
  3867. // Dial Progress dialog
  3868. // Listed alphabetically following stub API dialog proc
  3869. //----------------------------------------------------------------------------
  3870. BOOL
  3871. DialProgressDlg(
  3872. IN DINFO* pInfo )
  3873. // Popup the Dial Progress dialog. 'PInfo' is the dialog context.
  3874. //
  3875. // Returns true if user connected successfully, false is he cancelled or
  3876. // hit an error.
  3877. //
  3878. {
  3879. INT_PTR nStatus;
  3880. // Run the dialog.
  3881. //
  3882. nStatus =
  3883. DialogBoxParam(
  3884. g_hinstDll,
  3885. MAKEINTRESOURCE( DID_DP_DialProgress ),
  3886. pInfo->pArgs->hwndOwner,
  3887. DpDlgProc,
  3888. (LPARAM )pInfo );
  3889. if (nStatus == -1)
  3890. {
  3891. ErrorDlg( pInfo->pArgs->hwndOwner, SID_OP_LoadDlg,
  3892. ERROR_UNKNOWN, NULL );
  3893. pInfo->pArgs->dwError = ERROR_UNKNOWN;
  3894. nStatus = FALSE;
  3895. }
  3896. if (nStatus)
  3897. {
  3898. DWORD dwErr;
  3899. PBFILE file;
  3900. // Connected successfully, so read possible changes to the entry made
  3901. // by RasDial.
  3902. //
  3903. dwErr = ReadPhonebookFile( pInfo->pFile->pszPath, pInfo->pUser,
  3904. pInfo->pEntry->pszEntryName, RPBF_ReadOnly, &file );
  3905. if (dwErr == 0)
  3906. {
  3907. DTLNODE* pNodeNew;
  3908. pNodeNew = DtlGetFirstNode( file.pdtllistEntries );
  3909. if (pNodeNew)
  3910. {
  3911. DtlRemoveNode( pInfo->pFile->pdtllistEntries, pInfo->pNode );
  3912. DestroyEntryNode( pInfo->pNode );
  3913. DtlRemoveNode( file.pdtllistEntries, pNodeNew );
  3914. DtlAddNodeLast( pInfo->pFile->pdtllistEntries, pNodeNew );
  3915. pInfo->pNode = pNodeNew;
  3916. pInfo->pEntry = (PBENTRY* )DtlGetData( pNodeNew );
  3917. }
  3918. ClosePhonebookFile( &file );
  3919. }
  3920. }
  3921. // See if we need to change the entry based on what happened while
  3922. // dialing.
  3923. //
  3924. {
  3925. BOOL fChange = FALSE;
  3926. if (pInfo->fResetAutoLogon)
  3927. {
  3928. ASSERT( !pInfo->pNoUser );
  3929. pInfo->pEntry->fAutoLogon = FALSE;
  3930. fChange = TRUE;
  3931. }
  3932. if (pInfo->dwfExcludedProtocols)
  3933. {
  3934. pInfo->pEntry->dwfExcludedProtocols
  3935. |= pInfo->dwfExcludedProtocols;
  3936. fChange = TRUE;
  3937. }
  3938. if (pInfo->pListPortsToDelete)
  3939. {
  3940. DTLNODE* pNode;
  3941. pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  3942. while (pNode)
  3943. {
  3944. DTLNODE* pNodeNext;
  3945. DTLNODE* pNodePtd;
  3946. PBLINK* pLink;
  3947. TCHAR* pszPort;
  3948. pNodeNext = DtlGetNextNode( pNode );
  3949. pLink = (PBLINK* )DtlGetData( pNode );
  3950. pszPort = pLink->pbport.pszPort;
  3951. for (pNodePtd = DtlGetFirstNode( pInfo->pListPortsToDelete );
  3952. pNodePtd;
  3953. pNodePtd = DtlGetNextNode( pNodePtd ))
  3954. {
  3955. TCHAR* pszPtd = (TCHAR* )DtlGetData( pNodePtd );
  3956. if (lstrcmp( pszPtd, pszPort ) == 0)
  3957. {
  3958. pNode = DtlRemoveNode(
  3959. pInfo->pEntry->pdtllistLinks, pNode );
  3960. DestroyLinkNode( pNode );
  3961. fChange = TRUE;
  3962. break;
  3963. }
  3964. }
  3965. pNode = pNodeNext;
  3966. }
  3967. }
  3968. if (fChange)
  3969. {
  3970. pInfo->pEntry->fDirty = TRUE;
  3971. WritePhonebookFile( pInfo->pFile, NULL );
  3972. }
  3973. }
  3974. return (BOOL )nStatus;
  3975. }
  3976. INT_PTR CALLBACK
  3977. DpDlgProc(
  3978. IN HWND hwnd,
  3979. IN UINT unMsg,
  3980. IN WPARAM wparam,
  3981. IN LPARAM lparam )
  3982. // DialogProc callback for the User Authentication dialog. Parameters and
  3983. // return value are as described for standard windows 'DialogProc's.
  3984. //
  3985. {
  3986. #if 0
  3987. TRACE4( "DpDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  3988. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  3989. #endif
  3990. switch (unMsg)
  3991. {
  3992. case WM_INITDIALOG:
  3993. {
  3994. return DpInit( hwnd, (DINFO* )lparam );
  3995. }
  3996. case WM_COMMAND:
  3997. {
  3998. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  3999. ASSERT( pInfo );
  4000. return DpCommand(
  4001. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  4002. }
  4003. case WM_RASDIAL:
  4004. {
  4005. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  4006. ASSERT( pInfo );
  4007. Sleep( 0 );
  4008. DpDial( pInfo, (BOOL)wparam );
  4009. return TRUE;
  4010. }
  4011. case WM_RASERROR:
  4012. {
  4013. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  4014. ASSERT( pInfo );
  4015. Sleep( 0 );
  4016. //For whistler bug 381337
  4017. //
  4018. if ( !pInfo->fCancelPressed )
  4019. {
  4020. DpError( pInfo, (DPSTATE* )lparam );
  4021. }
  4022. else
  4023. {
  4024. TRACE("DpDlgProc is already canceled, wont respond to WM_RASERROR");
  4025. }
  4026. return TRUE;
  4027. }
  4028. case WM_RASBUNDLEERROR:
  4029. {
  4030. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  4031. ASSERT( pInfo );
  4032. Sleep( 0 );
  4033. if (BundlingErrorsDlg( pInfo ))
  4034. {
  4035. EndDialog( pInfo->hwndDlg, TRUE );
  4036. }
  4037. else
  4038. {
  4039. DpCancel( pInfo );
  4040. }
  4041. return TRUE;
  4042. }
  4043. case WM_DESTROY:
  4044. {
  4045. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  4046. ASSERT( pInfo );
  4047. // Whistler Bugs: 344019 SECBUGBASH: leaving leaked password in
  4048. // memory when user changes password over RAS
  4049. //
  4050. // 289587 Failed RAS connections reset password to blank
  4051. //
  4052. if (pInfo->pszGoodPassword)
  4053. {
  4054. ZeroMemory(
  4055. pInfo->pszGoodPassword,
  4056. (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) );
  4057. Free( pInfo->pszGoodPassword );
  4058. pInfo->pszGoodPassword = NULL;
  4059. }
  4060. if (pInfo->pszGoodUserName)
  4061. {
  4062. Free( pInfo->pszGoodUserName );
  4063. pInfo->pszGoodUserName = NULL;
  4064. }
  4065. if (DpCallbacksFlag( pInfo, -1 ))
  4066. {
  4067. // Callbacks are active. Stall until they complete.
  4068. //
  4069. TRACE( "Stall until callbacks disabled" );
  4070. PostMessage( hwnd, WM_DESTROY, wparam, lparam );
  4071. return TRUE;
  4072. }
  4073. DpTerm( hwnd );
  4074. break;
  4075. }
  4076. }
  4077. return FALSE;
  4078. }
  4079. VOID
  4080. DpAppendBlankLine(
  4081. IN OUT TCHAR* pszLines )
  4082. // Append a blank line on the end of 'pszLines'.
  4083. //
  4084. {
  4085. lstrcat( pszLines, TEXT("\n") );
  4086. }
  4087. VOID
  4088. DpAppendConnectErrorLine(
  4089. IN OUT TCHAR* pszLines,
  4090. IN DWORD sidProtocol,
  4091. IN DWORD dwError )
  4092. // Append a connect error line for protocol 'sidProtocol' and error
  4093. // 'dwError' onto the end of 'pszLines'.
  4094. //
  4095. {
  4096. #define MAXRASERRORLEN 256
  4097. TCHAR* pszProtocol;
  4098. TCHAR* pszErrStr;
  4099. TCHAR szErrNumBuf[ MAXLTOTLEN + 1 ];
  4100. // Gather the argument strings.
  4101. //
  4102. pszProtocol = PszFromId( g_hinstDll, sidProtocol );
  4103. if (!pszProtocol)
  4104. {
  4105. return;
  4106. }
  4107. LToT( dwError, szErrNumBuf, 10 );
  4108. pszErrStr = NULL;
  4109. GetErrorText( dwError, &pszErrStr );
  4110. // Format the line and append it to caller's line buffer.
  4111. //
  4112. {
  4113. TCHAR* pszLineFormat;
  4114. TCHAR* pszLine;
  4115. TCHAR* apszArgs[ 3 ];
  4116. pszLineFormat = PszFromId( g_hinstDll, SID_FMT_ProjectError );
  4117. if (pszLineFormat)
  4118. {
  4119. apszArgs[ 0 ] = pszProtocol;
  4120. apszArgs[ 1 ] = szErrNumBuf;
  4121. apszArgs[ 2 ] = (pszErrStr) ? pszErrStr : TEXT("");
  4122. pszLine = NULL;
  4123. FormatMessage(
  4124. FORMAT_MESSAGE_FROM_STRING
  4125. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  4126. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4127. pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1,
  4128. (va_list* )apszArgs );
  4129. Free( pszLineFormat );
  4130. if (pszLine)
  4131. {
  4132. lstrcat( pszLines, pszLine );
  4133. LocalFree( pszLine );
  4134. }
  4135. }
  4136. }
  4137. Free( pszProtocol );
  4138. Free0( pszErrStr );
  4139. }
  4140. VOID
  4141. DpAppendConnectOkLine(
  4142. IN OUT TCHAR* pszLines,
  4143. IN DWORD sidProtocol )
  4144. // Append a "connected successfully" line for protocol 'sidProtocol' onto
  4145. // the end of 'pszLines'.
  4146. //
  4147. {
  4148. TCHAR* pszProtocol;
  4149. // Get the argument string.
  4150. //
  4151. pszProtocol = PszFromId( g_hinstDll, sidProtocol );
  4152. if (!pszProtocol)
  4153. {
  4154. return;
  4155. }
  4156. // Format the line and append it to caller's line buffer.
  4157. //
  4158. {
  4159. TCHAR* pszLineFormat;
  4160. TCHAR* pszLine;
  4161. TCHAR* apszArgs[ 1 ];
  4162. pszLineFormat = PszFromId( g_hinstDll, SID_FMT_ProjectOk );
  4163. if (pszLineFormat)
  4164. {
  4165. apszArgs[ 0 ] = pszProtocol;
  4166. pszLine = NULL;
  4167. FormatMessage(
  4168. FORMAT_MESSAGE_FROM_STRING
  4169. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  4170. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4171. pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1,
  4172. (va_list* )apszArgs );
  4173. Free( pszLineFormat );
  4174. if (pszLine)
  4175. {
  4176. lstrcat( pszLines, pszLine );
  4177. LocalFree( pszLine );
  4178. }
  4179. }
  4180. }
  4181. Free( pszProtocol );
  4182. }
  4183. VOID
  4184. DpAppendFailCodeLine(
  4185. IN OUT TCHAR* pszLines,
  4186. IN DWORD dw )
  4187. // Append hexidecimal fail code 'dw' as an extended error line on the end
  4188. // of 'pszLines'.
  4189. //
  4190. {
  4191. TCHAR szNumBuf[ MAXLTOTLEN + 1 ];
  4192. // Get the argument string.
  4193. //
  4194. LToT( dw, szNumBuf, 16 );
  4195. // Format the line and append it to caller's line buffer.
  4196. //
  4197. {
  4198. TCHAR* pszLineFormat;
  4199. TCHAR* pszLine;
  4200. TCHAR* apszArgs[ 1 ];
  4201. pszLineFormat = PszFromId( g_hinstDll, SID_FMT_FailCode );
  4202. if (pszLineFormat)
  4203. {
  4204. apszArgs[ 0 ] = szNumBuf;
  4205. pszLine = NULL;
  4206. FormatMessage(
  4207. FORMAT_MESSAGE_FROM_STRING
  4208. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  4209. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4210. pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1,
  4211. (va_list* )apszArgs );
  4212. Free( pszLineFormat );
  4213. if (pszLine)
  4214. {
  4215. lstrcat( pszLines, pszLine );
  4216. LocalFree( pszLine );
  4217. }
  4218. }
  4219. }
  4220. }
  4221. VOID
  4222. DpAppendNameLine(
  4223. IN OUT TCHAR* pszLines,
  4224. IN TCHAR* psz )
  4225. // Append NetBIOS name 'psz' as an extended error line on the end of
  4226. // 'pszLines'.
  4227. //
  4228. {
  4229. TCHAR* pszLineFormat;
  4230. TCHAR* pszLine;
  4231. TCHAR* apszArgs[ 1 ];
  4232. pszLineFormat = PszFromId( g_hinstDll, SID_FMT_Name );
  4233. if (pszLineFormat)
  4234. {
  4235. apszArgs[ 0 ] = psz;
  4236. pszLine = NULL;
  4237. FormatMessage(
  4238. FORMAT_MESSAGE_FROM_STRING
  4239. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  4240. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  4241. pszLineFormat, 0, 0, (LPTSTR )&pszLine, 1,
  4242. (va_list* )apszArgs );
  4243. Free( pszLineFormat );
  4244. if (pszLine)
  4245. {
  4246. lstrcat( pszLines, pszLine );
  4247. LocalFree( pszLine );
  4248. }
  4249. }
  4250. }
  4251. VOID
  4252. DpAuthNotify(
  4253. IN DPINFO* pInfo,
  4254. IN DPSTATE* pState )
  4255. // Called on an authentication notify, i.e. a message from RASCAUTH.DLL or
  4256. // RASPPPEN.DLL. 'PInfo' is the dialog context. 'PState' is the current
  4257. // link's context.
  4258. //
  4259. {
  4260. PBENTRY* pEntry;
  4261. TRACE( "DpAuthNotify" );
  4262. pEntry = pInfo->pArgs->pEntry;
  4263. if (pState->dwError == ERROR_ACCESS_DENIED && pEntry->fAutoLogon)
  4264. {
  4265. // A third party box has negotiated an authentication protocol that
  4266. // can't deal with the NT one-way-hashed password, i.e. something
  4267. // besides MS-extended CHAP or AMB. Map the error to a more
  4268. // informative error message.
  4269. //
  4270. pState->dwError = ERROR_CANNOT_USE_LOGON_CREDENTIALS;
  4271. if (!pInfo->pArgs->pNoUser)
  4272. {
  4273. TRACE( "Disable auto-logon" );
  4274. pEntry->fAutoLogon = FALSE;
  4275. pInfo->pArgs->fResetAutoLogon = TRUE;
  4276. }
  4277. }
  4278. if (pState->dwError == ERROR_CHANGING_PASSWORD)
  4279. {
  4280. TRACE( "DpAuthNotify - ERROR_CHANGING_PASSWORD" );
  4281. // Change password failed. Restore the password that worked for the
  4282. // "button" redial.
  4283. //
  4284. if (pInfo->pszGoodPassword)
  4285. {
  4286. // Whistler bug 254385 encode password when not being used
  4287. // Assumed password was encoded by DpPasswordExpired()
  4288. //
  4289. DecodePassword( pInfo->pszGoodPassword );
  4290. lstrcpyn(
  4291. pInfo->pArgs->rdp.szPassword,
  4292. pInfo->pszGoodPassword,
  4293. sizeof(pInfo->pArgs->rdp.szPassword) / sizeof(TCHAR) );
  4294. EncodePassword( pInfo->pArgs->rdp.szPassword );
  4295. ZeroMemory(
  4296. pInfo->pszGoodPassword,
  4297. (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) );
  4298. Free( pInfo->pszGoodPassword );
  4299. pInfo->pszGoodPassword = NULL;
  4300. }
  4301. if (pInfo->pszGoodUserName)
  4302. {
  4303. lstrcpyn(
  4304. pInfo->pArgs->rdp.szUserName,
  4305. pInfo->pszGoodUserName,
  4306. sizeof(pInfo->pArgs->rdp.szUserName) / sizeof(TCHAR) );
  4307. Free( pInfo->pszGoodUserName );
  4308. pInfo->pszGoodUserName = NULL;
  4309. }
  4310. }
  4311. // Update cached credentials, if any, with new password.
  4312. //
  4313. // Whistler Bugs: 344019 SECBUGBASH: leaving leaked password in memory when
  4314. // user changes password over RAS
  4315. //
  4316. // 289587 Failed RAS connections reset password to blank
  4317. //
  4318. if ((pState->sidState == SID_S_Projected) &&
  4319. (pInfo->pszGoodPassword) &&
  4320. (pInfo->pszGoodUserName))
  4321. {
  4322. DWORD dwErr;
  4323. RASCREDENTIALS rc;
  4324. TRACE( "DpAuthNotify - Success changing password, caching if necessary" );
  4325. ZeroMemory( &rc, sizeof(rc) );
  4326. rc.dwSize = sizeof(rc);
  4327. // Look up cached password. Since we are only calling in with the
  4328. // RASCM_Password flag here, with the current implementation of
  4329. // RasGet/SetCredentials, this works for the Set below whether we are
  4330. // saving a Per-User, Global, or the special case of having both saved
  4331. // at the same time. Whew, complicated!
  4332. //
  4333. rc.dwMask = RASCM_Password;
  4334. ASSERT( g_pRasGetCredentials );
  4335. TRACE( "RasGetCredentials" );
  4336. dwErr = g_pRasGetCredentials(
  4337. pInfo->pArgs->pFile->pszPath,
  4338. pInfo->pArgs->pEntry->pszEntryName,
  4339. &rc );
  4340. TRACE2( "RasGetCredentials=%d,m=%x", dwErr, rc.dwMask );
  4341. if (dwErr == 0 && (rc.dwMask & RASCM_Password))
  4342. {
  4343. // Password was cached, so update it.
  4344. //
  4345. DecodePassword( pInfo->pArgs->rdp.szPassword );
  4346. lstrcpyn(
  4347. rc.szPassword,
  4348. pInfo->pArgs->rdp.szPassword,
  4349. sizeof(rc.szPassword) / sizeof(TCHAR) );
  4350. EncodePassword( pInfo->pArgs->rdp.szPassword );
  4351. ASSERT( g_pRasSetCredentials );
  4352. TRACE( "RasSetCredentials(p,FALSE)" );
  4353. dwErr = g_pRasSetCredentials(
  4354. pInfo->pArgs->pFile->pszPath,
  4355. pInfo->pArgs->pEntry->pszEntryName, &rc, FALSE );
  4356. TRACE1( "RasSetCredentials=%d", dwErr );
  4357. if (dwErr != 0)
  4358. {
  4359. ErrorDlg( pInfo->hwndDlg, SID_OP_UncachePw, dwErr, NULL );
  4360. }
  4361. }
  4362. // Clean up
  4363. //
  4364. ZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
  4365. ZeroMemory(
  4366. pInfo->pszGoodPassword,
  4367. (lstrlen( pInfo->pszGoodPassword ) + 1) * sizeof(TCHAR) );
  4368. Free( pInfo->pszGoodPassword );
  4369. pInfo->pszGoodPassword = NULL;
  4370. Free( pInfo->pszGoodUserName );
  4371. pInfo->pszGoodUserName = NULL;
  4372. }
  4373. }
  4374. VOID
  4375. DpCallbackSetByCaller(
  4376. IN DPINFO* pInfo,
  4377. IN DPSTATE* pState )
  4378. // RASCS_CallbackSetByCaller state handling. 'PInfo' is the dialog
  4379. // context. 'PState' is the subentry state.
  4380. //
  4381. // Returns true if successful, or an error code.
  4382. //
  4383. {
  4384. TCHAR* pszDefault;
  4385. TCHAR szNum[ RAS_MaxCallbackNumber + 1 ];
  4386. TRACE( "DpCallbackSetByCaller" );
  4387. pszDefault = pInfo->pArgs->pUser->pszLastCallbackByCaller;
  4388. if (!pszDefault)
  4389. {
  4390. pszDefault = TEXT("");
  4391. }
  4392. lstrcpyn( szNum, pszDefault, RAS_MaxCallbackNumber + 1 );
  4393. if (DialCallbackDlg( pInfo->hwndDlg, szNum ))
  4394. {
  4395. lstrcpyn( pInfo->pArgs->rdp.szCallbackNumber, szNum, RAS_MaxCallbackNumber + 1 );
  4396. if (lstrcmp( szNum, pszDefault ) != 0)
  4397. {
  4398. Free0( pInfo->pArgs->pUser->pszLastCallbackByCaller );
  4399. pInfo->pArgs->pUser->pszLastCallbackByCaller = StrDup( szNum );
  4400. pInfo->pArgs->pUser->fDirty = TRUE;
  4401. }
  4402. }
  4403. else
  4404. {
  4405. pInfo->pArgs->rdp.szCallbackNumber[ 0 ] = TEXT('\0');
  4406. }
  4407. pState->sidState = 0;
  4408. }
  4409. BOOL
  4410. DpCallbacksFlag(
  4411. IN DPINFO* pInfo,
  4412. IN INT nSet )
  4413. // If 'nSet' is not less than 0, the 'pInfo->fCallbacksActive' flag is set
  4414. // to the value 'nSet'.
  4415. //
  4416. // Returns true is callbacks are active false otherwise.
  4417. //
  4418. {
  4419. BOOL f;
  4420. TRACE1( "DpCallbacksFlag:nSet=(%d)", nSet );
  4421. f = FALSE;
  4422. if (WaitForSingleObject(
  4423. g_hmutexCallbacks, INFINITE ) == WAIT_OBJECT_0)
  4424. {
  4425. TRACE("DpCallbacksFlag begin:");
  4426. TRACE1("Global active:(%d)", g_ulCallbacksActive);
  4427. TRACE1("Current thread active:(%d)", pInfo->ulCallbacksActive);
  4428. f = pInfo->fCallbacksActive;
  4429. if (nSet > 0)
  4430. {
  4431. ASSERT( !pInfo->fCallbacksActive );
  4432. pInfo->fCallbacksActive = TRUE;
  4433. ++g_ulCallbacksActive;
  4434. pInfo->ulCallbacksActive++;
  4435. }
  4436. else if (nSet == 0)
  4437. {
  4438. pInfo->fCallbacksActive = FALSE;
  4439. if ( 0 < pInfo->ulCallbacksActive )
  4440. {
  4441. // fix for whistler bug 341662 366237 gangz
  4442. //
  4443. if( 0 < g_ulCallbacksActive )
  4444. {
  4445. --g_ulCallbacksActive;
  4446. }
  4447. pInfo->ulCallbacksActive--;
  4448. }
  4449. }
  4450. TRACE("DpCallbacksFlag result:");
  4451. TRACE1("Global active:(%d)", g_ulCallbacksActive);
  4452. TRACE1("Current thread active:(%d)", pInfo->ulCallbacksActive);
  4453. ReleaseMutex( g_hmutexCallbacks );
  4454. }
  4455. TRACE1( "DpCallbacksFlag: This thread's active=%d", f );
  4456. return f;
  4457. }
  4458. VOID
  4459. DpCancel(
  4460. IN DPINFO* pInfo )
  4461. // Kill the dialog and any partially initiated call, as when cancel button
  4462. // is pressed. 'PInfo' is the dialog context block.
  4463. //
  4464. {
  4465. TRACE( "DpCancel" );
  4466. // Hide window to prevent visual complaints that arise if RasHangUp takes
  4467. // a long time to complete.
  4468. //
  4469. ShowWindow( pInfo->hwndDlg, SW_HIDE );
  4470. if (pInfo->hrasconn)
  4471. {
  4472. DWORD dwErr;
  4473. ASSERT( g_pRasHangUp );
  4474. TRACE( "RasHangUp" );
  4475. TRACE("DpCancel:call RasHangUp");
  4476. dwErr = g_pRasHangUp( pInfo->hrasconn );
  4477. TRACE1("DpCancel:get dwErr from RasHangUp:(%d)", dwErr);
  4478. TRACE1( "RasHangUp=%d", dwErr );
  4479. }
  4480. EndDialog( pInfo->hwndDlg, FALSE );
  4481. }
  4482. //return the pInfo->ulCallbacksActive, to get the g_ulCallbacksActive
  4483. //use CallbacksActive()
  4484. //
  4485. long
  4486. DpOnOffPerThreadTerminateFlag(
  4487. DPINFO *pInfo,
  4488. INT nSetTerminateAsap,
  4489. BOOL* pfTerminateAsap )
  4490. // If 'fSetTerminateAsap' >= 0, sets 'pInfo->fTerminateAsap' flag to 'nSetTerminateAsap'.
  4491. // If non-NULL, caller's '*pfTerminateAsap' is filled with the current value of
  4492. // 'pInfo->fTerminateAsap'.
  4493. //
  4494. // Returns the number of Rasdial callback threads active.
  4495. //
  4496. {
  4497. LONG ul;
  4498. TRACE1( "DpOnOffPerThreadTerminateFlag: Terminate=(%d)", nSetTerminateAsap );
  4499. ASSERT(pInfo);
  4500. ul = 0;
  4501. if (WaitForSingleObject( g_hmutexCallbacks, INFINITE ) == WAIT_OBJECT_0)
  4502. {
  4503. if( pInfo )
  4504. {
  4505. if (pfTerminateAsap)
  4506. {
  4507. *pfTerminateAsap = pInfo->fTerminateAsap;
  4508. }
  4509. if (nSetTerminateAsap >= 0)
  4510. {
  4511. pInfo->fTerminateAsap = (BOOL )nSetTerminateAsap;
  4512. }
  4513. }
  4514. else
  4515. {
  4516. TRACE( "DpOnOffPerThreadTerminateFlag: Invalid DPINFO input parameter" );
  4517. }
  4518. ul = pInfo->ulCallbacksActive;
  4519. ReleaseMutex( g_hmutexCallbacks );
  4520. }
  4521. TRACE1( "DpOnOffPerThreadTerminateFlag:Current Thread Active=%d", ul );
  4522. return ul;
  4523. }
  4524. BOOL
  4525. DpCommand(
  4526. IN DPINFO* pInfo,
  4527. IN WORD wNotification,
  4528. IN WORD wId,
  4529. IN HWND hwndCtrl )
  4530. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  4531. // is the notification code of the command. 'wId' is the control/menu
  4532. // identifier of the command. 'HwndCtrl' is the control window handle of
  4533. // the command.
  4534. //
  4535. // Returns true if processed message, false otherwise.
  4536. //
  4537. {
  4538. DWORD dwErr;
  4539. TRACE3( "DpCommand(n=%d,i=%d,c=$%x)",
  4540. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  4541. TRACE2("DpCommand:pInfo address (0x%x), Dialog Handle (0x%x)",
  4542. pInfo,
  4543. pInfo->hwndDlg);
  4544. TRACE2("DpCommand:Current proces:(0x%d), Current Thread:(0x%d)",
  4545. GetCurrentProcessId(),
  4546. GetCurrentThreadId());
  4547. switch (wId)
  4548. {
  4549. case IDCANCEL:
  4550. {
  4551. ULONG ulCallbacksActive;
  4552. ShowWindow( pInfo->hwndDlg, SW_HIDE );
  4553. //For whistler bug 381337
  4554. //
  4555. if( !pInfo->fCancelPressed)
  4556. {
  4557. TRACE("DpCommand:Cancel pressed");
  4558. pInfo->fCancelPressed = TRUE;
  4559. }
  4560. if (pInfo->hrasconn)
  4561. {
  4562. DWORD dwErr;
  4563. ASSERT( g_pRasHangUp );
  4564. TRACE( "RasHangUp" );
  4565. dwErr = g_pRasHangUp( pInfo->hrasconn );
  4566. TRACE1( "RasHangUp=%d", dwErr );
  4567. }
  4568. //set pInfo->fTerminateAsap to Terminate the dial
  4569. //in the current thread, also return the pInfo->ulCallbacksActive,
  4570. //if it is already 0, then we dont need to post the CANCEL window
  4571. //Message again whistler bug#291613 gangz
  4572. //
  4573. ulCallbacksActive = DpOnOffPerThreadTerminateFlag(pInfo, 1, NULL );
  4574. if ( 0 < ulCallbacksActive )
  4575. {
  4576. TRACE1( "DpCommand stall, current thread's ulCallbacksActive n=%d", ulCallbacksActive );
  4577. PostMessage( pInfo->hwndDlg, WM_COMMAND,
  4578. MAKEWPARAM(wId, wNotification),
  4579. (LPARAM) hwndCtrl );
  4580. //For whistler bug 378086 gangz
  4581. //to sleep a bit to give the rasman a break to call our callback
  4582. //function DpRasDialFunc2()
  4583. //
  4584. Sleep(10);
  4585. return TRUE;
  4586. }
  4587. EndDialog( pInfo->hwndDlg, FALSE );
  4588. //Reset the pInfo->fTerminateAsap flag
  4589. //
  4590. DpOnOffPerThreadTerminateFlag(pInfo, 0, NULL );
  4591. return TRUE;
  4592. }
  4593. }
  4594. return FALSE;
  4595. }
  4596. VOID
  4597. DpConnectDevice(
  4598. IN DPINFO* pInfo,
  4599. IN DPSTATE* pState )
  4600. // RASCS_ConnectDevice state handling. 'PInfo' is the dialog context.
  4601. // 'PState' is the subentry state.
  4602. //
  4603. {
  4604. DWORD dwErr;
  4605. RASCONNSTATUS rcs;
  4606. DWORD cb;
  4607. HRASCONN hrasconn;
  4608. TCHAR* pszPhoneNumber;
  4609. TRACE( "DpConnectDevice" );
  4610. // Get fully translated phone number, if any.
  4611. //
  4612. ZeroMemory( &rcs, sizeof(rcs) );
  4613. rcs.dwSize = sizeof(rcs);
  4614. ASSERT( g_pRasGetConnectStatus );
  4615. TRACE1( "RasGetConnectStatus($%08x)", pState->hrasconnLink );
  4616. dwErr = g_pRasGetConnectStatus( pState->hrasconnLink, &rcs );
  4617. TRACE1( "RasGetConnectStatus=%d", dwErr );
  4618. TRACEW1( " dt=%s", rcs.szDeviceType );
  4619. TRACEW1( " dn=%s", rcs.szDeviceName );
  4620. TRACEW1( " pn=%s", rcs.szPhoneNumber );
  4621. if (dwErr != 0)
  4622. {
  4623. pState->pbdt = PBDT_None;
  4624. }
  4625. pState->pbdt = PbdevicetypeFromPszType( rcs.szDeviceType );
  4626. pszPhoneNumber = rcs.szPhoneNumber;
  4627. switch (pState->pbdt)
  4628. {
  4629. case PBDT_Modem:
  4630. {
  4631. Free0( pState->pszStatusArg );
  4632. pState->pszStatusArg = StrDup( pszPhoneNumber );
  4633. if (pInfo->pArgs->pUser->fOperatorDial
  4634. && AllLinksAreModems( pInfo->pArgs->pEntry ))
  4635. {
  4636. pState->sidState = SID_S_ConnectModemOperator;
  4637. }
  4638. else if (pInfo->pArgs->pEntry->fPreviewPhoneNumber)
  4639. {
  4640. pState->sidState = SID_S_ConnectNumber;
  4641. }
  4642. else
  4643. {
  4644. pState->sidState = SID_S_ConnectModemNoNum;
  4645. }
  4646. break;
  4647. }
  4648. case PBDT_Pad:
  4649. {
  4650. Free0( pState->pszStatusArg );
  4651. pState->pszStatusArg = StrDup( rcs.szDeviceName );
  4652. pState->sidState = SID_S_ConnectPad;
  4653. if (pState->dwError == ERROR_X25_DIAGNOSTIC)
  4654. {
  4655. TCHAR* psz;
  4656. // Get the X.25 diagnostic string for display in the
  4657. // custom "diagnostics" error message format.
  4658. //
  4659. Free0( pState->pszFormatArg );
  4660. pState->pszFormatArg =
  4661. GetRasX25Diagnostic( pState->hrasconnLink );
  4662. }
  4663. break;
  4664. }
  4665. case PBDT_Switch:
  4666. {
  4667. Free0( pState->pszStatusArg );
  4668. pState->pszStatusArg = StrDup( rcs.szDeviceName );
  4669. pState->sidState =
  4670. (pState->fNotPreSwitch)
  4671. ? SID_S_ConnectPostSwitch
  4672. : SID_S_ConnectPreSwitch;
  4673. break;
  4674. }
  4675. case PBDT_Null:
  4676. {
  4677. pState->sidState = SID_S_ConnectNull;
  4678. break;
  4679. }
  4680. case PBDT_Parallel:
  4681. {
  4682. pState->sidState = SID_S_ConnectParallel;
  4683. break;
  4684. }
  4685. case PBDT_Irda:
  4686. {
  4687. pState->sidState = SID_S_ConnectIrda;
  4688. break;
  4689. }
  4690. case PBDT_Isdn:
  4691. {
  4692. Free0( pState->pszStatusArg );
  4693. pState->pszStatusArg = StrDup( pszPhoneNumber );
  4694. pState->sidState = SID_S_ConnectNumber;
  4695. break;
  4696. }
  4697. case PBDT_Vpn:
  4698. {
  4699. Free0( pState->pszStatusArg );
  4700. pState->pszStatusArg = StrDup( pszPhoneNumber );
  4701. pState->sidState = SID_S_ConnectVpn;
  4702. break;
  4703. }
  4704. default:
  4705. {
  4706. Free0( pState->pszStatusArg );
  4707. if (pszPhoneNumber[ 0 ] != TEXT('\0'))
  4708. {
  4709. pState->pszStatusArg = StrDup( pszPhoneNumber );
  4710. pState->sidState = SID_S_ConnectNumber;
  4711. }
  4712. else
  4713. {
  4714. pState->pszStatusArg = StrDup( rcs.szDeviceName );
  4715. pState->sidState = SID_S_ConnectDevice;
  4716. }
  4717. break;
  4718. }
  4719. }
  4720. }
  4721. VOID
  4722. DpDeviceConnected(
  4723. IN DPINFO* pInfo,
  4724. IN DPSTATE* pState )
  4725. // RASCS_DeviceConnected state handling. 'PInfo' is the dialog context.
  4726. // 'PState' is the subentry state.
  4727. //
  4728. // Returns 0 if successful, or an error code.
  4729. //
  4730. {
  4731. TRACE( "DpDeviceConnected" );
  4732. switch (pState->pbdt)
  4733. {
  4734. case PBDT_Modem:
  4735. {
  4736. pState->sidState = SID_S_ModemConnected;
  4737. pState->fNotPreSwitch = TRUE;
  4738. break;
  4739. }
  4740. case PBDT_Pad:
  4741. {
  4742. pState->sidState = SID_S_PadConnected;
  4743. pState->fNotPreSwitch = TRUE;
  4744. break;
  4745. }
  4746. case PBDT_Switch:
  4747. {
  4748. pState->sidState =
  4749. (pState->fNotPreSwitch)
  4750. ? SID_S_PostSwitchConnected
  4751. : SID_S_PreSwitchConnected;
  4752. pState->fNotPreSwitch = TRUE;
  4753. break;
  4754. }
  4755. case PBDT_Null:
  4756. {
  4757. pState->sidState = SID_S_NullConnected;
  4758. pState->fNotPreSwitch = TRUE;
  4759. break;
  4760. }
  4761. case PBDT_Parallel:
  4762. {
  4763. pState->sidState = SID_S_ParallelConnected;
  4764. pState->fNotPreSwitch = TRUE;
  4765. break;
  4766. }
  4767. case PBDT_Irda:
  4768. {
  4769. pState->sidState = SID_S_IrdaConnected;
  4770. pState->fNotPreSwitch = TRUE;
  4771. break;
  4772. }
  4773. default:
  4774. {
  4775. pState->sidState = SID_S_DeviceConnected;
  4776. break;
  4777. }
  4778. }
  4779. }
  4780. VOID
  4781. DpDial(
  4782. IN DPINFO* pInfo,
  4783. IN BOOL fPauseRestart )
  4784. // Dial with the parameters in the 'pInfo' dialog context block.
  4785. // 'FPausedRestart' indicates the dial is restarting from a paused state
  4786. // and dial states should not be reset.
  4787. //
  4788. {
  4789. DWORD dwErr;
  4790. TRACE1( "DpDial,fPauseRestart=%d", fPauseRestart );
  4791. if (!fPauseRestart)
  4792. {
  4793. DpInitStates( pInfo );
  4794. //comment for bug 277365, 291613 gangz
  4795. //Set the fCallbacksActive to be TRUE
  4796. //
  4797. TRACE("DpDial:Init global actives");
  4798. DpCallbacksFlag( pInfo, 1 );
  4799. }
  4800. else
  4801. {
  4802. TRACE("DpDial:WONT Init global actives for pausedRestart");
  4803. }
  4804. // Whistler bug 254385 encode password when not being used
  4805. // Assumed password was encoded previously
  4806. //
  4807. DecodePassword( pInfo->pArgs->rdp.szPassword );
  4808. TRACE1( "RasDial(h=$%08x)", pInfo->hrasconn );
  4809. ASSERT( g_pRasDial );
  4810. dwErr = g_pRasDial( &pInfo->pArgs->rde, pInfo->pArgs->pFile->pszPath,
  4811. &pInfo->pArgs->rdp, 2, (LPVOID )DpRasDialFunc2, &pInfo->hrasconn );
  4812. TRACE2( "RasDial=%d,h=$%08x", dwErr, pInfo->hrasconn );
  4813. EncodePassword( pInfo->pArgs->rdp.szPassword );
  4814. if (dwErr != 0)
  4815. {
  4816. // This same error will show up via the callback route on restarts
  4817. // from PAUSEd states so avoid double popups in that case. See bug
  4818. // 367482.
  4819. //
  4820. if (!fPauseRestart)
  4821. {
  4822. ErrorDlg( pInfo->hwndDlg, SID_OP_RasDial, dwErr, NULL );
  4823. DpCallbacksFlag( pInfo, 0 );
  4824. }
  4825. // If we receive error 668 here, it means that a rasevent is currently
  4826. // posted for state RASCS_Disconnected. We shouldn't cancel in this
  4827. // case since we Normal processing of RASCS_Disconnected will allow the
  4828. // user to redial. Also, calling DpCancel below will insert
  4829. // WM_DESTROY which will process before the popup that the rasevent
  4830. // produces can display. 367482
  4831. //
  4832. if (dwErr != ERROR_NO_CONNECTION)
  4833. {
  4834. DpCancel( pInfo );
  4835. }
  4836. }
  4837. }
  4838. VOID
  4839. DpError(
  4840. IN DPINFO* pInfo,
  4841. IN DPSTATE* pState )
  4842. // Popup error dialog for error identified by 'pState' and cancel or
  4843. // redial as indicated by user. 'PInfo' is the dialog context.
  4844. //
  4845. {
  4846. DWORD dwErr;
  4847. DWORD dwRedialAttemptsLeft;
  4848. DWORD sidState;
  4849. TRACE( "DpError" );
  4850. // Retrieve additional text from RASMXS on those special errors where the
  4851. // device returned something useful to display.
  4852. //
  4853. if (pState->dwError == ERROR_FROM_DEVICE
  4854. || pState->dwError == ERROR_UNRECOGNIZED_RESPONSE)
  4855. {
  4856. TCHAR* pszMessage;
  4857. dwErr = GetRasMessage( pInfo->hrasconn, &pszMessage );
  4858. if (dwErr == 0)
  4859. {
  4860. pState->sidFormatMsg = SID_FMT_ErrorMsgResp;
  4861. Free0( pState->pszFormatArg );
  4862. pState->pszFormatArg = pszMessage;
  4863. }
  4864. }
  4865. if (pState->sidFormatMsg == 0)
  4866. {
  4867. if (pState->dwExtendedError != 0)
  4868. {
  4869. // Translate extended error code into arguments.
  4870. //
  4871. TCHAR szNum[ 2 + MAXLTOTLEN + 1 ];
  4872. pState->sidFormatMsg = SID_FMT_ErrorMsgExt;
  4873. szNum[ 0 ] = TEXT('0');
  4874. szNum[ 1 ] = TEXT('x');
  4875. LToT( pState->dwExtendedError, szNum + 2, 16 );
  4876. Free0( pState->pszFormatArg );
  4877. pState->pszFormatArg = StrDup( szNum );
  4878. }
  4879. else if (pState->szExtendedError[ 0 ] != TEXT('\0'))
  4880. {
  4881. // Translate extended error string to argument. Currently, the
  4882. // string is always a NetBIOS name.
  4883. //
  4884. pState->sidFormatMsg = SID_FMT_ErrorMsgName;
  4885. Free0( pState->pszFormatArg );
  4886. pState->pszFormatArg = StrDup( pState->szExtendedError );
  4887. }
  4888. }
  4889. if (pInfo->hrasconn)
  4890. {
  4891. // Hang up before displaying error popup so server side resources are
  4892. // not tied up waiting for client to acknowledge error.
  4893. //
  4894. ASSERT( g_pRasHangUp );
  4895. TRACE( "RasHangUp" );
  4896. dwErr = g_pRasHangUp( pInfo->hrasconn );
  4897. TRACE1( "RasHangUp=%d", dwErr );
  4898. pInfo->hrasconn = NULL;
  4899. }
  4900. if (pInfo->pArgs->pEntry->pszPrerequisiteEntry
  4901. && *pInfo->pArgs->pEntry->pszPrerequisiteEntry)
  4902. {
  4903. // Select "no Redial button" mode for entries that have prerequisite
  4904. // entries. This is because RASMAN drops the prerequisite entry as
  4905. // soon as the dependent entry fails, thus dooming to defeat a redial
  4906. // of only the dependent entry. Yes, it should really redial both
  4907. // entries here, but that is not really feasible with the current
  4908. // non-integrated serial implementation of prerequisite entries. This
  4909. // at least improves the poor behavior cited in bug 230594.
  4910. //
  4911. dwRedialAttemptsLeft = -2;
  4912. }
  4913. else if (pInfo->dwRedialAttemptsLeft <= 0)
  4914. {
  4915. // No auto-redial countdown, but "Redial" button does appear in place
  4916. // of the default "OK".
  4917. //
  4918. dwRedialAttemptsLeft = -1;
  4919. }
  4920. else
  4921. {
  4922. // Auto-redial countdown based on the entries configuration.
  4923. //
  4924. dwRedialAttemptsLeft =
  4925. GetOverridableParam(
  4926. pInfo->pArgs->pUser,
  4927. pInfo->pArgs->pEntry,
  4928. RASOR_RedialSeconds );
  4929. }
  4930. // This hack works around a bug in RasDial API. See bug 313102.
  4931. //
  4932. sidState = pState ->sidState;
  4933. if (!sidState)
  4934. {
  4935. sidState = SID_S_AuthNotify;
  4936. }
  4937. if (DialErrorDlg(
  4938. pInfo->hwndDlg,
  4939. pInfo->pArgs->pEntry->pszEntryName,
  4940. pState->dwError,
  4941. sidState,
  4942. pState->pszStatusArg,
  4943. pState->sidFormatMsg,
  4944. pState->pszFormatArg,
  4945. dwRedialAttemptsLeft,
  4946. GetOverridableParam(
  4947. pInfo->pArgs->pUser, pInfo->pArgs->pEntry,
  4948. RASOR_PopupOnTopWhenRedialing ) ))
  4949. {
  4950. TRACE( "User redials" );
  4951. if (pInfo->dwRedialAttemptsLeft > 0)
  4952. {
  4953. --pInfo->dwRedialAttemptsLeft;
  4954. }
  4955. TRACE(" Post(DIAL)" );
  4956. PostMessage( pInfo->hwndDlg, WM_RASDIAL, FALSE, 0 );
  4957. }
  4958. else
  4959. {
  4960. TRACE( "User cancels" );
  4961. DpCancel( pInfo );
  4962. }
  4963. //
  4964. // Set the error so that the error is propagated back
  4965. // to the caller of the RasDialDlg api.
  4966. //
  4967. TRACE2("DpError settings error (0x%x) to %d",
  4968. &pInfo->pArgs->pArgs->dwError,
  4969. pState->dwError);
  4970. pInfo->pArgs->pArgs->dwError = pState->dwError;
  4971. }
  4972. DWORD
  4973. DpEvent(
  4974. IN DPINFO* pInfo,
  4975. IN DWORD dwSubEntry )
  4976. // Handle a RasDial callback event on subentry 'dwSubEntry'. 'PInfo' is
  4977. // the dialog context.
  4978. //
  4979. // Return 0 to stop callbacks from RasDial, or 1 to continue callbacks
  4980. // (normal), or 2 to indicate that the phonebook entry has changed and
  4981. // should be re-read by RasDial.
  4982. //
  4983. {
  4984. DWORD dwErr;
  4985. DWORD dwCode;
  4986. BOOL fLeader;
  4987. DWORD dwcSuccessLinks, dwcFailedLinks, i;
  4988. DPSTATE* pState;
  4989. BOOL fPartialMultilink;
  4990. BOOL fIsLaterState;
  4991. TRACE( "DpEvent" );
  4992. // Default to "normal" return.
  4993. //
  4994. dwCode = 1;
  4995. fPartialMultilink = FALSE;
  4996. TRACE2("Current proces:(0x%d), Current Thread:(0x%d)",
  4997. GetCurrentProcessId(),
  4998. GetCurrentThreadId());
  4999. // Find the associated state information and figure out if this is the
  5000. // most advanced sub-entry.
  5001. //
  5002. pState = &pInfo->pStates[ dwSubEntry - 1 ];
  5003. fIsLaterState = DpIsLaterState( pState->state, pInfo->state );
  5004. if (dwSubEntry == pInfo->dwSubEntry || fIsLaterState)
  5005. {
  5006. fLeader = TRUE;
  5007. if (fIsLaterState)
  5008. {
  5009. pInfo->dwSubEntry = dwSubEntry;
  5010. pInfo->state = pState->state;
  5011. }
  5012. }
  5013. else
  5014. {
  5015. fLeader = FALSE;
  5016. TRACE( "Trailing" );
  5017. }
  5018. // Execute the state.
  5019. //
  5020. TRACE1("State is:(%d)", pState->state);
  5021. switch (pState->state)
  5022. {
  5023. case RASCS_OpenPort:
  5024. {
  5025. pState->pbdt = PBDT_None;
  5026. pState->sidState = SID_S_OpenPort;
  5027. break;
  5028. }
  5029. case RASCS_PortOpened:
  5030. {
  5031. // Should have an hrasconnLink for this subentry now. Look it up
  5032. // and stash it in our context.
  5033. //
  5034. ASSERT( g_pRasGetSubEntryHandle );
  5035. TRACE1( "RasGetSubEntryHandle(se=%d)", dwSubEntry );
  5036. dwErr = g_pRasGetSubEntryHandle(
  5037. pInfo->hrasconn, dwSubEntry, &pState->hrasconnLink );
  5038. TRACE2( "RasGetSubEntryHandle=%d,hL=$%08x",
  5039. dwErr, pState->hrasconnLink );
  5040. if (dwErr != 0)
  5041. {
  5042. pState->dwError = dwErr;
  5043. }
  5044. pState->sidState = SID_S_PortOpened;
  5045. break;
  5046. }
  5047. case RASCS_ConnectDevice:
  5048. {
  5049. DTLNODE* pNode;
  5050. PBLINK* pLink;
  5051. pNode = DtlNodeFromIndex(
  5052. pInfo->pArgs->pEntry->pdtllistLinks, dwSubEntry - 1 );
  5053. ASSERT( pNode );
  5054. if(NULL == pNode)
  5055. {
  5056. pState->dwError = ERROR_NOT_ENOUGH_MEMORY;
  5057. }
  5058. else
  5059. {
  5060. pLink = (PBLINK* )DtlGetData( pNode );
  5061. }
  5062. if ((pState->dwError == ERROR_PORT_OR_DEVICE
  5063. && (pLink->pbport.fScriptBeforeTerminal
  5064. || pLink->pbport.fScriptBefore))
  5065. || (pState->dwError == ERROR_USER_DISCONNECTION
  5066. && (pInfo->pArgs->pUser->fOperatorDial
  5067. && AllLinksAreModems( pInfo->pArgs->pEntry ))))
  5068. {
  5069. // This happens when user presses Cancel on the Unimodem
  5070. // "Pre-Dial Terminal Screen" or "Operator Assisted or Manual
  5071. // Dial" dialog.
  5072. //
  5073. TRACE("DpEvent:Call DpCancel() in connectDevice, but still return 1\n");
  5074. DpCancel( pInfo );
  5075. return dwCode;
  5076. }
  5077. DpConnectDevice( pInfo, pState );
  5078. break;
  5079. }
  5080. case RASCS_DeviceConnected:
  5081. {
  5082. DpDeviceConnected( pInfo, pState );
  5083. break;
  5084. }
  5085. case RASCS_AllDevicesConnected:
  5086. {
  5087. pState->sidState = SID_S_AllDevicesConnected;
  5088. break;
  5089. }
  5090. case RASCS_Authenticate:
  5091. {
  5092. pState->sidState = SID_S_Authenticate;
  5093. break;
  5094. }
  5095. case RASCS_AuthNotify:
  5096. {
  5097. DpAuthNotify( pInfo, pState );
  5098. break;
  5099. }
  5100. case RASCS_AuthRetry:
  5101. {
  5102. pState->sidState = SID_S_AuthRetry;
  5103. break;
  5104. }
  5105. case RASCS_AuthCallback:
  5106. {
  5107. pState->sidState = SID_S_AuthCallback;
  5108. break;
  5109. }
  5110. case RASCS_AuthChangePassword:
  5111. {
  5112. pState->sidState = SID_S_AuthChangePassword;
  5113. break;
  5114. }
  5115. case RASCS_AuthProject:
  5116. {
  5117. pState->sidState = SID_S_AuthProject;
  5118. break;
  5119. }
  5120. case RASCS_AuthLinkSpeed:
  5121. {
  5122. pState->sidState = SID_S_AuthLinkSpeed;
  5123. break;
  5124. }
  5125. case RASCS_AuthAck:
  5126. {
  5127. pState->sidState = SID_S_AuthAck;
  5128. break;
  5129. }
  5130. case RASCS_ReAuthenticate:
  5131. {
  5132. pState->sidState = SID_S_ReAuthenticate;
  5133. break;
  5134. }
  5135. case RASCS_Authenticated:
  5136. {
  5137. pState->sidState = SID_S_Authenticated;
  5138. break;
  5139. }
  5140. case RASCS_PrepareForCallback:
  5141. {
  5142. pState->sidState = SID_S_PrepareForCallback;
  5143. break;
  5144. }
  5145. case RASCS_WaitForModemReset:
  5146. {
  5147. pState->sidState = SID_S_WaitForModemReset;
  5148. break;
  5149. }
  5150. case RASCS_WaitForCallback:
  5151. {
  5152. pState->sidState = SID_S_WaitForCallback;
  5153. break;
  5154. }
  5155. case RASCS_Projected:
  5156. {
  5157. if (fLeader)
  5158. {
  5159. // If DpProjected returns FALSE, it detected a fatal error,
  5160. // and the dialing process will stop. If DpProjected returns
  5161. // with pState->dwError non-zero, we display the error in a
  5162. // redial dialog, if redial is configured.
  5163. //
  5164. if (!DpProjected( pInfo, pState ))
  5165. {
  5166. TRACE("DpEvent:Call DpCancel() in RASCS_Projected, but still return 1 to DpRasDialFunc2()\n");
  5167. DpCancel( pInfo );
  5168. return dwCode;
  5169. }
  5170. else if (pState->dwError)
  5171. {
  5172. TRACE("DpCancel() in RASCS_Projected,return 0 to DpRasDialFunc2()");
  5173. TRACE( "DpEvent:Post(ERROR), return 0 to DpRasDialFunc2()" );
  5174. PostMessage( pInfo->hwndDlg,
  5175. WM_RASERROR, 0, (LPARAM )pState );
  5176. return 0;
  5177. }
  5178. }
  5179. break;
  5180. }
  5181. case RASCS_Interactive:
  5182. {
  5183. BOOL fChange = FALSE;
  5184. if (!DpInteractive( pInfo, pState, &fChange ))
  5185. {
  5186. DpCancel( pInfo );
  5187. return dwCode;
  5188. }
  5189. if (fChange)
  5190. {
  5191. dwCode = 2;
  5192. }
  5193. break;
  5194. }
  5195. case RASCS_RetryAuthentication:
  5196. {
  5197. if (!RetryAuthenticationDlg(
  5198. pInfo->hwndDlg, pInfo->pArgs ))
  5199. {
  5200. DpCancel( pInfo );
  5201. return dwCode;
  5202. }
  5203. pState->sidState = 0;
  5204. break;
  5205. }
  5206. case RASCS_InvokeEapUI:
  5207. {
  5208. if (g_pRasInvokeEapUI(
  5209. pInfo->hrasconn, dwSubEntry,
  5210. &pInfo->pArgs->rde, pInfo->hwndDlg ))
  5211. {
  5212. DpCancel( pInfo );
  5213. return dwCode;
  5214. }
  5215. pState->sidState = 0;
  5216. break;
  5217. }
  5218. case RASCS_CallbackSetByCaller:
  5219. {
  5220. DpCallbackSetByCaller( pInfo, pState );
  5221. break;
  5222. }
  5223. case RASCS_PasswordExpired:
  5224. {
  5225. if (!DpPasswordExpired( pInfo, pState ))
  5226. {
  5227. DpCancel( pInfo );
  5228. return dwCode;
  5229. }
  5230. break;
  5231. }
  5232. case RASCS_SubEntryConnected:
  5233. {
  5234. if (pInfo->cStates > 1)
  5235. {
  5236. pState->sidState = SID_S_SubConnected;
  5237. }
  5238. break;
  5239. }
  5240. case RASCS_SubEntryDisconnected:
  5241. {
  5242. break;
  5243. }
  5244. case RASCS_Connected:
  5245. {
  5246. pState->sidState = SID_S_Connected;
  5247. break;
  5248. }
  5249. case RASCS_Disconnected:
  5250. {
  5251. pState->sidState = SID_S_Disconnected;
  5252. break;
  5253. }
  5254. default:
  5255. {
  5256. pState->sidState = SID_S_Unknown;
  5257. break;
  5258. }
  5259. }
  5260. // Count the successful and failed links.
  5261. //
  5262. {
  5263. DPSTATE* p;
  5264. dwcSuccessLinks = dwcFailedLinks = 0;
  5265. for (i = 0, p = pInfo->pStates; i < pInfo->cStates; ++i, ++p)
  5266. {
  5267. if (p->state == RASCS_SubEntryConnected)
  5268. {
  5269. ++dwcSuccessLinks;
  5270. }
  5271. if (p->dwError)
  5272. {
  5273. ++dwcFailedLinks;
  5274. }
  5275. }
  5276. }
  5277. TRACE3( "s=%d,f=%d,t=%d", dwcSuccessLinks, dwcFailedLinks, pInfo->cStates );
  5278. if (pState->dwError)
  5279. {
  5280. DTLNODE *pdtlnode = NULL;
  5281. DWORD dwIndex = pInfo->pArgs->rdp.dwSubEntry;
  5282. if(0 != dwIndex)
  5283. {
  5284. pdtlnode = DtlNodeFromIndex(
  5285. pInfo->pArgs->pEntry->pdtllistLinks,
  5286. dwIndex - 1);
  5287. }
  5288. if ( (dwcFailedLinks == pInfo->cStates)
  5289. || ( (RASEDM_DialAll != pInfo->pArgs->pEntry->dwDialMode)
  5290. && (dwcSuccessLinks == 0))
  5291. || (NULL != pdtlnode))
  5292. {
  5293. // A terminal error state has occurred on all links. Post a
  5294. // message telling ourselves to popup an error, then release the
  5295. // callback so it doesn't hold the port open while the error popup
  5296. // is up,
  5297. //
  5298. TRACE( "Post(ERROR)" );
  5299. PostMessage( pInfo->hwndDlg, WM_RASERROR, 0, (LPARAM )pState );
  5300. return 0;
  5301. }
  5302. else if (dwcSuccessLinks + dwcFailedLinks == pInfo->cStates)
  5303. {
  5304. // An error occurred on the final link, but some link connected.
  5305. // It would be nice if RasDial would followup with a
  5306. // RASCS_Connected in that case, but it doesn't, so we duplicate
  5307. // the RASCS_Connected-style exit here.
  5308. //
  5309. TRACE( "Post(BUNDLEERROR)" );
  5310. PostMessage( pInfo->hwndDlg,
  5311. WM_RASBUNDLEERROR, 0, (LPARAM )pState );
  5312. return 0;
  5313. }
  5314. // A fatal error has occurred on a link, but there are other links
  5315. // still trying, so let it die quietly.
  5316. //
  5317. TRACE2( "Link %d fails, e=%d", dwSubEntry + 1, pState->dwError );
  5318. return dwCode;
  5319. }
  5320. // Display the status string for this state.
  5321. //
  5322. if (pState->sidState)
  5323. {
  5324. if (pState->sidState != pState->sidPrevState)
  5325. {
  5326. pState->sidPrevState = pState->sidState;
  5327. }
  5328. if (fLeader)
  5329. {
  5330. TCHAR* pszState = PszFromId( g_hinstDll, pState->sidState );
  5331. if ( (NULL != pszState)
  5332. && pState->pszStatusArg)
  5333. {
  5334. TCHAR* pszFormattedState;
  5335. TCHAR* pszArg;
  5336. TCHAR* apszArgs[ 1 ];
  5337. DWORD cch;
  5338. pszArg = (pState->pszStatusArg)
  5339. ? pState->pszStatusArg : TEXT("");
  5340. // Find length of formatted string with text argument (if any)
  5341. // inserted and any progress dots appended.
  5342. //
  5343. cch = lstrlen( pszState ) + lstrlen( pszArg ) + 1;
  5344. pszFormattedState = Malloc( cch * sizeof(TCHAR) );
  5345. if (pszFormattedState)
  5346. {
  5347. apszArgs[ 0 ] = pszArg;
  5348. *pszFormattedState = TEXT('\0');
  5349. FormatMessage(
  5350. FORMAT_MESSAGE_FROM_STRING
  5351. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  5352. pszState, 0, 0, pszFormattedState, cch,
  5353. (va_list* )apszArgs );
  5354. Free( pszState );
  5355. pszState = pszFormattedState;
  5356. }
  5357. }
  5358. TRACE1("DpEvent:State:'%s'",pszState);
  5359. if (pszState)
  5360. {
  5361. SetWindowText( pInfo->hwndStState, pszState );
  5362. InvalidateRect( pInfo->hwndStState, NULL, TRUE );
  5363. UpdateWindow( pInfo->hwndStState );
  5364. LocalFree( pszState );
  5365. }
  5366. }
  5367. }
  5368. if (pState->state & RASCS_PAUSED)
  5369. {
  5370. // Paused state just processed. Release the callback, and dial again
  5371. // to resume.
  5372. //
  5373. TRACE("DpEvent:Paused, will dial again\nthe global callbacks wont init again");
  5374. TRACE( "Post(DIAL)" );
  5375. PostMessage( pInfo->hwndDlg, WM_RASDIAL, TRUE, 0 );
  5376. return dwCode;
  5377. }
  5378. if (pState->state & RASCS_DONE)
  5379. {
  5380. // Terminal state just processed.
  5381. //
  5382. if (pState->state == RASCS_Connected)
  5383. {
  5384. // For multi-link entries, if there is at least one successful
  5385. // line and at least one failed line, popup the bundling error
  5386. // dialog.
  5387. //
  5388. if (pInfo->cStates > 1)
  5389. {
  5390. DPSTATE* p;
  5391. dwcSuccessLinks = dwcFailedLinks = 0;
  5392. for (i = 0, p = pInfo->pStates; i < pInfo->cStates; ++i, ++p)
  5393. {
  5394. if (p->dwError == 0)
  5395. {
  5396. ++dwcSuccessLinks;
  5397. }
  5398. else
  5399. {
  5400. ++dwcFailedLinks;
  5401. }
  5402. }
  5403. if (dwcSuccessLinks > 0 && dwcFailedLinks > 0)
  5404. {
  5405. TRACE( "Post(BUNDLEERROR)" );
  5406. PostMessage( pInfo->hwndDlg,
  5407. WM_RASBUNDLEERROR, 0, (LPARAM )pState );
  5408. return 0;
  5409. }
  5410. }
  5411. EndDialog( pInfo->hwndDlg, TRUE );
  5412. }
  5413. else
  5414. {
  5415. DpCancel( pInfo );
  5416. }
  5417. return 0;
  5418. }
  5419. TRACE1("DpEvent:returned dwCode:(%d)", dwCode);
  5420. TRACE("End of DpEvent");
  5421. return dwCode;
  5422. }
  5423. BOOL
  5424. DpInit(
  5425. IN HWND hwndDlg,
  5426. IN DINFO* pArgs )
  5427. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  5428. // 'PArgs' is caller's arguments as passed to the stub API.
  5429. //
  5430. // Return false if focus was set, true otherwise, i.e. as defined for
  5431. // WM_INITDIALOG.
  5432. //
  5433. {
  5434. DWORD dwErr;
  5435. DPINFO* pInfo;
  5436. PBENTRY* pEntry;
  5437. TRACE( "DpInit" );
  5438. // Allocate the dialog context block. Initialize minimally for proper
  5439. // cleanup, then attach to the dialog window.
  5440. //
  5441. {
  5442. pInfo = Malloc( sizeof(*pInfo) );
  5443. if (!pInfo)
  5444. {
  5445. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  5446. EndDialog( hwndDlg, FALSE );
  5447. return TRUE;
  5448. }
  5449. ZeroMemory( pInfo, sizeof(*pInfo) );
  5450. pInfo->dwValid = 0xC0BBC0DE;
  5451. pInfo->pArgs = pArgs;
  5452. pInfo->hwndDlg = hwndDlg;
  5453. //Add a per-thread Terminate flag for whistler bug 291613 gangz
  5454. //
  5455. pInfo->fTerminateAsap = FALSE;
  5456. pInfo->ulCallbacksActive = 0;
  5457. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  5458. TRACE( "Context set" );
  5459. }
  5460. pInfo->hwndStState = GetDlgItem( hwndDlg, CID_DP_ST_State );
  5461. ASSERT( pInfo->hwndStState );
  5462. pEntry = pArgs->pEntry;
  5463. // Set up our context to be returned by the RasDialFunc2 callback.
  5464. //
  5465. pInfo->pArgs->rdp.dwCallbackId = (ULONG_PTR )pInfo;
  5466. // Subclass the dialog so we can get the result from
  5467. // SendMessage(WM_RASDIALEVENT) in RasDlgFunc2.
  5468. //
  5469. pInfo->pOldWndProc =
  5470. (WNDPROC )SetWindowLongPtr(
  5471. pInfo->hwndDlg, GWLP_WNDPROC, (ULONG_PTR )DpWndProc );
  5472. // Set the title.
  5473. //
  5474. {
  5475. TCHAR* pszTitleFormat;
  5476. TCHAR* pszTitle;
  5477. TCHAR* apszArgs[ 1 ];
  5478. pszTitleFormat = GetText( hwndDlg );
  5479. if (pszTitleFormat)
  5480. {
  5481. apszArgs[ 0 ] = pEntry->pszEntryName;
  5482. pszTitle = NULL;
  5483. FormatMessage(
  5484. FORMAT_MESSAGE_FROM_STRING
  5485. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  5486. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  5487. pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1,
  5488. (va_list* )apszArgs );
  5489. Free( pszTitleFormat );
  5490. if (pszTitle)
  5491. {
  5492. SetWindowText( hwndDlg, pszTitle );
  5493. LocalFree( pszTitle );
  5494. }
  5495. }
  5496. }
  5497. // Set the correct icon. For whistler bug 372078 gangz
  5498. //
  5499. SetIconFromEntryType(
  5500. GetDlgItem( hwndDlg, CID_DP_Icon ),
  5501. pArgs->pEntry->dwType,
  5502. FALSE); //FALSE means large Icon
  5503. // Position the dialog per caller's instructions.
  5504. //
  5505. PositionDlg( hwndDlg,
  5506. pArgs->pArgs->dwFlags & RASDDFLAG_PositionDlg,
  5507. pArgs->pArgs->xDlg, pArgs->pArgs->yDlg );
  5508. // Hide the dialog if "no progress" user preference is set.
  5509. //
  5510. if (!pArgs->pEntry->fShowDialingProgress
  5511. || pArgs->fDialForReferenceOnly)
  5512. {
  5513. SetOffDesktop( hwndDlg, SOD_MoveOff, NULL );
  5514. }
  5515. SetForegroundWindow( hwndDlg );
  5516. // Allocate subentry status array. It's initialized by DpDial.
  5517. //
  5518. {
  5519. DWORD cb;
  5520. ASSERT( pEntry->pdtllistLinks );
  5521. pInfo->cStates = DtlGetNodes( pEntry->pdtllistLinks );
  5522. cb = sizeof(DPSTATE) * pInfo->cStates;
  5523. pInfo->pStates = Malloc( cb );
  5524. if (!pInfo->pStates)
  5525. {
  5526. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  5527. EndDialog( hwndDlg, FALSE );
  5528. return TRUE;
  5529. }
  5530. pInfo->dwRedialAttemptsLeft =
  5531. GetOverridableParam(
  5532. pInfo->pArgs->pUser, pInfo->pArgs->pEntry,
  5533. RASOR_RedialAttempts );
  5534. }
  5535. //for whistler bug 316622 gangz
  5536. //The dwSubEntry is not initialized
  5537. //
  5538. pInfo->pArgs->rdp.dwSubEntry = pInfo->pArgs->pArgs->dwSubEntry;
  5539. // Rock and roll.
  5540. //
  5541. DpDial( pInfo, FALSE );
  5542. return TRUE;
  5543. }
  5544. VOID
  5545. DpInitStates(
  5546. DPINFO* pInfo )
  5547. // Resets 'pInfo->pStates' to initial values. 'PInfo' is the dialog
  5548. // context.
  5549. //
  5550. {
  5551. DWORD i;
  5552. DPSTATE* pState;
  5553. for (i = 0, pState = pInfo->pStates; i < pInfo->cStates; ++i, ++pState)
  5554. {
  5555. ZeroMemory( pState, sizeof(*pState) );
  5556. pInfo->state = (RASCONNSTATE )-1;
  5557. pState->dwError = 0;
  5558. }
  5559. }
  5560. BOOL
  5561. DpInteractive(
  5562. IN DPINFO* pInfo,
  5563. IN DPSTATE* pState,
  5564. OUT BOOL* pfChange )
  5565. // RASCS_Interactive handling. 'PInfo' is the dialog context. 'PState'
  5566. // is the subentry state. '*pfChange' is set true if the entry (i.e. SLIP
  5567. // address) was changed or false otherwise.
  5568. //
  5569. // Returns true if successful, false if cancel.
  5570. //
  5571. {
  5572. DWORD dwErr;
  5573. DWORD sidTitle;
  5574. TCHAR szIpAddress[ TERM_IpAddress ];
  5575. TCHAR* pszIpAddress;
  5576. PBENTRY* pEntry;
  5577. TRACE( "DpInteractive" );
  5578. *pfChange = FALSE;
  5579. pEntry = pInfo->pArgs->pEntry;
  5580. if (pEntry->dwBaseProtocol == BP_Slip)
  5581. {
  5582. lstrcpyn(
  5583. szIpAddress,
  5584. (pEntry->pszIpAddress) ? pEntry->pszIpAddress : TEXT("0.0.0.0"),
  5585. sizeof(szIpAddress) / sizeof(TCHAR));
  5586. pszIpAddress = szIpAddress;
  5587. sidTitle = SID_T_SlipTerminal;
  5588. }
  5589. else
  5590. {
  5591. szIpAddress[0] = TEXT('\0');
  5592. pszIpAddress = szIpAddress;
  5593. sidTitle =
  5594. (pState->sidState == SID_S_ConnectPreSwitch)
  5595. ? SID_T_PreconnectTerminal
  5596. : (pState->sidState == SID_S_ConnectPostSwitch)
  5597. ? SID_T_PostconnectTerminal
  5598. : SID_T_ManualDialTerminal;
  5599. }
  5600. if(1 == pEntry->dwCustomScript)
  5601. {
  5602. DWORD dwErr = SUCCESS;
  5603. dwErr = DwCustomTerminalDlg(
  5604. pInfo->pArgs->pFile->pszPath,
  5605. pInfo->hrasconn,
  5606. pEntry,
  5607. pInfo->hwndDlg,
  5608. &pInfo->pArgs->rdp,
  5609. NULL);
  5610. if(SUCCESS == dwErr)
  5611. {
  5612. #if 0
  5613. //
  5614. // Reread the phonebook file since the
  5615. // custom script could have written
  5616. // new information to the file.
  5617. //
  5618. ClosePhonebookFile(pInfo->pArgs->pFile);
  5619. dwErr = ReadPhonebookFile(
  5620. pInfo->pArgs->pszPhonebook,
  5621. &pInfo->pArgs->user,
  5622. NULL, 0, &pInfo->pArgs->file );
  5623. if(SUCCESS == dwErr)
  5624. {
  5625. pInfo->pArgs->pFile = &pInfo->pArgs->file;
  5626. }
  5627. #endif
  5628. }
  5629. if (dwErr != 0)
  5630. {
  5631. ErrorDlg( pInfo->hwndDlg, SID_OP_ScriptHalted, dwErr, NULL );
  5632. }
  5633. return (ERROR_SUCCESS == dwErr);
  5634. }
  5635. if (!TerminalDlg(
  5636. pInfo->pArgs->pEntry, &pInfo->pArgs->rdp, pInfo->hwndDlg,
  5637. pState->hrasconnLink, sidTitle, pszIpAddress ))
  5638. {
  5639. TRACE( "TerminalDlg==FALSE" );
  5640. return FALSE;
  5641. }
  5642. TRACE2( "pszIpAddress=0x%08x(%ls)", pszIpAddress,
  5643. pszIpAddress ? pszIpAddress : TEXT("") );
  5644. TRACE2( "pEntry->pszIpAddress=0x%08x(%ls)", pEntry->pszIpAddress,
  5645. pEntry->pszIpAddress ? pEntry->pszIpAddress : TEXT("") );
  5646. if (pszIpAddress[0]
  5647. && (!pEntry->pszIpAddress
  5648. || lstrcmp( pszIpAddress, pEntry->pszIpAddress ) != 0))
  5649. {
  5650. Free0( pEntry->pszIpAddress );
  5651. pEntry->pszIpAddress = StrDup( szIpAddress );
  5652. pEntry->fDirty = TRUE;
  5653. *pfChange = TRUE;
  5654. dwErr = WritePhonebookFile( pInfo->pArgs->pFile, NULL );
  5655. if (dwErr != 0)
  5656. {
  5657. ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL );
  5658. }
  5659. }
  5660. pState->sidState = 0;
  5661. return TRUE;
  5662. }
  5663. BOOL
  5664. DpIsLaterState(
  5665. IN RASCONNSTATE stateNew,
  5666. IN RASCONNSTATE stateOld )
  5667. // Returns true if 'stateNew' is farther along in the connection than
  5668. // 'stateOld' false if the same or not as far along.
  5669. //
  5670. {
  5671. // This array is in the order events normally occur.
  5672. //
  5673. // !!! New EAP states?
  5674. //
  5675. static RASCONNSTATE aState[] =
  5676. {
  5677. (RASCONNSTATE )-1,
  5678. RASCS_OpenPort,
  5679. RASCS_PortOpened,
  5680. RASCS_ConnectDevice,
  5681. RASCS_DeviceConnected,
  5682. RASCS_Interactive,
  5683. RASCS_AllDevicesConnected,
  5684. RASCS_StartAuthentication,
  5685. RASCS_Authenticate,
  5686. RASCS_InvokeEapUI,
  5687. RASCS_AuthNotify,
  5688. RASCS_AuthRetry,
  5689. RASCS_AuthAck,
  5690. RASCS_PasswordExpired,
  5691. RASCS_AuthChangePassword,
  5692. RASCS_AuthCallback,
  5693. RASCS_CallbackSetByCaller,
  5694. RASCS_PrepareForCallback,
  5695. RASCS_WaitForModemReset,
  5696. RASCS_WaitForCallback,
  5697. RASCS_CallbackComplete,
  5698. RASCS_RetryAuthentication,
  5699. RASCS_ReAuthenticate,
  5700. RASCS_Authenticated,
  5701. RASCS_AuthLinkSpeed,
  5702. RASCS_AuthProject,
  5703. RASCS_Projected,
  5704. RASCS_LogonNetwork,
  5705. RASCS_SubEntryDisconnected,
  5706. RASCS_SubEntryConnected,
  5707. RASCS_Disconnected,
  5708. RASCS_Connected,
  5709. (RASCONNSTATE )-2,
  5710. };
  5711. RASCONNSTATE* pState;
  5712. for (pState = aState; *pState != (RASCONNSTATE )-2; ++pState)
  5713. {
  5714. if (*pState == stateNew)
  5715. {
  5716. return FALSE;
  5717. }
  5718. else if (*pState == stateOld)
  5719. {
  5720. return TRUE;
  5721. }
  5722. }
  5723. return FALSE;
  5724. }
  5725. BOOL
  5726. DpPasswordExpired(
  5727. IN DPINFO* pInfo,
  5728. IN DPSTATE* pState )
  5729. // RASCS_PasswordExpired state handling. 'PInfo' is the dialog context.
  5730. // 'PState' is the subentry state.
  5731. //
  5732. // Returns true if successful, false otherwise.
  5733. //
  5734. {
  5735. TCHAR szOldPassword[ PWLEN + 1 ];
  5736. BOOL fSuppliedOldPassword;
  5737. TRACE( "DpPasswordExpired" );
  5738. szOldPassword[ 0 ] = TEXT('\0');
  5739. // Stash "good" username and password which are restored if the password
  5740. // change fails.
  5741. //
  5742. pInfo->pszGoodUserName = StrDup( pInfo->pArgs->rdp.szUserName );
  5743. // Whistler bug 254385 encode password when not being used
  5744. // Assumed password was encoded previously
  5745. //
  5746. DecodePassword( pInfo->pArgs->rdp.szPassword );
  5747. pInfo->pszGoodPassword = StrDup( pInfo->pArgs->rdp.szPassword );
  5748. EncodePassword( pInfo->pArgs->rdp.szPassword );
  5749. EncodePassword( pInfo->pszGoodPassword );
  5750. fSuppliedOldPassword =
  5751. (!pInfo->pArgs->pEntry->fAutoLogon || pInfo->pArgs->pNoUser);
  5752. if (!ChangePasswordDlg(
  5753. pInfo->hwndDlg, !fSuppliedOldPassword,
  5754. szOldPassword, pInfo->pArgs->rdp.szPassword ))
  5755. {
  5756. // Whistler bug 254385 encode password when not being used
  5757. //
  5758. ZeroMemory( szOldPassword, sizeof(szOldPassword) );
  5759. return FALSE;
  5760. }
  5761. if (pInfo->pArgs->pNoUser)
  5762. {
  5763. // Whistler bug 254385 encode password when not being used
  5764. // Assumed password was encoded previously
  5765. //
  5766. DecodePassword( pInfo->pArgs->rdp.szPassword );
  5767. lstrcpyn(
  5768. pInfo->pArgs->pNoUser->szPassword,
  5769. pInfo->pArgs->rdp.szPassword,
  5770. PWLEN + 1);
  5771. EncodePassword( pInfo->pArgs->rdp.szPassword );
  5772. EncodePassword( pInfo->pArgs->pNoUser->szPassword );
  5773. *pInfo->pArgs->pfNoUserChanged = TRUE;
  5774. }
  5775. // The old password (in text form) is explicitly set, since in AutoLogon
  5776. // case a text form has not yet been specified. The old password in text
  5777. // form is required to change the password. The "old" private API expects
  5778. // an ANSI argument.
  5779. //
  5780. if (!fSuppliedOldPassword)
  5781. {
  5782. // Whistler bug 254385 encode password when not being used
  5783. // Assumed password was encoded by ChangePasswordDlg()
  5784. //
  5785. CHAR* pszOldPasswordA;
  5786. DecodePassword( szOldPassword );
  5787. pszOldPasswordA = StrDupAFromT( szOldPassword );
  5788. if (pszOldPasswordA)
  5789. {
  5790. ASSERT( g_pRasSetOldPassword );
  5791. g_pRasSetOldPassword( pInfo->hrasconn, pszOldPasswordA );
  5792. ZeroMemory( pszOldPasswordA, lstrlenA( pszOldPasswordA ) );
  5793. Free( pszOldPasswordA );
  5794. }
  5795. }
  5796. ZeroMemory( szOldPassword, sizeof(szOldPassword) );
  5797. if (pInfo->pArgs->rdp.szUserName[ 0 ] == TEXT('\0'))
  5798. {
  5799. // Explicitly set the username, effectively turning off AutoLogon for
  5800. // the "resume" password authentication, where the new password should
  5801. // be used.
  5802. //
  5803. lstrcpyn( pInfo->pArgs->rdp.szUserName, GetLogonUser(), UNLEN + 1 );
  5804. }
  5805. pState->sidState = 0;
  5806. return TRUE;
  5807. }
  5808. BOOL
  5809. DpProjected(
  5810. IN DPINFO* pInfo,
  5811. IN DPSTATE* pState )
  5812. // RASCS_Projected state handling. 'PInfo' is the dialog context.
  5813. // 'PState' is the subentry state.
  5814. //
  5815. // Returns true if successful, false otherwise.
  5816. //
  5817. {
  5818. DWORD dwErr;
  5819. RASAMB amb;
  5820. RASPPPNBF nbf;
  5821. RASPPPIPX ipx;
  5822. RASPPPIP ip;
  5823. RASPPPLCP lcp;
  5824. RASSLIP slip;
  5825. RASPPPCCP ccp;
  5826. BOOL fIncomplete;
  5827. DWORD dwfProtocols;
  5828. TCHAR* pszLines;
  5829. TRACE( "DpProjected" );
  5830. pState->sidState = SID_S_Projected;
  5831. //
  5832. // If PORT_NOT_OPEN is indicated, it probably means that the
  5833. // server disconnected the connection before result dialog
  5834. // was dismissed. In that case, this is the 2nd time DpProjected
  5835. // is called. This time, the error is indicated by ras and the
  5836. // state remains "projected".
  5837. //
  5838. // We need to return an error in this case so that the connection
  5839. // isn't hung since this is the last indication RAS will give us.
  5840. //
  5841. // See bug 382254
  5842. //
  5843. TRACE1("DpProjected: dwErr:(%d)", pState->dwError);
  5844. if ( (pState->dwError == ERROR_PORT_NOT_OPEN) ||
  5845. (pState->dwError == ERROR_NO_CONNECTION) ) //See bug 169111 whistler
  5846. {
  5847. return FALSE;
  5848. }
  5849. // Do this little dance to ignore the error that comes back from the
  5850. // "all-failed" projection since we detect this in the earlier
  5851. // notification where pState->dwError == 0. This avoids a race where the
  5852. // API comes back with the error before we can hang him up. This race
  5853. // would not occur if we called RasHangUp from within the callback thread
  5854. // (as recommended in our API doc). It's the price we pay for posting the
  5855. // error to the other thread in order to avoid holding the port open while
  5856. // an error dialog is up.
  5857. //
  5858. else if (pState->dwError != 0)
  5859. {
  5860. pState->dwError = 0;
  5861. DpCallbacksFlag( pInfo, 0 );
  5862. return TRUE;
  5863. }
  5864. // Read projection info for all protocols, translating "not requested"
  5865. // into an in-structure code for later reference.
  5866. //
  5867. dwErr = GetRasProjectionInfo(
  5868. pState->hrasconnLink, &amb, &nbf, &ip, &ipx, &lcp, &slip, &ccp );
  5869. if (dwErr != 0)
  5870. {
  5871. ErrorDlg( pInfo->hwndDlg, SID_OP_RasGetProtocolInfo, dwErr, NULL );
  5872. return FALSE;
  5873. }
  5874. if (amb.dwError != ERROR_PROTOCOL_NOT_CONFIGURED)
  5875. {
  5876. // It's an AMB projection.
  5877. //
  5878. if (amb.dwError != 0)
  5879. {
  5880. // Translate AMB projection errors into regular error codes. AMB
  5881. // does not use the special PPP projection error mechanism.
  5882. //
  5883. pState->dwError = amb.dwError;
  5884. lstrcpyn(
  5885. pState->szExtendedError,
  5886. amb.szNetBiosError,
  5887. sizeof(pState->szExtendedError) / sizeof(TCHAR));
  5888. }
  5889. return TRUE;
  5890. }
  5891. // At this point, all projection information has been gathered
  5892. // successfully and we know it's a PPP-based projection. Now analyze the
  5893. // projection results...
  5894. //
  5895. dwfProtocols = 0;
  5896. fIncomplete = FALSE;
  5897. if (DpProjectionError(
  5898. &nbf, &ipx, &ip,
  5899. &fIncomplete, &dwfProtocols, &pszLines, &pState->dwError ))
  5900. {
  5901. // A projection error occurred.
  5902. //
  5903. if (fIncomplete)
  5904. {
  5905. BOOL fStatus;
  5906. BOOL fDisable;
  5907. // An incomplete projection occurred, i.e. some requested CPs
  5908. // connected and some did not. Ask the user if what worked is
  5909. // good enough or he wants to bail.
  5910. //
  5911. pState->dwError = 0;
  5912. fDisable = FALSE;
  5913. fStatus = ProjectionResultDlg(
  5914. pInfo->hwndDlg, pszLines, &fDisable );
  5915. Free( pszLines );
  5916. if (fDisable)
  5917. {
  5918. pInfo->pArgs->dwfExcludedProtocols = dwfProtocols;
  5919. }
  5920. // Return now if user chose to hang up.
  5921. //
  5922. if (!fStatus)
  5923. {
  5924. return FALSE;
  5925. }
  5926. }
  5927. else
  5928. {
  5929. // All CPs in the projection failed. Process as a regular fatal
  5930. // error with 'pState->dwError' set to the first error in NBF, IP,
  5931. // or IPX, but with a format that substitutes the status argument
  5932. // for the "Error nnn: Description" text. This lets us patch in
  5933. // the special multiple error projection text, while still giving
  5934. // a meaningful help context.
  5935. //
  5936. Free0( pState->pszFormatArg );
  5937. pState->pszFormatArg = pszLines;
  5938. pState->sidFormatMsg = SID_FMT_ErrorMsgProject;
  5939. }
  5940. }
  5941. //
  5942. // pmay: 190394
  5943. //
  5944. // If the admin has a message, display it.
  5945. //
  5946. if ( (pState->dwError == NO_ERROR) &&
  5947. (wcslen (lcp.szReplyMessage) != 0)
  5948. )
  5949. {
  5950. MSGARGS MsgArgs, *pMsgArgs = &MsgArgs;
  5951. ZeroMemory(pMsgArgs, sizeof(MSGARGS));
  5952. pMsgArgs->dwFlags = MB_OK | MB_ICONINFORMATION;
  5953. pMsgArgs->apszArgs[0] = lcp.szReplyMessage;
  5954. //MsgDlg(
  5955. // pInfo->hwndDlg,
  5956. // SID_ReplyMessageFmt,
  5957. // pMsgArgs);
  5958. }
  5959. pState->sidState = SID_S_Projected;
  5960. return TRUE;
  5961. }
  5962. BOOL
  5963. DpProjectionError(
  5964. IN RASPPPNBF* pnbf,
  5965. IN RASPPPIPX* pipx,
  5966. IN RASPPPIP* pip,
  5967. OUT BOOL* pfIncomplete,
  5968. OUT DWORD* pdwfFailedProtocols,
  5969. OUT TCHAR** ppszLines,
  5970. OUT DWORD* pdwError )
  5971. // Figure out if a projection error occurred and, if so, build the
  5972. // appropriate status/error text lines into '*ppszLines'. '*PfIncomlete'
  5973. // is set true if at least one CP succeeded and at least one failed.
  5974. // '*pdwfFailedProtocols' is set to the bit mask of NP_* that failed.
  5975. // '*pdwError' is set to the first error that occurred in NBF, IP, or IPX
  5976. // in that order or 0 if none. 'pnbf', 'pipx', and 'pip' are projection
  5977. // information for the respective protocols with dwError set to
  5978. // ERROR_PROTOCOL_NOT_CONFIGURED if the protocols was not requested.
  5979. //
  5980. // This routine assumes that at least one protocol was requested.
  5981. //
  5982. // Returns true if a projection error occurred, false if not. It's
  5983. // caller's responsiblity to free '*ppszLines'.
  5984. //
  5985. {
  5986. #define MAXPROJERRLEN 1024
  5987. TCHAR szLines[ MAXPROJERRLEN ];
  5988. BOOL fIp = (pip->dwError != ERROR_PROTOCOL_NOT_CONFIGURED);
  5989. BOOL fIpx = (pipx->dwError != ERROR_PROTOCOL_NOT_CONFIGURED);
  5990. BOOL fNbf = (pnbf->dwError != ERROR_PROTOCOL_NOT_CONFIGURED);
  5991. BOOL fIpBad = (fIp && pip->dwError != 0);
  5992. BOOL fIpxBad = (fIpx && pipx->dwError != 0);
  5993. BOOL fNbfBad = (fNbf && pnbf->dwError != 0);
  5994. TRACE( "DpProjectionError" );
  5995. *pdwfFailedProtocols = 0;
  5996. if (!fNbfBad && !fIpxBad && !fIpBad)
  5997. {
  5998. return FALSE;
  5999. }
  6000. if (fNbfBad)
  6001. {
  6002. *pdwfFailedProtocols |= NP_Nbf;
  6003. }
  6004. if (fIpxBad)
  6005. {
  6006. *pdwfFailedProtocols |= NP_Ipx;
  6007. }
  6008. if (fIpBad)
  6009. {
  6010. *pdwfFailedProtocols |= NP_Ip;
  6011. }
  6012. *pfIncomplete =
  6013. ((fIp && pip->dwError == 0)
  6014. || (fIpx && pipx->dwError == 0)
  6015. || (fNbf && pnbf->dwError == 0));
  6016. szLines[ 0 ] = 0;
  6017. *ppszLines = NULL;
  6018. *pdwError = 0;
  6019. if (fIpBad || (*pfIncomplete && fIp))
  6020. {
  6021. if (fIpBad)
  6022. {
  6023. *pdwError = pip->dwError;
  6024. DpAppendConnectErrorLine( szLines, SID_Ip, pip->dwError );
  6025. }
  6026. else
  6027. {
  6028. DpAppendConnectOkLine( szLines, SID_Ip );
  6029. }
  6030. DpAppendBlankLine( szLines );
  6031. }
  6032. if (fIpxBad || (*pfIncomplete && fIpx))
  6033. {
  6034. if (fIpxBad)
  6035. {
  6036. *pdwError = pipx->dwError;
  6037. DpAppendConnectErrorLine( szLines, SID_Ipx, pipx->dwError );
  6038. }
  6039. else
  6040. {
  6041. DpAppendConnectOkLine( szLines, SID_Ipx );
  6042. }
  6043. DpAppendBlankLine( szLines );
  6044. }
  6045. if (fNbfBad || (*pfIncomplete && fNbf))
  6046. {
  6047. if (fNbfBad)
  6048. {
  6049. *pdwError = pnbf->dwError;
  6050. DpAppendConnectErrorLine( szLines, SID_Nbf, pnbf->dwError );
  6051. if (pnbf->dwNetBiosError)
  6052. {
  6053. DpAppendFailCodeLine( szLines, pnbf->dwNetBiosError );
  6054. }
  6055. if (pnbf->szNetBiosError[ 0 ] != '\0')
  6056. {
  6057. DpAppendNameLine( szLines, pnbf->szNetBiosError );
  6058. }
  6059. }
  6060. else
  6061. {
  6062. DpAppendConnectOkLine( szLines, SID_Nbf );
  6063. }
  6064. DpAppendBlankLine( szLines );
  6065. }
  6066. *ppszLines = StrDup( szLines );
  6067. return TRUE;
  6068. }
  6069. DWORD WINAPI
  6070. DpRasDialFunc2(
  6071. ULONG_PTR dwCallbackId,
  6072. DWORD dwSubEntry,
  6073. HRASCONN hrasconn,
  6074. UINT unMsg,
  6075. RASCONNSTATE state,
  6076. DWORD dwError,
  6077. DWORD dwExtendedError )
  6078. // RASDIALFUNC2 callback to receive RasDial events.
  6079. //
  6080. // Returns 0 to stop callbacks, 1 to continue callbacks (normal), and 2 to
  6081. // tell RAS API that relevant entry information (like SLIP IP address) has
  6082. // changed.
  6083. //
  6084. {
  6085. DWORD dwErr;
  6086. DWORD dwCode;
  6087. DPINFO* pInfo;
  6088. DPSTATE* pState;
  6089. BOOL fTerminateAsap;
  6090. TRACE4( "/DpRasDialFunc2(rcs=%d,s=%d,e=%d,x=%d)",
  6091. state, dwSubEntry, dwError, dwExtendedError );
  6092. pInfo = (DPINFO* )dwCallbackId;
  6093. if (pInfo->dwValid != 0xC0BBC0DE)
  6094. {
  6095. TRACE( "DpRasDialFunc2 returns for Late callback?" );
  6096. return 0;
  6097. }
  6098. if (dwSubEntry == 0 || dwSubEntry > pInfo->cStates)
  6099. {
  6100. TRACE( "DpRasDialFunc2 returns for Subentry out of range?" );
  6101. return 1;
  6102. }
  6103. pState = &pInfo->pStates[ dwSubEntry - 1 ];
  6104. pState->state = state;
  6105. pState->dwError = dwError;
  6106. pState->dwExtendedError = dwExtendedError;
  6107. // Post the event to the Dial Progress window and wait for it to be
  6108. // processed before returning. This avoids subtle problems with Z-order
  6109. // and focus when a window is manipulated from two different threads.
  6110. //
  6111. TRACE1("Send RasEvent to Dial Progress window, subEntry:(%d)", dwSubEntry);
  6112. TRACE1("Get dwError=(%d) from RasMan",pState->dwError);
  6113. TRACE2("DpRasDialFunc2:Process:(%x),Thread(%x)",
  6114. GetCurrentProcessId,
  6115. GetCurrentThreadId);
  6116. TRACE2("DpRasDialFunc2:pInfo address (0x%x), Dialog Handle (0x%x)",
  6117. pInfo,
  6118. pInfo->hwndDlg);
  6119. dwCode = (DWORD)SendMessage( pInfo->hwndDlg, WM_RASEVENT, dwSubEntry, 0 );
  6120. TRACE1( "\\DpRasDialFunc2: dwCode from SendMessage()=%d", dwCode );
  6121. TRACE1("dwCode returned:(%d)", dwCode);
  6122. // When callback function DpRasDialFunc2() returns 0, then RasMan wont
  6123. //call it again, so we wont return 0 unless all the message returned from
  6124. //RasMan has been processed for whislter bug 291613 gangz
  6125. //
  6126. {
  6127. long ulCallbacksActive;
  6128. //Check if current thread wants to terminate itself
  6129. //
  6130. ulCallbacksActive = DpOnOffPerThreadTerminateFlag(pInfo, -1, &fTerminateAsap );
  6131. TRACE1("Current thread's active:(%d)", ulCallbacksActive);
  6132. if ( fTerminateAsap )
  6133. {
  6134. //decrease pInfo->ulCallbacksActive and g_ulCallbacksActive
  6135. //if necessary
  6136. //
  6137. TRACE("Current Thread wants to terminate itself, its fterminateASSP=1!");
  6138. TRACE("Current thread will decrease its own and global active!");
  6139. DpCallbacksFlag( pInfo, 0 );
  6140. //reset per-thread terminateASAP flag
  6141. //
  6142. DpOnOffPerThreadTerminateFlag(pInfo, 0, NULL );
  6143. }
  6144. else
  6145. {
  6146. TRACE("Current Thread does NOT want to terminate itself,its fterminateASAP=0!");
  6147. }
  6148. //return the global number of active callbacks
  6149. //
  6150. ulCallbacksActive = CallbacksActive( -1, NULL );
  6151. TRACE1( "\\DpRasDialFunc2:g_ulCallbacksActive=%ld", ulCallbacksActive );
  6152. //if g_ulCallbacksActive is already zero, we must return 0 to RasMan
  6153. //
  6154. {
  6155. TRACE1("Global active:(%d)", ulCallbacksActive);
  6156. TRACE1("Current thread's active:(%d)",
  6157. DpOnOffPerThreadTerminateFlag(pInfo, -1, NULL ) );
  6158. }
  6159. if ( 0 == ulCallbacksActive )
  6160. {
  6161. if ( 0 == DpOnOffPerThreadTerminateFlag(pInfo, -1, NULL ) )
  6162. {
  6163. TRACE( "Will terminate Callbacks " );
  6164. dwCode = 0;
  6165. }
  6166. else
  6167. {
  6168. //For whistler bug 341662 366237 gangz
  6169. //Something messed up the g_ulCallbacksActive flag
  6170. // Now that g_ulCallbacksActive is 0, DpCallbacksFlag( pInfo, 0 ) wont
  6171. // decrease it now, it only decrease pInfo->ulCallbacksActive by 1
  6172. TRACE("ReSync accured!");
  6173. DpCallbacksFlag( pInfo, 0 );
  6174. //then call DpCallbacksFlag( pInfo, 1 ); to increase both the global
  6175. // callbacks active flag g_ulCallbacksActive and per thread
  6176. // pInfo->ulCallbacksActive
  6177. //
  6178. DpCallbacksFlag( pInfo, 1 );
  6179. }
  6180. }
  6181. else if ( 0 == dwCode )
  6182. {
  6183. //Other callbacks are still active, wait for them
  6184. //
  6185. dwCode = 1;
  6186. //Clear current pInfo->ulCallbacksActive if necessary when
  6187. //this dwCode is returned by SendMessage() at above
  6188. //
  6189. TRACE("Other callbacks are still active, wait for them");
  6190. TRACE("Just Clear current pInfo->ulCallbacksActive\n");
  6191. DpCallbacksFlag( pInfo, 0 );
  6192. //After cleared current pInfo->ulCallbacksActive, if the number
  6193. //of active callbacks becomes zero, then we should return 0 to RasMan
  6194. //
  6195. ulCallbacksActive = CallbacksActive( -1, &fTerminateAsap );
  6196. TRACE1( "\\DpRasDialFunc2:g_ulCallbacksActive after clearing cur-thread =%ld", ulCallbacksActive );
  6197. if ( 0 == ulCallbacksActive )
  6198. {
  6199. TRACE( "Will terminate Callbacks " );
  6200. dwCode = 0;
  6201. }
  6202. }
  6203. }
  6204. if (dwCode == 0)
  6205. {
  6206. // Set thread-safe flag indicating callbacks have terminated.
  6207. //
  6208. DpCallbacksFlag( pInfo, 0 );
  6209. }
  6210. // Note: If 'dwCode' is 0, the other thread is racing to terminate the
  6211. // dialog. Must not dereference 'pInfo' in this case.
  6212. TRACE1( "\\DpRasDialFunc2:final dwCode returned=%d", dwCode );
  6213. return dwCode;
  6214. }
  6215. VOID
  6216. DpTerm(
  6217. IN HWND hwndDlg )
  6218. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  6219. //
  6220. {
  6221. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  6222. TRACE( "DpTerm" );
  6223. if (pInfo)
  6224. {
  6225. if (pInfo->pOldWndProc)
  6226. {
  6227. SetWindowLongPtr( pInfo->hwndDlg,
  6228. GWLP_WNDPROC, (ULONG_PTR )pInfo->pOldWndProc );
  6229. }
  6230. Free0( pInfo->pStates );
  6231. pInfo->dwValid = 0;
  6232. Free( pInfo );
  6233. }
  6234. //For whistler bug 372078 gangz
  6235. //
  6236. {
  6237. HICON hIcon=NULL;
  6238. hIcon = (HICON)SendMessage( GetDlgItem( hwndDlg, CID_DP_Icon ),
  6239. STM_GETICON,
  6240. 0,
  6241. 0);
  6242. ASSERT(hIcon);
  6243. if( hIcon )
  6244. {
  6245. DestroyIcon(hIcon);
  6246. }
  6247. else
  6248. {
  6249. TRACE("DpTerm:Destroy Icon failed");
  6250. }
  6251. }
  6252. }
  6253. LRESULT APIENTRY
  6254. DpWndProc(
  6255. HWND hwnd,
  6256. UINT unMsg,
  6257. WPARAM wParam,
  6258. LPARAM lParam )
  6259. // Subclassed dialog window procedure.
  6260. //
  6261. {
  6262. DPINFO* pInfo = (DPINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  6263. ASSERT( pInfo );
  6264. if (unMsg == WM_RASEVENT)
  6265. {
  6266. return DpEvent( pInfo, (DWORD )wParam );
  6267. }
  6268. return
  6269. CallWindowProc(
  6270. pInfo->pOldWndProc, hwnd, unMsg, wParam, lParam );
  6271. }
  6272. //----------------------------------------------------------------------------
  6273. // Dialer dialogs
  6274. // Listed alphabetically following stub API and dialog proc
  6275. //----------------------------------------------------------------------------
  6276. BOOL
  6277. DialerDlg(
  6278. IN HWND hwndOwner,
  6279. IN OUT DINFO* pInfo )
  6280. // Determine if it's necessary, and if so, popup one of the variations of
  6281. // the dialer dialog, i.e. the prompter for user/password/domain, phone
  6282. // number, and location. 'HwndOwner' is the owning window. 'PInfo' is
  6283. // the dial dialog common context.
  6284. //
  6285. // Returns true if no dialog is needed or user chooses OK.
  6286. //
  6287. {
  6288. INT_PTR nStatus = FALSE;
  6289. int nDid;
  6290. DWORD dwfMode;
  6291. DRARGS args;
  6292. TRACE( "DialerDlg" );
  6293. do
  6294. {
  6295. dwfMode = 0;
  6296. if (!pInfo->pEntry->fAutoLogon
  6297. && pInfo->pEntry->fPreviewUserPw
  6298. && (!(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt)
  6299. || (pInfo->fUnattended && !HaveSavedPw( pInfo ))))
  6300. {
  6301. dwfMode |= DR_U;
  6302. if (pInfo->pEntry->fPreviewDomain)
  6303. {
  6304. dwfMode |= DR_D;
  6305. }
  6306. }
  6307. if (pInfo->pEntry->fPreviewPhoneNumber
  6308. && (!(pInfo->pArgs->dwFlags & RASDDFLAG_NoPrompt)
  6309. || (pInfo->fUnattended && !HaveSavedPw( pInfo ))))
  6310. {
  6311. DTLNODE* pNode;
  6312. PBLINK* pLink;
  6313. dwfMode |= DR_N;
  6314. // Location controls mode only when at least one phone number in
  6315. // the list is TAPI-enabled.
  6316. //
  6317. pNode = DtlGetFirstNode( pInfo->pEntry->pdtllistLinks );
  6318. pLink = (PBLINK* )DtlGetData( pNode );
  6319. for (pNode = DtlGetFirstNode( pLink->pdtllistPhones );
  6320. pNode;
  6321. pNode = DtlGetNextNode( pNode ))
  6322. {
  6323. PBPHONE* pPhone = (PBPHONE* )DtlGetData( pNode );
  6324. if (pPhone->fUseDialingRules)
  6325. {
  6326. dwfMode |= DR_L;
  6327. break;
  6328. }
  6329. }
  6330. }
  6331. // Customize the dialing flags for the type of eap authentication
  6332. // specified for this entry (if any)
  6333. if (DialerEapAssignMode(pInfo, &dwfMode) != NO_ERROR)
  6334. break;
  6335. if (dwfMode == DR_U)
  6336. {
  6337. nDid = DID_DR_DialerU;
  6338. }
  6339. else if (dwfMode == (DR_U | DR_D))
  6340. {
  6341. nDid = DID_DR_DialerUD;
  6342. }
  6343. else if (dwfMode == (DR_U | DR_N))
  6344. {
  6345. nDid = DID_DR_DialerUN;
  6346. }
  6347. else if (dwfMode == (DR_U | DR_N | DR_L))
  6348. {
  6349. nDid = DID_DR_DialerUNL;
  6350. }
  6351. else if (dwfMode == (DR_U | DR_D | DR_N))
  6352. {
  6353. nDid = DID_DR_DialerUDN;
  6354. }
  6355. else if (dwfMode == (DR_U | DR_D | DR_N | DR_L))
  6356. {
  6357. nDid = DID_DR_DialerUDNL;
  6358. }
  6359. else if (dwfMode == DR_N)
  6360. {
  6361. nDid = DID_DR_DialerN;
  6362. }
  6363. else if (dwfMode == (DR_N | DR_L))
  6364. {
  6365. nDid = DID_DR_DialerNL;
  6366. }
  6367. else if (dwfMode == DR_I) {
  6368. nDid = DID_DR_DialerI;
  6369. }
  6370. else if (dwfMode == (DR_I | DR_N)) {
  6371. nDid = DID_DR_DialerIN;
  6372. }
  6373. else if (dwfMode == (DR_I | DR_N | DR_L)) {
  6374. nDid = DID_DR_DialerINL;
  6375. }
  6376. // pmay: The following 3 permutations of the
  6377. // dialer dialog were added for bug 183577 which
  6378. // states that eap modules (that use DR_I) want to
  6379. // have the domain field available to them as well.
  6380. else if (dwfMode == (DR_I | DR_D)) {
  6381. nDid = DID_DR_DialerID;
  6382. }
  6383. else if (dwfMode == (DR_I | DR_D | DR_N)) {
  6384. nDid = DID_DR_DialerIDN;
  6385. }
  6386. else if (dwfMode == (DR_I | DR_D | DR_N | DR_L)) {
  6387. nDid = DID_DR_DialerIDNL;
  6388. }
  6389. else
  6390. {
  6391. ASSERT( dwfMode == 0 );
  6392. return TRUE;
  6393. }
  6394. args.pDinfo = pInfo;
  6395. args.dwfMode = dwfMode;
  6396. args.fReload = FALSE;
  6397. nStatus =
  6398. (BOOL )DialogBoxParam(
  6399. g_hinstDll,
  6400. MAKEINTRESOURCE( nDid ),
  6401. hwndOwner,
  6402. DrDlgProc,
  6403. (LPARAM )&args );
  6404. if (nStatus == -1)
  6405. {
  6406. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  6407. nStatus = FALSE;
  6408. }
  6409. }
  6410. while (args.fReload);
  6411. return (BOOL )nStatus;
  6412. }
  6413. INT_PTR CALLBACK
  6414. DrDlgProc(
  6415. IN HWND hwnd,
  6416. IN UINT unMsg,
  6417. IN WPARAM wparam,
  6418. IN LPARAM lparam )
  6419. // DialogProc callback for the dialer dialogs. Parameters and return
  6420. // value are as described for standard windows 'DialogProc's.
  6421. //
  6422. {
  6423. #if 0
  6424. TRACE4( "DrDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  6425. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  6426. #endif
  6427. switch (unMsg)
  6428. {
  6429. case WM_INITDIALOG:
  6430. {
  6431. return DrInit( hwnd, (DRARGS* )lparam );
  6432. }
  6433. case WM_HELP:
  6434. case WM_CONTEXTMENU:
  6435. {
  6436. ContextHelp( g_adwDrHelp, hwnd, unMsg, wparam, lparam );
  6437. break;
  6438. }
  6439. case WM_COMMAND:
  6440. {
  6441. DRINFO* pInfo = (DRINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  6442. ASSERT( pInfo );
  6443. return DrCommand(
  6444. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  6445. }
  6446. case WM_DESTROY:
  6447. {
  6448. DrTerm( hwnd );
  6449. break;
  6450. }
  6451. }
  6452. return FALSE;
  6453. }
  6454. VOID
  6455. DrGetFriendlyFont(
  6456. IN HWND hwnd,
  6457. IN BOOL fUpdate,
  6458. OUT HFONT* phFont )
  6459. // Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
  6460. // does not match the length of the password and causes confusion
  6461. //
  6462. {
  6463. LOGFONT BoldLogFont;
  6464. HFONT hFont;
  6465. HDC hdc;
  6466. *phFont = NULL;
  6467. // Get the font used by the specified window
  6468. //
  6469. hFont = (HFONT)SendMessage( hwnd, WM_GETFONT, 0, 0L );
  6470. if (NULL == hFont)
  6471. {
  6472. // If not found then the control is using the system font
  6473. //
  6474. hFont = (HFONT)GetStockObject( SYSTEM_FONT );
  6475. }
  6476. if (hFont && GetObject( hFont, sizeof(BoldLogFont), &BoldLogFont ))
  6477. {
  6478. if (fUpdate)
  6479. {
  6480. BoldLogFont.lfItalic = TRUE;
  6481. }
  6482. hdc = GetDC( hwnd );
  6483. if (hdc)
  6484. {
  6485. *phFont = CreateFontIndirect( &BoldLogFont );
  6486. ReleaseDC( hwnd, hdc );
  6487. }
  6488. }
  6489. return;
  6490. }
  6491. DWORD
  6492. DrEnableDisablePwControls(
  6493. IN DRINFO* pInfo,
  6494. IN BOOL fEnable )
  6495. {
  6496. if (pInfo->pArgs->pDinfo->fIsPublicPbk)
  6497. {
  6498. EnableWindow( pInfo->hwndRbSaveForEveryone, fEnable );
  6499. }
  6500. else
  6501. {
  6502. EnableWindow( pInfo->hwndRbSaveForEveryone, FALSE );
  6503. }
  6504. EnableWindow( pInfo->hwndRbSaveForMe, fEnable );
  6505. return NO_ERROR;
  6506. }
  6507. VOID
  6508. DrClearFriendlyPassword(
  6509. IN DRINFO* pInfo,
  6510. IN BOOL fFocus )
  6511. {
  6512. SetWindowText( pInfo->hwndEbPw, L"" );
  6513. if (fFocus)
  6514. {
  6515. SendMessage( pInfo->hwndEbPw, EM_SETPASSWORDCHAR,
  6516. pInfo->szPasswordChar, 0 );
  6517. if (pInfo->hNormalFont)
  6518. {
  6519. SendMessage(
  6520. pInfo->hwndEbPw,
  6521. WM_SETFONT,
  6522. (WPARAM)pInfo->hNormalFont,
  6523. MAKELPARAM(TRUE, 0) );
  6524. }
  6525. SetFocus( pInfo->hwndEbPw );
  6526. }
  6527. return;
  6528. }
  6529. VOID
  6530. DrDisplayFriendlyPassword(
  6531. IN DRINFO* pInfo,
  6532. IN TCHAR* pszFriendly )
  6533. {
  6534. if (pszFriendly)
  6535. {
  6536. SendMessage( pInfo->hwndEbPw, EM_SETPASSWORDCHAR, 0, 0 );
  6537. SetWindowText( pInfo->hwndEbPw, pszFriendly );
  6538. }
  6539. else
  6540. {
  6541. SetWindowText( pInfo->hwndEbPw, L"" );
  6542. }
  6543. if (pInfo->hItalicFont)
  6544. {
  6545. SendMessage(
  6546. pInfo->hwndEbPw,
  6547. WM_SETFONT,
  6548. (WPARAM)pInfo->hItalicFont,
  6549. MAKELPARAM(TRUE, 0) );
  6550. }
  6551. return;
  6552. }
  6553. BOOL
  6554. DrIsPasswordStyleEnabled(
  6555. IN HWND hWnd )
  6556. {
  6557. return SendMessage( hWnd, EM_GETPASSWORDCHAR, 0, 0 ) ? TRUE : FALSE;
  6558. }
  6559. BOOL
  6560. DrCommand(
  6561. IN DRINFO* pInfo,
  6562. IN WORD wNotification,
  6563. IN WORD wId,
  6564. IN HWND hwndCtrl )
  6565. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  6566. // is the notification code of the command. 'wId' is the control/menu
  6567. // identifier of the command. 'HwndCtrl' is the control window handle of
  6568. // the command.
  6569. //
  6570. // Returns true if processed message, false otherwise.
  6571. //
  6572. {
  6573. DWORD dwErr;
  6574. TRACE3( "DrCommand(n=%d,i=%d,c=$%x)",
  6575. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  6576. switch (wId)
  6577. {
  6578. case CID_DR_CLB_Numbers:
  6579. {
  6580. if (wNotification == CBN_SELCHANGE)
  6581. {
  6582. DrNumbersSelChange( pInfo );
  6583. return TRUE;
  6584. }
  6585. break;
  6586. }
  6587. case CID_DR_CB_SavePassword:
  6588. {
  6589. BOOL fEnable = Button_GetCheck( hwndCtrl );
  6590. DrEnableDisablePwControls( pInfo, fEnable );
  6591. DrPopulatePasswordField( pInfo, FALSE, FALSE );
  6592. return TRUE;
  6593. }
  6594. // Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
  6595. // does not match the length of the password and causes confusion
  6596. //
  6597. case CID_DR_EB_Password:
  6598. {
  6599. // This is a hack really so that we restore the Tab Stop to the
  6600. // username field. The reason it had to be removed was because we
  6601. // were receiving complaints that the focus shouldn't always go to
  6602. // the username field if it's non-null. The only way to fix this,
  6603. // since windows sets the initial focus to the first visible non-
  6604. // hidden tab stopped field, is to remove the tab stop temporarily
  6605. // from the username field.
  6606. //
  6607. if (wNotification == EN_KILLFOCUS)
  6608. {
  6609. LONG lStyle = GetWindowLong( pInfo->hwndEbUser, GWL_STYLE );
  6610. if (!(lStyle & WS_TABSTOP))
  6611. {
  6612. // If we detect tap stop removed from the username field,
  6613. // restore it. Since this case only fires when the password
  6614. // was not previously saved on init, we can return here.
  6615. //
  6616. SetWindowLong( pInfo->hwndEbUser, GWL_STYLE,
  6617. lStyle | WS_TABSTOP );
  6618. return TRUE;
  6619. }
  6620. // If the user leaves the password field w/o typing a new
  6621. // password, and a saved password is present, restore the
  6622. // friendly password text.
  6623. //
  6624. DrPopulatePasswordField( pInfo, FALSE, FALSE );
  6625. return TRUE;
  6626. }
  6627. // If the password field ever receives the focus, clear the
  6628. // friendly password text if applicable.
  6629. //
  6630. else if (wNotification == EN_SETFOCUS &&
  6631. !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))
  6632. {
  6633. DrPopulatePasswordField( pInfo, FALSE, TRUE );
  6634. return TRUE;
  6635. }
  6636. break;
  6637. }
  6638. case CID_DR_LB_Locations:
  6639. {
  6640. if (wNotification == CBN_SELCHANGE)
  6641. {
  6642. DrLocationsSelChange( pInfo );
  6643. return TRUE;
  6644. }
  6645. break;
  6646. }
  6647. case CID_DR_PB_Rules:
  6648. {
  6649. DrEditSelectedLocation( pInfo );
  6650. return TRUE;
  6651. }
  6652. case CID_DR_PB_Properties:
  6653. {
  6654. DrProperties( pInfo );
  6655. DrPopulatePasswordField( pInfo, FALSE, FALSE );
  6656. return TRUE;
  6657. }
  6658. case CID_DR_RB_SaveForMe:
  6659. case CID_DR_RB_SaveForEveryone:
  6660. {
  6661. DrPopulatePasswordField( pInfo, FALSE, FALSE );
  6662. DrPopulateIdentificationFields( pInfo, (wId == CID_DR_RB_SaveForMe));
  6663. return TRUE;
  6664. }
  6665. case IDOK:
  6666. case CID_DR_PB_DialConnect:
  6667. {
  6668. DrSave( pInfo );
  6669. EndDialog( pInfo->hwndDlg, TRUE );
  6670. return TRUE;
  6671. }
  6672. case IDCANCEL:
  6673. case CID_DR_PB_Cancel:
  6674. {
  6675. EndDialog( pInfo->hwndDlg, FALSE );
  6676. return TRUE;
  6677. }
  6678. case IDHELP:
  6679. case CID_DR_PB_Help:
  6680. {
  6681. TCHAR* pszCmdLine;
  6682. // Help button now invokes troubleshooting help per bug 210247.
  6683. //
  6684. pszCmdLine = PszFromId( g_hinstDll, SID_DialerHelpCmdLine );
  6685. if (pszCmdLine)
  6686. {
  6687. STARTUPINFO sInfo;
  6688. PROCESS_INFORMATION pInfo;
  6689. ZeroMemory( &sInfo, sizeof(sInfo) );
  6690. sInfo.cb = sizeof(sInfo);
  6691. ZeroMemory( &pInfo, sizeof(pInfo) );
  6692. CreateProcess(
  6693. NULL, pszCmdLine, NULL, NULL, FALSE,
  6694. 0, NULL, NULL, &sInfo, &pInfo );
  6695. Free( pszCmdLine );
  6696. }
  6697. return TRUE;
  6698. }
  6699. }
  6700. return FALSE;
  6701. }
  6702. BOOL CALLBACK
  6703. DrClbNumbersEnumChildProc(
  6704. IN HWND hwnd,
  6705. IN LPARAM lparam )
  6706. // Standard Windows EnumChildProc routine called back for each child
  6707. // window of the 'ClbNumbers' control.
  6708. //
  6709. {
  6710. DRINFO* pInfo;
  6711. LONG lId;
  6712. pInfo = (DRINFO* )lparam;
  6713. // There only one child window and it's the edit window.
  6714. //
  6715. pInfo->hwndClbNumbersEb = hwnd;
  6716. return FALSE;
  6717. }
  6718. BOOL CALLBACK
  6719. DrClbNumbersEnumWindowsProc(
  6720. IN HWND hwnd,
  6721. IN LPARAM lparam )
  6722. // Standard Windows EnumWindowsProc routine called back for each top-level
  6723. // window.
  6724. //
  6725. {
  6726. RECT rect;
  6727. GetWindowRect( hwnd, &rect );
  6728. if (rect.right - rect.left == DR_BOGUSWIDTH)
  6729. {
  6730. // This window has the unusual bogus width, so it must be the
  6731. // list-box.
  6732. //
  6733. ((DRINFO* )lparam)->hwndClbNumbersLb = hwnd;
  6734. return FALSE;
  6735. }
  6736. return TRUE;
  6737. }
  6738. LRESULT APIENTRY
  6739. DrClbNumbersEbWndProc(
  6740. HWND hwnd,
  6741. UINT unMsg,
  6742. WPARAM wParam,
  6743. LPARAM lParam )
  6744. // Subclassed combo-box edit-box child window procedure providing "manual
  6745. // edit" behavior.
  6746. //
  6747. // Return value depends on message type.
  6748. //
  6749. {
  6750. DRINFO* pInfo;
  6751. switch (unMsg)
  6752. {
  6753. case WM_SETTEXT:
  6754. {
  6755. // Prevent the combo-box from setting the contents of the edit box
  6756. // by discarding the request and reporting success.
  6757. //
  6758. return TRUE;
  6759. }
  6760. case DR_WM_SETTEXT:
  6761. {
  6762. // Convert our private SETTEXT to a regular SETTEXT and pass it on
  6763. // to the edit control.
  6764. //
  6765. unMsg = WM_SETTEXT;
  6766. break;
  6767. }
  6768. }
  6769. // Call the previous window procedure for everything else.
  6770. //
  6771. pInfo = (DRINFO* )GetProp( hwnd, g_contextId );
  6772. ASSERT( pInfo );
  6773. return
  6774. CallWindowProc(
  6775. pInfo->wndprocClbNumbersEb, hwnd, unMsg, wParam, lParam );
  6776. }
  6777. LRESULT APIENTRY
  6778. DrClbNumbersLbWndProc(
  6779. HWND hwnd,
  6780. UINT unMsg,
  6781. WPARAM wParam,
  6782. LPARAM lParam )
  6783. // Subclassed combo-box list-box child window procedure providing "manual
  6784. // edit" behavior.
  6785. //
  6786. // Return value depends on message type.
  6787. //
  6788. {
  6789. DRINFO* pInfo;
  6790. pInfo = (DRINFO* )GetProp( hwnd, g_contextId );
  6791. ASSERT( pInfo );
  6792. switch (unMsg)
  6793. {
  6794. case LB_FINDSTRINGEXACT:
  6795. case LB_FINDSTRING:
  6796. {
  6797. // This prevents the edit-box "completion" behavior of the
  6798. // combo-box, i.e. it prevents the edit-box contents from being
  6799. // extended to the closest match in the list.
  6800. //
  6801. return -1;
  6802. }
  6803. case LB_SETCURSEL:
  6804. case LB_SETTOPINDEX:
  6805. {
  6806. // Prevent the "match selection to edit-box" combo-box behavior by
  6807. // discarding any attempts to set the selection or top index to
  6808. // anything other than what we set.
  6809. //
  6810. if (wParam != pInfo->pLink->iLastSelectedPhone)
  6811. {
  6812. return -1;
  6813. }
  6814. break;
  6815. }
  6816. }
  6817. // Call the previous window procedure for everything else.
  6818. //
  6819. return
  6820. CallWindowProc(
  6821. pInfo->wndprocClbNumbersLb, hwnd, unMsg, wParam, lParam );
  6822. }
  6823. VOID
  6824. DrEditSelectedLocation(
  6825. IN DRINFO* pInfo )
  6826. // Called when the Dialing Rules button is pressed. 'PInfo' is the dialog
  6827. // context.
  6828. //
  6829. {
  6830. DWORD dwErr;
  6831. INT iSel;
  6832. DRNUMBERSITEM* pItem;
  6833. TRACE( "DrEditSelectedLocation" );
  6834. // Look up the phone number information for the selected number.
  6835. //
  6836. pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr(
  6837. pInfo->hwndClbNumbers, ComboBox_GetCurSel( pInfo->hwndClbNumbers ) );
  6838. ASSERT( pItem );
  6839. if(NULL == pItem)
  6840. {
  6841. return;
  6842. }
  6843. ASSERT( pItem->pPhone->fUseDialingRules );
  6844. // Popup TAPI dialing rules dialog.
  6845. //
  6846. dwErr = TapiLocationDlg(
  6847. g_hinstDll,
  6848. &pInfo->hlineapp,
  6849. pInfo->hwndDlg,
  6850. pItem->pPhone->dwCountryCode,
  6851. pItem->pPhone->pszAreaCode,
  6852. pItem->pPhone->pszPhoneNumber,
  6853. 0 );
  6854. if (dwErr != 0)
  6855. {
  6856. ErrorDlg( pInfo->hwndDlg, SID_OP_LoadTapiInfo, dwErr, NULL );
  6857. }
  6858. // Might have changed the location list so re-fill it.
  6859. //
  6860. DrFillLocationList( pInfo );
  6861. }
  6862. DWORD
  6863. DrFillLocationList(
  6864. IN DRINFO* pInfo )
  6865. // Fills the dropdown list of locations and sets the current selection.
  6866. //
  6867. // Returns 0 if successful, or an error code.
  6868. //
  6869. {
  6870. DWORD dwErr;
  6871. LOCATION* pLocations;
  6872. LOCATION* pLocation;
  6873. DWORD cLocations;
  6874. DWORD dwCurLocation;
  6875. DWORD i;
  6876. TRACE( "DrFillLocationList" );
  6877. ComboBox_ResetContent( pInfo->hwndLbLocations );
  6878. pLocations = NULL;
  6879. cLocations = 0;
  6880. dwCurLocation = 0xFFFFFFFF;
  6881. dwErr = GetLocationInfo(
  6882. g_hinstDll, &pInfo->hlineapp,
  6883. &pLocations, &cLocations, &dwCurLocation );
  6884. if (dwErr != 0)
  6885. {
  6886. return dwErr;
  6887. }
  6888. for (i = 0, pLocation = pLocations;
  6889. i < cLocations;
  6890. ++i, ++pLocation)
  6891. {
  6892. INT iItem;
  6893. iItem = ComboBox_AddItem(
  6894. pInfo->hwndLbLocations, pLocation->pszName,
  6895. (VOID* )UlongToPtr(pLocation->dwId ));
  6896. if (pLocation->dwId == dwCurLocation)
  6897. {
  6898. ComboBox_SetCurSelNotify( pInfo->hwndLbLocations, iItem );
  6899. }
  6900. }
  6901. FreeLocationInfo( pLocations, cLocations );
  6902. ComboBox_AutoSizeDroppedWidth( pInfo->hwndLbLocations );
  6903. return dwErr;
  6904. }
  6905. VOID
  6906. DrFillNumbersList(
  6907. IN DRINFO* pInfo )
  6908. // Fill the "Dial" combo-box with phone numbers and comments, and
  6909. // re-select the selected item in the list, or if none, the last one
  6910. // selected as specified in the PBLINK.
  6911. //
  6912. {
  6913. DTLNODE* pNode;
  6914. PBLINK* pLink;
  6915. PBPHONE* pPhone;
  6916. INT cItems;
  6917. INT i;
  6918. DrFreeClbNumbers( pInfo );
  6919. for (pNode = DtlGetFirstNode( pInfo->pLink->pdtllistPhones ), i = 0;
  6920. pNode;
  6921. pNode = DtlGetNextNode( pNode ), ++i)
  6922. {
  6923. TCHAR szBuf[ RAS_MaxPhoneNumber + RAS_MaxDescription + 3 + 1 ];
  6924. DRNUMBERSITEM* pItem;
  6925. pPhone = (PBPHONE* )DtlGetData( pNode );
  6926. ASSERT( pPhone );
  6927. pItem = Malloc( sizeof(DRNUMBERSITEM) );
  6928. if (!pItem)
  6929. {
  6930. break;
  6931. }
  6932. // Build the "<number> - <comment>" string in 'szBuf'.
  6933. //
  6934. pItem->pszNumber =
  6935. LinkPhoneNumberFromParts(
  6936. g_hinstDll, &pInfo->hlineapp,
  6937. pInfo->pArgs->pDinfo->pUser, pInfo->pArgs->pDinfo->pEntry,
  6938. pInfo->pLink, i, NULL, FALSE );
  6939. if (!pItem->pszNumber)
  6940. {
  6941. // Should not happen.
  6942. //
  6943. Free( pItem );
  6944. break;
  6945. }
  6946. lstrcpyn( szBuf, pItem->pszNumber, RAS_MaxPhoneNumber);
  6947. if (pPhone->pszComment && !IsAllWhite( pPhone->pszComment ))
  6948. {
  6949. DWORD dwLen, dwSize = sizeof(szBuf) / sizeof(TCHAR);
  6950. lstrcat( szBuf, TEXT(" - ") );
  6951. dwLen = lstrlen(szBuf) + 1;
  6952. lstrcpyn(
  6953. szBuf + (dwLen - 1),
  6954. pPhone->pszComment,
  6955. dwSize - dwLen );
  6956. }
  6957. pItem->pPhone = pPhone;
  6958. ComboBox_AddItem( pInfo->hwndClbNumbers, szBuf, pItem );
  6959. }
  6960. // Make the selection and trigger the update of the edit-box to the number
  6961. // without the comment.
  6962. //
  6963. cItems = ComboBox_GetCount( pInfo->hwndClbNumbers );
  6964. if (cItems > 0)
  6965. {
  6966. if ((INT )pInfo->pLink->iLastSelectedPhone >= cItems)
  6967. {
  6968. pInfo->pLink->iLastSelectedPhone = 0;
  6969. }
  6970. ListBox_SetTopIndex(
  6971. pInfo->hwndClbNumbersLb, pInfo->pLink->iLastSelectedPhone );
  6972. ComboBox_SetCurSelNotify(
  6973. pInfo->hwndClbNumbers, pInfo->pLink->iLastSelectedPhone );
  6974. }
  6975. ComboBox_AutoSizeDroppedWidth( pInfo->hwndClbNumbers );
  6976. }
  6977. VOID
  6978. DrFreeClbNumbers(
  6979. IN DRINFO* pInfo )
  6980. // Free up the displayable number string associated with each entry of the
  6981. // phone number combo-box leaving the box empty.
  6982. //
  6983. {
  6984. DRNUMBERSITEM* pItem;
  6985. while (pItem = ComboBox_GetItemDataPtr( pInfo->hwndClbNumbers, 0 ))
  6986. {
  6987. ComboBox_DeleteString( pInfo->hwndClbNumbers, 0 );
  6988. Free( pItem->pszNumber );
  6989. Free( pItem );
  6990. }
  6991. }
  6992. DWORD
  6993. DrFindAndSubclassClbNumbersControls(
  6994. IN DRINFO* pInfo )
  6995. // Locate and sub-class the edit-box and list-box child controls of the
  6996. // phone number combo-box. This is necessary to get "manual edit"
  6997. // behavior, i.e. prevent the combo-box from automatically updating the
  6998. // edit box at various times. We need this because the phone number
  6999. // comments are to be appended in the list, but not in the edit box.
  7000. // 'PInfo' is the dialog context.
  7001. //
  7002. // Returns 0 if successful or an error code.
  7003. //
  7004. {
  7005. DWORD dxOld;
  7006. // Find the edit window which is simply a child enumeration.
  7007. //
  7008. EnumChildWindows(
  7009. pInfo->hwndClbNumbers,
  7010. DrClbNumbersEnumChildProc,
  7011. (LPARAM)pInfo );
  7012. if (!pInfo->hwndClbNumbersEb)
  7013. {
  7014. return ERROR_NOT_FOUND;
  7015. }
  7016. // Find the list window which *sigh* doesn't show up in the child
  7017. // enumeration though it has WS_CHILD style because Windows sets it's
  7018. // parent window to NULL after it is created. To find it, we set the
  7019. // dropped width to an unusual bogus value, then search all windows for
  7020. // one with that width.
  7021. //
  7022. dxOld = (DWORD )SendMessage(
  7023. pInfo->hwndClbNumbers, CB_GETDROPPEDWIDTH, 0, 0 );
  7024. SendMessage( pInfo->hwndClbNumbers,
  7025. CB_SETDROPPEDWIDTH, (WPARAM )DR_BOGUSWIDTH, 0 );
  7026. EnumWindows( DrClbNumbersEnumWindowsProc, (LPARAM)pInfo );
  7027. SendMessage( pInfo->hwndClbNumbers,
  7028. CB_SETDROPPEDWIDTH, (WPARAM )dxOld, 0 );
  7029. if (!pInfo->hwndClbNumbersLb)
  7030. {
  7031. return ERROR_NOT_FOUND;
  7032. }
  7033. // Subclass the windows after associating the dialog context with them for
  7034. // retrieval in the WndProcs.
  7035. //
  7036. SetProp( pInfo->hwndClbNumbersEb, g_contextId, pInfo );
  7037. SetProp( pInfo->hwndClbNumbersLb, g_contextId, pInfo );
  7038. pInfo->wndprocClbNumbersEb =
  7039. (WNDPROC )SetWindowLongPtr(
  7040. pInfo->hwndClbNumbersEb,
  7041. GWLP_WNDPROC, (ULONG_PTR )DrClbNumbersEbWndProc );
  7042. pInfo->wndprocClbNumbersLb =
  7043. (WNDPROC )SetWindowLongPtr(
  7044. pInfo->hwndClbNumbersLb,
  7045. GWLP_WNDPROC, (ULONG_PTR )DrClbNumbersLbWndProc );
  7046. return 0;
  7047. }
  7048. void
  7049. DrEnsureNetshellLoaded (
  7050. IN DRINFO* pInfo)
  7051. {
  7052. // Load the netshell utilities interface. The interface is freed in PeTerm.
  7053. //
  7054. if (!pInfo->pNetConUtilities)
  7055. {
  7056. // Initialize the NetConnectionsUiUtilities
  7057. //
  7058. HrCreateNetConnectionUtilities( &pInfo->pNetConUtilities );
  7059. }
  7060. }
  7061. BOOL
  7062. DrInit(
  7063. IN HWND hwndDlg,
  7064. IN DRARGS* pArgs )
  7065. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  7066. // 'PArgs' is caller's arguments to the stub API.
  7067. //
  7068. // Return false if focus was set, true otherwise, i.e. as defined for
  7069. // WM_INITDIALOG.
  7070. //
  7071. {
  7072. DWORD dwErr;
  7073. DRINFO* pInfo;
  7074. PBENTRY* pEntry;
  7075. BOOL fEnableProperties;
  7076. TRACE( "DrInit" );
  7077. // Allocate the dialog context block. Initialize minimally for proper
  7078. // cleanup, then attach to the dialog window.
  7079. //
  7080. {
  7081. pInfo = Malloc( sizeof(*pInfo) );
  7082. if (!pInfo)
  7083. {
  7084. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  7085. EndDialog( hwndDlg, FALSE );
  7086. return TRUE;
  7087. }
  7088. ZeroMemory( pInfo, sizeof(*pInfo) );
  7089. pInfo->pArgs = pArgs;
  7090. pInfo->hwndDlg = hwndDlg;
  7091. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  7092. TRACE( "Context set" );
  7093. }
  7094. pEntry = pArgs->pDinfo->pEntry;
  7095. pInfo->hwndBmDialer = GetDlgItem( hwndDlg, CID_DR_BM_Useless );
  7096. ASSERT( pInfo->hwndBmDialer );
  7097. // Look up control handles.
  7098. //
  7099. if ((pArgs->dwfMode & DR_U) ||
  7100. (pArgs->dwfMode & DR_I))
  7101. {
  7102. pInfo->hwndEbUser = GetDlgItem( hwndDlg, CID_DR_EB_User );
  7103. ASSERT( pInfo->hwndEbUser );
  7104. if (pArgs->dwfMode & DR_U)
  7105. {
  7106. pInfo->hwndEbPw = GetDlgItem( hwndDlg, CID_DR_EB_Password );
  7107. ASSERT( pInfo->hwndEbPw );
  7108. pInfo->hwndCbSavePw = GetDlgItem( hwndDlg, CID_DR_CB_SavePassword );
  7109. ASSERT( pInfo->hwndCbSavePw );
  7110. pInfo->hwndRbSaveForMe = GetDlgItem( hwndDlg, CID_DR_RB_SaveForMe );
  7111. ASSERT( pInfo->hwndRbSaveForMe );
  7112. pInfo->hwndRbSaveForEveryone =
  7113. GetDlgItem( hwndDlg, CID_DR_RB_SaveForEveryone );
  7114. ASSERT( pInfo->hwndRbSaveForEveryone );
  7115. }
  7116. if (pArgs->dwfMode & DR_D)
  7117. {
  7118. pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_DR_EB_Domain );
  7119. ASSERT( pInfo->hwndEbDomain );
  7120. }
  7121. }
  7122. if (pArgs->dwfMode & DR_N)
  7123. {
  7124. pInfo->hwndClbNumbers = GetDlgItem( hwndDlg, CID_DR_CLB_Numbers );
  7125. ASSERT( pInfo->hwndClbNumbers );
  7126. if (pArgs->dwfMode & DR_L)
  7127. {
  7128. pInfo->hwndStLocations = GetDlgItem( hwndDlg, CID_DR_ST_Locations );
  7129. ASSERT( pInfo->hwndStLocations );
  7130. pInfo->hwndLbLocations = GetDlgItem( hwndDlg, CID_DR_LB_Locations );
  7131. ASSERT( pInfo->hwndLbLocations );
  7132. pInfo->hwndPbRules = GetDlgItem( hwndDlg, CID_DR_PB_Rules );
  7133. ASSERT( pInfo->hwndPbRules );
  7134. }
  7135. }
  7136. pInfo->hwndPbProperties = GetDlgItem( hwndDlg, CID_DR_PB_Properties );
  7137. ASSERT( pInfo->hwndPbProperties );
  7138. // In location-enabled mode, popup TAPI's "first location" dialog if they
  7139. // are uninitialized. Typically, this will do nothing.
  7140. //
  7141. if (pArgs->dwfMode & DR_L)
  7142. {
  7143. dwErr = TapiNoLocationDlg( g_hinstDll, &pInfo->hlineapp, hwndDlg );
  7144. if (dwErr != 0)
  7145. {
  7146. // Error here is treated as a "cancel" per bug 288385.
  7147. //
  7148. pArgs->pDinfo->pArgs->dwError = 0;
  7149. EndDialog( hwndDlg, FALSE );
  7150. return TRUE;
  7151. }
  7152. }
  7153. // Set the title.
  7154. //
  7155. {
  7156. TCHAR* pszTitleFormat;
  7157. TCHAR* pszTitle;
  7158. TCHAR* apszArgs[ 1 ];
  7159. if (pArgs->pDinfo->fUnattended)
  7160. {
  7161. pszTitleFormat = PszFromId( g_hinstDll, SID_DR_ReconnectTitle );
  7162. }
  7163. else
  7164. {
  7165. pszTitleFormat = GetText( hwndDlg );
  7166. }
  7167. if (pszTitleFormat)
  7168. {
  7169. apszArgs[ 0 ] = pEntry->pszEntryName;
  7170. pszTitle = NULL;
  7171. FormatMessage(
  7172. FORMAT_MESSAGE_FROM_STRING
  7173. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  7174. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  7175. pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1,
  7176. (va_list* )apszArgs );
  7177. Free( pszTitleFormat );
  7178. if (pszTitle)
  7179. {
  7180. SetWindowText( hwndDlg, pszTitle );
  7181. LocalFree( pszTitle );
  7182. }
  7183. }
  7184. }
  7185. // Change the Dial button to Connect for non-phone devices.
  7186. //
  7187. if (pEntry->dwType != RASET_Phone)
  7188. {
  7189. TCHAR* psz;
  7190. psz = PszFromId( g_hinstDll, SID_ConnectButton );
  7191. if (psz)
  7192. {
  7193. SetWindowText( GetDlgItem( hwndDlg, CID_DR_PB_DialConnect ), psz );
  7194. Free( psz );
  7195. }
  7196. }
  7197. // Initialize credentials section.
  7198. //
  7199. if (pArgs->dwfMode & DR_U)
  7200. {
  7201. ASSERT( !pEntry->fAutoLogon );
  7202. // Fill credential fields with initial values.
  7203. //
  7204. Edit_LimitText( pInfo->hwndEbUser, UNLEN );
  7205. SetWindowText( pInfo->hwndEbUser, pArgs->pDinfo->rdp.szUserName );
  7206. Edit_LimitText( pInfo->hwndEbPw, PWLEN );
  7207. if (pArgs->dwfMode & DR_D)
  7208. {
  7209. Edit_LimitText( pInfo->hwndEbDomain, DNLEN );
  7210. SetWindowText( pInfo->hwndEbDomain, pArgs->pDinfo->rdp.szDomain );
  7211. }
  7212. if (pArgs->pDinfo->pNoUser || pArgs->pDinfo->fDisableSavePw)
  7213. {
  7214. // Can't stash password without a logon context, so hide the
  7215. // checkbox.
  7216. //
  7217. ASSERT( !HaveSavedPw( pArgs->pDinfo )) ;
  7218. EnableWindow( pInfo->hwndCbSavePw, FALSE );
  7219. EnableWindow( pInfo->hwndRbSaveForMe, FALSE );
  7220. EnableWindow( pInfo->hwndRbSaveForEveryone, FALSE );
  7221. // Whistler bug 400714 RAS does not grab password at winlogon time
  7222. // when Connect dialog is displayed
  7223. //
  7224. // Whistler bug 254385 encode password when not being used
  7225. // Assumed password was encoded previously
  7226. //
  7227. DecodePassword( pArgs->pDinfo->rdp.szPassword );
  7228. SetWindowText( pInfo->hwndEbPw, pArgs->pDinfo->rdp.szPassword );
  7229. EncodePassword( pArgs->pDinfo->rdp.szPassword );
  7230. }
  7231. else
  7232. {
  7233. // Whistler bug: 195480 Dial-up connection dialog - Number of
  7234. // asterisks does not match the length of the password and causes
  7235. // confusion
  7236. //
  7237. // Init the password character. Default to the round dot if we fail
  7238. // to get it.
  7239. //
  7240. pInfo->szPasswordChar = (WCHAR) SendMessage( pInfo->hwndEbPw,
  7241. EM_GETPASSWORDCHAR, 0, 0 );
  7242. if (!pInfo->szPasswordChar)
  7243. {
  7244. pInfo->szPasswordChar = 0x25CF;
  7245. }
  7246. // Init the fonts for the password field
  7247. //
  7248. DrGetFriendlyFont( hwndDlg, TRUE, &(pInfo->hItalicFont) );
  7249. DrGetFriendlyFont( hwndDlg, FALSE, &(pInfo->hNormalFont) );
  7250. // Check "save password" and render the type of saved
  7251. // password.
  7252. //
  7253. Button_SetCheck(
  7254. pInfo->hwndCbSavePw,
  7255. HaveSavedPw( pArgs->pDinfo ));
  7256. if ((!pArgs->pDinfo->fIsPublicPbk) ||
  7257. (!HaveSavedPw( pArgs->pDinfo )))
  7258. {
  7259. // If this is a for-me-only connection or if
  7260. // there is no saved password, then initialize the
  7261. // pw save type to save-for-me
  7262. //
  7263. Button_SetCheck( pInfo->hwndRbSaveForMe, TRUE );
  7264. }
  7265. else
  7266. {
  7267. // Check the appropriate radio button
  7268. // Note that a per-user password is always used if
  7269. // both a per-user and global password are saved.
  7270. // Dont check global password if its a per-user connectoid
  7271. //
  7272. Button_SetCheck(
  7273. (pArgs->pDinfo->fHaveSavedPwUser) ?
  7274. pInfo->hwndRbSaveForMe :
  7275. pInfo->hwndRbSaveForEveryone,
  7276. TRUE);
  7277. }
  7278. DrEnableDisablePwControls( pInfo, HaveSavedPw( pArgs->pDinfo ) );
  7279. // Whistler bug: 195480 Dial-up connection dialog - Number of
  7280. // asterisks does not match the length of the password and causes
  7281. // confusion
  7282. //
  7283. DrPopulatePasswordField( pInfo, TRUE, FALSE );
  7284. }
  7285. }
  7286. if (pArgs->dwfMode & DR_N)
  7287. {
  7288. pInfo->pLinkNode = NULL;
  7289. if (pArgs->pDinfo->pArgs->dwSubEntry > 0)
  7290. {
  7291. // Look up the API caller specified link.
  7292. //
  7293. pInfo->pLinkNode =
  7294. DtlNodeFromIndex(
  7295. pArgs->pDinfo->pEntry->pdtllistLinks,
  7296. pArgs->pDinfo->pArgs->dwSubEntry - 1 );
  7297. }
  7298. if (!pInfo->pLinkNode)
  7299. {
  7300. // Look up the default (first) link.
  7301. //
  7302. pInfo->pLinkNode =
  7303. DtlGetFirstNode( pArgs->pDinfo->pEntry->pdtllistLinks );
  7304. }
  7305. ASSERT( pInfo->pLinkNode );
  7306. pInfo->pLink = (PBLINK* )DtlGetData( pInfo->pLinkNode );
  7307. dwErr = DrFindAndSubclassClbNumbersControls( pInfo );
  7308. if (dwErr != 0)
  7309. {
  7310. pArgs->pDinfo->pArgs->dwError = ERROR_NOT_FOUND;
  7311. EndDialog( hwndDlg, FALSE );
  7312. return TRUE;
  7313. }
  7314. // Ignore any "last selected" information when the "try next on fail"
  7315. // flag is set. New entries will not have "last selected" non-0 in
  7316. // this case but pre-existing entries might, so double-check here.
  7317. // See bug 150958.
  7318. //
  7319. if (pInfo->pLink->fTryNextAlternateOnFail)
  7320. {
  7321. pInfo->pLink->iLastSelectedPhone = 0;
  7322. }
  7323. // Record the initially selected phone number, used to determine
  7324. // whether user has changed the selection.
  7325. //
  7326. pInfo->iFirstSelectedPhone = pInfo->pLink->iLastSelectedPhone;
  7327. DrFillNumbersList( pInfo );
  7328. if (pArgs->dwfMode & DR_L)
  7329. {
  7330. DrFillLocationList( pInfo );
  7331. }
  7332. }
  7333. // danielwe: Bug #222744, scottbri Bug #245310
  7334. // Disable Properties... button if user does not have sufficent rights.
  7335. //
  7336. {
  7337. HRESULT hr;
  7338. hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );
  7339. if (hr == RPC_E_CHANGED_MODE)
  7340. {
  7341. hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
  7342. }
  7343. if (hr == S_OK || hr == S_FALSE)
  7344. {
  7345. pInfo->fComInitialized = TRUE;
  7346. }
  7347. }
  7348. fEnableProperties = FALSE;
  7349. DrEnsureNetshellLoaded (pInfo);
  7350. if (NULL != pInfo->pNetConUtilities)
  7351. {
  7352. //For whislter bug 409504 gangz
  7353. //for a VPN double dial scenario,if now it is in the prerequiste dial
  7354. //process, we should use DINFO->pEntryMain->pszPrerequisitePbk to check
  7355. //if it is a publicPhonebook
  7356. //
  7357. BOOL fAllUsers = TRUE;
  7358. if( pArgs->pDinfo->fPrerequisiteDial )
  7359. {
  7360. fAllUsers =
  7361. IsPublicPhonebook(pArgs->pDinfo->pEntryMain->pszPrerequisitePbk);
  7362. }
  7363. else
  7364. {
  7365. fAllUsers = IsPublicPhonebook(pArgs->pDinfo->pszPhonebook);
  7366. }
  7367. if (((fAllUsers && INetConnectionUiUtilities_UserHasPermission(
  7368. pInfo->pNetConUtilities,
  7369. NCPERM_RasAllUserProperties)) ||
  7370. (!fAllUsers && INetConnectionUiUtilities_UserHasPermission(
  7371. pInfo->pNetConUtilities,
  7372. NCPERM_RasMyProperties))) &&
  7373. (NULL == pArgs->pDinfo->pNoUser))
  7374. {
  7375. fEnableProperties = TRUE;
  7376. }
  7377. // We only needed it breifly, release it
  7378. INetConnectionUiUtilities_Release(pInfo->pNetConUtilities);
  7379. pInfo->pNetConUtilities = NULL;
  7380. }
  7381. // stevec: 267157-Allow access at win-login if admin enables.
  7382. //
  7383. if (NULL != pArgs->pDinfo->pNoUser
  7384. && pArgs->pDinfo->pUser->fAllowLogonPhonebookEdits)
  7385. {
  7386. fEnableProperties = TRUE;
  7387. }
  7388. EnableWindow( pInfo->hwndPbProperties, fEnableProperties );
  7389. // The help engine doesn't work at win-logon as it requires a user
  7390. // context, so disable the Help button in that case. See bug 343030.
  7391. //
  7392. if (pArgs->pDinfo->pNoUser)
  7393. {
  7394. HWND hwndPbHelp;
  7395. hwndPbHelp = GetDlgItem( hwndDlg, CID_DR_PB_Help );
  7396. ASSERT( hwndPbHelp );
  7397. EnableWindow( hwndPbHelp, FALSE );
  7398. ShowWindow( hwndPbHelp, SW_HIDE );
  7399. }
  7400. // Set the bitmap to the low res version if that is appropriate
  7401. //
  7402. // Ignore the error -- it is non-critical
  7403. //
  7404. DrSetBitmap(pInfo);
  7405. // Position the dialog per caller's instructions.
  7406. //
  7407. PositionDlg( hwndDlg,
  7408. !!(pArgs->pDinfo->pArgs->dwFlags & RASDDFLAG_PositionDlg),
  7409. pArgs->pDinfo->pArgs->xDlg, pArgs->pDinfo->pArgs->yDlg );
  7410. //Add this function for whislter bug 320863 gangz
  7411. //To adjust the bitmap's position and size
  7412. //
  7413. CenterExpandWindowRemainLeftMargin( pInfo->hwndBmDialer,
  7414. hwndDlg,
  7415. TRUE,
  7416. TRUE,
  7417. pInfo->hwndEbUser);
  7418. // Adjust the title bar widgets.
  7419. //
  7420. //TweakTitleBar( hwndDlg );
  7421. AddContextHelpButton( hwndDlg );
  7422. return TRUE;
  7423. }
  7424. VOID
  7425. DrLocationsSelChange(
  7426. IN DRINFO* pInfo )
  7427. // Called when a location is selected from the list. 'PInfo' is the
  7428. // dialog context.
  7429. //
  7430. {
  7431. DWORD dwErr;
  7432. DWORD dwLocationId;
  7433. TRACE("DuLocationChange");
  7434. // Set global TAPI location based on user's selection.
  7435. //
  7436. dwLocationId = (DWORD )ComboBox_GetItemData(
  7437. pInfo->hwndLbLocations, ComboBox_GetCurSel( pInfo->hwndLbLocations ) );
  7438. dwErr = SetCurrentLocation( g_hinstDll, &pInfo->hlineapp, dwLocationId );
  7439. if (dwErr != 0)
  7440. {
  7441. ErrorDlg( pInfo->hwndDlg, SID_OP_SaveTapiInfo, dwErr, NULL );
  7442. }
  7443. // Location change may cause changes in built numbers so re-fill the
  7444. // numbers combo-box.
  7445. //
  7446. DrFillNumbersList( pInfo );
  7447. }
  7448. VOID
  7449. DrNumbersSelChange(
  7450. IN DRINFO* pInfo )
  7451. // Called when a phone number is selected from the list. 'PInfo' is the
  7452. // dialog context.
  7453. //
  7454. {
  7455. INT iSel;
  7456. BOOL fEnable;
  7457. DRNUMBERSITEM* pItem;
  7458. iSel = ComboBox_GetCurSel( pInfo->hwndClbNumbers );
  7459. if (iSel >= 0)
  7460. {
  7461. if (iSel != (INT )pInfo->pLink->iLastSelectedPhone)
  7462. {
  7463. pInfo->pArgs->pDinfo->pEntry->fDirty = TRUE;
  7464. }
  7465. pInfo->pLink->iLastSelectedPhone = (DWORD )iSel;
  7466. }
  7467. pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr(
  7468. pInfo->hwndClbNumbers, iSel );
  7469. ASSERT( pItem );
  7470. if(NULL == pItem)
  7471. {
  7472. return;
  7473. }
  7474. // Enable/disable the location fields based on whether they are relevant
  7475. // to the selected number.
  7476. //
  7477. if (pInfo->pArgs->dwfMode & DR_L)
  7478. {
  7479. fEnable = pItem->pPhone->fUseDialingRules;
  7480. EnableWindow( pInfo->hwndStLocations, fEnable );
  7481. EnableWindow( pInfo->hwndLbLocations, fEnable );
  7482. EnableWindow( pInfo->hwndPbRules, fEnable );
  7483. }
  7484. DrSetClbNumbersText( pInfo, pItem->pszNumber );
  7485. }
  7486. DWORD
  7487. DrPopulateIdentificationFields(
  7488. IN DRINFO* pInfo,
  7489. IN BOOL fForMe )
  7490. // Updates the identification fields in the dialer
  7491. // UI according to whether the all-user or per-user
  7492. // dialparms should be used.
  7493. //
  7494. {
  7495. RASDIALPARAMS* prdp, *prdpOld;
  7496. BOOL fUpdate;
  7497. TCHAR pszUser[UNLEN + 1];
  7498. INT iCount;
  7499. prdp = (fForMe)
  7500. ? &(pInfo->pArgs->pDinfo->rdpu) : &(pInfo->pArgs->pDinfo->rdpg);
  7501. prdpOld = (fForMe)
  7502. ? &(pInfo->pArgs->pDinfo->rdpg) : &(pInfo->pArgs->pDinfo->rdpu);
  7503. iCount = GetWindowText(
  7504. pInfo->hwndEbUser,
  7505. pszUser,
  7506. UNLEN + 1);
  7507. if (iCount == 0)
  7508. {
  7509. fUpdate = TRUE;
  7510. }
  7511. else
  7512. {
  7513. if (lstrcmp(prdpOld->szUserName, pszUser) == 0)
  7514. {
  7515. fUpdate = TRUE;
  7516. }
  7517. else
  7518. {
  7519. fUpdate = FALSE;
  7520. }
  7521. }
  7522. if (fUpdate)
  7523. {
  7524. if (pInfo->hwndEbUser && *(prdp->szUserName))
  7525. {
  7526. SetWindowText(pInfo->hwndEbUser, prdp->szUserName);
  7527. }
  7528. if (pInfo->hwndEbDomain && *(prdp->szDomain))
  7529. {
  7530. SetWindowText(pInfo->hwndEbDomain, prdp->szDomain);
  7531. }
  7532. }
  7533. return NO_ERROR;
  7534. }
  7535. DWORD
  7536. DrPopulatePasswordField(
  7537. IN DRINFO* pInfo,
  7538. IN BOOL fInit,
  7539. IN BOOL fDisable )
  7540. {
  7541. BOOL fSave, fMeOnly;
  7542. TCHAR* pszFriendly = NULL;
  7543. // Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
  7544. // does not match the length of the password and causes confusion
  7545. //
  7546. // Case 1. The user has clicked on the password field. We clear the
  7547. // friendly password and set the font back to normal.
  7548. //
  7549. if (fDisable)
  7550. {
  7551. DrClearFriendlyPassword( pInfo, TRUE );
  7552. return NO_ERROR;
  7553. }
  7554. // Initialze
  7555. //
  7556. fSave = Button_GetCheck( pInfo->hwndCbSavePw );
  7557. fMeOnly = Button_GetCheck( pInfo->hwndRbSaveForMe );
  7558. pszFriendly = PszFromId( g_hinstDll, SID_SavePasswordFrndly );
  7559. // Case 2. Clear the password field if the user a) choose not to save the
  7560. // password and b) has not manually entered a password.
  7561. //
  7562. if ( (!fSave) && !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ) )
  7563. {
  7564. DrClearFriendlyPassword( pInfo, FALSE );
  7565. }
  7566. // Case 3. Show the friendly saved password text if the user a) choose to
  7567. // save the password of himself only and b) there is a per-user password
  7568. // saved and c) the user has not entered a password manually.
  7569. //
  7570. else if ( (fSave) && (fMeOnly) &&
  7571. ((fInit) || ( !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))) )
  7572. {
  7573. // Whistler bug: 288234 When switching back and forth from
  7574. // "I connect" and "Any user connects" password is not
  7575. // caching correctly
  7576. //
  7577. if (pInfo->pArgs->pDinfo->fHaveSavedPwUser)
  7578. {
  7579. DrDisplayFriendlyPassword(pInfo, pszFriendly );
  7580. }
  7581. else
  7582. {
  7583. DrClearFriendlyPassword( pInfo, FALSE );
  7584. }
  7585. }
  7586. // Case 4. Show the friendly saved password text if the user a) choose to
  7587. // save the password for everyone and b) there is a default password saved
  7588. // and c) the user has not entered a password manually.
  7589. //
  7590. else if ( (fSave) && (!fMeOnly) &&
  7591. ((fInit) || ( !DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))) )
  7592. {
  7593. if (pInfo->pArgs->pDinfo->fHaveSavedPwGlobal)
  7594. {
  7595. DrDisplayFriendlyPassword( pInfo, pszFriendly );
  7596. }
  7597. else
  7598. {
  7599. DrClearFriendlyPassword( pInfo, FALSE );
  7600. }
  7601. }
  7602. // Case 5. Show the friendly saved password text if the user a) choose to
  7603. // save the password for everyone or himself and b) there is a
  7604. // corresponding password saved and c) the user has not entered a password
  7605. // manually.
  7606. //
  7607. // This case catches a) when the user is switching between "me" and
  7608. // "everyone" and b) when the user leaves the focus of the password field
  7609. // but hasn't changed the password
  7610. //
  7611. else if ( (fSave) && !GetWindowTextLength( pInfo->hwndEbPw ) &&
  7612. DrIsPasswordStyleEnabled( pInfo->hwndEbPw ) &&
  7613. ((pInfo->pArgs->pDinfo->fHaveSavedPwGlobal && !fMeOnly) ||
  7614. (pInfo->pArgs->pDinfo->fHaveSavedPwUser && fMeOnly)) )
  7615. {
  7616. DrDisplayFriendlyPassword( pInfo, pszFriendly );
  7617. }
  7618. // NT5 bug: 215432, Whistler bug: 364341
  7619. //
  7620. // Whistler bug: 195480 Dial-up connection dialog - Number of asterisks
  7621. // does not match the length of the password and causes confusion
  7622. //
  7623. // Set focus appropiately
  7624. //
  7625. if (fInit)
  7626. {
  7627. if (!GetWindowTextLength( pInfo->hwndEbUser ))
  7628. {
  7629. SetFocus( pInfo->hwndEbUser );
  7630. }
  7631. else if (!GetWindowTextLength( pInfo->hwndEbPw ))
  7632. {
  7633. SetFocus( pInfo->hwndEbPw );
  7634. // This removes the tab stop property from the username field. This
  7635. // is a hack so we can set the focus properly. Tab stop is put back
  7636. // in DrCommand.
  7637. //
  7638. SetWindowLong( pInfo->hwndEbUser, GWL_STYLE,
  7639. GetWindowLong( pInfo->hwndEbUser, GWL_STYLE ) & ~WS_TABSTOP );
  7640. }
  7641. else
  7642. {
  7643. SetFocus( pInfo->hwndEbUser );
  7644. }
  7645. }
  7646. // Clean up
  7647. //
  7648. Free0( pszFriendly );
  7649. return NO_ERROR;
  7650. }
  7651. VOID
  7652. DrProperties(
  7653. IN DRINFO* pInfo )
  7654. // Called when the Properties button is pressed. 'PInfo' is the dialog
  7655. // context.
  7656. //
  7657. {
  7658. BOOL fOk;
  7659. RASENTRYDLG info;
  7660. INTERNALARGS iargs;
  7661. DINFO* pDinfo;
  7662. // First, save any entry related changes user has made on the dial dialog.
  7663. //
  7664. DrSave( pInfo );
  7665. // Set up for parameters for call to RasEntryDlg.
  7666. //
  7667. ZeroMemory( &info, sizeof(info) );
  7668. info.dwSize = sizeof(info);
  7669. info.hwndOwner = pInfo->hwndDlg;
  7670. {
  7671. RECT rect;
  7672. info.dwFlags = RASEDFLAG_PositionDlg;
  7673. GetWindowRect( pInfo->hwndDlg, &rect );
  7674. info.xDlg = rect.left + DXSHEET;
  7675. info.yDlg = rect.top + DYSHEET;
  7676. }
  7677. // The secret hack to share information already loaded with the entry API.
  7678. //
  7679. pDinfo = pInfo->pArgs->pDinfo;
  7680. ZeroMemory( &iargs, sizeof(iargs) );
  7681. iargs.pFile = pDinfo->pFile;
  7682. iargs.pUser = pDinfo->pUser;
  7683. iargs.pNoUser = pDinfo->pNoUser;
  7684. iargs.fNoUser = !!(pDinfo->pNoUser);
  7685. //For whislter bug 234515 set fDisableFirstConnect to be FALSE
  7686. //
  7687. iargs.fDisableFirstConnect = FALSE;
  7688. info.reserved = (ULONG_PTR )&iargs;
  7689. TRACE( "RasEntryDlg" );
  7690. fOk = RasEntryDlg(
  7691. pDinfo->pszPhonebook, pDinfo->pEntry->pszEntryName, &info );
  7692. TRACE1( "RasEntryDlg=%d", fOk );
  7693. if (fOk)
  7694. {
  7695. DWORD dwErr;
  7696. // Reload when user presses OK on properties since that may change the
  7697. // appearance and content of this dialog. Must first reset the DINFO
  7698. // context parameters based on the replaced PBENTRY from the property
  7699. // sheet.
  7700. //
  7701. dwErr = FindEntryAndSetDialParams( pInfo->pArgs->pDinfo );
  7702. if (dwErr != 0)
  7703. {
  7704. // Should not happen.
  7705. //
  7706. EndDialog( pInfo->hwndDlg, FALSE );
  7707. }
  7708. pInfo->pArgs->fReload = TRUE;
  7709. EndDialog( pInfo->hwndDlg, FALSE );
  7710. }
  7711. }
  7712. VOID
  7713. DrSave(
  7714. IN DRINFO* pInfo )
  7715. // Saves dialog field contents to RASDIALPARAMS, and if appropriate to LSA
  7716. // secret area or NOUSER output argument. 'PInfo' is the dialog context.
  7717. //
  7718. {
  7719. DWORD dwErr;
  7720. RASDIALPARAMS* prdp;
  7721. RASCREDENTIALS rc;
  7722. DINFO* pDinfo;
  7723. pDinfo = pInfo->pArgs->pDinfo;
  7724. if ((pInfo->pArgs->dwfMode & DR_U) ||
  7725. (pInfo->pArgs->dwfMode & DR_I))
  7726. {
  7727. // Save credentials into parameter block to be passed to RasDial.
  7728. //
  7729. prdp = &pDinfo->rdp;
  7730. GetWindowText( pInfo->hwndEbUser, prdp->szUserName, UNLEN + 1 );
  7731. if (pInfo->pArgs->dwfMode & DR_U)
  7732. {
  7733. // Whistler bug 254385 encode password when not being used
  7734. // Assumed password was not encoded by GetWindowText()
  7735. //
  7736. // Whistler bug: 195480 Dial-up connection dialog - Number of
  7737. // asterisks does not match the length of the password and causes
  7738. // confusion
  7739. //
  7740. if (!DrIsPasswordStyleEnabled( pInfo->hwndEbPw ))
  7741. {
  7742. lstrcpyn( prdp->szPassword, g_pszSavedPasswordToken,
  7743. g_dwSavedPasswordTokenLength );
  7744. }
  7745. else
  7746. {
  7747. GetWindowText( pInfo->hwndEbPw, prdp->szPassword, PWLEN + 1 );
  7748. }
  7749. SetWindowText( pInfo->hwndEbPw, L"" );
  7750. EncodePassword( prdp->szPassword );
  7751. }
  7752. if (pInfo->pArgs->dwfMode & DR_D)
  7753. {
  7754. GetWindowText( pInfo->hwndEbDomain, prdp->szDomain, DNLEN + 1 );
  7755. }
  7756. ZeroMemory( &rc, sizeof(rc) );
  7757. rc.dwSize = sizeof(rc);
  7758. lstrcpyn( rc.szUserName, prdp->szUserName, UNLEN + 1 );
  7759. // Whistler bug 254385 encode password when not being used
  7760. // Assumed password was encoded previously
  7761. //
  7762. DecodePassword( prdp->szPassword );
  7763. lstrcpyn( rc.szPassword, prdp->szPassword, PWLEN + 1 );
  7764. EncodePassword( prdp->szPassword );
  7765. lstrcpyn( rc.szDomain, prdp->szDomain, DNLEN + 1);
  7766. if (pDinfo->pNoUser)
  7767. {
  7768. // Save credentials into output block for return to caller,
  7769. // typically WinLogon.
  7770. //
  7771. lstrcpyn( pDinfo->pNoUser->szUserName, rc.szUserName, UNLEN + 1 );
  7772. // Whistler bug 254385 encode password when not being used
  7773. // Assumed password was not encoded previously
  7774. //
  7775. lstrcpyn( pDinfo->pNoUser->szPassword, rc.szPassword, PWLEN + 1 );
  7776. EncodePassword( pDinfo->pNoUser->szPassword );
  7777. lstrcpyn( pDinfo->pNoUser->szDomain, rc.szDomain, DNLEN + 1 );
  7778. *(pDinfo->pfNoUserChanged) = TRUE;
  7779. }
  7780. else if (pInfo->pArgs->dwfMode & DR_I)
  7781. {
  7782. // Nothing to do
  7783. }
  7784. else if (!pDinfo->fDisableSavePw)
  7785. {
  7786. BOOL fGlobalCreds = FALSE;
  7787. ASSERT( g_pRasSetCredentials );
  7788. if (Button_GetCheck( pInfo->hwndCbSavePw ))
  7789. {
  7790. rc.dwMask = 0;
  7791. // If the user elected to save the credentials for
  7792. // everybody, then clear any previously saved per-user
  7793. // credentials
  7794. //
  7795. fGlobalCreds = Button_GetCheck( pInfo->hwndRbSaveForEveryone );
  7796. if( (fGlobalCreds)
  7797. && IsPublicPhonebook(pDinfo->pFile->pszPath))
  7798. {
  7799. DeleteSavedCredentials(
  7800. pDinfo,
  7801. pInfo->hwndDlg,
  7802. FALSE,
  7803. TRUE );
  7804. pDinfo->fHaveSavedPwUser = FALSE;
  7805. rc.dwMask = RASCM_DefaultCreds;
  7806. }
  7807. // If there is currently no saved per-user password and the user
  7808. // opts to save the password himself, then ask whetehr the global
  7809. // password should be deleted if it exists.
  7810. //
  7811. else if (pDinfo->fHaveSavedPwGlobal && !pDinfo->fHaveSavedPwUser)
  7812. {
  7813. MSGARGS msgargs;
  7814. ZeroMemory( &msgargs, sizeof(msgargs) );
  7815. msgargs.dwFlags = MB_ICONQUESTION | MB_YESNO;
  7816. // Delete the default credentials if the user answers yes
  7817. //
  7818. if (IDYES ==
  7819. MsgDlg(pInfo->hwndDlg, SID_DR_GlobalPassword, &msgargs))
  7820. {
  7821. DeleteSavedCredentials(
  7822. pDinfo,
  7823. pInfo->hwndDlg,
  7824. TRUE,
  7825. TRUE );
  7826. pDinfo->fHaveSavedPwGlobal = FALSE;
  7827. }
  7828. }
  7829. // User chose to save password. Cache username, password, and
  7830. // domain.
  7831. //
  7832. rc.dwMask |= RASCM_UserName |
  7833. RASCM_Password | RASCM_Domain;
  7834. TRACE( "RasSetCredentials(u|p|d,FALSE)" );
  7835. dwErr = g_pRasSetCredentials(
  7836. pDinfo->pFile->pszPath, pDinfo->pEntry->pszEntryName,
  7837. &rc, FALSE );
  7838. TRACE1( "RasSetCredentials=%d", dwErr );
  7839. if (dwErr != 0)
  7840. {
  7841. ErrorDlg( pInfo->hwndDlg, SID_OP_CachePw, dwErr, NULL );
  7842. }
  7843. else
  7844. {
  7845. if (fGlobalCreds)
  7846. {
  7847. pDinfo->fHaveSavedPwGlobal = TRUE;
  7848. }
  7849. else
  7850. {
  7851. // Whistler bug: 288234 When switching back and forth
  7852. // from "I connect" and "Any user connects" password is
  7853. // not caching correctly
  7854. //
  7855. pDinfo->fHaveSavedPwUser = TRUE;
  7856. }
  7857. }
  7858. }
  7859. else
  7860. {
  7861. // Delete the global credentials.
  7862. //
  7863. // Note that we have to delete the global identity
  7864. // as well because we do not support deleting
  7865. // just the global password. This is so that
  7866. // RasSetCredentials can emulate RasSetDialParams.
  7867. //
  7868. DeleteSavedCredentials(
  7869. pDinfo,
  7870. pInfo->hwndDlg,
  7871. TRUE,
  7872. TRUE );
  7873. // Delete the password saved per-user. Keep the user name
  7874. // and domain saved, however.
  7875. //
  7876. DeleteSavedCredentials(
  7877. pDinfo,
  7878. pInfo->hwndDlg,
  7879. FALSE,
  7880. FALSE );
  7881. pDinfo->fHaveSavedPwUser = FALSE;
  7882. pDinfo->fHaveSavedPwGlobal = FALSE;
  7883. }
  7884. }
  7885. ZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
  7886. }
  7887. if (pInfo->pArgs->dwfMode & DR_N)
  7888. {
  7889. TCHAR* pszNumber;
  7890. TCHAR* pszOriginal;
  7891. DTLNODE* pPhoneNode;
  7892. DRNUMBERSITEM* pItem;
  7893. PBPHONE* pPhone;
  7894. BOOL fUserChange;
  7895. pszNumber = GetText( pInfo->hwndClbNumbers );
  7896. if (!pszNumber)
  7897. {
  7898. return;
  7899. }
  7900. pItem = (DRNUMBERSITEM* )ComboBox_GetItemDataPtr(
  7901. pInfo->hwndClbNumbers, pInfo->pLink->iLastSelectedPhone );
  7902. if (pItem)
  7903. {
  7904. pszOriginal = pItem->pszNumber;
  7905. }
  7906. else
  7907. {
  7908. pszOriginal = TEXT("");
  7909. }
  7910. if (lstrcmp( pszNumber, pszOriginal ) != 0
  7911. || (pInfo->pLink->iLastSelectedPhone != pInfo->iFirstSelectedPhone))
  7912. {
  7913. MSGARGS msgargs;
  7914. BOOL fMultiLink;
  7915. BOOL fSingleNumber;
  7916. // The phone number was edited by user to something not originally
  7917. // on the list OR the user selected a different item on the list.
  7918. //
  7919. fSingleNumber = (DtlGetNodes( pInfo->pLink->pdtllistPhones ) == 1);
  7920. fMultiLink = (DtlGetNodes( pDinfo->pEntry->pdtllistLinks ) > 1);
  7921. ZeroMemory( &msgargs, sizeof(msgargs) );
  7922. msgargs.dwFlags = MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2;
  7923. if (fSingleNumber
  7924. && (!fMultiLink || pDinfo->pEntry->fSharedPhoneNumbers)
  7925. && MsgDlg( pInfo->hwndDlg,
  7926. SID_SavePreview, &msgargs ) == IDYES)
  7927. {
  7928. // User says he wants to make the change permanent.
  7929. //
  7930. pDinfo->pEntry->fDirty = TRUE;
  7931. if (pItem)
  7932. {
  7933. pPhone = pItem->pPhone;
  7934. Free0( pItem->pszNumber );
  7935. pItem->pszNumber = StrDup( pszNumber );
  7936. }
  7937. else
  7938. {
  7939. pPhoneNode = CreatePhoneNode();
  7940. if (pPhoneNode)
  7941. {
  7942. DtlAddNodeFirst(
  7943. pInfo->pLink->pdtllistPhones, pPhoneNode );
  7944. pPhone = (PBPHONE* )DtlGetData( pPhoneNode );
  7945. }
  7946. }
  7947. if (pItem)
  7948. {
  7949. ASSERT( pItem->pPhone );
  7950. Free0( pPhone->pszPhoneNumber );
  7951. pPhone->pszPhoneNumber = StrDup( pszNumber );
  7952. pPhone->fUseDialingRules = FALSE;
  7953. if (fMultiLink)
  7954. {
  7955. DTLNODE* pNode;
  7956. for (pNode = DtlGetFirstNode(
  7957. pDinfo->pEntry->pdtllistLinks );
  7958. pNode;
  7959. pNode = DtlGetNextNode( pNode ))
  7960. {
  7961. PBLINK* pLink = (PBLINK* )DtlGetData( pNode );
  7962. ASSERT( pLink );
  7963. ASSERT( pLink->fEnabled );
  7964. CopyLinkPhoneNumberInfo( pNode, pInfo->pLinkNode );
  7965. }
  7966. }
  7967. }
  7968. }
  7969. fUserChange = TRUE;
  7970. }
  7971. else
  7972. {
  7973. fUserChange = FALSE;
  7974. }
  7975. if (fUserChange || !pInfo->pLink->fTryNextAlternateOnFail)
  7976. {
  7977. if (!*pszNumber)
  7978. {
  7979. TCHAR* psz;
  7980. // We have a problem when user edits in an empty string,
  7981. // because the RasDial API does not accept an empty override
  7982. // phone number. Convert it to a single blank string in this
  7983. // case, which is as good as we can do. If user really needs
  7984. // to dial an empty string they can enter one as the entry's
  7985. // permanent phone number. See bug 179561.
  7986. //
  7987. psz = StrDup( TEXT(" ") );
  7988. if (psz)
  7989. {
  7990. Free( pszNumber );
  7991. pszNumber = psz;
  7992. }
  7993. }
  7994. // Set the override phone number to what user typed or selected.
  7995. //
  7996. lstrcpyn(
  7997. pDinfo->rdp.szPhoneNumber,
  7998. pszNumber,
  7999. RAS_MaxPhoneNumber + 1);
  8000. }
  8001. Free( pszNumber );
  8002. }
  8003. if (pDinfo->pEntry->fDirty)
  8004. {
  8005. // Write the new phone number and/or "last selected phone number" to
  8006. // the phonebook.
  8007. //
  8008. dwErr = WritePhonebookFile( pDinfo->pFile, NULL );
  8009. if (dwErr != 0)
  8010. {
  8011. ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL );
  8012. }
  8013. }
  8014. }
  8015. DWORD
  8016. DrSetBitmap(
  8017. IN DRINFO* pInfo)
  8018. // Set the appropriate bitmap for this dialer.
  8019. //
  8020. {
  8021. DWORD dwErr = NO_ERROR;
  8022. HBITMAP hbmNew = NULL;
  8023. HDC hdc = NULL;
  8024. INT iDepth = 0;
  8025. do
  8026. {
  8027. if (pInfo->hwndBmDialer == NULL)
  8028. {
  8029. dwErr = ERROR_CAN_NOT_COMPLETE;
  8030. break;
  8031. }
  8032. // Get the device context for the window
  8033. //
  8034. hdc = GetDC( pInfo->hwndBmDialer );
  8035. if (hdc == NULL)
  8036. {
  8037. dwErr = GetLastError();
  8038. break;
  8039. }
  8040. // If the color depth >= 8bit, the current bitmap
  8041. // is fine (high res is default)
  8042. //
  8043. iDepth = GetDeviceCaps(hdc, NUMCOLORS);
  8044. if ( (iDepth == -1) || (iDepth == 256) )
  8045. {
  8046. dwErr = NO_ERROR;
  8047. break;
  8048. }
  8049. // Load in the low-res bitmap
  8050. //
  8051. hbmNew = LoadBitmap(g_hinstDll, MAKEINTRESOURCE( BID_Dialer ));
  8052. if (hbmNew == NULL)
  8053. {
  8054. dwErr = GetLastError();
  8055. break;
  8056. }
  8057. // Set the low-res bitmap
  8058. //
  8059. pInfo->hbmOrig = (HBITMAP)
  8060. SendMessage(
  8061. pInfo->hwndBmDialer,
  8062. STM_SETIMAGE,
  8063. IMAGE_BITMAP,
  8064. (LPARAM )hbmNew );
  8065. } while (FALSE);
  8066. // Cleanup
  8067. //
  8068. {
  8069. if (hdc)
  8070. {
  8071. ReleaseDC(pInfo->hwndBmDialer, hdc);
  8072. }
  8073. }
  8074. return dwErr;
  8075. }
  8076. VOID
  8077. DrSetClbNumbersText(
  8078. IN DRINFO* pInfo,
  8079. IN TCHAR* pszText )
  8080. // Set the text of the 'ClbNumbers' edit box to 'pszText'. See
  8081. // DrClbNumbersEbWndProc. 'PInfo' is the dialog context.
  8082. //
  8083. {
  8084. ASSERT( pInfo->hwndClbNumbersEb );
  8085. SendMessage( pInfo->hwndClbNumbersEb, DR_WM_SETTEXT, 0, (LPARAM )pszText );
  8086. }
  8087. VOID
  8088. DrTerm(
  8089. IN HWND hwndDlg )
  8090. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  8091. //
  8092. {
  8093. DRINFO* pInfo = (DRINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  8094. HBITMAP hbmNew = NULL;
  8095. TRACE( "DrTerm" );
  8096. if (pInfo)
  8097. {
  8098. // Note: Don't use 'pInfo->pLinkNode' or 'pInfo->pLink' here as they
  8099. // are not currently restored prior to exit for post-Property
  8100. // button reloading.
  8101. //
  8102. if (pInfo->hwndClbNumbers)
  8103. {
  8104. DrFreeClbNumbers( pInfo );
  8105. if (pInfo->wndprocClbNumbersEb)
  8106. {
  8107. SetWindowLongPtr( pInfo->hwndClbNumbersEb,
  8108. GWLP_WNDPROC, (ULONG_PTR )pInfo->wndprocClbNumbersEb );
  8109. }
  8110. if (pInfo->wndprocClbNumbersLb)
  8111. {
  8112. SetWindowLongPtr( pInfo->hwndClbNumbersLb,
  8113. GWLP_WNDPROC, (ULONG_PTR )pInfo->wndprocClbNumbersLb );
  8114. }
  8115. }
  8116. // Whistler bug: 195480 Dial-up connection dialog - Number of
  8117. // asterisks does not match the length of the password and causes
  8118. // confusion
  8119. //
  8120. if (pInfo->hItalicFont)
  8121. {
  8122. DeleteObject( pInfo->hItalicFont );
  8123. }
  8124. if (pInfo->hNormalFont)
  8125. {
  8126. DeleteObject( pInfo->hNormalFont );
  8127. }
  8128. if (pInfo->fComInitialized)
  8129. {
  8130. CoUninitialize();
  8131. }
  8132. // Clean up the low-res bitmap if appropriate
  8133. //
  8134. if ( pInfo->hbmOrig )
  8135. {
  8136. hbmNew = (HBITMAP)
  8137. SendMessage(
  8138. pInfo->hwndBmDialer,
  8139. STM_SETIMAGE,
  8140. IMAGE_BITMAP,
  8141. (LPARAM ) pInfo->hbmOrig );
  8142. if (hbmNew)
  8143. {
  8144. DeleteObject(hbmNew);
  8145. }
  8146. }
  8147. Free( pInfo );
  8148. }
  8149. }
  8150. //----------------------------------------------------------------------------
  8151. // Projection Result dialog
  8152. // Listed alphabetically following stub API and dialog proc
  8153. //----------------------------------------------------------------------------
  8154. BOOL
  8155. ProjectionResultDlg(
  8156. IN HWND hwndOwner,
  8157. IN TCHAR* pszLines,
  8158. OUT BOOL* pfDisableFailedProtocols )
  8159. // Popup the Projection Result dialog. 'HwndOwner' is the owning window.
  8160. // 'PszLines' is the status line text to display. See DpProjectionError.
  8161. // 'DwfDisableFailedProtocols' indicates user chose to disable the failed
  8162. // protocols.
  8163. //
  8164. // Returns true if user chooses to redial or lets it timeout, false if
  8165. // cancels.
  8166. //
  8167. {
  8168. INT_PTR nStatus;
  8169. PRARGS args;
  8170. TRACE( "ProjectionResultDlg" );
  8171. args.pszLines = pszLines;
  8172. args.pfDisableFailedProtocols = pfDisableFailedProtocols;
  8173. nStatus =
  8174. DialogBoxParam(
  8175. g_hinstDll,
  8176. MAKEINTRESOURCE( DID_PR_ProjectionResult ),
  8177. hwndOwner,
  8178. PrDlgProc,
  8179. (LPARAM )&args );
  8180. if (nStatus == -1)
  8181. {
  8182. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  8183. nStatus = FALSE;
  8184. }
  8185. return (nStatus) ? TRUE : FALSE;
  8186. }
  8187. INT_PTR CALLBACK
  8188. PrDlgProc(
  8189. IN HWND hwnd,
  8190. IN UINT unMsg,
  8191. IN WPARAM wparam,
  8192. IN LPARAM lparam )
  8193. // DialogProc callback for the Projection Result dialog. Parameters and
  8194. // return value are as described for standard windows 'DialogProc's.
  8195. //
  8196. {
  8197. #if 0
  8198. TRACE4( "PrDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  8199. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  8200. #endif
  8201. switch (unMsg)
  8202. {
  8203. case WM_INITDIALOG:
  8204. {
  8205. return PrInit( hwnd, (PRARGS* )lparam );
  8206. }
  8207. case WM_HELP:
  8208. case WM_CONTEXTMENU:
  8209. {
  8210. ContextHelp( g_adwPrHelp, hwnd, unMsg, wparam, lparam );
  8211. break;
  8212. }
  8213. case WM_COMMAND:
  8214. {
  8215. return PrCommand(
  8216. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  8217. }
  8218. }
  8219. return FALSE;
  8220. }
  8221. BOOL
  8222. PrCommand(
  8223. IN HWND hwnd,
  8224. IN WORD wNotification,
  8225. IN WORD wId,
  8226. IN HWND hwndCtrl )
  8227. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  8228. // the notification code of the command. 'wId' is the control/menu
  8229. // identifier of the command. 'HwndCtrl' is the control window handle of
  8230. // the command.
  8231. //
  8232. // Returns true if processed message, false otherwise.
  8233. //
  8234. {
  8235. DWORD dwErr;
  8236. TRACE3( "PrCommand(n=%d,i=%d,c=$%x)",
  8237. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  8238. switch (wId)
  8239. {
  8240. case IDOK:
  8241. case IDCANCEL:
  8242. {
  8243. BOOL fCb;
  8244. BOOL* pfDisable;
  8245. TRACE1( "%s pressed", (wId==IDOK) ? "OK" : "Cancel" );
  8246. fCb = IsDlgButtonChecked( hwnd, CID_PR_CB_DisableProtocols );
  8247. pfDisable = (BOOL* )GetWindowLongPtr( hwnd, DWLP_USER );
  8248. ASSERT( pfDisable );
  8249. *pfDisable = fCb;
  8250. EndDialog( hwnd, (wId == IDOK) );
  8251. return TRUE;
  8252. }
  8253. }
  8254. return FALSE;
  8255. }
  8256. BOOL
  8257. PrInit(
  8258. IN HWND hwndDlg,
  8259. IN PRARGS* pArgs )
  8260. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  8261. // 'PArgs' is caller's arguments to the stub API.
  8262. //
  8263. // Return false if focus was set, true otherwise, i.e. as defined for
  8264. // WM_INITDIALOG.
  8265. //
  8266. {
  8267. DWORD dwErr;
  8268. HWND hwndStText;
  8269. HWND hwndPbAccept;
  8270. HWND hwndPbHangUp;
  8271. HWND hwndCbDisable;
  8272. TRACE( "PrInit" );
  8273. hwndStText = GetDlgItem( hwndDlg, CID_PR_ST_Text );
  8274. ASSERT( hwndStText );
  8275. hwndPbAccept = GetDlgItem( hwndDlg, IDOK );
  8276. ASSERT( hwndPbAccept );
  8277. hwndPbHangUp = GetDlgItem( hwndDlg, IDCANCEL );
  8278. ASSERT( hwndPbHangUp );
  8279. hwndCbDisable = GetDlgItem( hwndDlg, CID_PR_CB_DisableProtocols );
  8280. ASSERT( hwndCbDisable );
  8281. {
  8282. TCHAR szBuf[ 1024 ];
  8283. TCHAR* psz;
  8284. // Build the message text.
  8285. //
  8286. szBuf[ 0 ] = TEXT('\0');
  8287. psz = PszFromId( g_hinstDll, SID_ProjectionResult1 );
  8288. if (psz)
  8289. {
  8290. lstrcat( szBuf, psz );
  8291. Free( psz );
  8292. }
  8293. lstrcat( szBuf, pArgs->pszLines );
  8294. psz = PszFromId( g_hinstDll, SID_ProjectionResult2 );
  8295. if (psz)
  8296. {
  8297. lstrcat( szBuf, psz );
  8298. Free( psz );
  8299. }
  8300. // Load the text into the static control, then stretch the window to a
  8301. // vertical size appropriate for the text.
  8302. //
  8303. {
  8304. HDC hdc;
  8305. RECT rect;
  8306. RECT rectNew;
  8307. HFONT hfont;
  8308. LONG dyGrow;
  8309. SetWindowText( hwndStText, szBuf );
  8310. GetClientRect( hwndStText, &rect );
  8311. hdc = GetDC( hwndStText );
  8312. if(NULL != hdc)
  8313. {
  8314. hfont = (HFONT )SendMessage( hwndStText, WM_GETFONT, 0, 0 );
  8315. if (hfont)
  8316. SelectObject( hdc, hfont );
  8317. rectNew = rect;
  8318. DrawText( hdc, szBuf, -1, &rectNew,
  8319. DT_CALCRECT | DT_WORDBREAK | DT_EXPANDTABS | DT_NOPREFIX );
  8320. ReleaseDC( hwndStText, hdc );
  8321. }
  8322. dyGrow = rectNew.bottom - rect.bottom;
  8323. ExpandWindow( hwndDlg, 0, dyGrow );
  8324. ExpandWindow( hwndStText, 0, dyGrow );
  8325. SlideWindow( hwndPbAccept, hwndDlg, 0, dyGrow );
  8326. SlideWindow( hwndPbHangUp, hwndDlg, 0, dyGrow );
  8327. SlideWindow( hwndCbDisable, hwndDlg, 0, dyGrow );
  8328. }
  8329. }
  8330. // Save address of caller's BOOL as the dialog context.
  8331. //
  8332. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pArgs->pfDisableFailedProtocols );
  8333. // Add context help button to title bar.
  8334. //
  8335. AddContextHelpButton( hwndDlg );
  8336. // Display the finished window above all other windows. The window
  8337. // position is set to "topmost" then immediately set to "not topmost"
  8338. // because we want it on top but not always-on-top. Always-on-top alone
  8339. // is incredibly annoying, e.g. it is always on top of the on-line help if
  8340. // user presses the Help button.
  8341. //
  8342. SetWindowPos(
  8343. hwndDlg, HWND_TOPMOST, 0, 0, 0, 0,
  8344. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  8345. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  8346. ShowWindow( hwndDlg, SW_SHOW );
  8347. SetWindowPos(
  8348. hwndDlg, HWND_NOTOPMOST, 0, 0, 0, 0,
  8349. SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE );
  8350. return TRUE;
  8351. }
  8352. //----------------------------------------------------------------------------
  8353. // Retry Authentication dialog
  8354. // Listed alphabetically following stub API and dialog proc
  8355. //----------------------------------------------------------------------------
  8356. BOOL
  8357. RetryAuthenticationDlg(
  8358. IN HWND hwndOwner,
  8359. IN DINFO* pDinfo )
  8360. // Pops up the retry authentication dialog. 'PDinfo' is the dial dialog
  8361. // common context.
  8362. //
  8363. // Returns true if user presses OK, false if Cancel or an error occurs.
  8364. //
  8365. {
  8366. INT_PTR nStatus;
  8367. TRACE( "RetryAuthenticationDlg" );
  8368. nStatus =
  8369. (BOOL )DialogBoxParam(
  8370. g_hinstDll,
  8371. MAKEINTRESOURCE( DID_UA_RetryAuthenticationUD ),
  8372. hwndOwner,
  8373. UaDlgProc,
  8374. (LPARAM )pDinfo );
  8375. if (nStatus == -1)
  8376. {
  8377. ErrorDlg( hwndOwner, SID_OP_LoadDlg, ERROR_UNKNOWN, NULL );
  8378. nStatus = FALSE;
  8379. }
  8380. return (BOOL )nStatus;
  8381. }
  8382. INT_PTR CALLBACK
  8383. UaDlgProc(
  8384. IN HWND hwnd,
  8385. IN UINT unMsg,
  8386. IN WPARAM wparam,
  8387. IN LPARAM lparam )
  8388. // DialogProc callback for the User Authentication dialog. Parameters and
  8389. // return value are as described for standard windows 'DialogProc's.
  8390. //
  8391. {
  8392. #if 0
  8393. TRACE4( "UaDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  8394. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  8395. #endif
  8396. switch (unMsg)
  8397. {
  8398. case WM_INITDIALOG:
  8399. {
  8400. return UaInit( hwnd, (DINFO* )lparam );
  8401. }
  8402. case WM_HELP:
  8403. case WM_CONTEXTMENU:
  8404. {
  8405. ContextHelp( g_adwUaHelp, hwnd, unMsg, wparam, lparam );
  8406. break;
  8407. }
  8408. case WM_COMMAND:
  8409. {
  8410. UAINFO* pInfo = (UAINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  8411. if (!pInfo)
  8412. {
  8413. // This happened in stress one night. Don't understand how
  8414. // unless it was a WinUser bug or something. Anyhow, this
  8415. // avoids an AV in such case.
  8416. //
  8417. break;
  8418. }
  8419. return UaCommand(
  8420. pInfo, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  8421. }
  8422. case WM_DESTROY:
  8423. {
  8424. UaTerm( hwnd );
  8425. break;
  8426. }
  8427. }
  8428. return FALSE;
  8429. }
  8430. BOOL
  8431. UaCommand(
  8432. IN UAINFO* pInfo,
  8433. IN WORD wNotification,
  8434. IN WORD wId,
  8435. IN HWND hwndCtrl )
  8436. // Called on WM_COMMAND. 'PInfo' is the dialog context. 'WNotification'
  8437. // is the notification code of the command. 'wId' is the control/menu
  8438. // identifier of the command. 'HwndCtrl' is the control window handle of
  8439. // the command.
  8440. //
  8441. // Returns true if processed message, false otherwise.
  8442. //
  8443. {
  8444. TRACE3( "UaCommand(n=%d,i=%d,c=$%x)",
  8445. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  8446. switch (wId)
  8447. {
  8448. case CID_UA_EB_UserName:
  8449. {
  8450. if (pInfo->fAutoLogonPassword && wNotification == EN_CHANGE)
  8451. {
  8452. // User's changing the username in auto-logon retry mode,
  8453. // which means we have to admit we don't really have the text
  8454. // password and force him to re-enter it.
  8455. //
  8456. pInfo->fAutoLogonPassword = FALSE;
  8457. SetWindowText( pInfo->hwndEbPassword, TEXT("") );
  8458. }
  8459. break;
  8460. }
  8461. case CID_UA_EB_Password:
  8462. {
  8463. if (wNotification == EN_CHANGE)
  8464. {
  8465. pInfo->fAutoLogonPassword = FALSE;
  8466. }
  8467. break;
  8468. }
  8469. case IDOK:
  8470. {
  8471. UaSave( pInfo );
  8472. EndDialog( pInfo->hwndDlg, TRUE );
  8473. return TRUE;
  8474. }
  8475. case IDCANCEL:
  8476. {
  8477. TRACE( "Cancel pressed" );
  8478. EndDialog( pInfo->hwndDlg, FALSE );
  8479. return TRUE;
  8480. }
  8481. }
  8482. return FALSE;
  8483. }
  8484. BOOL
  8485. UaInit(
  8486. IN HWND hwndDlg,
  8487. IN DINFO* pArgs )
  8488. // Called on WM_INITDIALOG. 'hwndDlg' is the handle of the owning window.
  8489. // 'PArgs' is caller's arguments as passed to the stub API.
  8490. //
  8491. // Return false if focus was set, true otherwise, i.e. as defined for
  8492. // WM_INITDIALOG.
  8493. //
  8494. {
  8495. DWORD dwErr;
  8496. UAINFO* pInfo;
  8497. PBENTRY* pEntry;
  8498. TRACE( "UaInit" );
  8499. // Allocate the dialog context block. Initialize minimally for proper
  8500. // cleanup, then attach to the dialog window.
  8501. //
  8502. {
  8503. pInfo = Malloc( sizeof(*pInfo) );
  8504. if (!pInfo)
  8505. {
  8506. ErrorDlg( hwndDlg, SID_OP_LoadDlg, ERROR_NOT_ENOUGH_MEMORY, NULL );
  8507. EndDialog( hwndDlg, FALSE );
  8508. return TRUE;
  8509. }
  8510. ZeroMemory( pInfo, sizeof(*pInfo) );
  8511. pInfo->pArgs = pArgs;
  8512. pInfo->hwndDlg = hwndDlg;
  8513. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  8514. TRACE( "Context set" );
  8515. }
  8516. pInfo->fDomain = TRUE;
  8517. pInfo->hwndEbUserName = GetDlgItem( hwndDlg, CID_UA_EB_UserName );
  8518. ASSERT( pInfo->hwndEbUserName );
  8519. pInfo->hwndEbPassword = GetDlgItem( hwndDlg, CID_UA_EB_Password );
  8520. ASSERT( pInfo->hwndEbPassword );
  8521. if (pInfo->fDomain)
  8522. {
  8523. pInfo->hwndEbDomain = GetDlgItem( hwndDlg, CID_UA_EB_Domain );
  8524. ASSERT( pInfo->hwndEbDomain );
  8525. }
  8526. pInfo->hwndCbSavePw = GetDlgItem( hwndDlg, CID_UA_CB_SavePassword );
  8527. ASSERT( pInfo->hwndCbSavePw );
  8528. pEntry = pArgs->pEntry;
  8529. // Set the title.
  8530. //
  8531. {
  8532. TCHAR* pszTitleFormat;
  8533. TCHAR* pszTitle;
  8534. TCHAR* apszArgs[ 1 ];
  8535. pszTitleFormat = GetText( hwndDlg );
  8536. if (pszTitleFormat)
  8537. {
  8538. apszArgs[ 0 ] = pEntry->pszEntryName;
  8539. pszTitle = NULL;
  8540. FormatMessage(
  8541. FORMAT_MESSAGE_FROM_STRING
  8542. | FORMAT_MESSAGE_ALLOCATE_BUFFER
  8543. | FORMAT_MESSAGE_ARGUMENT_ARRAY,
  8544. pszTitleFormat, 0, 0, (LPTSTR )&pszTitle, 1,
  8545. (va_list* )apszArgs );
  8546. Free( pszTitleFormat );
  8547. if (pszTitle)
  8548. {
  8549. SetWindowText( hwndDlg, pszTitle );
  8550. LocalFree( pszTitle );
  8551. }
  8552. }
  8553. }
  8554. // Fill edit fields with initial values.
  8555. //
  8556. Edit_LimitText( pInfo->hwndEbUserName, UNLEN );
  8557. Edit_LimitText( pInfo->hwndEbPassword, PWLEN );
  8558. if (pInfo->fDomain)
  8559. {
  8560. Edit_LimitText( pInfo->hwndEbDomain, DNLEN );
  8561. }
  8562. {
  8563. BOOL fUserNameSet = FALSE;
  8564. BOOL fPasswordSet = FALSE;
  8565. if (pEntry->fAutoLogon && !pInfo->pArgs->pNoUser)
  8566. {
  8567. // On the first retry use the logged on user's name. Act like the
  8568. // user's password is in the edit box. If he changes the username
  8569. // or password we'll have to admit we don't have it, but he'll
  8570. // probably just change the domain.
  8571. //
  8572. if (pArgs->rdp.szUserName[ 0 ] == TEXT('\0'))
  8573. {
  8574. SetWindowText( pInfo->hwndEbUserName, GetLogonUser() );
  8575. fUserNameSet = TRUE;
  8576. }
  8577. if (pArgs->rdp.szPassword[ 0 ] == TEXT('\0'))
  8578. {
  8579. SetWindowText( pInfo->hwndEbPassword, TEXT("********") );
  8580. pInfo->fAutoLogonPassword = TRUE;
  8581. fPasswordSet = TRUE;
  8582. }
  8583. }
  8584. if (!fUserNameSet)
  8585. {
  8586. SetWindowText( pInfo->hwndEbUserName, pArgs->rdp.szUserName );
  8587. }
  8588. if (!fPasswordSet)
  8589. {
  8590. // Whistler bug 254385 encode password when not being used
  8591. // Assumed password was encoded previously
  8592. //
  8593. DecodePassword( pArgs->rdp.szPassword );
  8594. SetWindowText( pInfo->hwndEbPassword, pArgs->rdp.szPassword );
  8595. EncodePassword( pArgs->rdp.szPassword );
  8596. }
  8597. if (pInfo->fDomain)
  8598. {
  8599. SetWindowText( pInfo->hwndEbDomain, pArgs->rdp.szDomain );
  8600. }
  8601. }
  8602. if (pArgs->pNoUser || pArgs->fDisableSavePw)
  8603. {
  8604. // Can't stash password without a logon context, so hide the checkbox.
  8605. //
  8606. ASSERT( !HaveSavedPw( pArgs ) );
  8607. EnableWindow( pInfo->hwndCbSavePw, FALSE );
  8608. ShowWindow( pInfo->hwndCbSavePw, SW_HIDE );
  8609. }
  8610. else
  8611. {
  8612. // Check "save password" if a password was previously cached. Maybe
  8613. // he changed the password while on the LAN.
  8614. //
  8615. Button_SetCheck( pInfo->hwndCbSavePw, HaveSavedPw( pArgs ) );
  8616. }
  8617. // Position the dialog per caller's instructions.
  8618. //
  8619. PositionDlg( hwndDlg,
  8620. (pArgs->pArgs->dwFlags & RASDDFLAG_PositionDlg),
  8621. pArgs->pArgs->xDlg, pArgs->pArgs->yDlg );
  8622. SetForegroundWindow( hwndDlg );
  8623. // Add context help button to title bar.
  8624. //
  8625. AddContextHelpButton( hwndDlg );
  8626. // Set focus to the empty username or empty password, or if both are
  8627. // present to the domain if auto-logon or the password if not.
  8628. //
  8629. if (Edit_GetTextLength( pInfo->hwndEbUserName ) == 0)
  8630. {
  8631. Edit_SetSel( pInfo->hwndEbUserName, 0, -1 );
  8632. SetFocus( pInfo->hwndEbUserName );
  8633. }
  8634. else if (Edit_GetTextLength( pInfo->hwndEbPassword ) == 0
  8635. || !pEntry->fAutoLogon
  8636. || !pInfo->fDomain)
  8637. {
  8638. Edit_SetSel( pInfo->hwndEbPassword, 0, -1 );
  8639. SetFocus( pInfo->hwndEbPassword );
  8640. }
  8641. else
  8642. {
  8643. ASSERT( pInfo->fDomain );
  8644. Edit_SetSel( pInfo->hwndEbDomain, 0, -1 );
  8645. SetFocus( pInfo->hwndEbDomain );
  8646. }
  8647. // Hide the Dial Progress dialog.
  8648. //
  8649. SetOffDesktop( GetParent( hwndDlg ), SOD_MoveOff, NULL );
  8650. return FALSE;
  8651. }
  8652. VOID
  8653. UaSave(
  8654. IN UAINFO* pInfo )
  8655. // Called when the OK button is pressed.
  8656. //
  8657. // Returns true if user presses OK, false if Cancel or an error occurs.
  8658. //
  8659. {
  8660. DWORD dwErr;
  8661. PBENTRY* pEntry;
  8662. BOOL fSavePw;
  8663. RASDIALPARAMS* prdp;
  8664. RASCREDENTIALS rc;
  8665. TRACE( "UaSave" );
  8666. prdp = &pInfo->pArgs->rdp;
  8667. GetWindowText( pInfo->hwndEbUserName, prdp->szUserName, UNLEN + 1 );
  8668. // Whistler bug 254385 encode password when not being used
  8669. // Assumed password was not encoded by GetWindowText()
  8670. //
  8671. GetWindowText( pInfo->hwndEbPassword, prdp->szPassword, PWLEN + 1 );
  8672. EncodePassword( prdp->szPassword );
  8673. if (pInfo->fDomain)
  8674. {
  8675. GetWindowText( pInfo->hwndEbDomain, prdp->szDomain, DNLEN + 1 );
  8676. //
  8677. //if the Domain is not empty, set the "include Windows Logon Domain check box on Option Tab"
  8678. // for bug 167229 whistler
  8679. //
  8680. if ( ( 0 < lstrlen ( prdp->szDomain ) ) && (!pInfo->pArgs->pEntry->fPreviewDomain ))
  8681. {
  8682. pInfo->pArgs->pEntry->fPreviewDomain = TRUE;
  8683. pInfo->pArgs->pEntry->fDirty = TRUE;
  8684. dwErr = WritePhonebookFile( pInfo->pArgs->pFile, NULL );
  8685. if (dwErr != 0)
  8686. {
  8687. ErrorDlg( pInfo->hwndDlg, SID_OP_WritePhonebook, dwErr, NULL );
  8688. }
  8689. }
  8690. }
  8691. pEntry = pInfo->pArgs->pEntry;
  8692. if (pEntry->fAutoLogon && !pInfo->pArgs->pNoUser)
  8693. {
  8694. if (pInfo->fAutoLogonPassword)
  8695. {
  8696. // User did not change username or password, so continue to
  8697. // retrieve logon username and password credentials.
  8698. //
  8699. TRACE( "Retain auto-logon" );
  8700. prdp->szUserName[ 0 ] = TEXT('\0');
  8701. prdp->szPassword[ 0 ] = TEXT('\0');
  8702. }
  8703. else
  8704. {
  8705. // User changed username and/or password so we can no longer
  8706. // retrieve the logon username and password credentials from the
  8707. // system. Switch the entry to non-auto-logon mode.
  8708. //
  8709. TRACE( "Disable auto-logon" );
  8710. pEntry->fAutoLogon = FALSE;
  8711. pInfo->pArgs->fResetAutoLogon = TRUE;
  8712. }
  8713. }
  8714. ZeroMemory( &rc, sizeof(rc) );
  8715. rc.dwSize = sizeof(rc);
  8716. lstrcpyn( rc.szUserName, prdp->szUserName, UNLEN + 1 );
  8717. // Whistler bug 254385 encode password when not being used
  8718. // Assumed password was encoded previously
  8719. //
  8720. DecodePassword( prdp->szPassword );
  8721. lstrcpyn( rc.szPassword, prdp->szPassword, PWLEN + 1 );
  8722. EncodePassword( prdp->szPassword );
  8723. lstrcpyn( rc.szDomain, prdp->szDomain, DNLEN + 1 );
  8724. if (pInfo->pArgs->pNoUser)
  8725. {
  8726. lstrcpyn( pInfo->pArgs->pNoUser->szUserName, rc.szUserName, UNLEN + 1 );
  8727. // Whistler bug 254385 encode password when not being used
  8728. // Assumed password was not encoded previously
  8729. //
  8730. lstrcpyn( pInfo->pArgs->pNoUser->szPassword, rc.szPassword, PWLEN + 1 );
  8731. EncodePassword( pInfo->pArgs->pNoUser->szPassword );
  8732. lstrcpyn( pInfo->pArgs->pNoUser->szDomain, rc.szDomain, DNLEN + 1 );
  8733. *pInfo->pArgs->pfNoUserChanged = TRUE;
  8734. }
  8735. else if (!pInfo->pArgs->fDisableSavePw)
  8736. {
  8737. ASSERT( g_pRasSetCredentials );
  8738. if (Button_GetCheck( pInfo->hwndCbSavePw ))
  8739. {
  8740. // User chose "save password". Cache username, password, and
  8741. // domain.
  8742. //
  8743. rc.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain;
  8744. // Whistler bug: 288234 When switching back and forth from
  8745. // "I connect" and "Any user connects" password is not
  8746. // caching correctly
  8747. //
  8748. if( (pInfo->pArgs->fHaveSavedPwGlobal)
  8749. && !pInfo->pArgs->fHaveSavedPwUser
  8750. && IsPublicPhonebook(pInfo->pArgs->pFile->pszPath))
  8751. {
  8752. rc.dwMask |= RASCM_DefaultCreds;
  8753. }
  8754. TRACE( "RasSetCredentials(u|p|d,FALSE)" );
  8755. dwErr = g_pRasSetCredentials(
  8756. pInfo->pArgs->pFile->pszPath,
  8757. pInfo->pArgs->pEntry->pszEntryName,
  8758. &rc, FALSE );
  8759. TRACE1( "RasSetCredentials=%d", dwErr );
  8760. if (dwErr != 0)
  8761. {
  8762. ErrorDlg( pInfo->hwndDlg, SID_OP_CachePw, dwErr, NULL );
  8763. }
  8764. }
  8765. else
  8766. {
  8767. // Whistler bug: 288234 When switching back and forth from
  8768. // "I connect" and "Any user connects" password is not
  8769. // caching correctly
  8770. //
  8771. // User chose not to save password; Cache username and domain only
  8772. //
  8773. rc.dwMask = RASCM_UserName | RASCM_Domain;
  8774. TRACE( "RasSetCredentials(u|d,FALSE)" );
  8775. dwErr = g_pRasSetCredentials(
  8776. pInfo->pArgs->pFile->pszPath,
  8777. pInfo->pArgs->pEntry->pszEntryName,
  8778. &rc, FALSE );
  8779. TRACE1( "RasSetCredentials=%d", dwErr );
  8780. if (dwErr != 0)
  8781. {
  8782. ErrorDlg( pInfo->hwndDlg, SID_OP_UncachePw, dwErr, NULL );
  8783. }
  8784. // Whistler bug: 288234 When switching back and forth from
  8785. // "I connect" and "Any user connects" password is not
  8786. // caching correctly
  8787. //
  8788. // Delete the password saved per-user; Keep the user name
  8789. // and domain saved, however.
  8790. //
  8791. if (pInfo->pArgs->fHaveSavedPwUser)
  8792. {
  8793. DeleteSavedCredentials(
  8794. pInfo->pArgs,
  8795. pInfo->hwndDlg,
  8796. FALSE,
  8797. FALSE );
  8798. pInfo->pArgs->fHaveSavedPwUser = FALSE;
  8799. }
  8800. // Delete the global credentials.
  8801. //
  8802. // Note that we have to delete the global identity
  8803. // as well because we do not support deleting
  8804. // just the global password. This is so that
  8805. // RasSetCredentials can emulate RasSetDialParams.
  8806. //
  8807. else if (pInfo->pArgs->fHaveSavedPwGlobal)
  8808. {
  8809. DeleteSavedCredentials(
  8810. pInfo->pArgs,
  8811. pInfo->hwndDlg,
  8812. TRUE,
  8813. TRUE );
  8814. pInfo->pArgs->fHaveSavedPwGlobal = FALSE;
  8815. }
  8816. }
  8817. }
  8818. ZeroMemory( rc.szPassword, sizeof(rc.szPassword) );
  8819. }
  8820. VOID
  8821. UaTerm(
  8822. IN HWND hwndDlg )
  8823. // Called on WM_DESTROY. 'HwndDlg' is that handle of the dialog window.
  8824. //
  8825. {
  8826. UAINFO* pInfo = (UAINFO* )GetWindowLongPtr( hwndDlg, DWLP_USER );
  8827. TRACE( "UaTerm" );
  8828. if (pInfo)
  8829. {
  8830. // Restore the Dial Progress dialog.
  8831. //
  8832. SetOffDesktop( GetParent( hwndDlg ), SOD_MoveBackFree, NULL );
  8833. Free( pInfo );
  8834. }
  8835. }
  8836. //----------------------------------------------------------------------------
  8837. // VPN Double Dial help dialog
  8838. // Listed alphabetically following stub API and dialog proc
  8839. //----------------------------------------------------------------------------
  8840. BOOL
  8841. VpnDoubleDialDlg(
  8842. IN HWND hwndOwner,
  8843. IN DINFO* pInfo )
  8844. // Popup the VPN double dial help dialog. 'HwndOwner' is the owning
  8845. // window. 'PInfo' is the dialing context information.
  8846. //
  8847. // Returns false if user sees the dialog and decides not to continue, true
  8848. // otherwise.
  8849. //
  8850. {
  8851. INT_PTR nStatus;
  8852. TRACE( "VpnDoubleDialDlg" );
  8853. if (pInfo->pEntryMain->dwType != RASET_Vpn
  8854. || !pInfo->fPrerequisiteDial
  8855. || pInfo->pEntryMain->fSkipDoubleDialDialog)
  8856. {
  8857. return TRUE;
  8858. }
  8859. nStatus =
  8860. (BOOL )DialogBoxParam(
  8861. g_hinstDll,
  8862. MAKEINTRESOURCE( DID_VI_VpnInitial ),
  8863. hwndOwner,
  8864. ViDlgProc,
  8865. (LPARAM )pInfo );
  8866. if (nStatus == -1)
  8867. {
  8868. nStatus = FALSE;
  8869. }
  8870. return !!(nStatus);
  8871. }
  8872. INT_PTR CALLBACK
  8873. ViDlgProc(
  8874. IN HWND hwnd,
  8875. IN UINT unMsg,
  8876. IN WPARAM wparam,
  8877. IN LPARAM lparam )
  8878. // DialogProc callback for the dialog. Parameters and return value are as
  8879. // described for standard windows 'DialogProc's.
  8880. //
  8881. {
  8882. #if 0
  8883. TRACE4( "ViDlgProc(h=$%x,m=$%x,w=$%x,l=$%x)",
  8884. (DWORD )hwnd, (DWORD )unMsg, (DWORD )wparam, (DWORD )lparam );
  8885. #endif
  8886. switch (unMsg)
  8887. {
  8888. case WM_INITDIALOG:
  8889. {
  8890. return ViInit( hwnd, (DINFO* )lparam );
  8891. }
  8892. case WM_COMMAND:
  8893. {
  8894. return ViCommand(
  8895. hwnd, HIWORD( wparam ), LOWORD( wparam ), (HWND )lparam );
  8896. }
  8897. }
  8898. return FALSE;
  8899. }
  8900. BOOL
  8901. ViCommand(
  8902. IN HWND hwnd,
  8903. IN WORD wNotification,
  8904. IN WORD wId,
  8905. IN HWND hwndCtrl )
  8906. // Called on WM_COMMAND. 'Hwnd' is the dialog window. 'WNotification' is
  8907. // the notification code of the command. 'wId' is the control/menu
  8908. // identifier of the command. 'HwndCtrl' is the control window handle of
  8909. // the command.
  8910. //
  8911. // Returns true if processed message, false otherwise.
  8912. //
  8913. {
  8914. TRACE3( "ViCommand(n=%d,i=%d,c=$%x)",
  8915. (DWORD )wNotification, (DWORD )wId, (ULONG_PTR )hwndCtrl );
  8916. switch (wId)
  8917. {
  8918. case IDYES:
  8919. case IDNO:
  8920. {
  8921. // Per bug 261955, the box setting is saved when either the Yes or
  8922. // No, but not the 'X' button, is pressed.
  8923. //
  8924. DINFO* pInfo = (DINFO* )GetWindowLongPtr( hwnd, DWLP_USER );
  8925. ASSERT( pInfo );
  8926. if (IsDlgButtonChecked( hwnd, CID_VI_CB_SkipMessage ))
  8927. {
  8928. pInfo->pEntryMain->fSkipDoubleDialDialog = TRUE;
  8929. pInfo->pEntryMain->fDirty = TRUE;
  8930. WritePhonebookFile( pInfo->pFileMain, NULL );
  8931. }
  8932. EndDialog( hwnd, (wId == IDYES) );
  8933. return TRUE;
  8934. }
  8935. case IDCANCEL:
  8936. {
  8937. EndDialog( hwnd, FALSE );
  8938. return TRUE;
  8939. }
  8940. }
  8941. return FALSE;
  8942. }
  8943. BOOL
  8944. ViInit(
  8945. IN HWND hwndDlg,
  8946. IN DINFO* pInfo )
  8947. // Called on WM_INITDIALOG. 'HwndDlg' is the handle of dialog. 'PUser'
  8948. // is caller's argument to the stub API.
  8949. //
  8950. // Return false if focus was set, true otherwise, i.e. as defined for
  8951. // WM_INITDIALOG.
  8952. //
  8953. {
  8954. TRACE( "ViInit" );
  8955. // Set the dialog context.
  8956. //
  8957. SetWindowLongPtr( hwndDlg, DWLP_USER, (ULONG_PTR )pInfo );
  8958. // Set the explanatory text.
  8959. //
  8960. {
  8961. MSGARGS msgargs;
  8962. ZeroMemory( &msgargs, sizeof(msgargs) );
  8963. msgargs.apszArgs[ 0 ] = pInfo->pEntryMain->pszEntryName;
  8964. msgargs.apszArgs[ 1 ] = pInfo->pEntry->pszEntryName;
  8965. msgargs.fStringOutput = TRUE;
  8966. MsgDlgUtil( NULL, SID_VI_ST_Explain, &msgargs, g_hinstDll, 0 );
  8967. if (msgargs.pszOutput)
  8968. {
  8969. SetDlgItemText( hwndDlg, CID_VI_ST_Explain, msgargs.pszOutput );
  8970. Free( msgargs.pszOutput );
  8971. }
  8972. }
  8973. // Display finished window.
  8974. //
  8975. CenterWindow( hwndDlg, GetParent( hwndDlg ) );
  8976. SetForegroundWindow( hwndDlg );
  8977. return TRUE;
  8978. }
  8979. DWORD
  8980. DwTerminalDlg(
  8981. LPCWSTR lpszPhonebook,
  8982. LPCWSTR lpszEntry,
  8983. RASDIALPARAMS *prdp,
  8984. HWND hwndOwner,
  8985. HRASCONN hRasconn)
  8986. {
  8987. DWORD dwErr = ERROR_SUCCESS;
  8988. PBENTRY *pEntry = NULL;
  8989. PBFILE pbfile;
  8990. DTLNODE *pNode = NULL;
  8991. WCHAR szIpAddress[ TERM_IpAddress ];
  8992. DWORD sidTitle;
  8993. WCHAR *pszIpAddress;
  8994. //
  8995. //Initialize memory for Whistler bug 160888
  8996. //
  8997. ZeroMemory(&pbfile, sizeof(PBFILE));
  8998. pbfile.hrasfile = -1;
  8999. dwErr = LoadRas( g_hinstDll, hwndOwner );
  9000. if (ERROR_SUCCESS != dwErr)
  9001. {
  9002. goto done;
  9003. }
  9004. dwErr = GetPbkAndEntryName(
  9005. lpszPhonebook,
  9006. lpszEntry,
  9007. 0,
  9008. &pbfile,
  9009. &pNode);
  9010. if( (NULL == pNode)
  9011. || (ERROR_SUCCESS != dwErr))
  9012. {
  9013. dwErr = ERROR_CANNOT_FIND_PHONEBOOK_ENTRY;
  9014. goto done;
  9015. }
  9016. pEntry = (PBENTRY *) DtlGetData(pNode);
  9017. ASSERT(NULL != pEntry);
  9018. if(NULL == pEntry)
  9019. {
  9020. goto done;
  9021. }
  9022. if (pEntry->dwBaseProtocol == BP_Slip)
  9023. {
  9024. lstrcpyn(
  9025. szIpAddress,
  9026. (pEntry->pszIpAddress) ? pEntry->pszIpAddress : TEXT("0.0.0.0"),
  9027. sizeof(szIpAddress) / sizeof(TCHAR));
  9028. pszIpAddress = szIpAddress;
  9029. sidTitle = SID_T_SlipTerminal;
  9030. }
  9031. else
  9032. {
  9033. szIpAddress[0] = TEXT('\0');
  9034. pszIpAddress = szIpAddress;
  9035. sidTitle = SID_T_PostconnectTerminal;
  9036. }
  9037. if (!TerminalDlg(
  9038. pEntry, prdp, hwndOwner,
  9039. hRasconn, sidTitle, pszIpAddress ))
  9040. {
  9041. TRACE( "TerminalDlg==FALSE" );
  9042. dwErr = E_FAIL;
  9043. goto done;
  9044. }
  9045. TRACE2( "pszIpAddress=0x%08x(%ls)", pszIpAddress,
  9046. pszIpAddress ? pszIpAddress : TEXT("") );
  9047. TRACE2( "pEntry->pszIpAddress=0x%08x(%ls)", pEntry->pszIpAddress,
  9048. pEntry->pszIpAddress ? pEntry->pszIpAddress : TEXT("") );
  9049. if (pszIpAddress[0]
  9050. && (!pEntry->pszIpAddress
  9051. || lstrcmp( pszIpAddress, pEntry->pszIpAddress ) != 0))
  9052. {
  9053. Free0( pEntry->pszIpAddress );
  9054. pEntry->pszIpAddress = StrDup( szIpAddress );
  9055. pEntry->fDirty = TRUE;
  9056. dwErr = WritePhonebookFile( &pbfile, NULL );
  9057. if (dwErr != 0)
  9058. {
  9059. ErrorDlg( hwndOwner, SID_OP_WritePhonebook, dwErr, NULL );
  9060. }
  9061. }
  9062. done:
  9063. ClosePhonebookFile(&pbfile);
  9064. return dwErr;
  9065. }