Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

13923 lines
451 KiB

  1. //+----------------------------------------------------------------------------
  2. //
  3. // File: connect.cpp
  4. //
  5. // Module: CMDIAL32.DLL
  6. //
  7. // Synopsis: The main code path for establishing a connection.
  8. //
  9. // Copyright (c) 1998-1999 Microsoft Corporation
  10. //
  11. // Author: nickball Created 2/10/98
  12. //
  13. //+----------------------------------------------------------------------------
  14. #include "cmmaster.h"
  15. //
  16. // Local includes
  17. //
  18. #include "ConnStat.h"
  19. #include "CompChck.h"
  20. #include "Dialogs.h"
  21. #include "ActList.h"
  22. #include "dial_str.h"
  23. #include "dun_str.h"
  24. #include "dl_str.h"
  25. #include "pwd_str.h"
  26. #include "tunl_str.h"
  27. #include "mon_str.h"
  28. #include "conact_str.h"
  29. #include "pbk_str.h"
  30. #include "stp_str.h"
  31. #include "profile_str.h"
  32. #include "ras_str.h"
  33. #include "cmtiming.h"
  34. #include "cm_eap.cpp"
  35. #include "MemberOfGroup.cpp"
  36. //
  37. // Include the header for linking to the SafeNet Config APIs
  38. //
  39. #include "cmsafenet.h"
  40. //
  41. // .CMP and .CMS flag used only by connect.cpp
  42. //
  43. const TCHAR* const c_pszCmEntryMonitorCallingProgram= TEXT("MonitorCallingProgram");
  44. const TCHAR* const c_pszCmEntryUserNameOptional = TEXT("UserNameOptional");
  45. const TCHAR* const c_pszCmEntryDomainOptional = TEXT("DomainOptional");
  46. const TCHAR* const c_pszCmEntryServiceType = TEXT("ServiceType");
  47. const TCHAR* const c_pszCmEntryRedialDelay = TEXT("RedialDelay");
  48. const TCHAR* const c_pszCmEntryRedial = TEXT("Redial");
  49. const TCHAR* const c_pszCmEntryIdle = TEXT("Idle");
  50. const TCHAR* const c_pszCmEntryDialAutoMessage = TEXT("DialAutoMessage");
  51. const TCHAR* const c_pszCmEntryCheckOsComponents = TEXT("CheckOSComponents");
  52. const TCHAR* const c_pszCmEntryDoNotCheckBindings = TEXT("DoNotCheckBindings");
  53. const TCHAR* const c_pszCmEntryIsdnDialMode = TEXT("IsdnDialMode");
  54. const TCHAR* const c_pszCmEntryResetPassword = TEXT("ResetPassword");
  55. const TCHAR* const c_pszCmEntryCustomButtonText = TEXT("CustomButtonText");
  56. const TCHAR* const c_pszCmEntryCustomButtonToolTip = TEXT("CustomButtonToolTip");
  57. const TCHAR* const c_pszCmDynamicPhoneNumber = TEXT("DynamicPhoneNumber");
  58. const TCHAR* const c_pszCmNoDialingRules = TEXT("NoDialingRules");
  59. const TCHAR* const c_pszCmEntryHideDialAuto = TEXT("HideDialAutomatically");
  60. const TCHAR* const c_pszCmEntryHideRememberPwd = TEXT("HideRememberPassword");
  61. const TCHAR* const c_pszCmEntryHideRememberInetPwd = TEXT("HideRememberInternetPassword");
  62. const TCHAR* const c_pszCmEntryHideInetUserName = TEXT("HideInternetUserName");
  63. const TCHAR* const c_pszCmEntryHideInetPassword = TEXT("HideInternetPassword");
  64. const TCHAR* const c_pszCmEntryHideUnattended = TEXT("HideUnattended");
  65. const TCHAR* const c_pszCmEntryRegion = TEXT("Region");
  66. const TCHAR* const c_pszCmEntryPhonePrefix = TEXT("Phone");
  67. const TCHAR* const c_pszCmEntryPhoneCanonical = TEXT("PhoneCanonical");
  68. const TCHAR* const c_pszCmEntryPhoneDunPrefix = TEXT("DUN");
  69. const TCHAR* const c_pszCmEntryPhoneDescPrefix = TEXT("Description");
  70. const TCHAR* const c_pszCmEntryPhoneCountryPrefix = TEXT("PhoneCountry");
  71. const TCHAR* const c_pszCmEntryPhoneSourcePrefix = TEXT("PhoneSource");
  72. const TCHAR* const c_pszCmEntryUseDialingRules = TEXT("UseDialingRules");
  73. const TCHAR* const c_pszCmEntryAnimatedLogo = TEXT("AnimatedLogo");
  74. const TCHAR* const c_pszCmSectionAnimatedLogo = TEXT("Animated Logo");
  75. const TCHAR* const c_pszCmSectionAnimatedActions = TEXT("Animation Actions");
  76. const TCHAR* const c_pszCmEntryAniMovie = TEXT("Movie");
  77. const TCHAR* const c_pszCmEntryAniPsInteractive = TEXT("Initial");
  78. const TCHAR* const c_pszCmEntryAniPsDialing0 = TEXT("Dialing0");
  79. const TCHAR* const c_pszCmEntryAniPsDialing1 = TEXT("Dialing1");
  80. const TCHAR* const c_pszCmEntryAniPsPausing = TEXT("Pausing");
  81. const TCHAR* const c_pszCmEntryAniPsAuthenticating = TEXT("Authenticating");
  82. const TCHAR* const c_pszCmEntryAniPsOnline = TEXT("Connected");
  83. const TCHAR* const c_pszCmEntryAniPsTunnel = TEXT("Tunneling");
  84. const TCHAR* const c_pszCmEntryAniPsError = TEXT("Error");
  85. const TCHAR* const c_pszCmEntryWriteDialParams = TEXT("WriteRasDialUpParams");
  86. //
  87. // Used for loading EAP identity DLL
  88. //
  89. const TCHAR* const c_pszRasEapRegistryLocation = TEXT("System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP");
  90. const TCHAR* const c_pszRasEapValueNameIdentity = TEXT("IdentityPath");
  91. const TCHAR* const c_pszInvokeUsernameDialog = TEXT("InvokeUsernameDialog");
  92. //
  93. // Definitions
  94. //
  95. #define MAX_OBJECT_WAIT 30000 // milliseconds to wait for cmmon launch and RNA thread return
  96. //============================================================================
  97. static void LoadPhoneInfoFromProfile(ArgsStruct *pArgs);
  98. HRESULT UpdateTable(ArgsStruct *pArgs, CmConnectState CmState);
  99. HRESULT ConnectMonitor(ArgsStruct *pArgs);
  100. void OnMainExit(ArgsStruct *pArgs);
  101. void ProcessCleanup(ArgsStruct* pArgs);
  102. VOID UpdateError(ArgsStruct *pArgs, DWORD dwErr);
  103. DWORD GetEapUserId(ArgsStruct *pArgs,
  104. HWND hwndDlg,
  105. LPTSTR pszRasPbk,
  106. LPBYTE pbEapAuthData,
  107. DWORD dwEapAuthDataSize,
  108. DWORD dwCustomAuthKey,
  109. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity);
  110. DWORD CmEapGetIdentity(ArgsStruct *pArgs,
  111. LPTSTR pszRasPbk,
  112. LPBYTE pbEapAuthData,
  113. DWORD dwEapAuthDataSize,
  114. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity);
  115. void CheckStartupInfo(HWND hwndDlg, ArgsStruct *pArgs);
  116. BOOL InitConnect(ArgsStruct *pArgs);
  117. void ObfuscatePasswordEdit(ArgsStruct *pArgs);
  118. void DeObfuscatePasswordEdit(ArgsStruct *pArgs);
  119. void GetPasswordFromEdit(ArgsStruct *pArgs);
  120. DWORD ReSaveEapCustomAuthData(ArgsStruct *pArgs, CIni *pcini, BOOL fTunnelEntry, LPTSTR pszRasPbk);
  121. HRESULT EraseDunSettingsEapData(LPCTSTR pszSection, LPCTSTR pszCmsFile);
  122. DWORD SaveNewEAPCustomAuthData(LPCTSTR pszCmsFile, LPTSTR pszLoadSection, DWORD cbEapAuthData, PBYTE pbEapAuthData, PBYTE pbEapStruct);
  123. //+----------------------------------------------------------------------------
  124. //
  125. // Function: GetPasswordFromEdit
  126. //
  127. // Synopsis: Updates pArgs->szPassword with contents of edit control
  128. //
  129. // Arguments: pArgs - Ptr to global Args struct
  130. //
  131. // Returns: Nothing
  132. //
  133. // History: nickball Created 04/13/00
  134. //
  135. //+----------------------------------------------------------------------------
  136. void GetPasswordFromEdit(ArgsStruct *pArgs)
  137. {
  138. MYDBGASSERT(pArgs);
  139. if (NULL == pArgs)
  140. {
  141. return;
  142. }
  143. if (NULL == GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT))
  144. {
  145. return;
  146. }
  147. //
  148. // Retrieve the password and update memory based storage.
  149. //
  150. LPTSTR pszPassword = CmGetWindowTextAlloc(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  151. MYDBGASSERT(pszPassword);
  152. if (pszPassword)
  153. {
  154. //
  155. // Update pArgs with main password.
  156. //
  157. (VOID)pArgs->SecurePW.SetPassword(pszPassword);
  158. CmWipePassword(pszPassword);
  159. CmFree(pszPassword);
  160. }
  161. else
  162. {
  163. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  164. }
  165. return;
  166. }
  167. //+----------------------------------------------------------------------------
  168. //
  169. // Function: DeObfuscatePasswordEdit
  170. //
  171. // Synopsis: Undoes the work of ObfuscatePasswordEdit by updating the password
  172. // edit with the plain text password
  173. //
  174. // Arguments: pArgs - Ptr to global Args struct
  175. //
  176. // Returns: Nothing
  177. //
  178. // History: nickball Created 04/13/00
  179. //
  180. //+----------------------------------------------------------------------------
  181. void DeObfuscatePasswordEdit(ArgsStruct *pArgs)
  182. {
  183. MYDBGASSERT(pArgs);
  184. if (NULL == pArgs)
  185. {
  186. return;
  187. }
  188. HWND hwndEdit = GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  189. if (NULL == hwndEdit)
  190. {
  191. return;
  192. }
  193. //
  194. // Make sure we don't trigger EN_CHANGE notifications
  195. //
  196. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  197. pArgs->fIgnoreChangeNotification = TRUE;
  198. //
  199. // Update the edit control
  200. //
  201. LPTSTR pszClearPassword = NULL;
  202. DWORD cbClearPassword = 0;
  203. BOOL fRetPassword = FALSE;
  204. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  205. if (fRetPassword && pszClearPassword)
  206. {
  207. SetWindowTextU(hwndEdit, pszClearPassword);
  208. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  209. }
  210. //
  211. // Restore EN_CHANGE notifications
  212. //
  213. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  214. }
  215. //+----------------------------------------------------------------------------
  216. //
  217. // Function: ObfuscatePasswordEdit
  218. //
  219. // Synopsis: Helper routine to mangle password edit contents by replacing
  220. // them with an equivalent number of *s
  221. //
  222. // Arguments: pArgs - Ptr to global Args struct
  223. //
  224. // Returns: Nothing
  225. //
  226. // NOTE: This function assumes that pArgs->szPassword has been previously
  227. // updated with GetPasswordFromEdit. This assumption is made
  228. // because it is critical to the Odfuscate/DeObfuscate sequence,
  229. // which will breakdown if the latest password is not cached in
  230. // memory (pArgs) before the edit contents are modified.
  231. //
  232. // History: nickball Created 04/13/00
  233. //
  234. //+----------------------------------------------------------------------------
  235. void ObfuscatePasswordEdit(ArgsStruct *pArgs)
  236. {
  237. MYDBGASSERT(pArgs);
  238. if (NULL == pArgs)
  239. {
  240. return;
  241. }
  242. HWND hwndEdit = GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  243. if (NULL == hwndEdit)
  244. {
  245. return;
  246. }
  247. //
  248. // Generate a buffer of the same length as the current password, but
  249. // containing only asterisks.
  250. //
  251. LPTSTR pszClearPassword = NULL;
  252. DWORD cbClearPassword = 0;
  253. BOOL fRetPassword = FALSE;
  254. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  255. if (fRetPassword && pszClearPassword)
  256. {
  257. //
  258. // Make sure we don't trigger EN_CHANGE notifications
  259. //
  260. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  261. pArgs->fIgnoreChangeNotification = TRUE;
  262. LPTSTR pszTmp = pszClearPassword;
  263. while (*pszTmp)
  264. {
  265. *pszTmp++ = TEXT('*');
  266. }
  267. //
  268. // Update the edit control with the modified buffer
  269. //
  270. SetWindowTextU(hwndEdit, pszClearPassword);
  271. //
  272. // Restore EN_CHANGE notifications
  273. //
  274. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  275. //
  276. // Clear and Free the clear-text password
  277. //
  278. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  279. }
  280. }
  281. //+----------------------------------------------------------------------------
  282. //
  283. // Function: InitConnect
  284. //
  285. // Synopsis: Init routine for the connection. Assumes that we have the profile
  286. // initialized and the basic integrity of the profile verified.
  287. //
  288. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  289. //
  290. // Returns: BOOL - True if init succeeds.
  291. //
  292. // History: nickball Created 03/10/00
  293. //
  294. //+----------------------------------------------------------------------------
  295. BOOL InitConnect(ArgsStruct *pArgs)
  296. {
  297. //
  298. // If this is an AUTODIAL, add the process ID to the watch list
  299. //
  300. if ((pArgs->dwFlags & FL_AUTODIAL) &&
  301. pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMonitorCallingProgram, 1))
  302. {
  303. CMTRACE(TEXT("InitConnect() Adding calling process to watch list"));
  304. AddWatchProcessId(pArgs, GetCurrentProcessId());
  305. }
  306. //
  307. // Do we want tunneling?
  308. //
  309. pArgs->fTunnelPrimary = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryTunnelPrimary);
  310. pArgs->fTunnelReferences = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryTunnelReferences);
  311. //
  312. // Now we can determine our connect type
  313. //
  314. GetConnectType(pArgs);
  315. //
  316. // Set fUseTunneling. If not obvious (eg. direct VPN) then
  317. // base the initial value upon the primary phone number.
  318. //
  319. if (pArgs->IsDirectConnect())
  320. {
  321. pArgs->fUseTunneling = TRUE;
  322. }
  323. else
  324. {
  325. pArgs->fUseTunneling = UseTunneling(pArgs, 0);
  326. }
  327. //
  328. // Load the path for the VPN file if we have one
  329. //
  330. LPTSTR pszTemp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryTunnelFile);
  331. if (pszTemp && pszTemp[0])
  332. {
  333. //
  334. // Now expand the relative path to a full path
  335. //
  336. pArgs->pszVpnFile = CmBuildFullPathFromRelative(pArgs->piniProfile->GetFile(), pszTemp);
  337. MYDBGASSERT(pArgs->pszVpnFile && pArgs->pszVpnFile[0]);
  338. }
  339. CmFree(pszTemp);
  340. TCHAR szTmp[MAX_PATH];
  341. MYVERIFY(GetModuleFileNameU(NULL, szTmp, MAX_PATH));
  342. pArgs->Log.Log(PREINIT_EVENT, szTmp);
  343. //
  344. // Run any init time actions that we may have.
  345. //
  346. CActionList PreInitActList;
  347. PreInitActList.Append(pArgs->piniService, c_pszCmSectionPreInit);
  348. if (!PreInitActList.RunAccordType(pArgs->hwndMainDlg, pArgs))
  349. {
  350. //
  351. // Fail the connection
  352. //
  353. return FALSE;
  354. }
  355. return TRUE;
  356. }
  357. //+----------------------------------------------------------------------------
  358. //
  359. // Function: CheckStartupInfo
  360. //
  361. // Synopsis: Sub-routine to initialize startup info if necessary and perform
  362. // any other functions specific to this juncture in the init sequence.
  363. //
  364. // Arguments: HWND hwndDlg - HWND of main dlg
  365. // ArgStruct *pArgs - Ptr to global Args struct
  366. //
  367. // Returns: Nothing
  368. //
  369. // History: nickball Created 10/28/99
  370. //
  371. //+----------------------------------------------------------------------------
  372. void CheckStartupInfo(IN HWND hwndDlg, IN ArgsStruct *pArgs)
  373. {
  374. MYDBGASSERT(pArgs);
  375. if (NULL == pArgs)
  376. {
  377. return;
  378. }
  379. if (!pArgs->fStartupInfoLoaded)
  380. {
  381. //
  382. // When no one is logged on the IsWindowVisible will not return true when ICS is dialing
  383. //
  384. if (IsLogonAsSystem() || IsWindowVisible(hwndDlg))
  385. {
  386. //
  387. // The code is here to make sure FutureSplash starts with
  388. // the frame associated with Initial/Interactive state
  389. // and not Frame 1
  390. //
  391. if (NULL != pArgs->pCtr)
  392. {
  393. pArgs->pCtr->MapStateToFrame(PS_Interactive);
  394. }
  395. //
  396. // If we're doing unattended, and the behavior isn't explicitly turned off,
  397. // hide the UI while we do our unattended dial. Note: Be sure to set hide
  398. // state before first paint message is processed by system.
  399. //
  400. if (pArgs->dwFlags & FL_UNATTENDED)
  401. {
  402. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideUnattended, TRUE))
  403. {
  404. ShowWindow(hwndDlg, SW_HIDE);
  405. }
  406. }
  407. //
  408. // Post a message to ourselves to begin loading startup info.
  409. //
  410. PostMessageU(hwndDlg, WM_LOADSTARTUPINFO, (WPARAM)0, (LPARAM)0);
  411. }
  412. }
  413. }
  414. //+----------------------------------------------------------------------------
  415. //
  416. // Function: UpdateError
  417. //
  418. // Synopsis: Simple sub-routine to update the UI and program state in the
  419. // event of an error.
  420. //
  421. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  422. // DWORD dwErr - The error code
  423. //
  424. // Returns: Nothing
  425. //
  426. // History: nickball Created 05/31/99
  427. //
  428. //+----------------------------------------------------------------------------
  429. VOID UpdateError(ArgsStruct *pArgs, DWORD dwErr)
  430. {
  431. MYDBGASSERT(pArgs);
  432. if (pArgs)
  433. {
  434. //
  435. // Update the status display providing that the special case error code
  436. // ERROR_INVALID_DLL is not being used. This code is only used by CM to
  437. // designate that a Connect Action failed. Because the display is
  438. // updated by the action list, we must ensure that we don't overwrite.
  439. //
  440. if (ERROR_INVALID_DLL != dwErr)
  441. {
  442. CheckConnectionError(pArgs->hwndMainDlg, dwErr, pArgs, IsDialingTunnel(pArgs));
  443. }
  444. //
  445. // Update the logon dialog controls
  446. //
  447. SetInteractive(pArgs->hwndMainDlg, pArgs);
  448. //
  449. // Update the program state
  450. //
  451. pArgs->psState = PS_Error;
  452. }
  453. }
  454. //+----------------------------------------------------------------------------
  455. //
  456. // Function: UpdateTable
  457. //
  458. // Synopsis: Encapsulates updating to Connection Table according to our
  459. // current state
  460. //
  461. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  462. // CmConnectState CmState - The state we are now in.
  463. //
  464. // Returns: HRESULT - Failure code.
  465. //
  466. // History: nickball Created Header 2/9/98
  467. //
  468. //+----------------------------------------------------------------------------
  469. HRESULT UpdateTable(ArgsStruct *pArgs, CmConnectState CmState)
  470. {
  471. MYDBGASSERT(pArgs);
  472. MYDBGASSERT(pArgs->pConnTable);
  473. HRESULT hrRet = E_FAIL;
  474. //
  475. // Set the state as appropriate
  476. //
  477. switch (CmState)
  478. {
  479. case CM_CONNECTING:
  480. hrRet = pArgs->pConnTable->AddEntry(pArgs->szServiceName, pArgs->fAllUser);
  481. break;
  482. case CM_CONNECTED:
  483. hrRet = pArgs->pConnTable->SetConnected(pArgs->szServiceName, pArgs->hrcRasConn, pArgs->hrcTunnelConn);
  484. break;
  485. case CM_DISCONNECTING:
  486. hrRet = pArgs->pConnTable->SetDisconnecting(pArgs->szServiceName);
  487. break;
  488. case CM_DISCONNECTED:
  489. hrRet = pArgs->pConnTable->ClearEntry(pArgs->szServiceName);
  490. break;
  491. default:
  492. MYDBGASSERT(FALSE);
  493. break;
  494. }
  495. return hrRet;
  496. }
  497. //+----------------------------------------------------------------------------
  498. //
  499. // Function: EndMainDialog
  500. //
  501. // Synopsis: Simple helper to encapsulate EndDialog call and associated clean
  502. // up.
  503. //
  504. // Arguments: HWND hwndDlg - HWND of main dialog
  505. // ArgsStruct *pArgs - Ptr to global Args struct
  506. // int nResult - int to be passed on the EndDialog
  507. //
  508. // Returns: Nothing
  509. //
  510. // History: nickball Created 2/23/98
  511. //
  512. //+----------------------------------------------------------------------------
  513. void EndMainDialog(HWND hwndDlg, ArgsStruct *pArgs, int nResult)
  514. {
  515. //
  516. // Kill timer if we have one
  517. //
  518. if (pArgs->nTimerId)
  519. {
  520. KillTimer(hwndDlg,pArgs->nTimerId);
  521. pArgs->nTimerId = 0;
  522. }
  523. //
  524. // Cleanup future splash
  525. //
  526. if (pArgs->pCtr)
  527. {
  528. CleanupCtr(pArgs->pCtr);
  529. pArgs->pCtr = NULL;
  530. }
  531. //
  532. // Release our dialog specific data
  533. //
  534. pArgs->fStartupInfoLoaded = FALSE;
  535. OnMainExit(pArgs);
  536. //
  537. // hasta la vista, final
  538. //
  539. EndDialog(hwndDlg, nResult);
  540. }
  541. //+----------------------------------------------------------------------------
  542. //
  543. // Function: GetWatchCount
  544. //
  545. // Synopsis: Determines the number of processes in the watch list by searching
  546. // for the first NULL entry.
  547. //
  548. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  549. //
  550. // Returns: DWORD - Number of processes in list
  551. //
  552. // History: nickball Created Header 2/10/98
  553. //
  554. //+----------------------------------------------------------------------------
  555. DWORD GetWatchCount(const ArgsStruct *pArgs)
  556. {
  557. MYDBGASSERT(pArgs);
  558. DWORD dwCnt = 0;
  559. if (pArgs && pArgs->phWatchProcesses)
  560. {
  561. for (DWORD dwIdx = 0; pArgs->phWatchProcesses[dwIdx]; dwIdx++)
  562. {
  563. dwCnt++;
  564. }
  565. }
  566. return dwCnt;
  567. }
  568. //+----------------------------------------------------------------------------
  569. //
  570. // Function: AddWatchProcess
  571. //
  572. // Synopsis: Adds the given process handle to our list. The list is allocated
  573. // and reallocated as needed to accomodate new entries.
  574. //
  575. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  576. // HANDLE hProcess - The process handle to be added to the list
  577. //
  578. // Returns: Nothing
  579. //
  580. // History: nickball Created Header 2/10/98
  581. // tomkel Fixed PREFIX issues 11/21/2000
  582. //
  583. //+----------------------------------------------------------------------------
  584. void AddWatchProcess(ArgsStruct *pArgs, HANDLE hProcess)
  585. {
  586. MYDBGASSERT(pArgs);
  587. MYDBGASSERT(hProcess);
  588. if (NULL == hProcess || NULL == pArgs)
  589. {
  590. return;
  591. }
  592. //
  593. // Get count and Allocate room for 2 more, 1 new, 1 NULL
  594. //
  595. DWORD dwCnt = GetWatchCount(pArgs);
  596. HANDLE *phTmp = (HANDLE *) CmMalloc((dwCnt+2)*sizeof(HANDLE));
  597. if (NULL != phTmp)
  598. {
  599. //
  600. // Copy the existing list, and add the new handle
  601. //
  602. if (NULL != pArgs->phWatchProcesses)
  603. {
  604. CopyMemory(phTmp,pArgs->phWatchProcesses,sizeof(HANDLE)*dwCnt);
  605. }
  606. phTmp[dwCnt] = hProcess;
  607. //
  608. // Fix up the pointers
  609. //
  610. CmFree(pArgs->phWatchProcesses);
  611. pArgs->phWatchProcesses = phTmp;
  612. }
  613. }
  614. //+----------------------------------------------------------------------------
  615. //
  616. // Function: AddWatchProcessId
  617. //
  618. // Synopsis: Given a process Id, adds a handle for the given process to the w
  619. // atch process list.
  620. //
  621. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct.
  622. // DWORD dwProcessId - The ID of the process to be added
  623. //
  624. // Returns: Nothing
  625. //
  626. // History: nickball Created Header 2/10/98
  627. //
  628. //+----------------------------------------------------------------------------
  629. void AddWatchProcessId(ArgsStruct *pArgs, DWORD dwProcessId)
  630. {
  631. MYDBGASSERT(pArgs);
  632. MYDBGASSERT(dwProcessId);
  633. if (NULL == pArgs || NULL == dwProcessId)
  634. {
  635. return;
  636. }
  637. //
  638. // Open the process Id to obtain handle
  639. //
  640. HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
  641. //
  642. // Add to the watch process list
  643. //
  644. if (hProcess)
  645. {
  646. AddWatchProcess(pArgs,hProcess);
  647. }
  648. else
  649. {
  650. CMTRACE1(TEXT("AddWatchProcess() OpenProcess() failed, GLE=%u."), GetLastError());
  651. }
  652. }
  653. //+----------------------------------------------------------------------------
  654. //
  655. // Function: CleanupConnect
  656. //
  657. // Synopsis: Helper function encapsulating release of resource allocated duri
  658. // ng connect.
  659. //
  660. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  661. //
  662. // Returns: Nothing
  663. //
  664. // History: nickball Created 9/25/98
  665. //
  666. //+----------------------------------------------------------------------------
  667. void CleanupConnect(ArgsStruct *pArgs)
  668. {
  669. MYDBGASSERT(pArgs);
  670. if (NULL == pArgs)
  671. {
  672. return;
  673. }
  674. pArgs->m_ShellDll.Unload();
  675. //
  676. // Unlink RAS and TAPI DLLs
  677. //
  678. UnlinkFromRas(&pArgs->rlsRasLink);
  679. UnlinkFromTapi(&pArgs->tlsTapiLink);
  680. //
  681. // un-init password encryption, only if it is initialized
  682. //
  683. if (pArgs->fInitSecureCalled)
  684. {
  685. DeInitSecure();
  686. pArgs->fInitSecureCalled = FALSE;
  687. }
  688. //
  689. // Cleanup WatchProcess handles
  690. //
  691. ProcessCleanup(pArgs);
  692. //
  693. // Release all paths loaded for connect.
  694. //
  695. if (pArgs->pszRasPbk)
  696. {
  697. CmFree(pArgs->pszRasPbk);
  698. pArgs->pszRasPbk = NULL;
  699. }
  700. if (pArgs->pszRasHiddenPbk)
  701. {
  702. CmFree(pArgs->pszRasHiddenPbk);
  703. pArgs->pszRasHiddenPbk = NULL;
  704. }
  705. if(pArgs->pszVpnFile)
  706. {
  707. CmFree(pArgs->pszVpnFile);
  708. pArgs->pszVpnFile = NULL;
  709. }
  710. if (pArgs->pRasDialExtensions)
  711. {
  712. CmFree(pArgs->pRasDialExtensions);
  713. pArgs->pRasDialExtensions = NULL;
  714. }
  715. if (pArgs->pRasDialParams)
  716. {
  717. CmFree(pArgs->pRasDialParams);
  718. pArgs->pRasDialParams = NULL;
  719. }
  720. if (pArgs->pszCurrentAccessPoint)
  721. {
  722. CmFree(pArgs->pszCurrentAccessPoint);
  723. pArgs->pszCurrentAccessPoint = NULL;
  724. }
  725. //
  726. // Cleanup Help by killing the help file window if any and releasing the help file
  727. // string.
  728. //
  729. if (pArgs->pszHelpFile)
  730. {
  731. CmWinHelp((HWND)NULL, (HWND)NULL, pArgs->pszHelpFile, HELP_QUIT, 0);
  732. CmFree(pArgs->pszHelpFile);
  733. pArgs->pszHelpFile = NULL;
  734. }
  735. //
  736. // Release Ini objects
  737. //
  738. ReleaseIniObjects(pArgs);
  739. //
  740. // Release OLE links if any
  741. //
  742. if (pArgs->olsOle32Link.hInstOle32 && pArgs->olsOle32Link.pfnOleUninitialize)
  743. {
  744. pArgs->olsOle32Link.pfnOleUninitialize();
  745. }
  746. UnlinkFromOle32(&pArgs->olsOle32Link);
  747. //
  748. // Release stats and table classes
  749. //
  750. if (pArgs->pConnStatistics)
  751. {
  752. delete pArgs->pConnStatistics;
  753. }
  754. if (pArgs->pConnTable)
  755. {
  756. MYVERIFY(SUCCEEDED(pArgs->pConnTable->Close()));
  757. delete pArgs->pConnTable;
  758. }
  759. }
  760. //
  761. // Releases any resources allocated during initialization
  762. //
  763. void OnMainExit(ArgsStruct *pArgs)
  764. {
  765. //
  766. // Release bitmap resources for main dlg. Make sure to send a STM_SETIMAGE with a NULL
  767. // bitmap pointer to clear out the window classes pointer to our memory. Only then is it
  768. // safe to free it.
  769. //
  770. SendDlgItemMessageU(pArgs->hwndMainDlg, IDC_MAIN_BITMAP, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM)NULL);
  771. ReleaseBitmapData(&pArgs->BmpData);
  772. if (pArgs->hMasterPalette)
  773. {
  774. UnrealizeObject(pArgs->hMasterPalette);
  775. DeleteObject(pArgs->hMasterPalette);
  776. pArgs->hMasterPalette = NULL;
  777. }
  778. //
  779. // Release icon resources
  780. //
  781. if (pArgs->hBigIcon)
  782. {
  783. DeleteObject(pArgs->hBigIcon);
  784. pArgs->hBigIcon = NULL;
  785. }
  786. if (pArgs->hSmallIcon)
  787. {
  788. DeleteObject(pArgs->hSmallIcon);
  789. pArgs->hSmallIcon = NULL;
  790. }
  791. if (pArgs->pszResetPasswdExe)
  792. {
  793. CmFree(pArgs->pszResetPasswdExe);
  794. pArgs->pszResetPasswdExe = NULL;
  795. }
  796. if (pArgs->uiCurrentDnsTunnelAddr)
  797. {
  798. CmFree(pArgs->pucDnsTunnelIpAddr_list);
  799. pArgs->pucDnsTunnelIpAddr_list = NULL;
  800. }
  801. if (pArgs->rgwRandomDnsIndex)
  802. {
  803. CmFree(pArgs->rgwRandomDnsIndex);
  804. pArgs->rgwRandomDnsIndex = NULL;
  805. }
  806. }
  807. //
  808. // GetPhoneByIdx: get phone number, etc. information from .cmp file
  809. //
  810. LPTSTR GetPhoneByIdx(ArgsStruct *pArgs,
  811. UINT nIdx,
  812. LPTSTR *ppszDesc,
  813. LPTSTR *ppszDUN,
  814. LPDWORD pdwCountryID,
  815. LPTSTR *ppszRegionName,
  816. LPTSTR *ppszServiceType,
  817. LPTSTR *ppszPhoneBookFile,
  818. LPTSTR *ppszCanonical,
  819. DWORD *pdwPhoneInfoFlags)
  820. {
  821. MYDBGASSERT(ppszCanonical);
  822. MYDBGASSERT(pdwPhoneInfoFlags);
  823. //
  824. // Note: ppszCanonical and pdwPhoneInfoFlags are now required parameters.
  825. // While somewhat unfortunate, this is necessary to retain the integrity
  826. // of the retrieved data as legacy handling forces us to return data
  827. // that may not be an exact representation of the profile contents.
  828. // For example, the ppszCanonical and pdwPhoneInfoFlags value may be modified
  829. // overridden in certain situations. Please see comments below for details.
  830. //
  831. int nMaxPhoneLen = 0;
  832. BOOL bTmp = FALSE;
  833. // service profile: .CMP file
  834. CIni iniTmp(pArgs->piniProfile->GetHInst(),pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  835. iniTmp.SetEntryFromIdx(nIdx);
  836. //
  837. // Set the read flags
  838. //
  839. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA)
  840. {
  841. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  842. if (pszICSDataReg)
  843. {
  844. iniTmp.SetReadICSData(TRUE);
  845. iniTmp.SetICSDataPath(pszICSDataReg);
  846. }
  847. CmFree(pszICSDataReg);
  848. }
  849. LPTSTR pszTmp = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhonePrefix);
  850. if (ppszDesc)
  851. {
  852. *ppszDesc = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneDescPrefix);
  853. }
  854. if (ppszDUN)
  855. {
  856. *ppszDUN = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneDunPrefix);
  857. }
  858. if (pdwCountryID)
  859. {
  860. *pdwCountryID = iniTmp.GPPI(c_pszCmSection,c_pszCmEntryPhoneCountryPrefix);
  861. }
  862. if (ppszPhoneBookFile)
  863. {
  864. LPTSTR pszPb = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneSourcePrefix);
  865. //
  866. // If the value is empty, just store the ptr
  867. //
  868. if ((!*pszPb))
  869. {
  870. *ppszPhoneBookFile = pszPb;
  871. }
  872. else
  873. {
  874. *ppszPhoneBookFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszPb);
  875. CmFree(pszPb);
  876. }
  877. }
  878. if (ppszRegionName)
  879. {
  880. *ppszRegionName = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryRegion);
  881. }
  882. if (ppszServiceType)
  883. {
  884. *ppszServiceType = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryServiceType);
  885. }
  886. //
  887. // Get the extended form of the telephone number.
  888. //
  889. if (ppszCanonical)
  890. {
  891. *ppszCanonical = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryPhoneCanonical);
  892. }
  893. //
  894. // Set the phoneinfo flags
  895. //
  896. if (pdwPhoneInfoFlags)
  897. {
  898. *pdwPhoneInfoFlags = 0;
  899. //
  900. // Get the dial as long distance flag. Check CMS if no value found.
  901. //
  902. int iTmp = iniTmp.GPPI(c_pszCmSection, c_pszCmEntryUseDialingRules, -1);
  903. if (-1 == iTmp)
  904. {
  905. iTmp = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryUseDialingRules, 1);
  906. }
  907. if (iTmp)
  908. {
  909. *pdwPhoneInfoFlags |= PIF_USE_DIALING_RULES;
  910. }
  911. }
  912. //
  913. // Truncate phone string if we have one.
  914. // Note: Admin can override our default, but we
  915. // must stay within RAS_MaxPhoneNumber chars.
  916. //
  917. if (pszTmp && *pszTmp)
  918. {
  919. int nDefaultPhoneLen = (OS_NT ? MAX_PHONE_LENNT : MAX_PHONE_LEN95);
  920. nMaxPhoneLen = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPhoneNumber, nDefaultPhoneLen);
  921. nMaxPhoneLen = __min(nMaxPhoneLen, RAS_MaxPhoneNumber);
  922. if ((int)lstrlenU(pszTmp) > nMaxPhoneLen)
  923. {
  924. pszTmp[nMaxPhoneLen] = TEXT('\0');
  925. }
  926. }
  927. //
  928. // Special handling for the case where we have a Phone number
  929. // but the CanonicalPhone value doesn't exist. This indicates
  930. // that its either a legacy profile or a hand-edit.
  931. //
  932. if (pszTmp && *pszTmp && ppszCanonical && *ppszCanonical && (!(**ppszCanonical)))
  933. {
  934. //
  935. // This block is for handling LEGACY numbers only. If we detect a
  936. // canonically formatted number (begins with "+"), then we re-format
  937. // the number to fit our new scheme. Hand-edits are not modified,
  938. // but PIF_USE_DIALING_RULES is turned off, which overrides the
  939. // default setting for the flag (if any) specified in
  940. // the .CMS
  941. //
  942. if (pszTmp == CmStrchr(pszTmp, TEXT('+')))
  943. {
  944. *pdwPhoneInfoFlags |= PIF_USE_DIALING_RULES;
  945. if (*ppszCanonical)
  946. {
  947. CmFree(*ppszCanonical);
  948. }
  949. *ppszCanonical = CmStrCpyAlloc(pszTmp);
  950. StripCanonical(pszTmp);
  951. }
  952. else
  953. {
  954. *pdwPhoneInfoFlags &= ~PIF_USE_DIALING_RULES; // #284702
  955. }
  956. }
  957. return (pszTmp);
  958. }
  959. // write phone number dialing options to .CMP file
  960. void PutPhoneByIdx(ArgsStruct *pArgs,
  961. UINT nIdx,
  962. LPCTSTR pszPhone,
  963. LPCTSTR pszDesc,
  964. LPCTSTR pszDUN,
  965. DWORD dwCountryID,
  966. LPCTSTR pszRegionName,
  967. LPCTSTR pszServiceType,
  968. LPCTSTR pszPhoneBookFile,
  969. LPCTSTR pszCanonical,
  970. DWORD dwPhoneInfoFlags)
  971. {
  972. CIni iniTmp(pArgs->piniProfile->GetHInst(), pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  973. iniTmp.SetEntryFromIdx(nIdx);
  974. //
  975. // Set the write flags
  976. //
  977. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_WRITE_ICS_DATA)
  978. {
  979. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  980. if (pszICSDataReg)
  981. {
  982. iniTmp.SetWriteICSData(TRUE);
  983. iniTmp.SetICSDataPath(pszICSDataReg);
  984. }
  985. CmFree(pszICSDataReg);
  986. }
  987. //
  988. // Store the raw form of the number
  989. //
  990. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhonePrefix, pszPhone);
  991. //
  992. // Store the canonical form of the number
  993. //
  994. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneCanonical, pszCanonical);
  995. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneDescPrefix, pszDesc);
  996. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneDunPrefix, pszDUN);
  997. iniTmp.WPPI(c_pszCmSection, c_pszCmEntryPhoneCountryPrefix, dwCountryID);
  998. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryRegion, pszRegionName);
  999. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryServiceType, pszServiceType);
  1000. //
  1001. // If there is a phonebookfile path, convert it to relative form
  1002. //
  1003. if (pszPhoneBookFile && *pszPhoneBookFile)
  1004. {
  1005. LPTSTR pszTmp = ReducePathToRelative(pArgs, pszPhoneBookFile);
  1006. if (pszTmp)
  1007. {
  1008. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneSourcePrefix, pszTmp);
  1009. }
  1010. CmFree(pszTmp);
  1011. }
  1012. iniTmp.WPPB(c_pszCmSection, c_pszCmEntryUseDialingRules, (dwPhoneInfoFlags & PIF_USE_DIALING_RULES));
  1013. }
  1014. //+----------------------------------------------------------------------------
  1015. //
  1016. // Function: LoadPhoneInfoFromProfile
  1017. //
  1018. // Synopsis: Load phone number information for profile to the dial info structure
  1019. //
  1020. // Arguments: ArgsStruct *pArgs -
  1021. //
  1022. // Returns: Nothing
  1023. //
  1024. // History: fengsun Created Header 3/5/98
  1025. //
  1026. //+----------------------------------------------------------------------------
  1027. void LoadPhoneInfoFromProfile(ArgsStruct *pArgs)
  1028. {
  1029. for (int nPhoneIdx=0; nPhoneIdx<MAX_PHONE_NUMBERS; nPhoneIdx++)
  1030. {
  1031. LPTSTR pszDUN = NULL;
  1032. LPTSTR pszDesc = NULL;
  1033. LPTSTR pszPhoneBookFile = NULL;
  1034. LPTSTR pszRegionName = NULL;
  1035. LPTSTR pszServiceType = NULL;
  1036. LPTSTR pszCanonical = NULL;
  1037. DWORD dwCountryID;
  1038. DWORD dwPhoneInfoFlags;
  1039. //
  1040. // get phone nubmer by index; Phone0, Phone1 , etc...
  1041. //
  1042. LPTSTR pszPhone = GetPhoneByIdx(pArgs,
  1043. nPhoneIdx,
  1044. &pszDesc,
  1045. &pszDUN,
  1046. &dwCountryID,
  1047. &pszRegionName,
  1048. &pszServiceType,
  1049. &pszPhoneBookFile,
  1050. &pszCanonical,
  1051. &dwPhoneInfoFlags);
  1052. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber, pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber));
  1053. pArgs->aDialInfo[nPhoneIdx].dwCountryID = dwCountryID;
  1054. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDUN, pszDUN, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDUN));
  1055. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szPhoneBookFile,
  1056. pszPhoneBookFile, CELEMS(pArgs->aDialInfo[nPhoneIdx].szPhoneBookFile));
  1057. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDesc, pszDesc, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDesc));
  1058. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szRegionName,
  1059. pszRegionName, CELEMS(pArgs->aDialInfo[nPhoneIdx].szRegionName));
  1060. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szServiceType,
  1061. pszServiceType, CELEMS(pArgs->aDialInfo[nPhoneIdx].szServiceType));
  1062. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szCanonical,
  1063. pszCanonical, CELEMS(pArgs->aDialInfo[nPhoneIdx].szCanonical));
  1064. pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags = dwPhoneInfoFlags;
  1065. // Cleanup
  1066. CmFree(pszDUN);
  1067. CmFree(pszPhone);
  1068. CmFree(pszDesc);
  1069. CmFree(pszPhoneBookFile);
  1070. CmFree(pszRegionName);
  1071. CmFree(pszServiceType);
  1072. CmFree(pszCanonical);
  1073. } // for loop
  1074. }
  1075. //+----------------------------------------------------------------------------
  1076. //
  1077. // Function: LoadDialInfo
  1078. //
  1079. // Synopsis: load dialup information
  1080. //
  1081. // Arguments: ArgsStruct *pArgs - Ptr to glbal Args struct
  1082. // HWND hwndDlg - HWND of main dialog
  1083. // BOOL fInstallModem - Whether we should check modem isntall
  1084. // BOOL fAlwaysMunge - Whether we should munge the phone number
  1085. //
  1086. // Returns: DWORD - ERROR_SUCCESS if load successfuly
  1087. // ERROR_PORT_NOT_AVAILABLE if can not find any modem
  1088. // ERROR_BAD_PHONE_NUMBER either there is no primary phone #
  1089. // or failed to convert it to dialable #
  1090. //
  1091. // History: 10/24/97 fengsun Created Header and change return type to DWORD
  1092. // 02/08/99 nickball Added fAlwaysMunge
  1093. //
  1094. //+----------------------------------------------------------------------------
  1095. DWORD LoadDialInfo(ArgsStruct *pArgs, HWND hwndDlg, BOOL fInstallModem, BOOL fAlwaysMunge)
  1096. {
  1097. DWORD dwRet = ERROR_SUCCESS;
  1098. if (pArgs->bDialInfoLoaded)
  1099. {
  1100. if (pArgs->aDialInfo[0].szDialablePhoneNumber[0] == TEXT('\0') &&
  1101. pArgs->aDialInfo[1].szDialablePhoneNumber[0] == TEXT('\0'))
  1102. {
  1103. return ERROR_BAD_PHONE_NUMBER;
  1104. }
  1105. else
  1106. {
  1107. //
  1108. // If fAlways munge is set, then stick around.
  1109. //
  1110. if (!fAlwaysMunge)
  1111. {
  1112. return ERROR_SUCCESS;
  1113. }
  1114. }
  1115. }
  1116. //
  1117. // Don't need to repeat ourselves
  1118. //
  1119. if (!pArgs->bDialInfoLoaded)
  1120. {
  1121. pArgs->fNoDialingRules = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmNoDialingRules);
  1122. //
  1123. // Do a full test on just the modem
  1124. //
  1125. if (fInstallModem)
  1126. {
  1127. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM, hwndDlg, pArgs->szServiceName, (pArgs->dwFlags & FL_UNATTENDED));
  1128. if (pArgs->dwExitCode != ERROR_SUCCESS)
  1129. {
  1130. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1131. goto LoadDialInfoExit;
  1132. }
  1133. }
  1134. //
  1135. // Establish TAPI link before we continue
  1136. //
  1137. if (!LinkToTapi(&pArgs->tlsTapiLink, "TAPI32") )
  1138. {
  1139. //
  1140. // Link to TAPI failed.
  1141. // If unattended, return with failure.
  1142. // Otherwise, try to install components and LinkToTapi again
  1143. //
  1144. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  1145. if (!(pArgs->dwFlags & FL_UNATTENDED))
  1146. {
  1147. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM | CC_RNA | CC_RASRUNNING,
  1148. hwndDlg, pArgs->szServiceName);
  1149. }
  1150. if (pArgs->dwExitCode != ERROR_SUCCESS || !LinkToTapi(&pArgs->tlsTapiLink, "TAPI32"))
  1151. {
  1152. pArgs->szDeviceType[0] = TEXT('\0');
  1153. pArgs->szDeviceName[0] = TEXT('\0');
  1154. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1155. goto LoadDialInfoExit;
  1156. }
  1157. }
  1158. //
  1159. // RasEnumDevice and LineInitialize is SLOW. It takes 50% of the start-up time
  1160. //
  1161. if (!PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName))
  1162. {
  1163. //
  1164. // Because pick modem failed we need to check if we have RAS/Modem installed
  1165. //
  1166. ClearComponentsChecked();
  1167. //
  1168. // No modem is installed.
  1169. // If unattended or caller does not want to install modem, return with failure.
  1170. // Otherwise, try to install the modem and call pick modem again
  1171. //
  1172. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  1173. if (!(pArgs->dwFlags & FL_UNATTENDED) && fInstallModem)
  1174. {
  1175. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM | CC_RNA | CC_RASRUNNING,
  1176. hwndDlg, pArgs->szServiceName);
  1177. }
  1178. if (pArgs->dwExitCode != ERROR_SUCCESS ||
  1179. !PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName))
  1180. {
  1181. pArgs->szDeviceType[0] = TEXT('\0');
  1182. pArgs->szDeviceName[0] = TEXT('\0');
  1183. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1184. goto LoadDialInfoExit;
  1185. }
  1186. }
  1187. }
  1188. //
  1189. // See if munge is required and Cleanup as needed
  1190. //
  1191. if (!pArgs->bDialInfoLoaded || TRUE == fAlwaysMunge)
  1192. {
  1193. MungeDialInfo(pArgs);
  1194. pArgs->bDialInfoLoaded = TRUE;
  1195. }
  1196. if (pArgs->aDialInfo[0].szDialablePhoneNumber[0] == TEXT('\0') &&
  1197. pArgs->aDialInfo[1].szDialablePhoneNumber[0] == TEXT('\0'))
  1198. {
  1199. dwRet = ERROR_BAD_PHONE_NUMBER;
  1200. }
  1201. LoadDialInfoExit:
  1202. return dwRet;
  1203. }
  1204. //+----------------------------------------------------------------------------
  1205. //
  1206. // Function: MungeDialInfo
  1207. //
  1208. // Synopsis: Encapsulates the munging of the phone numbers prior to dialing
  1209. //
  1210. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  1211. //
  1212. // Returns: Nothing - Check Dialable string and fNeedConfigureTapi
  1213. //
  1214. // History: 02/08/99 nickball Created - pulled from LoadDialInfo
  1215. //
  1216. //+----------------------------------------------------------------------------
  1217. VOID MungeDialInfo(ArgsStruct *pArgs)
  1218. {
  1219. for (int nPhoneIdx=0; nPhoneIdx<MAX_PHONE_NUMBERS; nPhoneIdx++)
  1220. {
  1221. //
  1222. // If dialing rules is disabled, then just use the NonCanonical #
  1223. //
  1224. if (pArgs->fNoDialingRules)
  1225. {
  1226. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1227. pArgs->aDialInfo[nPhoneIdx].szPhoneNumber, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1228. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1229. pArgs->aDialInfo[nPhoneIdx].szPhoneNumber, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1230. pArgs->aDialInfo[nPhoneIdx].szCanonical[0] = TEXT('\0');
  1231. continue;
  1232. }
  1233. LPTSTR pszDialableString= NULL;
  1234. //
  1235. // Retrieve the number based upon dialing rules and munge it.
  1236. //
  1237. LPTSTR pszPhone;
  1238. if (pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags & PIF_USE_DIALING_RULES)
  1239. {
  1240. pszPhone = CmStrCpyAlloc(pArgs->aDialInfo[nPhoneIdx].szCanonical);
  1241. }
  1242. else
  1243. {
  1244. pszPhone = CmStrCpyAlloc(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber);
  1245. }
  1246. if (pszPhone && pszPhone[0])
  1247. {
  1248. //
  1249. // If we can't munge the number, display an error
  1250. //
  1251. if (pArgs->szDeviceName[0] &&
  1252. ERROR_SUCCESS != MungePhone(pArgs->szDeviceName,
  1253. &pszPhone,
  1254. &pArgs->tlsTapiLink,
  1255. g_hInst,
  1256. pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags & PIF_USE_DIALING_RULES,
  1257. &pszDialableString,
  1258. pArgs->fAccessPointsEnabled))
  1259. {
  1260. CmFree(pszPhone);
  1261. pszPhone = CmStrCpyAlloc(TEXT("")); // CmFmtMsg(g_hInst,IDMSG_CANTFORMAT);
  1262. pszDialableString = CmStrCpyAlloc(TEXT("")); // CmFmtMsg(g_hInst,IDMSG_CANTFORMAT);
  1263. }
  1264. else if (!pszDialableString || pszDialableString[0] == '\0')
  1265. {
  1266. //
  1267. // So what happened now? pszPhone is not empty, but after
  1268. // we munge the phone, which means applying TAPI rules,
  1269. // pszDialbleString becomes empty. This means only one
  1270. // thing: TAPI isn't intialized.
  1271. //
  1272. // Note: If you uninstall TAPI between launching the app.
  1273. // and pressing connect, all bets are off with the above.
  1274. //
  1275. // This flag will be reset in CheckTapi(), which will put
  1276. // up a TAPI configuration dialog and ask the user to fill
  1277. // up such information
  1278. //
  1279. pArgs->fNeedConfigureTapi = TRUE;
  1280. }
  1281. }
  1282. // Copy the munged number
  1283. //
  1284. // Unless explicitly disabled we always apply TAPI rules
  1285. // in order to pick up TONE/PULSE, etc.
  1286. //
  1287. if (NULL != pszDialableString)
  1288. {
  1289. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1290. pszDialableString, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1291. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1292. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1293. }
  1294. else
  1295. {
  1296. if (NULL != pszPhone)
  1297. {
  1298. //
  1299. // Just do it on WIN32 because our TAPI checks were done above
  1300. //
  1301. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1302. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1303. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1304. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1305. }
  1306. }
  1307. CmFree(pszPhone);
  1308. CmFree(pszDialableString);
  1309. } // for loop
  1310. }
  1311. //+---------------------------------------------------------------------------
  1312. //
  1313. // Function: LoadHelpFileInfo
  1314. //
  1315. // Synopsis: Load the help file name
  1316. //
  1317. // Arguments: pArgs [the ptr to ArgsStruct]
  1318. //
  1319. // Returns: NONE
  1320. //
  1321. // History: henryt Created 3/5/97
  1322. // byao Modified 3/20/97 to handle empty helpfile string
  1323. //----------------------------------------------------------------------------
  1324. void LoadHelpFileInfo(ArgsStruct *pArgs)
  1325. {
  1326. MYDBGASSERT(pArgs);
  1327. //
  1328. // Look for a custom helpfile name, otherwise use default.
  1329. //
  1330. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryHelpFile);
  1331. if (NULL == pszTmp || 0 == pszTmp[0])
  1332. {
  1333. CmFree(pszTmp);
  1334. pszTmp = CmStrCpyAlloc(c_pszDefaultHelpFile);
  1335. }
  1336. //
  1337. // Make sure that any relative path is converted to full
  1338. //
  1339. pArgs->pszHelpFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  1340. CmFree(pszTmp);
  1341. }
  1342. //
  1343. // CopyPhone:
  1344. //
  1345. void CopyPhone(ArgsStruct *pArgs,
  1346. LPRASENTRY preEntry,
  1347. DWORD dwEntry)
  1348. {
  1349. LPTSTR pszPhone = NULL;
  1350. LPTSTR pszCanonical = NULL;
  1351. LPTSTR pszTmp;
  1352. LPTSTR pszDescription = NULL;
  1353. BOOL Setcountry = FALSE;
  1354. DWORD dwPhoneInfoFlags = 0;
  1355. pszPhone = GetPhoneByIdx(pArgs,(UINT) dwEntry, &pszDescription,
  1356. NULL, NULL, NULL,
  1357. NULL, NULL, &pszCanonical, &dwPhoneInfoFlags);
  1358. //
  1359. // If "Use Dialing Rules" turn of CountryAndAreaCodes option
  1360. //
  1361. if (dwPhoneInfoFlags & PIF_USE_DIALING_RULES)
  1362. {
  1363. //
  1364. // We want to use dialing rules, so parse the canonical form
  1365. // of the number to get the country and area codes for the entry
  1366. //
  1367. pszTmp = CmStrchr(pszCanonical,TEXT('+'));
  1368. if (pszTmp)
  1369. {
  1370. preEntry->dwCountryCode = CmAtol(pszTmp+1);
  1371. //
  1372. // NOTE: Currently CM uses code and ID interchangeably
  1373. // The countryID value in the .CMP is actually the country
  1374. // code used when constructing the phone number in its
  1375. // canonical format. This is probably not entirely correct
  1376. // but we maitain consistency with it here by using the
  1377. // country code parsed from the number as the country ID.
  1378. //
  1379. preEntry->dwCountryID = preEntry->dwCountryCode;
  1380. preEntry->dwfOptions |= RASEO_UseCountryAndAreaCodes;
  1381. Setcountry = TRUE;
  1382. }
  1383. if (Setcountry)
  1384. {
  1385. pszTmp = CmStrchr(pszCanonical,'('); //strip out area code
  1386. if (pszTmp)
  1387. {
  1388. wsprintfU(preEntry->szAreaCode, TEXT("%u"), CmAtol(pszTmp+1));
  1389. }
  1390. pszTmp = CmStrchr(pszCanonical,')');
  1391. if (pszTmp)
  1392. {
  1393. ++pszTmp;
  1394. while(*pszTmp == ' ')
  1395. ++pszTmp; //remove whitespace
  1396. }
  1397. else
  1398. {
  1399. // no area code
  1400. preEntry->szAreaCode[0]=TEXT('\0');
  1401. pszTmp = CmStrchr(pszCanonical,' ');
  1402. if (pszTmp)
  1403. {
  1404. while(*pszTmp == ' ')
  1405. ++pszTmp; // skip past space - may need MBCS change
  1406. }
  1407. }
  1408. }
  1409. }
  1410. else
  1411. {
  1412. //
  1413. // Use the straight up phone number and don't apply rules
  1414. //
  1415. preEntry->dwfOptions &= ~RASEO_UseCountryAndAreaCodes;
  1416. pszTmp = pszPhone;
  1417. }
  1418. if ((NULL != pszTmp) && *pszTmp)
  1419. {
  1420. lstrcpynU(preEntry->szLocalPhoneNumber, pszTmp, CELEMS(preEntry->szLocalPhoneNumber));
  1421. }
  1422. else
  1423. {
  1424. lstrcpynU(preEntry->szLocalPhoneNumber, TEXT(" "), CELEMS(preEntry->szLocalPhoneNumber));//prevent zero from appearing
  1425. }
  1426. CmFree(pszPhone);
  1427. CmFree(pszCanonical);
  1428. CmFree(pszDescription);
  1429. }
  1430. //+----------------------------------------------------------------------------
  1431. //
  1432. // Function: AppendStatusPane
  1433. //
  1434. // Synopsis: Append the text to the main dialog status window
  1435. //
  1436. // Arguments: HWND hwndDlg - The main dialog window handle
  1437. // DWORD dwMsgId - The resource id of the message
  1438. //
  1439. // Returns: Nothing
  1440. //
  1441. // History: Created Header 10/24/97
  1442. //
  1443. //+----------------------------------------------------------------------------
  1444. void AppendStatusPane(HWND hwndDlg,
  1445. DWORD dwMsgId)
  1446. {
  1447. LPTSTR pszTmp = CmFmtMsg(g_hInst,dwMsgId);
  1448. if (pszTmp != NULL)
  1449. {
  1450. AppendStatusPane(hwndDlg,pszTmp);
  1451. CmFree(pszTmp);
  1452. }
  1453. }
  1454. //
  1455. // AppendStatusPane: Update the original status, append new message 'pszMsg'
  1456. // at the end
  1457. //
  1458. void AppendStatusPane(HWND hwndDlg,
  1459. LPCTSTR pszMsg)
  1460. {
  1461. size_t nLines;
  1462. //
  1463. // Get the existing message
  1464. //
  1465. LPTSTR pszStatus = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_STATUS_DISPLAY);
  1466. LPTSTR pszTmp = CmStrrchr(pszStatus, TEXT('\n'));
  1467. if (!pszTmp)
  1468. {
  1469. // empty message, so simply display 'pszMsg'
  1470. CmFree(pszStatus);
  1471. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY,pszMsg);
  1472. //
  1473. // force an update right away
  1474. //
  1475. UpdateWindow(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY));
  1476. return;
  1477. }
  1478. pszTmp[1] = 0;
  1479. CmStrCatAlloc(&pszStatus,pszMsg); // append pszMsg at the end of old message
  1480. nLines = 0;
  1481. pszTmp = pszStatus + lstrlenU(pszStatus);
  1482. while (pszTmp != pszStatus)
  1483. {
  1484. pszTmp--;
  1485. if (*pszTmp == '\n')
  1486. {
  1487. if (++nLines == 2)
  1488. {
  1489. lstrcpyU(pszStatus,pszTmp+1);
  1490. break;
  1491. }
  1492. }
  1493. }
  1494. SetDlgItemTextU(hwndDlg,IDC_MAIN_STATUS_DISPLAY,pszStatus);
  1495. SendDlgItemMessageU(hwndDlg,IDC_MAIN_STATUS_DISPLAY,EM_SCROLL,SB_PAGEDOWN,0);
  1496. CmFree(pszStatus);
  1497. //
  1498. // force an update right away
  1499. //
  1500. UpdateWindow(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY));
  1501. }
  1502. // bitmap logo loading code - took this out of LoadFromFile so it can
  1503. // be called in multiple cases - like when the FS OC loading code
  1504. // fails, we can degrade gracefully with this.
  1505. VOID LoadLogoBitmap(ArgsStruct * pArgs,
  1506. HWND hwndDlg)
  1507. {
  1508. LPTSTR pszTmp;
  1509. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryLogo);
  1510. if (*pszTmp)
  1511. {
  1512. //
  1513. // Make sure we have a full path (if appropriate) and load logo bitmap
  1514. //
  1515. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  1516. pArgs->BmpData.hDIBitmap = CmLoadBitmap(g_hInst, pszFile);
  1517. CmFree(pszFile);
  1518. }
  1519. CmFree(pszTmp);
  1520. if (!pArgs->BmpData.hDIBitmap)
  1521. {
  1522. pArgs->BmpData.hDIBitmap = CmLoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_APP));
  1523. }
  1524. //
  1525. // If we have a handle, create a new Device Dependent bitmap
  1526. //
  1527. if (pArgs->BmpData.hDIBitmap)
  1528. {
  1529. pArgs->BmpData.phMasterPalette = &pArgs->hMasterPalette;
  1530. pArgs->BmpData.bForceBackground = TRUE; // paint as a background app
  1531. if (CreateBitmapData(pArgs->BmpData.hDIBitmap, &pArgs->BmpData, hwndDlg, TRUE))
  1532. {
  1533. SendDlgItemMessageU(hwndDlg,IDC_MAIN_BITMAP,STM_SETIMAGE,IMAGE_BITMAP,
  1534. (LPARAM) &pArgs->BmpData);
  1535. }
  1536. }
  1537. }
  1538. const LONG MAX_SECTION = 512;
  1539. HRESULT LoadFutureSplash(ArgsStruct * pArgs,
  1540. HWND hwndDlg)
  1541. {
  1542. // set up the Future Splash OC container.
  1543. LPCTSTR pszFile = pArgs->piniBoth->GetFile();
  1544. TCHAR achSections[MAX_SECTION] = {0};
  1545. HRESULT hr;
  1546. LPTSTR pszVal = NULL;
  1547. LPTSTR pszTmp = NULL;
  1548. LPICMOCCtr pCtr;
  1549. HWND hDlgItem = ::GetDlgItem(hwndDlg, IDC_MAIN_BITMAP);
  1550. if (NULL == hDlgItem)
  1551. {
  1552. hr = E_FAIL;
  1553. goto Cleanup;
  1554. }
  1555. pArgs->pCtr = new CICMOCCtr(hwndDlg, hDlgItem);
  1556. if (!pArgs->pCtr)
  1557. {
  1558. goto MemoryError;
  1559. }
  1560. if (!pArgs->pCtr->Initialized())
  1561. {
  1562. hr = E_FAIL;
  1563. goto Cleanup;
  1564. }
  1565. pCtr = pArgs->pCtr;
  1566. if (!::GetPrivateProfileStringU(
  1567. c_pszCmSectionAnimatedLogo,
  1568. 0,
  1569. TEXT(""),
  1570. achSections,
  1571. NElems(achSections),
  1572. pszFile))
  1573. {
  1574. hr = E_FAIL;
  1575. goto Cleanup;
  1576. }
  1577. pszVal = (LPTSTR) CmMalloc(INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
  1578. if (NULL == pszVal)
  1579. {
  1580. hr = E_OUTOFMEMORY;
  1581. goto Cleanup;
  1582. }
  1583. pszTmp = achSections;
  1584. while (pszTmp[0])
  1585. {
  1586. // if this fails, we keep on looping, looking for
  1587. // the next one.
  1588. if (::GetPrivateProfileStringU(
  1589. c_pszCmSectionAnimatedLogo,
  1590. pszTmp,
  1591. TEXT(""),
  1592. pszVal,
  1593. INTERNET_MAX_URL_LENGTH, // number of TCHARS in pszVal
  1594. pszFile))
  1595. {
  1596. if (lstrcmpiU(pszTmp, c_pszCmEntryAniMovie) == 0) // is this the 'movie' entry?
  1597. {
  1598. //
  1599. // Build full path from .CMP and relative path
  1600. //
  1601. LPTSTR pszMovieFileName = CmBuildFullPathFromRelative(pArgs->piniProfile->GetFile(), pszVal);
  1602. if (!pszMovieFileName)
  1603. {
  1604. hr = S_FALSE;
  1605. CmFree(pszMovieFileName);
  1606. goto Cleanup;
  1607. }
  1608. //
  1609. // Does this file exist?
  1610. //
  1611. if (FALSE == FileExists(pszMovieFileName))
  1612. {
  1613. hr = S_FALSE;
  1614. CmFree(pszMovieFileName);
  1615. goto Cleanup;
  1616. }
  1617. lstrcpyU(pszVal, pszMovieFileName); // store the full pathname back
  1618. CmFree(pszMovieFileName);
  1619. }
  1620. hr = pCtr->AddPropertyToBag(pszTmp, pszVal);
  1621. if (S_OK != hr)
  1622. goto Cleanup;
  1623. }
  1624. // get the next key name.
  1625. pszTmp += (lstrlenU(pszTmp) + 1);
  1626. }
  1627. // create the Future Splash OC.
  1628. hr = pCtr->CreateFSOC(&pArgs->olsOle32Link);
  1629. if (S_OK != hr)
  1630. {
  1631. goto Cleanup;
  1632. }
  1633. // now, do the state mappings, no matter what happens, we won't
  1634. // fail on this. just keep on going.
  1635. pCtr->SetFrameMapping(PS_Interactive,
  1636. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1637. c_pszCmEntryAniPsInteractive,
  1638. -1,
  1639. pszFile));
  1640. pCtr->SetFrameMapping(PS_Dialing,
  1641. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1642. c_pszCmEntryAniPsDialing0,
  1643. -1,
  1644. pszFile));
  1645. pCtr->SetFrameMapping(PS_RedialFrame,
  1646. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1647. c_pszCmEntryAniPsDialing1,
  1648. -1,
  1649. pszFile));
  1650. pCtr->SetFrameMapping(PS_Pausing,
  1651. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1652. c_pszCmEntryAniPsPausing,
  1653. -1,
  1654. pszFile));
  1655. pCtr->SetFrameMapping(PS_Authenticating,
  1656. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1657. c_pszCmEntryAniPsAuthenticating,
  1658. -1,
  1659. pszFile));
  1660. pCtr->SetFrameMapping(PS_Online,
  1661. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1662. c_pszCmEntryAniPsOnline,
  1663. -1,
  1664. pszFile));
  1665. pCtr->SetFrameMapping(PS_TunnelDialing,
  1666. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1667. c_pszCmEntryAniPsTunnel,
  1668. -1,
  1669. pszFile));
  1670. pCtr->SetFrameMapping(PS_Error,
  1671. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1672. c_pszCmEntryAniPsError,
  1673. -1,
  1674. pszFile));
  1675. Cleanup:
  1676. if (pszVal)
  1677. {
  1678. CmFree(pszVal);
  1679. }
  1680. return hr;
  1681. MemoryError:
  1682. hr = E_OUTOFMEMORY;
  1683. goto Cleanup;
  1684. }
  1685. //+---------------------------------------------------------------------------
  1686. //
  1687. // Function: LoadProperties
  1688. //
  1689. // Synopsis: This func loads CM Properties from cmp/cms, registry, password
  1690. // cache, etc, into its internal variables. This func should
  1691. // only be called once. This should not be specific to the main
  1692. // sign-in dlg. DO NOT do any icon/bitmap stuff, dlg specific
  1693. // stuff here.
  1694. //
  1695. // Arguments: pArgs [the ptr to ArgsStruct]
  1696. //
  1697. // Returns: NONE
  1698. //
  1699. // History: henryt Created 5/2/97
  1700. //
  1701. // t-urama Modified 08/02/00 Added Access Points
  1702. //----------------------------------------------------------------------------
  1703. void LoadProperties(
  1704. ArgsStruct *pArgs
  1705. )
  1706. {
  1707. LPTSTR pszTmp = NULL;
  1708. LPTSTR pszUserName = NULL;
  1709. UINT nTmp;
  1710. CMTRACE(TEXT("Begin LoadProperties()"));
  1711. //
  1712. // First make sure we can use the RAS CredStore
  1713. // This flag is used in the calls below
  1714. //
  1715. if (OS_NT5)
  1716. {
  1717. pArgs->bUseRasCredStore = TRUE;
  1718. }
  1719. //
  1720. // Upgrade userinfo if necessary. Note that we have
  1721. // an upgrade from CM 1.0/1.1 cmp data and we also
  1722. // have an upgrade of CM 1.2 registry data to
  1723. // the method used in CM 1.3 on Win2k which uses both
  1724. // the registry and RAS credential storage.
  1725. //
  1726. int iUpgradeType = NeedToUpgradeUserInfo(pArgs);
  1727. if (c_iUpgradeFromRegToRas == iUpgradeType)
  1728. {
  1729. UpgradeUserInfoFromRegToRasAndReg(pArgs);
  1730. }
  1731. else if (c_iUpgradeFromCmp == iUpgradeType)
  1732. {
  1733. UpgradeUserInfoFromCmp(pArgs);
  1734. }
  1735. //
  1736. // Need to refresh Credential support. The TRUE flag also sets the current creds
  1737. // type inside the function. If an error occurs we can keep executing.
  1738. //
  1739. if(FALSE == RefreshCredentialTypes(pArgs, TRUE))
  1740. {
  1741. CMTRACE(TEXT("LoadProperties() - Error refreshing credential types."));
  1742. }
  1743. if (IsTunnelEnabled(pArgs))
  1744. {
  1745. //
  1746. // do we use the same username/password for tunneling?
  1747. // This value is set by ISP, CM does not change it
  1748. //
  1749. pArgs->fUseSameUserName = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName);
  1750. //
  1751. // read in inet username
  1752. // Special case where the same user name isn't being used, and internet globals don't exist
  1753. // Then we have to read the user name from the user creds store in order to pre-populate
  1754. //
  1755. DWORD dwRememberedCredType = pArgs->dwCurrentCredentialType;
  1756. pszUserName = NULL;
  1757. if ((FALSE == pArgs->fUseSameUserName) &&
  1758. (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType) &&
  1759. (FALSE == (BOOL)(CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)))
  1760. {
  1761. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  1762. }
  1763. GetUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszUserName);
  1764. //
  1765. // Restore credential store
  1766. //
  1767. pArgs->dwCurrentCredentialType = dwRememberedCredType;
  1768. if (pszUserName)
  1769. {
  1770. //
  1771. // check username length
  1772. //
  1773. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  1774. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  1775. {
  1776. CmFree(pszUserName);
  1777. pArgs->szInetUserName[0] = TEXT('\0');
  1778. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  1779. }
  1780. else
  1781. {
  1782. lstrcpyU(pArgs->szInetUserName, pszUserName);
  1783. CmFree(pszUserName);
  1784. }
  1785. }
  1786. else
  1787. {
  1788. *pArgs->szInetUserName = TEXT('\0');
  1789. }
  1790. //
  1791. // Read in inet password unless we are reconnecting in which case, we
  1792. // already have the correct password, and we want to use it and dial
  1793. // automatically.
  1794. //
  1795. if (!(pArgs->dwFlags & FL_RECONNECT))
  1796. {
  1797. LPTSTR pszPassword = NULL;
  1798. GetUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszPassword);
  1799. if (!pszPassword)
  1800. {
  1801. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  1802. }
  1803. else
  1804. {
  1805. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  1806. if ((UINT)lstrlenU(pszPassword) > __min(PWLEN, nTmp))
  1807. {
  1808. CmFree(pszPassword);
  1809. pszPassword = CmStrCpyAlloc(TEXT(""));
  1810. }
  1811. (VOID)pArgs->SecureInetPW.SetPassword(pszPassword);
  1812. CmWipePassword(pszPassword);
  1813. CmFree(pszPassword);
  1814. }
  1815. }
  1816. }
  1817. //
  1818. // The presence of either lpRasNoUser or lpEapLogonInfo indicates
  1819. // that we retrieved credentials via WinLogon. We ignore cached
  1820. // creds in this situation.
  1821. //
  1822. if ((!pArgs->lpRasNoUser) && (!pArgs->lpEapLogonInfo))
  1823. {
  1824. //
  1825. // get username, domain, etc. from CMS file
  1826. //
  1827. GetUserInfo(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  1828. if (pszUserName)
  1829. {
  1830. //
  1831. // check username length
  1832. //
  1833. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  1834. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  1835. {
  1836. CmFree(pszUserName);
  1837. pszUserName = CmStrCpyAlloc(TEXT(""));
  1838. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUserName);
  1839. }
  1840. lstrcpyU(pArgs->szUserName, pszUserName);
  1841. CmFree(pszUserName);
  1842. }
  1843. else
  1844. {
  1845. *pArgs->szUserName = TEXT('\0');
  1846. }
  1847. //
  1848. // Read in the standard password unless we are reconnecting in which case
  1849. // we already have the correct password, and we want to use it and dial
  1850. // automatically.
  1851. //
  1852. if (!(pArgs->dwFlags & FL_RECONNECT))
  1853. {
  1854. pszTmp = NULL;
  1855. GetUserInfo(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp);
  1856. if (pszTmp)
  1857. {
  1858. //
  1859. // max length for user password
  1860. //
  1861. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryMaxPassword,PWLEN);
  1862. if ((UINT)lstrlenU(pszTmp) > __min(PWLEN,nTmp))
  1863. {
  1864. CmFree(pszTmp);
  1865. pszTmp = CmStrCpyAlloc(TEXT(""));
  1866. }
  1867. (VOID)pArgs->SecurePW.SetPassword(pszTmp);
  1868. CmWipePassword(pszTmp);
  1869. CmFree(pszTmp);
  1870. }
  1871. else
  1872. {
  1873. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  1874. }
  1875. }
  1876. //
  1877. // Load domain info
  1878. //
  1879. LPTSTR pszDomain = NULL;
  1880. GetUserInfo(pArgs, UD_ID_DOMAIN, (PVOID*)&pszDomain);
  1881. if (pszDomain)
  1882. {
  1883. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  1884. if (nTmp <= 0)
  1885. {
  1886. nTmp = DNLEN;
  1887. }
  1888. if ((UINT)lstrlenU(pszDomain) > __min(DNLEN, nTmp))
  1889. {
  1890. CmFree(pszDomain);
  1891. pszDomain = CmStrCpyAlloc(TEXT(""));
  1892. }
  1893. lstrcpyU(pArgs->szDomain, pszDomain);
  1894. CmFree(pszDomain);
  1895. }
  1896. else
  1897. {
  1898. *pArgs->szDomain = TEXT('\0');
  1899. }
  1900. }
  1901. //
  1902. // fDialAutomatically,
  1903. // fRememberMainPassword
  1904. //
  1905. if (pArgs->fHideDialAutomatically)
  1906. {
  1907. pArgs->fDialAutomatically = FALSE;
  1908. }
  1909. else
  1910. {
  1911. PVOID pv = &pArgs->fDialAutomatically;
  1912. GetUserInfo(pArgs, UD_ID_NOPROMPT, &pv);
  1913. }
  1914. if (pArgs->fHideRememberPassword)
  1915. {
  1916. pArgs->fRememberMainPassword = FALSE;
  1917. }
  1918. else
  1919. {
  1920. //
  1921. // For Win2K+ this gets trickier because we use the RAS cred store and
  1922. // we know which creds were saved. Thus we need to modify this flag according
  1923. // to what credentials we actually have, insted of what was retrieved from the registry/file.
  1924. // This needs to be done after calling the function that refreshes credential types (above).
  1925. //
  1926. if (OS_NT5)
  1927. {
  1928. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  1929. {
  1930. pArgs->fRememberMainPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)? TRUE: FALSE);
  1931. }
  1932. else
  1933. {
  1934. pArgs->fRememberMainPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)? TRUE: FALSE);
  1935. }
  1936. }
  1937. else
  1938. {
  1939. PVOID pv = &pArgs->fRememberMainPassword;
  1940. GetUserInfo(pArgs, UD_ID_REMEMBER_PWD, &pv);
  1941. }
  1942. }
  1943. //
  1944. // remember non-tunnel password?
  1945. //
  1946. if (pArgs->fHideRememberInetPassword)
  1947. {
  1948. pArgs->fRememberInetPassword = FALSE;
  1949. }
  1950. else
  1951. {
  1952. //
  1953. // For Win2K+ this gets trickier because we use the RAS cred store and
  1954. // we know which creds were saved. Thus we need to modify this flag according
  1955. // to what credentials we actually have, insted of what was retrieved from the registry/file.
  1956. // This needs to be done after calling the function that refreshes credential types (above).
  1957. //
  1958. if (OS_NT5)
  1959. {
  1960. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  1961. {
  1962. pArgs->fRememberInetPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)? TRUE: FALSE);
  1963. }
  1964. else
  1965. {
  1966. pArgs->fRememberInetPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)? TRUE: FALSE);
  1967. }
  1968. }
  1969. else
  1970. {
  1971. PVOID pv = &pArgs->fRememberInetPassword;
  1972. GetUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, &pv);
  1973. }
  1974. }
  1975. //
  1976. // Make sure that the passwords are empty if we don't want to remember them
  1977. // unless we are reconnecting in which case we will just use what we have
  1978. // from the previous connection. When the log on type is ICS don't want
  1979. // to clear the passwords either.
  1980. //
  1981. if ((!(pArgs->dwFlags & FL_RECONNECT)) &&
  1982. (!pArgs->lpRasNoUser) &&
  1983. (!pArgs->lpEapLogonInfo) &&
  1984. (CM_LOGON_TYPE_ICS != pArgs->dwWinLogonType))
  1985. {
  1986. //
  1987. // NULL the password if dial-auto is disabled.
  1988. //
  1989. if (!pArgs->fRememberMainPassword)
  1990. {
  1991. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  1992. }
  1993. if (!pArgs->fRememberInetPassword)
  1994. {
  1995. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  1996. }
  1997. }
  1998. //
  1999. // has references
  2000. //
  2001. pszTmp = pArgs->piniService->GPPS(c_pszCmSectionIsp, c_pszCmEntryIspReferences);
  2002. pArgs->fHasRefs = (pszTmp && *pszTmp ? TRUE : FALSE);
  2003. CmFree(pszTmp);
  2004. //
  2005. // do we have valid pbk's?
  2006. //
  2007. pArgs->fHasValidTopLevelPBK = ValidTopLevelPBK(pArgs);
  2008. if (pArgs->fHasRefs)
  2009. {
  2010. pArgs->fHasValidReferencedPBKs = ValidReferencedPBKs(pArgs);
  2011. }
  2012. //
  2013. // Get idle settings for auto disconnect
  2014. // 1.0 profile has a BOOL flag "Idle", if FALSE, IdleTimeout is ignored
  2015. //
  2016. if (!pArgs->piniBothNonFav->GPPB(c_pszCmSection, c_pszCmEntryIdle, TRUE))
  2017. {
  2018. //
  2019. // If this is a 1.0 profile and Idle==0, set IdleTimeout to 0, so CMMOM works correctly
  2020. //
  2021. pArgs->dwIdleTimeout = 0; // never timeout
  2022. pArgs->piniProfile->WPPI(c_pszCmSection, c_pszCmEntryIdle, TRUE); // write back
  2023. pArgs->piniProfile->WPPI(c_pszCmSection, c_pszCmEntryIdleTimeout, 0); // write back
  2024. }
  2025. else
  2026. {
  2027. pArgs->dwIdleTimeout = (int) pArgs->piniBothNonFav->GPPI(c_pszCmSection,
  2028. c_pszCmEntryIdleTimeout,
  2029. DEFAULT_IDLETIMEOUT);
  2030. }
  2031. //
  2032. // get redial count
  2033. // 1.0 profile has a BOOL flag "Redial", if FALSE, RedialCount is ignored
  2034. //
  2035. if (!pArgs->piniBothNonFav->GPPB(c_pszCmSection, c_pszCmEntryRedial, TRUE))
  2036. {
  2037. //
  2038. // If this is a 1.0 profile and Redial==0, set RetryCount to 0
  2039. //
  2040. pArgs->nMaxRedials = 0;
  2041. pArgs->piniBothNonFav->WPPI(c_pszCmSection, c_pszCmEntryRedialCount, 0); // write back
  2042. }
  2043. else
  2044. {
  2045. pArgs->nMaxRedials = (int) pArgs->piniBothNonFav->GPPI(c_pszCmSection,
  2046. c_pszCmEntryRedialCount,
  2047. DEFAULT_REDIALS);
  2048. if (pArgs->nMaxRedials > MAX_NUMBER_OF_REDIALS)
  2049. {
  2050. pArgs->nMaxRedials = MAX_NUMBER_OF_REDIALS;
  2051. }
  2052. }
  2053. //
  2054. // Get the redial delay value
  2055. //
  2056. pArgs->nRedialDelay = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryRedialDelay,DEFAULT_REDIAL_DELAY);
  2057. //
  2058. // should we enable ISDN dial on demand?
  2059. //
  2060. pArgs->dwIsdnDialMode = pArgs->piniService->GPPI(c_pszCmSection,
  2061. c_pszCmEntryIsdnDialMode,
  2062. CM_ISDN_MODE_SINGLECHANNEL);
  2063. //
  2064. // Get the Tapi location from the registry
  2065. //
  2066. if (pArgs->fAccessPointsEnabled)
  2067. {
  2068. pArgs->tlsTapiLink.dwTapiLocationForAccessPoint = pArgs->piniProfile->GPPI(c_pszCmSection,
  2069. c_pszCmEntryTapiLocation);
  2070. }
  2071. CMTRACE(TEXT("End LoadProperties()"));
  2072. }
  2073. //+---------------------------------------------------------------------------
  2074. //
  2075. // Function: LoadIconsAndBitmaps
  2076. //
  2077. // Synopsis: This func loads icon and bitmap settings. It should be part
  2078. // of the main dlg init.
  2079. //
  2080. // Arguments: pArgs [the ptr to ArgsStruct]
  2081. // hwndDlg [the main dlg]
  2082. //
  2083. // Returns: NONE
  2084. //
  2085. // History: henryt Copied from LoadFromFile() 5/2/97
  2086. //
  2087. //----------------------------------------------------------------------------
  2088. void LoadIconsAndBitmaps(
  2089. ArgsStruct *pArgs,
  2090. HWND hwndDlg
  2091. )
  2092. {
  2093. LPTSTR pszTmp;
  2094. UINT nTmp;
  2095. // Load large icon name
  2096. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryBigIcon);
  2097. if (*pszTmp)
  2098. {
  2099. //
  2100. // Make sure we have a full path (if appropriate) and load big icon
  2101. //
  2102. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  2103. pArgs->hBigIcon = CmLoadIcon(g_hInst, pszFile);
  2104. CmFree(pszFile);
  2105. }
  2106. CmFree(pszTmp);
  2107. // Use default (EXE) large icon if no user icon found
  2108. if (!pArgs->hBigIcon)
  2109. {
  2110. pArgs->hBigIcon = CmLoadIcon(g_hInst, MAKEINTRESOURCE(IDI_APP));
  2111. }
  2112. SendMessageU(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM) pArgs->hBigIcon);
  2113. // Load small icon name
  2114. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntrySmallIcon);
  2115. if (*pszTmp)
  2116. {
  2117. //
  2118. // Make sure we have a full path (if appropriate) and load small icon
  2119. //
  2120. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  2121. pArgs->hSmallIcon = CmLoadSmallIcon(g_hInst, pszFile);
  2122. CmFree(pszFile);
  2123. }
  2124. CmFree(pszTmp);
  2125. // Use default (EXE) small icon if no user icon found
  2126. if (!pArgs->hSmallIcon)
  2127. {
  2128. pArgs->hSmallIcon = CmLoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_APP));
  2129. }
  2130. SendMessageU(hwndDlg,WM_SETICON,ICON_SMALL,(LPARAM) pArgs->hSmallIcon);
  2131. //
  2132. // this is where the Bitmap gets loaded in. Check to see first if we're doing
  2133. // the Future Splash thang. if so, no bitmap
  2134. //
  2135. // Note that we do not load FutureSplash if this is WinLogon. This is because
  2136. // Future Splash Animations can have imbedded actions and thus could be used
  2137. // to launch web pages, etc. from WinLogon as the system account. Definitely
  2138. // would be a security hole.
  2139. //
  2140. nTmp = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryAnimatedLogo);
  2141. if (!nTmp || IsLogonAsSystem())
  2142. {
  2143. //
  2144. // either there was no 'Animated Logo' entry, or it was 0, which means
  2145. // we go ahead and load the bitmap.
  2146. //
  2147. LoadLogoBitmap(pArgs, hwndDlg);
  2148. }
  2149. else
  2150. {
  2151. //
  2152. // if, for any reason, loading FS OC fails, go ahead and
  2153. // degrade and load the logo bitmap.
  2154. //
  2155. if (S_OK != LoadFutureSplash(pArgs, hwndDlg))
  2156. {
  2157. LoadLogoBitmap(pArgs, hwndDlg);
  2158. }
  2159. }
  2160. }
  2161. //+----------------------------------------------------------------------------
  2162. //
  2163. // Function: DoRasHangup
  2164. //
  2165. // Synopsis: Hangup the given RAS device handle
  2166. //
  2167. // Arguments: prlsRasLink - Ptr to RAS linkage struct
  2168. // hRasConnection - The RAS device to hangup
  2169. // hwndDlg - The main dlg to display "Disconnecting .. " msg
  2170. // Only used if fWaitForComplete is TRUE
  2171. // Optional, default = NULL
  2172. // fWaitForComplete - Whether to wait for Hangup to complete on 95
  2173. // If set to TRUE, will wait until hRasConnection
  2174. // is invalid. Optional, default = FALSE
  2175. // pfWaiting - Ptr to boolean value indicating our wait state
  2176. // and whether Timer and Ras messages should be
  2177. // ignored. Optional, default = NULL
  2178. //
  2179. // Returns: DWORD - ERROR_SUCCESS if success or error code
  2180. //
  2181. // Note: pArgs is removed so that the Disconnect path can use this function
  2182. // thus concentrating the timing mess in one place.
  2183. //
  2184. // History: fengsun Created Header 10/22/97
  2185. // fengsun Add fWaitForComplete 12/18/97
  2186. // nickball Removed pArgs dependency
  2187. //
  2188. //+----------------------------------------------------------------------------
  2189. DWORD DoRasHangup(RasLinkageStruct *prlsRasLink,
  2190. HRASCONN hRasConnection,
  2191. HWND hwndDlg,
  2192. BOOL fWaitForComplete,
  2193. LPBOOL pfWaiting)
  2194. {
  2195. DWORD dwRes = ERROR_SUCCESS;
  2196. MYDBGASSERT(hRasConnection != NULL);
  2197. MYDBGASSERT(prlsRasLink->pfnHangUp != NULL);
  2198. //
  2199. // Do we need to check the return value
  2200. // now that RAS is going to disconnect modem too?
  2201. //
  2202. dwRes = prlsRasLink->pfnHangUp(hRasConnection);
  2203. CMTRACE1(TEXT("DoRasHangup() RasHangup() returned %u."), dwRes);
  2204. // On Win32 RasHangup returns immediately, so loop until we
  2205. // are certain that the disconnected state had been reached
  2206. if ((dwRes == ERROR_SUCCESS) && prlsRasLink->pfnGetConnectStatus)
  2207. {
  2208. RASCONNSTATUS rcs;
  2209. CMTRACE(TEXT("DoRasHangup() Waiting for hangup to complete"));
  2210. //
  2211. // On 95 Wait for HANGUP_TIMEOUT seconds
  2212. // On NT wait until the connection is released
  2213. // This will cause this to loop till the connection status
  2214. // is RASCS_Disconnected
  2215. //
  2216. #define HANGUP_TIMEOUT 60 // timeout for 95 hangup
  2217. if (pfWaiting)
  2218. {
  2219. //
  2220. // Keep the message looping to avoid freezing CM
  2221. // But do not handle WM_TIMER and RAS msg
  2222. //
  2223. MYDBGASSERT(!*pfWaiting);
  2224. *pfWaiting = TRUE;
  2225. }
  2226. if (fWaitForComplete && hwndDlg)
  2227. {
  2228. //
  2229. // Display the disconnecting message, if we have to wait
  2230. //
  2231. LPTSTR pszTmp = CmLoadString(g_hInst,IDMSG_DISCONNECTING);
  2232. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTmp);
  2233. CmFree(pszTmp);
  2234. }
  2235. DWORD dwStartWaitTime = GetTickCount();
  2236. HCURSOR hWaitCursor = LoadCursorU(NULL,IDC_WAIT);
  2237. ZeroMemory(&rcs,sizeof(rcs));
  2238. rcs.dwSize = sizeof(rcs);
  2239. while ((dwRes = prlsRasLink->pfnGetConnectStatus(hRasConnection,&rcs)) == ERROR_SUCCESS)
  2240. {
  2241. //
  2242. // If it is NT, or do not need to wait for hangup to complete,
  2243. // RASCS_Disconnected state is considered hangup complete
  2244. //
  2245. if (rcs.rasconnstate == RASCS_Disconnected &&
  2246. (!fWaitForComplete || OS_NT))
  2247. {
  2248. break;
  2249. }
  2250. //
  2251. // We only have time out for 95/98
  2252. //
  2253. if (OS_W9X && (GetTickCount() - dwStartWaitTime >= HANGUP_TIMEOUT * 1000))
  2254. {
  2255. CMTRACE(TEXT("DoRasHangup() Wait timed out"));
  2256. break;
  2257. }
  2258. //
  2259. // Try to dispatch message, however, some time the wait cursor is
  2260. // changed back to arrow
  2261. //
  2262. MSG msg;
  2263. while (PeekMessageU(&msg, NULL, 0, 0, PM_REMOVE))
  2264. {
  2265. if (msg.message != WM_SETCURSOR)
  2266. {
  2267. TranslateMessage(&msg);
  2268. DispatchMessageU(&msg);
  2269. if (GetCursor() != hWaitCursor)
  2270. {
  2271. SetCursor(hWaitCursor);
  2272. }
  2273. }
  2274. }
  2275. Sleep(500);
  2276. }
  2277. if (dwRes == ERROR_INVALID_HANDLE)
  2278. {
  2279. dwRes = ERROR_SUCCESS;
  2280. }
  2281. else
  2282. {
  2283. CMTRACE1(TEXT("MyRasHangup() RasGetConnectStatus(), GLE=%u."), dwRes);
  2284. }
  2285. if (pfWaiting)
  2286. {
  2287. *pfWaiting = FALSE;
  2288. }
  2289. }
  2290. CMTRACE(TEXT("DoRasHangup() completed"));
  2291. return dwRes;
  2292. }
  2293. //+----------------------------------------------------------------------------
  2294. //
  2295. // Function: MyRasHangup
  2296. //
  2297. // Synopsis: Simple wrapper for DoRasHangup, that takes pArgs as a param.
  2298. //
  2299. // Arguments: pArgs - Ptr to global Args struct
  2300. // hRasConnection - The RAS device to hangup
  2301. // hwndDlg - The main dlg to display "Disconnecting .. " msg
  2302. // Only used if fWaitForComplete is TRUE
  2303. // Optional, default = NULL
  2304. // fWaitForComplete - Whether to wait for Hangup to complete on 95
  2305. // If set to TRUE, will wait until hRasConnection
  2306. // is invalid. Optional, default = FALSE
  2307. //
  2308. // Returns: DWORD - ERROR_SUCCESS if success or error code
  2309. //
  2310. // History: nickball Implemented as wrapper 2/11/98
  2311. //
  2312. //+----------------------------------------------------------------------------
  2313. DWORD MyRasHangup(ArgsStruct *pArgs,
  2314. HRASCONN hRasConnection,
  2315. HWND ,
  2316. BOOL fWaitForComplete)
  2317. {
  2318. CMTRACE(TEXT("MyRasHangup() calling DoRasHangup()"));
  2319. return DoRasHangup(&pArgs->rlsRasLink, hRasConnection, NULL, fWaitForComplete, &pArgs->fIgnoreTimerRasMsg);
  2320. }
  2321. //+----------------------------------------------------------------------------
  2322. //
  2323. // Function: HangupCM
  2324. //
  2325. // Synopsis: hangup both dial-up and tunnel connection, if exist
  2326. //
  2327. // Arguments: ArgsStruct *pArgs -
  2328. // hwndDlg the main dlg to display "Disconnecting .. " msg
  2329. // fWaitForComplete: Whether to wait for Hangup to complete on 95
  2330. // If set to TRUE, will wait until hRasConnection
  2331. // is invalid.
  2332. //
  2333. // Returns: DWORD -
  2334. //
  2335. // History: fengsun Created Header 10/22/97
  2336. // fengsun Add fWaitForComplete 12/18/97
  2337. //
  2338. //+----------------------------------------------------------------------------
  2339. DWORD HangupCM(ArgsStruct *pArgs,
  2340. HWND hwndDlg,
  2341. BOOL fWaitForComplete,
  2342. BOOL fUpdateTable)
  2343. {
  2344. MYDBGASSERT(pArgs);
  2345. MYDBGASSERT(hwndDlg);
  2346. CMTRACE(TEXT("HangupCM()"));
  2347. if (!pArgs)
  2348. {
  2349. CMTRACE(TEXT("HangupCM() invalid parameter."));
  2350. return (ERROR_INVALID_PARAMETER);
  2351. }
  2352. DWORD dwRes = ERROR_SUCCESS;
  2353. //
  2354. // If change password dialog is up tell it to go away
  2355. //
  2356. if (pArgs->hWndChangePassword)
  2357. {
  2358. CMTRACE(TEXT("HangupCM() Terminating ChangePassword dialog"));
  2359. PostMessage(pArgs->hWndChangePassword, WM_COMMAND, IDCANCEL, 0);
  2360. }
  2361. //
  2362. // If Callback number dialog is up tell it to go away too.
  2363. //
  2364. if (pArgs->hWndCallbackNumber)
  2365. {
  2366. CMTRACE(TEXT("HangupCM() Terminating CallbackNumber dialog"));
  2367. PostMessage(pArgs->hWndCallbackNumber, WM_COMMAND, IDCANCEL, 0);
  2368. }
  2369. //
  2370. // If Callback number dialog is up tell it to go away too.
  2371. //
  2372. if (pArgs->hWndRetryAuthentication)
  2373. {
  2374. CMTRACE(TEXT("HangupCM() Terminating RetryAuthentication dialog"));
  2375. PostMessage(pArgs->hWndRetryAuthentication, WM_COMMAND, IDCANCEL, 0);
  2376. }
  2377. //
  2378. // If table updates are desired set the entry to the disconnecting state
  2379. // Note: In the case of redial, we don't want to modify the table state
  2380. // even though we are hanging up because technically we are still connecting.
  2381. //
  2382. if (fUpdateTable)
  2383. {
  2384. UpdateTable(pArgs, CM_DISCONNECTING);
  2385. }
  2386. //
  2387. // Check the RasLink pointer and hang up the device, tunnel first
  2388. //
  2389. #ifdef DEBUG
  2390. if (!pArgs->rlsRasLink.pfnHangUp)
  2391. {
  2392. CMTRACE(TEXT("HangupCM() can't hang up."));
  2393. }
  2394. #endif
  2395. //
  2396. // Show wait cursor before hanging up
  2397. //
  2398. HCURSOR hPrev;
  2399. if (hwndDlg)
  2400. {
  2401. hPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  2402. ShowCursor(TRUE);
  2403. }
  2404. //
  2405. // The assumption is that we have been connected, why else would we call
  2406. // hangup. So release statistics handles, hooks, etc.
  2407. //
  2408. if (pArgs->pConnStatistics)
  2409. {
  2410. pArgs->pConnStatistics->Close();
  2411. }
  2412. //
  2413. // Hangup connections
  2414. //
  2415. if (pArgs->rlsRasLink.pfnHangUp && pArgs->hrcTunnelConn)
  2416. {
  2417. //
  2418. // first, hangup tunnel connection
  2419. //
  2420. CMTRACE(TEXT("HangupCM() calling MyRasHangup() for tunnel connection"));
  2421. dwRes = MyRasHangup(pArgs, pArgs->hrcTunnelConn, hwndDlg, fWaitForComplete);
  2422. #ifdef DEBUG
  2423. if (dwRes != ERROR_SUCCESS)
  2424. {
  2425. CMTRACE1(TEXT("MyRasHangup failed, GLE=%u."), GetLastError());
  2426. }
  2427. #endif
  2428. pArgs->hrcTunnelConn = NULL;
  2429. }
  2430. //
  2431. // If we have a valid link and handle, hangup the modem
  2432. //
  2433. if (pArgs->rlsRasLink.pfnHangUp && pArgs->hrcRasConn)
  2434. {
  2435. CMTRACE(TEXT("HangupCM() calling MyRasHangup() for dial-up connection"));
  2436. dwRes = MyRasHangup(pArgs, pArgs->hrcRasConn);
  2437. }
  2438. // Restore cursor
  2439. if (hwndDlg)
  2440. {
  2441. ShowCursor(FALSE);
  2442. SetCursor(hPrev);
  2443. }
  2444. pArgs->hrcRasConn = NULL;
  2445. //
  2446. // Update the Connection table if asked
  2447. //
  2448. if (fUpdateTable)
  2449. {
  2450. UpdateTable(pArgs, CM_DISCONNECTED);
  2451. }
  2452. return (dwRes);
  2453. }
  2454. //+----------------------------------------------------------------------------
  2455. //
  2456. // Function: CleanupZapThread
  2457. //
  2458. // Synopsis: Simple helper to deal with signaling an event to stop Zap thread
  2459. // and waiting for the thread to terminate.
  2460. //
  2461. // Arguments: HANDLE hEvent - The event handle
  2462. // HANDLE hThread - Handle to the Zap thread.
  2463. //
  2464. // Returns: static void - Nothing
  2465. //
  2466. // History: nickball Created 3/5/98
  2467. //
  2468. //+----------------------------------------------------------------------------
  2469. static void CleanupZapThread(HANDLE hEvent,
  2470. HANDLE hThread)
  2471. {
  2472. MYDBGASSERT(hEvent);
  2473. MYDBGASSERT(hThread);
  2474. //
  2475. // If we have an event, then it is assumed that have a Zap thread running
  2476. //
  2477. if (hEvent)
  2478. {
  2479. //
  2480. // Signal termination to notify thread that we are done
  2481. //
  2482. BOOL bRes = SetEvent(hEvent);
  2483. #ifdef DEBUG
  2484. if (!bRes)
  2485. {
  2486. CMTRACE1(TEXT("CleanupZapThread() SetEvent() failed, GLE=%u."), GetLastError());
  2487. }
  2488. #endif
  2489. if (hThread)
  2490. {
  2491. //
  2492. // Wait for thread to terminate, but pump messages in the mean time
  2493. //
  2494. BOOL bDone = FALSE;
  2495. DWORD dwWaitCode;
  2496. while (FALSE == bDone)
  2497. {
  2498. dwWaitCode = MsgWaitForMultipleObjects(1, &hThread, FALSE, MAX_OBJECT_WAIT, QS_ALLINPUT);
  2499. switch(dwWaitCode)
  2500. {
  2501. //
  2502. // Thread has terminated, or time is up, we're done here
  2503. //
  2504. case -1:
  2505. CMTRACE1(TEXT("CleanupZapThread() MsgWaitForMultipleObjects returned an error GLE=%u."),
  2506. GetLastError());
  2507. case WAIT_TIMEOUT:
  2508. case WAIT_OBJECT_0:
  2509. bDone = TRUE;
  2510. break;
  2511. //
  2512. // If there is a message in the queue, process it
  2513. //
  2514. case WAIT_OBJECT_0+1:
  2515. {
  2516. MSG msg;
  2517. while (PeekMessageU(&msg, 0, 0, 0, PM_REMOVE))
  2518. {
  2519. TranslateMessage(&msg);
  2520. DispatchMessageU(&msg);
  2521. }
  2522. break;
  2523. }
  2524. //
  2525. // Unexpected, report, but continue
  2526. //
  2527. default:
  2528. MYDBGASSERT(FALSE);
  2529. }
  2530. }
  2531. //
  2532. // We are done with the thread, close the handle
  2533. //
  2534. bRes = CloseHandle(hThread);
  2535. #ifdef DEBUG
  2536. if (!bRes)
  2537. {
  2538. CMTRACE1(TEXT("CleanupZapThread() CloseHandle(hThread) failed, GLE=%u."), GetLastError());
  2539. }
  2540. #endif
  2541. }
  2542. //
  2543. // Close our event handle
  2544. //
  2545. bRes = CloseHandle(hEvent);
  2546. #ifdef DEBUG
  2547. if (!bRes)
  2548. {
  2549. CMTRACE1(TEXT("CleanupZapThread() CloseHandle(hEvent) failed, GLE=%u."), GetLastError());
  2550. }
  2551. #endif
  2552. }
  2553. }
  2554. //+----------------------------------------------------------------------------
  2555. //
  2556. // Function: OnConnectedCM
  2557. //
  2558. // Synopsis: Process WM_CONNECTED_CM which indicates that we are connected and
  2559. // connect processing such as connect actions can begin
  2560. //
  2561. // Arguments: HWND hwndDlg - HWND of main dialog
  2562. // ArgsStruct *pArgs - Ptr to global Args struct
  2563. //
  2564. // Returns: Nothing
  2565. //
  2566. // History: nickball Created 03/05/98
  2567. //
  2568. //+----------------------------------------------------------------------------
  2569. void OnConnectedCM(HWND hwndDlg, ArgsStruct *pArgs)
  2570. {
  2571. HANDLE hEvent = NULL;
  2572. HANDLE hThread = NULL;
  2573. CActionList ConnectActList;
  2574. CActionList AutoActList;
  2575. //
  2576. // Check to see if we are in a valid state to connect. if not just abort.
  2577. //
  2578. MYDBGASSERT(pArgs);
  2579. if (pArgs->hrcRasConn == NULL && pArgs->hrcTunnelConn == NULL)
  2580. {
  2581. CMTRACE(TEXT("Bogus OnConnectCM msg received"));
  2582. goto OnConnectedCMExit;
  2583. }
  2584. //
  2585. // Set state to online
  2586. //
  2587. if (IsDialingTunnel(pArgs))
  2588. {
  2589. //
  2590. // For Win2K+ this tries to resave the EAP Auth data if there is any present in the .cms for a tunnel
  2591. //
  2592. if (OS_NT5)
  2593. {
  2594. CIni iniFile(g_hInst, pArgs->piniService->GetFile());
  2595. ReSaveEapCustomAuthData(pArgs, &iniFile, TRUE, pArgs->pszRasPbk);
  2596. }
  2597. //
  2598. // This is a patch, it is only a patch - #187202
  2599. // UI should not be tied to RASENTRY type, but it is for now so we
  2600. // have to make sure that it is set back to RASET_Internet once we
  2601. // have our tunnel connection connected.
  2602. //
  2603. if (OS_NT5)
  2604. {
  2605. LPRASENTRY pRasEntry = MyRGEP(pArgs->pszRasPbk, pArgs->szServiceName, &pArgs->rlsRasLink);
  2606. CMASSERTMSG(pRasEntry, TEXT("OnConnectedCM() - MyRGEP() failed."));
  2607. //
  2608. // Set the type back and save the RASENTRY
  2609. //
  2610. if (pRasEntry)
  2611. {
  2612. ((LPRASENTRY_V500)pRasEntry)->dwType = RASET_Internet;
  2613. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  2614. {
  2615. DWORD dwTmp = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  2616. pArgs->szServiceName,
  2617. pRasEntry,
  2618. pRasEntry->dwSize,
  2619. NULL,
  2620. 0);
  2621. CMTRACE2(TEXT("OnConnectedCM() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  2622. MYDBGSTR(pArgs->szServiceName), dwTmp);
  2623. CMASSERTMSG(dwTmp == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  2624. }
  2625. }
  2626. CmFree(pRasEntry);
  2627. }
  2628. pArgs->psState = PS_TunnelOnline;
  2629. }
  2630. else
  2631. {
  2632. //
  2633. // For Win2K+ this tries to resave the EAP Auth data if there is any present in the .cms for
  2634. // a dial-up connection
  2635. //
  2636. if (OS_NT5)
  2637. {
  2638. DWORD dwEntry = pArgs->nDialIdx;
  2639. CIni *piniService = NULL;
  2640. LPTSTR pszRasPbk = NULL;
  2641. if (OS_NT && pArgs->fUseTunneling)
  2642. {
  2643. if (!pArgs->pszRasHiddenPbk)
  2644. {
  2645. pArgs->pszRasHiddenPbk = CreateRasPrivatePbk(pArgs);
  2646. }
  2647. pszRasPbk = pArgs->pszRasHiddenPbk;
  2648. }
  2649. else
  2650. {
  2651. pszRasPbk = pArgs->pszRasPbk;
  2652. }
  2653. //
  2654. // Need to work with the correct service file(the top-level service
  2655. // or a referenced service).
  2656. //
  2657. piniService = GetAppropriateIniService(pArgs, dwEntry);
  2658. if (piniService)
  2659. {
  2660. CIni iniFile(g_hInst, piniService->GetFile());
  2661. ReSaveEapCustomAuthData(pArgs, &iniFile, FALSE, pszRasPbk);
  2662. delete piniService;
  2663. piniService = NULL;
  2664. }
  2665. }
  2666. //
  2667. // Set dial index back to primary number
  2668. //
  2669. pArgs->nDialIdx = 0;
  2670. pArgs->psState = PS_Online;
  2671. //
  2672. // Make sure to update the stored username back to just the Username as RAS has saved the exact username
  2673. // that we dialed with including realm info.
  2674. //
  2675. if (OS_NT5)
  2676. {
  2677. if (!pArgs->fUseTunneling || pArgs->fUseSameUserName)
  2678. {
  2679. if (0 != lstrcmpi(pArgs->szUserName, pArgs->pRasDialParams->szUserName))
  2680. {
  2681. MYVERIFY(SaveUserInfo(pArgs, UD_ID_USERNAME, pArgs->szUserName));
  2682. }
  2683. }
  2684. else
  2685. {
  2686. if (0 != lstrcmpi(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName))
  2687. {
  2688. MYVERIFY(SaveUserInfo(pArgs, UD_ID_INET_USERNAME, pArgs->szInetUserName));
  2689. }
  2690. }
  2691. }
  2692. }
  2693. pArgs->dwStateStartTime = GetTickCount();
  2694. // pszMsg = GetDurMsg(g_hInst,pArgs->dwStateStartTime); // connect duration
  2695. pArgs->nLastSecondsDisplay = (UINT) -1;
  2696. //
  2697. // added by byao: for PPTP connection
  2698. //
  2699. if (pArgs->fUseTunneling && pArgs->psState == PS_Online)
  2700. {
  2701. //
  2702. // Now do the second dial: PPTP dialup
  2703. //
  2704. pArgs->psState = PS_TunnelDialing;
  2705. pArgs->dwStateStartTime = GetTickCount();
  2706. pArgs->nLastSecondsDisplay = (UINT) -1;
  2707. DWORD dwRes = DoTunnelDial(hwndDlg, pArgs);
  2708. if (ERROR_SUCCESS != dwRes)
  2709. {
  2710. HangupCM(pArgs, hwndDlg);
  2711. UpdateError(pArgs, dwRes);
  2712. SetLastError(dwRes);
  2713. }
  2714. goto OnConnectedCMExit;
  2715. }
  2716. //
  2717. // If this W95, then we need to Zap the RNA "Connected To" dialog
  2718. //
  2719. if (OS_W95)
  2720. {
  2721. // LPTSTR pszTmp = GetEntryName(pArgs, pArgs->pszRasPbk, pArgs->piniService);
  2722. LPTSTR pszTmp = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  2723. //
  2724. // Create an event for signalling Zap thread to snuff itself out
  2725. //
  2726. hEvent = CreateEventU(NULL, TRUE, FALSE, NULL);
  2727. if (hEvent)
  2728. {
  2729. hThread = ZapRNAConnectedTo(pszTmp, hEvent);
  2730. }
  2731. #ifdef DEBUG
  2732. if (!hEvent)
  2733. {
  2734. CMTRACE1(TEXT("OnConnectedCM() CreateEvent failed, GLE=%u."), GetLastError());
  2735. }
  2736. #endif
  2737. CmFree(pszTmp);
  2738. }
  2739. pArgs->Log.Log(CONNECT_EVENT);
  2740. //
  2741. // If connection actions are enabled, update the list and run it
  2742. //
  2743. CMTRACE(TEXT("Connect Actions enabled: processsing Run List"));
  2744. ConnectActList.Append(pArgs->piniService, c_pszCmSectionOnConnect);
  2745. if (!ConnectActList.RunAccordType(hwndDlg, pArgs))
  2746. {
  2747. //
  2748. // Connect action failed
  2749. // Run disconnect action
  2750. //
  2751. TCHAR szTmp[MAX_PATH];
  2752. MYVERIFY(GetModuleFileNameU(g_hInst, szTmp, MAX_PATH));
  2753. pArgs->Log.Log(DISCONNECT_EVENT, szTmp);
  2754. //
  2755. // Do not let disconnect action description overwrite the failure message
  2756. // Save the status pane text and restore it after disconnect actions
  2757. // 162942: Connect Action failed message is not displayed
  2758. //
  2759. TCHAR szFailedMsg[256] = TEXT("");
  2760. GetWindowTextU(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY),
  2761. szFailedMsg, sizeof(szFailedMsg)/sizeof(szFailedMsg[0]));
  2762. CActionList DisconnectActList;
  2763. DisconnectActList.Append(pArgs->piniService, c_pszCmSectionOnDisconnect);
  2764. DisconnectActList.RunAccordType(hwndDlg, pArgs, FALSE); // fStatusMsgOnFailure = FALSE
  2765. HangupCM(pArgs, hwndDlg);
  2766. //
  2767. // Restore the connect action failure message
  2768. //
  2769. if (szFailedMsg[0] != TEXT('\0'))
  2770. {
  2771. SetWindowTextU(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY),szFailedMsg);
  2772. }
  2773. goto OnConnectedCMExit;
  2774. }
  2775. //
  2776. // Always run AutoApps if there are any. Used to only do this in the
  2777. // non-autodial case, which was un-intuitive to our admin users.
  2778. //
  2779. AutoActList.Append(pArgs->piniService, c_pszCmSectionOnIntConnect);
  2780. AutoActList.RunAutoApp(hwndDlg, pArgs);
  2781. //
  2782. // Connect to the connection monitor
  2783. //
  2784. if (SUCCEEDED(UpdateTable(pArgs, CM_CONNECTED)))
  2785. {
  2786. if (SUCCEEDED(ConnectMonitor(pArgs)))
  2787. {
  2788. EndMainDialog(hwndDlg, pArgs, 0); // TRUE);
  2789. //
  2790. // SUCCESS We're fully connected, update error code
  2791. // as it may contain an interim value such as a
  2792. // failed primary number dial.
  2793. //
  2794. pArgs->dwExitCode = ERROR_SUCCESS;
  2795. }
  2796. else
  2797. {
  2798. HangupCM(pArgs, hwndDlg);
  2799. AppendStatusPane(hwndDlg,IDMSG_CMMON_LAUNCH_FAIL);
  2800. SetInteractive(hwndDlg,pArgs);
  2801. goto OnConnectedCMExit;
  2802. }
  2803. }
  2804. //
  2805. // Update changed password if needed
  2806. //
  2807. if (pArgs->fChangedPassword && pArgs->fRememberMainPassword)
  2808. {
  2809. //
  2810. // Note: fRememberMainPassword should never be set in the
  2811. // WinLogon case. Complain if we have WinLogon specific data.
  2812. //
  2813. MYDBGASSERT(!pArgs->lpRasNoUser);
  2814. MYDBGASSERT(!pArgs->lpEapLogonInfo);
  2815. //
  2816. // If the password has changed, then update storage
  2817. // Make sure this isn't a handle we are saving, because it would actually
  2818. // overwrite the correct password.
  2819. //
  2820. if (FALSE == pArgs->SecurePW.IsHandleToPassword())
  2821. {
  2822. LPTSTR pszClearPassword = NULL;
  2823. DWORD cbClearPassword = 0;
  2824. BOOL fRetPassword = FALSE;
  2825. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  2826. if (fRetPassword && pszClearPassword)
  2827. {
  2828. SaveUserInfo(pArgs, UD_ID_PASSWORD, (PVOID)pszClearPassword);
  2829. if (pArgs->fUseSameUserName)
  2830. {
  2831. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pszClearPassword);
  2832. //
  2833. // Make sure to update our pArgs structure
  2834. //
  2835. (VOID)pArgs->SecureInetPW.SetPassword(pszClearPassword);
  2836. }
  2837. //
  2838. // Clear and Free the clear-text password
  2839. //
  2840. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  2841. }
  2842. }
  2843. }
  2844. pArgs->fChangedPassword = FALSE;
  2845. //
  2846. // Update changed Internet password if needed
  2847. //
  2848. if (pArgs->fChangedInetPassword && pArgs->fRememberInetPassword)
  2849. {
  2850. LPTSTR pszClearInetPassword = NULL;
  2851. DWORD cbClearInetPassword = 0;
  2852. BOOL fRetPassword = FALSE;
  2853. fRetPassword = pArgs->SecureInetPW.GetPasswordWithAlloc(&pszClearInetPassword, &cbClearInetPassword);
  2854. if (fRetPassword && pszClearInetPassword)
  2855. {
  2856. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pszClearInetPassword);
  2857. //
  2858. // Clear and Free the clear-text password
  2859. //
  2860. pArgs->SecureInetPW.ClearAndFree(&pszClearInetPassword, cbClearInetPassword);
  2861. }
  2862. }
  2863. pArgs->fChangedInetPassword = FALSE;
  2864. OnConnectedCMExit:
  2865. if (hEvent)
  2866. {
  2867. MYDBGASSERT(OS_W9X);
  2868. CleanupZapThread(hEvent, hThread);
  2869. }
  2870. return;
  2871. }
  2872. #define MAX_BLOB_CHARS_PER_LINE 128
  2873. #define MAX_KEY_NAME_LEN 32
  2874. //+----------------------------------------------------------------------------
  2875. //
  2876. // Function: ReSaveEapCustomAuthData
  2877. //
  2878. // Synopsis: This function resaves CustomAuthData key of the EAP settings
  2879. // for the given section in a CMS file. The reason we need to
  2880. // resave the data is because at connect time the data might
  2881. // actually change (eg. if the users accepts a new auth cert). If
  2882. // we don't save the data back to the .cms, the user keeps getting
  2883. // prompted each time they connect to accept the same cert.
  2884. // This function figures out if there is EAP Custom Auth Data,
  2885. // and if so, it reads the blob from .cms, and the ras API,
  2886. // then it erases the .cms data from the file and calls
  2887. // SaveNewEAPCustomAuthData to construct and write out the new
  2888. // structure to .cms
  2889. //
  2890. // Arguments: ArgsStruct *pArgs - pointer to Args structure
  2891. // piniFile - CIni object pointing to .cms file
  2892. // fTunnelEntry - TRUE if this is a tunnel entry, FALSE otherwise
  2893. // pszRasPhoneBook - RAS Pbk
  2894. //
  2895. // Returns: DWORD - ERROR_SUCCESS or error code
  2896. //
  2897. // History: tomkel 08/09/2001 Created
  2898. //
  2899. //+----------------------------------------------------------------------------
  2900. DWORD ReSaveEapCustomAuthData(ArgsStruct *pArgs, CIni *piniFile, BOOL fTunnelEntry, LPTSTR pszRasPhoneBook)
  2901. {
  2902. int nTmp = 0;
  2903. LPTSTR pszDun = NULL;
  2904. LPTSTR pszIniSection = NULL;
  2905. DWORD dwRetVal = ERROR_SUCCESS;
  2906. //
  2907. // pszRasPhoneBook parameter can be NULL
  2908. //
  2909. if (NULL == pArgs || NULL == piniFile)
  2910. {
  2911. return ERROR_INVALID_PARAMETER;
  2912. }
  2913. //
  2914. // Get the DUN name
  2915. //
  2916. if ((FALSE == fTunnelEntry) && pArgs->aDialInfo[pArgs->nDialIdx].szDUN[0])
  2917. {
  2918. pszDun = CmStrCpyAlloc(pArgs->aDialInfo[pArgs->nDialIdx].szDUN);
  2919. }
  2920. else
  2921. {
  2922. pszDun = GetDefaultDunSettingName(piniFile, fTunnelEntry);
  2923. }
  2924. pszIniSection = CmStrCpyAlloc(TEXT("&"));
  2925. pszIniSection = CmStrCatAlloc(&pszIniSection, pszDun); //TODO:verify pArgs->aDialInfo[dwEntry].szDUN
  2926. piniFile->SetSection(pszIniSection);
  2927. nTmp = piniFile->GPPI(c_pszCmSectionDunServer, c_pszCmEntryDunServerCustomAuthKey, -1);
  2928. //
  2929. // If a type ID for EAP is specified, see if there is any EAP Custom Auth data
  2930. //
  2931. if ((-1 != nTmp) && pArgs->rlsRasLink.pfnGetCustomAuthData)
  2932. {
  2933. //
  2934. // We have an ID, read the EAP config data
  2935. //
  2936. LPBYTE pbEapStruct = NULL;
  2937. DWORD cbEapStruct = 0;
  2938. PBYTE pbEapData = NULL;
  2939. DWORD dwEapSize = 0;
  2940. PBYTE pbEapAuthData = NULL;
  2941. DWORD cbEapAuthData = 0;
  2942. DWORD dwTmp = 0;
  2943. LPWSTR pszLoadSection = NULL;
  2944. cbEapAuthData = 1024; // some default buffer size
  2945. pbEapAuthData = (PBYTE)CmMalloc(cbEapAuthData);
  2946. if (pbEapAuthData)
  2947. {
  2948. dwTmp = pArgs->rlsRasLink.pfnGetCustomAuthData(pszRasPhoneBook,
  2949. pArgs->pRasDialParams->szEntryName,
  2950. pbEapAuthData,
  2951. &cbEapAuthData);
  2952. if (ERROR_BUFFER_TOO_SMALL == dwTmp)
  2953. {
  2954. CmFree(pbEapAuthData);
  2955. pbEapAuthData = NULL;
  2956. pbEapAuthData = (PBYTE)CmMalloc(cbEapAuthData + 1);
  2957. if (pbEapAuthData)
  2958. {
  2959. dwTmp = pArgs->rlsRasLink.pfnGetCustomAuthData(pszRasPhoneBook,
  2960. pArgs->pRasDialParams->szEntryName,
  2961. pbEapAuthData,
  2962. &cbEapAuthData);
  2963. }
  2964. }
  2965. }
  2966. //
  2967. // Need to check pbEapAuthData in case the second CmMalloc failed above
  2968. //
  2969. if ((ERROR_SUCCESS == dwTmp) && pbEapAuthData)
  2970. {
  2971. BOOL fRead = FALSE;
  2972. pszLoadSection = piniFile->LoadSection(c_pszCmSectionDunServer);
  2973. //
  2974. // Read the existing data blob. We don't care about just the
  2975. // EapData. We want the whole Eap structure (EAP_CUSTOM_DATA)
  2976. //
  2977. fRead = ReadDunSettingsEapData(piniFile, &pbEapData, &dwEapSize, nTmp, &pbEapStruct, &cbEapStruct);
  2978. if (fRead && pbEapStruct && cbEapStruct && pszLoadSection)
  2979. {
  2980. //
  2981. // Erase the existing EAP Auth data from .cms file
  2982. //
  2983. HRESULT hr = EraseDunSettingsEapData(pszLoadSection, piniFile->GetFile());
  2984. //
  2985. // If we weren't able to erase anything (no write access)
  2986. // there is no point in trying to save the blob, otherwise save the new auth data
  2987. //
  2988. if (SUCCEEDED(hr))
  2989. {
  2990. DWORD dwRC = SaveNewEAPCustomAuthData(piniFile->GetFile(), pszLoadSection, cbEapAuthData, pbEapAuthData, pbEapStruct);
  2991. if (ERROR_SUCCESS != dwRC)
  2992. {
  2993. CMTRACE1(TEXT("ReSaveEapCustomAuthData() - SaveNewEAPCustomAuthData returned error = %u"), dwRC);
  2994. dwRetVal = dwRC;
  2995. }
  2996. }
  2997. else
  2998. {
  2999. CMTRACE1(TEXT("ReSaveEapCustomAuthData() - EraseDunSettingsEapData returned error = 0x%x"), hr);
  3000. dwRetVal = (0x0000FFFF & hr); // convert HRESULT back to normal Win32 error
  3001. }
  3002. }
  3003. }
  3004. CmFree(pbEapAuthData);
  3005. pbEapAuthData = NULL;
  3006. cbEapAuthData = 0;
  3007. CmFree(pbEapStruct);
  3008. pbEapStruct = NULL;
  3009. cbEapStruct = 0;
  3010. CmFree(pbEapData);
  3011. pbEapData = NULL;
  3012. dwEapSize = 0;
  3013. CmFree(pszLoadSection);
  3014. pszLoadSection = NULL;
  3015. }
  3016. CmFree(pszDun);
  3017. pszDun = NULL;
  3018. CmFree(pszIniSection);
  3019. pszIniSection = NULL;
  3020. return dwRetVal;
  3021. }
  3022. //+----------------------------------------------------------------------------
  3023. //
  3024. // Function: SaveNewEAPCustomAuthData
  3025. //
  3026. // Synopsis: This function resaves CustomAuthData key of the EAP settings
  3027. // for the given section in a CMS file. The reason we need to
  3028. // resave the data is because at connect time the data might
  3029. // actually change (eg. if the users accepts a new auth cert). If
  3030. // we don't save the data back to the .cms, the user keeps getting
  3031. // prompted each time they connect to accept the same cert.
  3032. //
  3033. // Arguments: pszCmsFile - filepath to the .cms file
  3034. // pszLoadSection - appropriate section in the file to write to
  3035. // cbEapAuthData - # of bytes in pbEapAuthData
  3036. // pbEapAuthData - buffer with the current eap custom auth data from RAS
  3037. // pbEapStruct - buffer of the existing (from .cms) EAP_CUSTOM_AUTH
  3038. // structure
  3039. //
  3040. // Returns: DWORD - ERROR_SUCCESS or error code
  3041. //
  3042. // History: tomkel 08/09/2001 Created
  3043. //
  3044. //+----------------------------------------------------------------------------
  3045. DWORD SaveNewEAPCustomAuthData(LPCTSTR pszCmsFile, LPTSTR pszLoadSection, DWORD cbEapAuthData, PBYTE pbEapAuthData, PBYTE pbEapStruct)
  3046. {
  3047. if (NULL == pszCmsFile || NULL == pszLoadSection || NULL == pbEapAuthData || NULL == pbEapStruct)
  3048. {
  3049. return ERROR_INVALID_PARAMETER;
  3050. }
  3051. DWORD dwRetVal = ERROR_SUCCESS;
  3052. LPSTR pszAnsiSection = WzToSzWithAlloc(pszLoadSection);
  3053. LPSTR pszAnsiCmsFile = WzToSzWithAlloc(pszCmsFile);
  3054. DWORD dwSize = cbEapAuthData + sizeof(EAP_CUSTOM_DATA); // Size for the new EAP_CUSTOM_DATA structure
  3055. EAP_CUSTOM_DATA *pNewEAPCustomData = (EAP_CUSTOM_DATA*)CmMalloc(dwSize);
  3056. if (pNewEAPCustomData && pszAnsiSection && pszAnsiCmsFile)
  3057. {
  3058. CHAR szOutput[MAX_BLOB_CHARS_PER_LINE+1] = {0};
  3059. CHAR szAnsiKeyName[MAX_KEY_NAME_LEN] = {0};
  3060. CHAR* pszOutput = NULL;
  3061. int iCount = 0;
  3062. int iLineNum = 0;
  3063. //
  3064. // Replace the data in the strucutre
  3065. //
  3066. LPBYTE pCurrentByte = (LPBYTE)pNewEAPCustomData;
  3067. EAP_CUSTOM_DATA *pEAPExistingCustomData = (EAP_CUSTOM_DATA *)pbEapStruct;
  3068. pNewEAPCustomData->dwSignature = pEAPExistingCustomData->dwSignature;
  3069. pNewEAPCustomData->dwCustomAuthKey = pEAPExistingCustomData->dwCustomAuthKey;
  3070. pNewEAPCustomData->dwSize = cbEapAuthData;
  3071. CopyMemory(pNewEAPCustomData->abdata, pbEapAuthData, cbEapAuthData);
  3072. pszOutput = szOutput;
  3073. //
  3074. // Change the buffer to hex and write it out to the file
  3075. //
  3076. while (pCurrentByte < ((LPBYTE)pNewEAPCustomData + dwSize))
  3077. {
  3078. *pszOutput++ = HexChar( (BYTE )(*pCurrentByte / 16) );
  3079. *pszOutput++ = HexChar( (BYTE )(*pCurrentByte % 16) );
  3080. pCurrentByte++;
  3081. iCount = iCount + 2; // keep track of number of chars in ansi output buffer
  3082. if ((MAX_BLOB_CHARS_PER_LINE == iCount) || (pCurrentByte == ((LPBYTE)pNewEAPCustomData + dwSize)))
  3083. {
  3084. *pszOutput = '\0';
  3085. wsprintfA(szAnsiKeyName, "%s%d", c_pszCmEntryDunServerCustomAuthData, iLineNum);
  3086. MYVERIFY(0 != WritePrivateProfileStringA(pszAnsiSection, szAnsiKeyName, szOutput, pszAnsiCmsFile));
  3087. pszOutput = szOutput;
  3088. iCount = 0;
  3089. iLineNum++;
  3090. }
  3091. }
  3092. dwRetVal = ERROR_SUCCESS;
  3093. }
  3094. else
  3095. {
  3096. dwRetVal = ERROR_NOT_ENOUGH_MEMORY;
  3097. }
  3098. CmFree(pNewEAPCustomData);
  3099. CmFree(pszAnsiCmsFile);
  3100. CmFree(pszAnsiSection);
  3101. return dwRetVal;
  3102. }
  3103. /*
  3104. //+----------------------------------------------------------------------------
  3105. //
  3106. // Function: EraseDunSettingsEapData
  3107. //
  3108. // Synopsis: This function erases the CustomAuthData key of the EAP settings
  3109. // for the given section and CMS file
  3110. //
  3111. // Arguments: LPCTSTR pszSection - section name to erase the CustomAuthData from
  3112. // LPCTSTR pszCmsFile - cms file to erase the data from
  3113. //
  3114. // Returns: HRESULT - standard COM style error codes
  3115. //
  3116. // History: quintinb Created 03/27/00
  3117. // tomkel Copied from profwiz 08/09/2001
  3118. //
  3119. //+----------------------------------------------------------------------------
  3120. HRESULT EraseDunSettingsEapData(LPCTSTR pszSection, LPCTSTR pszCmsFile)
  3121. {
  3122. if ((NULL == pszSection) || (NULL == pszCmsFile) ||
  3123. (TEXT('\0') == pszSection[0]) || (TEXT('\0') == pszCmsFile[0]))
  3124. {
  3125. return E_INVALIDARG;
  3126. }
  3127. HRESULT hr = S_OK;
  3128. int iLineNum = 0;
  3129. DWORD dwRet = -1;
  3130. TCHAR szKeyName[MAX_PATH+1];
  3131. TCHAR szLine[MAX_PATH+1];
  3132. while(0 != dwRet)
  3133. {
  3134. wsprintfU(szKeyName, TEXT("%S%d"), c_pszCmEntryDunServerCustomAuthData, iLineNum);
  3135. dwRet = GetPrivateProfileStringU(pszSection, szKeyName, TEXT(""), szLine, MAX_PATH, pszCmsFile);
  3136. if (dwRet)
  3137. {
  3138. if (0 == WritePrivateProfileStringU(pszSection, szKeyName, NULL, pszCmsFile))
  3139. {
  3140. DWORD dwGLE = GetLastError();
  3141. hr = HRESULT_FROM_WIN32(dwGLE);
  3142. break;
  3143. }
  3144. }
  3145. iLineNum++;
  3146. }
  3147. return hr;
  3148. }
  3149. */
  3150. //+----------------------------------------------------------------------------
  3151. //
  3152. // Function: SetTcpWindowSizeOnWin2k
  3153. //
  3154. // Synopsis: This function is basically a wrapper to load the RasSetEntryTcpWindowSize
  3155. // API (which was QFE-ed and shipped in SP3 for Win2k) and call it.
  3156. // It should fail gracefully if the API is not present.
  3157. //
  3158. // Arguments: HMODULE hInstRas - module handle for Rasapi32.dll
  3159. // LPCTSTR pszConnectoid - name of the connectoid to set the window size for
  3160. // LPCTSTR pszPhonebook - phonebook that the connectoid lives in
  3161. // DWORD dwTcpWindowSize - size to set, note that calling with 0
  3162. // sets it to the system default
  3163. //
  3164. // Returns: DWORD - win32 error code or ERROR_SUCCESS if successful
  3165. //
  3166. // History: quintinb Created 02/14/2001
  3167. //
  3168. //+----------------------------------------------------------------------------
  3169. DWORD SetTcpWindowSizeOnWin2k(HMODULE hInstRas, LPCTSTR pszConnectoid, LPCTSTR pszPhonebook, DWORD dwTcpWindowSize)
  3170. {
  3171. //
  3172. // Check inputs, note that pszPhonebook could be NULL
  3173. //
  3174. if ((NULL == hInstRas) || (NULL == pszConnectoid) || (TEXT('\0') == pszConnectoid[0]))
  3175. {
  3176. CMASSERTMSG(FALSE, TEXT("SetTcpWindowSizeOnWin2k -- Invalid arguments passed."));
  3177. return ERROR_BAD_ARGUMENTS;
  3178. }
  3179. //
  3180. // Check to make sure we are only calling this on Win2k
  3181. //
  3182. if ((FALSE == OS_NT5) || OS_NT51)
  3183. {
  3184. CMASSERTMSG(FALSE, TEXT("SetTcpWindowSizeOnWin2k -- This function should only be called on Win2k."));
  3185. return -1;
  3186. }
  3187. //
  3188. // See if we can load the new RAS function to set the Window size
  3189. //
  3190. LPCSTR c_pszDwSetEntryPropertiesPrivate = "DwSetEntryPropertiesPrivate";
  3191. typedef DWORD (WINAPI *pfnDwSetEntryPropertiesPrivateSpec)(IN LPCWSTR, IN LPCWSTR, IN DWORD, IN PVOID);
  3192. DWORD dwReturn;
  3193. pfnDwSetEntryPropertiesPrivateSpec pfnDwSetEntryPropertiesPrivate = (pfnDwSetEntryPropertiesPrivateSpec)GetProcAddress(hInstRas, c_pszDwSetEntryPropertiesPrivate);
  3194. if (pfnDwSetEntryPropertiesPrivate)
  3195. {
  3196. RASENTRY_EX_0 PrivateRasEntryExtension;
  3197. PrivateRasEntryExtension.dwTcpWindowSize = dwTcpWindowSize;
  3198. dwReturn = (pfnDwSetEntryPropertiesPrivate)(pszPhonebook, pszConnectoid, 0, &PrivateRasEntryExtension); // 0 = struct version num
  3199. if (ERROR_SUCCESS != dwReturn)
  3200. {
  3201. CMTRACE1(TEXT("SetTcpWindowSizeOnWin2k -- DwSetEntryPropertiesPrivate returned %d"), dwReturn);
  3202. CMASSERTMSG(FALSE, TEXT("SetTcpWindowSizeOnWin2k -- DwSetEntryPropertiesPrivate returned something other than success, check the trace file for the error code."));
  3203. }
  3204. }
  3205. else
  3206. {
  3207. dwReturn = GetLastError();
  3208. }
  3209. return dwReturn;
  3210. }
  3211. //+----------------------------------------------------------------------------
  3212. //
  3213. // Function: DoRasDial
  3214. //
  3215. // Synopsis: Call RasDial to dial the PPP connection
  3216. //
  3217. // Arguments: HWND hwndDlg - Main signon window
  3218. // ArgsStruct *pArgs -
  3219. // DWORD dwEntry - The index in pArgs->aDialInfo
  3220. //
  3221. // Returns: DWORD -
  3222. // ERROR_SUCCESS if success
  3223. // ERROR_NOT_ENOUGH_MEMORY
  3224. // E_UNEXPECTED, unexpected error, such as tunnel address not found
  3225. // Otherwise, RAS error
  3226. //
  3227. // History: fengsun Created Header 3/6/98
  3228. //
  3229. //+----------------------------------------------------------------------------
  3230. DWORD DoRasDial(HWND hwndDlg,
  3231. ArgsStruct *pArgs,
  3232. DWORD dwEntry)
  3233. {
  3234. LPRASENTRY preRasEntry = NULL;
  3235. LPRASSUBENTRY rgRasSubEntry = NULL;
  3236. LPRASEAPUSERIDENTITY lpRasEapUserIdentity = NULL;
  3237. DWORD dwSubEntryCount;
  3238. LPTSTR pszUsername;
  3239. LPTSTR pszPassword;
  3240. LPTSTR pszDomain = NULL;
  3241. LPTSTR pszRasPbk;
  3242. LPTSTR pszTmp;
  3243. CSecurePassword* pSecPass = NULL;
  3244. LPTSTR pszClearPassword = NULL;
  3245. DWORD cbClearPassword = 0;
  3246. BOOL fRetPassword = FALSE;
  3247. CIni *piniService = NULL;
  3248. DWORD dwRes = ERROR_SUCCESS; // the return value of this function
  3249. DWORD dwTmp;
  3250. LPBYTE pbEapAuthData = NULL; // Ptr to Eap Data
  3251. DWORD dwEapAuthDataSize = 0; // The size of the EAP blob if any
  3252. MYDBGASSERT(pArgs->hrcRasConn == NULL);
  3253. MYDBGASSERT(!pArgs->IsDirectConnect());
  3254. pArgs->hrcRasConn = NULL;
  3255. if (!pArgs->aDialInfo[dwEntry].szDialablePhoneNumber[0])
  3256. {
  3257. CMASSERTMSG(FALSE, TEXT("DoRasDial() szDialablePhoneNumber[0] is empty."));
  3258. return ERROR_BAD_PHONE_NUMBER;
  3259. }
  3260. //
  3261. // set pArgs->fUseTunneling accordingly every time DoRasDial() is called
  3262. // since we can switch from phonenumber0 to phonenumber1 and vice versa.
  3263. //
  3264. pArgs->fUseTunneling = UseTunneling(pArgs, dwEntry);
  3265. //
  3266. // we need to work with the correct service file(the top-level service
  3267. // or a referenced service).
  3268. //
  3269. //
  3270. if (!(piniService = GetAppropriateIniService(pArgs, dwEntry)))
  3271. {
  3272. return ERROR_NOT_ENOUGH_MEMORY;
  3273. }
  3274. //
  3275. // If it's NT and we're tunneling, we create the connectoid in a hidden ras pbk, not the
  3276. // rasphone.pbk in the system.
  3277. //
  3278. if (OS_NT && pArgs->fUseTunneling)
  3279. {
  3280. if (!pArgs->pszRasHiddenPbk)
  3281. {
  3282. pArgs->pszRasHiddenPbk = CreateRasPrivatePbk(pArgs);
  3283. }
  3284. pszRasPbk = pArgs->pszRasHiddenPbk;
  3285. }
  3286. else
  3287. {
  3288. pszRasPbk = pArgs->pszRasPbk;
  3289. }
  3290. //
  3291. // Setup dial params
  3292. //
  3293. if (!pArgs->pRasDialParams)
  3294. {
  3295. pArgs->pRasDialParams = AllocateAndInitRasDialParams();
  3296. if (!pArgs->pRasDialParams)
  3297. {
  3298. CMTRACE(TEXT("DoRasDial: failed to alloc a ras dial params"));
  3299. return ERROR_NOT_ENOUGH_MEMORY;
  3300. }
  3301. }
  3302. else
  3303. {
  3304. InitRasDialParams(pArgs->pRasDialParams);
  3305. }
  3306. //
  3307. // Get the connectoid name.
  3308. //
  3309. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  3310. if (!pszConnectoid)
  3311. {
  3312. return ERROR_NOT_ENOUGH_MEMORY;
  3313. }
  3314. lstrcpynU(pArgs->pRasDialParams->szEntryName, pszConnectoid, sizeof(pArgs->pRasDialParams->szEntryName)/sizeof(TCHAR));
  3315. CmFree(pszConnectoid);
  3316. //
  3317. // Generate the default connectoid
  3318. //
  3319. preRasEntry = CreateRASEntryStruct(pArgs,
  3320. pArgs->aDialInfo[dwEntry].szDUN,
  3321. piniService,
  3322. FALSE,
  3323. pszRasPbk,
  3324. &pbEapAuthData,
  3325. &dwEapAuthDataSize);
  3326. if (!preRasEntry)
  3327. {
  3328. dwRes = GetLastError();
  3329. goto exit;
  3330. }
  3331. //
  3332. // Force update of the phone number to make sure that we pick up any manual
  3333. // changes in country, etc.
  3334. //
  3335. CopyPhone(pArgs, preRasEntry, dwEntry);
  3336. //
  3337. // Handle NT specifics for Idle Disconnect and IDSN
  3338. //
  3339. if (OS_NT || OS_MIL)
  3340. {
  3341. //
  3342. // set NT idle disconnect
  3343. //
  3344. if (OS_NT)
  3345. {
  3346. SetNtIdleDisconnectInRasEntry(pArgs, preRasEntry);
  3347. }
  3348. else
  3349. {
  3350. MYVERIFY(DisableSystemIdleDisconnect(preRasEntry));
  3351. }
  3352. //
  3353. // if we're using isdn and we want to dial all channels/on demand,
  3354. // set isdn dial mode
  3355. //
  3356. if (pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL &&
  3357. !lstrcmpiU(pArgs->szDeviceType, RASDT_Isdn))
  3358. {
  3359. MYVERIFY(SetIsdnDualChannelEntries(pArgs,
  3360. preRasEntry,
  3361. &rgRasSubEntry,
  3362. &dwSubEntryCount));
  3363. }
  3364. else
  3365. {
  3366. //
  3367. // Delete any additional sub entries since we only need one
  3368. //
  3369. if (pArgs->rlsRasLink.pfnDeleteSubEntry) // available on NT5 & Millennium currently
  3370. {
  3371. DWORD dwSubEntryIndex = (OS_MIL ? 1 : 2); // NT & Millennium dual-channel differences
  3372. DWORD dwReturn = pArgs->rlsRasLink.pfnDeleteSubEntry(pszRasPbk,
  3373. pArgs->pRasDialParams->szEntryName,
  3374. dwSubEntryIndex);
  3375. CMTRACE1(TEXT("DoRasDial -- Called RasDeleteSubEntry to delete a second sub entry if it exists, dwReturn=%d"), dwReturn);
  3376. }
  3377. }
  3378. }
  3379. else if (OS_W95)
  3380. {
  3381. //
  3382. // fix another Win95 RAS bug -- byao, 8/16/97
  3383. // The Before and After terminal window options will be switched each
  3384. // time you call RasSetEntryProperties
  3385. // This is fixed in Memphis, so it's only in Win95 Golden and OSR2
  3386. //
  3387. BOOL fTerminalAfterDial, fTerminalBeforeDial;
  3388. fTerminalBeforeDial = (BOOL) (preRasEntry->dwfOptions & RASEO_TerminalBeforeDial);
  3389. fTerminalAfterDial = (BOOL) (preRasEntry->dwfOptions & RASEO_TerminalAfterDial);
  3390. //
  3391. // switch them
  3392. //
  3393. if (fTerminalBeforeDial)
  3394. {
  3395. preRasEntry->dwfOptions |= RASEO_TerminalAfterDial;
  3396. }
  3397. else
  3398. {
  3399. preRasEntry->dwfOptions &= ~RASEO_TerminalAfterDial;
  3400. }
  3401. if (fTerminalAfterDial)
  3402. {
  3403. preRasEntry->dwfOptions |= RASEO_TerminalBeforeDial;
  3404. }
  3405. else
  3406. {
  3407. preRasEntry->dwfOptions &= ~RASEO_TerminalBeforeDial;
  3408. }
  3409. }
  3410. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  3411. {
  3412. #ifdef DEBUG
  3413. LPRASENTRY_V500 lpRasEntry50;
  3414. if (OS_NT5)
  3415. {
  3416. lpRasEntry50 = (LPRASENTRY_V500) preRasEntry;
  3417. }
  3418. #endif
  3419. //
  3420. // use 1 on Millennium to signify that we want to use the modem cpl settings
  3421. // for the modem speaker such instead of the cached copy that DUN keeps.
  3422. // Note we only do this for a dialup connection and not a tunnel since there
  3423. // is no modem speaker to worry about. See Millennium bug 127371.
  3424. //
  3425. LPBYTE lpDeviceInfo = OS_MIL ? (LPBYTE)1 : NULL;
  3426. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryProperties(pszRasPbk,
  3427. pArgs->pRasDialParams->szEntryName,
  3428. preRasEntry,
  3429. preRasEntry->dwSize,
  3430. lpDeviceInfo,
  3431. 0);
  3432. CMTRACE2(TEXT("DoRasDial() RasSetEntryProperties(*pszPhoneBook=%s) returns %u."),
  3433. MYDBGSTR(pArgs->pRasDialParams->szEntryName), dwResDbg);
  3434. CMASSERTMSG(dwResDbg == ERROR_SUCCESS, TEXT("RasSetEntryProperties failed"));
  3435. //
  3436. // set the subentries for isdn dual channel/dial on demand
  3437. //
  3438. if (pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL &&
  3439. rgRasSubEntry &&
  3440. pArgs->rlsRasLink.pfnSetSubEntryProperties)
  3441. {
  3442. UINT i;
  3443. for (i=0; i< dwSubEntryCount; i++)
  3444. {
  3445. #ifdef DEBUG
  3446. dwResDbg =
  3447. #endif
  3448. pArgs->rlsRasLink.pfnSetSubEntryProperties(pszRasPbk,
  3449. pArgs->pRasDialParams->szEntryName,
  3450. i+1,
  3451. &rgRasSubEntry[i],
  3452. rgRasSubEntry[i].dwSize,
  3453. NULL,
  3454. 0);
  3455. CMTRACE2(TEXT("DoRasDial: RasSetSubEntryProps(index=%u) returned %u"), i+1, dwResDbg);
  3456. CMASSERTMSG(!dwResDbg, TEXT("RasSetSubEntryProperties failed"));
  3457. }
  3458. CmFree(rgRasSubEntry);
  3459. }
  3460. }
  3461. //
  3462. // Set the TCP Window size -- the NTT DoCoMo fix for Win2k. The Win2k version of this fix
  3463. // must be written through a private RAS API that must be called after the phonebook entry
  3464. // exists ie. after we call RasSetEntryProperties ... otherwise it won't work on the first
  3465. // dial.
  3466. //
  3467. if (OS_NT5 && !OS_NT51)
  3468. {
  3469. //
  3470. // Figure out the DUN setting name to use and then build up TCP/IP&DunName.
  3471. //
  3472. LPTSTR pszDunSetting = GetDunSettingName(pArgs, dwEntry, FALSE);
  3473. LPTSTR pszSection = CmStrCpyAlloc(c_pszCmSectionDunTcpIp);
  3474. pszSection = CmStrCatAlloc(&pszSection, TEXT("&"));
  3475. if (pszDunSetting && pszSection)
  3476. {
  3477. pszSection = CmStrCatAlloc(&pszSection, pszDunSetting);
  3478. if (pszSection)
  3479. {
  3480. DWORD dwTcpWindowSize = piniService->GPPI(pszSection, c_pszCmEntryDunTcpIpTcpWindowSize, 0);
  3481. (void)SetTcpWindowSizeOnWin2k(pArgs->rlsRasLink.hInstRas, pArgs->szServiceName, pszRasPbk, dwTcpWindowSize);
  3482. }
  3483. else
  3484. {
  3485. CMASSERTMSG(FALSE, TEXT("DoRasDial -- unable to allocate section name for setting TcpWindowSize"));
  3486. }
  3487. }
  3488. else
  3489. {
  3490. CMASSERTMSG(FALSE, TEXT("DoRasDial -- unable to allocate section name or dun setting name for setting TcpWindowSize"));
  3491. }
  3492. CmFree (pszDunSetting);
  3493. CmFree (pszSection);
  3494. }
  3495. //
  3496. // On NT5, check for EAP configuration and update the connectoid accordingly.
  3497. //
  3498. if (OS_NT5)
  3499. {
  3500. //
  3501. // pbEapAuthData can be NULL and dwEapAuthDataSize can be 0. The API handles this.
  3502. // By passing in NULL and 0, we make sure that the CustomAuthData in rasphone.pbk
  3503. // gets cleared.
  3504. //
  3505. if (pArgs->rlsRasLink.pfnSetCustomAuthData)
  3506. {
  3507. dwTmp = pArgs->rlsRasLink.pfnSetCustomAuthData(pszRasPbk,
  3508. pArgs->pRasDialParams->szEntryName,
  3509. pbEapAuthData,
  3510. dwEapAuthDataSize);
  3511. CMTRACE1(TEXT("DoRasDial() - SetCustomAuthData returns %u"), dwTmp);
  3512. if (ERROR_SUCCESS != dwTmp)
  3513. {
  3514. dwRes = dwTmp;
  3515. goto exit;
  3516. }
  3517. }
  3518. }
  3519. //
  3520. // Prepare Phone Number
  3521. //
  3522. lstrcpynU(pArgs->pRasDialParams->szPhoneNumber,
  3523. pArgs->aDialInfo[dwEntry].szDialablePhoneNumber,
  3524. sizeof(pArgs->pRasDialParams->szPhoneNumber)/sizeof(TCHAR));
  3525. //
  3526. // Prepare user info
  3527. //
  3528. // #165775 - RADIUS/CHAP authentication requires that we omit the
  3529. // user specified domain from the dial params and pre-pend it to
  3530. // the user name instead when doing same-name logon. - nickball
  3531. //
  3532. if (!pArgs->fUseTunneling || pArgs->fUseSameUserName)
  3533. {
  3534. pszUsername = pArgs->szUserName;
  3535. pszDomain = pArgs->szDomain;
  3536. pSecPass = &(pArgs->SecurePW);
  3537. }
  3538. else
  3539. {
  3540. //
  3541. // if there's no username or password, we need to ask the user for it.
  3542. //
  3543. BOOL fIsInetPWEmpty = FALSE;
  3544. fIsInetPWEmpty = pArgs->SecureInetPW.IsEmptyString();
  3545. if (!*pArgs->szInetUserName &&
  3546. !pArgs->fHideInetUsername &&
  3547. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUserNameOptional) ||
  3548. fIsInetPWEmpty &&
  3549. !pArgs->fHideInetPassword &&
  3550. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional))
  3551. {
  3552. //
  3553. // We need to collect data from user, determine the dlg template ID
  3554. //
  3555. UINT uiTemplateID = IDD_INTERNET_SIGNIN;
  3556. if (pArgs->fHideInetUsername)
  3557. {
  3558. uiTemplateID = IDD_INTERNET_SIGNIN_NO_UID;
  3559. }
  3560. else if (pArgs->fHideInetPassword)
  3561. {
  3562. uiTemplateID = IDD_INTERNET_SIGNIN_NO_PWD;
  3563. }
  3564. //
  3565. // Now load the dialog
  3566. //
  3567. CInetSignInDlg SignInDlg(pArgs);
  3568. if (IDCANCEL == SignInDlg.DoDialogBox(g_hInst, uiTemplateID, hwndDlg))
  3569. {
  3570. dwRes = ERROR_CANCELLED;
  3571. goto exit;
  3572. }
  3573. }
  3574. pszUsername = pArgs->szInetUserName;
  3575. pSecPass = &(pArgs->SecureInetPW);
  3576. }
  3577. //
  3578. // Apply suffix, prefix, to username as necessary
  3579. //
  3580. pszTmp = ApplyPrefixSuffixToBufferAlloc(pArgs, piniService, pszUsername);
  3581. MYDBGASSERT(pszTmp);
  3582. if (pszTmp)
  3583. {
  3584. //
  3585. // Apply domain to username as necessary. Note: Reassigns pszUsername
  3586. //
  3587. pszUsername = ApplyDomainPrependToBufferAlloc(pArgs, piniService, pszTmp, (pArgs->aDialInfo[dwEntry].szDUN));
  3588. MYDBGASSERT(pszUsername);
  3589. if (pszUsername)
  3590. {
  3591. lstrcpynU(pArgs->pRasDialParams->szUserName, pszUsername, sizeof(pArgs->pRasDialParams->szUserName)/sizeof(TCHAR));
  3592. }
  3593. CmFree(pszUsername);
  3594. CmFree(pszTmp);
  3595. }
  3596. pszUsername = NULL;
  3597. pszTmp = NULL;
  3598. //
  3599. // Update RasDialPArams with domain info if we have any
  3600. //
  3601. if (pszDomain)
  3602. {
  3603. lstrcpyU(pArgs->pRasDialParams->szDomain, pszDomain);
  3604. }
  3605. //
  3606. // Prepare the password
  3607. //
  3608. if (pSecPass)
  3609. {
  3610. fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  3611. if (fRetPassword && pszClearPassword)
  3612. {
  3613. //
  3614. // Convert password: all upper case, all lower case, or no conversion
  3615. //
  3616. ApplyPasswordHandlingToBuffer(pArgs, pszClearPassword);
  3617. (VOID)pSecPass->SetPassword(pszClearPassword);
  3618. //
  3619. // Clear and Free the clear-text password
  3620. //
  3621. pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword);
  3622. cbClearPassword = 0;
  3623. }
  3624. }
  3625. else
  3626. {
  3627. dwRes = ERROR_INVALID_DATA;
  3628. goto exit;
  3629. }
  3630. if (pArgs->rlsRasLink.pfnDial)
  3631. {
  3632. LPTSTR pszDunSetting = GetDunSettingName(pArgs, dwEntry, FALSE);
  3633. LPTSTR pszPhoneBook = GetCMSforPhoneBook(pArgs, dwEntry);
  3634. pArgs->Log.Log(PREDIAL_EVENT,
  3635. pArgs->pRasDialParams->szUserName,
  3636. pArgs->pRasDialParams->szDomain,
  3637. SAFE_LOG_ARG(pszPhoneBook),
  3638. SAFE_LOG_ARG(pszDunSetting),
  3639. pArgs->szDeviceName,
  3640. pArgs->aDialInfo[dwEntry].szDialablePhoneNumber);
  3641. CmFree(pszDunSetting);
  3642. CmFree(pszPhoneBook);
  3643. //
  3644. // Run pre-dial connect action before calling RasDial
  3645. //
  3646. CActionList PreDialActList;
  3647. PreDialActList.Append(pArgs->piniService, c_pszCmSectionPreDial);
  3648. if (!PreDialActList.RunAccordType(hwndDlg, pArgs))
  3649. {
  3650. //
  3651. // Some pre-tunnel connect action failed
  3652. //
  3653. dwRes = ERROR_INVALID_DLL; // Only used for failed CA
  3654. }
  3655. else
  3656. {
  3657. //
  3658. // Set state and tick counters.
  3659. //
  3660. pArgs->psState = PS_Dialing;
  3661. pArgs->dwStateStartTime = GetTickCount();
  3662. pArgs->nLastSecondsDisplay = (UINT) -1;
  3663. //
  3664. // Record the initial Dial-Up Adapter Statistic info
  3665. // open the registry key for the perfmon data
  3666. //
  3667. if (pArgs->pConnStatistics)
  3668. {
  3669. pArgs->pConnStatistics->InitStatistics();
  3670. }
  3671. if (OS_NT)
  3672. {
  3673. BOOL fUsePausedStates = TRUE;
  3674. BOOL fUseCustomScripting = !!(preRasEntry->dwfOptions & RASEO_CustomScript); // OS_NT51 (whistler+) only
  3675. if (OS_NT4)
  3676. {
  3677. //
  3678. // If a script is specified, then explcitly don't handle
  3679. // pause states. This is because we can't handle the script
  3680. // pause state. On W2K, RAS is smart enough not to send us
  3681. // the scripting pause state because we have the terminal
  3682. // option turned off.
  3683. //
  3684. if (preRasEntry->szScript[0] != TEXT('\0'))
  3685. {
  3686. fUsePausedStates = FALSE;
  3687. }
  3688. }
  3689. dwRes = SetRasDialExtensions(pArgs, fUsePausedStates, fUseCustomScripting);
  3690. if (dwRes != ERROR_SUCCESS)
  3691. {
  3692. goto exit;
  3693. }
  3694. //
  3695. // On NT5, we may be getting credentials via EAP
  3696. //
  3697. if (OS_NT5 && ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey)
  3698. {
  3699. //
  3700. // We're using EAP, get credentials from EAP through RAS
  3701. //
  3702. dwRes = GetEapUserId(pArgs,
  3703. hwndDlg,
  3704. pszRasPbk,
  3705. pbEapAuthData,
  3706. dwEapAuthDataSize,
  3707. ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey,
  3708. &lpRasEapUserIdentity);
  3709. if (ERROR_SUCCESS != dwRes)
  3710. {
  3711. goto exit;
  3712. }
  3713. }
  3714. }
  3715. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szUserName is %s"), pArgs->pRasDialParams->szUserName);
  3716. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szDomain is %s"), pArgs->pRasDialParams->szDomain);
  3717. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szPhoneNumber is %s"), pArgs->pRasDialParams->szPhoneNumber);
  3718. //
  3719. // Decode the password, and fill dial params, then re-encode both the pArgs
  3720. // version of the password and the dial params copy.
  3721. //
  3722. fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  3723. if (fRetPassword && pszClearPassword)
  3724. {
  3725. lstrcpynU(pArgs->pRasDialParams->szPassword, pszClearPassword, sizeof(pArgs->pRasDialParams->szPassword)/sizeof(TCHAR));
  3726. //
  3727. // Clear and Free the clear-text password
  3728. //
  3729. pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword);
  3730. cbClearPassword = 0;
  3731. }
  3732. //
  3733. // Write the RasDialParams if necessary.
  3734. // We must keep this, even though RasSetEntryDialParams() is expensive. Inverse uses the
  3735. // information stored in the DialParams structure. However, since this can cause problems
  3736. // with EAP (overwriting the saved PIN for instance) we will make the storing of the
  3737. // credential information configurable by a CMS flag. Specifically, the WriteRasDialParams
  3738. // flag in the [Connection Manager] section. If the flag is 1, then we will write the
  3739. // RasDialParams and otherwise we won't. Note that the flag defaults to 0.
  3740. // Please see bug 399976 for reference.
  3741. //
  3742. if (piniService->GPPI(c_pszCmSection, c_pszCmEntryWriteDialParams))
  3743. {
  3744. //
  3745. // Note that since we throw the connectoid away if we are on NT and
  3746. // doing a double dial, there is no point in making an expensive set
  3747. // dial params call on it.
  3748. //
  3749. if ((!pArgs->fUseTunneling && pArgs->fRememberMainPassword) ||
  3750. (pArgs->fUseTunneling && pArgs->fRememberInetPassword && OS_W9X))
  3751. {
  3752. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryDialParams(pszRasPbk, pArgs->pRasDialParams, FALSE);
  3753. CMTRACE1(TEXT("DoRasDial() SetEntryDialParams returns %u."), dwResDbg);
  3754. }
  3755. else
  3756. {
  3757. //
  3758. // Forget the password, note that the DialParams contain the password but we set the
  3759. // fRemovePassword flag to TRUE so the password will be removed anyway.
  3760. //
  3761. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryDialParams(pszRasPbk,
  3762. pArgs->pRasDialParams, TRUE);
  3763. CMTRACE1(TEXT("DoRasDial() SetEntryDialParams returns %u."), dwResDbg);
  3764. }
  3765. }
  3766. //
  3767. // Do the dial (PPP)
  3768. //
  3769. if (OS_NT)
  3770. {
  3771. lstrcpyU(pArgs->pRasDialParams->szCallbackNumber, TEXT("*"));
  3772. }
  3773. //
  3774. // check to ensure we're not already in a Cancel operation
  3775. //
  3776. LONG lInConnectOrCancel = InterlockedExchange(&(pArgs->lInConnectOrCancel), IN_CONNECT_OR_CANCEL);
  3777. CMASSERTMSG(((NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel) || (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)),
  3778. TEXT("DoRasDial - synch variable has unexpected value!"));
  3779. if (NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel)
  3780. {
  3781. dwRes = pArgs->rlsRasLink.pfnDial(pArgs->pRasDialExtensions,
  3782. pszRasPbk,
  3783. pArgs->pRasDialParams,
  3784. GetRasCallBackType(),
  3785. GetRasCallBack(pArgs),
  3786. &pArgs->hrcRasConn);
  3787. }
  3788. else
  3789. {
  3790. // this is a rare stress case - deliberately did not set dwRes to error value.
  3791. CMTRACE(TEXT("DoRasDial() did not dial, we are already in a Cancel operation"));
  3792. }
  3793. (void) InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  3794. //
  3795. // No need for us to hold on to this password in this structure since
  3796. // we are done using it.
  3797. //
  3798. CmWipePassword(pArgs->pRasDialParams->szPassword);
  3799. CMTRACE1(TEXT("DoRasDial() RasDial() returns %u."), dwRes);
  3800. if (dwRes != ERROR_SUCCESS)
  3801. {
  3802. pArgs->hrcRasConn = NULL;
  3803. goto exit;
  3804. }
  3805. }
  3806. }
  3807. exit:
  3808. if (lpRasEapUserIdentity)
  3809. {
  3810. MYDBGASSERT(OS_NT5); // NO EAP down-level
  3811. //
  3812. // A RasEapUserIdentity struct was allocated, free it via the
  3813. // appropriate free mechanism. In the WinLogon case we will always
  3814. // perform the allocation, otherwise we have to go through RAS API.
  3815. //
  3816. if (pArgs->lpEapLogonInfo)
  3817. {
  3818. CmFree(lpRasEapUserIdentity);
  3819. }
  3820. else
  3821. {
  3822. if (pArgs->rlsRasLink.pfnFreeEapUserIdentity)
  3823. {
  3824. pArgs->rlsRasLink.pfnFreeEapUserIdentity(lpRasEapUserIdentity);
  3825. }
  3826. }
  3827. }
  3828. CmFree(pbEapAuthData);
  3829. CmFree(preRasEntry);
  3830. delete piniService;
  3831. return dwRes;
  3832. }
  3833. //+---------------------------------------------------------------------------
  3834. //
  3835. // Function: DoTunnelDial
  3836. //
  3837. // Synopsis: call RasDial to dial up to the tunnel server
  3838. //
  3839. // Arguments: hwndDlg [dlg window handle]
  3840. // pargs pointer to ArgValue structure
  3841. //
  3842. // Returns: DWORD -
  3843. // ERROR_SUCCESS if success
  3844. // ERROR_NOT_ENOUGH_MEMORY
  3845. // E_UNEXPECTED, unexpected error, such as phone entry not found
  3846. // Otherwise, RAS error
  3847. //
  3848. // History: byao Created 3/1/97
  3849. // fengsun change return type to DWORD 3/6/98
  3850. //
  3851. //----------------------------------------------------------------------------
  3852. DWORD DoTunnelDial(IN HWND hwndDlg, IN ArgsStruct *pArgs)
  3853. {
  3854. LPRASENTRY preRasEntry = NULL;
  3855. LPRASEAPUSERIDENTITY lpRasEapUserIdentity = NULL;
  3856. LPTSTR pszVpnSetting = NULL;
  3857. LPBYTE pbEapAuthData = NULL; // Ptr to Eap Data
  3858. DWORD dwEapAuthDataSize = 0; // The size of the EAP blob if any
  3859. CSecurePassword* pSecPass = &(pArgs->SecurePW);
  3860. LPTSTR pszClearPassword = NULL;
  3861. DWORD cbClearPassword = 0;
  3862. BOOL fRetPassword = FALSE;
  3863. DWORD dwRes = (DWORD)E_UNEXPECTED;
  3864. DWORD dwTmp;
  3865. MYDBGASSERT(pArgs->hrcTunnelConn == NULL);
  3866. pArgs->hrcTunnelConn = NULL;
  3867. //
  3868. // What's the tunnel end point? Do this now so that the UI can be updated
  3869. // properly if lana wait or pre-tunnel actions are time consuming.
  3870. //
  3871. LPTSTR pszTunnelIP = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  3872. if (pszTunnelIP)
  3873. {
  3874. if (lstrlenU(pszTunnelIP) > RAS_MaxPhoneNumber)
  3875. {
  3876. pszTunnelIP[0] = TEXT('\0');
  3877. }
  3878. pArgs->SetPrimaryTunnel(pszTunnelIP);
  3879. CmFree(pszTunnelIP);
  3880. }
  3881. //
  3882. // See if tunnel server was specified
  3883. //
  3884. if (!(pArgs->GetTunnelAddress()[0]))
  3885. {
  3886. CMASSERTMSG(FALSE, TEXT("DoTunnelDial() TunnelAddress is invalid."));
  3887. return ERROR_BAD_ADDRESS_SPECIFIED;
  3888. }
  3889. CMTRACE1(TEXT("DoTunnelDial() - TunnelAddress is %s"), pArgs->GetTunnelAddress());
  3890. //
  3891. // Caution should be used when changing this if statement. We want this to happen both for direct connect
  3892. // and for double dial connections. You can still get into the LANA situation with two CM
  3893. // connections dialed independently (one to the internet and the other a tunnel), doing the lana
  3894. // wait for direct connections prevents the lana registration problem from occuring in this situation.
  3895. // Note that the Lana wait isn't necessary on Win98 SE or Win98 Millennium because the DUN bug
  3896. // is fixed. Thus we have reversed the default and will only do the LANA wait if the reg key exists
  3897. // and specifies that the wait should be performed.
  3898. //
  3899. if (OS_W9X)
  3900. {
  3901. //
  3902. // Sets us up to wait for Vredir to register LANA for connection to internet
  3903. // Note: Returns FALSE if the user hits cancel while we are waiting. In this
  3904. // event, we should not continue the tunnel dial.
  3905. //
  3906. if (FALSE == LanaWait(pArgs, hwndDlg))
  3907. {
  3908. return ERROR_SUCCESS;
  3909. }
  3910. }
  3911. LPTSTR pszDunSetting = GetDunSettingName(pArgs, -1, TRUE);
  3912. pArgs->Log.Log(PRETUNNEL_EVENT,
  3913. pArgs->szUserName,
  3914. pArgs->szDomain,
  3915. SAFE_LOG_ARG(pszDunSetting),
  3916. pArgs->szTunnelDeviceName,
  3917. pArgs->GetTunnelAddress());
  3918. CmFree(pszDunSetting);
  3919. CActionList PreTunnelActList;
  3920. if (PreTunnelActList.Append(pArgs->piniService, c_pszCmSectionPreTunnel))
  3921. {
  3922. CMTRACE(TEXT("DoTunnelDial() - Running Pre-Tunnel actions"));
  3923. if (!PreTunnelActList.RunAccordType(hwndDlg, pArgs))
  3924. {
  3925. //
  3926. // Some pre-tunnel connect action failed
  3927. //
  3928. dwRes = ERROR_INVALID_DLL; // Only used for failed CA
  3929. goto exit;
  3930. }
  3931. //
  3932. // Now that pre-tunnel actions have run, what's the tunnel end point?
  3933. // We perform this read again here in the event that the pre-tunnel
  3934. // action modified the tunnel address. Note: This is an exception to
  3935. // the rule that the .CMS should not be modified on the client side,
  3936. // especially by 3rd parties.
  3937. //
  3938. // REVIEW: It probably isn't necessary to re-read this with the new VPN tab. However, some people might still
  3939. // be using the connect action solution that ITG gave out and we want to be careful not to break them if
  3940. // we haven't already. Thus we will continue to re-read this for Whistler but we should remove it afterwards.
  3941. // quintinb 11-01-00
  3942. pszTunnelIP = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  3943. if (pszTunnelIP)
  3944. {
  3945. if (lstrlenU(pszTunnelIP) > RAS_MaxPhoneNumber)
  3946. {
  3947. pszTunnelIP[0] = TEXT('\0');
  3948. }
  3949. pArgs->SetPrimaryTunnel(pszTunnelIP);
  3950. CmFree(pszTunnelIP);
  3951. }
  3952. //
  3953. // See if tunnel server was specified
  3954. //
  3955. if (!(pArgs->GetTunnelAddress()[0]))
  3956. {
  3957. CMASSERTMSG(FALSE, TEXT("DoTunnelDial() TunnelAddress is invalid."));
  3958. dwRes = (DWORD)ERROR_BAD_ADDRESS_SPECIFIED;
  3959. goto exit;
  3960. }
  3961. CMTRACE1(TEXT("DoTunnelDial() - TunnelAddress is %s"), pArgs->GetTunnelAddress());
  3962. }
  3963. //
  3964. // Setup dial params
  3965. //
  3966. if (!pArgs->pRasDialParams)
  3967. {
  3968. pArgs->pRasDialParams = AllocateAndInitRasDialParams();
  3969. if (!pArgs->pRasDialParams)
  3970. {
  3971. CMTRACE(TEXT("DoTunnelDial: failed to alloc a ras dial params"));
  3972. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  3973. goto exit;
  3974. }
  3975. }
  3976. else
  3977. {
  3978. InitRasDialParams(pArgs->pRasDialParams);
  3979. }
  3980. //
  3981. // Get the connectoid name
  3982. //
  3983. LPTSTR pszConnectoid;
  3984. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, TRUE);
  3985. if (!pszConnectoid)
  3986. {
  3987. dwRes = (DWORD)ERROR_NOT_ENOUGH_MEMORY;
  3988. goto exit;
  3989. }
  3990. lstrcpyU(pArgs->pRasDialParams->szEntryName, pszConnectoid);
  3991. CmFree(pszConnectoid);
  3992. //
  3993. // We'll create the RAS connectoid if the RAS connectoid doesn't exist.
  3994. // NOTE: Tunnel settings should always be taken from the top-level CMS.
  3995. // so use it when creating the connectoid.
  3996. //
  3997. pszVpnSetting = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelDun, TEXT(""));
  3998. preRasEntry = CreateRASEntryStruct(pArgs,
  3999. (pszVpnSetting ? pszVpnSetting : TEXT("")),
  4000. pArgs->piniService,
  4001. TRUE,
  4002. pArgs->pszRasPbk,
  4003. &pbEapAuthData,
  4004. &dwEapAuthDataSize);
  4005. CmFree(pszVpnSetting);
  4006. if (!preRasEntry)
  4007. {
  4008. dwRes = GetLastError();
  4009. goto exit;
  4010. }
  4011. //
  4012. // If this is Millennium we need to disable Idle disconnect so that it doesn't
  4013. // fight with ours.
  4014. //
  4015. if (OS_MIL)
  4016. {
  4017. MYVERIFY(DisableSystemIdleDisconnect(preRasEntry));
  4018. }
  4019. //
  4020. // We need to delete a second sub entry if it exists. See 406637 for details
  4021. //
  4022. if (pArgs->rlsRasLink.pfnDeleteSubEntry) // available on NT5 & Millennium currently
  4023. {
  4024. DWORD dwReturn = pArgs->rlsRasLink.pfnDeleteSubEntry(pArgs->pszRasPbk,
  4025. pArgs->pRasDialParams->szEntryName,
  4026. (OS_MIL ? 1 : 2)); // see comment in DoRasDial
  4027. CMTRACE1(TEXT("DoTunnelDial -- Called RasDeleteSubEntry to delete a second sub entry if it exists, dwReturn=%d"), dwReturn);
  4028. }
  4029. //
  4030. // On NT5, we have to set the connection type to VPN instead of Internet
  4031. //
  4032. if (OS_NT5)
  4033. {
  4034. MYDBGASSERT(preRasEntry->dwSize >= sizeof(RASENTRY_V500));
  4035. ((LPRASENTRY_V500)preRasEntry)->dwType = RASET_Vpn;
  4036. ((LPRASENTRY_V500)preRasEntry)->szDeviceName[0] = TEXT('\0'); // let RAS pickup the tunnel device
  4037. }
  4038. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  4039. {
  4040. #ifdef DEBUG
  4041. LPRASENTRY_V500 lpRasEntry50;
  4042. if (OS_NT5)
  4043. {
  4044. lpRasEntry50 = (LPRASENTRY_V500) preRasEntry;
  4045. }
  4046. #endif
  4047. dwRes = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  4048. pArgs->pRasDialParams->szEntryName,
  4049. preRasEntry,
  4050. preRasEntry->dwSize,
  4051. NULL,
  4052. 0);
  4053. CMTRACE2(TEXT("DoTunnelDial() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  4054. MYDBGSTR(pArgs->pRasDialParams->szEntryName), dwRes);
  4055. CMASSERTMSG(dwRes == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  4056. }
  4057. //
  4058. // Set the TCP Window size -- the NTT DoCoMo fix for Win2k. The Win2k version of this fix
  4059. // must be written through a private RAS API that must be called after the phonebook entry
  4060. // exists ie. after we call RasSetEntryProperties ... otherwise it won't work on the first
  4061. // dial.
  4062. //
  4063. if (OS_NT5 && !OS_NT51)
  4064. {
  4065. //
  4066. // Figure out the DUN setting name to use and then build up TCP/IP&DunName.
  4067. //
  4068. pszDunSetting = GetDunSettingName(pArgs, -1, TRUE);
  4069. LPTSTR pszSection = CmStrCpyAlloc(c_pszCmSectionDunTcpIp);
  4070. pszSection = CmStrCatAlloc(&pszSection, TEXT("&"));
  4071. if (pszDunSetting && pszSection)
  4072. {
  4073. pszSection = CmStrCatAlloc(&pszSection, pszDunSetting);
  4074. if (pszSection)
  4075. {
  4076. DWORD dwTcpWindowSize = pArgs->piniService->GPPI(pszSection, c_pszCmEntryDunTcpIpTcpWindowSize, 0);
  4077. (void)SetTcpWindowSizeOnWin2k(pArgs->rlsRasLink.hInstRas, pArgs->szServiceName, pArgs->pszRasPbk, dwTcpWindowSize);
  4078. }
  4079. else
  4080. {
  4081. CMASSERTMSG(FALSE, TEXT("DoTunnelDial -- unable to allocate section name for setting TcpWindowSize"));
  4082. }
  4083. }
  4084. else
  4085. {
  4086. CMASSERTMSG(FALSE, TEXT("DoTunnelDial -- unable to allocate section name or dun setting name for setting TcpWindowSize"));
  4087. }
  4088. CmFree (pszDunSetting);
  4089. CmFree (pszSection);
  4090. }
  4091. //
  4092. // On NT5, check for EAP configuration and update the connectoid accordingly.
  4093. //
  4094. if (OS_NT5)
  4095. {
  4096. //
  4097. // pbEapAuthData can be NULL and dwEapAuthDataSize can be 0. The API handles this.
  4098. // By passing in NULL and 0, we make sure that the CustomAuthData in rasphone.pbk
  4099. // gets cleared.
  4100. //
  4101. if (pArgs->rlsRasLink.pfnSetCustomAuthData)
  4102. {
  4103. dwTmp = pArgs->rlsRasLink.pfnSetCustomAuthData(pArgs->pszRasPbk,
  4104. pArgs->pRasDialParams->szEntryName,
  4105. pbEapAuthData,
  4106. dwEapAuthDataSize);
  4107. if (ERROR_SUCCESS != dwTmp)
  4108. {
  4109. CMTRACE(TEXT("DoTunnelDial() - SetCustomAuthData failed"));
  4110. dwRes = dwTmp;
  4111. goto exit;
  4112. }
  4113. }
  4114. }
  4115. //
  4116. // Phone Number for PPTP is the DNS name of IP addr of PPTP server
  4117. //
  4118. lstrcpynU(pArgs->pRasDialParams->szPhoneNumber,pArgs->GetTunnelAddress(), sizeof(pArgs->pRasDialParams->szPhoneNumber));
  4119. //
  4120. // Prepare User Name and Domain
  4121. //
  4122. lstrcpyU(pArgs->pRasDialParams->szUserName, pArgs->szUserName);
  4123. lstrcpyU(pArgs->pRasDialParams->szDomain, pArgs->szDomain);
  4124. //
  4125. // Prepare the password
  4126. //
  4127. if (pSecPass)
  4128. {
  4129. fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  4130. if (fRetPassword && pszClearPassword)
  4131. {
  4132. //
  4133. // Convert password: all upper case, all lower case, or no conversion
  4134. //
  4135. ApplyPasswordHandlingToBuffer(pArgs, pszClearPassword);
  4136. (VOID)pSecPass->SetPassword(pszClearPassword);
  4137. //
  4138. // Clear and Free the clear-text password
  4139. //
  4140. pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword);
  4141. cbClearPassword = 0;
  4142. }
  4143. }
  4144. else
  4145. {
  4146. CMTRACE(TEXT("DoTunnelDial() - CmSecurePassword object (pSecPass) is NULL!"));
  4147. dwRes = ERROR_INVALID_DATA;
  4148. goto exit;
  4149. }
  4150. if (pArgs->rlsRasLink.pfnDial)
  4151. {
  4152. if (pArgs->IsDirectConnect())
  4153. {
  4154. //
  4155. // Record the initial Dial-Up Adapter Statistic info.
  4156. //
  4157. if (pArgs->pConnStatistics)
  4158. {
  4159. pArgs->pConnStatistics->InitStatistics();
  4160. }
  4161. }
  4162. if (OS_NT)
  4163. {
  4164. MYDBGASSERT(TEXT('\0') == preRasEntry->szScript[0]); // we should never have a script on a tunnel connection
  4165. dwRes = SetRasDialExtensions(pArgs, TRUE, FALSE); // TRUE == fUsePausedStates, FALSE == fEnableCustomScripting
  4166. if (dwRes != ERROR_SUCCESS)
  4167. {
  4168. goto exit;
  4169. }
  4170. //
  4171. // On NT5, we may be getting credentials via EAP
  4172. //
  4173. if (OS_NT5 && ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey)
  4174. {
  4175. //
  4176. // We're using EAP, get credentials from EAP through RAS
  4177. //
  4178. dwRes = GetEapUserId(pArgs,
  4179. hwndDlg,
  4180. pArgs->pszRasPbk,
  4181. pbEapAuthData,
  4182. dwEapAuthDataSize,
  4183. ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey,
  4184. &lpRasEapUserIdentity);
  4185. if (ERROR_SUCCESS != dwRes)
  4186. {
  4187. goto exit;
  4188. }
  4189. }
  4190. }
  4191. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szUserName is %s"), pArgs->pRasDialParams->szUserName);
  4192. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szDomain is %s"), pArgs->pRasDialParams->szDomain);
  4193. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szPhoneNumber is %s"), pArgs->pRasDialParams->szPhoneNumber);
  4194. //
  4195. // Get the password before dialing.
  4196. //
  4197. fRetPassword = pSecPass->GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  4198. if (fRetPassword && pszClearPassword)
  4199. {
  4200. lstrcpyU(pArgs->pRasDialParams->szPassword, pszClearPassword);
  4201. //
  4202. // Clear and Free the clear-text password
  4203. //
  4204. pSecPass->ClearAndFree(&pszClearPassword, cbClearPassword);
  4205. cbClearPassword = 0;
  4206. }
  4207. //
  4208. // Do the dial (PPTP or L2TP)
  4209. //
  4210. dwRes = pArgs->rlsRasLink.pfnDial(pArgs->pRasDialExtensions,
  4211. pArgs->pszRasPbk,
  4212. pArgs->pRasDialParams,
  4213. GetRasCallBackType(),
  4214. GetRasCallBack(pArgs),
  4215. &pArgs->hrcTunnelConn);
  4216. //
  4217. // No need for us to hold on to this password in this structure since
  4218. // we are done using it.
  4219. //
  4220. CmWipePassword(pArgs->pRasDialParams->szPassword);
  4221. CMTRACE1(TEXT("DoTunnelDial() RasDial() returns %u."), dwRes);
  4222. //
  4223. // NT5 - Reset the connection type so that it will display properly in
  4224. // the Connections Folder. This is a temporary solution to #187202
  4225. //
  4226. if (OS_NT5)
  4227. {
  4228. MYDBGASSERT(preRasEntry->dwSize >= sizeof(RASENTRY_V500));
  4229. ((LPRASENTRY_V500)preRasEntry)->dwType = RASET_Internet;
  4230. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  4231. {
  4232. dwTmp = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  4233. pArgs->pRasDialParams->szEntryName,
  4234. preRasEntry,
  4235. preRasEntry->dwSize,
  4236. NULL,
  4237. 0);
  4238. CMTRACE2(TEXT("DoTunnelDial() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  4239. MYDBGSTR(pArgs->pRasDialParams->szEntryName), dwTmp);
  4240. CMASSERTMSG(dwTmp == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  4241. }
  4242. }
  4243. if (dwRes != ERROR_SUCCESS)
  4244. {
  4245. pArgs->hrcTunnelConn = NULL;
  4246. goto exit;
  4247. }
  4248. }
  4249. exit:
  4250. if (lpRasEapUserIdentity)
  4251. {
  4252. MYDBGASSERT(OS_NT5); // NO EAP down-level
  4253. //
  4254. // A RasEapUserIdentity struct was allocated, free it via the
  4255. // appropriate free mechanism. In the WinLogon case we will always
  4256. // perform the allocation, otherwise we have to go through RAS API.
  4257. //
  4258. if (pArgs->lpEapLogonInfo)
  4259. {
  4260. CmFree(lpRasEapUserIdentity);
  4261. }
  4262. else
  4263. {
  4264. if (pArgs->rlsRasLink.pfnFreeEapUserIdentity)
  4265. {
  4266. pArgs->rlsRasLink.pfnFreeEapUserIdentity(lpRasEapUserIdentity);
  4267. }
  4268. }
  4269. }
  4270. CmFree(preRasEntry); // Now we can release the RAS entry structure. #187202
  4271. CmFree(pbEapAuthData);
  4272. return dwRes;
  4273. }
  4274. //+---------------------------------------------------------------------------
  4275. //
  4276. // Function: CheckConnect
  4277. //
  4278. // Synopsis: double check to make sure all required fields are filled in, such
  4279. // as username, password, modem, etc.
  4280. //
  4281. // Arguments: hwndDlg [dlg window handle]
  4282. // pArgs pointer to ArgValue structure
  4283. // pnCtrlFocus The button whose value is missing will have the focus
  4284. // fShowMsg Whether a message should be shown to the user or not. Default value of FALSE.
  4285. //
  4286. // Returns: True is ready to connect
  4287. //
  4288. // History: byao Modified 3/7/97
  4289. // nickball return BOOLEAN 9/9/98
  4290. //
  4291. //----------------------------------------------------------------------------
  4292. BOOL CheckConnect(HWND hwndDlg,
  4293. ArgsStruct *pArgs,
  4294. UINT *pnCtrlFocus,
  4295. BOOL fShowMsg)
  4296. {
  4297. LPTSTR pszTmp;
  4298. BOOL bEnable = TRUE;
  4299. int nId = 0;
  4300. UINT nCtrlFocus;
  4301. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  4302. pArgs->fIgnoreChangeNotification = TRUE;
  4303. MYDBGASSERT(*pArgs->piniProfile->GetFile());
  4304. if (bEnable && IsTunnelEnabled(pArgs))
  4305. {
  4306. //
  4307. // If we already have a device picked, no need to pick a new one...
  4308. //
  4309. if ((pArgs->szTunnelDeviceName[0] == TEXT('\0')) || (pArgs->szTunnelDeviceType[0] == TEXT('\0')))
  4310. {
  4311. lstrcpyU(pArgs->szTunnelDeviceType, RASDT_Vpn);
  4312. //
  4313. // Pick the tunnel device
  4314. //
  4315. if (!PickTunnelDevice(pArgs, pArgs->szTunnelDeviceType, pArgs->szTunnelDeviceName))
  4316. {
  4317. //
  4318. // If we can't pick a tunnel device make sure tunneling is installed
  4319. //
  4320. //
  4321. // Disable the connect/setting button during component checking and installation
  4322. //
  4323. EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
  4324. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_PROPERTIES_BUTTON), FALSE);
  4325. //
  4326. // Install the PPTP and pick tunnel device one more time
  4327. //
  4328. DWORD dwComponentsToCheck = CC_PPTP | CC_RNA | CC_RASRUNNING
  4329. | CC_TCPIP| CC_CHECK_BINDINGS;
  4330. if (TRUE == pArgs->bDoNotCheckBindings)
  4331. {
  4332. dwComponentsToCheck &= ~CC_CHECK_BINDINGS;
  4333. }
  4334. //
  4335. // PPTP is not installed.
  4336. // If not unattended, try to install the PPTP and call PickTunnel again
  4337. //
  4338. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  4339. if (!(pArgs->dwFlags & FL_UNATTENDED))
  4340. {
  4341. pArgs->dwExitCode = CheckAndInstallComponents(dwComponentsToCheck,
  4342. hwndDlg, pArgs->szServiceName);
  4343. }
  4344. if (pArgs->dwExitCode != ERROR_SUCCESS ||
  4345. !PickTunnelDevice(pArgs, pArgs->szTunnelDeviceType, pArgs->szTunnelDeviceName))
  4346. {
  4347. bEnable = FALSE;
  4348. nId = GetPPTPMsgId();
  4349. nCtrlFocus = IDCANCEL;
  4350. }
  4351. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_PROPERTIES_BUTTON), TRUE);
  4352. }
  4353. }
  4354. }
  4355. //
  4356. // Next, check the username.
  4357. //
  4358. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  4359. {
  4360. if (bEnable &&
  4361. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUserNameOptional))
  4362. {
  4363. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_USERNAME_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  4364. {
  4365. bEnable = FALSE;
  4366. nId = IDMSG_NEED_USERNAME;
  4367. nCtrlFocus = IDC_MAIN_USERNAME_EDIT;
  4368. }
  4369. }
  4370. }
  4371. //
  4372. // Next, check the password.
  4373. //
  4374. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  4375. {
  4376. if (!pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional))
  4377. {
  4378. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  4379. {
  4380. if (bEnable)
  4381. {
  4382. bEnable = FALSE;
  4383. nId = IDMSG_NEED_PASSWORD;
  4384. nCtrlFocus = IDC_MAIN_PASSWORD_EDIT;
  4385. }
  4386. //
  4387. // Disable "Remember password" check box
  4388. //
  4389. if (!pArgs->fHideRememberPassword)
  4390. {
  4391. pArgs->fRememberMainPassword = FALSE;
  4392. CheckDlgButton(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX, FALSE);
  4393. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  4394. if (pArgs->fGlobalCredentialsSupported)
  4395. {
  4396. //
  4397. // Also disable the option buttons
  4398. //
  4399. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  4400. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  4401. }
  4402. }
  4403. //
  4404. // disable the "dial automatically..." checkbox
  4405. //
  4406. if (!pArgs->fHideDialAutomatically)
  4407. {
  4408. pArgs->fDialAutomatically = FALSE;
  4409. pArgs->fRememberMainPassword = FALSE;
  4410. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, FALSE);
  4411. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  4412. }
  4413. }
  4414. else
  4415. {
  4416. //
  4417. // Enable the "Remember password" checkbox
  4418. //
  4419. if (!pArgs->fHideRememberPassword)
  4420. {
  4421. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), TRUE);
  4422. }
  4423. //
  4424. // Enable the "dial automatically..." checkbox
  4425. // if HideDialAutomatically is not set
  4426. // and if Password is not optional, Remember Password must be true
  4427. //
  4428. if ((!pArgs->fHideDialAutomatically) &&
  4429. (pArgs->fRememberMainPassword ||
  4430. pArgs->piniService->GPPB(c_pszCmSection,
  4431. c_pszCmEntryPwdOptional)))
  4432. {
  4433. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), TRUE);
  4434. }
  4435. }
  4436. }
  4437. }
  4438. //
  4439. // Next, check the domain.
  4440. //
  4441. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT))
  4442. {
  4443. if (bEnable &&
  4444. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryDomainOptional, TRUE))
  4445. {
  4446. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  4447. {
  4448. bEnable = FALSE;
  4449. nId = IDMSG_NEED_DOMAIN;
  4450. nCtrlFocus = IDC_MAIN_DOMAIN_EDIT;
  4451. }
  4452. }
  4453. }
  4454. //
  4455. // Check whether primary phone number is empty -- a quick fix for bug 3123 -byao (4/11/97)
  4456. //
  4457. if (!pArgs->IsDirectConnect())
  4458. {
  4459. //
  4460. // Its not a direct connection, so we must check the phonenumber. If both
  4461. // szPhoneNumber and szCanonical are blank then we don't have a number.
  4462. //
  4463. if (bEnable &&
  4464. IsBlankString(pArgs->aDialInfo[0].szPhoneNumber) &&
  4465. IsBlankString(pArgs->aDialInfo[0].szCanonical))
  4466. {
  4467. bEnable = FALSE;
  4468. if (pArgs->fNeedConfigureTapi)
  4469. {
  4470. nId = IDMSG_NEED_CONFIGURE_TAPI;
  4471. }
  4472. else
  4473. {
  4474. //
  4475. // If direct and dial-up,the message should include the
  4476. // possibility of direct connection, otherwise use
  4477. // the standard need a phone number message
  4478. //
  4479. if (pArgs->IsBothConnTypeSupported())
  4480. {
  4481. nId = IDMSG_NEED_PHONE_DIRECT;
  4482. }
  4483. else
  4484. {
  4485. nId = IDMSG_NEED_PHONE_DIAL;
  4486. }
  4487. }
  4488. nCtrlFocus = IDC_MAIN_PROPERTIES_BUTTON;
  4489. }
  4490. }
  4491. //
  4492. // If tunneling is enabled and we are using a VPN file, make sure
  4493. // the user has selected a tunnel endpoint.
  4494. //
  4495. if (bEnable && IsTunnelEnabled(pArgs) && pArgs->pszVpnFile)
  4496. {
  4497. LPTSTR pszTunnelAddress = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  4498. if ((NULL == pszTunnelAddress) || (TEXT('\0') == pszTunnelAddress[0]))
  4499. {
  4500. bEnable = FALSE;
  4501. nId = IDMSG_PICK_VPN_ADDRESS;
  4502. nCtrlFocus = IDC_MAIN_PROPERTIES_BUTTON;
  4503. }
  4504. CmFree(pszTunnelAddress);
  4505. }
  4506. if (bEnable)
  4507. {
  4508. //
  4509. // well, now we can set the focus to the 'connect' button
  4510. // Display ready to dial message
  4511. //
  4512. nCtrlFocus = IDOK;
  4513. nId = IDMSG_READY;
  4514. }
  4515. if (pnCtrlFocus)
  4516. {
  4517. *pnCtrlFocus = nCtrlFocus;
  4518. }
  4519. pszTmp = CmFmtMsg(g_hInst,nId);
  4520. if (NULL == pszTmp)
  4521. {
  4522. return FALSE;
  4523. }
  4524. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTmp);
  4525. //
  4526. // If necessary, throw a message box at the user.
  4527. //
  4528. if (!bEnable && fShowMsg)
  4529. {
  4530. MessageBoxEx(hwndDlg,
  4531. pszTmp,
  4532. pArgs->szServiceName,
  4533. MB_OK|MB_ICONINFORMATION,
  4534. LANG_USER_DEFAULT);
  4535. }
  4536. CmFree(pszTmp);
  4537. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  4538. //
  4539. // Something went wrong in the config. we need to recheck the
  4540. // configs next time we run CM.
  4541. //
  4542. if (GetPPTPMsgId() == nId) // not an assignment, stay left
  4543. {
  4544. ClearComponentsChecked();
  4545. }
  4546. return bEnable;
  4547. }
  4548. void MainSetDefaultButton(HWND hwndDlg,
  4549. UINT nCtrlId)
  4550. {
  4551. switch (nCtrlId)
  4552. {
  4553. case IDCANCEL:
  4554. case IDC_MAIN_PROPERTIES_BUTTON:
  4555. break;
  4556. default:
  4557. nCtrlId = IDOK;
  4558. break;
  4559. }
  4560. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)nCtrlId, 0);
  4561. }
  4562. //+---------------------------------------------------------------------------
  4563. //
  4564. // Function: SetMainDlgUserInfo
  4565. //
  4566. // Synopsis: Set user info in the main dlg.
  4567. //
  4568. // Arguments: pArgs - the ArgStruct *
  4569. // hwndDlg - the main dlg
  4570. //
  4571. // Returns: NONE
  4572. //
  4573. // History: henryt Created 5/5/97
  4574. //
  4575. //----------------------------------------------------------------------------
  4576. void SetMainDlgUserInfo(
  4577. ArgsStruct *pArgs,
  4578. HWND hwndDlg
  4579. )
  4580. {
  4581. HWND hwndTemp = NULL;
  4582. //
  4583. // Fill in the edit controls that exist
  4584. // Set the textbox modification flag. For Win9x compatibily issues we have to explicitly
  4585. // call SendMessageU instead of using the Edit_SetModify macro. The flag is used to see
  4586. // if the user has manually changed the contents of the edit boxes.
  4587. //
  4588. if (pArgs->fAccessPointsEnabled)
  4589. {
  4590. //
  4591. // This fuction populates the combo box passed to it with info from the reg
  4592. //
  4593. ShowAccessPointInfoFromReg(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  4594. }
  4595. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  4596. if (hwndTemp)
  4597. {
  4598. SetDlgItemTextU(hwndDlg, IDC_MAIN_USERNAME_EDIT, pArgs->szUserName);
  4599. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4600. }
  4601. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  4602. if (hwndTemp)
  4603. {
  4604. LPTSTR pszClearPassword = NULL;
  4605. DWORD cbClearPassword = 0;
  4606. BOOL fRetPassword = FALSE;
  4607. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  4608. if (fRetPassword && pszClearPassword)
  4609. {
  4610. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, pszClearPassword);
  4611. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4612. //
  4613. // Clear and Free the clear-text password
  4614. //
  4615. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  4616. }
  4617. }
  4618. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT);
  4619. if (hwndTemp) // !pArgs->fHideDomain)
  4620. {
  4621. SetDlgItemTextU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, pArgs->szDomain);
  4622. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4623. }
  4624. }
  4625. //+---------------------------------------------------------------------------
  4626. //
  4627. // Function: OnResetPassword
  4628. //
  4629. // Synopsis: Handle reset password.
  4630. //
  4631. // Arguments: pArgs - the ArgStruct *
  4632. // hwndDlg - the main dlg
  4633. //
  4634. // Returns: BOOL -- TRUE if SUCCEEDED
  4635. //
  4636. // History: henryt Created 5/6/97
  4637. //
  4638. //----------------------------------------------------------------------------
  4639. BOOL OnResetPassword(HWND hwndDlg, ArgsStruct *pArgs)
  4640. {
  4641. LPTSTR pszArgs = NULL;
  4642. LPTSTR pszCmd = NULL;
  4643. BOOL bReturn = FALSE;
  4644. MYDBGASSERT(pArgs);
  4645. MYDBGASSERT(pArgs->pszResetPasswdExe);
  4646. //
  4647. // Get the latest password data from the edit control
  4648. // and obfuscate its contents so that connect actions
  4649. // can't retrieve it.
  4650. //
  4651. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  4652. ObfuscatePasswordEdit(pArgs);
  4653. if (pArgs && pArgs->pszResetPasswdExe)
  4654. {
  4655. if (CmParsePath(pArgs->pszResetPasswdExe, pArgs->piniService->GetFile(), &pszCmd, &pszArgs))
  4656. {
  4657. pArgs->Log.Log(PASSWORD_RESET_EVENT, pszCmd);
  4658. SHELLEXECUTEINFO ShellExInfo;
  4659. ZeroMemory(&ShellExInfo, sizeof(SHELLEXECUTEINFO));
  4660. //
  4661. // Fill in the Execute Struct
  4662. //
  4663. ShellExInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  4664. ShellExInfo.hwnd = hwndDlg;
  4665. ShellExInfo.lpVerb = TEXT("open");
  4666. ShellExInfo.lpFile = pszCmd;
  4667. ShellExInfo.lpParameters = pszArgs;
  4668. ShellExInfo.nShow = SW_SHOWNORMAL;
  4669. bReturn = pArgs->m_ShellDll.ExecuteEx(&ShellExInfo);
  4670. }
  4671. CmFree(pszCmd);
  4672. CmFree(pszArgs);
  4673. }
  4674. #ifdef DEBUG
  4675. CMASSERTMSG(bReturn, TEXT("OnResetPassword() - ShellExecute failed."));
  4676. #endif
  4677. DeObfuscatePasswordEdit(pArgs);
  4678. return bReturn;
  4679. }
  4680. //+---------------------------------------------------------------------------
  4681. //
  4682. // Function: OnCustom
  4683. //
  4684. // Synopsis: Handle custom button
  4685. //
  4686. // Arguments: pArgs - the ArgStruct *
  4687. // hwndDlg - the main dlg
  4688. //
  4689. // Returns: NONE
  4690. //
  4691. // History: t-adnani Created 6/26/99
  4692. //
  4693. //----------------------------------------------------------------------------
  4694. void OnCustom(
  4695. HWND hwndDlg,
  4696. ArgsStruct *pArgs)
  4697. {
  4698. MYDBGASSERT(pArgs);
  4699. if (NULL == pArgs)
  4700. {
  4701. return;
  4702. }
  4703. pArgs->Log.Log(CUSTOM_BUTTON_EVENT);
  4704. //
  4705. // Get the latest password data from the edit control
  4706. // and obfuscate its contents so that connect actions
  4707. // can't retrieve it.
  4708. //
  4709. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  4710. ObfuscatePasswordEdit(pArgs);
  4711. //
  4712. // Run the CustomButton actions
  4713. //
  4714. int iTextBoxLength = (int) SendDlgItemMessage(hwndDlg, IDC_MAIN_STATUS_DISPLAY, WM_GETTEXTLENGTH, 0, (LPARAM)0) + 1;
  4715. TCHAR *pszTextBoxContents = (TCHAR *) CmMalloc(iTextBoxLength * sizeof(TCHAR));
  4716. if (pszTextBoxContents)
  4717. {
  4718. GetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTextBoxContents, iTextBoxLength);
  4719. }
  4720. CActionList CustomActList;
  4721. CustomActList.Append(pArgs->piniService, c_pszCmSectionCustom);
  4722. if (!CustomActList.RunAccordType(hwndDlg, pArgs))
  4723. {
  4724. //
  4725. // Connect action failed
  4726. //
  4727. }
  4728. else
  4729. {
  4730. if (pszTextBoxContents)
  4731. {
  4732. SetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTextBoxContents);
  4733. }
  4734. }
  4735. CmFree(pszTextBoxContents);
  4736. DeObfuscatePasswordEdit(pArgs);
  4737. }
  4738. //----------------------------------------------------------------------------
  4739. //
  4740. // Function: SetupInternalInfo
  4741. //
  4742. // Synopsis: Load system dll's and init ArgsStruct with info from cmp/cms.
  4743. //
  4744. // Arguments: pArgs - the ArgStruct *
  4745. // hwndDlg - the main dlg
  4746. //
  4747. // Returns: NONE
  4748. //
  4749. // History: henryt created 8/13/97
  4750. //
  4751. //----------------------------------------------------------------------------
  4752. BOOL SetupInternalInfo(
  4753. ArgsStruct *pArgs,
  4754. HWND hwndDlg
  4755. )
  4756. {
  4757. HCURSOR hcursorPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  4758. BOOL fRet = FALSE;
  4759. //
  4760. // Check to see if the SafeNet Client is available.
  4761. //
  4762. if ((OS_W9X || OS_NT4) && IsSafeNetClientAvailable())
  4763. {
  4764. SafeNetLinkageStruct SnLinkage = {0};
  4765. if (LinkToSafeNet(&SnLinkage))
  4766. {
  4767. UnLinkFromSafeNet(&SnLinkage);
  4768. pArgs->bSafeNetClientAvailable = TRUE;
  4769. }
  4770. }
  4771. //
  4772. // Should we check if TCP is bound to PPP? Note that if the SafeNet client is installed, we
  4773. // automatically don't check bindings because the Deterministic Networks shim is in the way
  4774. // and bindings checking will fail.
  4775. //
  4776. if (pArgs->bSafeNetClientAvailable)
  4777. {
  4778. pArgs->bDoNotCheckBindings = TRUE;
  4779. }
  4780. else
  4781. {
  4782. pArgs->bDoNotCheckBindings = pArgs->piniService->GPPB(c_pszCmSection,
  4783. c_pszCmEntryDoNotCheckBindings,
  4784. FALSE);
  4785. }
  4786. DWORD dwComponentsToCheck = CC_RNA | CC_TCPIP | CC_RASRUNNING
  4787. | CC_SCRIPTING | CC_CHECK_BINDINGS;
  4788. if (TRUE == pArgs->bDoNotCheckBindings)
  4789. {
  4790. //
  4791. // Do not check if TCP is bound to PPP
  4792. //
  4793. dwComponentsToCheck &= ~CC_CHECK_BINDINGS;
  4794. }
  4795. #if 0 // Don't do this until the user gets into the app.
  4796. /*
  4797. //
  4798. // If current connection type is dial-up (not Direct means Dial-up),
  4799. // then check modem
  4800. //
  4801. if (!pArgs->IsDirectConnect())
  4802. {
  4803. dwComponentsToCheck |= CC_MODEM;
  4804. }
  4805. */
  4806. #endif
  4807. if (TRUE == IsTunnelEnabled(pArgs))
  4808. {
  4809. dwComponentsToCheck |= CC_PPTP;
  4810. }
  4811. //
  4812. // should we check OS components, regardless what is in the registry key
  4813. // Default is use the registry key
  4814. //
  4815. BOOL fIgnoreRegKey = pArgs->piniService->GPPB(c_pszCmSection,
  4816. c_pszCmEntryCheckOsComponents,
  4817. FALSE);
  4818. //
  4819. // If fIgnoreRegKey is TRUE, Do not bother looking ComponentsChecked from registry.
  4820. // in 'Unattended Dialing' mode, check only, do not try to install
  4821. //
  4822. pArgs->dwExitCode = CheckAndInstallComponents( dwComponentsToCheck,
  4823. hwndDlg, pArgs->szServiceName, fIgnoreRegKey, pArgs->dwFlags & FL_UNATTENDED);
  4824. if (pArgs->dwExitCode != ERROR_SUCCESS )
  4825. {
  4826. goto done;
  4827. }
  4828. //
  4829. // If we haven't loaded RAS yet, do so now.
  4830. //
  4831. if (!IsRasLoaded(&(pArgs->rlsRasLink)))
  4832. {
  4833. if (!LinkToRas(&pArgs->rlsRasLink))
  4834. {
  4835. if (pArgs->dwFlags & FL_UNATTENDED)
  4836. {
  4837. goto done;
  4838. }
  4839. //
  4840. // Something terrible happened! We want to check our configs and install
  4841. // necessary components now.
  4842. //
  4843. dwComponentsToCheck = CC_RNA | CC_RASRUNNING | CC_TCPIP;
  4844. if (TRUE != pArgs->bDoNotCheckBindings)
  4845. {
  4846. dwComponentsToCheck |= CC_CHECK_BINDINGS;
  4847. }
  4848. pArgs->dwExitCode = CheckAndInstallComponents(dwComponentsToCheck, hwndDlg, pArgs->szServiceName);
  4849. if (pArgs->dwExitCode != ERROR_SUCCESS || !LinkToRas(&pArgs->rlsRasLink))
  4850. {
  4851. goto done;
  4852. }
  4853. }
  4854. }
  4855. //
  4856. // Load properties data
  4857. //
  4858. LoadProperties(pArgs);
  4859. //
  4860. // Get phone info(phone #'s, etc)
  4861. // CheckConnect will check for empty phone number
  4862. //
  4863. LoadPhoneInfoFromProfile(pArgs);
  4864. fRet = TRUE;
  4865. done:
  4866. SetCursor(hcursorPrev);
  4867. return fRet;
  4868. }
  4869. //----------------------------------------------------------------------------
  4870. //
  4871. // Function: OnMainLoadStartupInfo
  4872. //
  4873. // Synopsis: Load the startup info for the main dlg(after WM_INITDIALOG).
  4874. // This includes loading system dll's and setting up the UI.
  4875. //
  4876. // Arguments: hwndDlg - the main dlg
  4877. // pArgs - the ArgStruct *
  4878. //
  4879. // Returns: NONE
  4880. //
  4881. // History: henryt created 8/13/97
  4882. //
  4883. //----------------------------------------------------------------------------
  4884. void OnMainLoadStartupInfo(
  4885. HWND hwndDlg,
  4886. ArgsStruct *pArgs
  4887. )
  4888. {
  4889. UINT i;
  4890. UINT nCtrlFocus;
  4891. BOOL fSaveNoNotify = pArgs->fIgnoreChangeNotification;
  4892. pArgs->fStartupInfoLoaded = TRUE;
  4893. //
  4894. // if failed to load dll's, etc...
  4895. //
  4896. if (!SetupInternalInfo(pArgs, hwndDlg))
  4897. {
  4898. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL,0);
  4899. return;
  4900. }
  4901. //
  4902. // Set the length limit for the edit controls that exist
  4903. //
  4904. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  4905. {
  4906. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  4907. if (i <= 0)
  4908. {
  4909. i = UNLEN; // username
  4910. }
  4911. SendDlgItemMessageU(hwndDlg, IDC_MAIN_USERNAME_EDIT, EM_SETLIMITTEXT, __min(UNLEN, i), 0);
  4912. }
  4913. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  4914. {
  4915. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  4916. if (i <= 0)
  4917. {
  4918. i = PWLEN; // password
  4919. }
  4920. SendDlgItemMessageU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, EM_SETLIMITTEXT, __min(PWLEN, i), 0);
  4921. }
  4922. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  4923. {
  4924. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  4925. if (i <= 0)
  4926. {
  4927. i = DNLEN; // domain
  4928. }
  4929. SendDlgItemMessageU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, EM_SETLIMITTEXT, __min(DNLEN, i), 0);
  4930. }
  4931. //
  4932. // if there's no service msg text, we need to hide and disable the control
  4933. // so that context help doesn't work.
  4934. //
  4935. if (!GetWindowTextLengthU(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY)))
  4936. {
  4937. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY), SW_HIDE);
  4938. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY), FALSE);
  4939. }
  4940. //
  4941. // display the user info
  4942. //
  4943. pArgs->fIgnoreChangeNotification = TRUE;
  4944. SetMainDlgUserInfo(pArgs, hwndDlg);
  4945. pArgs->fIgnoreChangeNotification = fSaveNoNotify;
  4946. //
  4947. // init "Remember password"
  4948. //
  4949. if (pArgs->fHideRememberPassword)
  4950. {
  4951. //
  4952. // disable and hide the checkbox if the ISP doesn't use this feature
  4953. //
  4954. //ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), SW_HIDE);
  4955. //EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  4956. }
  4957. else
  4958. {
  4959. CheckDlgButton(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX,
  4960. pArgs->fRememberMainPassword);
  4961. //
  4962. // Don't care if the pArgs->fRememberMainPassword is set
  4963. // since controls will get disabled later
  4964. // Set the save as option buttons according to what the current
  4965. // deafult is
  4966. //
  4967. SetCredentialUIOptionBasedOnDefaultCreds(pArgs, hwndDlg);
  4968. }
  4969. //
  4970. // init "Dial automatically..."
  4971. //
  4972. if (pArgs->fHideDialAutomatically)
  4973. {
  4974. //
  4975. // disable and hide the checkbox if the ISP doesn't use this feature
  4976. //
  4977. //ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), SW_HIDE);
  4978. //EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  4979. }
  4980. else
  4981. {
  4982. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, pArgs->fDialAutomatically);
  4983. }
  4984. //
  4985. // Check the main dlg status and set the default button and focus accordingly
  4986. //
  4987. BOOL bReady = CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  4988. MainSetDefaultButton(hwndDlg, nCtrlFocus);
  4989. SetFocus(GetDlgItem(hwndDlg, nCtrlFocus));
  4990. //
  4991. // Check if we want to dial without prompting user
  4992. // if so, send the button click to connect button
  4993. // We also want to dial if the user isn't logged on (ICS case)
  4994. //
  4995. if (bReady)
  4996. {
  4997. if (pArgs->fDialAutomatically ||
  4998. pArgs->dwFlags & FL_RECONNECT ||
  4999. pArgs->dwFlags & FL_UNATTENDED ||
  5000. ((CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType) && (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseWinLogonCredentials, TRUE))))
  5001. {
  5002. PostMessageU(hwndDlg, WM_COMMAND, IDOK, 0);
  5003. }
  5004. }
  5005. else
  5006. {
  5007. //
  5008. // there are settings missing.
  5009. // silently fail in unattended dial, set exit code
  5010. //
  5011. if (pArgs->dwFlags & FL_UNATTENDED)
  5012. {
  5013. pArgs->psState = PS_Error;
  5014. pArgs->dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  5015. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL,0);
  5016. }
  5017. }
  5018. CM_SET_TIMING_INTERVAL("OnMainLoadStartupInfo - Complete");
  5019. }
  5020. //+----------------------------------------------------------------------------
  5021. //
  5022. // Function: CreateCustomButtonNextToTextBox
  5023. //
  5024. // Synopsis: Creates a pushbutton next to the specified text box
  5025. //
  5026. // Arguments: HWND hwndDlg - Dialog Handle
  5027. // HWND hwndTextBox - TextBox Handle
  5028. // LPTSTR pszTitle - Push Button Title
  5029. // LPTSTR pszToolTip - Push Button Tooltip
  5030. // UINT uButtonID - Control ID of Button to create
  5031. //
  5032. // Returns: Nothing
  5033. //
  5034. // History: t-adnani Created Header 6/28/99
  5035. //
  5036. //+----------------------------------------------------------------------------
  5037. void CreateCustomButtonNextToTextBox(
  5038. HWND hwndDlg, // Dialog Handle
  5039. HWND hwndTextBox, // TextBox Handle
  5040. LPTSTR pszTitle, // Caption
  5041. LPTSTR pszToolTip, // ToolTip Text
  5042. UINT uButtonID // ButtonID
  5043. )
  5044. {
  5045. if ((NULL == hwndDlg) || (NULL == hwndTextBox) || (NULL == pszTitle) || (0 == uButtonID))
  5046. {
  5047. CMASSERTMSG(FALSE, TEXT("Invalid parameter passed to CreateCustomButtonNextToTextBox"));
  5048. return;
  5049. }
  5050. RECT rt;
  5051. POINT pt1, pt2, ptTextBox1, ptTextBox2;
  5052. HFONT hfont;
  5053. HWND hwndButton;
  5054. //
  5055. // Get the rectangle and convert to points before we reduce its size.
  5056. //
  5057. GetWindowRect(hwndTextBox, &rt);
  5058. pt1.x = rt.left;
  5059. pt1.y = rt.top;
  5060. pt2.x = rt.right;
  5061. pt2.y = rt.bottom;
  5062. ScreenToClient(hwndDlg, &pt1);
  5063. ScreenToClient(hwndDlg, &pt2);
  5064. //
  5065. // Then calculate the points for reduction
  5066. //
  5067. ptTextBox1.x = rt.left;
  5068. ptTextBox1.y = rt.top;
  5069. ptTextBox2.x = rt.right;
  5070. ptTextBox2.y = rt.bottom;
  5071. ScreenToClient(hwndDlg, &ptTextBox1);
  5072. ScreenToClient(hwndDlg, &ptTextBox2);
  5073. //
  5074. // Make the text box smaller
  5075. //
  5076. MoveWindow(hwndTextBox, ptTextBox1.x, ptTextBox1.y,
  5077. ptTextBox2.x - ptTextBox1.x - CUSTOM_BUTTON_WIDTH - 7,
  5078. ptTextBox2.y - ptTextBox1.y, TRUE);
  5079. //
  5080. // Create the button
  5081. //
  5082. hwndButton = CreateWindowExU(0,
  5083. TEXT("button"),
  5084. pszTitle,
  5085. BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP,
  5086. pt2.x - CUSTOM_BUTTON_WIDTH,
  5087. ptTextBox1.y,
  5088. CUSTOM_BUTTON_WIDTH,
  5089. ptTextBox2.y-ptTextBox1.y,
  5090. hwndDlg,
  5091. (HMENU)UIntToPtr(uButtonID),
  5092. g_hInst,
  5093. NULL);
  5094. if (NULL == hwndButton)
  5095. {
  5096. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() CreateWindowExU() failed, GLE=%u."),GetLastError());
  5097. }
  5098. //
  5099. // Set the font on the button
  5100. //
  5101. hfont = (HFONT)SendMessageU(hwndTextBox, WM_GETFONT, 0, 0);
  5102. if (NULL == hfont)
  5103. {
  5104. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() WM_GETFONT failed, GLE=%u."),GetLastError());
  5105. return;
  5106. }
  5107. SendMessageU(hwndButton, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0));
  5108. //
  5109. // do the tool tip
  5110. //
  5111. if (pszToolTip)
  5112. {
  5113. HWND hwndTT = CreateWindowExU(0, TOOLTIPS_CLASS, TEXT(""), TTS_ALWAYSTIP,
  5114. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  5115. hwndDlg, (HMENU) NULL, g_hInst, NULL);
  5116. CMTRACE2(TEXT("CreateCustomButtonNextToTextBox() hwndTT is %u and IsWindow returns %u"),hwndTT, IsWindow(hwndButton));
  5117. if (NULL == hwndTT)
  5118. {
  5119. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() CreateWindowExU() failed, GLE=%u."),GetLastError());
  5120. MYDBGASSERT(hwndTT);
  5121. return;
  5122. }
  5123. TOOLINFO ti; // tool information
  5124. ti.cbSize = sizeof(TOOLINFO);
  5125. ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP | TTF_SUBCLASS;
  5126. ti.hwnd = hwndDlg;
  5127. ti.hinst = g_hInst;
  5128. ti.uId = (UINT_PTR) hwndButton;
  5129. ti.lpszText = pszToolTip;
  5130. SendMessageU(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
  5131. CMTRACE2(TEXT("CreateCustomButtonNextToTextBox() hwndTT is %u and IsWindow returns %u"),hwndTT, IsWindow(hwndButton));
  5132. }
  5133. return;
  5134. }
  5135. //+---------------------------------------------------------------------------
  5136. //
  5137. // Function: OnMainInit
  5138. //
  5139. // Synopsis: Process the WM_INITDIALOG message
  5140. // initialization function for Main dialog box
  5141. //
  5142. // Arguments: hwndDlg - the main dlg
  5143. // pArgs - the ArgStruct *
  5144. //
  5145. // Returns: NONE
  5146. //
  5147. // History: byao Modified 5/9/97
  5148. // Added code to handle "Unattended Dial" and "Dial with Connectoid"
  5149. //
  5150. //----------------------------------------------------------------------------
  5151. void OnMainInit(HWND hwndDlg,
  5152. ArgsStruct *pArgs)
  5153. {
  5154. RECT rDlg;
  5155. RECT rWorkArea;
  5156. LPTSTR pszTitle;
  5157. SetForegroundWindow(hwndDlg);
  5158. //
  5159. // load the icons and bitmaps
  5160. //
  5161. LoadIconsAndBitmaps(pArgs, hwndDlg);
  5162. //
  5163. // Use long sevice name as title text for signin window,
  5164. //
  5165. pszTitle = CmStrCpyAlloc(pArgs->szServiceName);
  5166. SetWindowTextU(hwndDlg, pszTitle);
  5167. CmFree(pszTitle);
  5168. //
  5169. // Set the msg for the main dlg for profile dialing
  5170. //
  5171. LPTSTR pszMsg = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryServiceMessage);
  5172. SetDlgItemTextU(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY, pszMsg);
  5173. CmFree(pszMsg);
  5174. //
  5175. // Show "remember password" checkbox?
  5176. //
  5177. if (IsLogonAsSystem())
  5178. {
  5179. //
  5180. // If the program is running in the system account, hide the checkbox
  5181. // Bug 196184: big security hole logging onto box with cm
  5182. //
  5183. pArgs->fHideRememberPassword = TRUE;
  5184. //
  5185. // Another big security hole by launching help files from winlogon.
  5186. // See NTRAID 429678 for details.
  5187. //
  5188. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_HELP_BUTTON), FALSE);
  5189. }
  5190. else
  5191. {
  5192. pArgs->fHideRememberPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberPwd);
  5193. }
  5194. //
  5195. // See if the Internet Password should be hidden, take HideRemember
  5196. // value as the default if no actual value is specified in the .CMS
  5197. // The Internet Password can be saved regardless of the logon context
  5198. //
  5199. pArgs->fHideRememberInetPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberInetPwd, pArgs->fHideRememberPassword);
  5200. //
  5201. // show "dial automatically" checkbox?
  5202. //
  5203. // if "hide remember password", then we also want to hide "dial automatically"
  5204. //
  5205. pArgs->fHideDialAutomatically = (pArgs->fHideRememberPassword?
  5206. TRUE :
  5207. pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideDialAuto));
  5208. // Get the dialog rect and the available work area.
  5209. GetWindowRect(hwndDlg,&rDlg);
  5210. if (SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
  5211. {
  5212. MoveWindow(hwndDlg,
  5213. rWorkArea.left + ((rWorkArea.right-rWorkArea.left)-(rDlg.right-rDlg.left))/2,
  5214. rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top)-(rDlg.bottom-rDlg.top))/2,
  5215. rDlg.right-rDlg.left,
  5216. rDlg.bottom-rDlg.top,
  5217. FALSE);
  5218. }
  5219. //
  5220. // hide all the hidden controls asap
  5221. //
  5222. if (pArgs->fHideRememberPassword)
  5223. {
  5224. //
  5225. // disable and hide the checkbox if the ISP doesn't use this feature
  5226. //
  5227. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), SW_HIDE);
  5228. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  5229. //
  5230. // Even though we are hiding the remember password box,
  5231. // we should not hide these two controls as they might not exist on the
  5232. // dialog. fGlobalCredentialsSupported controls which dialog templates get loaded and
  5233. // if the flag is FALSE then the dialog template doesn't have these controls
  5234. // thus there is no reason to hide them.
  5235. //
  5236. if (pArgs->fGlobalCredentialsSupported)
  5237. {
  5238. //
  5239. // Also hide the option buttons
  5240. //
  5241. ShowWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), SW_HIDE);
  5242. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  5243. ShowWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), SW_HIDE);
  5244. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  5245. }
  5246. }
  5247. else
  5248. {
  5249. //
  5250. // Here we don't care if pArgs->fRememberMainPassword is set, because
  5251. // these controls will get disabled later, but we still need to set
  5252. // the default option.
  5253. //
  5254. SetCredentialUIOptionBasedOnDefaultCreds(pArgs, hwndDlg );
  5255. }
  5256. if (pArgs->fHideDialAutomatically)
  5257. {
  5258. //
  5259. // disable and hide the checkbox if the ISP doesn't use this feature
  5260. //
  5261. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), SW_HIDE);
  5262. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  5263. }
  5264. //
  5265. // Show the custom button?
  5266. //
  5267. // NT #368810
  5268. // If logged on in the system account, don't do dynamic buttons
  5269. //
  5270. if (!IsLogonAsSystem() && GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  5271. {
  5272. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryCustomButtonText);
  5273. if (pszTmp && *pszTmp)
  5274. {
  5275. LPTSTR pszToolTip = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryCustomButtonToolTip);
  5276. CMTRACE(TEXT("Creating Custom Button"));
  5277. CreateCustomButtonNextToTextBox(hwndDlg,
  5278. GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT),
  5279. pszTmp,
  5280. *pszToolTip ? pszToolTip : NULL,
  5281. IDC_MAIN_CUSTOM);
  5282. CmFree(pszToolTip);
  5283. }
  5284. CmFree(pszTmp);
  5285. }
  5286. //
  5287. // Show the reset password button?
  5288. //
  5289. if (!IsLogonAsSystem() && GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  5290. {
  5291. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryResetPassword);
  5292. if (pszTmp && *pszTmp)
  5293. {
  5294. DWORD dwTmp;
  5295. DWORD dwLen = (MAX_PATH * 2);
  5296. pArgs->pszResetPasswdExe = (LPTSTR) CmMalloc(sizeof(TCHAR) * dwLen);
  5297. if (pArgs->pszResetPasswdExe)
  5298. {
  5299. //
  5300. // Expand any environment strings that may exist
  5301. //
  5302. CMTRACE1(TEXT("Expanding ResetPassword environment string as %s"), pszTmp);
  5303. dwTmp = ExpandEnvironmentStringsU(pszTmp, pArgs->pszResetPasswdExe, dwLen);
  5304. MYDBGASSERT(dwTmp <= dwLen);
  5305. //
  5306. // As long as expansion succeeded, pass along the result
  5307. //
  5308. if (dwTmp <= dwLen)
  5309. {
  5310. pszTitle = CmLoadString(g_hInst, IDS_RESETPASSWORD);
  5311. CMTRACE((TEXT("Showing ResetPassword button for %s"), pArgs->pszResetPasswdExe));
  5312. CreateCustomButtonNextToTextBox(hwndDlg,
  5313. GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT),
  5314. pszTitle,
  5315. (LPTSTR)MAKEINTRESOURCE(IDS_NEW_PASSWORD_TOOLTIP),
  5316. IDC_MAIN_RESET_PASSWORD);
  5317. CmFree(pszTitle);
  5318. }
  5319. }
  5320. }
  5321. CmFree(pszTmp);
  5322. }
  5323. //
  5324. // Notify user that we are intializing
  5325. //
  5326. AppendStatusPane(hwndDlg,IDMSG_INITIALIZING);
  5327. //
  5328. // Initialize system menu
  5329. //
  5330. HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
  5331. MYDBGASSERT(hMenu);
  5332. // Delete size and maximize menuitems. These are
  5333. // not appropriate for a dialog with a no-resize frame.
  5334. DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
  5335. DeleteMenu(hMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  5336. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED);
  5337. //
  5338. // See if we are hiding any InetLogon controls
  5339. //
  5340. if (IsTunnelEnabled(pArgs) && !pArgs->fUseSameUserName)
  5341. {
  5342. pArgs->fHideInetUsername = pArgs->piniService->GPPB(c_pszCmSection,
  5343. c_pszCmEntryHideInetUserName);
  5344. pArgs->fHideInetPassword = pArgs->piniService->GPPB(c_pszCmSection,
  5345. c_pszCmEntryHideInetPassword);
  5346. }
  5347. //
  5348. // set timer
  5349. //
  5350. pArgs->nTimerId = SetTimer(hwndDlg,1,TIMER_RATE,NULL);
  5351. }
  5352. //
  5353. // map state to frame: splash????
  5354. //
  5355. VOID MapStateToFrame(ArgsStruct * pArgs)
  5356. {
  5357. static ProgState psOldFrame = PS_Interactive;
  5358. ProgState psNewFrame = pArgs->psState;
  5359. if (psNewFrame == PS_Dialing || psNewFrame == PS_TunnelDialing)
  5360. {
  5361. //
  5362. // If we are dialing anything other than the primary number
  5363. // switch the state to RedialFrame
  5364. // RedialFrame is a misnomer - this is the frame that is displayed
  5365. // when dialing backup number. It is not used when Redialing the
  5366. // primary number again
  5367. //
  5368. if (pArgs->nDialIdx > 0)
  5369. {
  5370. psNewFrame = PS_RedialFrame;
  5371. }
  5372. }
  5373. if (pArgs->pCtr && psNewFrame != psOldFrame)
  5374. {
  5375. psOldFrame = psNewFrame;
  5376. //
  5377. // don't check for failure here - nothing we can do.
  5378. //
  5379. pArgs->pCtr->MapStateToFrame(psOldFrame);
  5380. }
  5381. }
  5382. //
  5383. // SetInteractive: enable most of the windows and buttons so user can interact with
  5384. // connection manager again
  5385. //
  5386. void SetInteractive(HWND hwndDlg,
  5387. ArgsStruct *pArgs)
  5388. {
  5389. if (pArgs->dwFlags & FL_UNATTENDED)
  5390. {
  5391. //
  5392. // When we are unattended mode we don't want to put the UI into
  5393. // interactive mode and wait for user input. Since the unattended
  5394. // UI is now hidden, this would put up the UI waiting for user
  5395. // interaction even though the UI was invisible. Instead we
  5396. // will set the state to Interactive and post a message to cancel
  5397. // the dialer.
  5398. //
  5399. CMTRACE(TEXT("SetInteractive called while in unattended mode, posting a message to cancel"));
  5400. pArgs->psState = PS_Interactive;
  5401. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL, ERROR_CANCELLED);
  5402. }
  5403. else
  5404. {
  5405. pArgs->psState = PS_Interactive;
  5406. MapStateToFrame(pArgs);
  5407. pArgs->dwStateStartTime = GetTickCount();
  5408. EnableWindow(GetDlgItem(hwndDlg,IDOK),TRUE);
  5409. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),TRUE);
  5410. //
  5411. // Enable edit controls as necessary
  5412. //
  5413. if (GetDlgItem(hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO))
  5414. {
  5415. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_STATIC),TRUE);
  5416. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_COMBO),TRUE);
  5417. }
  5418. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  5419. {
  5420. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_EDIT),TRUE);
  5421. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_STATIC),TRUE);
  5422. }
  5423. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  5424. {
  5425. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_EDIT),TRUE);
  5426. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_STATIC),TRUE);
  5427. }
  5428. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  5429. {
  5430. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_EDIT),TRUE);
  5431. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_STATIC),TRUE);
  5432. }
  5433. if (pArgs->hwndResetPasswdButton)
  5434. {
  5435. EnableWindow(pArgs->hwndResetPasswdButton, TRUE);
  5436. }
  5437. if (!pArgs->fHideRememberPassword)
  5438. {
  5439. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), TRUE);
  5440. if (pArgs->fGlobalCredentialsSupported && pArgs->fRememberMainPassword)
  5441. {
  5442. //
  5443. // Also enable the option buttons
  5444. //
  5445. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), TRUE);
  5446. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), TRUE);
  5447. }
  5448. }
  5449. if ((!pArgs->fHideDialAutomatically) &&
  5450. (pArgs->fRememberMainPassword ||
  5451. pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional)))
  5452. {
  5453. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), TRUE);
  5454. }
  5455. //
  5456. // Set the default button
  5457. //
  5458. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDOK, 0);
  5459. SetFocus(GetDlgItem(hwndDlg,IDOK));
  5460. }
  5461. DeObfuscatePasswordEdit(pArgs);
  5462. }
  5463. //+----------------------------------------------------------------------------
  5464. //
  5465. // Function: SetWatchHandles
  5466. //
  5467. // Synopsis: Handles the messy details of Duplicating each of the Watch
  5468. // handles so that they can be accessed by the CMMON process.
  5469. // The list of handles is assumed to be NULL terminated.
  5470. //
  5471. // Arguments: HANDLE *phOldHandles - Ptr to the current handle list.
  5472. // HANDLE *phNewHandles - Ptr to storage for duplicted handles.
  5473. // HWND hwndMon - HWND in the target process.
  5474. //
  5475. // Returns: BOOL - TRUE on success
  5476. //
  5477. // History: nickball Created 2/11/98
  5478. //
  5479. //+----------------------------------------------------------------------------
  5480. BOOL
  5481. SetWatchHandles(
  5482. IN HANDLE *phOldHandles,
  5483. OUT HANDLE *phNewHandles,
  5484. IN HWND hwndMon)
  5485. {
  5486. MYDBGASSERT(phOldHandles);
  5487. MYDBGASSERT(phNewHandles);
  5488. MYDBGASSERT(hwndMon);
  5489. BOOL bReturn = TRUE;
  5490. if (NULL == phOldHandles || NULL == phNewHandles || NULL == hwndMon)
  5491. {
  5492. return FALSE;
  5493. }
  5494. //
  5495. // First we need to get the Handle of our current process
  5496. //
  5497. DWORD dwProcessId = GetCurrentProcessId();
  5498. HANDLE hSourceProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  5499. //
  5500. // Now the handle of the target process
  5501. //
  5502. GetWindowThreadProcessId(hwndMon, &dwProcessId);
  5503. HANDLE hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  5504. //
  5505. // Loop through our handles list and duplicate
  5506. //
  5507. DWORD dwIdx = 0;
  5508. if (hTargetProcess && hSourceProcess)
  5509. {
  5510. for (dwIdx = 0; phOldHandles[dwIdx]; dwIdx++)
  5511. {
  5512. if (FALSE == DuplicateHandle(hSourceProcess, phOldHandles[dwIdx], // Val
  5513. hTargetProcess, &phNewHandles[dwIdx], // Ptr
  5514. NULL, FALSE, DUPLICATE_SAME_ACCESS))
  5515. {
  5516. CMTRACE1(TEXT("SetWatchHandles() - DuplicateHandles failed on item %u"), dwIdx);
  5517. MYDBGASSERT(FALSE);
  5518. bReturn = FALSE;
  5519. break;
  5520. }
  5521. }
  5522. }
  5523. MYDBGASSERT(dwIdx); // Don't call if you don't have handles to duplicate
  5524. //
  5525. // Cleanup
  5526. //
  5527. if (!bReturn)
  5528. {
  5529. // we failed during Handle Duplication... must clean up
  5530. while (dwIdx > 0)
  5531. {
  5532. CloseHandle(phNewHandles[--dwIdx]);
  5533. }
  5534. }
  5535. CloseHandle(hTargetProcess);
  5536. CloseHandle(hSourceProcess);
  5537. return bReturn;
  5538. }
  5539. //+----------------------------------------------------------------------------
  5540. //
  5541. // Function: ConnectMonitor
  5542. //
  5543. // Synopsis: Encapsulates the details of launching CMMON, waiting for load
  5544. // verification, and providing it with connect data.
  5545. //
  5546. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  5547. //
  5548. // Returns: HRESULT - Failure code
  5549. //
  5550. // History: nickball Created 2/9/98
  5551. //
  5552. //+----------------------------------------------------------------------------
  5553. HRESULT ConnectMonitor(ArgsStruct *pArgs)
  5554. {
  5555. LRESULT lRes = ERROR_SUCCESS;
  5556. BOOL fMonReady = FALSE;
  5557. HWND hwndMon = NULL;
  5558. TCHAR szDesktopName[MAX_PATH];
  5559. TCHAR szWinDesktop[MAX_PATH];
  5560. //
  5561. // Determine if CMMON is running
  5562. //
  5563. if (SUCCEEDED(pArgs->pConnTable->GetMonitorWnd(&hwndMon)))
  5564. {
  5565. fMonReady = IsWindow(hwndMon);
  5566. }
  5567. //
  5568. // If not, launch it
  5569. //
  5570. if (FALSE == fMonReady)
  5571. {
  5572. //
  5573. // Create launch event
  5574. //
  5575. HANDLE hEvent = CreateEventU(NULL, TRUE, FALSE, c_pszCmMonReadyEvent);
  5576. if (NULL == hEvent)
  5577. {
  5578. MYDBGASSERT(FALSE);
  5579. lRes = GetLastError();
  5580. }
  5581. else
  5582. {
  5583. STARTUPINFO StartupInfo;
  5584. PROCESS_INFORMATION ProcessInfo;
  5585. TCHAR szCommandLine[2 * MAX_PATH + 3];
  5586. TCHAR szCmmon32Path[MAX_PATH + 1 + 11 + 1]; // 11 == lstrlenU(c_pszCmMonExeName)
  5587. //
  5588. // Launch c_pszCmMonExeName
  5589. //
  5590. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  5591. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  5592. StartupInfo.cb = sizeof(StartupInfo);
  5593. //
  5594. // If this is win2k or whistler, then we don't want to launch cmmon32.exe onto the users
  5595. // desktop since it is a security hole to have a system process with a window on the users
  5596. // desktop. This window could be attacked by WM_TIMER and other messages ...
  5597. // But in case of ICS (no user is logged on), just launch CMMON in normally by leaving
  5598. // StartupInfo.lpDesktop = NULL. By leaving this NULL the new process inherits
  5599. // the desktop and window station of its parent process.This makes it work with
  5600. // ICS when no user is logged-on. Otherwise CM never gets the event back from
  5601. // CMMON because it's on a different desktop.
  5602. //
  5603. if (OS_NT5 && IsLogonAsSystem() && (CM_LOGON_TYPE_ICS != pArgs->dwWinLogonType))
  5604. {
  5605. DWORD cb;
  5606. HDESK hDesk = GetThreadDesktop(GetCurrentThreadId());
  5607. //
  5608. // Get the name of the desktop. Normally returns default or Winlogon or system or WinNT
  5609. //
  5610. szDesktopName[0] = 0;
  5611. if (hDesk && GetUserObjectInformation(hDesk, UOI_NAME, szDesktopName, sizeof(szDesktopName), &cb))
  5612. {
  5613. lstrcpyU(szWinDesktop, TEXT("Winsta0\\"));
  5614. lstrcatU(szWinDesktop, szDesktopName);
  5615. StartupInfo.lpDesktop = szWinDesktop;
  5616. StartupInfo.wShowWindow = SW_SHOW;
  5617. CMTRACE1(TEXT("ConnectMonitor - running under system account, so launching cmmon32.exe onto Desktop = %s"), MYDBGSTR(StartupInfo.lpDesktop));
  5618. }
  5619. else
  5620. {
  5621. //
  5622. // If we are here, cmmon32.exe probably isn't going to be able to communicate with
  5623. // cmdial32.dll which means the handoff between the two will fail and the call will be
  5624. // aborted.
  5625. //
  5626. CMASSERTMSG(FALSE, TEXT("ConnectMonitor -- GetUserObjectInformation failed."));
  5627. }
  5628. }
  5629. else if (OS_NT4 && IsLogonAsSystem())
  5630. {
  5631. //
  5632. // We are less concerned about the security risk on NT4 and more concerned with the loss
  5633. // of the functionality that cmmon32.exe provides to the user. Thus we will push the
  5634. // cmmon32.exe window onto the user's desktop.
  5635. //
  5636. StartupInfo.lpDesktop = TEXT("Winsta0\\Default");
  5637. StartupInfo.wShowWindow = SW_SHOW;
  5638. CMTRACE1(TEXT("ConnectMonitor - running on system account on NT4, so launching cmmon32.exe onto Desktop = %s"), MYDBGSTR(StartupInfo.lpDesktop ));
  5639. }
  5640. ZeroMemory(&szCmmon32Path[0], sizeof(szCmmon32Path));
  5641. ZeroMemory(&szCommandLine[0], sizeof(szCommandLine));
  5642. if (0 == GetSystemDirectoryU(szCmmon32Path, MAX_PATH))
  5643. {
  5644. lRes = GetLastError();
  5645. CMTRACE1(TEXT("ConnectMonitor() GetSystemDirectoryU(), GLE=%u."), lRes);
  5646. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5647. }
  5648. //
  5649. // Since there are no params, Application name is the same as the command line
  5650. //
  5651. szCommandLine[0] = TEXT('"');
  5652. lstrcatU(szCommandLine + 1, szCmmon32Path);
  5653. lstrcatU(szCommandLine, TEXT("\\"));
  5654. lstrcatU(szCommandLine, c_pszCmMonExeName);
  5655. lstrcatU(szCommandLine, TEXT("\""));
  5656. CMTRACE1(TEXT("ConnectMonitor() - Launching %s"), szCommandLine);
  5657. lstrcatU(szCmmon32Path, TEXT("\\"));
  5658. lstrcatU(szCmmon32Path, c_pszCmMonExeName);
  5659. if (NULL == CreateProcessU(szCmmon32Path, szCommandLine,
  5660. NULL, NULL, FALSE, 0,
  5661. NULL, NULL,
  5662. &StartupInfo, &ProcessInfo))
  5663. {
  5664. lRes = GetLastError();
  5665. CMTRACE2(TEXT("ConnectMonitor() CreateProcess() of %s failed, GLE=%u."),
  5666. c_pszCmMonExeName, lRes);
  5667. }
  5668. else
  5669. {
  5670. //
  5671. // Wait for event to be signaled, that CMMON is up
  5672. //
  5673. DWORD dwWait = WaitForSingleObject(hEvent, MAX_OBJECT_WAIT);
  5674. if (WAIT_OBJECT_0 != dwWait)
  5675. {
  5676. if (WAIT_TIMEOUT == dwWait)
  5677. {
  5678. lRes = ERROR_TIMEOUT;
  5679. }
  5680. else
  5681. {
  5682. lRes = GetLastError();
  5683. }
  5684. }
  5685. else
  5686. {
  5687. fMonReady = TRUE;
  5688. }
  5689. //
  5690. // Close Process handles. Note, we don't use these handles for
  5691. // duplicating handles in order to maintain a common code path
  5692. // regardless of whether CMMON was up already.
  5693. //
  5694. CloseHandle(ProcessInfo.hProcess);
  5695. CloseHandle(ProcessInfo.hThread);
  5696. }
  5697. CloseHandle(hEvent);
  5698. }
  5699. }
  5700. if (fMonReady)
  5701. {
  5702. //
  5703. // Get the hwnd for CMMON. Note: CMMON is expected to set
  5704. // the hwnd in the table before it signals the ready event.
  5705. //
  5706. if (FAILED(pArgs->pConnTable->GetMonitorWnd(&hwndMon)))
  5707. {
  5708. CMTRACE(TEXT("ConnectMonitor() - No Monitor HWND in table"));
  5709. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5710. }
  5711. //
  5712. // Make sure the HWND for CMMON is valid before trying to send data.
  5713. //
  5714. if (!IsWindow(hwndMon))
  5715. {
  5716. MSG msg;
  5717. HANDLE hHandle = GetCurrentProcess();
  5718. //
  5719. // Sometimes it takes a few ticks for us to get a positive response
  5720. // from IsWindow, so loop and pump messages while we are waiting.
  5721. //
  5722. while (hHandle && (MsgWaitForMultipleObjects(1, &hHandle, FALSE,
  5723. MAX_OBJECT_WAIT,
  5724. QS_ALLINPUT) == (WAIT_OBJECT_0 + 1)))
  5725. {
  5726. while (PeekMessageU(&msg, NULL, 0, 0, PM_REMOVE))
  5727. {
  5728. CMTRACE(TEXT("ConnectMonitor() - Waiting for IsWindow(hwndMon) - got Message"));
  5729. TranslateMessage(&msg);
  5730. DispatchMessageU(&msg);
  5731. }
  5732. //
  5733. // If the window is valid, we can go. Otherwise, keep pumping.
  5734. //
  5735. if (IsWindow(hwndMon))
  5736. {
  5737. break;
  5738. }
  5739. }
  5740. if (FALSE == IsWindow(hwndMon))
  5741. {
  5742. CMTRACE(TEXT("ConnectMonitor() - Monitor HWND in table is not valid"));
  5743. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5744. }
  5745. }
  5746. //
  5747. // Allocate buffer for CONNECTED_INFO, including extension for Watch Process list
  5748. //
  5749. DWORD dwWatchCount = GetWatchCount(pArgs);
  5750. DWORD dwDataSize = sizeof(CM_CONNECTED_INFO) + (dwWatchCount * sizeof(HANDLE));
  5751. LPCM_CONNECTED_INFO pInfo = (LPCM_CONNECTED_INFO) CmMalloc(dwDataSize);
  5752. //
  5753. // Allocate the COPYDATASTRUCT
  5754. //
  5755. COPYDATASTRUCT *pCopyData = (COPYDATASTRUCT*) CmMalloc(sizeof(COPYDATASTRUCT));
  5756. if (NULL == pInfo || NULL == pCopyData)
  5757. {
  5758. lRes = ERROR_NOT_ENOUGH_MEMORY;
  5759. }
  5760. else
  5761. {
  5762. //
  5763. // Fill in the CONNECTED_INFO
  5764. //
  5765. lstrcpyU(pInfo->szEntryName, pArgs->szServiceName);
  5766. lstrcpyU(pInfo->szProfilePath, pArgs->piniProfile->GetFile());
  5767. //
  5768. // Provide any password data that we have
  5769. //
  5770. // Due to security issues we are no longer allowed to keep password in memory.
  5771. //
  5772. //
  5773. // And the RAS phonebook
  5774. //
  5775. if (pArgs->pszRasPbk)
  5776. {
  5777. lstrcpynU(pInfo->szRasPhoneBook, pArgs->pszRasPbk,
  5778. sizeof(pInfo->szRasPhoneBook)/sizeof(pInfo->szRasPhoneBook[0]));
  5779. }
  5780. else
  5781. {
  5782. pInfo->szRasPhoneBook[0] = L'\0';
  5783. }
  5784. pInfo->dwCmFlags = pArgs->dwFlags;
  5785. //
  5786. // Need to know about global creds for Fast User Switching
  5787. //
  5788. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  5789. {
  5790. pInfo->dwCmFlags |= FL_GLOBALCREDS;
  5791. CMTRACE(TEXT("ConnectMonitor - we have globalcreds!!"));
  5792. }
  5793. //
  5794. // For W95, we must pass initial statistics data to CMMON
  5795. //
  5796. pInfo->dwInitBytesRecv = -1; // default to no stats
  5797. pInfo->dwInitBytesSend = -1; // default to no stats
  5798. if (pArgs->pConnStatistics)
  5799. {
  5800. //
  5801. // Get reg based stat data if available
  5802. //
  5803. if (pArgs->pConnStatistics->IsAvailable())
  5804. {
  5805. pInfo->dwInitBytesRecv = pArgs->pConnStatistics->GetInitBytesRead();
  5806. pInfo->dwInitBytesSend = pArgs->pConnStatistics->GetInitBytesWrite();
  5807. }
  5808. //
  5809. // Note: Adapter info is good, even if stats aren't available
  5810. //
  5811. pInfo->fDialup2 = pArgs->pConnStatistics->IsDialupTwo();
  5812. }
  5813. //
  5814. // Update the watch process list at the end of the CONNECTED_INFO struct
  5815. //
  5816. if (dwWatchCount)
  5817. {
  5818. if (FALSE == SetWatchHandles(pArgs->phWatchProcesses, &pInfo->ahWatchHandles[0], hwndMon))
  5819. {
  5820. pInfo->ahWatchHandles[0] = NULL;
  5821. }
  5822. }
  5823. //
  5824. // Send CONNECTED_INFO to CMMON
  5825. //
  5826. pCopyData->dwData = CMMON_CONNECTED_INFO;
  5827. pCopyData->cbData = dwDataSize;
  5828. pCopyData->lpData = (PVOID) pInfo;
  5829. SendMessageU(hwndMon, WM_COPYDATA, NULL, (LPARAM) pCopyData);
  5830. }
  5831. //
  5832. // Release allocations
  5833. //
  5834. if (pInfo)
  5835. {
  5836. CmFree(pInfo);
  5837. }
  5838. if (pCopyData)
  5839. {
  5840. CmFree(pCopyData);
  5841. }
  5842. }
  5843. return HRESULT_FROM_WIN32(lRes);
  5844. }
  5845. //+----------------------------------------------------------------------------
  5846. //
  5847. // Function: CreateConnTable
  5848. //
  5849. // Synopsis: Initializes our CConnectionTable ptr and creates a new ConnTable
  5850. // or opens an existing one as needed
  5851. //
  5852. // Arguments: ArgsStruct *pArgs - Ptr to global args struct containing.
  5853. //
  5854. // Returns: HRESULT - Failure code
  5855. //
  5856. // History: nickball Created 2/9/98
  5857. //
  5858. //+----------------------------------------------------------------------------
  5859. HRESULT CreateConnTable(ArgsStruct *pArgs)
  5860. {
  5861. HRESULT hrRet = E_FAIL;
  5862. pArgs->pConnTable = new CConnectionTable();
  5863. if (pArgs->pConnTable)
  5864. {
  5865. //
  5866. // We have our class, now create/open the connection table.
  5867. //
  5868. hrRet = pArgs->pConnTable->Open();
  5869. if (FAILED(hrRet))
  5870. {
  5871. hrRet = pArgs->pConnTable->Create();
  5872. if (HRESULT_CODE(hrRet) == ERROR_ALREADY_EXISTS)
  5873. {
  5874. CMTRACE1(TEXT("CreateConnTable -- ConnTable creation failed with error 0x%x. Strange since the Open failed too..."), hrRet);
  5875. }
  5876. else
  5877. {
  5878. CMTRACE1(TEXT("CreateConnTable -- ConnTable creation failed with error 0x%x"), hrRet);
  5879. }
  5880. }
  5881. }
  5882. else
  5883. {
  5884. hrRet = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  5885. }
  5886. MYDBGASSERT(SUCCEEDED(hrRet));
  5887. return hrRet;
  5888. }
  5889. #if 0 // NT 301988
  5890. /*
  5891. //+----------------------------------------------------------------------------
  5892. //
  5893. // Function: HandleMainConnectRequest
  5894. //
  5895. // Synopsis: Helper routine to handle the possibility that there may be a
  5896. // connect in progress on this service.
  5897. //
  5898. // Arguments: HWND hwndDlg - HWND of main dialog
  5899. // ArgsStruct *pArgs - Ptr to global Args struct
  5900. //
  5901. // Returns: BOOL - TRUE if we have fully handled the request
  5902. // and it is ok to terminate this instance.
  5903. //
  5904. // History: nickball Created 2/23/98
  5905. //
  5906. //+----------------------------------------------------------------------------
  5907. BOOL HandleMainConnectRequest(HWND hwndDlg, ArgsStruct *pArgs)
  5908. {
  5909. MYDBGASSERT(pArgs);
  5910. BOOL fResolved = FALSE;
  5911. LPCM_CONNECTION pConnection = GetConnection(pArgs);
  5912. //
  5913. // If no conection found, then there is no work to be done here, continue.
  5914. //
  5915. if (pConnection)
  5916. {
  5917. //
  5918. // If we are in any state besides RECONNECT, we can handle it here
  5919. //
  5920. if (CM_RECONNECTPROMPT != pConnection->CmState)
  5921. {
  5922. fResolved = TRUE;
  5923. if (pArgs->dwFlags & FL_DESKTOP)
  5924. {
  5925. //
  5926. // Caller is from the desktop, notify the user and we're done
  5927. //
  5928. NotifyUserOfExistingConnection(hwndDlg, pConnection, TRUE);
  5929. }
  5930. else
  5931. {
  5932. BOOL fSuccess = TRUE;
  5933. //
  5934. // We have a programmatic caller, if connected just bump the ref count
  5935. // and return successfully. Otherwise we return failure so that the
  5936. // caller doesn't erroneously believe that there is a connection.
  5937. //
  5938. if (CM_CONNECTED != pConnection->CmState)
  5939. {
  5940. fSuccess = FALSE;
  5941. }
  5942. else
  5943. {
  5944. UpdateTable(pArgs, CM_CONNECTING);
  5945. }
  5946. //
  5947. // Terminate this connect instance.
  5948. //
  5949. EndMainDialog(hwndDlg, pArgs, 0); // fSuccess);
  5950. }
  5951. }
  5952. else
  5953. {
  5954. //
  5955. // We're in reconnect mode and going to connect.
  5956. //
  5957. if (!(pArgs->dwFlags & FL_RECONNECT))
  5958. {
  5959. //
  5960. // This request is not a reconnect request from CMMON,
  5961. // make that sure the dialog is no longer displayed.
  5962. //
  5963. HangupNotifyCmMon(pArgs->pConnTable, pConnection->szEntry);
  5964. }
  5965. else
  5966. {
  5967. //
  5968. // We are handling a reconnect for CMMON, reduce the usage
  5969. // count so it is in sync when we begin connecting.
  5970. //
  5971. pArgs->pConnTable->RemoveEntry(pConnection->szEntry);
  5972. }
  5973. }
  5974. CmFree(pConnection);
  5975. }
  5976. return fResolved;
  5977. }
  5978. */
  5979. #endif
  5980. //
  5981. // OnMainConnect: Command Handler when user clicked on 'Connect' Button in
  5982. // Main Dialog Box
  5983. //
  5984. void OnMainConnect(HWND hwndDlg,
  5985. ArgsStruct *pArgs)
  5986. {
  5987. CM_SET_TIMING_INTERVAL("OnMainConnect - Begin");
  5988. //
  5989. // If we aren't ready to dial, set focus appropriately and bail
  5990. //
  5991. UINT nCtrlFocus;
  5992. if (FALSE == CheckConnect(hwndDlg, pArgs, &nCtrlFocus, !(pArgs->dwFlags & FL_UNATTENDED)))
  5993. {
  5994. MainSetDefaultButton(hwndDlg, nCtrlFocus);
  5995. SetFocus(GetDlgItem(hwndDlg, nCtrlFocus));
  5996. return;
  5997. }
  5998. (void) InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  5999. //
  6000. // Access Points - Disable AP combo box before connecting
  6001. //
  6002. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_STATIC),FALSE);
  6003. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_COMBO),FALSE);
  6004. //
  6005. // Store the current access point to reg.
  6006. //
  6007. if (pArgs->fAccessPointsEnabled)
  6008. {
  6009. WriteUserInfoToReg(pArgs, UD_ID_CURRENTACCESSPOINT, (PVOID)(pArgs->pszCurrentAccessPoint));
  6010. }
  6011. //
  6012. // Assume success unless something contradictory happens
  6013. //
  6014. pArgs->dwExitCode = ERROR_SUCCESS;
  6015. HCURSOR hPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  6016. LPTSTR pszMsg = CmFmtMsg(g_hInst, IDMSG_WORKING);
  6017. if (pszMsg)
  6018. {
  6019. SetDlgItemTextA(hwndDlg, IDC_MAIN_STATUS_DISPLAY, "");
  6020. AppendStatusPane(hwndDlg,pszMsg);
  6021. CmFree(pszMsg);
  6022. }
  6023. //
  6024. // We're connecting, update the table.
  6025. //
  6026. UpdateTable(pArgs, CM_CONNECTING);
  6027. //
  6028. // Clear out everything on the status panel
  6029. //
  6030. SetDlgItemTextA(hwndDlg, IDC_MAIN_STATUS_DISPLAY, "");
  6031. //
  6032. // Set the default button to Cancel
  6033. //
  6034. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDCANCEL, 0);
  6035. SetFocus(GetDlgItem(hwndDlg,IDCANCEL));
  6036. BOOL fSaveUPD = TRUE;
  6037. BOOL fSaveOtherUserInfo = TRUE;
  6038. //
  6039. // We want to save and/or delete credentials only when the user is logged on.
  6040. // This is taken care of by the functions that get called here. As long as
  6041. // the user is logged on, we try to mark, delete credentials and
  6042. // potentially resave credential info. From this level we shouldn't
  6043. // worry if we have the ras cred store or how the creds are really stored.
  6044. //
  6045. if (CM_LOGON_TYPE_USER == pArgs->dwWinLogonType)
  6046. {
  6047. //
  6048. // If this is NT4 or Win9X the GetAndStoreUserInfo takes care of storing
  6049. // the user info w/o the credential store.
  6050. //
  6051. if (OS_NT5)
  6052. {
  6053. //
  6054. // For Win2K+ we use the RAS API to save the credentials. The call saves
  6055. // and deletes user and global creds based on the current state and the
  6056. // user's choices (whether to save a password, etc.)
  6057. //
  6058. TryToDeleteAndSaveCredentials(pArgs, hwndDlg);
  6059. //
  6060. // Parameter to GetAndStoreUserInfo() - doesn't save Username, Password, Domain
  6061. //
  6062. fSaveUPD = FALSE;
  6063. }
  6064. }
  6065. else
  6066. {
  6067. //
  6068. // User isn't logged on, thus we don't want to save anything
  6069. //
  6070. fSaveUPD = FALSE;
  6071. fSaveOtherUserInfo = FALSE;
  6072. }
  6073. //
  6074. // Gets the userinfo from the edit boxes into the pArgs structure ans saves the other
  6075. // user flags. This is also saves the credentials on NT4 & Win 9x if the 3rd parameter is true
  6076. //
  6077. // 3rd parameter (fSaveUPD) - used to save Username, Domain, Password.
  6078. // 4th param (fSaveOtherUserInfo) - used to save user info flags. (remember password,
  6079. // dial automatically, etc.)
  6080. //
  6081. GetAndStoreUserInfo(pArgs, hwndDlg, fSaveUPD, fSaveOtherUserInfo);
  6082. //
  6083. // Vars for RAS
  6084. //
  6085. pArgs->nDialIdx = 0;
  6086. //
  6087. // Set our redial counter with the maximum. The max value is read
  6088. // in when we initialize the dialog. It is just a place holder
  6089. // nRedialCnt is the var used/modified to regulate the re-dial process.
  6090. //
  6091. pArgs->nRedialCnt = pArgs->nMaxRedials;
  6092. //
  6093. // Disable username controls before dialing
  6094. //
  6095. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_EDIT),FALSE);
  6096. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_STATIC),FALSE);
  6097. //
  6098. // Disable password controls before dialing
  6099. //
  6100. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_EDIT),FALSE);
  6101. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_STATIC),FALSE);
  6102. //
  6103. // Disable domain controls before dialing
  6104. //
  6105. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_EDIT),FALSE);
  6106. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_STATIC),FALSE);
  6107. //
  6108. // disable all other buttons
  6109. //
  6110. EnableWindow(GetDlgItem(hwndDlg,IDOK),FALSE);
  6111. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),FALSE);
  6112. if (pArgs->hwndResetPasswdButton)
  6113. {
  6114. EnableWindow(pArgs->hwndResetPasswdButton, FALSE);
  6115. }
  6116. if (!pArgs->fHideRememberPassword)
  6117. {
  6118. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  6119. if (pArgs->fGlobalCredentialsSupported)
  6120. {
  6121. //
  6122. // Also disable the option buttons
  6123. //
  6124. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  6125. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  6126. }
  6127. }
  6128. if (!pArgs->fHideDialAutomatically)
  6129. {
  6130. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  6131. }
  6132. //
  6133. // Try to check the Advanced Tab settings (ICF/ICS) and see if we need to enable or disable
  6134. // them based on what's configured in the .cms file. This is only on WinXP+ & if the user is logged in
  6135. //
  6136. VerifyAdvancedTabSettings(pArgs);
  6137. //
  6138. // Dial the number
  6139. //
  6140. DWORD dwResult = ERROR_SUCCESS;
  6141. pArgs->Log.Log(PRECONNECT_EVENT, pArgs->GetTypeOfConnection());
  6142. //
  6143. // Run the Pre-Connect actions
  6144. //
  6145. CActionList PreConnActList;
  6146. PreConnActList.Append(pArgs->piniService, c_pszCmSectionPreConnect);
  6147. if (!PreConnActList.RunAccordType(hwndDlg, pArgs))
  6148. {
  6149. //
  6150. // Connect action failed
  6151. //
  6152. UpdateTable(pArgs, CM_DISCONNECTED);
  6153. }
  6154. else
  6155. {
  6156. if (pArgs->IsDirectConnect())
  6157. {
  6158. MYDBGASSERT(pArgs->hrcRasConn == NULL);
  6159. pArgs->fUseTunneling = TRUE;
  6160. pArgs->psState = PS_TunnelDialing;
  6161. pArgs->dwStateStartTime = GetTickCount();
  6162. pArgs->nLastSecondsDisplay = (UINT) -1;
  6163. dwResult = DoTunnelDial(hwndDlg,pArgs);
  6164. }
  6165. else
  6166. {
  6167. //
  6168. // If the DynamicPhoneNumber flag is set, then we need to re-read
  6169. // the phoneinfo from the profile and make sure it re-munged.
  6170. //
  6171. BOOL bDynamicNum = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmDynamicPhoneNumber);
  6172. if (bDynamicNum)
  6173. {
  6174. LoadPhoneInfoFromProfile(pArgs);
  6175. }
  6176. //
  6177. // Load dial info(phone #'s, etc)
  6178. // In the auto-dial case we pass FALSE for fInstallModem so that
  6179. // LoadDialInfo does not try to install a modem because it would
  6180. // require user intervention
  6181. //
  6182. dwResult = LoadDialInfo(pArgs, hwndDlg, !(pArgs->dwFlags & FL_UNATTENDED), bDynamicNum);
  6183. if (dwResult == ERROR_SUCCESS)
  6184. {
  6185. dwResult = DoRasDial(hwndDlg,pArgs,pArgs->nDialIdx);
  6186. }
  6187. //
  6188. // If modem is not installed and LoadDialInfo failed to install modem, dwResult will be
  6189. // ERROR_PORT_NOT_AVAILABLE. Ideally, we should disable the connect button and display
  6190. // a different error message.
  6191. //
  6192. }
  6193. if (ERROR_SUCCESS != dwResult)
  6194. {
  6195. pArgs->dwExitCode = dwResult;
  6196. UpdateError(pArgs, dwResult);
  6197. }
  6198. }
  6199. if (ERROR_SUCCESS != dwResult)
  6200. {
  6201. HangupCM(pArgs, hwndDlg);
  6202. if (IsLogonAsSystem() && BAD_SCARD_PIN(dwResult))
  6203. {
  6204. //
  6205. // Disable the Connect button to avoid smartcard lockout. Also propagate
  6206. // the error back to our caller (RAS) so that they can End the 'choose
  6207. // connectoid' dialog and return to winlogon, where the user can enter
  6208. // the correct PIN.
  6209. //
  6210. pArgs->dwSCardErr = dwResult;
  6211. EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
  6212. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDCANCEL, 0);
  6213. SetFocus(GetDlgItem(hwndDlg, IDCANCEL));
  6214. }
  6215. SetLastError(dwResult);
  6216. }
  6217. SetCursor(hPrev);
  6218. CM_SET_TIMING_INTERVAL("OnMainConnect - End");
  6219. }
  6220. //+---------------------------------------------------------------------------
  6221. //
  6222. // Function: UseTunneling
  6223. //
  6224. // Synopsis: Check to see if we should do tunneling based on fTunnelPrimary
  6225. // and fTunnelReferences.
  6226. //
  6227. // Arguments: pArgs [the ArgStruct ptr]
  6228. // dwEntry [the phone index]
  6229. //
  6230. // Returns: TRUE if we tunnel, FALSE otherwise.
  6231. //
  6232. // History: henryt Created 3/5/97
  6233. //
  6234. //----------------------------------------------------------------------------
  6235. BOOL UseTunneling(
  6236. ArgsStruct *pArgs,
  6237. DWORD dwEntry
  6238. )
  6239. {
  6240. LPTSTR pszRefPhoneSource = NULL;
  6241. BOOL fPhoneNumIsFromPrimaryPBK;
  6242. LPTSTR pszTmp;
  6243. CIni iniTmp(pArgs->piniProfile->GetHInst(),pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  6244. BOOL fUseTunneling = FALSE;
  6245. //
  6246. // Set the read flags
  6247. //
  6248. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA)
  6249. {
  6250. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  6251. if (pszICSDataReg)
  6252. {
  6253. iniTmp.SetReadICSData(TRUE);
  6254. iniTmp.SetICSDataPath(pszICSDataReg);
  6255. }
  6256. CmFree(pszICSDataReg);
  6257. }
  6258. iniTmp.SetEntryFromIdx(dwEntry);
  6259. pszRefPhoneSource = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryPhoneSourcePrefix);
  6260. //
  6261. // If PhoneSource[0|1] is not empty, verify its existence
  6262. //
  6263. if (*pszRefPhoneSource)
  6264. {
  6265. //
  6266. // pszRefPhoneSource is either a relative or full path.
  6267. // CmConvertRelativePath() will do the conversion to a full path properly
  6268. //
  6269. pszTmp = CmConvertRelativePath(pArgs->piniService->GetFile(), pszRefPhoneSource);
  6270. if (!pszTmp || FALSE == FileExists(pszTmp))
  6271. {
  6272. CmFree(pszRefPhoneSource);
  6273. CmFree(pszTmp);
  6274. return fUseTunneling;
  6275. }
  6276. //
  6277. // Is the phone # from the primary(top level) phone book?
  6278. //
  6279. fPhoneNumIsFromPrimaryPBK = (lstrcmpiU(pszTmp, pArgs->piniService->GetFile()) == 0);
  6280. CmFree(pszTmp);
  6281. fUseTunneling =
  6282. ((fPhoneNumIsFromPrimaryPBK && pArgs->fTunnelPrimary) ||
  6283. (!fPhoneNumIsFromPrimaryPBK && pArgs->fTunnelReferences));
  6284. }
  6285. else
  6286. {
  6287. // the phone # is not from a phone book. the user probably typed it in
  6288. // him/herself.
  6289. fUseTunneling = pArgs->fTunnelPrimary;
  6290. }
  6291. CmFree(pszRefPhoneSource);
  6292. return fUseTunneling;
  6293. }
  6294. //
  6295. // OnMainProperties: command handler for 'Properties' button in the main dialog box
  6296. //
  6297. int OnMainProperties(HWND hwndDlg,
  6298. ArgsStruct *pArgs)
  6299. {
  6300. CMTRACE(TEXT("Begin OnMainProperties()"));
  6301. //
  6302. // do the settings dlg.
  6303. //
  6304. BOOL bCachedAccessPointsEnabled = pArgs->fAccessPointsEnabled;
  6305. int iRet = DoPropertiesPropSheets(hwndDlg, pArgs);
  6306. //
  6307. // We need to re-enumerate the access points and re-check connecting because
  6308. // the user may have added or deleted an access point and then hit cancel.
  6309. //
  6310. if (pArgs->hwndMainDlg)
  6311. {
  6312. if (bCachedAccessPointsEnabled != pArgs->fAccessPointsEnabled)
  6313. {
  6314. CMTRACE(TEXT("Access points state changed, returning to the main dialog which needs to relaunch itself with the proper template."));
  6315. iRet = ID_OK_RELAUNCH_MAIN_DLG;
  6316. }
  6317. else
  6318. {
  6319. //
  6320. // If the user canceled, then we want to set the accesspoint back to what it was on the main dialog
  6321. // since the user may have changed it on the properties dialog but then canceled.
  6322. //
  6323. if (pArgs->fAccessPointsEnabled)
  6324. {
  6325. if (0 == iRet) // user hit cancel
  6326. {
  6327. ChangedAccessPoint(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  6328. }
  6329. ShowAccessPointInfoFromReg(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  6330. }
  6331. UINT nCtrlFocus;
  6332. CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  6333. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  6334. SetFocus(GetDlgItem(hwndDlg,nCtrlFocus));
  6335. }
  6336. }
  6337. CMTRACE(TEXT("End OnMainProperties()"));
  6338. return iRet;
  6339. }
  6340. //
  6341. // user pressed the cancel button!!!!!
  6342. //
  6343. void OnMainCancel(HWND hwndDlg,
  6344. ArgsStruct *pArgs)
  6345. {
  6346. CMTRACE1(TEXT("OnMainCancel(), state is %d"), pArgs->psState);
  6347. //
  6348. // Re-entrancy protection. If we're in the middle of a RasDial, wait 2 seconds.
  6349. // If the "semaphore" is still held, exit. (This is only likely to happen during
  6350. // a stress situation, so failing the cancel is acceptable.)
  6351. //
  6352. LONG lInConnectOrCancel;
  6353. int SleepTimeInMilliseconds = 0;
  6354. do
  6355. {
  6356. lInConnectOrCancel = InterlockedExchange(&(pArgs->lInConnectOrCancel), IN_CONNECT_OR_CANCEL);
  6357. CMASSERTMSG(((NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel) || (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)),
  6358. TEXT("OnMainCancel - synch variable has unexpected value!"));
  6359. Sleep(50);
  6360. SleepTimeInMilliseconds += 50;
  6361. }
  6362. while ((IN_CONNECT_OR_CANCEL == lInConnectOrCancel) && (SleepTimeInMilliseconds < 2000));
  6363. if (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)
  6364. {
  6365. CMTRACE(TEXT("OnMainCancel - waited 2 seconds for system for InRasDial mutex to be freed, leaving Cancel"));
  6366. return;
  6367. }
  6368. //
  6369. // Terminate Lana
  6370. //
  6371. if (PS_TunnelDialing == pArgs->psState && pArgs->uLanaMsgId)
  6372. {
  6373. MYDBGASSERT(OS_W9X);
  6374. PostMessageU(hwndDlg, pArgs->uLanaMsgId, 0, 0);
  6375. }
  6376. if (pArgs->psState != PS_Interactive && pArgs->psState != PS_Error)
  6377. {
  6378. pArgs->Log.Log(ONCANCEL_EVENT);
  6379. //
  6380. // Run OnCancel connect actions. If we are dialing, this is a cancel
  6381. // dialing event. Note: The assumption here is CM never post itself
  6382. // an IDCANCEL message when dialing
  6383. //
  6384. CActionList OnCancelActList;
  6385. OnCancelActList.Append(pArgs->piniService, c_pszCmSectionOnCancel);
  6386. //
  6387. // fStatusMsgOnFailure = FALSE
  6388. //
  6389. OnCancelActList.RunAccordType(hwndDlg, pArgs, FALSE);
  6390. }
  6391. switch (pArgs->psState)
  6392. {
  6393. case PS_Dialing:
  6394. case PS_TunnelDialing:
  6395. case PS_Authenticating:
  6396. case PS_TunnelAuthenticating:
  6397. // fall through
  6398. case PS_Pausing:
  6399. //
  6400. // we should also try to hangup for ps_pausing since cm could be
  6401. // in the middle or redialing the tunnel server. we need to
  6402. // hangup the first ppp connection.
  6403. //
  6404. //
  6405. // Set fWaitForComplete to TRUE.
  6406. // This will cause HangupCM to block until the ras handle is invalid.
  6407. // Otherwise, HangupCM will return while the device is in use.
  6408. //
  6409. HangupCM(pArgs,hwndDlg, TRUE); // fWaitForComplete = TRUE
  6410. //
  6411. // Display cancelled message
  6412. //
  6413. AppendStatusPane(hwndDlg, IDMSG_CANCELED);
  6414. SetInteractive(hwndDlg,pArgs);
  6415. break;
  6416. case PS_Online:
  6417. //
  6418. // If pArgs->fUseTunneling is TRUE, CM actually does not have the PS_Online state
  6419. //
  6420. MYDBGASSERT(!pArgs->fUseTunneling);
  6421. if (pArgs->fUseTunneling)
  6422. {
  6423. break;
  6424. }
  6425. case PS_TunnelOnline:
  6426. {
  6427. TCHAR szTmp[MAX_PATH];
  6428. MYVERIFY(GetModuleFileNameU(g_hInst, szTmp, MAX_PATH));
  6429. pArgs->Log.Log(DISCONNECT_EVENT, szTmp);
  6430. CActionList DisconnectActList;
  6431. DisconnectActList.Append(pArgs->piniService, c_pszCmSectionOnDisconnect);
  6432. //
  6433. // fStatusMsgOnFailure = FALSE
  6434. //
  6435. DisconnectActList.RunAccordType(hwndDlg, pArgs, FALSE);
  6436. HangupCM(pArgs,hwndDlg);
  6437. pArgs->dwExitCode = ERROR_CANCELLED;
  6438. // fall through
  6439. }
  6440. case PS_Interactive:
  6441. //
  6442. // Set the error code to tell us the user cancelled and then fall through
  6443. //
  6444. pArgs->dwExitCode = ERROR_CANCELLED;
  6445. case PS_Error:
  6446. EndMainDialog(hwndDlg, pArgs, 0); // FALSE);
  6447. break;
  6448. default:
  6449. MYDBGASSERT(FALSE);
  6450. break;
  6451. }
  6452. //
  6453. // We're definitely not waiting for a callback anymore.
  6454. //
  6455. pArgs->fWaitingForCallback = FALSE;
  6456. //
  6457. // We are exiting Cancel state
  6458. //
  6459. (void)InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  6460. }
  6461. void OnMainEnChange(HWND hwndDlg,
  6462. ArgsStruct *pArgs)
  6463. {
  6464. CheckConnect(hwndDlg, pArgs, NULL);
  6465. }
  6466. //+----------------------------------------------------------------------------
  6467. //
  6468. // Function: OnRasErrorMessage
  6469. //
  6470. // Synopsis: Process RAS error message
  6471. //
  6472. // Arguments: HWND hwndDlg - Main Dialog window handle
  6473. // ArgsStruct *pArgs -
  6474. // DWORD dwError - RAS error code
  6475. //
  6476. // Returns: Nothing
  6477. //
  6478. // History: fengsun Created Header 10/24/97
  6479. //
  6480. //+----------------------------------------------------------------------------
  6481. void OnRasErrorMessage(HWND hwndDlg,
  6482. ArgsStruct *pArgs,
  6483. DWORD dwError)
  6484. {
  6485. //
  6486. // Save off whether we are tunneling, before we change state
  6487. //
  6488. BOOL bTunneling = IsDialingTunnel(pArgs);
  6489. //
  6490. // Set the progstate to Error if user did not cancel dialing.
  6491. // Note: Set here to ensure that we don't inadvertantly update the status on
  6492. // timer ticks thereby overwriting the error message. Additionally we do this
  6493. // following SetInteractive in the no-redial case below.
  6494. //
  6495. if (ERROR_CANCELLED != dwError)
  6496. {
  6497. CMTRACE(TEXT("OnRasErrorMessage - Entering PS_Error state"));
  6498. pArgs->psState = PS_Error;
  6499. }
  6500. //
  6501. // Set the "ErrorCode" property
  6502. //
  6503. pArgs->dwExitCode = dwError;
  6504. lstrcpyU(pArgs->szLastErrorSrc, TEXT("RAS"));
  6505. if (bTunneling && (OS_NT4 || OS_W9X) && IsSafeNetDevice(pArgs->szTunnelDeviceType, pArgs->szTunnelDeviceName))
  6506. {
  6507. //
  6508. // Okay, if we are using the SafeNet client we want to point the user to the
  6509. // SafeNet Log file. Let's get the path and log it out.
  6510. //
  6511. LPTSTR pszFullPathToSafeNetLog = GetPathToSafeNetLogFile();
  6512. if (pszFullPathToSafeNetLog)
  6513. {
  6514. pArgs->Log.Log(ONERROR_EVENT_W_SAFENET, pArgs->dwExitCode, pArgs->szLastErrorSrc, pszFullPathToSafeNetLog);
  6515. CmFree(pszFullPathToSafeNetLog);
  6516. pszFullPathToSafeNetLog = NULL;
  6517. }
  6518. }
  6519. else
  6520. {
  6521. //
  6522. // Otherwise just log the OnError event normally.
  6523. //
  6524. pArgs->Log.Log(ONERROR_EVENT, pArgs->dwExitCode, pArgs->szLastErrorSrc);
  6525. }
  6526. //
  6527. // Run On-Error connect actions
  6528. //
  6529. CActionList OnErrorActList;
  6530. OnErrorActList.Append(pArgs->piniService, c_pszCmSectionOnError);
  6531. //
  6532. // fStatusMsgOnFailure = FALSE
  6533. //
  6534. OnErrorActList.RunAccordType(hwndDlg, pArgs, FALSE, TRUE);
  6535. LPTSTR pszRasErrMsg = NULL;
  6536. //
  6537. // See if the error is recoverable (re-dialable)
  6538. // CheckConnectionError also display error msg in the status window
  6539. // Get the ras err msg also. we'll display it ourself.
  6540. //
  6541. BOOL bDoRedial = !CheckConnectionError(hwndDlg, dwError, pArgs, bTunneling, &pszRasErrMsg);
  6542. //
  6543. // Whether CM get ERROR_PORT_NOT_AVAILABLE because of modem change
  6544. //
  6545. BOOL fNewModem = FALSE;
  6546. if (dwError == ERROR_PORT_NOT_AVAILABLE && !IsDialingTunnel(pArgs))
  6547. {
  6548. //
  6549. // Modem is not avaliable. See if the modem is changed
  6550. //
  6551. BOOL fSameModem = TRUE;
  6552. if (PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName, &fSameModem))
  6553. {
  6554. if (!fSameModem)
  6555. {
  6556. //
  6557. // If the modem is changed, use the new modem.
  6558. // bDoRedial is still FALSE here so we will not
  6559. // increase redial count or use the backup number
  6560. //
  6561. fNewModem = TRUE;
  6562. }
  6563. }
  6564. //
  6565. // if PickModem failed, do not try to install modem here
  6566. // cnetcfg return ERROR_CANCELLED, even if modem is intalled
  6567. //
  6568. }
  6569. //
  6570. // should we try another tunnel dns addr?
  6571. //
  6572. BOOL fTryAnotherTunnelDnsAddr = FALSE;
  6573. if (bDoRedial)
  6574. {
  6575. //
  6576. // The error is recoverable
  6577. //
  6578. CMTRACE1(TEXT("OnRasErrorMessage - Recoverable error %u received."), dwError);
  6579. //
  6580. // If we're dialing a tunnel, try a different IP address on failure.
  6581. //
  6582. if (PS_TunnelDialing == pArgs->psState)
  6583. {
  6584. fTryAnotherTunnelDnsAddr = TryAnotherTunnelDnsAddress(pArgs);
  6585. }
  6586. //
  6587. // If we're trying a different IP, then don't count this as a normal
  6588. // redial. Otherwise, bump the indices and move on to the next number.
  6589. if (!fTryAnotherTunnelDnsAddr)
  6590. {
  6591. //
  6592. // we display the ras error only if:
  6593. // (1) we're not redialing OR
  6594. // (2) we're not redialing a tunnel OR
  6595. // (3) we're redialing a tunnel but NOT redialing with a different
  6596. // tunnel dns ip addr.
  6597. //
  6598. if (pszRasErrMsg)
  6599. {
  6600. AppendStatusPane(hwndDlg, pszRasErrMsg);
  6601. }
  6602. // should we redial?
  6603. //
  6604. if (pArgs->nRedialCnt)
  6605. {
  6606. //
  6607. // We get an error message from RAS each time we dial (modem, vpn, ISDN). In case of
  6608. // dual channel ISDN we get two notification (one per channel), and we need to ignore
  6609. // one of them. Here we chose to ignore the 2nd one. Thus we want to change the
  6610. // redial count and change the dial index only if this is NOT the 2nd RasSubEntry
  6611. // in case of dual channel ISDN.
  6612. //
  6613. if (FALSE == ((CM_ISDN_MODE_DUALCHANNEL_FALLBACK == pArgs->dwIsdnDialMode ||
  6614. CM_ISDN_MODE_DUALCHANNEL_ONLY == pArgs->dwIsdnDialMode) &&
  6615. 2 == pArgs->dwRasSubEntry))
  6616. {
  6617. //
  6618. // We have not reached the retry limit, try to redial
  6619. //
  6620. pArgs->nRedialCnt--;
  6621. pArgs->nDialIdx++;
  6622. }
  6623. //
  6624. // If ndx now matches count, or if the next number is empty
  6625. // (not dialable) this our last number to dial on this pass.
  6626. // Adjust the re-dial counter if it applies.
  6627. //
  6628. if (pArgs->nDialIdx == MAX_PHONE_NUMBERS ||
  6629. !pArgs->aDialInfo[pArgs->nDialIdx].szDialablePhoneNumber[0])
  6630. {
  6631. pArgs->nDialIdx = 0;
  6632. }
  6633. }
  6634. else
  6635. {
  6636. //
  6637. // Last redial try failed
  6638. //
  6639. bDoRedial = FALSE;
  6640. }
  6641. }
  6642. }
  6643. else
  6644. {
  6645. CMTRACE1(TEXT("OnRasErrorMessage - Non-recoverable error %u received."), dwError);
  6646. //
  6647. // we display the ras error only if:
  6648. // (1) we're not redialing OR
  6649. // (2) we're not redialing a tunnel OR
  6650. // (3) we're redialing a tunnel but NOT redialing with a different
  6651. // tunnel dns ip addr.
  6652. //
  6653. if (pszRasErrMsg)
  6654. {
  6655. AppendStatusPane(hwndDlg, pszRasErrMsg);
  6656. }
  6657. }
  6658. bDoRedial |= fNewModem; // fNewModem only true if not dialing tunnel
  6659. //
  6660. // Perform Hangup here
  6661. //
  6662. if (IsDialingTunnel(pArgs) && bDoRedial)
  6663. {
  6664. //
  6665. // For tunnel dialing, only hangup tunnel connection, Do not hangup
  6666. // PPP connection before retry.
  6667. //
  6668. MyRasHangup(pArgs,pArgs->hrcTunnelConn);
  6669. pArgs->hrcTunnelConn = NULL;
  6670. if (pArgs->IsDirectConnect())
  6671. {
  6672. //
  6673. // The statistic is stopped in HangupCM
  6674. // Since we do not call HangupCM, we have to close it here
  6675. //
  6676. if (pArgs->pConnStatistics)
  6677. {
  6678. pArgs->pConnStatistics->Close();
  6679. }
  6680. }
  6681. }
  6682. else
  6683. {
  6684. if (OS_NT)
  6685. {
  6686. HangupCM(pArgs, hwndDlg, FALSE, !bDoRedial);
  6687. }
  6688. else
  6689. {
  6690. //
  6691. // On win9x, in some PPP case, when CM get Tunnel RAS error message,
  6692. // RasHangup will not release the PPP RAS handle until this
  6693. // message returns. See bug 39718
  6694. //
  6695. PostMessageU(hwndDlg, WM_HANGUP_CM, !bDoRedial, dwError);
  6696. }
  6697. }
  6698. //
  6699. // If we want re-dial enter pause state, otherwise just SetInteractive
  6700. //
  6701. if (bDoRedial)
  6702. {
  6703. //
  6704. // If the state is PS_Error, we will use the timer we set before the call.
  6705. // However we will not check whether the timer expired here.
  6706. //
  6707. if (fTryAnotherTunnelDnsAddr)
  6708. {
  6709. //
  6710. // if we want to try another tunnel dns addr, we don't want to display
  6711. // any error msg or pause, just retry with another addr without the
  6712. // user realizing it.
  6713. //
  6714. pArgs->dwStateStartTime = GetTickCount() + (pArgs->nRedialDelay * 1000);
  6715. }
  6716. else
  6717. {
  6718. //
  6719. // NT #360488 - nickball
  6720. //
  6721. // Reset the timer so that we pause for the redial delay before
  6722. // trying to connect again. ErrorEx (now unused), conditioned this
  6723. // code on the error state not being PS_Error, however, this was
  6724. // broken when we started setting the state to PS_Error at the
  6725. // beginning of this function. Because ErrorEx is not longer used,
  6726. // we can restore the timer reset to all states.
  6727. //
  6728. pArgs->dwStateStartTime = GetTickCount();
  6729. pArgs->nLastSecondsDisplay = (UINT) -1;
  6730. }
  6731. pArgs->psState = PS_Pausing;
  6732. }
  6733. else
  6734. {
  6735. SetInteractive(hwndDlg,pArgs);
  6736. if (ERROR_CANCELLED != dwError)
  6737. {
  6738. CMTRACE(TEXT("OnRasErrorMessage - Restoring PS_Error state"));
  6739. pArgs->psState = PS_Error;
  6740. }
  6741. pArgs->dwExitCode = dwError;
  6742. // in 'unattended dial' mode, exit ICM
  6743. if (pArgs->dwFlags & FL_UNATTENDED)
  6744. {
  6745. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL, dwError);
  6746. }
  6747. }
  6748. if (pszRasErrMsg)
  6749. {
  6750. CmFree(pszRasErrMsg);
  6751. }
  6752. }
  6753. //+----------------------------------------------------------------------------
  6754. //
  6755. // Function: OnRasNotificationMessage
  6756. //
  6757. // Synopsis: Message handler for RAS status/error messages.
  6758. //
  6759. // Arguments: HWND hwndDlg - Main Dialog window handle
  6760. // ArgsStruct *pArgs - Ptr to global Args struct
  6761. // WPARAM wParam - RAS status message
  6762. // LPARAM lParam - RAS error message. ERROR_SUCCESS if none.
  6763. //
  6764. // Returns: Error code if applicable.
  6765. //
  6766. // History: nickball Created Header 05/19/99
  6767. //
  6768. //+----------------------------------------------------------------------------
  6769. DWORD OnRasNotificationMessage(HWND hwndDlg,
  6770. ArgsStruct *pArgs,
  6771. WPARAM wParam,
  6772. LPARAM lParam)
  6773. {
  6774. static BOOL bFirstChannelConnected = -1; // set it to neither connected nor failed
  6775. static BOOL bSecondChannelConnected = -1; // set it to neither connected nor failed
  6776. CMTRACE2(TEXT("OnRasNotificationMessage() wParam=%u, lParam=%u"), wParam, lParam);
  6777. if (pArgs->fIgnoreTimerRasMsg)
  6778. {
  6779. CMTRACE(TEXT("OnRasNotificationMessage() ignoring Ras and Timer messages"));
  6780. return ERROR_SUCCESS;
  6781. }
  6782. //
  6783. // If we have an error notification from RAS, handle it.
  6784. //
  6785. if (ERROR_SUCCESS != lParam)
  6786. {
  6787. //
  6788. // If one of the subchannels on multilinked ISDN fails, default to single channel if we are configured to do so.
  6789. //
  6790. if (OS_NT5)
  6791. {
  6792. if (CM_ISDN_MODE_DUALCHANNEL_FALLBACK == pArgs->dwIsdnDialMode)
  6793. {
  6794. //
  6795. // If we are in here then we are doing ISDN dual channel with fallback mode and one of the channels failed.
  6796. // Since we are in fallback mode, it is okay to continue with only one. If the other channel has already
  6797. // connected then go ahead and post the connect message. If not, then it will be handled below in the
  6798. // RASCS_SubEntryConnected processing. Note that RAS doesn't send a RASCS_Connected notification in this case.
  6799. //
  6800. if (1 == pArgs->dwRasSubEntry)
  6801. {
  6802. bFirstChannelConnected = FALSE;
  6803. }
  6804. else if (2 == pArgs->dwRasSubEntry)
  6805. {
  6806. bSecondChannelConnected = FALSE;
  6807. }
  6808. else
  6809. {
  6810. CMASSERTMSG(FALSE, TEXT("OnRasNotificationMessage -- error on unknown subentry."));
  6811. }
  6812. //
  6813. // If one of the channels connected already, go ahead and post the connect message.
  6814. //
  6815. if ((TRUE == bFirstChannelConnected) || (TRUE == bSecondChannelConnected))
  6816. {
  6817. CMTRACE(TEXT("Sending WM_CONNECTED_CM -- one entry succeeded and one failed."));
  6818. PostMessageU(hwndDlg, WM_CONNECTED_CM, 0, 0);
  6819. return ERROR_SUCCESS;
  6820. }
  6821. }
  6822. }
  6823. //
  6824. // Skip PENDING notifications
  6825. //
  6826. if (PENDING == lParam)
  6827. {
  6828. CMTRACE(TEXT("OnRasNotificationMessage() Skipping PENDING notification."));
  6829. return ERROR_SUCCESS;
  6830. }
  6831. //
  6832. // If we're already in the interactive or error state, then
  6833. // ignore any subsequent error notifications from RAS.
  6834. //
  6835. // For example: RAS often sends a ERROR_USER_DISCONNECTION
  6836. // notification when we call RasHangup.
  6837. //
  6838. if (pArgs->psState == PS_Interactive || pArgs->psState == PS_Error)
  6839. {
  6840. CMTRACE1(TEXT("OnRasNotificationMessage() Ignoring error because pArgs->psState is %u."), pArgs->psState);
  6841. return ERROR_SUCCESS;
  6842. }
  6843. CMTRACE(TEXT("OnRasNotificationMessage() Handling error message."));
  6844. OnRasErrorMessage(hwndDlg, pArgs, (DWORD)lParam);
  6845. }
  6846. else
  6847. {
  6848. // We have a RAS status update, act accordingly
  6849. switch (wParam)
  6850. {
  6851. case RASCS_OpenPort:
  6852. {
  6853. if (OS_NT5 || OS_MIL)
  6854. {
  6855. //
  6856. // Make sure to init the ISDN fallback mode vars just in case
  6857. // the state machine is cancelled in the middle somewhere. We
  6858. // want the next call to have the correct values for these vars.
  6859. //
  6860. if (1 == pArgs->dwRasSubEntry)
  6861. {
  6862. bFirstChannelConnected = -1;
  6863. }
  6864. else if (2 == pArgs->dwRasSubEntry)
  6865. {
  6866. bSecondChannelConnected = -1;
  6867. }
  6868. }
  6869. }
  6870. break;
  6871. case RASCS_Authenticate:
  6872. {
  6873. //
  6874. // Win9x often sends two RASCS_Authenticate messages a few seconds apart. This has the disconcerting
  6875. // effect of restarting the authenticating timer that the user sees. Thus, we now don't reset the time if
  6876. // we are already in the PS_XXX state that we are going to be setting.
  6877. //
  6878. BOOL bResetAuthTime = FALSE;
  6879. CMTRACE(TEXT("RASCS_Authenticate"));
  6880. if (IsDialingTunnel(pArgs)) // PPTP dialing
  6881. {
  6882. if (PS_TunnelAuthenticating != pArgs->psState)
  6883. {
  6884. bResetAuthTime = TRUE;
  6885. }
  6886. pArgs->psState = PS_TunnelAuthenticating;
  6887. }
  6888. else
  6889. {
  6890. if (PS_Authenticating != pArgs->psState)
  6891. {
  6892. bResetAuthTime = TRUE;
  6893. }
  6894. pArgs->psState = PS_Authenticating;
  6895. }
  6896. if (bResetAuthTime)
  6897. {
  6898. pArgs->dwStateStartTime = GetTickCount();
  6899. pArgs->nLastSecondsDisplay = (UINT) -1;
  6900. }
  6901. }
  6902. break;
  6903. case RASCS_SubEntryConnected:
  6904. {
  6905. //
  6906. // Special handling for the ISDN dual channel case when we are in fallback mode. Since
  6907. // RAS doesn't send us a RASCS_Connected notification if some of the channels fail but
  6908. // not all of them, we must keep track of what happened on the two channels and react
  6909. // accordingly.
  6910. //
  6911. if (OS_NT5)
  6912. {
  6913. if (CM_ISDN_MODE_DUALCHANNEL_FALLBACK == pArgs->dwIsdnDialMode)
  6914. {
  6915. if (1 == pArgs->dwRasSubEntry)
  6916. {
  6917. bFirstChannelConnected = TRUE;
  6918. }
  6919. else if (2 == pArgs->dwRasSubEntry)
  6920. {
  6921. bSecondChannelConnected = TRUE;
  6922. }
  6923. else
  6924. {
  6925. CMASSERTMSG(FALSE, TEXT("OnRasNotificationMessage -- error on unknown subentry. (RASCS_SubEntryConnected)"));
  6926. }
  6927. //
  6928. // If one of the channels failed already, go ahead and post the connect message.
  6929. // Otherwise we will wait for the RASCS_Connected.
  6930. //
  6931. if ((TRUE == bFirstChannelConnected) && (FALSE == bSecondChannelConnected) ||
  6932. (FALSE == bFirstChannelConnected) && (TRUE == bSecondChannelConnected))
  6933. {
  6934. CMTRACE(TEXT("Sending WM_CONNECTED_CM -- one entry succeeded and one failed."));
  6935. PostMessageU(hwndDlg, WM_CONNECTED_CM, 0, 0);
  6936. return ERROR_SUCCESS;
  6937. }
  6938. }
  6939. }
  6940. }
  6941. break;
  6942. case RASCS_Connected:
  6943. {
  6944. CMTRACE(TEXT("RASCS_Connected"));
  6945. //
  6946. // Post a message to ourselves to indicate that we are connected
  6947. //
  6948. PostMessageU(hwndDlg, WM_CONNECTED_CM,0,0);
  6949. break;
  6950. }
  6951. //
  6952. // Pause states are dealt with explicity below
  6953. //
  6954. case (RASCS_PAUSED + 4): // 4100 - RASCS_InvokeEapUI
  6955. case RASCS_Interactive:
  6956. case RASCS_RetryAuthentication:
  6957. case RASCS_CallbackSetByCaller:
  6958. case RASCS_PasswordExpired:
  6959. break;
  6960. //
  6961. // Callback handling states
  6962. //
  6963. case RASCS_PrepareForCallback:
  6964. pArgs->fWaitingForCallback = TRUE;
  6965. pArgs->psState = PS_Pausing;
  6966. break;
  6967. case RASCS_CallbackComplete:
  6968. pArgs->fWaitingForCallback = FALSE;
  6969. break;
  6970. //
  6971. // The following status codes are not handled explicitly
  6972. //
  6973. case RASCS_Disconnected:
  6974. break;
  6975. case RASCS_SubEntryDisconnected:
  6976. break;
  6977. case RASCS_PortOpened:
  6978. break;
  6979. case RASCS_ConnectDevice:
  6980. break;
  6981. case RASCS_DeviceConnected:
  6982. break;
  6983. case RASCS_AllDevicesConnected:
  6984. break;
  6985. case RASCS_AuthNotify:
  6986. break;
  6987. case RASCS_AuthRetry:
  6988. break;
  6989. case RASCS_AuthCallback:
  6990. break;
  6991. case RASCS_AuthChangePassword:
  6992. break;
  6993. case RASCS_AuthProject:
  6994. break;
  6995. case RASCS_AuthLinkSpeed:
  6996. break;
  6997. case RASCS_AuthAck:
  6998. break;
  6999. case RASCS_ReAuthenticate:
  7000. break;
  7001. case RASCS_Authenticated:
  7002. break;
  7003. case RASCS_WaitForModemReset:
  7004. break;
  7005. case RASCS_WaitForCallback:
  7006. break;
  7007. case RASCS_Projected:
  7008. break;
  7009. case RASCS_StartAuthentication:
  7010. break;
  7011. case RASCS_LogonNetwork:
  7012. break;
  7013. default:
  7014. CMTRACE(TEXT("OnRasNotificationMessage() - message defaulted"));
  7015. break;
  7016. }
  7017. }
  7018. if (wParam & RASCS_PAUSED)
  7019. {
  7020. //
  7021. // Screen out unsupported states
  7022. //
  7023. switch (wParam)
  7024. {
  7025. case RASCS_Interactive: // for scripts -- NTRAID 378224
  7026. case (RASCS_PAUSED + 4): // 4100 - RASCS_InvokeEapUI
  7027. case RASCS_PasswordExpired:
  7028. case RASCS_RetryAuthentication:
  7029. case RASCS_CallbackSetByCaller:
  7030. PostMessageU(hwndDlg, WM_PAUSE_RASDIAL, wParam, lParam);
  7031. break;
  7032. default:
  7033. MYDBGASSERT(FALSE);
  7034. return (ERROR_INTERACTIVE_MODE); // unhandled pause state
  7035. }
  7036. }
  7037. return ERROR_SUCCESS;
  7038. }
  7039. // timer: check the current connection manager status, update the status message
  7040. // on the screen
  7041. void OnMainTimer(HWND hwndDlg,
  7042. ArgsStruct *pArgs)
  7043. {
  7044. //
  7045. // If timer ID is null, don't process messages
  7046. //
  7047. if (NULL == pArgs->nTimerId)
  7048. {
  7049. return;
  7050. }
  7051. //
  7052. // Timer is good, check StartupInfoLoad
  7053. //
  7054. LPTSTR pszMsg = NULL;
  7055. DWORD dwSeconds = (GetTickCount() - pArgs->dwStateStartTime) / 1000;
  7056. CheckStartupInfo(hwndDlg, pArgs);
  7057. // CMTRACE1(TEXT("OnMainTimer() pArgs->psState is %u"), pArgs->psState);
  7058. //
  7059. // Update future splash if any
  7060. //
  7061. MapStateToFrame(pArgs);
  7062. switch (pArgs->psState)
  7063. {
  7064. case PS_Dialing:
  7065. if (pArgs->nLastSecondsDisplay != dwSeconds)
  7066. {
  7067. pszMsg = CmFmtMsg(g_hInst,
  7068. IDMSG_DIALING,
  7069. pArgs->aDialInfo[pArgs->nDialIdx].szDisplayablePhoneNumber,
  7070. pArgs->szDeviceName,
  7071. dwSeconds);
  7072. //
  7073. // Clear the status window
  7074. //
  7075. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7076. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7077. }
  7078. break;
  7079. case PS_TunnelDialing:
  7080. if (pArgs->nLastSecondsDisplay != dwSeconds)
  7081. {
  7082. pszMsg = CmFmtMsg(g_hInst,
  7083. IDMSG_TUNNELDIALING,
  7084. pArgs->GetTunnelAddress(),
  7085. dwSeconds);
  7086. //
  7087. // Clear the status window
  7088. //
  7089. SetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7090. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7091. }
  7092. break;
  7093. case PS_Pausing:
  7094. //
  7095. // Special case of pausing is when we're waiting for the server to call us back.
  7096. //
  7097. if (pArgs->fWaitingForCallback)
  7098. {
  7099. //
  7100. // Notify the user of this fact
  7101. //
  7102. pszMsg = CmFmtMsg(g_hInst,
  7103. IDMSG_WAITING_FOR_CALLBACK,
  7104. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  7105. //
  7106. // Clear the status window
  7107. //
  7108. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7109. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7110. break;
  7111. }
  7112. if (GetTickCount()-pArgs->dwStateStartTime <= pArgs->nRedialDelay * 1000)
  7113. {
  7114. //
  7115. // Update the display if not timeout
  7116. //
  7117. if (pArgs->nLastSecondsDisplay != dwSeconds)
  7118. {
  7119. pszMsg = CmFmtMsg(g_hInst,IDMSG_PAUSING,dwSeconds);
  7120. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7121. }
  7122. }
  7123. else
  7124. {
  7125. DWORD dwRes;
  7126. if (pArgs->IsDirectConnect() || pArgs->hrcRasConn != NULL)
  7127. {
  7128. //
  7129. // For the first tunnel try, CM does not hangup ppp connection
  7130. //
  7131. MYDBGASSERT(pArgs->fUseTunneling);
  7132. pArgs->psState = PS_TunnelDialing;
  7133. pArgs->dwStateStartTime = GetTickCount();
  7134. pArgs->nLastSecondsDisplay = (UINT) -1;
  7135. dwRes = DoTunnelDial(hwndDlg,pArgs);
  7136. //
  7137. // Update the status right away because there are times
  7138. // that things happen so quickly that the main status
  7139. // display doesn't have a chance to display the tunnel
  7140. // dialing info...
  7141. //
  7142. pszMsg = CmFmtMsg(g_hInst,
  7143. IDMSG_TUNNELDIALING,
  7144. pArgs->GetTunnelAddress(),
  7145. 0);
  7146. //
  7147. // Clear the status window
  7148. //
  7149. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7150. }
  7151. else
  7152. {
  7153. dwRes = DoRasDial(hwndDlg,pArgs,pArgs->nDialIdx);
  7154. }
  7155. if (dwRes == ERROR_SUCCESS)
  7156. {
  7157. MapStateToFrame(pArgs);
  7158. pArgs->dwStateStartTime = GetTickCount();
  7159. pArgs->nLastSecondsDisplay = (UINT) -1;
  7160. }
  7161. else
  7162. {
  7163. HangupCM(pArgs, hwndDlg);
  7164. UpdateError(pArgs, dwRes);
  7165. SetLastError(dwRes);
  7166. }
  7167. }
  7168. break;
  7169. case PS_Authenticating:
  7170. if (pArgs->nLastSecondsDisplay != dwSeconds)
  7171. {
  7172. //
  7173. // Get the appropriate username based on whether we're
  7174. // tunneling and using the same credentials for dial-up.
  7175. //
  7176. LPTSTR pszTmpUserName;
  7177. if (pArgs->fUseTunneling && (!pArgs->fUseSameUserName))
  7178. {
  7179. pszTmpUserName = pArgs->szInetUserName;
  7180. }
  7181. else
  7182. {
  7183. pszTmpUserName = pArgs->szUserName;
  7184. }
  7185. //
  7186. // If username is still blank, use the RasDialParams as a
  7187. // backup. This can occur in cases such as EAP
  7188. //
  7189. if (TEXT('\0') == *pszTmpUserName)
  7190. {
  7191. pszTmpUserName = pArgs->pRasDialParams->szUserName;
  7192. }
  7193. pszMsg = CmFmtMsg(g_hInst,
  7194. IDMSG_CHECKINGPASSWORD,
  7195. pszTmpUserName,
  7196. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  7197. //
  7198. // Clear the status window
  7199. //
  7200. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7201. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7202. }
  7203. break;
  7204. case PS_TunnelAuthenticating:
  7205. if (pArgs->nLastSecondsDisplay != dwSeconds)
  7206. {
  7207. LPTSTR pszTmpUserName = pArgs->szUserName;
  7208. //
  7209. // If username is still blank, use the RasDialParams as a
  7210. // backup. This can occur in cases such as EAP
  7211. //
  7212. if (TEXT('\0') == *pszTmpUserName)
  7213. {
  7214. pszTmpUserName = pArgs->pRasDialParams->szUserName;
  7215. }
  7216. pszMsg = CmFmtMsg(g_hInst,
  7217. IDMSG_CHECKINGPASSWORD,
  7218. pszTmpUserName,
  7219. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  7220. //
  7221. // Clear the status window
  7222. //
  7223. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  7224. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  7225. }
  7226. break;
  7227. case PS_Online:
  7228. //
  7229. // If pArgs->fUseTunneling is TRUE, CM actually does not have the PS_Online state
  7230. //
  7231. MYDBGASSERT(!pArgs->fUseTunneling);
  7232. case PS_TunnelOnline:
  7233. //
  7234. // The dialog should be ended by now
  7235. //
  7236. MYDBGASSERT(!"The dialog should be ended by now");
  7237. break;
  7238. case PS_Error:
  7239. case PS_Interactive:
  7240. default:
  7241. break;
  7242. }
  7243. // If we have a status message as a result of the above, display it
  7244. if (pszMsg)
  7245. {
  7246. AppendStatusPane(hwndDlg,pszMsg);
  7247. CmFree(pszMsg);
  7248. }
  7249. }
  7250. //
  7251. // MainDlgProc: main dialog box message processing function
  7252. //
  7253. INT_PTR CALLBACK MainDlgProc(HWND hwndDlg,
  7254. UINT uMsg,
  7255. WPARAM wParam,
  7256. LPARAM lParam)
  7257. {
  7258. ArgsStruct *pArgs = (ArgsStruct *) GetWindowLongU(hwndDlg,DWLP_USER);
  7259. static const DWORD adwHelp[] = {IDC_MAIN_NOPROMPT_CHECKBOX, IDH_LOGON_AUTOCONN,
  7260. IDC_MAIN_NOPASSWORD_CHECKBOX, IDH_LOGON_SAVEPW,
  7261. IDC_MAIN_USERNAME_STATIC,IDH_LOGON_NAME,
  7262. IDC_MAIN_USERNAME_EDIT,IDH_LOGON_NAME,
  7263. IDC_MAIN_PASSWORD_STATIC,IDH_LOGON_PSWD,
  7264. IDC_MAIN_PASSWORD_EDIT,IDH_LOGON_PSWD,
  7265. IDC_MAIN_DOMAIN_STATIC, IDH_LOGON_DOMAIN,
  7266. IDC_MAIN_DOMAIN_EDIT, IDH_LOGON_DOMAIN,
  7267. IDC_MAIN_RESET_PASSWORD, IDH_LOGON_NEW,
  7268. IDC_MAIN_MESSAGE_DISPLAY,IDH_LOGON_SVCMSG,
  7269. IDC_MAIN_STATUS_LABEL,IDH_LOGON_CONNECT_STAT,
  7270. IDC_MAIN_STATUS_DISPLAY,IDH_LOGON_CONNECT_STAT,
  7271. IDOK,IDH_LOGON_CONNECT,
  7272. IDCANCEL,IDH_LOGON_CANCEL,
  7273. IDC_MAIN_PROPERTIES_BUTTON,IDH_LOGON_PROPERTIES,
  7274. IDC_MAIN_HELP_BUTTON,IDH_CMHELP,
  7275. IDC_MAIN_ACCESSPOINT_COMBO, IDH_LOGON_ACCESSPOINTS,
  7276. IDC_MAIN_ACCESSPOINT_STATIC, IDH_LOGON_ACCESSPOINTS,
  7277. IDC_OPT_CREDS_SINGLE_USER, IDH_LOGON_SAVEFORME,
  7278. IDC_OPT_CREDS_ALL_USER, IDH_LOGON_SAVEFORALL,
  7279. 0,0};
  7280. //
  7281. // Dialog box message processing
  7282. //
  7283. switch (uMsg)
  7284. {
  7285. case WM_PAINT:
  7286. CheckStartupInfo(hwndDlg, pArgs);
  7287. break;
  7288. case WM_INITDIALOG:
  7289. CM_SET_TIMING_INTERVAL("WM_INITDIALOG - Begin");
  7290. UpdateFont(hwndDlg);
  7291. //
  7292. // Extract args and perform main initialization
  7293. //
  7294. pArgs = (ArgsStruct *) lParam;
  7295. if (pArgs)
  7296. {
  7297. pArgs->hwndMainDlg = hwndDlg;
  7298. }
  7299. SetWindowLongU(hwndDlg,DWLP_USER, (LONG_PTR) pArgs);
  7300. OnMainInit(hwndDlg, pArgs);
  7301. CM_SET_TIMING_INTERVAL("WM_INITDIALOG - End");
  7302. return (FALSE);
  7303. case WM_ENDSESSION:
  7304. //
  7305. // Windows system is shutting down or logging off
  7306. //
  7307. if ((BOOL)wParam == TRUE)
  7308. {
  7309. //
  7310. // Just cancel
  7311. //
  7312. OnMainCancel(hwndDlg, pArgs);
  7313. }
  7314. return 0;
  7315. case WM_COMMAND:
  7316. switch (LOWORD(wParam))
  7317. {
  7318. case IDOK:
  7319. OnMainConnect(hwndDlg,pArgs);
  7320. //
  7321. // Check if there is an error, and if it's unattended dial,
  7322. // we just exit silently -- byao 5/9/97
  7323. //
  7324. if ((PS_Interactive == pArgs->psState || PS_Error == pArgs->psState) &&
  7325. (pArgs->dwFlags & FL_UNATTENDED))
  7326. {
  7327. OnMainCancel(hwndDlg, pArgs);
  7328. }
  7329. return (TRUE);
  7330. case IDC_MAIN_PROPERTIES_BUTTON:
  7331. if (ID_OK_RELAUNCH_MAIN_DLG == OnMainProperties(hwndDlg,pArgs))
  7332. {
  7333. //
  7334. // We want to relaunch the logon UI with Access Points enabled or disabled depending
  7335. // on the change the user made in the properties dialog.
  7336. //
  7337. EndMainDialog(hwndDlg, pArgs, ID_OK_RELAUNCH_MAIN_DLG);
  7338. }
  7339. return (TRUE);
  7340. case IDC_MAIN_HELP_BUTTON:
  7341. {
  7342. UINT nCtrlFocus = IsWindowEnabled(GetDlgItem(hwndDlg,IDOK)) ? IDOK : IDCANCEL;
  7343. CmWinHelp(hwndDlg,hwndDlg,pArgs->pszHelpFile,HELP_FORCEFILE,0);
  7344. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  7345. return (TRUE);
  7346. }
  7347. case IDC_MAIN_NOPROMPT_CHECKBOX:
  7348. pArgs->fDialAutomatically = !pArgs->fDialAutomatically;
  7349. if (TRUE == pArgs->fDialAutomatically)
  7350. {
  7351. MYDBGASSERT(!pArgs->fHideDialAutomatically);
  7352. //
  7353. // Display message explaining Dial Automatically
  7354. //
  7355. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection,
  7356. c_pszCmEntryDialAutoMessage);
  7357. if (pszTmp && *pszTmp)
  7358. {
  7359. MessageBoxEx(hwndDlg,
  7360. pszTmp,
  7361. pArgs->szServiceName,
  7362. MB_OK|MB_ICONWARNING,
  7363. LANG_USER_DEFAULT);
  7364. }
  7365. CmFree(pszTmp);
  7366. }
  7367. break;
  7368. case IDC_MAIN_NOPASSWORD_CHECKBOX:
  7369. pArgs->fRememberMainPassword = !(pArgs->fRememberMainPassword);
  7370. if (!pArgs->piniService->GPPB(c_pszCmSection,
  7371. c_pszCmEntryPwdOptional))
  7372. {
  7373. //
  7374. // If password is not optional, enable/disable
  7375. // Dial Automatically according to state of
  7376. // "Remember password"
  7377. //
  7378. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX),
  7379. pArgs->fRememberMainPassword);
  7380. if (FALSE == pArgs->fRememberMainPassword)
  7381. {
  7382. //
  7383. // Reset Dial Automatically if user
  7384. // unchecks Save Password and password
  7385. // is not optional
  7386. //
  7387. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, FALSE);
  7388. pArgs->fDialAutomatically = FALSE;
  7389. if (pArgs->fGlobalCredentialsSupported)
  7390. {
  7391. //
  7392. // Also disable the option buttons
  7393. //
  7394. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  7395. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  7396. }
  7397. //
  7398. // Since we aren't remembering the main password
  7399. // see if we need to not remember Inet passwords
  7400. //
  7401. if (pArgs->fUseSameUserName)
  7402. {
  7403. pArgs->fRememberInetPassword = FALSE;
  7404. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  7405. }
  7406. //
  7407. // If the password edit hasn't been edited by the user, then we
  7408. // mostly likely have 16 *'s which doesn't help the user when
  7409. // they try to connect. Thus we need to clear the edit box
  7410. //
  7411. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  7412. if (hwndPassword)
  7413. {
  7414. pArgs->fIgnoreChangeNotification = TRUE;
  7415. BOOL fPWFieldModified = (BOOL) SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L);
  7416. if (FALSE == fPWFieldModified)
  7417. {
  7418. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  7419. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  7420. }
  7421. pArgs->fIgnoreChangeNotification = FALSE;
  7422. }
  7423. }
  7424. else
  7425. {
  7426. //
  7427. // Save Password option is Enabled
  7428. //
  7429. if (pArgs->fGlobalCredentialsSupported)
  7430. {
  7431. //
  7432. // Also enable the option buttons
  7433. //
  7434. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), TRUE);
  7435. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), TRUE);
  7436. }
  7437. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  7438. if (hwndPassword)
  7439. {
  7440. BOOL fPWFieldModified = (BOOL) SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L);
  7441. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  7442. {
  7443. //
  7444. // Try to reload current creds now that the user has enabled the save
  7445. // password option, unless the password field has been edited
  7446. //
  7447. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_CHECKED);
  7448. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_UNCHECKED);
  7449. if (FALSE == fPWFieldModified)
  7450. {
  7451. //
  7452. // Set the 3rd param to TRUE in order to bypass the check
  7453. // that it's called when we are in the local credential mode.
  7454. //
  7455. SwitchToGlobalCreds(pArgs, hwndDlg, TRUE);
  7456. }
  7457. }
  7458. else
  7459. {
  7460. if (pArgs->fGlobalCredentialsSupported)
  7461. {
  7462. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_UNCHECKED);
  7463. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_CHECKED);
  7464. }
  7465. if (FALSE == fPWFieldModified)
  7466. {
  7467. //
  7468. // Set the 3rd param to TRUE in order to bypass the check
  7469. // that it's called when we are in the global credential mode.
  7470. //
  7471. SwitchToLocalCreds(pArgs, hwndDlg, TRUE);
  7472. }
  7473. }
  7474. }
  7475. }
  7476. }
  7477. break;
  7478. case IDC_OPT_CREDS_SINGLE_USER:
  7479. {
  7480. //
  7481. // FALSE - allows the function to only execute if we are currently using
  7482. // the global credential store and the user now wants to switch.
  7483. //
  7484. SwitchToLocalCreds(pArgs, hwndDlg, FALSE);
  7485. break;
  7486. }
  7487. case IDC_OPT_CREDS_ALL_USER:
  7488. {
  7489. //
  7490. // FALSE - allows the function to only execute if we are currently using
  7491. // the local credential store and the user now wants to switch.
  7492. //
  7493. SwitchToGlobalCreds(pArgs, hwndDlg, FALSE);
  7494. break;
  7495. }
  7496. case IDC_MAIN_RESET_PASSWORD:
  7497. OnResetPassword(hwndDlg, pArgs);
  7498. break;
  7499. case IDC_MAIN_CUSTOM:
  7500. OnCustom(hwndDlg, pArgs);
  7501. break;
  7502. case IDCANCEL:
  7503. OnMainCancel(hwndDlg,pArgs);
  7504. return (TRUE);
  7505. case IDC_MAIN_PASSWORD_EDIT:
  7506. case IDC_MAIN_USERNAME_EDIT:
  7507. case IDC_MAIN_DOMAIN_EDIT:
  7508. if ((HIWORD(wParam) == EN_CHANGE))
  7509. {
  7510. if (!pArgs->fIgnoreChangeNotification)
  7511. {
  7512. OnMainEnChange(hwndDlg,pArgs);
  7513. return (TRUE);
  7514. }
  7515. }
  7516. break;
  7517. case IDC_MAIN_ACCESSPOINT_COMBO:
  7518. if (CBN_SELENDOK == HIWORD(wParam))
  7519. {
  7520. if (ChangedAccessPoint(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO))
  7521. {
  7522. UINT nCtrlFocus;
  7523. CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  7524. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  7525. }
  7526. }
  7527. default:
  7528. break;
  7529. }
  7530. break;
  7531. case WM_HELP:
  7532. CmWinHelp((HWND) (((LPHELPINFO) lParam)->hItemHandle),
  7533. (HWND) (((LPHELPINFO) lParam)->hItemHandle),
  7534. pArgs->pszHelpFile,
  7535. HELP_WM_HELP,
  7536. (ULONG_PTR) (LPSTR) adwHelp);
  7537. return (TRUE);
  7538. case WM_CONTEXTMENU:
  7539. {
  7540. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  7541. HWND hwndCtrl;
  7542. ScreenToClient(hwndDlg, &pt);
  7543. hwndCtrl = ChildWindowFromPoint(hwndDlg, pt);
  7544. if (!hwndCtrl || HaveContextHelp(hwndDlg, hwndCtrl))
  7545. {
  7546. CmWinHelp((HWND) wParam,
  7547. hwndCtrl,
  7548. pArgs->pszHelpFile,
  7549. HELP_CONTEXTMENU,
  7550. (ULONG_PTR)adwHelp);
  7551. }
  7552. return (TRUE);
  7553. }
  7554. case WM_SIZE:
  7555. //
  7556. // Dynamicly Enable/Disable system menu
  7557. //
  7558. {
  7559. HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
  7560. if (hMenu)
  7561. {
  7562. //
  7563. // if the dlg is minimized, then disable the minimized menu
  7564. //
  7565. if (wParam == SIZE_MINIMIZED)
  7566. {
  7567. EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_GRAYED);
  7568. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED);
  7569. }
  7570. else if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
  7571. {
  7572. EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_ENABLED);
  7573. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED);
  7574. }
  7575. }
  7576. MYDBGASSERT(hMenu); // assert if hMenu is NULL
  7577. }
  7578. break;
  7579. case WM_TIMER:
  7580. //
  7581. // Ignore the timer, if a (pre)connect action is running
  7582. //
  7583. if (!pArgs->fIgnoreTimerRasMsg)
  7584. {
  7585. OnMainTimer(hwndDlg,pArgs);
  7586. }
  7587. break;
  7588. case WM_PALETTEISCHANGING:
  7589. CMTRACE2(TEXT("MainDlgProc() got WM_PALETTEISCHANGING message, wParam=0x%x, hwndDlg=0x%x."),
  7590. wParam, hwndDlg);
  7591. break;
  7592. case WM_PALETTECHANGED:
  7593. {
  7594. //
  7595. // If its not our window that changed the palette, and we have a bitmap
  7596. //
  7597. if (IsWindowVisible(hwndDlg) && (wParam != (WPARAM) hwndDlg) && pArgs->BmpData.hDIBitmap)
  7598. {
  7599. //
  7600. // Handle the palette change.
  7601. //
  7602. // Note: We used to pass a flag indicating whether another
  7603. // bitmap was being displayed, but given that we select the
  7604. // paletted as a background app. this is no longer needed
  7605. //
  7606. CMTRACE2(TEXT("MainDlgProc() handling WM_PALETTECHANGED message, wParam=0x%x, hwndDlg=0x%x."),
  7607. wParam, hwndDlg);
  7608. PaletteChanged(&pArgs->BmpData, hwndDlg, IDC_MAIN_BITMAP);
  7609. }
  7610. return TRUE;
  7611. }
  7612. case WM_QUERYNEWPALETTE:
  7613. if (IsWindowVisible(hwndDlg))
  7614. {
  7615. CMTRACE2(TEXT("MainDlgProc() handling WM_QUERYNEWPALETTE message, wParam=0x%x, hwndDlg=0x%x."),
  7616. wParam, hwndDlg);
  7617. QueryNewPalette(&pArgs->BmpData, hwndDlg, IDC_MAIN_BITMAP);
  7618. }
  7619. return TRUE;
  7620. case WM_LOADSTARTUPINFO:
  7621. OnMainLoadStartupInfo(hwndDlg, pArgs);
  7622. break;
  7623. case WM_HANGUP_CM:
  7624. MYDBGASSERT(OS_W9X);
  7625. HangupCM(pArgs, hwndDlg, FALSE, (BOOL)wParam);
  7626. break;
  7627. case WM_CONNECTED_CM:
  7628. OnConnectedCM(hwndDlg, pArgs);
  7629. break;
  7630. case WM_PAUSE_RASDIAL:
  7631. OnPauseRasDial(hwndDlg, pArgs, wParam, lParam);
  7632. break;
  7633. default:
  7634. break;
  7635. }
  7636. if (pArgs && (uMsg == pArgs->uMsgId))
  7637. {
  7638. OnRasNotificationMessage(hwndDlg, pArgs, wParam, lParam);
  7639. return (TRUE);
  7640. }
  7641. return (FALSE);
  7642. }
  7643. //+---------------------------------------------------------------------------
  7644. //
  7645. // Function: ProcessCleanup
  7646. //
  7647. // Synopsis: Helper function to encapsulate closing Watch process handles
  7648. //
  7649. // Arguments: pArgs - pointer to global args struct
  7650. //
  7651. // Returns: Nothing
  7652. //
  7653. // History: a-nichb - Created - 4/30/97
  7654. //
  7655. //----------------------------------------------------------------------------
  7656. void ProcessCleanup(ArgsStruct* pArgs)
  7657. {
  7658. BOOL bRes;
  7659. if (pArgs->phWatchProcesses)
  7660. {
  7661. DWORD dwIdx;
  7662. for (dwIdx=0;pArgs->phWatchProcesses[dwIdx];dwIdx++)
  7663. {
  7664. bRes = CloseHandle(pArgs->phWatchProcesses[dwIdx]);
  7665. #ifdef DEBUG
  7666. if (!bRes)
  7667. {
  7668. CMTRACE1(TEXT("ProcessCleanup() CloseHandle() failed, GLE=%u."), GetLastError());
  7669. }
  7670. #endif
  7671. }
  7672. CmFree(pArgs->phWatchProcesses);
  7673. }
  7674. }
  7675. //+---------------------------------------------------------------------------
  7676. //
  7677. // Function: CheckProfileIntegrity
  7678. //
  7679. // Synopsis: Helper function to verify that we have valid profile.
  7680. // Verifies that we have a .CMP file name and that the
  7681. // .CMS file exists.
  7682. //
  7683. // Arguments: pArgs - pointer to global args struct
  7684. //
  7685. // Returns: TRUE if profile is valid
  7686. //
  7687. // History: a-nichb - Created - 5/8/97
  7688. // byao - Modified - 6/3/97 Added CMS/CMP file version check
  7689. //----------------------------------------------------------------------------
  7690. BOOL CheckProfileIntegrity(ArgsStruct* pArgs)
  7691. {
  7692. LPTSTR pszTmp = NULL;
  7693. LPCTSTR pszCmsFile = NULL;
  7694. DWORD dwCmsVersion, dwCmpVersion, dwCmVersion;
  7695. int iMsgId = 0;
  7696. if (NULL == pArgs)
  7697. {
  7698. return FALSE;
  7699. }
  7700. //
  7701. // Make sure that we have a profile name and a CMS that exists
  7702. //
  7703. if (!(*pArgs->piniProfile->GetFile()))
  7704. {
  7705. iMsgId = IDMSG_DAMAGED_PROFILE;
  7706. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run without a .cmp file."));
  7707. }
  7708. //
  7709. // If profile is good, check CMS
  7710. //
  7711. if (0 == iMsgId)
  7712. {
  7713. pszCmsFile = pArgs->piniService->GetFile();
  7714. if (!*pszCmsFile || FALSE == FileExists(pszCmsFile))
  7715. {
  7716. iMsgId = IDMSG_DAMAGED_PROFILE;
  7717. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run without a valid .cms file."));
  7718. }
  7719. }
  7720. //
  7721. // Now check the CMS/CMP file version
  7722. //
  7723. if (0 == iMsgId)
  7724. {
  7725. dwCmsVersion = pArgs->piniService->GPPI(c_pszCmSectionProfileFormat, c_pszVersion);
  7726. dwCmpVersion = pArgs->piniProfile->GPPI(c_pszCmSectionProfileFormat, c_pszVersion);
  7727. if ((dwCmsVersion != dwCmpVersion) || 0 == dwCmpVersion || 0 == dwCmsVersion)
  7728. {
  7729. iMsgId = IDMSG_DAMAGED_PROFILE;
  7730. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run with different version numbers."));
  7731. }
  7732. if (0 == iMsgId)
  7733. {
  7734. if (dwCmsVersion > PROFILEVERSION || dwCmpVersion > PROFILEVERSION)
  7735. {
  7736. //
  7737. // CM has older version than either CMS or CMP file
  7738. //
  7739. iMsgId = IDMSG_WRONG_PROFILE_VERSION;
  7740. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run with a newer CMS/CMP file."));
  7741. }
  7742. }
  7743. }
  7744. //
  7745. // Report any problems to the user
  7746. //
  7747. if (iMsgId)
  7748. {
  7749. //
  7750. // Make sure we aren't in unattended mode before showing UI to the user
  7751. //
  7752. if (0 == (pArgs->dwFlags & FL_UNATTENDED))
  7753. {
  7754. pszTmp = CmFmtMsg(g_hInst, iMsgId);
  7755. MessageBoxEx(NULL, pszTmp, pArgs->szServiceName, MB_OK|MB_ICONSTOP, LANG_USER_DEFAULT);//13309
  7756. CmFree(pszTmp);
  7757. }
  7758. pArgs->dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  7759. return FALSE;
  7760. }
  7761. return TRUE;
  7762. }
  7763. //+----------------------------------------------------------------------------
  7764. //
  7765. // Function: GetConnectType
  7766. //
  7767. // Synopsis: Encapsulates determination of connect type based upon tunneling,
  7768. // etc.
  7769. //
  7770. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  7771. //
  7772. // Returns: Nothing
  7773. //
  7774. // History: nickball Created 2/9/98
  7775. //
  7776. //+----------------------------------------------------------------------------
  7777. void GetConnectType(ArgsStruct *pArgs)
  7778. {
  7779. //
  7780. // If tunneling is not enabled, the decision is a simple one
  7781. //
  7782. if (!IsTunnelEnabled(pArgs))
  7783. {
  7784. //
  7785. // Only support dial-up, if tunnel is not enabled
  7786. //
  7787. pArgs->SetBothConnTypeSupported(FALSE);
  7788. pArgs->SetDirectConnect(FALSE);
  7789. }
  7790. else
  7791. {
  7792. //
  7793. // Load connection type info for CM 1.1, default is support both
  7794. //
  7795. int iSupportDialup = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDialup, 1);
  7796. int iSupportDirect = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDirect, 1);
  7797. if (iSupportDialup == TRUE && iSupportDirect == TRUE)
  7798. {
  7799. pArgs->SetBothConnTypeSupported(TRUE);
  7800. if (pArgs->piniBoth->GPPI(c_pszCmSection, c_pszCmEntryConnectionType, 0))
  7801. {
  7802. pArgs->SetDirectConnect(TRUE);
  7803. }
  7804. else
  7805. {
  7806. pArgs->SetDirectConnect(FALSE);
  7807. }
  7808. }
  7809. else
  7810. {
  7811. pArgs->SetBothConnTypeSupported(FALSE);
  7812. pArgs->SetDirectConnect(iSupportDirect == TRUE);
  7813. }
  7814. }
  7815. }
  7816. //+----------------------------------------------------------------------------
  7817. //
  7818. // Function: _ArgsStruct::GetTypeOfConnection
  7819. //
  7820. // Synopsis: Figures out what type of connection we are doing (dialup,
  7821. // double dial, or direct) and returns one of the connection define
  7822. // values listed in icm.h.
  7823. //
  7824. // Arguments: None
  7825. //
  7826. // Returns: DWORD - value indicating the type of connection, see icm.h for values
  7827. //
  7828. // History: quintinb Created 04/20/00
  7829. //
  7830. //+----------------------------------------------------------------------------
  7831. DWORD _ArgsStruct::GetTypeOfConnection()
  7832. {
  7833. DWORD dwType = 0;
  7834. if (this->IsDirectConnect())
  7835. {
  7836. return DIRECT_CONNECTION;
  7837. }
  7838. else
  7839. {
  7840. //
  7841. // Its not direct, so see if the primary phone
  7842. // number is for a tunneling scenario.
  7843. //
  7844. if (this->fUseTunneling) // Ambiguous during Pre-Init action.
  7845. {
  7846. return DOUBLE_DIAL_CONNECTION;
  7847. }
  7848. else
  7849. {
  7850. return DIAL_UP_CONNECTION;
  7851. }
  7852. }
  7853. }
  7854. //+----------------------------------------------------------------------------
  7855. //
  7856. // Function: _ArgsStruct::GetProperty
  7857. //
  7858. // Synopsis: get the cm property by name
  7859. // This function is used by connect actions
  7860. //
  7861. // Arguments: const TCHAR* pszName - name of the property
  7862. // BOOL *pbValidPropertyName - ptr to bool to indicate validity of property
  7863. //
  7864. // Returns: LPTSTR - Value of the property. Caller should use CmFree
  7865. // to free the memory
  7866. //
  7867. // History: fengsun Created Header 07/07/98
  7868. // nickball pbValidPropertyName 07/27/99
  7869. //
  7870. //+----------------------------------------------------------------------------
  7871. LPTSTR _ArgsStruct::GetProperty(const TCHAR* pszName, BOOL *pbValidPropertyName)
  7872. {
  7873. *pbValidPropertyName = TRUE;
  7874. //
  7875. // This function could be called with in RasCustomHangup.
  7876. // Some information of pArgs may bot be loaded
  7877. //
  7878. MYDBGASSERT(pszName);
  7879. MYDBGASSERT(pszName[0]);
  7880. if (pszName == NULL)
  7881. {
  7882. return NULL;
  7883. }
  7884. //
  7885. // Type - Dial-up only, VPN only, double-dial
  7886. //
  7887. if (lstrcmpiU(pszName, TEXT("ConnectionType")) == 0)
  7888. {
  7889. LPTSTR pszValue = (LPTSTR)CmMalloc(64*sizeof(TCHAR)); // large enough to hold the error code
  7890. MYDBGASSERT(pszValue);
  7891. if (pszValue)
  7892. {
  7893. wsprintfU(pszValue, TEXT("%u"), this->GetTypeOfConnection());
  7894. }
  7895. return pszValue;
  7896. }
  7897. //
  7898. // UserPrefix
  7899. //
  7900. if (lstrcmpiU(pszName,TEXT("UserPrefix")) == 0)
  7901. {
  7902. LPTSTR pszUsernamePrefix = NULL;
  7903. LPTSTR pszUsernameSuffix = NULL;
  7904. //
  7905. // Retrieve the suffix and prefix as they are a logical pair,
  7906. // but we only return the allocated PREFIX in this case.
  7907. //
  7908. CIni *piniService = GetAppropriateIniService(this, this->nDialIdx);
  7909. GetPrefixSuffix(this, piniService, &pszUsernamePrefix, &pszUsernameSuffix);
  7910. CmFree(pszUsernameSuffix);
  7911. delete piniService;
  7912. return pszUsernamePrefix;
  7913. }
  7914. //
  7915. // UserSuffix
  7916. //
  7917. if (lstrcmpiU(pszName,TEXT("UserSuffix")) == 0)
  7918. {
  7919. LPTSTR pszUsernamePrefix = NULL;
  7920. LPTSTR pszUsernameSuffix = NULL;
  7921. //
  7922. // Retrieve the suffix and prefix as they are a logical pair,
  7923. // but we only return the allocated SUFFIX in this case.
  7924. //
  7925. CIni *piniService = GetAppropriateIniService(this, this->nDialIdx);
  7926. GetPrefixSuffix(this, piniService, &pszUsernamePrefix, &pszUsernameSuffix);
  7927. CmFree(pszUsernamePrefix);
  7928. delete piniService;
  7929. return pszUsernameSuffix;
  7930. }
  7931. //
  7932. // UserName
  7933. //
  7934. if (lstrcmpiU(pszName,TEXT("UserName")) == 0)
  7935. {
  7936. LPTSTR pszValue = NULL;
  7937. //
  7938. // We want to get the value by calling GetUserInfo so that we don't break
  7939. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7940. // value directly out of the Args Structure.
  7941. //
  7942. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7943. {
  7944. GetUserInfo(this, UD_ID_USERNAME, (PVOID*)&pszValue);
  7945. }
  7946. else
  7947. {
  7948. pszValue = CmStrCpyAlloc(this->szUserName);
  7949. }
  7950. return pszValue;
  7951. }
  7952. //
  7953. // InetUserName
  7954. //
  7955. if (lstrcmpiU(pszName,TEXT("InetUserName")) == 0)
  7956. {
  7957. LPTSTR pszValue = NULL;
  7958. //
  7959. // If we aren't doing a double dial, then the InetUserName doesn't make
  7960. // sense and thus should be zero. Also if UseSameUserName is
  7961. // set then we want to return the UserName and skip trying to
  7962. // find the InetUserName
  7963. //
  7964. if (this->fUseTunneling && (FALSE == this->IsDirectConnect()))
  7965. {
  7966. if (this->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName))
  7967. {
  7968. //
  7969. // We want to get the value by calling GetUserInfo so that we don't break
  7970. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7971. // value directly out of the Args Structure.
  7972. //
  7973. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7974. {
  7975. GetUserInfo(this, UD_ID_USERNAME, (PVOID*)&pszValue);
  7976. }
  7977. else
  7978. {
  7979. pszValue = CmStrCpyAlloc(this->szUserName);
  7980. }
  7981. }
  7982. else
  7983. {
  7984. //
  7985. // We want to get the value by calling GetUserInfo so that we don't break
  7986. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7987. // value directly out of the Args Structure.
  7988. //
  7989. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7990. {
  7991. GetUserInfo(this, UD_ID_INET_USERNAME, (PVOID*)&pszValue);
  7992. }
  7993. else
  7994. {
  7995. pszValue = CmStrCpyAlloc(this->szInetUserName);
  7996. }
  7997. }
  7998. }
  7999. return pszValue;
  8000. }
  8001. //
  8002. // Domain
  8003. //
  8004. if (lstrcmpiU(pszName,TEXT("Domain")) == 0)
  8005. {
  8006. LPTSTR pszValue = NULL;
  8007. //
  8008. // We want to get the value by calling GetUserInfo so that we don't break
  8009. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  8010. // value directly out of the Args Structure.
  8011. //
  8012. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  8013. {
  8014. GetUserInfo(this, UD_ID_DOMAIN, (PVOID*)&pszValue);
  8015. }
  8016. else
  8017. {
  8018. pszValue = CmStrCpyAlloc(this->szDomain);
  8019. }
  8020. return pszValue;
  8021. }
  8022. //
  8023. // Profile
  8024. //
  8025. if (lstrcmpiU(pszName,TEXT("Profile")) == 0)
  8026. {
  8027. return CmStrCpyAlloc(this->piniProfile->GetFile());
  8028. }
  8029. //
  8030. // ServiceDir
  8031. //
  8032. if (lstrcmpiU(pszName, TEXT("ServiceDir")) == 0)
  8033. {
  8034. LPTSTR pszServiceDir = NULL;
  8035. // start with the file name of the Service
  8036. LPCTSTR pszService = this->piniService->GetFile();
  8037. if (pszService)
  8038. {
  8039. // find out where the filename.cmp portion starts
  8040. LPTSTR pszTmp = CmStrrchr(pszService, TEXT('\\'));
  8041. size_t nSize = pszTmp - pszService + 1;
  8042. // alloc enough space for the directory name (and terminating NULL)
  8043. pszServiceDir = (LPTSTR)CmMalloc( nSize * sizeof(TCHAR));
  8044. if (pszServiceDir)
  8045. {
  8046. lstrcpynU(pszServiceDir, pszService, nSize);
  8047. //
  8048. // The Win32 lstrcpyN function enforces a terminating NULL,
  8049. // so the above works without requiring any further code.
  8050. //
  8051. }
  8052. }
  8053. return pszServiceDir;
  8054. }
  8055. //
  8056. // ServiceName
  8057. //
  8058. if (lstrcmpiU(pszName,c_pszCmEntryServiceName) == 0)
  8059. {
  8060. MYDBGASSERT(this->szServiceName[0]);
  8061. return CmStrCpyAlloc(this->szServiceName);
  8062. }
  8063. //
  8064. // DialRasPhoneBook
  8065. //
  8066. if (lstrcmpiU(pszName, TEXT("DialRasPhoneBook")) == 0)
  8067. {
  8068. //
  8069. // We want to return NULL if this was a direct connection
  8070. // and we want to return the hidden ras phonebook path if
  8071. // this was a double dial connection (tunnel over a PPP
  8072. // connection that we dialed).
  8073. //
  8074. if (this->IsDirectConnect())
  8075. {
  8076. return NULL;
  8077. }
  8078. else
  8079. {
  8080. if (this->fUseTunneling)
  8081. {
  8082. return CreateRasPrivatePbk(this);
  8083. }
  8084. else
  8085. {
  8086. return CmStrCpyAlloc(this->pszRasPbk);
  8087. }
  8088. }
  8089. }
  8090. //
  8091. // DialRasEntry
  8092. //
  8093. if (lstrcmpiU(pszName, TEXT("DialRasEntry")) == 0)
  8094. {
  8095. if (this->IsDirectConnect())
  8096. {
  8097. return NULL;
  8098. }
  8099. else
  8100. {
  8101. return GetRasConnectoidName(this, this->piniService, FALSE);
  8102. }
  8103. }
  8104. //
  8105. // TunnelRasPhoneBook
  8106. //
  8107. if (lstrcmpiU(pszName, TEXT("TunnelRasPhoneBook")) == 0)
  8108. {
  8109. //
  8110. // If we are not tunneling then we want to make sure that we
  8111. // return NULL for the tunnel entry name and the tunnel
  8112. // phonebook
  8113. //
  8114. if (this->fUseTunneling)
  8115. {
  8116. CMTRACE1(TEXT("GetProperty - TunnelRasPhoneBook is %s"), this->pszRasPbk);
  8117. return CmStrCpyAlloc(this->pszRasPbk);
  8118. }
  8119. else
  8120. {
  8121. CMTRACE(TEXT("GetProperty - TunnelRasPhoneBook returns NULL"));
  8122. return NULL;
  8123. }
  8124. }
  8125. //
  8126. // TunnelRasEntry
  8127. //
  8128. if (lstrcmpiU(pszName, TEXT("TunnelRasEntry")) == 0)
  8129. {
  8130. //
  8131. // If we are not tunneling then we want to make sure that we
  8132. // return NULL for the tunnel entry name and the tunnel
  8133. // phonebook
  8134. //
  8135. if (this->fUseTunneling)
  8136. {
  8137. return GetRasConnectoidName(this, this->piniService, TRUE);
  8138. }
  8139. else
  8140. {
  8141. return NULL;
  8142. }
  8143. }
  8144. //
  8145. // AutoRedial, TRUE or FALSE
  8146. ///
  8147. if (lstrcmpiU(pszName, TEXT("AutoRedial")) == 0)
  8148. {
  8149. //
  8150. // Return TRUE for the first try.
  8151. //
  8152. return CmStrCpyAlloc( this->nRedialCnt != this->nMaxRedials
  8153. ? TEXT("1") : TEXT("0"));
  8154. }
  8155. if (lstrcmpiU(pszName, TEXT("LastErrorSource")) == 0)
  8156. {
  8157. return CmStrCpyAlloc(this->szLastErrorSrc);
  8158. }
  8159. //
  8160. // PopName, as the city name in phone-book
  8161. //
  8162. if (lstrcmpiU(pszName, TEXT("PopName")) == 0)
  8163. {
  8164. if (this->IsDirectConnect())
  8165. {
  8166. //
  8167. // Ensure no POP description on DirectConnect #324951
  8168. //
  8169. return NULL;
  8170. }
  8171. else
  8172. {
  8173. //
  8174. // the szDesc is in the format of "CityName (BaudMin - BaudMax bps)"
  8175. // We could save the CityNme when we load the phone number from phonebook
  8176. // But we have to change cmpbk code then.
  8177. //
  8178. LPTSTR pszDesc = CmStrCpyAlloc(this->aDialInfo[nDialIdx].szDesc);
  8179. //
  8180. // The city name is followed by " ("
  8181. //
  8182. LPTSTR pszEnd = CmStrStr(pszDesc, TEXT(" ("));
  8183. if (pszEnd == NULL)
  8184. {
  8185. CmFree(pszDesc);
  8186. return NULL;
  8187. }
  8188. *pszEnd = TEXT('\0');
  8189. return pszDesc;
  8190. }
  8191. }
  8192. //
  8193. // The current favorite
  8194. //
  8195. if (lstrcmpiU(pszName, TEXT("CurrentFavorite")) == 0)
  8196. {
  8197. return CmStrCpyAlloc(this->pszCurrentAccessPoint);
  8198. }
  8199. //
  8200. // The current tunnel server address
  8201. //
  8202. if (lstrcmpiU(pszName, TEXT("TunnelServerAddress")) == 0)
  8203. {
  8204. if (this->fUseTunneling)
  8205. {
  8206. return this->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  8207. }
  8208. else
  8209. {
  8210. return NULL;
  8211. }
  8212. }
  8213. //
  8214. // The canonical number if there is one and if not then the szPhonenumber field itself.
  8215. //
  8216. if (lstrcmpiU(pszName, TEXT("PhoneNumberDialed")) == 0)
  8217. {
  8218. if (this->IsDirectConnect())
  8219. {
  8220. return NULL;
  8221. }
  8222. else
  8223. {
  8224. if (this->aDialInfo[nDialIdx].szCanonical[0])
  8225. {
  8226. return CmStrCpyAlloc(this->aDialInfo[nDialIdx].szCanonical);
  8227. }
  8228. else
  8229. {
  8230. return CmStrCpyAlloc(this->aDialInfo[nDialIdx].szPhoneNumber);
  8231. }
  8232. }
  8233. }
  8234. //
  8235. // ErrorCode in decimal
  8236. //
  8237. if (lstrcmpiU(pszName, TEXT("ErrorCode")) == 0)
  8238. {
  8239. LPTSTR pszValue = (LPTSTR)CmMalloc(64*sizeof(TCHAR)); // large enough to hold the error code
  8240. MYDBGASSERT(pszValue);
  8241. if (pszValue)
  8242. {
  8243. wsprintfU(pszValue, TEXT("%d"), this->dwExitCode);
  8244. }
  8245. return pszValue;
  8246. }
  8247. //
  8248. // The client's or server's IP address
  8249. //
  8250. if (lstrcmpiU(pszName, TEXT("ClientIPAddress")) == 0 || lstrcmpiU(pszName, TEXT("ServerIPAddress")) == 0)
  8251. {
  8252. RASPROJECTION RasProj = RASP_PppIp;
  8253. RASPPPIP RasPPPIP;
  8254. DWORD dwBufSize = sizeof(RASPPPIP);
  8255. DWORD dwRet = ERROR_SUCCESS;
  8256. HRASCONN hrcRasConn = NULL;
  8257. // Set a flag based on whether client or server was asked for
  8258. BOOL fClientIP = ((lstrcmpiU(pszName, TEXT("ClientIPAddress")) == 0) ? TRUE : FALSE);
  8259. if (this->hrcTunnelConn)
  8260. {
  8261. // we have a tunnel handle => we're tunneling
  8262. hrcRasConn = this->hrcTunnelConn;
  8263. }
  8264. else if (this->hrcRasConn)
  8265. {
  8266. // we have a ras handle => we're dialing
  8267. hrcRasConn = this->hrcRasConn;
  8268. }
  8269. else
  8270. {
  8271. // no soup for you
  8272. return NULL;
  8273. }
  8274. ZeroMemory(&RasPPPIP, dwBufSize);
  8275. RasPPPIP.dwSize = dwBufSize;
  8276. dwRet = this->rlsRasLink.pfnGetProjectionInfo(hrcRasConn, RasProj, (PVOID) &RasPPPIP, &dwBufSize);
  8277. if (ERROR_SUCCESS == dwRet)
  8278. {
  8279. if (fClientIP)
  8280. {
  8281. return CmStrCpyAlloc(RasPPPIP.szIpAddress);
  8282. }
  8283. else
  8284. {
  8285. return CmStrCpyAlloc(RasPPPIP.szServerIpAddress);
  8286. }
  8287. }
  8288. else
  8289. {
  8290. CMTRACE1(TEXT("GetProperty - RasGetProjectionInfo returns %d"), dwRet);
  8291. }
  8292. return NULL;
  8293. }
  8294. //
  8295. // Should the customaction interact with the user
  8296. //
  8297. if (lstrcmpiU(pszName, TEXT("Interactive")) == 0)
  8298. {
  8299. LPTSTR pszValue = (LPTSTR) CmMalloc(2 * sizeof(TCHAR)); // this is 0 or 1
  8300. MYDBGASSERT(pszValue);
  8301. if (pszValue)
  8302. {
  8303. wsprintfU(pszValue, TEXT("%u"), (this->dwFlags & FL_UNATTENDED) ? 0 : 1);
  8304. }
  8305. return pszValue;
  8306. }
  8307. CMTRACE1(TEXT("%%%s%% not a macro, may be environment variable"), pszName);
  8308. *pbValidPropertyName = FALSE;
  8309. return NULL;
  8310. }
  8311. //+----------------------------------------------------------------------------
  8312. //
  8313. // Function: GetMainDlgTemplate
  8314. //
  8315. // Synopsis: Encapsulates determining which template is to be used
  8316. // for the main dialog.
  8317. //
  8318. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  8319. //
  8320. // Returns: UINT - Dlg template ID.
  8321. //
  8322. // History: nickball Created 9/25/98
  8323. // tomkel 01/30/2001 Added support for global credentials UI
  8324. // by using pArgs->fGlobalCredentialsSupported
  8325. //
  8326. //+----------------------------------------------------------------------------
  8327. UINT GetMainDlgTemplate(ArgsStruct *pArgs)
  8328. {
  8329. MYDBGASSERT(pArgs);
  8330. if (NULL == pArgs)
  8331. {
  8332. MYDBGASSERT(pArgs);
  8333. return 0;
  8334. }
  8335. UINT uiNewMainDlgID = 0;
  8336. DWORD dwNewTemplateMask = 0;
  8337. UINT i = 0;
  8338. //
  8339. // Currently there are 24 dialogs used in this function. If you add more dialogs
  8340. // make sure to increase the size of the array and the loop. The dialog templates
  8341. // aren't in any particular order, since we loop through all of them
  8342. // comparing the masks until we find the correct one.
  8343. //
  8344. DWORD rdwTemplateIDs[24][2] = {
  8345. {CMTM_FAVS | CMTM_U_P_D | CMTM_GCOPT, IDD_MAIN_ALL_USERDATA_FAV_GCOPT},
  8346. {CMTM_FAVS | CMTM_U_P_D, IDD_MAIN_ALL_USERDATA_FAV},
  8347. {CMTM_FAVS | CMTM_UID, IDD_MAIN_UID_ONLY_FAV},
  8348. {CMTM_FAVS | CMTM_PWD | CMTM_GCOPT, IDD_MAIN_PWD_ONLY_FAV_GCOPT},
  8349. {CMTM_FAVS | CMTM_PWD, IDD_MAIN_PWD_ONLY_FAV},
  8350. {CMTM_FAVS | CMTM_DMN, IDD_MAIN_DMN_ONLY_FAV},
  8351. {CMTM_FAVS | CMTM_UID_AND_PWD | CMTM_GCOPT, IDD_MAIN_UID_AND_PWD_FAV_GCOPT},
  8352. {CMTM_FAVS | CMTM_UID_AND_PWD, IDD_MAIN_UID_AND_PWD_FAV},
  8353. {CMTM_FAVS | CMTM_UID_AND_DMN, IDD_MAIN_UID_AND_DMN_FAV},
  8354. {CMTM_FAVS | CMTM_PWD_AND_DMN | CMTM_GCOPT, IDD_MAIN_PWD_AND_DMN_FAV_GCOPT},
  8355. {CMTM_FAVS | CMTM_PWD_AND_DMN, IDD_MAIN_PWD_AND_DMN_FAV},
  8356. {CMTM_FAVS, IDD_MAIN_NO_USERDATA_FAV},
  8357. {CMTM_U_P_D | CMTM_GCOPT, IDD_MAIN_ALL_USERDATA_GCOPT},
  8358. {CMTM_U_P_D, IDD_MAIN_ALL_USERDATA},
  8359. {CMTM_UID, IDD_MAIN_UID_ONLY},
  8360. {CMTM_PWD | CMTM_GCOPT, IDD_MAIN_PWD_ONLY_GCOPT},
  8361. {CMTM_PWD, IDD_MAIN_PWD_ONLY},
  8362. {CMTM_DMN, IDD_MAIN_DMN_ONLY},
  8363. {CMTM_UID_AND_PWD | CMTM_GCOPT, IDD_MAIN_UID_AND_PWD_GCOPT},
  8364. {CMTM_UID_AND_PWD, IDD_MAIN_UID_AND_PWD},
  8365. {CMTM_UID_AND_DMN, IDD_MAIN_UID_AND_DMN},
  8366. {CMTM_PWD_AND_DMN | CMTM_GCOPT, IDD_MAIN_PWD_AND_DMN_GCOPT},
  8367. {CMTM_PWD_AND_DMN, IDD_MAIN_PWD_AND_DMN},
  8368. {0, IDD_MAIN_NO_USERDATA}};
  8369. //
  8370. // Set the mask according to the pArgs flags for each value.
  8371. //
  8372. if (!pArgs->fHideUserName)
  8373. {
  8374. dwNewTemplateMask |= CMTM_UID;
  8375. }
  8376. //
  8377. // If the password edit is not displayed, there is no need to
  8378. // check for the global creds flag since there are no such dialogs
  8379. //
  8380. if (!pArgs->fHidePassword)
  8381. {
  8382. dwNewTemplateMask |= CMTM_PWD;
  8383. //
  8384. // Since we show the password field, lets check if we should display
  8385. // the global creds option as well.
  8386. //
  8387. if (pArgs->fGlobalCredentialsSupported)
  8388. {
  8389. dwNewTemplateMask |= CMTM_GCOPT;
  8390. }
  8391. }
  8392. if (!pArgs->fHideDomain)
  8393. {
  8394. dwNewTemplateMask |= CMTM_DMN;
  8395. }
  8396. if (pArgs->fAccessPointsEnabled)
  8397. {
  8398. dwNewTemplateMask |= CMTM_FAVS;
  8399. }
  8400. //
  8401. // Now find the corresponding template id
  8402. //
  8403. for (i = 0; i < 24; i++)
  8404. {
  8405. if (rdwTemplateIDs[i][0] == dwNewTemplateMask)
  8406. {
  8407. uiNewMainDlgID = rdwTemplateIDs[i][1];
  8408. break;
  8409. }
  8410. }
  8411. if (0 == uiNewMainDlgID)
  8412. {
  8413. MYDBGASSERT(FALSE);
  8414. uiNewMainDlgID = IDD_MAIN_NO_USERDATA;
  8415. }
  8416. return uiNewMainDlgID;
  8417. }
  8418. //+----------------------------------------------------------------------------
  8419. //
  8420. // Function: Connect
  8421. //
  8422. // Synopsis: The main dialing (connect path) replaces the winmain from the
  8423. // original CMMGR32.EXE
  8424. //
  8425. // Arguments: HWND hwndParent - window handle of parent
  8426. // LPCTSTR lpszEntry - Ptr to the name of the connection entry
  8427. // LPTSTR lpszPhonebook - Ptr to the name of the phonebook
  8428. // LPRASDIALDLG lpRasDialDlg - RasDialDlg data - ignored
  8429. // LPRASENTRYDLG lpRasEntryDlg - RasEntryDlg data - ignored
  8430. // LPCMDIALINFO lpCmInfo - CM specific dial info such as flags
  8431. // DWORD dwFlags - Flags for AllUser, SingleUser, EAP, etc.
  8432. // PVOID pvLogonBlob - Ptr to blob passed by RAS at WinLogon on W2K
  8433. //
  8434. // Returns: Nothing
  8435. //
  8436. // Note: RasDialDlg->hwndOwner and RasDialDlg->hwndOwner are honored, but they
  8437. // are currently passed in via the hwndParent parameter as appropriate by
  8438. // the caller, CmCustomDialDlg.
  8439. //
  8440. // History: nickball Created 02/06/98
  8441. // nickball hwndParent 11/10/98
  8442. // nickball Passed down dwFlags instead of BOOL 07/13/99
  8443. //
  8444. //+----------------------------------------------------------------------------
  8445. HRESULT Connect(HWND hwndParent,
  8446. LPCTSTR pszEntry,
  8447. LPTSTR lpszPhonebook,
  8448. LPRASDIALDLG, // lpRasDialDlg,
  8449. LPRASENTRYDLG, // lpRasEntryDlg,
  8450. LPCMDIALINFO lpCmInfo,
  8451. DWORD dwFlags,
  8452. PVOID pvLogonBlob)
  8453. {
  8454. MYDBGASSERT(pszEntry);
  8455. MYDBGASSERT(pszEntry[0]);
  8456. MYDBGASSERT(lpCmInfo);
  8457. CMTRACE(TEXT("Connect()"));
  8458. if (NULL == pszEntry || NULL == lpCmInfo)
  8459. {
  8460. return E_POINTER;
  8461. }
  8462. if (0 == pszEntry[0])
  8463. {
  8464. return E_INVALIDARG;
  8465. }
  8466. HRESULT hrRes = S_OK;
  8467. BOOL fLoggingInitialized = FALSE;
  8468. //
  8469. // Allocate our args struct from the heap. Not on our stack.
  8470. //
  8471. ArgsStruct* pArgs = (ArgsStruct*) CmMalloc(sizeof(ArgsStruct));
  8472. if (NULL == pArgs)
  8473. {
  8474. hrRes = HRESULT_FROM_WIN32(ERROR_ALLOCATING_MEMORY);
  8475. goto done;
  8476. }
  8477. //
  8478. // Clear and init global args struct
  8479. //
  8480. hrRes = InitArgsForConnect(pArgs, lpszPhonebook, lpCmInfo, (dwFlags & RCD_AllUsers));
  8481. if (FAILED(hrRes))
  8482. {
  8483. goto done;
  8484. }
  8485. //
  8486. // Setup the connection table
  8487. //
  8488. hrRes = CreateConnTable(pArgs);
  8489. if (FAILED(hrRes))
  8490. {
  8491. goto done;
  8492. }
  8493. //
  8494. // Initialize the profile
  8495. //
  8496. hrRes = InitProfile(pArgs, pszEntry);
  8497. if (FAILED(hrRes))
  8498. {
  8499. goto done;
  8500. }
  8501. //
  8502. // Make sure we have a .cmp name and that the specified .cms exists
  8503. //
  8504. if (FALSE == CheckProfileIntegrity(pArgs))
  8505. {
  8506. // CheckProfileIntegrity() will set pArgs->dwExitCode accordingly
  8507. goto done;
  8508. }
  8509. //
  8510. // Initialize logging
  8511. //
  8512. (VOID) InitLogging(pArgs, pszEntry, TRUE); // TRUE => write a banner;
  8513. // ignore return value
  8514. fLoggingInitialized = TRUE;
  8515. //
  8516. // If the SafeNet client is available then let's enable logging. We won't
  8517. // know for sure if we are using it till much later and I don't want to miss
  8518. // it discovering other adapters (dialup adapters coming up for instance). I
  8519. // would rather log too much than not enough.
  8520. //
  8521. if ((OS_W9X || OS_NT4) && IsSafeNetClientAvailable())
  8522. {
  8523. SafeNetLinkageStruct SnLinkage = {0};
  8524. BOOL bUseLogFile = pArgs->Log.IsEnabled();
  8525. if (LinkToSafeNet(&SnLinkage))
  8526. {
  8527. if (SnLinkage.pfnSnPolicySet(SN_USELOGFILE, (VOID*)&bUseLogFile))
  8528. {
  8529. MYVERIFY(0 != SnLinkage.pfnSnPolicyReload());
  8530. }
  8531. else
  8532. {
  8533. DWORD dwError = GetLastError();
  8534. CMTRACE1(TEXT("Connect -- unable to toggle the SafeNet log file. SnPolicySet failed with GLE %d"), dwError);
  8535. }
  8536. UnLinkFromSafeNet(&SnLinkage);
  8537. }
  8538. }
  8539. //
  8540. // Pick up any pre-existing credentials (eg. WinLogon, Reconnect)
  8541. //
  8542. hrRes = InitCredentials(pArgs, lpCmInfo, dwFlags, pvLogonBlob);
  8543. if (S_OK != hrRes)
  8544. {
  8545. goto done;
  8546. }
  8547. //
  8548. // Now that credential support and existance flags are initialized we need
  8549. // to initialize the read/write flags in order to support global user
  8550. // info. This can only be called only after InitCredentials
  8551. //
  8552. SetIniObjectReadWriteFlags(pArgs);
  8553. //
  8554. // Calling InitConnect depends on having the Ini objects read/write flags initialized correctly
  8555. // thus this calls needs to happen after SetIniObjectReadWriteFlags. This is important in case
  8556. // of ICS where it needs to be able to read data correctly from the ICSData reg key or default to
  8557. // the .cms/.cmp files.
  8558. //
  8559. if (!InitConnect(pArgs))
  8560. {
  8561. goto done;
  8562. }
  8563. //
  8564. // Register Classes
  8565. //
  8566. RegisterBitmapClass(g_hInst);
  8567. RegisterWindowClass(g_hInst);
  8568. //
  8569. // Get the helpfile path
  8570. //
  8571. LoadHelpFileInfo(pArgs);
  8572. //
  8573. // If we are in FL_PROPERTIES mode, just get the settings from the
  8574. // profile. Otherwise go ahead and launch the MainDlgProc
  8575. //
  8576. if (pArgs->dwFlags & FL_PROPERTIES)
  8577. {
  8578. if (*pArgs->piniProfile->GetFile() && SetupInternalInfo(pArgs, NULL))
  8579. {
  8580. OnMainProperties(hwndParent, pArgs);
  8581. }
  8582. }
  8583. else
  8584. {
  8585. //
  8586. // Need to call OleInitialize()? See if we need FutureSplash. We don't display
  8587. // animations at WinLogon because of the security implications.
  8588. //
  8589. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryAnimatedLogo) && !IsLogonAsSystem())
  8590. {
  8591. if (!pArgs->olsOle32Link.hInstOle32)
  8592. {
  8593. if (LinkToOle32(&pArgs->olsOle32Link, "OLE32"))
  8594. {
  8595. if (pArgs->olsOle32Link.pfnOleInitialize(NULL) != S_OK)
  8596. {
  8597. //
  8598. // Note: it's not fatal to fail OleInitialize().
  8599. // We will just load the normal bitmap then.
  8600. //
  8601. CMTRACE(TEXT("Connect() OleInitialize failed"));
  8602. }
  8603. }
  8604. else
  8605. {
  8606. CMTRACE(TEXT("Connect() LinkToOle32 failed"));
  8607. }
  8608. }
  8609. }
  8610. //
  8611. // Launch main dialog
  8612. //
  8613. INT_PTR iMainDlgReturn = 0;
  8614. do
  8615. {
  8616. iMainDlgReturn = DialogBoxParamU(g_hInst,
  8617. MAKEINTRESOURCE(GetMainDlgTemplate(pArgs)),
  8618. hwndParent,
  8619. MainDlgProc,
  8620. (LPARAM) pArgs);
  8621. if (0 != pArgs->dwSCardErr)
  8622. {
  8623. //
  8624. // User entered a bad smartcard PIN. We exit immediately to avoid
  8625. // locking up the smartcard with multiple incorrect retries.
  8626. //
  8627. MYDBGASSERT(BAD_SCARD_PIN(pArgs->dwSCardErr));
  8628. hrRes = pArgs->dwSCardErr;
  8629. goto done;
  8630. }
  8631. } while (ID_OK_RELAUNCH_MAIN_DLG == iMainDlgReturn);
  8632. }
  8633. done:
  8634. //
  8635. // Now that we are done, we should clear up all the messes :)
  8636. //
  8637. CleanupConnect(pArgs);
  8638. //
  8639. // Un-initialize logging
  8640. //
  8641. if (pArgs && fLoggingInitialized)
  8642. {
  8643. (VOID) pArgs->Log.DeInit();
  8644. // ignore return value
  8645. }
  8646. //
  8647. // Un-initialize Secure password classes
  8648. //
  8649. if (pArgs)
  8650. {
  8651. pArgs->SecurePW.UnInit();
  8652. pArgs->SecureInetPW.UnInit();
  8653. }
  8654. //
  8655. // If hRes isn't already set, use the exitcode value
  8656. //
  8657. if (S_OK == hrRes)
  8658. {
  8659. if (pArgs->dwExitCode > 0x7FFFFFFF)
  8660. {
  8661. hrRes = pArgs->dwExitCode;
  8662. }
  8663. else
  8664. {
  8665. hrRes = HRESULT_FROM_WIN32(pArgs->dwExitCode);
  8666. }
  8667. }
  8668. //
  8669. // Release pArgs, and exit completely
  8670. //
  8671. CmFree(pArgs);
  8672. return hrRes;
  8673. }
  8674. //
  8675. // Define funtion prototypes for EAP functions
  8676. // that are implemented in the actual EAP dll.
  8677. //
  8678. typedef DWORD (WINAPI* pfnRasEapGetIdentity)(
  8679. DWORD,
  8680. HWND,
  8681. DWORD,
  8682. const WCHAR*,
  8683. const WCHAR*,
  8684. PBYTE,
  8685. DWORD,
  8686. PBYTE,
  8687. DWORD,
  8688. PBYTE*,
  8689. DWORD*,
  8690. WCHAR**
  8691. );
  8692. typedef DWORD (WINAPI* pfnRasEapFreeMemory)(
  8693. PBYTE
  8694. );
  8695. //+----------------------------------------------------------------------------
  8696. //
  8697. // Function: CmEapGetIdentity
  8698. //
  8699. // Synopsis: Given EapUserData, looks up and calls RasEapGetIdentity for
  8700. // the current EAP. Designed to handle the WinLogon case when we
  8701. // want to use the EapUserData passed to us, rather then letting
  8702. // RasGetEapUserIdentity look it up. Because it is only used in
  8703. // this case we pass RAS_EAP_FLAG_LOGON this enables other EAPs
  8704. // to disregard the data if necessary.
  8705. //
  8706. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  8707. // LPTSTR lpszPhonebook - Ptr to the RAS phonebook
  8708. // LPBYTE pbEapAuthData - Eap auth data blob
  8709. // DWORD dwEapAuthDataSize - size of the Eap auth data blob
  8710. // DWORD dwCustomAuthKey - The EAP identifier
  8711. // LPRASEAPUSERIDENTITY* ppRasEapUserIdentity - Identity data
  8712. //
  8713. // Returns: Error Code
  8714. //
  8715. // History: nickball Created 07/16/99
  8716. // nickball ppRasEapUserIdentity 07/30/99
  8717. //
  8718. //+----------------------------------------------------------------------------
  8719. static DWORD CmEapGetIdentity(ArgsStruct *pArgs,
  8720. LPTSTR pszRasPbk,
  8721. LPBYTE pbEapAuthData,
  8722. DWORD dwEapAuthDataSize,
  8723. DWORD dwCustomAuthKey,
  8724. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity)
  8725. {
  8726. MYDBGASSERT(OS_NT5);
  8727. MYDBGASSERT(pArgs);
  8728. MYDBGASSERT(ppRasEapUserIdentity);
  8729. MYDBGASSERT(pArgs->lpEapLogonInfo);
  8730. if (NULL == pArgs || NULL == pArgs->lpEapLogonInfo || NULL == ppRasEapUserIdentity)
  8731. {
  8732. return ERROR_INVALID_PARAMETER;
  8733. }
  8734. DWORD dwErr = ERROR_SUCCESS;
  8735. DWORD dwTmp = 0;
  8736. DWORD dwSize = 0;
  8737. DWORD cbDataOut = 0;
  8738. LPBYTE pbDataOut = NULL;
  8739. WCHAR* pwszIdentity = NULL;
  8740. HKEY hKeyEap = NULL;
  8741. HINSTANCE hInst = NULL;
  8742. LPWSTR pszwPath = NULL;
  8743. pfnRasEapFreeMemory pfnEapFreeMemory = NULL;
  8744. pfnRasEapGetIdentity pfnEapGetIdentity = NULL;
  8745. //
  8746. // First we have to locate the Identity DLL for our EAP. Step one is to
  8747. // build the reg key name using the base path and EAP number.
  8748. //
  8749. WCHAR szwTmp[MAX_PATH];
  8750. wsprintfU(szwTmp, TEXT("%s\\%u"), c_pszRasEapRegistryLocation, dwCustomAuthKey);
  8751. //
  8752. // Now we can open the EAP key
  8753. //
  8754. dwErr = RegOpenKeyExU(HKEY_LOCAL_MACHINE,
  8755. szwTmp,
  8756. 0,
  8757. KEY_QUERY_VALUE ,
  8758. &hKeyEap);
  8759. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), szwTmp, dwErr);
  8760. if (ERROR_SUCCESS != dwErr)
  8761. {
  8762. return dwErr;
  8763. }
  8764. //
  8765. // See if the EAP supports RasEapGetIdentity
  8766. //
  8767. dwSize = sizeof(dwSize);
  8768. dwErr = RegQueryValueExU(hKeyEap,
  8769. c_pszInvokeUsernameDialog,
  8770. NULL,
  8771. NULL,
  8772. (BYTE*)&dwTmp,
  8773. &dwSize);
  8774. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), c_pszInvokeUsernameDialog, dwErr);
  8775. if ((dwErr) || (0 != dwTmp))
  8776. {
  8777. dwErr = ERROR_INVALID_FUNCTION_FOR_ENTRY;
  8778. goto CmEapGetIdentityExit;
  8779. }
  8780. //
  8781. // Next we need to retrieve the path of the EAP's identity DLL
  8782. //
  8783. dwSize = sizeof(szwTmp);
  8784. dwErr = RegQueryValueExU(hKeyEap, c_pszRasEapValueNameIdentity, NULL,
  8785. NULL, (LPBYTE) szwTmp, &dwSize);
  8786. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), c_pszRasEapValueNameIdentity, dwErr);
  8787. if (ERROR_SUCCESS != dwErr)
  8788. {
  8789. return dwErr;
  8790. }
  8791. pszwPath = (LPWSTR) CmMalloc(MAX_PATH * sizeof(TCHAR));
  8792. if (NULL == pszwPath)
  8793. {
  8794. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  8795. goto CmEapGetIdentityExit;
  8796. }
  8797. ExpandEnvironmentStringsU(szwTmp, pszwPath, MAX_PATH);
  8798. //
  8799. // Finally we have the path to the identity DLL. Now we can load the DLL
  8800. // and get the address of the RasEapGetIdentity and RasEapFreeMemory funcs.
  8801. //
  8802. CMTRACE1(TEXT("CmEapGetIdentity - Loading EAP Identity DLL %s"), pszwPath);
  8803. hInst = LoadLibraryExU(pszwPath, NULL, 0);
  8804. if (NULL == hInst)
  8805. {
  8806. dwErr = GetLastError();
  8807. goto CmEapGetIdentityExit;
  8808. }
  8809. pfnEapFreeMemory = (pfnRasEapFreeMemory) GetProcAddress(hInst, "RasEapFreeMemory");
  8810. pfnEapGetIdentity = (pfnRasEapGetIdentity) GetProcAddress(hInst, "RasEapGetIdentity");
  8811. if (pfnEapGetIdentity && pfnEapFreeMemory)
  8812. {
  8813. dwErr = pfnEapGetIdentity(dwCustomAuthKey,
  8814. pArgs->hwndMainDlg,
  8815. RAS_EAP_FLAG_LOGON | RAS_EAP_FLAG_PREVIEW,
  8816. pszRasPbk,
  8817. pArgs->pRasDialParams->szEntryName,
  8818. pbEapAuthData,
  8819. dwEapAuthDataSize,
  8820. (LPBYTE) pArgs->lpEapLogonInfo,
  8821. pArgs->lpEapLogonInfo->dwSize,
  8822. &pbDataOut,
  8823. &cbDataOut,
  8824. &pwszIdentity);
  8825. CMTRACE3(TEXT("CmEapGetIdentity - RasEapGetIdentity returns %u, cbDataOut is %u, pwszIdentity is %s"), dwErr, cbDataOut, pwszIdentity);
  8826. if (ERROR_SUCCESS == dwErr)
  8827. {
  8828. //
  8829. // If data was returned, use it. Otherwise, use the
  8830. // blob that was given to us by RAS at WinLogon.
  8831. //
  8832. if (cbDataOut)
  8833. {
  8834. dwSize = cbDataOut;
  8835. }
  8836. else
  8837. {
  8838. CMTRACE(TEXT("CmEapGetIdentity - there was no pbDataOut from the EAP, using lpEapLogonInfo"));
  8839. CMTRACE1(TEXT("CmEapGetIdentity - pArgs->lpEapLogonInfo->dwSize is %u"), pArgs->lpEapLogonInfo->dwSize);
  8840. CMTRACE1(TEXT("CmEapGetIdentity - dwLogonInfoSize is %u"), pArgs->lpEapLogonInfo->dwLogonInfoSize);
  8841. CMTRACE1(TEXT("CmEapGetIdentity - dwOffsetLogonInfo is %u"), pArgs->lpEapLogonInfo->dwOffsetLogonInfo);
  8842. CMTRACE1(TEXT("CmEapGetIdentity - dwPINInfoSize is %u"), pArgs->lpEapLogonInfo->dwPINInfoSize);
  8843. CMTRACE1(TEXT("CmEapGetIdentity - dwOffsetPINInfo is %u"), pArgs->lpEapLogonInfo->dwOffsetPINInfo);
  8844. dwSize = pArgs->lpEapLogonInfo->dwSize;
  8845. pbDataOut = (LPBYTE) pArgs->lpEapLogonInfo; // Note: pbDataOut is not our memory
  8846. }
  8847. //
  8848. // Allocate the structure.
  8849. //
  8850. *ppRasEapUserIdentity = (LPRASEAPUSERIDENTITY) CmMalloc((sizeof(RASEAPUSERIDENTITY) - 1) + dwSize);
  8851. if (NULL == *ppRasEapUserIdentity)
  8852. {
  8853. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  8854. goto CmEapGetIdentityExit;
  8855. }
  8856. if (pbDataOut) // no crashy
  8857. {
  8858. CMTRACE1(TEXT("CmEapGetIdentity - filling *ppRasEapUserIdentity with pbDataOut of size %u"), dwSize);
  8859. lstrcpyn((*ppRasEapUserIdentity)->szUserName, pwszIdentity, UNLEN);
  8860. (*ppRasEapUserIdentity)->szUserName[UNLEN] = 0;
  8861. (*ppRasEapUserIdentity)->dwSizeofEapInfo = dwSize;
  8862. CopyMemory((*ppRasEapUserIdentity)->pbEapInfo, pbDataOut, dwSize);
  8863. CMTRACE1(TEXT("CmEapGetIdentity - *ppRasEapUserIdentity filled with pbDataOut of size %u"), dwSize);
  8864. }
  8865. else
  8866. {
  8867. dwErr = ERROR_INVALID_DATA;
  8868. MYDBGASSERT(FALSE);
  8869. goto CmEapGetIdentityExit;
  8870. }
  8871. }
  8872. }
  8873. else
  8874. {
  8875. dwErr = GetLastError();
  8876. }
  8877. CmEapGetIdentityExit:
  8878. //
  8879. // Cleanup our temporary buffers
  8880. //
  8881. if (NULL != pfnEapFreeMemory)
  8882. {
  8883. //
  8884. // If cbDataOut is 0 then pbDataOut points at
  8885. // EapLogonInfo, which is not ours to free.
  8886. //
  8887. if (cbDataOut && (NULL != pbDataOut))
  8888. {
  8889. pfnEapFreeMemory(pbDataOut);
  8890. }
  8891. if (NULL != pwszIdentity)
  8892. {
  8893. pfnEapFreeMemory((BYTE*)pwszIdentity);
  8894. }
  8895. }
  8896. if (NULL != hKeyEap)
  8897. {
  8898. RegCloseKey(hKeyEap);
  8899. }
  8900. if (hInst)
  8901. {
  8902. FreeLibrary(hInst);
  8903. }
  8904. CmFree(pszwPath);
  8905. CMTRACE1(TEXT("CmEapGetIdentity - returns %u"), dwErr);
  8906. return dwErr;
  8907. }
  8908. //+----------------------------------------------------------------------------
  8909. //
  8910. // Function: GetEapUserId
  8911. //
  8912. // Synopsis: Helper func to deal with the details of calling out to RAS for EAP
  8913. // credentials.
  8914. //
  8915. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  8916. // HWND hwndDlg - Window handle of dialog to own any UI
  8917. // LPTSTR lpszPhonebook - Ptr to the RAS phonebook
  8918. // LPBYTE pbEapAuthData - Eap auth data blob
  8919. // DWORD dwEapAuthDataSize - Size of the Eap auth data blob.
  8920. // DWORD dwCustomAuthKey - The EAP identifier
  8921. // LPRASEAPUSERIDENTITY* ppRasEapUserIdentity - Ptr to RAS EAP identity
  8922. // struct to be allocated on our behalf.
  8923. //
  8924. // Returns: Error Code
  8925. //
  8926. // History: nickball Created 05/22/99
  8927. // nickball ppRasEapUserIdentity 07/30/99
  8928. //
  8929. //+----------------------------------------------------------------------------
  8930. static DWORD GetEapUserId(ArgsStruct *pArgs,
  8931. HWND hwndDlg,
  8932. LPTSTR pszRasPbk,
  8933. LPBYTE pbEapAuthData,
  8934. DWORD dwEapAuthDataSize,
  8935. DWORD dwCustomAuthKey,
  8936. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity)
  8937. {
  8938. MYDBGASSERT(OS_NT5);
  8939. MYDBGASSERT(pArgs);
  8940. MYDBGASSERT(ppRasEapUserIdentity);
  8941. MYDBGASSERT(0 == *ppRasEapUserIdentity); // should always be NULL
  8942. DWORD dwRet = ERROR_SUCCESS;
  8943. if (NULL == pArgs ||
  8944. NULL == pArgs->rlsRasLink.pfnGetEapUserIdentity ||
  8945. NULL == ppRasEapUserIdentity)
  8946. {
  8947. return ERROR_INVALID_PARAMETER;
  8948. }
  8949. *ppRasEapUserIdentity = 0;
  8950. //
  8951. // If we have data from WinLogon, then use our own version of
  8952. // GetEapIdentity. Under the covers, RasGetEapUserIdentity calls
  8953. // GetEapUserData (which potentially prompts the user) and then
  8954. // GetEapIdentity. Because we already have the equivalent
  8955. // (from WinLogon) of the data retrieved by GetEapUserData,
  8956. // we can call RasGetEapIdentity directly. This enables us
  8957. // to prevent an unnecessary prompt for the identity info that
  8958. // the user already gave at WinLogon.
  8959. //
  8960. if (pArgs->lpEapLogonInfo)
  8961. {
  8962. dwRet = CmEapGetIdentity(pArgs,
  8963. pszRasPbk,
  8964. pbEapAuthData,
  8965. dwEapAuthDataSize,
  8966. dwCustomAuthKey,
  8967. ppRasEapUserIdentity);
  8968. }
  8969. else
  8970. {
  8971. DWORD dwEapIdentityFlags = 0;
  8972. //
  8973. // Note: In the case that we are called from WinLogon,
  8974. // but without EAP data, but the connection is configured for EAP
  8975. // we send the RAS_EAP_FLAG_LOGON flag down to the EAP so it knows
  8976. // what to do.
  8977. //
  8978. if (IsLogonAsSystem() && (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType))
  8979. {
  8980. dwEapIdentityFlags |= RAS_EAP_FLAG_LOGON;
  8981. }
  8982. //
  8983. // In case we don't want UI set the - RAS_EAP_FLAG_NON_INTERACTIVE
  8984. // same as RASEAPF_NonInteractive
  8985. //
  8986. if (pArgs->dwFlags & FL_UNATTENDED)
  8987. {
  8988. dwEapIdentityFlags |= RAS_EAP_FLAG_NON_INTERACTIVE;
  8989. }
  8990. else
  8991. {
  8992. //
  8993. // Always prompt for EAP credentials. Otherwise when the PIN is saved
  8994. // the user has no way of un-saving it because TLS will cache it and
  8995. // won't display the prompt if it has everything it needs.
  8996. //
  8997. dwEapIdentityFlags = RAS_EAP_FLAG_PREVIEW;
  8998. }
  8999. //
  9000. // Our smartcard PIN retry story: If called from winlogon with an EAP blob,
  9001. // we never retry because we have no way to sending the corrected PIN back
  9002. // to winlogon. In other cases, we retry once only.
  9003. // Retrying oftener greatly increases the chance of locking the smartcard.
  9004. //
  9005. DWORD dwMaxTries = 3; // essentially arbitrary number. (If a smartcard: most do lock you out after 3 tries.)
  9006. DWORD dwCurrentTry = 0;
  9007. do
  9008. {
  9009. dwRet = pArgs->rlsRasLink.pfnGetEapUserIdentity(
  9010. pszRasPbk,
  9011. pArgs->pRasDialParams->szEntryName,
  9012. dwEapIdentityFlags, // See Note above
  9013. hwndDlg,
  9014. ppRasEapUserIdentity);
  9015. }
  9016. while ((dwCurrentTry++ < dwMaxTries) && (ERROR_SUCCESS != dwRet) && (ERROR_CANCELLED != dwRet));
  9017. //
  9018. // We also clear the password and domain in this case because
  9019. // they become irrelevant and we don't want to mix CAD credentials
  9020. // with smartcard credentials. Specifically, we don't want a clash
  9021. // between the UPN username that EAP usually produces and the
  9022. // standard username, domain provided with CAD at WinLogon.
  9023. //
  9024. // TODO: BUGBUG 739044 (not fixed - postponed to LH)
  9025. // In case of EAP-MD5 we shouldn't clear these fields
  9026. //
  9027. CmSecureZeroMemory(pArgs->pRasDialParams->szPassword, sizeof(pArgs->pRasDialParams->szPassword));
  9028. CmSecureZeroMemory(pArgs->pRasDialParams->szDomain, sizeof(pArgs->pRasDialParams->szDomain));
  9029. }
  9030. switch (dwRet)
  9031. {
  9032. case ERROR_FILE_NOT_FOUND:
  9033. //
  9034. // The EAP package couldn't be loaded or didn't exist. In order to send back an error message
  9035. // to the user that's better than "File not found", we send ERROR_INVALID_DATA. Our error processing
  9036. // code will translate this to IDMSG_UNSUPPORTED_SETTING. Hopefully that gives the user enough to go on.
  9037. //
  9038. dwRet = ERROR_INVALID_DATA;
  9039. break;
  9040. //
  9041. // If user id isn't required, succeed
  9042. //
  9043. case ERROR_INVALID_FUNCTION_FOR_ENTRY:
  9044. dwRet = ERROR_SUCCESS;
  9045. break;
  9046. //
  9047. // Retrieve the EAP credential data and store in dial params
  9048. //
  9049. case ERROR_SUCCESS:
  9050. //
  9051. // Copy Eap info to Dial Params and Dial Extensions for dialing
  9052. //
  9053. CMTRACE(TEXT("GetEapUserId() setting dial extension with *ppRasEapUserIdentity->pbEapInfo"));
  9054. lstrcpy(pArgs->pRasDialParams->szUserName, (*ppRasEapUserIdentity)->szUserName);
  9055. ((LPRASDIALEXTENSIONS_V500) pArgs->pRasDialExtensions)->RasEapInfo.dwSizeofEapInfo =
  9056. (*ppRasEapUserIdentity)->dwSizeofEapInfo;
  9057. ((LPRASDIALEXTENSIONS_V500) pArgs->pRasDialExtensions)->RasEapInfo.pbEapInfo =
  9058. (*ppRasEapUserIdentity)->pbEapInfo;
  9059. break;
  9060. default:
  9061. break;
  9062. }
  9063. if (ERROR_SUCCESS == dwRet)
  9064. {
  9065. //
  9066. // We have a user (identity) now, update internal and external records
  9067. // so that this information can be reported out. If we're dialing a
  9068. // tunnel, or its not a tunneling profile, store the name in the
  9069. // UserName cache, otherwise its the dial-up portion of double-dial
  9070. // and we store the identity in the InetUserName cache. #388199
  9071. //
  9072. if ((!UseTunneling(pArgs, pArgs->nDialIdx)) || IsDialingTunnel(pArgs))
  9073. {
  9074. lstrcpy(pArgs->szUserName, pArgs->pRasDialParams->szUserName);
  9075. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pArgs->pRasDialParams->szUserName);
  9076. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pArgs->pRasDialParams->szDomain);
  9077. }
  9078. else
  9079. {
  9080. lstrcpy(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName);
  9081. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  9082. }
  9083. }
  9084. CMTRACE2(TEXT("GetEapUserId() returns %u (0x%x)"), dwRet, dwRet);
  9085. return dwRet;
  9086. }
  9087. //+----------------------------------------------------------------------------
  9088. //
  9089. // Func: ShowAccessPointInfoFromReg
  9090. //
  9091. // Desc: Get the access points from the registry and populate the combo box
  9092. // passed as input to the function
  9093. //
  9094. // Args: ArgsStruct *pArgs - Ptr to global args struct
  9095. // HWND hwndCombo - Handle to the combo box to puopulate
  9096. //
  9097. // Return: BOOL - Success or failure
  9098. //
  9099. // Notes:
  9100. //
  9101. // History: t-urama 07/28/2000 Created
  9102. //-----------------------------------------------------------------------------
  9103. BOOL ShowAccessPointInfoFromReg(ArgsStruct *pArgs, HWND hwndParent, UINT uiComboID)
  9104. {
  9105. MYDBGASSERT(pArgs);
  9106. if ((NULL == pArgs) || (NULL == hwndParent) || (NULL == pArgs->pszCurrentAccessPoint))
  9107. {
  9108. return FALSE;
  9109. }
  9110. LPTSTR pszKeyName = NULL;
  9111. DWORD dwTypeTmp;
  9112. DWORD dwSizeTmp = 1;
  9113. HKEY hKeyCm;
  9114. DWORD dwRes = 1;
  9115. DWORD dwIndex = 0;
  9116. PFILETIME pftLastWriteTime = NULL;
  9117. LPTSTR pszRegPath = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  9118. MYDBGASSERT(pszRegPath);
  9119. if (NULL == pszRegPath)
  9120. {
  9121. return FALSE;
  9122. }
  9123. CmStrCatAlloc(&pszRegPath, TEXT("\\"));
  9124. CmStrCatAlloc(&pszRegPath, c_pszRegKeyAccessPoints);
  9125. MYDBGASSERT(pszRegPath);
  9126. if (NULL == pszRegPath)
  9127. {
  9128. return FALSE;
  9129. }
  9130. //
  9131. // Open the sub key under HKCU
  9132. //
  9133. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  9134. pszRegPath,
  9135. 0,
  9136. KEY_READ,
  9137. &hKeyCm);
  9138. //
  9139. // If we opened the key successfully, retrieve the value
  9140. //
  9141. if (ERROR_SUCCESS == dwRes)
  9142. {
  9143. HWND hwndCombo = GetDlgItem(hwndParent, uiComboID);
  9144. if (hwndCombo)
  9145. {
  9146. SendDlgItemMessageU(hwndParent, uiComboID, CB_RESETCONTENT, 0, 0L);
  9147. do
  9148. {
  9149. dwSizeTmp = 1;
  9150. do
  9151. {
  9152. CmFree(pszKeyName);
  9153. dwSizeTmp = dwSizeTmp + MAX_PATH;
  9154. MYDBGASSERT(dwSizeTmp < 320);
  9155. if (dwSizeTmp > 320)
  9156. {
  9157. RegCloseKey(hKeyCm);
  9158. goto ShowError;
  9159. }
  9160. pszKeyName = (LPTSTR) CmMalloc((dwSizeTmp + 1) * sizeof(TCHAR));
  9161. if (NULL == pszKeyName)
  9162. {
  9163. RegCloseKey(hKeyCm);
  9164. goto ShowError;
  9165. }
  9166. dwRes = RegEnumKeyExU(hKeyCm,
  9167. dwIndex,
  9168. pszKeyName,
  9169. &dwSizeTmp,
  9170. NULL,
  9171. NULL,
  9172. NULL,
  9173. pftLastWriteTime);
  9174. } while (ERROR_MORE_DATA == dwRes);
  9175. // now write the name of the sub key to the combo box
  9176. if (ERROR_SUCCESS == dwRes )
  9177. {
  9178. SendDlgItemMessageU(hwndParent, uiComboID, CB_ADDSTRING,
  9179. 0, (LPARAM)pszKeyName);
  9180. }
  9181. if (ERROR_SUCCESS != dwRes && ERROR_NO_MORE_ITEMS != dwRes)
  9182. {
  9183. CMTRACE1(TEXT("ShowAccessPointInfoFromReg() failed, GLE=%u."), GetLastError());
  9184. RegCloseKey(hKeyCm);
  9185. goto ShowError;
  9186. }
  9187. dwIndex ++;
  9188. } while(ERROR_NO_MORE_ITEMS != dwRes);
  9189. DWORD dwIdx = (DWORD)SendDlgItemMessageU(hwndParent,
  9190. uiComboID,
  9191. CB_FINDSTRINGEXACT,
  9192. 0,
  9193. (LPARAM)pArgs->pszCurrentAccessPoint);
  9194. if (dwIdx != CB_ERR)
  9195. {
  9196. SendDlgItemMessageU(hwndParent, uiComboID, CB_SETCURSEL, (WPARAM)dwIdx, 0L);
  9197. }
  9198. else
  9199. {
  9200. LPTSTR pszDefaultAccessPointName = CmLoadString(g_hInst, IDS_DEFAULT_ACCESSPOINT);
  9201. CMASSERTMSG(pszDefaultAccessPointName, TEXT("ShowAccessPointInfoFromReg -- CmLoadString of IDS_DEFAULT_ACCESSPOINT failed"));
  9202. if (pszDefaultAccessPointName)
  9203. {
  9204. dwIdx = (DWORD)SendDlgItemMessageU(hwndParent,
  9205. uiComboID,
  9206. CB_FINDSTRINGEXACT,
  9207. 0,
  9208. (LPARAM)pszDefaultAccessPointName);
  9209. if (dwIdx != CB_ERR)
  9210. {
  9211. SendDlgItemMessageU(hwndParent, uiComboID, CB_SETCURSEL, (WPARAM)dwIdx, 0L);
  9212. ChangedAccessPoint(pArgs, hwndParent, uiComboID);
  9213. }
  9214. CmFree(pszDefaultAccessPointName);
  9215. }
  9216. }
  9217. }
  9218. CmFree(pszKeyName);
  9219. CmFree(pszRegPath);
  9220. RegCloseKey(hKeyCm);
  9221. return TRUE;
  9222. }
  9223. ShowError:
  9224. CmFree(pszRegPath);
  9225. CmFree(pszKeyName);
  9226. return FALSE;
  9227. }
  9228. //+----------------------------------------------------------------------------
  9229. //
  9230. // Func: ChangedAccessPoint
  9231. //
  9232. // Desc: Changes the values of access point relevant stuff in pArgs
  9233. // if the value of the current access point changes
  9234. //
  9235. // Args: ArgsStruct *pArgs - Ptr to global args struct
  9236. //
  9237. // Return: BOOL - True if the access point has changed
  9238. //
  9239. // Notes:
  9240. //
  9241. // History: t-urama 07/28/2000 Created
  9242. //-----------------------------------------------------------------------------
  9243. BOOL ChangedAccessPoint(ArgsStruct *pArgs, HWND hwndDlg, UINT uiComboID)
  9244. {
  9245. BOOL bReturn = FALSE;
  9246. MYDBGASSERT(pArgs);
  9247. MYDBGASSERT(hwndDlg);
  9248. if ((NULL == pArgs) || (NULL == hwndDlg) || (NULL == pArgs->pszCurrentAccessPoint))
  9249. {
  9250. return FALSE;
  9251. }
  9252. HWND hwndCombo = GetDlgItem(hwndDlg, uiComboID);
  9253. if (hwndCombo)
  9254. {
  9255. LPTSTR pszAccessPoint = NULL;
  9256. LRESULT lRes = 0;
  9257. LRESULT lResTextLen = 0;
  9258. //
  9259. // Need to get the currently selected text from the combobox.
  9260. // Previously we used GetWindowTextU(hwndCombo, szAccessPoint, MAX_PATH+1), but it
  9261. // incorrectly returned the text.
  9262. // First get the selected index, find out the string length, allocate memory
  9263. //
  9264. lRes = SendMessageU(hwndCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  9265. if (CB_ERR != lRes)
  9266. {
  9267. lResTextLen = SendMessageU(hwndCombo, CB_GETLBTEXTLEN, (WPARAM)lRes, (LPARAM)0);
  9268. if (CB_ERR != lResTextLen)
  9269. {
  9270. pszAccessPoint = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lResTextLen+1));
  9271. if (NULL != pszAccessPoint)
  9272. {
  9273. //
  9274. // Retrieve the text.
  9275. //
  9276. lRes = SendMessageU(hwndCombo, CB_GETLBTEXT, (WPARAM)lRes, (LPARAM)pszAccessPoint);
  9277. if (CB_ERR != lRes)
  9278. {
  9279. if (0 != lstrcmpiU(pArgs->pszCurrentAccessPoint, pszAccessPoint))
  9280. {
  9281. CmFree(pArgs->pszCurrentAccessPoint);
  9282. pArgs->pszCurrentAccessPoint = CmStrCpyAlloc(pszAccessPoint);
  9283. if (pArgs->pszCurrentAccessPoint)
  9284. {
  9285. LPTSTR pszRegPath = FormRegPathFromAccessPoint(pArgs);
  9286. if (pszRegPath)
  9287. {
  9288. pArgs->piniBoth->SetPrimaryRegPath(pszRegPath);
  9289. pArgs->piniProfile->SetRegPath(pszRegPath);
  9290. CmFree(pszRegPath);
  9291. //
  9292. // First we determine our connect type
  9293. //
  9294. GetConnectType(pArgs);
  9295. //
  9296. // Set fUseTunneling. If not obvious (eg. direct VPN) then
  9297. // base the initial value upon the primary phone number.
  9298. //
  9299. if (pArgs->IsDirectConnect())
  9300. {
  9301. pArgs->fUseTunneling = TRUE;
  9302. }
  9303. else
  9304. {
  9305. pArgs->fUseTunneling = UseTunneling(pArgs, 0);
  9306. }
  9307. //
  9308. // Make sure we re-munge the phone number we are about to load.
  9309. //
  9310. pArgs->bDialInfoLoaded = FALSE;
  9311. //
  9312. // get new values for redial count, idle timeout, and the tapi location
  9313. //
  9314. LoadProperties(pArgs);
  9315. //
  9316. // get new values for phone info
  9317. //
  9318. LoadPhoneInfoFromProfile(pArgs);
  9319. PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName);
  9320. CMTRACE1(TEXT("ChangedAccessPoint() - Changed Access point to %s"), pArgs->pszCurrentAccessPoint);
  9321. bReturn = TRUE;
  9322. }
  9323. else
  9324. {
  9325. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- FormRegPathFromAccessPoint returned NULL"));
  9326. }
  9327. }
  9328. else
  9329. {
  9330. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- CmStrCpyAlloc returned NULL trying to copy the current access point."));
  9331. }
  9332. } // else, nothing to do if the favorites are the same
  9333. }
  9334. else
  9335. {
  9336. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETLBTEXT,...) returned CB_ERR"));
  9337. }
  9338. }
  9339. else
  9340. {
  9341. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- Unable to allocate memory"));
  9342. }
  9343. CmFree(pszAccessPoint);
  9344. }
  9345. else
  9346. {
  9347. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETLBTEXTLEN,...) returned CB_ERR"));
  9348. }
  9349. }
  9350. else
  9351. {
  9352. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETCURSEL,...) returned CB_ERR"));
  9353. }
  9354. }
  9355. else
  9356. {
  9357. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- Unable to get the combo HWND"));
  9358. }
  9359. return bReturn;
  9360. }
  9361. //----------------------------------------------------------------------------
  9362. //
  9363. // Function: FindEntryCredentialsForCM
  9364. //
  9365. // Synopsis: The algorithm and most of the code is taken from RAS and modified
  9366. // for use by CM.
  9367. //
  9368. // This routine determines whether per-user or per-connection credentials exist or
  9369. // both.
  9370. //
  9371. // The logic is a little complicated because RasGetCredentials had to
  9372. // support legacy usage of the API.
  9373. //
  9374. // Here's how it works. If only one set of credentials is stored for a
  9375. // connection, then RasGetCredentials will return that set regardless of
  9376. // whether the RASCM_DefaultCreds flag is set. If two sets of credentials
  9377. // are saved, then RasGetCredentials will return the per-user credentials
  9378. // if the RASCM_DefaultCreds bit is set, and the per-connection credentials
  9379. // otherwise.
  9380. //
  9381. // Here is the algorithm for loading the credentials
  9382. //
  9383. // 1. Call RasGetCredentials with the RASCM_DefaultCreds bit cleared
  9384. // 1a. If nothing is returned, no credentials are saved
  9385. // 1b. If the RASCM_DefaultCreds bit is set on return, then only
  9386. // global credentials are saved.
  9387. //
  9388. // 2. Call RasGetCredentials with the RASCM_DefaultCreds bit set
  9389. // 2a. If the RASCM_DefaultCreds bit is set on return, then
  9390. // both global and per-connection credentials are saved.
  9391. // 2b. Otherwise, only per-user credentials are saved.
  9392. //
  9393. // Arguments: pArgs - pointer to the ArgStruct
  9394. // pszPhoneBook - path to the phone book. Could be NULL.
  9395. // *pfUser - out param set true if per user creds found
  9396. // *pfGlobal - out param set true if global creds found
  9397. //
  9398. // Returns: BOOL - TRUE is succeeds else FALSE
  9399. //
  9400. // History: 01/31/2001 tomkel Created
  9401. //
  9402. //----------------------------------------------------------------------------
  9403. DWORD FindEntryCredentialsForCM(ArgsStruct *pArgs, LPTSTR pszPhoneBook,
  9404. BOOL *pfUser, BOOL *pfGlobal)
  9405. {
  9406. RASCREDENTIALS rc1 = {0};
  9407. RASCREDENTIALS rc2 = {0};
  9408. BOOL fUseLogonDomain = FALSE;
  9409. DWORD dwErr = ERROR_INVALID_PARAMETER;
  9410. LPTSTR pszConnectoid = NULL;
  9411. CMTRACE(TEXT("FindEntryCredentialsForCM() - Begin"));
  9412. if (NULL == pArgs || NULL == pfUser || NULL == pfGlobal)
  9413. {
  9414. MYDBGASSERT(pArgs && pfUser && pfGlobal);
  9415. CMTRACE(TEXT("FindEntryCredentialsForCM() - Error! Invalid Parameter."));
  9416. return dwErr;
  9417. }
  9418. //
  9419. // Initialize the out params
  9420. //
  9421. *pfUser = FALSE;
  9422. *pfGlobal = FALSE;
  9423. //
  9424. // After setting the OUT params, check if RAS dll have been loaded and if we can use the ras creds store
  9425. //
  9426. if (NULL == pArgs->rlsRasLink.pfnGetCredentials || FALSE == pArgs->bUseRasCredStore)
  9427. {
  9428. CMTRACE(TEXT("FindEntryCredentialsForCM() - RAS Creds store not supported on this platform."));
  9429. return ERROR_NOT_SUPPORTED;
  9430. }
  9431. //
  9432. // Set the size of the structures
  9433. //
  9434. rc1.dwSize = sizeof(rc1);
  9435. rc2.dwSize = sizeof(rc2);
  9436. //
  9437. // The third parameter is used only on Win9x (for tunneling) thus we set it to FALSE
  9438. // since this function is called on Win2K+
  9439. //
  9440. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  9441. if (pszConnectoid)
  9442. {
  9443. do
  9444. {
  9445. //
  9446. // Look up per-user cached username, password, and domain.
  9447. // See comment '1.' in the function header
  9448. //
  9449. rc1.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain;
  9450. dwErr = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &rc1);
  9451. CMTRACE2(TEXT("FindEntryCredentialsForCM() - Per-User RasGetCredentials=%d,m=%d"), dwErr, rc1.dwMask);
  9452. if (dwErr != NO_ERROR)
  9453. {
  9454. break;
  9455. }
  9456. if (0 == rc1.dwMask)
  9457. {
  9458. //
  9459. // See 1a. in the function header comments
  9460. //
  9461. dwErr = ERROR_SUCCESS;
  9462. break;
  9463. }
  9464. else if (rc1.dwMask & RASCM_DefaultCreds)
  9465. {
  9466. //
  9467. // See 1b. in the function header comments
  9468. //
  9469. *pfGlobal = TRUE;
  9470. //
  9471. // Assumed password was not encoded by RasGetCredentials()
  9472. //
  9473. CmEncodePassword(rc1.szPassword);
  9474. dwErr = ERROR_SUCCESS;
  9475. break;
  9476. }
  9477. //
  9478. // Look up global per-user cached username, password, domain.
  9479. // See comment 2. in the function header
  9480. //
  9481. rc2.dwMask =
  9482. RASCM_UserName | RASCM_Password | RASCM_Domain | RASCM_DefaultCreds;
  9483. dwErr = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &rc2);
  9484. CMTRACE2(TEXT("FindEntryCredentialsForCM() - Global RasGetCredentials=%d,m=%d"), dwErr, rc2.dwMask);
  9485. if (dwErr != ERROR_SUCCESS)
  9486. {
  9487. break;
  9488. }
  9489. if (rc2.dwMask & RASCM_DefaultCreds)
  9490. {
  9491. //
  9492. // See 2a. in the function header comments
  9493. //
  9494. *pfGlobal = TRUE;
  9495. if (rc1.dwMask & RASCM_Password)
  9496. {
  9497. *pfUser = TRUE;
  9498. }
  9499. //
  9500. // Assumed password was not encoded by RasGetCredentials()
  9501. //
  9502. CmEncodePassword(rc1.szPassword);
  9503. CmEncodePassword(rc2.szPassword);
  9504. }
  9505. else
  9506. {
  9507. //
  9508. // See 2b. in the function header comments
  9509. //
  9510. if (rc1.dwMask & RASCM_Password)
  9511. {
  9512. *pfUser = TRUE;
  9513. }
  9514. //
  9515. // Assumed password was not encoded by RasGetCredentials()
  9516. //
  9517. CmEncodePassword(rc1.szPassword);
  9518. }
  9519. }while (FALSE);
  9520. }
  9521. //
  9522. // Cleanup
  9523. //
  9524. CmSecureZeroMemory(rc1.szPassword, sizeof(rc1.szPassword));
  9525. CmSecureZeroMemory(rc2.szPassword, sizeof(rc2.szPassword));
  9526. CmFree(pszConnectoid);
  9527. CMTRACE(TEXT("FindEntryCredentialsForCM() - End"));
  9528. return dwErr;
  9529. }
  9530. //----------------------------------------------------------------------------
  9531. //
  9532. // Function: InitializeCredentialSupport
  9533. //
  9534. // Synopsis: Helper function to initialize user and global credential
  9535. // support. Some of the flags are redundantly initialized
  9536. // (to FALSE). That is done on purpose for clarity.
  9537. //
  9538. // Arguments: pArgs - the ArgStruct *
  9539. //
  9540. // Returns: BOOL - TRUE is succeeds else FALSE
  9541. //
  9542. // History: 01/31/2001 tomkel Created
  9543. //
  9544. //----------------------------------------------------------------------------
  9545. BOOL InitializeCredentialSupport(ArgsStruct *pArgs)
  9546. {
  9547. BOOL fGlobalCreds = FALSE;
  9548. BOOL fGlobalUserSettings = FALSE;
  9549. if (NULL == pArgs)
  9550. {
  9551. MYDBGASSERT(pArgs);
  9552. return FALSE;
  9553. }
  9554. //
  9555. // By default the the Internet Connection Sharing & Internet Connection
  9556. // Firewall (ICS) tab is disabled.
  9557. //
  9558. pArgs->bShowHNetCfgAdvancedTab = FALSE;
  9559. //
  9560. // User profile read/write support when user is logged off or using dial-up
  9561. // This flag determines if the user info needs to be also saved or loaded from
  9562. // the .cmp file
  9563. //
  9564. pArgs->dwGlobalUserInfo = 0;
  9565. //
  9566. // Credential existance flags - here we cannot yet determine which creds exist
  9567. // that is done in a later call to RefreshCredentialTypes
  9568. //
  9569. pArgs->dwExistingCredentials = 0;
  9570. //
  9571. // Default for which credential store to use - set based on the existance flag so
  9572. // this will also get set appropriatelly after a call to RefreshCredentialTypes
  9573. //
  9574. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9575. //
  9576. // Deletion flags - used to mark a set of creds for deletion. Since the
  9577. // user can Cancel out of a dialog we don't want to commit the changed
  9578. // until we actually do a dial.
  9579. //
  9580. pArgs->dwDeleteCredentials = 0;
  9581. //
  9582. // Check if this is WindowsXP. We want display the Advanced tab for single-user and
  9583. // all-user profiles
  9584. //
  9585. if (OS_NT51)
  9586. {
  9587. if (IsLogonAsSystem())
  9588. {
  9589. //
  9590. // LocalSystem - winlogon or ICS (in both cases user is logged off)
  9591. // WinLogon - creds are passed through MSGina
  9592. // ICS - need to use glocal creds store
  9593. // pArgs->dwWinLogonType was intialized in InitCredentials()
  9594. // We don't want to read ICSData info if this is a single user profile
  9595. //
  9596. if (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType || FALSE == pArgs->fAllUser)
  9597. {
  9598. pArgs->fGlobalCredentialsSupported = FALSE;
  9599. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9600. pArgs->dwGlobalUserInfo = 0;
  9601. }
  9602. else
  9603. {
  9604. pArgs->fGlobalCredentialsSupported = TRUE;
  9605. pArgs->dwCurrentCredentialType = CM_CREDS_GLOBAL;
  9606. pArgs->dwGlobalUserInfo |= CM_GLOBAL_USER_INFO_READ_ICS_DATA ;
  9607. }
  9608. CMTRACE(TEXT("InitializeCredentialSupport() - LocalSystem - Global creds OK."));
  9609. }
  9610. else
  9611. {
  9612. //
  9613. // User is logged on
  9614. //
  9615. //
  9616. // By default we want to we want to display the tab. By negating
  9617. // this value we can then correctly save it in the Args structure. This
  9618. // needs to be initialized for everyone
  9619. //
  9620. const TCHAR* const c_pszCmEntryHideICFICSAdvancedTab = TEXT("HideAdvancedTab");
  9621. pArgs->bShowHNetCfgAdvancedTab = !(pArgs->piniService->GPPB(c_pszCmSection,
  9622. c_pszCmEntryHideICFICSAdvancedTab,
  9623. FALSE));
  9624. //
  9625. // If this an all-user profile then we want to see if the profile enables
  9626. // global user settings and displays global credential options.
  9627. // These two features are disabled for single user profiles with the exception of
  9628. // showing the Advanced (ICS) tab
  9629. //
  9630. if (pArgs->fAllUser)
  9631. {
  9632. //
  9633. // If ICS is enabled then we need to support global user settings.
  9634. // Otherwise we read the setting from the file
  9635. //
  9636. if (pArgs->bShowHNetCfgAdvancedTab)
  9637. {
  9638. fGlobalUserSettings = TRUE;
  9639. }
  9640. else
  9641. {
  9642. //
  9643. // See if we support global user settings. By default is it off except if ICS is enabled
  9644. //
  9645. const TCHAR* const c_pszCmEntryGlobalUserSettings = TEXT("GlobalUserSettings");
  9646. fGlobalUserSettings = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryGlobalUserSettings, FALSE);
  9647. }
  9648. //
  9649. // Read the info from the .cms file. By default global credentials are supported
  9650. //
  9651. const TCHAR* const c_pszCmEntryHideGlobalCredentials = TEXT("GlobalCredentials");
  9652. fGlobalCreds = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideGlobalCredentials, TRUE);
  9653. }
  9654. //
  9655. // Check to see if we are going to be hiding the Save Password option, if so then
  9656. // we don't want to support global credentials
  9657. //
  9658. pArgs->fHideRememberPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberPwd);
  9659. if (fGlobalCreds && FALSE == pArgs->fHideRememberPassword)
  9660. {
  9661. //
  9662. // Global creds are supported
  9663. //
  9664. //
  9665. // Pick a default for creds type - it might change after calling RefreshCredentialTypes
  9666. //
  9667. pArgs->fGlobalCredentialsSupported = TRUE;
  9668. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9669. if (fGlobalUserSettings)
  9670. {
  9671. pArgs->dwGlobalUserInfo |= CM_GLOBAL_USER_INFO_WRITE_ICS_DATA;
  9672. }
  9673. CMTRACE(TEXT("InitializeCredentialSupport() - User, global creds, show global UI."));
  9674. }
  9675. else
  9676. {
  9677. //
  9678. // Global creds not supported
  9679. //
  9680. pArgs->fGlobalCredentialsSupported = FALSE;
  9681. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9682. pArgs->dwGlobalUserInfo = 0;
  9683. CMTRACE(TEXT("InitializeCredentialSupport() - User, no global creds, normal UI."));
  9684. }
  9685. }
  9686. }
  9687. else
  9688. {
  9689. //
  9690. // Single user or not WindowsXP
  9691. //
  9692. pArgs->fGlobalCredentialsSupported = FALSE;
  9693. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9694. pArgs->dwGlobalUserInfo = 0;
  9695. CMTRACE(TEXT("InitializeCredentialSupport() - Single User profile or not WindowsXP. Global creds not supported"));
  9696. }
  9697. return TRUE;
  9698. }
  9699. //----------------------------------------------------------------------------
  9700. //
  9701. // Function: RefreshCredentialTypes
  9702. //
  9703. // Synopsis: This refreshes credential info. If fSetCredsDefault is TRUE
  9704. // then we also need to set the default type:
  9705. // pArgs->dwCurrentCredentialType.
  9706. //
  9707. //
  9708. // Arguments: pArgs - the ArgStruct *
  9709. // fSetCredsDefault- used to set the default creds type
  9710. //
  9711. // Returns: BOOL - TRUE is succeeds else FALSE
  9712. //
  9713. // History: 01/31/2001 tomkel Created
  9714. //
  9715. //----------------------------------------------------------------------------
  9716. BOOL RefreshCredentialTypes(ArgsStruct *pArgs, BOOL fSetCredsDefault)
  9717. {
  9718. DWORD dwRC = ERROR_INVALID_PARAMETER;
  9719. LPTSTR pszPrivatePbk = NULL;
  9720. if (NULL == pArgs)
  9721. {
  9722. MYDBGASSERT(pArgs);
  9723. return FALSE;
  9724. }
  9725. //
  9726. // This should be run on Win2K+ whether this is an all user profile or not
  9727. // The call that actually determines which credentials exist makes sure we
  9728. // can use the ras cred store
  9729. //
  9730. if (OS_NT5)
  9731. {
  9732. BOOL fUserCredsExist = FALSE;
  9733. BOOL fGlobalCredsExist = FALSE;
  9734. //
  9735. // See if the main creds exist. Inside the function we determine whether
  9736. // we can use the RAS cred store
  9737. //
  9738. dwRC = FindEntryCredentialsForCM(pArgs,
  9739. pArgs->pszRasPbk,
  9740. &fUserCredsExist,
  9741. &fGlobalCredsExist);
  9742. if (ERROR_SUCCESS == dwRC)
  9743. {
  9744. CMTRACE2(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned: (Main) User=%d, Global=%d"),
  9745. fUserCredsExist, fGlobalCredsExist);
  9746. }
  9747. else
  9748. {
  9749. CMTRACE(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned an error. (Main)"));
  9750. }
  9751. //
  9752. // Set the existence flags
  9753. //
  9754. if (fUserCredsExist)
  9755. {
  9756. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_USER;
  9757. }
  9758. else
  9759. {
  9760. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  9761. }
  9762. if (fGlobalCredsExist)
  9763. {
  9764. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_GLOBAL;
  9765. }
  9766. else
  9767. {
  9768. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  9769. }
  9770. fUserCredsExist = FALSE;
  9771. fGlobalCredsExist = FALSE;
  9772. pszPrivatePbk = CreateRasPrivatePbk(pArgs);
  9773. if (pszPrivatePbk)
  9774. {
  9775. //
  9776. // See if the Internet creds exist - by using the private phonebook
  9777. // Inside the function we determine whether we can use the RAS cred store
  9778. //
  9779. dwRC = FindEntryCredentialsForCM(pArgs,
  9780. pszPrivatePbk,
  9781. &fUserCredsExist,
  9782. &fGlobalCredsExist);
  9783. if (ERROR_SUCCESS == dwRC)
  9784. {
  9785. CMTRACE2(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned: (Internet) User=%d, Global=%d"),
  9786. fUserCredsExist, fGlobalCredsExist);
  9787. }
  9788. else
  9789. {
  9790. CMTRACE(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned an error. (Internet)"));
  9791. }
  9792. }
  9793. //
  9794. // Set the flags whether or not we successfully created a private pbk
  9795. //
  9796. if (fUserCredsExist)
  9797. {
  9798. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_USER;
  9799. }
  9800. else
  9801. {
  9802. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  9803. }
  9804. if (fGlobalCredsExist)
  9805. {
  9806. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_GLOBAL;
  9807. }
  9808. else
  9809. {
  9810. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  9811. }
  9812. //
  9813. // If we don't support Global Creds then explicitly set
  9814. // the existance to FALSE. This can occur if the .cms flag
  9815. // is set not to support global creds, but there are actually
  9816. // global creds on the system.
  9817. //
  9818. if (FALSE == pArgs->fGlobalCredentialsSupported)
  9819. {
  9820. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  9821. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  9822. CMTRACE(TEXT("RefreshCredentialTypes() - Global Credentials are disabled."));
  9823. }
  9824. if (fSetCredsDefault)
  9825. {
  9826. pArgs->dwCurrentCredentialType = GetCurrentCredentialType(pArgs);
  9827. CMTRACE1(TEXT("RefreshCredentialTypes() - Set default Credentials = %d"), pArgs->dwCurrentCredentialType);
  9828. }
  9829. }
  9830. CmFree(pszPrivatePbk);
  9831. return TRUE;
  9832. }
  9833. //----------------------------------------------------------------------------
  9834. //
  9835. // Function: GetCurrentCredentialType
  9836. //
  9837. // Synopsis: Gets the default credentials based on which ones exist based
  9838. // on which flags are set. This function should be called only
  9839. // after RefreshCredentialTypes since that function actually
  9840. // queries the RAS creds store. This one only looks up the cached
  9841. // status of those creds and determines the default according to
  9842. // what credentials exist.
  9843. //
  9844. // Arguments: pArgs - the ArgStruct *
  9845. // fSetCredsDefault- used to set the default creds type
  9846. //
  9847. // Returns: BOOL - TRUE is succeeds else FALSE
  9848. //
  9849. // History: 01/31/2001 tomkel Created
  9850. //
  9851. //----------------------------------------------------------------------------
  9852. DWORD GetCurrentCredentialType(ArgsStruct *pArgs)
  9853. {
  9854. DWORD dwReturn = CM_CREDS_USER;
  9855. if (NULL == pArgs)
  9856. {
  9857. MYDBGASSERT(pArgs);
  9858. return dwReturn;
  9859. }
  9860. //
  9861. // If Global creds aren't supported as in WinLogon case or single-user
  9862. // profiles or anything below WinXP, the default is User Creds Store
  9863. //
  9864. if (FALSE == pArgs->fGlobalCredentialsSupported)
  9865. {
  9866. return dwReturn;
  9867. }
  9868. //
  9869. // Normal Rules when a user is logged on
  9870. //
  9871. if (CM_LOGON_TYPE_USER == pArgs->dwWinLogonType)
  9872. {
  9873. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)
  9874. {
  9875. //
  9876. // Doesn't matter if main global creds exist since main user credentials
  9877. // have precendence if both exist
  9878. //
  9879. dwReturn = CM_CREDS_USER;
  9880. }
  9881. else if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)
  9882. {
  9883. dwReturn = CM_CREDS_GLOBAL;
  9884. }
  9885. else
  9886. {
  9887. //
  9888. // If none of them exist then we want to default to user creds
  9889. //
  9890. dwReturn = CM_CREDS_USER;
  9891. }
  9892. }
  9893. else
  9894. {
  9895. //
  9896. // In any other case dafult to global creds - (ICS scenario)
  9897. //
  9898. dwReturn = CM_CREDS_GLOBAL;
  9899. }
  9900. return dwReturn;
  9901. }
  9902. //----------------------------------------------------------------------------
  9903. //
  9904. // Function: DeleteSavedCredentials
  9905. //
  9906. // Synopsis: Helper function to delete credentials from the RAS store.
  9907. //
  9908. // Arguments: pArgs - the ArgStruct *
  9909. // dwCredsType - Normal or Internet credentials
  9910. // fDeleteGlobal - specifies whether to delete global credentials.
  9911. // If TRUE we delete user, domain name,
  9912. // password as well
  9913. // fDeleteIdentity - specifies whether to delete the user and
  9914. // domain names in addition to the password
  9915. //
  9916. // Returns: BOOL - TRUE is succeeds else FALSE
  9917. //
  9918. // History: 01/31/2001 tomkel Created
  9919. //
  9920. //----------------------------------------------------------------------------
  9921. BOOL DeleteSavedCredentials(ArgsStruct *pArgs, DWORD dwCredsType, BOOL fDeleteGlobal, BOOL fDeleteIdentity)
  9922. {
  9923. RASCREDENTIALS rc;
  9924. BOOL fReturn = FALSE;
  9925. DWORD dwErr = ERROR_INVALID_PARAMETER;
  9926. LPTSTR pszConnectoid = NULL;
  9927. CMTRACE2(TEXT("DeleteSavedCredentials() - Begin: %d %d"), fDeleteGlobal, fDeleteIdentity );
  9928. if (NULL == pArgs)
  9929. {
  9930. MYDBGASSERT(pArgs);
  9931. return fReturn;
  9932. }
  9933. //
  9934. // Check if globals should be deleted in case globals are not supported.
  9935. // This can be in case of global creds are disabled on WinXP or this is
  9936. // Win2K or the platform < Win2K where RASSetCredentials isn't even supported.
  9937. // Thus we still should return TRUE
  9938. //
  9939. if ((fDeleteGlobal && FALSE == pArgs->fGlobalCredentialsSupported) ||
  9940. (NULL == pArgs->rlsRasLink.pfnSetCredentials) ||
  9941. (FALSE == pArgs->bUseRasCredStore))
  9942. {
  9943. CMTRACE(TEXT("DeleteSavedCredentials() - Global Creds not supported or do not have ras store on this platform."));
  9944. return TRUE;
  9945. }
  9946. //
  9947. // We don't support deleting globals on Win2K (that is caught by the above if since Win2K
  9948. // will not have global credentials supported. Otherwise on Win2K we can delete the main
  9949. // user creds. On WinXP anything is fine.
  9950. //
  9951. if (OS_NT5)
  9952. {
  9953. ZeroMemory(&rc, sizeof(rc));
  9954. rc.dwSize = sizeof(RASCREDENTIALS);
  9955. rc.dwMask = RASCM_Password;
  9956. if (fDeleteIdentity)
  9957. {
  9958. rc.dwMask |= (RASCM_UserName | RASCM_Domain);
  9959. }
  9960. if (fDeleteGlobal && pArgs->fGlobalCredentialsSupported)
  9961. {
  9962. rc.dwMask |= RASCM_UserName | RASCM_Domain | RASCM_DefaultCreds;
  9963. }
  9964. //
  9965. // The third parameter is used only on Win9x (for tunneling) thus we set it to FALSE
  9966. // since this function is called on Win2K+
  9967. //
  9968. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  9969. if (pszConnectoid)
  9970. {
  9971. if (CM_CREDS_TYPE_INET == dwCredsType)
  9972. {
  9973. LPTSTR pszPrivatePbk = CreateRasPrivatePbk(pArgs);
  9974. if (pszPrivatePbk)
  9975. {
  9976. dwErr = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePbk,
  9977. pszConnectoid,
  9978. &rc,
  9979. TRUE );
  9980. CmFree(pszPrivatePbk);
  9981. }
  9982. }
  9983. else
  9984. {
  9985. dwErr = pArgs->rlsRasLink.pfnSetCredentials(pArgs->pszRasPbk,
  9986. pszConnectoid,
  9987. &rc,
  9988. TRUE );
  9989. }
  9990. if (ERROR_SUCCESS == dwErr)
  9991. {
  9992. fReturn = TRUE;
  9993. }
  9994. }
  9995. CMTRACE1(TEXT("DeleteSavedCredentials() - End: RasSetCredentials=%d"), dwErr );
  9996. }
  9997. else
  9998. {
  9999. CMTRACE(TEXT("DeleteSavedCredentials() - Platform is less than Win2K"));
  10000. }
  10001. CmFree(pszConnectoid);
  10002. return fReturn;
  10003. }
  10004. //+---------------------------------------------------------------------------
  10005. //
  10006. // Function: SetCredentialUIOptionBasedOnDefaultCreds
  10007. //
  10008. // Synopsis: Selects (checks) the appropriate UI option for saving credentials
  10009. // based on the current credential store default.
  10010. //
  10011. // Arguments: pArgs - ptr to ArgsStruct
  10012. // hwndDlg - handle to the dialog window
  10013. //
  10014. // Returns: NONE
  10015. //
  10016. // History: 02/05/2001 tomkel Created
  10017. //
  10018. //----------------------------------------------------------------------------
  10019. VOID SetCredentialUIOptionBasedOnDefaultCreds(ArgsStruct *pArgs, HWND hwndDlg)
  10020. {
  10021. if (NULL == pArgs || NULL == hwndDlg)
  10022. {
  10023. MYDBGASSERT(pArgs && hwndDlg);
  10024. return;
  10025. }
  10026. //
  10027. // fGlobalCredentialsSupported controls which dialog templates get loaded and
  10028. // if the flag is FALSE then the dialog template doesn't have these controls
  10029. // thus there is no reason to set them.
  10030. //
  10031. if (pArgs->fGlobalCredentialsSupported)
  10032. {
  10033. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  10034. {
  10035. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_UNCHECKED);
  10036. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_CHECKED);
  10037. }
  10038. else
  10039. {
  10040. //
  10041. // CM_CREDS_USER
  10042. //
  10043. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_CHECKED);
  10044. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_UNCHECKED);
  10045. }
  10046. }
  10047. return;
  10048. }
  10049. //+---------------------------------------------------------------------------
  10050. //
  10051. // Function: RefreshCredentialInfo
  10052. //
  10053. // Synopsis: This is a slimmed down version of LoadProperties. It only
  10054. // loads user info from cmp/cms, registry, password
  10055. // cache, etc, into its internal variables.
  10056. //
  10057. //
  10058. // Arguments: pArgs - ptr to ArgsStruct
  10059. // dwCredsType - type of credentials to refresh
  10060. //
  10061. // Returns: NONE
  10062. //
  10063. // History: 02/05/2001 tomkel Created
  10064. //
  10065. //----------------------------------------------------------------------------
  10066. VOID RefreshCredentialInfo(ArgsStruct *pArgs, DWORD dwCredsType)
  10067. {
  10068. LPTSTR pszTmp = NULL;
  10069. LPTSTR pszUserName = NULL;
  10070. UINT nTmp;
  10071. CMTRACE(TEXT("RefreshCredentialInfo() - Begin"));
  10072. if (NULL == pArgs)
  10073. {
  10074. MYDBGASSERT(pArgs);
  10075. return;
  10076. }
  10077. if (IsTunnelEnabled(pArgs))
  10078. {
  10079. if (CM_CREDS_TYPE_BOTH == dwCredsType || CM_CREDS_TYPE_INET == dwCredsType)
  10080. {
  10081. //
  10082. // read in inet username
  10083. // Special case where the same user name isn't being used, and internet globals don't exist
  10084. // Then we have to read the user name from the user creds store in order to pre-populate
  10085. //
  10086. DWORD dwRememberedCredType = pArgs->dwCurrentCredentialType;
  10087. pszUserName = NULL;
  10088. if ((FALSE == pArgs->fUseSameUserName) &&
  10089. (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType) &&
  10090. (FALSE == (BOOL)(CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)))
  10091. {
  10092. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  10093. }
  10094. GetUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszUserName);
  10095. //
  10096. // Restore credential store
  10097. //
  10098. pArgs->dwCurrentCredentialType = dwRememberedCredType;
  10099. if (pszUserName)
  10100. {
  10101. //
  10102. // check username length
  10103. //
  10104. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  10105. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  10106. {
  10107. CmFree(pszUserName);
  10108. pArgs->szInetUserName[0] = TEXT('\0');
  10109. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  10110. }
  10111. else
  10112. {
  10113. lstrcpyU(pArgs->szInetUserName, pszUserName);
  10114. CmFree(pszUserName);
  10115. }
  10116. }
  10117. else
  10118. {
  10119. *pArgs->szInetUserName = TEXT('\0');
  10120. }
  10121. //
  10122. // Read in inet password unless we are reconnecting in which case, we
  10123. // already have the correct password, and we want to use it and dial
  10124. // automatically.
  10125. //
  10126. if (!(pArgs->dwFlags & FL_RECONNECT))
  10127. {
  10128. LPTSTR pszPassword = NULL;
  10129. GetUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszPassword);
  10130. if (!pszPassword)
  10131. {
  10132. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  10133. }
  10134. else
  10135. {
  10136. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  10137. if ((UINT)lstrlenU(pszPassword) > __min(PWLEN, nTmp))
  10138. {
  10139. CmFree(pszPassword);
  10140. pszPassword = CmStrCpyAlloc(TEXT(""));
  10141. }
  10142. (VOID)pArgs->SecureInetPW.SetPassword(pszPassword);
  10143. CmWipePassword(pszPassword);
  10144. CmFree(pszPassword);
  10145. }
  10146. }
  10147. }
  10148. }
  10149. if (CM_CREDS_TYPE_BOTH == dwCredsType || CM_CREDS_TYPE_MAIN == dwCredsType)
  10150. {
  10151. //
  10152. // The presence of either lpRasNoUser or lpEapLogonInfo indicates
  10153. // that we retrieved credentials via WinLogon. We ignore cached
  10154. // creds in this situation.
  10155. //
  10156. if ((!pArgs->lpRasNoUser) && (!pArgs->lpEapLogonInfo))
  10157. {
  10158. //
  10159. // get username, domain, etc. from CMS file
  10160. //
  10161. GetUserInfo(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  10162. if (pszUserName)
  10163. {
  10164. //
  10165. // check username length
  10166. //
  10167. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  10168. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  10169. {
  10170. CmFree(pszUserName);
  10171. pszUserName = CmStrCpyAlloc(TEXT(""));
  10172. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUserName);
  10173. }
  10174. lstrcpyU(pArgs->szUserName, pszUserName);
  10175. CmFree(pszUserName);
  10176. }
  10177. else
  10178. {
  10179. *pArgs->szUserName = TEXT('\0');
  10180. }
  10181. //
  10182. // Read in the standard password unless we are reconnecting in which case
  10183. // we already have the correct password, and we want to use it and dial
  10184. // automatically.
  10185. //
  10186. if (!(pArgs->dwFlags & FL_RECONNECT))
  10187. {
  10188. pszTmp = NULL;
  10189. GetUserInfo(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp);
  10190. if (pszTmp)
  10191. {
  10192. //
  10193. // max length for user password
  10194. //
  10195. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryMaxPassword,PWLEN);
  10196. if ((UINT)lstrlenU(pszTmp) > __min(PWLEN,nTmp))
  10197. {
  10198. CmFree(pszTmp);
  10199. pszTmp = CmStrCpyAlloc(TEXT(""));
  10200. }
  10201. (VOID)pArgs->SecurePW.SetPassword(pszTmp);
  10202. CmWipePassword(pszTmp);
  10203. CmFree(pszTmp);
  10204. }
  10205. else
  10206. {
  10207. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  10208. }
  10209. }
  10210. //
  10211. // Load domain info
  10212. //
  10213. LPTSTR pszDomain = NULL;
  10214. GetUserInfo(pArgs, UD_ID_DOMAIN, (PVOID*)&pszDomain);
  10215. if (pszDomain)
  10216. {
  10217. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  10218. if (nTmp <= 0)
  10219. {
  10220. nTmp = DNLEN;
  10221. }
  10222. if ((UINT)lstrlenU(pszDomain) > __min(DNLEN, nTmp))
  10223. {
  10224. CmFree(pszDomain);
  10225. pszDomain = CmStrCpyAlloc(TEXT(""));
  10226. }
  10227. lstrcpyU(pArgs->szDomain, pszDomain);
  10228. CmFree(pszDomain);
  10229. }
  10230. else
  10231. {
  10232. *pArgs->szDomain = TEXT('\0');
  10233. }
  10234. }
  10235. }
  10236. CMTRACE(TEXT("RefreshCredentialInfo() - End"));
  10237. return;
  10238. }
  10239. //+---------------------------------------------------------------------------
  10240. //
  10241. // Function: GetAndStoreUserInfo
  10242. //
  10243. // Synopsis: Most of this code existed in the OnMainConnect function.
  10244. // Gets the username, domain, password from the edit boxes and saves them
  10245. // to the internal structure pArgs->szUserName, pArgs->szPassword, pArgs->szDomain
  10246. // if the fSaveOtherUserInfo is TRUE then it also saves them to the appropriate
  10247. // place (RAS store, reg, etc.)
  10248. //
  10249. // Arguments: pArgs - ptr to ArgsStruct
  10250. // hwndDlg - handle to the dialog window
  10251. // fSaveUPD - save UserName, Password, Domain (U, P, D)
  10252. // fSaveOtherUserInfo - flag whether to save other userinfo (excluding U, P, D)
  10253. //
  10254. // Returns: NONE
  10255. //
  10256. // History: 02/05/2001 tomkel Created
  10257. //
  10258. //----------------------------------------------------------------------------
  10259. VOID GetAndStoreUserInfo(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSaveUPD, BOOL fSaveOtherUserInfo)
  10260. {
  10261. if (NULL == pArgs || NULL == hwndDlg)
  10262. {
  10263. MYDBGASSERT(pArgs && hwndDlg);
  10264. return;
  10265. }
  10266. //
  10267. // Process UserName info, if any
  10268. //
  10269. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  10270. {
  10271. LPTSTR pszUsername = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  10272. //
  10273. // save the user info
  10274. //
  10275. if (fSaveUPD)
  10276. {
  10277. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUsername);
  10278. }
  10279. lstrcpyU(pArgs->szUserName, pszUsername);
  10280. CmFree(pszUsername);
  10281. }
  10282. else
  10283. {
  10284. //
  10285. // In case the user name field is hidden then just re-save what's in the
  10286. // structure. This needs to be done since all of the credentials might have
  10287. // been deleted from the ras cred store
  10288. //
  10289. if (fSaveUPD)
  10290. {
  10291. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pArgs->szUserName);
  10292. }
  10293. }
  10294. //
  10295. // Update password related flags
  10296. //
  10297. if (!pArgs->fHideRememberPassword)
  10298. {
  10299. //
  10300. // save "Remember password"
  10301. //
  10302. if (fSaveOtherUserInfo)
  10303. {
  10304. SaveUserInfo(pArgs, UD_ID_REMEMBER_PWD,
  10305. (PVOID)&pArgs->fRememberMainPassword);
  10306. }
  10307. }
  10308. if (!pArgs->fHideDialAutomatically)
  10309. {
  10310. //
  10311. // save "Dial automatically..."
  10312. //
  10313. if (fSaveOtherUserInfo)
  10314. {
  10315. SaveUserInfo(pArgs, UD_ID_NOPROMPT,
  10316. (PVOID)&pArgs->fDialAutomatically);
  10317. }
  10318. }
  10319. //
  10320. // Process Password info, if any. If field is hidden, then don't save anything.
  10321. //
  10322. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  10323. if (hwndPassword)
  10324. {
  10325. BOOL fSavePassword = TRUE;
  10326. //
  10327. // We don't want to copy the password into pArgs structure if fSaveUPD isn't true,
  10328. // because it will be obfuscated in this case. The password is already in the structure
  10329. // on Win2K+
  10330. //
  10331. if (fSaveUPD)
  10332. {
  10333. //
  10334. // Get the latest password data from the edit control
  10335. // and obfuscate its contents so that connect actions
  10336. // can't retrieve it.
  10337. //
  10338. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  10339. ObfuscatePasswordEdit(pArgs);
  10340. //
  10341. // Check if we have 16 *'s
  10342. //
  10343. if ((pArgs->SecurePW.IsHandleToPassword()) &&
  10344. (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L)))
  10345. {
  10346. //
  10347. // We have 16 *'s and the user hasn't modified the editbox. This
  10348. // password is from the RAS cred store, so we don't want to save the 16 *'s
  10349. //
  10350. fSavePassword = FALSE;
  10351. }
  10352. }
  10353. //
  10354. // For winlogon we need to take the password from the edit box
  10355. //
  10356. if (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType)
  10357. {
  10358. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  10359. }
  10360. //
  10361. // Update persistent storage
  10362. // No need to delete the password here as it was done by the calling function
  10363. //
  10364. if (pArgs->fRememberMainPassword)
  10365. {
  10366. //
  10367. // If the password has changed, then update storage
  10368. // Always save password - 303382
  10369. //
  10370. if (fSaveUPD && fSavePassword)
  10371. {
  10372. LPTSTR pszClearPassword = NULL;
  10373. DWORD cbClearPassword = 0;
  10374. BOOL fRetPassword = FALSE;
  10375. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  10376. if (fRetPassword && pszClearPassword)
  10377. {
  10378. SaveUserInfo(pArgs, UD_ID_PASSWORD, (PVOID)pszClearPassword);
  10379. //
  10380. // Clear and Free the clear-text password
  10381. //
  10382. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  10383. }
  10384. }
  10385. //
  10386. // Check DialAutomatically and carry remember state
  10387. // over to InetPassword if it isn't remembered already.
  10388. //
  10389. // Need to check if this is a double-dial scenario. Also need to check if we are
  10390. // allowed to save UPD, otherwise we don't want to change the state mainly
  10391. // (pArgs->fRememberInetPassword)
  10392. //
  10393. if (pArgs->fDialAutomatically && fSaveUPD &&
  10394. (DOUBLE_DIAL_CONNECTION == pArgs->GetTypeOfConnection()))
  10395. {
  10396. //
  10397. // Carry remember state from DialAutomatically over to
  10398. // InetPassword if it isn't already remembered.
  10399. //
  10400. if (!pArgs->fRememberInetPassword)
  10401. {
  10402. pArgs->fRememberInetPassword = TRUE;
  10403. if (fSavePassword)
  10404. {
  10405. LPTSTR pszClearInetPassword = NULL;
  10406. DWORD cbClearInetPassword = 0;
  10407. BOOL fRetPassword = FALSE;
  10408. fRetPassword = pArgs->SecureInetPW.GetPasswordWithAlloc(&pszClearInetPassword, &cbClearInetPassword);
  10409. if (fRetPassword && pszClearInetPassword)
  10410. {
  10411. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pszClearInetPassword);
  10412. //
  10413. // Clear and Free the clear-text password
  10414. //
  10415. pArgs->SecureInetPW.ClearAndFree(&pszClearInetPassword, cbClearInetPassword);
  10416. }
  10417. }
  10418. }
  10419. }
  10420. }
  10421. else
  10422. {
  10423. //
  10424. // If we don't have the ras cred store then the password wasn't deleted
  10425. // so we must deleted by calling this function
  10426. //
  10427. if (fSavePassword) // No need to check fSaveUPD, taken care of ras creds store check
  10428. {
  10429. if (FALSE == pArgs->bUseRasCredStore)
  10430. {
  10431. DeleteUserInfo(pArgs, UD_ID_PASSWORD);
  10432. }
  10433. }
  10434. }
  10435. if (fSaveUPD)
  10436. {
  10437. BOOL fSaveInetPassword = TRUE;
  10438. //
  10439. // Check if we have 16 *'s for Internet Password.
  10440. //
  10441. if (pArgs->SecureInetPW.IsHandleToPassword())
  10442. {
  10443. //
  10444. // We have 16 *'s This password is from the RAS cred store, so we don't want to save the 16 *'s
  10445. //
  10446. fSaveInetPassword = FALSE;
  10447. }
  10448. //
  10449. // Check to see if we should re-save Internet creds
  10450. // This needs to be done here in case the user has switched between
  10451. // global and local credentials using the option buttons while having Internet
  10452. // credentials set in the Internet Login (CInetPage) property sheet. By switching
  10453. // the options, the user switched the current credential store
  10454. // (pArgs->dwCurrentCredentialType) so in order not to lose that data, we need to
  10455. // re-save the internet creds. Re-saving puts them in the correct (global or local)
  10456. // ras cred store.
  10457. // When the username is the same and we saved the main password (SaveUserInfo)
  10458. // this also saves the password to the Internet creds store
  10459. //
  10460. if (pArgs->fUseSameUserName)
  10461. {
  10462. if (fSaveInetPassword)
  10463. {
  10464. if (pArgs->fRememberMainPassword)
  10465. {
  10466. //
  10467. // Save the UserName into the InetUserName field
  10468. // Password has been saved when saving UD_ID_PASSWORD. There is a special
  10469. // case that also saves the main password as the internet password
  10470. //
  10471. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szUserName);
  10472. pArgs->fRememberInetPassword = TRUE;
  10473. }
  10474. else
  10475. {
  10476. if (FALSE == pArgs->bUseRasCredStore)
  10477. {
  10478. DeleteUserInfo(pArgs, UD_ID_INET_PASSWORD);
  10479. pArgs->fRememberInetPassword = FALSE;
  10480. }
  10481. }
  10482. }
  10483. }
  10484. else
  10485. {
  10486. if (fSaveInetPassword)
  10487. {
  10488. if(pArgs->fRememberInetPassword)
  10489. {
  10490. LPTSTR pszClearInetPassword = NULL;
  10491. DWORD cbClearInetPassword = 0;
  10492. BOOL fRetPassword = FALSE;
  10493. fRetPassword = pArgs->SecureInetPW.GetPasswordWithAlloc(&pszClearInetPassword, &cbClearInetPassword);
  10494. if (fRetPassword && pszClearInetPassword)
  10495. {
  10496. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pszClearInetPassword);
  10497. //
  10498. // Clear and Free the clear-text password
  10499. //
  10500. pArgs->SecureInetPW.ClearAndFree(&pszClearInetPassword, cbClearInetPassword);
  10501. }
  10502. }
  10503. else
  10504. {
  10505. if (FALSE == pArgs->bUseRasCredStore)
  10506. {
  10507. DeleteUserInfo(pArgs, UD_ID_INET_PASSWORD);
  10508. }
  10509. }
  10510. }
  10511. //
  10512. // Need to save username in either case so we can pre-populate this
  10513. //
  10514. SaveUserInfo(pArgs, UD_ID_INET_USERNAME,
  10515. (PVOID)pArgs->szInetUserName);
  10516. }
  10517. }
  10518. }
  10519. //
  10520. // This should be saved in all cases except ICS
  10521. //
  10522. if (fSaveOtherUserInfo)
  10523. {
  10524. SaveUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, (PVOID)&pArgs->fRememberInetPassword);
  10525. }
  10526. //
  10527. // Process Domain info, if any
  10528. //
  10529. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  10530. {
  10531. LPTSTR pszDomain = CmGetWindowTextAlloc(hwndDlg,IDC_MAIN_DOMAIN_EDIT);
  10532. //
  10533. // save the user info
  10534. //
  10535. if (fSaveUPD)
  10536. {
  10537. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pszDomain);
  10538. }
  10539. lstrcpyU(pArgs->szDomain, pszDomain);
  10540. CmFree(pszDomain);
  10541. }
  10542. else
  10543. {
  10544. //
  10545. // In case the domain field is hidden then just re-save what's in the
  10546. // structure. This needs to be done since all of the credentials might have
  10547. // been deleted from the ras cred store.
  10548. //
  10549. if (fSaveUPD)
  10550. {
  10551. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pArgs->szDomain);
  10552. }
  10553. }
  10554. return;
  10555. }
  10556. //+---------------------------------------------------------------------------
  10557. //
  10558. // Function: SetIniObjectReadWriteFlags
  10559. //
  10560. // Synopsis: If the read or write flags are set we need to enable reading and/or
  10561. // writing to the .CMP file. Each instance of the CIni class may
  10562. // or may not use the .cmp file. It can also be using the .CMP as either
  10563. // the primary file or normal file. See InitProfileFromName function
  10564. // in init.cpp for detailed comments about these instances.
  10565. //
  10566. // pArgs->piniProfile - uses .CMP as a regular file
  10567. // pArgs->piniService - doesn't use .CMP file at all
  10568. // pArgs->piniBoth - uses .CMP as a primary file
  10569. // pArgs->piniBothNonFav - uses .CMP as a primary file
  10570. //
  10571. // Arguments: pArgs - ptr to ArgsStruct
  10572. //
  10573. // Returns: NONE
  10574. //
  10575. // History: 02/14/2001 tomkel Created
  10576. //
  10577. //----------------------------------------------------------------------------
  10578. VOID SetIniObjectReadWriteFlags(ArgsStruct *pArgs)
  10579. {
  10580. if (NULL == pArgs)
  10581. {
  10582. MYDBGASSERT(pArgs);
  10583. return;
  10584. }
  10585. BOOL fWriteICSInfo = FALSE;
  10586. BOOL fReadGlobalICSInfo = FALSE;
  10587. //
  10588. // Get the read flag
  10589. //
  10590. fReadGlobalICSInfo = ((BOOL)(pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA) ? TRUE : FALSE);
  10591. //
  10592. // Get the write flag.
  10593. //
  10594. fWriteICSInfo = ((BOOL)(pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_WRITE_ICS_DATA) ? TRUE : FALSE);
  10595. if (fReadGlobalICSInfo || fWriteICSInfo)
  10596. {
  10597. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  10598. if (pszICSDataReg)
  10599. {
  10600. //
  10601. // Now that there is a reg key and at least one of the above flags is TRUE,
  10602. // then we want to set the read and write flags in the classes. By default
  10603. // they are set to FALSE in the constructors, so we don't have to
  10604. // explicitly set them if we don't need this functionality.
  10605. //
  10606. // Set ICSData reg key
  10607. //
  10608. pArgs->piniProfile->SetICSDataPath(pszICSDataReg);
  10609. pArgs->piniBoth->SetICSDataPath(pszICSDataReg);
  10610. pArgs->piniBothNonFav->SetICSDataPath(pszICSDataReg);
  10611. //
  10612. // Set Write flag since we have a reg key
  10613. //
  10614. pArgs->piniProfile->SetWriteICSData(fWriteICSInfo);
  10615. pArgs->piniBoth->SetWriteICSData(fWriteICSInfo);
  10616. pArgs->piniBothNonFav->SetWriteICSData(fWriteICSInfo);
  10617. //
  10618. // Set Read flag since we have a reg key
  10619. //
  10620. pArgs->piniProfile->SetReadICSData(fReadGlobalICSInfo);
  10621. pArgs->piniBoth->SetReadICSData(fReadGlobalICSInfo);
  10622. pArgs->piniBothNonFav->SetReadICSData(fReadGlobalICSInfo);
  10623. }
  10624. CmFree(pszICSDataReg);
  10625. }
  10626. return;
  10627. }
  10628. //----------------------------------------------------------------------------
  10629. //
  10630. // Function: TryToDeleteAndSaveCredentials
  10631. //
  10632. // Synopsis: Used on Win2K and WinXP+. This function uses the RAS Credential
  10633. // store to save and delete credentials based on user's selection.
  10634. // First we need to determine if the user is saving their password.
  10635. // Then appropriately delete or prompt to delete existing credentials.
  10636. // If we aren't saving any credentials, then delete all of them.
  10637. // The special case is if the user is deleting his local credentials
  10638. // and global credentials exist on the system. Then we have to prompt
  10639. // if we should delete the global creds as well.
  10640. // Toward the botton of the function we get the info from the UI.
  10641. // If the password is 16 *'s then we don't save the password After
  10642. // getting info from the UI, we save it in the RAS Cred store.
  10643. // Internet credentials are saved if we are using the same user
  10644. // name. Otherwise we leave the Internet creds. They were saved
  10645. // on the Inet properties page. There is a scenario where the user
  10646. // saved the internet creds on the property page and then switched
  10647. // the way credentials should be saved (global vs. local) which might cause
  10648. // the internet password to be stored under in the wrong (global vs. local)
  10649. // ras store. If the passwords are disjoined (pArgs->fUseSameUserName is FALSE)
  10650. // there isn't much we can do.
  10651. //
  10652. // NOTE: We only want to delete credentials if and only if the existence
  10653. // flag are set! This is to prevent from deleting mainly global credentials
  10654. // in a certain profile where global credentials are disabled.
  10655. //
  10656. //
  10657. // Arguments: pArgs - ptr to ArgsStruct
  10658. // hwndDlg - HWND to dialog
  10659. //
  10660. // Returns: NONE
  10661. //
  10662. // History: 03/24/2001 tomkel Created
  10663. //
  10664. //----------------------------------------------------------------------------
  10665. VOID TryToDeleteAndSaveCredentials(ArgsStruct *pArgs, HWND hwndDlg)
  10666. {
  10667. if (NULL == pArgs || NULL == hwndDlg)
  10668. {
  10669. MYDBGASSERT(pArgs && hwndDlg);
  10670. return;
  10671. }
  10672. //
  10673. // Check if this is Win2K+ (That's where RAS Creds store is supported)
  10674. //
  10675. if (!OS_NT5)
  10676. {
  10677. MYDBGASSERT(FALSE);
  10678. return;
  10679. }
  10680. BOOL fSave = FALSE;
  10681. BOOL fResaveInetUserCreds = FALSE;
  10682. RASCREDENTIALS rc = {0};
  10683. RASCREDENTIALS rcInet={0};
  10684. rc.dwSize = sizeof(rc);
  10685. rcInet.dwSize = sizeof(rcInet);
  10686. //
  10687. // See if we want to save the credentials
  10688. //
  10689. if (pArgs->fRememberMainPassword)
  10690. {
  10691. //
  10692. // Which password are we saving?
  10693. //
  10694. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  10695. {
  10696. //
  10697. // Delete User creds w/o asking. No need to check for existence since these
  10698. // are just user (main & inet) creds.
  10699. //
  10700. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10701. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  10702. rc.dwMask = RASCM_DefaultCreds;
  10703. //
  10704. // Delete Internet User creds w/o asking
  10705. // It doesn't matter that we aren't using the same user name
  10706. // If we are saving globals, then user creds must always be deleted! This applies for main and Internet.
  10707. //
  10708. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10709. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  10710. }
  10711. else
  10712. {
  10713. //
  10714. // Trying to save User creds. if there is currently no saved per-user password
  10715. // and the user opts to save the password himself, then ask whether the global
  10716. // password should be deleted if it exists.
  10717. //
  10718. if ((CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials) &&
  10719. !(CM_EXIST_CREDS_MAIN_USER & pArgs->dwExistingCredentials))
  10720. {
  10721. LPTSTR pszTmp = CmLoadString(g_hInst, IDMSG_DELETE_GLOBAL_CREDS);
  10722. if (pszTmp)
  10723. {
  10724. if (IDYES == MessageBoxEx(hwndDlg, pszTmp, pArgs->szServiceName,
  10725. MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2,
  10726. LANG_USER_DEFAULT))
  10727. {
  10728. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10729. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  10730. //
  10731. // Check for existence before deleting. If they don't exist, no need to
  10732. // delete them.
  10733. //
  10734. if ((CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials))
  10735. {
  10736. //
  10737. // Delete Internet Global creds if we are using the same creds
  10738. //
  10739. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10740. {
  10741. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10742. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  10743. }
  10744. }
  10745. }
  10746. }
  10747. CmFree(pszTmp);
  10748. }
  10749. }
  10750. //
  10751. // User chose to save password. Cache username, password, and
  10752. // domain.
  10753. //
  10754. fSave = TRUE;
  10755. rc.dwMask |= RASCM_UserName | RASCM_Password | RASCM_Domain;
  10756. }
  10757. else
  10758. {
  10759. //
  10760. // Don't save password
  10761. //
  10762. //
  10763. // Check which option button is currently selected
  10764. //
  10765. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  10766. {
  10767. //
  10768. // User is trying to delete his local creds. Delete the user creds.
  10769. // No need to check if they exist since these are local user creds.
  10770. //
  10771. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10772. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  10773. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10774. {
  10775. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10776. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  10777. }
  10778. //
  10779. // Check if global creds exist and if so prompt the user asking if he wants
  10780. // to delete the globals as well
  10781. //
  10782. if (CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials)
  10783. {
  10784. int iMsgBoxResult = 0;
  10785. LPTSTR pszTmp = CmLoadString(g_hInst, IDMSG_DELETE_ALL_CREDS);
  10786. if (pszTmp)
  10787. {
  10788. //
  10789. // Set the default to the 2nd button (NO), thus the user won't
  10790. // accidentally delete the global creds.
  10791. //
  10792. iMsgBoxResult = MessageBoxEx(hwndDlg, pszTmp, pArgs->szServiceName,
  10793. MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2,
  10794. LANG_USER_DEFAULT);
  10795. if (IDYES == iMsgBoxResult)
  10796. {
  10797. //
  10798. // Delete global creds
  10799. //
  10800. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10801. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  10802. if (CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)
  10803. {
  10804. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10805. {
  10806. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10807. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  10808. }
  10809. }
  10810. }
  10811. }
  10812. CmFree(pszTmp);
  10813. pszTmp = NULL;
  10814. }
  10815. //
  10816. // We need to resave username or domain info, even if it existed in case the
  10817. // user has updated it.
  10818. //
  10819. fSave = TRUE;
  10820. rc.dwMask |= RASCM_UserName | RASCM_Domain;
  10821. }
  10822. else
  10823. {
  10824. //
  10825. // Delete both sets of credentials
  10826. //
  10827. //
  10828. // Check if we need to resave User Name and Domain. The call that deletes the
  10829. // user creds doesn't wipe out User Name and Domain so there is no need to re-save.
  10830. //
  10831. if (FALSE == (BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER))
  10832. {
  10833. //
  10834. // Resave the username, and domain since user creds didn't exist
  10835. // and we want to pre-populate this info next time CM is loaded
  10836. //
  10837. fSave = TRUE;
  10838. rc.dwMask |= RASCM_UserName | RASCM_Domain;
  10839. }
  10840. if (CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials)
  10841. {
  10842. //
  10843. // Delete the global credentials.
  10844. // Note from RAS codebase: Note that we have to delete the global identity
  10845. // as well because we do not support deleting
  10846. // just the global password. This is so that
  10847. // RasSetCredentials can emulate RasSetDialParams.
  10848. //
  10849. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10850. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  10851. }
  10852. if (CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)
  10853. {
  10854. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10855. {
  10856. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10857. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  10858. //
  10859. // If we don't have Inet user creds then we need to cache the username for Inet creds
  10860. //
  10861. if (FALSE == (BOOL)(CM_EXIST_CREDS_INET_USER & pArgs->dwExistingCredentials))
  10862. {
  10863. fResaveInetUserCreds = TRUE;
  10864. }
  10865. }
  10866. }
  10867. //
  10868. // Delete the password saved per-user. Keep the user name
  10869. // and domain saved, however.
  10870. //
  10871. if (CM_EXIST_CREDS_MAIN_USER & pArgs->dwExistingCredentials)
  10872. {
  10873. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10874. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  10875. }
  10876. if (CM_EXIST_CREDS_INET_USER & pArgs->dwExistingCredentials)
  10877. {
  10878. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10879. {
  10880. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10881. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  10882. }
  10883. }
  10884. }
  10885. }
  10886. //
  10887. // Gets the info from the UI into pArgs and copy them into the RASCREDENTIALS structure
  10888. //
  10889. GetUserInfoFromDialog(pArgs, hwndDlg, &rc);
  10890. //
  10891. // See if we need to save anything
  10892. //
  10893. if (fSave)
  10894. {
  10895. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  10896. DWORD dwCurrentMask = rc.dwMask;
  10897. DWORD dwInetCurrentMask = rc.dwMask & ~RASCM_Domain; // Don't need domain info
  10898. if (pszConnectoid && pArgs->rlsRasLink.pfnSetCredentials)
  10899. {
  10900. DWORD dwRet = (DWORD)-1; // Some non ERROR_SUCCESS value
  10901. DWORD dwRetInet = (DWORD)-1; // Some non ERROR_SUCCESS value
  10902. LPTSTR pszPhoneBook = pArgs->pszRasPbk;
  10903. LPTSTR pszPrivatePhoneBook = CreateRasPrivatePbk(pArgs);
  10904. CopyMemory((LPVOID)&rcInet, (LPVOID)&rc, sizeof(rcInet));
  10905. //
  10906. // Save the creds
  10907. //
  10908. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &rc, FALSE);
  10909. if (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRet)
  10910. {
  10911. //
  10912. // Then the phonebook entry doesn't exist yet, lets create it.
  10913. //
  10914. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  10915. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  10916. {
  10917. pRasEntry->dwSize = sizeof(RASENTRY);
  10918. dwRet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  10919. //
  10920. // Lets try to set the credentials one more time ...
  10921. //
  10922. if (ERROR_SUCCESS == dwRet)
  10923. {
  10924. //
  10925. // dwMask needs to be reassigned, the previous call modified it
  10926. //
  10927. rc.dwMask = dwCurrentMask;
  10928. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &rc, FALSE);
  10929. }
  10930. CmFree(pRasEntry);
  10931. }
  10932. }
  10933. //
  10934. // Now try to save Internet creds
  10935. //
  10936. if (ERROR_SUCCESS == dwRet && pszPrivatePhoneBook)
  10937. {
  10938. //
  10939. // If we aren't using the credentials for main and Inet, then there
  10940. // is no need to resave Internet credentials, because they were saved on
  10941. // the Inet-Dialog page and they weren't deleted above.
  10942. //
  10943. if (pArgs->fUseSameUserName)
  10944. {
  10945. //
  10946. // dwMask needs to be reassigned, the previous call modified it
  10947. //
  10948. rcInet.dwMask = dwInetCurrentMask;
  10949. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10950. }
  10951. else
  10952. {
  10953. if (fResaveInetUserCreds)
  10954. {
  10955. rcInet.dwMask = dwInetCurrentMask;
  10956. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10957. }
  10958. if (pArgs->fDialAutomatically &&
  10959. (DOUBLE_DIAL_CONNECTION == pArgs->GetTypeOfConnection()))
  10960. {
  10961. //
  10962. // Carry remember state from DialAutomatically over to
  10963. // InetPassword if it isn't already remembered.
  10964. //
  10965. if (FALSE == pArgs->fRememberInetPassword)
  10966. {
  10967. pArgs->fRememberInetPassword = TRUE;
  10968. LPTSTR pszClearInetPassword = NULL;
  10969. DWORD cbClearInetPassword = 0;
  10970. BOOL fRetPassword = FALSE;
  10971. //
  10972. // Compare to 16 *'s. We don't want to resave if we have 16 *'s
  10973. // otherwise the user will get an auth-retry.
  10974. //
  10975. if (FALSE == pArgs->SecureInetPW.IsHandleToPassword())
  10976. {
  10977. fRetPassword = pArgs->SecureInetPW.GetPasswordWithAlloc(&pszClearInetPassword, &cbClearInetPassword);
  10978. if (fRetPassword && pszClearInetPassword)
  10979. {
  10980. //
  10981. // No need to save the domain
  10982. //
  10983. rcInet.dwMask = dwInetCurrentMask;
  10984. lstrcpyU(rcInet.szUserName, pArgs->szInetUserName);
  10985. lstrcpyU(rcInet.szPassword, pszClearInetPassword);
  10986. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10987. //
  10988. // Clear and Free the clear-text password
  10989. //
  10990. pArgs->SecureInetPW.ClearAndFree(&pszClearInetPassword, cbClearInetPassword);
  10991. }
  10992. }
  10993. }
  10994. }
  10995. }
  10996. }
  10997. if ((ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRetInet) && pszPrivatePhoneBook)
  10998. {
  10999. //
  11000. // Then the phonebook entry doesn't exist yet, lets create it.
  11001. //
  11002. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  11003. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  11004. {
  11005. pRasEntry->dwSize = sizeof(RASENTRY);
  11006. dwRetInet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPrivatePhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  11007. //
  11008. // Lets try to set the credentials one more time ...
  11009. //
  11010. if (ERROR_SUCCESS == dwRetInet)
  11011. {
  11012. //
  11013. // dwMask needs to be reassigned, the previous call modifies the mask
  11014. //
  11015. rcInet.dwMask = dwInetCurrentMask;
  11016. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  11017. }
  11018. CmFree(pRasEntry);
  11019. }
  11020. }
  11021. if (ERROR_SUCCESS == dwRet)
  11022. {
  11023. //
  11024. // Only set the existance flags if we are saving the password and everything
  11025. // succeeded
  11026. //
  11027. if (pArgs->fRememberMainPassword)
  11028. {
  11029. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  11030. {
  11031. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_GLOBAL;
  11032. if (pArgs->fUseSameUserName && (ERROR_SUCCESS == dwRetInet))
  11033. {
  11034. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_GLOBAL;
  11035. }
  11036. }
  11037. else
  11038. {
  11039. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_USER;
  11040. if (pArgs->fUseSameUserName && (ERROR_SUCCESS == dwRetInet))
  11041. {
  11042. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_USER;
  11043. }
  11044. }
  11045. }
  11046. }
  11047. CmFree(pszPrivatePhoneBook);
  11048. }
  11049. CmFree(pszConnectoid);
  11050. }
  11051. CmSecureZeroMemory(rc.szPassword, sizeof(rc.szPassword));
  11052. CmSecureZeroMemory(rcInet.szPassword, sizeof(rcInet.szPassword));
  11053. return;
  11054. }
  11055. //----------------------------------------------------------------------------
  11056. //
  11057. // Function: GetUserInfoFromDialog
  11058. //
  11059. // Synopsis: Gets the user information from the editboxes into pArgs
  11060. // structure. Then it copies the info into rascredentials
  11061. // structure. If the password is 16 *'s then we clear
  11062. // the password mask in the rascredentials in order not to save
  11063. // the password.
  11064. //
  11065. // Arguments: pArgs - ptr to ArgsStruct
  11066. // hwndDlg - HWND to dialog
  11067. // prc - [IN/OUT] rascredentials structure
  11068. //
  11069. // Returns: NONE
  11070. //
  11071. // History: 03/24/2001 tomkel Created
  11072. //
  11073. //----------------------------------------------------------------------------
  11074. VOID GetUserInfoFromDialog(ArgsStruct *pArgs, HWND hwndDlg, RASCREDENTIALS *prc)
  11075. {
  11076. if (NULL == pArgs || NULL == hwndDlg || NULL == prc)
  11077. {
  11078. MYDBGASSERT(pArgs && hwndDlg && prc);
  11079. return;
  11080. }
  11081. //
  11082. // Process Password info, if any.
  11083. //
  11084. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  11085. if (hwndPassword)
  11086. {
  11087. //
  11088. // Get the latest password data from the edit control
  11089. // and obfuscate its contents so that connect actions
  11090. // can't retrieve it.
  11091. //
  11092. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  11093. ObfuscatePasswordEdit(pArgs); // sets *'s into the password edit box
  11094. //
  11095. // Check if we have 16 *'s
  11096. //
  11097. if (pArgs->SecurePW.IsHandleToPassword() &&
  11098. (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L)))
  11099. {
  11100. //
  11101. // We have 16 *'s and the user hasn't modified the editbox. This
  11102. // password is from the RAS cred store, so we don't want to save the 16 *'s
  11103. //
  11104. prc->dwMask &= ~RASCM_Password;
  11105. }
  11106. }
  11107. //
  11108. // Process UserName info, if any
  11109. //
  11110. HWND hwndUserName = GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  11111. if (hwndUserName)
  11112. {
  11113. LPTSTR pszUsername = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  11114. lstrcpyU(pArgs->szUserName, pszUsername);
  11115. CmFree(pszUsername);
  11116. }
  11117. //
  11118. // Process Domain info, if any
  11119. //
  11120. HWND hwndDomain = GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT);
  11121. if (hwndDomain)
  11122. {
  11123. LPTSTR pszDomain = CmGetWindowTextAlloc(hwndDlg,IDC_MAIN_DOMAIN_EDIT);
  11124. lstrcpyU(pArgs->szDomain, pszDomain);
  11125. CmFree(pszDomain);
  11126. }
  11127. //
  11128. // This needs to be separate because in some cases
  11129. // the editboxes will not exist on the dialog, but we still need to save the info
  11130. // from the pArgs structure into RASCREDENTIALS.
  11131. //
  11132. lstrcpyU(prc->szUserName, pArgs->szUserName);
  11133. lstrcpyU(prc->szDomain, pArgs->szDomain);
  11134. LPTSTR pszClearPassword = NULL;
  11135. DWORD cbClearPassword = 0;
  11136. BOOL fRetPassword = FALSE;
  11137. fRetPassword = pArgs->SecurePW.GetPasswordWithAlloc(&pszClearPassword, &cbClearPassword);
  11138. if (fRetPassword && pszClearPassword)
  11139. {
  11140. lstrcpyU(prc->szPassword, pszClearPassword);
  11141. //
  11142. // Clear and Free the clear-text password
  11143. //
  11144. pArgs->SecurePW.ClearAndFree(&pszClearPassword, cbClearPassword);
  11145. }
  11146. }
  11147. //----------------------------------------------------------------------------
  11148. //
  11149. // Function: SwitchToLocalCreds
  11150. //
  11151. // Synopsis: Clear the password, but only if it wasn't recently modified
  11152. // only then we can reuse and resave it. That's because when
  11153. // we switch credential stores, the value of the szPassword
  11154. // is what was read from the RAS cred store (16 *'s). It doesn't
  11155. // make sense to save this value into a new user RAS creds store. If the
  11156. // password already existed there, then it's fine.
  11157. // In case the user modified the password text box and then decided
  11158. // to swich, the modification flag will be on, so we'll assume that the
  11159. // user entered a valid password and that it wasn't read in from the
  11160. // creds store.
  11161. // The actual deletion of credential happnes once the user clicks
  11162. // the connect button. Here we just clear things out of memory
  11163. // and update the UI. We also need to update the remember Internet
  11164. // flag based on if the Internet credential exist. This is so the
  11165. // UI stays consistent with what credentials are loaded in memory.
  11166. //
  11167. // Arguments: pArgs - ptr to ArgsStruct
  11168. // hwndDlg - HWND to dialog
  11169. // fSwitchToGlobal - used to ignore the check which credential
  11170. // store is currently active
  11171. //
  11172. // Returns: NONE
  11173. //
  11174. // History: 03/24/2001 tomkel Created
  11175. //
  11176. //----------------------------------------------------------------------------
  11177. VOID SwitchToLocalCreds(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSwitchToLocal)
  11178. {
  11179. if (NULL == pArgs || NULL == hwndDlg)
  11180. {
  11181. return;
  11182. }
  11183. //
  11184. // Switching to using Single-User credentials
  11185. //
  11186. //
  11187. // Check that previously the default was the Global creds store
  11188. //
  11189. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType || fSwitchToLocal)
  11190. {
  11191. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  11192. HWND hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  11193. BOOL fPWChanged = FALSE;
  11194. if (hwndTemp)
  11195. {
  11196. //
  11197. // Don't use Edit_GetModify. This needs need to run on Win9x so call
  11198. // SendMessageU
  11199. //
  11200. fPWChanged = (BOOL) SendMessageU(hwndTemp, EM_GETMODIFY, 0L, 0L);
  11201. if (FALSE == fPWChanged)
  11202. {
  11203. pArgs->fIgnoreChangeNotification = TRUE;
  11204. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  11205. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  11206. pArgs->fIgnoreChangeNotification = FALSE;
  11207. }
  11208. }
  11209. if (FALSE == fPWChanged)
  11210. {
  11211. //
  11212. // Only if Password field didn't change
  11213. //
  11214. if (OS_NT51)
  11215. {
  11216. //
  11217. // Wipe the Internet password - since we are switching from globals
  11218. // or we are using the same user name the Inet password will get re-populated
  11219. // from the main password, otherwise the user needs to set this password in
  11220. // the InetDialog.
  11221. //
  11222. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  11223. pArgs->fRememberInetPassword = FALSE;
  11224. //
  11225. // Only reload if main user creds exist
  11226. //
  11227. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)
  11228. {
  11229. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  11230. {
  11231. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  11232. pArgs->fRememberInetPassword = TRUE;
  11233. }
  11234. else
  11235. {
  11236. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_MAIN);
  11237. }
  11238. }
  11239. else
  11240. {
  11241. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  11242. {
  11243. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  11244. pArgs->fRememberInetPassword = TRUE;
  11245. }
  11246. else
  11247. {
  11248. pArgs->fRememberInetPassword = FALSE;
  11249. }
  11250. }
  11251. }
  11252. else
  11253. {
  11254. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  11255. }
  11256. }
  11257. else
  11258. {
  11259. if (OS_NT51)
  11260. {
  11261. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  11262. {
  11263. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  11264. pArgs->fRememberInetPassword = TRUE;
  11265. }
  11266. else
  11267. {
  11268. pArgs->fRememberInetPassword = FALSE;
  11269. }
  11270. }
  11271. else
  11272. {
  11273. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  11274. }
  11275. }
  11276. }
  11277. }
  11278. //----------------------------------------------------------------------------
  11279. //
  11280. // Function: SwitchToGlobalCreds
  11281. //
  11282. // Synopsis: Clear the password and reload the credentials if they exist.
  11283. // Otherwise we clear the password if it hasn't been modified by
  11284. // the user.
  11285. //
  11286. // Arguments: pArgs - ptr to ArgsStruct
  11287. // hwndDlg - HWND to dialog
  11288. // fSwitchToGlobal - used to ignore the check which credential
  11289. // store is currently active
  11290. //
  11291. // Returns: NONE
  11292. //
  11293. // History: 03/24/2001 tomkel Created
  11294. //
  11295. //----------------------------------------------------------------------------
  11296. VOID SwitchToGlobalCreds(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSwitchToGlobal)
  11297. {
  11298. if (NULL == pArgs || NULL == hwndDlg)
  11299. {
  11300. return;
  11301. }
  11302. //
  11303. // This should only be called on WinXP+
  11304. //
  11305. if (!OS_NT51)
  11306. {
  11307. MYDBGASSERT(FALSE);
  11308. return;
  11309. }
  11310. //
  11311. // Switching to using Global credentials
  11312. //
  11313. //
  11314. // Check that previously the default was the User creds store
  11315. //
  11316. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType || fSwitchToGlobal)
  11317. {
  11318. pArgs->dwCurrentCredentialType = CM_CREDS_GLOBAL;
  11319. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)
  11320. {
  11321. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  11322. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  11323. pArgs->fRememberInetPassword = FALSE;
  11324. //
  11325. // Globals exist
  11326. //
  11327. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)
  11328. {
  11329. //
  11330. // Both exist - reload both
  11331. //
  11332. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  11333. pArgs->fRememberInetPassword = TRUE;
  11334. }
  11335. else
  11336. {
  11337. //
  11338. // User Globals - exist, reload
  11339. // Internet Globals - don't exist, clear password
  11340. //
  11341. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_MAIN);
  11342. }
  11343. }
  11344. else
  11345. {
  11346. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  11347. pArgs->fIgnoreChangeNotification = TRUE;
  11348. (VOID)pArgs->SecureInetPW.SetPassword(TEXT(""));
  11349. pArgs->fRememberInetPassword = FALSE;
  11350. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)
  11351. {
  11352. //
  11353. // User Globals - don't exist - clear password
  11354. // Internet Globals - exist - reload
  11355. //
  11356. RefreshCredentialInfo(pArgs, CM_CREDS_TYPE_INET);
  11357. //
  11358. // In case user inet creds didn't exist, we should
  11359. //
  11360. pArgs->fRememberInetPassword = TRUE;
  11361. }
  11362. //
  11363. // Clear the main password only if it wasn't recently modified
  11364. //
  11365. if (hwndPassword)
  11366. {
  11367. if (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L))
  11368. {
  11369. (VOID)pArgs->SecurePW.SetPassword(TEXT(""));
  11370. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  11371. }
  11372. }
  11373. pArgs->fIgnoreChangeNotification = FALSE;
  11374. }
  11375. }
  11376. }
  11377. //----------------------------------------------------------------------------
  11378. //
  11379. // Function: ReloadCredentials
  11380. //
  11381. // Synopsis: Wrapper to reload credentials into the editboxes
  11382. //
  11383. // Arguments: pArgs - ptr to ArgsStruct
  11384. // hwndDlg - HWND to dialog
  11385. // dwWhichCredType - type of credential to reload
  11386. //
  11387. // Returns: NONE
  11388. //
  11389. // History: 03/24/2001 tomkel Created
  11390. //
  11391. //----------------------------------------------------------------------------
  11392. VOID ReloadCredentials(ArgsStruct *pArgs, HWND hwndDlg, DWORD dwWhichCredType)
  11393. {
  11394. if (NULL == pArgs || NULL == hwndDlg)
  11395. {
  11396. MYDBGASSERT(pArgs && hwndDlg);
  11397. return;
  11398. }
  11399. pArgs->fIgnoreChangeNotification = TRUE;
  11400. RefreshCredentialInfo(pArgs, dwWhichCredType);
  11401. SetMainDlgUserInfo(pArgs, hwndDlg);
  11402. pArgs->fIgnoreChangeNotification = FALSE;
  11403. }
  11404. //----------------------------------------------------------------------------
  11405. //
  11406. // Function: VerifyAdvancedTabSettings
  11407. //
  11408. // Synopsis: Verifies and possibly modifed the connection's ICF/ICS settings
  11409. // based on what was configured in the .cms file. These functions
  11410. // depend on the hnetcfg objects and private/internal interfaces.
  11411. // We got them from the homenet team.
  11412. // Some parts of the code were taken from:
  11413. // nt\net\homenet\config\dll\saui.cpp
  11414. //
  11415. // Arguments: pArgs - ptr to ArgsStruct
  11416. //
  11417. // Returns: NONE
  11418. //
  11419. // History: 04/26/2001 tomkel Created
  11420. //
  11421. //----------------------------------------------------------------------------
  11422. VOID VerifyAdvancedTabSettings(ArgsStruct *pArgs)
  11423. {
  11424. #ifndef _WIN64
  11425. HRESULT hr;
  11426. IHNetConnection *pHNetConn = NULL;
  11427. IHNetCfgMgr *pHNetCfgMgr = NULL;
  11428. INetConnectionUiUtilities* pncuu = NULL;
  11429. BOOL fCOMInitialized = FALSE;
  11430. BOOL fEnableICF = FALSE;
  11431. BOOL fDisableICS = FALSE;
  11432. BOOL fAllowUserToModifySettings = TRUE;
  11433. if (OS_NT51)
  11434. {
  11435. CMTRACE(TEXT("VerifyAdvancedTabSettings()"));
  11436. //
  11437. // Check rights - taken from saui.cpp
  11438. //
  11439. if (FALSE == IsAdmin())
  11440. {
  11441. return;
  11442. }
  11443. fEnableICF = pArgs->piniService->GPPB(c_pszCmSection,
  11444. c_pszCmEntryEnableICF,
  11445. FALSE);
  11446. fDisableICS = pArgs->piniService->GPPB(c_pszCmSection,
  11447. c_pszCmEntryDisableICS,
  11448. FALSE);
  11449. if (fEnableICF || fDisableICS)
  11450. {
  11451. hr = CoInitialize(NULL);
  11452. if (S_OK == hr)
  11453. {
  11454. CMTRACE(TEXT("VerifyAdvancedTabSettings - Correctly Initialized COM."));
  11455. fCOMInitialized = TRUE;
  11456. }
  11457. else if (S_FALSE == hr)
  11458. {
  11459. CMTRACE(TEXT("VerifyAdvancedTabSettings - This concurrency model is already initialized. CoInitialize returned S_FALSE."));
  11460. fCOMInitialized = TRUE;
  11461. hr = S_OK;
  11462. }
  11463. else if (RPC_E_CHANGED_MODE == hr)
  11464. {
  11465. CMTRACE1(TEXT("VerifyAdvancedTabSettings - Using different concurrency model. Did not initialize COM - RPC_E_CHANGED_MODE. hr=0x%x"), hr);
  11466. hr = S_OK;
  11467. }
  11468. else
  11469. {
  11470. CMTRACE1(TEXT("VerifyAdvancedTabSettings - Failed to Initialized COM. hr=0x%x"), hr);
  11471. }
  11472. if (SUCCEEDED(hr))
  11473. {
  11474. //
  11475. // Check user permissions. Needed to initialize COM first
  11476. // Check if ZAW is denying access to the Shared Access UI - taken from saui.cpp
  11477. //
  11478. hr = HrCreateNetConnectionUtilities(&pncuu);
  11479. if (SUCCEEDED(hr) && pncuu)
  11480. {
  11481. fEnableICF = (BOOL)(fEnableICF && pncuu->UserHasPermission(NCPERM_PersonalFirewallConfig));
  11482. fDisableICS = (BOOL)(fDisableICS && pncuu->UserHasPermission(NCPERM_ShowSharedAccessUi));
  11483. if ((FALSE == fEnableICF) && (FALSE == fDisableICS))
  11484. {
  11485. goto done;
  11486. }
  11487. }
  11488. //
  11489. // Create the home networking configuration manager
  11490. //
  11491. hr = CoCreateInstance(CLSID_HNetCfgMgr, NULL, CLSCTX_ALL,
  11492. IID_IHNetCfgMgr, (void**)&pHNetCfgMgr);
  11493. if (SUCCEEDED(hr))
  11494. {
  11495. //
  11496. // Convert the entry to an IHNetConnection
  11497. //
  11498. CMTRACE(TEXT("VerifyAdvancedTabSettings - Created CLSID_HNetCfgMgr object."));
  11499. GUID *pGuid = NULL;
  11500. LPRASENTRY pRasEntry = MyRGEP(pArgs->pszRasPbk, pArgs->szServiceName, &pArgs->rlsRasLink);
  11501. if (pRasEntry && sizeof(RASENTRY_V501) >= pRasEntry->dwSize)
  11502. {
  11503. //
  11504. // Get the pGuid value
  11505. //
  11506. pGuid = &(((LPRASENTRY_V501)pRasEntry)->guidId);
  11507. hr = pHNetCfgMgr->GetIHNetConnectionForGuid(pGuid, FALSE, TRUE, &pHNetConn);
  11508. if (SUCCEEDED(hr) && pHNetConn)
  11509. {
  11510. if (fEnableICF)
  11511. {
  11512. EnableInternetFirewall(pHNetConn);
  11513. }
  11514. if (fDisableICS)
  11515. {
  11516. DisableSharing(pHNetConn);
  11517. }
  11518. }
  11519. else
  11520. {
  11521. CMTRACE1(TEXT("VerifyAdvancedTabSettings() - Call to pHNetCfgMgr->GetIHNetConnectionForGuid returned an error. hr=0x%x"), hr);
  11522. }
  11523. }
  11524. else
  11525. {
  11526. CMTRACE(TEXT("VerifyAdvancedTabSettings - Failed to LoadRAS Entry."));
  11527. }
  11528. CmFree(pRasEntry);
  11529. pRasEntry = NULL;
  11530. }
  11531. else
  11532. {
  11533. CMTRACE(TEXT("VerifyAdvancedTabSettings - Failed to create CLSID_HNetCfgMgr object."));
  11534. }
  11535. }
  11536. }
  11537. done:
  11538. //
  11539. // Clean up and Uninitilize COM
  11540. //
  11541. if (pHNetConn)
  11542. {
  11543. pHNetConn->Release();
  11544. pHNetConn = NULL;
  11545. }
  11546. if (pHNetCfgMgr)
  11547. {
  11548. pHNetCfgMgr->Release();
  11549. pHNetCfgMgr = NULL;
  11550. }
  11551. if (pncuu)
  11552. {
  11553. pncuu->Release();
  11554. pncuu = NULL;
  11555. }
  11556. if (fCOMInitialized)
  11557. {
  11558. CoUninitialize();
  11559. }
  11560. }
  11561. #endif // _WIN64
  11562. }
  11563. //----------------------------------------------------------------------------
  11564. //
  11565. // Function: EnableInternetFirewall
  11566. //
  11567. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  11568. // This is part of the internal api.
  11569. //
  11570. // Arguments: pHNetConn - HNetConnection
  11571. //
  11572. // Returns: None.
  11573. //
  11574. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11575. //
  11576. //----------------------------------------------------------------------------
  11577. VOID EnableInternetFirewall(IHNetConnection *pHNetConn)
  11578. {
  11579. HRESULT hr = S_FALSE;
  11580. BOOLEAN bEnabled = FALSE;
  11581. if (NULL == pHNetConn)
  11582. {
  11583. return;
  11584. }
  11585. hr = InternalGetFirewallEnabled(pHNetConn, &bEnabled);
  11586. if (SUCCEEDED(hr) && !bEnabled)
  11587. {
  11588. IHNetFirewalledConnection* pFirewalledConnection = NULL;
  11589. hr = pHNetConn->Firewall(&pFirewalledConnection);
  11590. if (SUCCEEDED(hr))
  11591. {
  11592. if (pFirewalledConnection)
  11593. {
  11594. pFirewalledConnection->Release();
  11595. pFirewalledConnection = NULL;
  11596. }
  11597. }
  11598. }
  11599. }
  11600. //----------------------------------------------------------------------------
  11601. //
  11602. // Function: InternalGetFirewallEnabled
  11603. //
  11604. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  11605. //
  11606. // Arguments: pHNetConnection - HNetConnection
  11607. // pbEnabled - [out] whether the Firewall is enabled
  11608. //
  11609. // Returns: HRESULT
  11610. //
  11611. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11612. //
  11613. //----------------------------------------------------------------------------
  11614. HRESULT InternalGetFirewallEnabled(IHNetConnection *pHNetConnection, BOOLEAN *pbEnabled)
  11615. {
  11616. HRESULT hr;
  11617. HNET_CONN_PROPERTIES* pProps = NULL;
  11618. if (NULL == pHNetConnection)
  11619. {
  11620. hr = E_INVALIDARG;
  11621. }
  11622. else if (NULL == pbEnabled)
  11623. {
  11624. hr = E_POINTER;
  11625. }
  11626. else
  11627. {
  11628. *pbEnabled = FALSE;
  11629. hr = pHNetConnection->GetProperties(&pProps);
  11630. if (SUCCEEDED(hr))
  11631. {
  11632. if (pProps->fFirewalled)
  11633. {
  11634. *pbEnabled = TRUE;
  11635. }
  11636. CoTaskMemFree(pProps);
  11637. }
  11638. }
  11639. return hr;
  11640. }
  11641. //----------------------------------------------------------------------------
  11642. //
  11643. // Function: DisableSharing
  11644. //
  11645. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  11646. //
  11647. // Arguments: pHNetConn - HNetConnection
  11648. //
  11649. // Returns: HRESULT
  11650. //
  11651. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11652. //
  11653. //----------------------------------------------------------------------------
  11654. STDMETHODIMP DisableSharing(IHNetConnection *pHNetConn)
  11655. {
  11656. HRESULT hr;
  11657. BOOLEAN bEnabled = FALSE;
  11658. SHARINGCONNECTIONTYPE Type;
  11659. if (NULL == pHNetConn)
  11660. {
  11661. return E_INVALIDARG;
  11662. }
  11663. hr = InternalGetSharingEnabled(pHNetConn, &bEnabled, &Type);
  11664. if (SUCCEEDED(hr) && bEnabled )
  11665. {
  11666. switch(Type)
  11667. {
  11668. case ICSSHARINGTYPE_PUBLIC:
  11669. {
  11670. IHNetIcsPublicConnection* pPublicConnection = NULL;
  11671. hr = pHNetConn->GetControlInterface(
  11672. __uuidof(IHNetIcsPublicConnection),
  11673. reinterpret_cast<void**>(&pPublicConnection) );
  11674. if (SUCCEEDED(hr))
  11675. {
  11676. hr = pPublicConnection->Unshare();
  11677. if (pPublicConnection)
  11678. {
  11679. pPublicConnection->Release();
  11680. pPublicConnection = NULL;
  11681. }
  11682. }
  11683. }
  11684. break;
  11685. case ICSSHARINGTYPE_PRIVATE:
  11686. {
  11687. IHNetIcsPrivateConnection* pPrivateConnection = NULL;
  11688. hr = pHNetConn->GetControlInterface(
  11689. __uuidof(IHNetIcsPrivateConnection),
  11690. reinterpret_cast<void**>(&pPrivateConnection) );
  11691. if (SUCCEEDED(hr))
  11692. {
  11693. hr = pPrivateConnection->RemoveFromIcs();
  11694. if (pPrivateConnection)
  11695. {
  11696. pPrivateConnection->Release();
  11697. pPrivateConnection = NULL;
  11698. }
  11699. }
  11700. }
  11701. break;
  11702. default:
  11703. hr = E_UNEXPECTED;
  11704. }
  11705. }
  11706. return hr;
  11707. }
  11708. //----------------------------------------------------------------------------
  11709. //
  11710. // Function: InternalGetSharingEnabled
  11711. //
  11712. // Synopsis: Returns whether sharing is enabled on a given connection
  11713. //
  11714. // Arguments: pHNetConnection - HNetConnection
  11715. // pbEnabled - [out] returns the value
  11716. // pType - type of connection
  11717. //
  11718. // Returns: HRESULT
  11719. //
  11720. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11721. //
  11722. //----------------------------------------------------------------------------
  11723. HRESULT InternalGetSharingEnabled(IHNetConnection *pHNetConnection, BOOLEAN *pbEnabled, SHARINGCONNECTIONTYPE* pType)
  11724. {
  11725. HRESULT hr;
  11726. HNET_CONN_PROPERTIES* pProps;
  11727. if (NULL == pHNetConnection)
  11728. {
  11729. hr = E_INVALIDARG;
  11730. }
  11731. else if ((NULL == pbEnabled) || (NULL == pType))
  11732. {
  11733. hr = E_POINTER;
  11734. }
  11735. else
  11736. {
  11737. *pbEnabled = FALSE;
  11738. *pType = ICSSHARINGTYPE_PUBLIC;
  11739. hr = pHNetConnection->GetProperties(&pProps);
  11740. if (SUCCEEDED(hr))
  11741. {
  11742. if (pProps->fIcsPublic)
  11743. {
  11744. *pbEnabled = TRUE;
  11745. *pType = ICSSHARINGTYPE_PUBLIC;
  11746. }
  11747. else if (pProps->fIcsPrivate)
  11748. {
  11749. *pbEnabled = TRUE;
  11750. *pType = ICSSHARINGTYPE_PRIVATE;
  11751. }
  11752. CoTaskMemFree(pProps);
  11753. }
  11754. }
  11755. return hr;
  11756. }
  11757. //----------------------------------------------------------------------------
  11758. //
  11759. // Function: HrCreateNetConnectionUtilities
  11760. //
  11761. // Synopsis: Returns the pointer to the connection ui utilities object
  11762. //
  11763. // Arguments: ppncuu - pointer to INetConnectionUiUtilities object
  11764. //
  11765. // Returns: HRESULT
  11766. //
  11767. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\saui.cpp
  11768. //
  11769. //----------------------------------------------------------------------------
  11770. HRESULT APIENTRY HrCreateNetConnectionUtilities(INetConnectionUiUtilities ** ppncuu)
  11771. {
  11772. HRESULT hr = E_INVALIDARG;
  11773. if (ppncuu)
  11774. {
  11775. hr = CoCreateInstance (CLSID_NetConnectionUiUtilities, NULL,
  11776. CLSCTX_INPROC_SERVER,
  11777. IID_INetConnectionUiUtilities, (void**)ppncuu);
  11778. }
  11779. return hr;
  11780. }