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

13326 lines
416 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. //
  35. // .CMP and .CMS flag used only by connect.cpp
  36. //
  37. const TCHAR* const c_pszCmEntryMonitorCallingProgram= TEXT("MonitorCallingProgram");
  38. const TCHAR* const c_pszCmEntryUserNameOptional = TEXT("UserNameOptional");
  39. const TCHAR* const c_pszCmEntryDomainOptional = TEXT("DomainOptional");
  40. const TCHAR* const c_pszCmEntryServiceType = TEXT("ServiceType");
  41. const TCHAR* const c_pszCmEntryRedialDelay = TEXT("RedialDelay");
  42. const TCHAR* const c_pszCmEntryRedial = TEXT("Redial");
  43. const TCHAR* const c_pszCmEntryIdle = TEXT("Idle");
  44. const TCHAR* const c_pszCmEntryDialAutoMessage = TEXT("DialAutoMessage");
  45. const TCHAR* const c_pszCmEntryCheckOsComponents = TEXT("CheckOSComponents");
  46. const TCHAR* const c_pszCmEntryDoNotCheckBindings = TEXT("DoNotCheckBindings");
  47. const TCHAR* const c_pszCmEntryIsdnDialMode = TEXT("IsdnDialMode");
  48. const TCHAR* const c_pszCmEntryResetPassword = TEXT("ResetPassword");
  49. const TCHAR* const c_pszCmEntryCustomButtonText = TEXT("CustomButtonText");
  50. const TCHAR* const c_pszCmEntryCustomButtonToolTip = TEXT("CustomButtonToolTip");
  51. const TCHAR* const c_pszCmDynamicPhoneNumber = TEXT("DynamicPhoneNumber");
  52. const TCHAR* const c_pszCmNoDialingRules = TEXT("NoDialingRules");
  53. const TCHAR* const c_pszCmEntryHideDialAuto = TEXT("HideDialAutomatically");
  54. const TCHAR* const c_pszCmEntryHideRememberPwd = TEXT("HideRememberPassword");
  55. const TCHAR* const c_pszCmEntryHideRememberInetPwd = TEXT("HideRememberInternetPassword");
  56. const TCHAR* const c_pszCmEntryHideInetUserName = TEXT("HideInternetUserName");
  57. const TCHAR* const c_pszCmEntryHideInetPassword = TEXT("HideInternetPassword");
  58. const TCHAR* const c_pszCmEntryHideUnattended = TEXT("HideUnattended");
  59. const TCHAR* const c_pszCmEntryRegion = TEXT("Region");
  60. const TCHAR* const c_pszCmEntryPhonePrefix = TEXT("Phone");
  61. const TCHAR* const c_pszCmEntryPhoneCanonical = TEXT("PhoneCanonical");
  62. const TCHAR* const c_pszCmEntryPhoneDunPrefix = TEXT("DUN");
  63. const TCHAR* const c_pszCmEntryPhoneDescPrefix = TEXT("Description");
  64. const TCHAR* const c_pszCmEntryPhoneCountryPrefix = TEXT("PhoneCountry");
  65. const TCHAR* const c_pszCmEntryPhoneSourcePrefix = TEXT("PhoneSource");
  66. const TCHAR* const c_pszCmEntryUseDialingRules = TEXT("UseDialingRules");
  67. const TCHAR* const c_pszCmEntryAnimatedLogo = TEXT("AnimatedLogo");
  68. const TCHAR* const c_pszCmSectionAnimatedLogo = TEXT("Animated Logo");
  69. const TCHAR* const c_pszCmSectionAnimatedActions = TEXT("Animation Actions");
  70. const TCHAR* const c_pszCmEntryAniMovie = TEXT("Movie");
  71. const TCHAR* const c_pszCmEntryAniPsInteractive = TEXT("Initial");
  72. const TCHAR* const c_pszCmEntryAniPsDialing0 = TEXT("Dialing0");
  73. const TCHAR* const c_pszCmEntryAniPsDialing1 = TEXT("Dialing1");
  74. const TCHAR* const c_pszCmEntryAniPsPausing = TEXT("Pausing");
  75. const TCHAR* const c_pszCmEntryAniPsAuthenticating = TEXT("Authenticating");
  76. const TCHAR* const c_pszCmEntryAniPsOnline = TEXT("Connected");
  77. const TCHAR* const c_pszCmEntryAniPsTunnel = TEXT("Tunneling");
  78. const TCHAR* const c_pszCmEntryAniPsError = TEXT("Error");
  79. const TCHAR* const c_pszCmEntryWriteDialParams = TEXT("WriteRasDialUpParams");
  80. //
  81. // Used for loading EAP identity DLL
  82. //
  83. const TCHAR* const c_pszRasEapRegistryLocation = TEXT("System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP");
  84. const TCHAR* const c_pszRasEapValueNameIdentity = TEXT("IdentityPath");
  85. const TCHAR* const c_pszInvokeUsernameDialog = TEXT("InvokeUsernameDialog");
  86. //
  87. // Definitions
  88. //
  89. #define MAX_OBJECT_WAIT 30000 // milliseconds to wait for cmmon launch and RNA thread return
  90. //============================================================================
  91. static void LoadPhoneInfoFromProfile(ArgsStruct *pArgs);
  92. HRESULT UpdateTable(ArgsStruct *pArgs, CmConnectState CmState);
  93. HRESULT ConnectMonitor(ArgsStruct *pArgs);
  94. void OnMainExit(ArgsStruct *pArgs);
  95. void ProcessCleanup(ArgsStruct* pArgs);
  96. VOID UpdateError(ArgsStruct *pArgs, DWORD dwErr);
  97. DWORD GetEapUserId(ArgsStruct *pArgs,
  98. HWND hwndDlg,
  99. LPTSTR pszRasPbk,
  100. LPBYTE pbEapAuthData,
  101. DWORD dwEapAuthDataSize,
  102. DWORD dwCustomAuthKey,
  103. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity);
  104. DWORD CmEapGetIdentity(ArgsStruct *pArgs,
  105. LPTSTR pszRasPbk,
  106. LPBYTE pbEapAuthData,
  107. DWORD dwEapAuthDataSize,
  108. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity);
  109. void CheckStartupInfo(HWND hwndDlg, ArgsStruct *pArgs);
  110. BOOL InitConnect(ArgsStruct *pArgs);
  111. void ObfuscatePasswordEdit(ArgsStruct *pArgs);
  112. void DeObfuscatePasswordEdit(ArgsStruct *pArgs);
  113. void GetPasswordFromEdit(ArgsStruct *pArgs);
  114. //+----------------------------------------------------------------------------
  115. //
  116. // Function: GetPasswordFromEdit
  117. //
  118. // Synopsis: Updates pArgs->szPassword with contents of edit control
  119. //
  120. // Arguments: pArgs - Ptr to global Args struct
  121. //
  122. // Returns: Nothing
  123. //
  124. // History: nickball Created 04/13/00
  125. //
  126. //+----------------------------------------------------------------------------
  127. void GetPasswordFromEdit(ArgsStruct *pArgs)
  128. {
  129. MYDBGASSERT(pArgs);
  130. if (NULL == pArgs)
  131. {
  132. return;
  133. }
  134. if (NULL == GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT))
  135. {
  136. return;
  137. }
  138. //
  139. // Retrieve the password and update memory based storage.
  140. //
  141. LPTSTR pszPassword = CmGetWindowTextAlloc(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  142. MYDBGASSERT(pszPassword);
  143. if (pszPassword)
  144. {
  145. //
  146. // Update pArgs with main password.
  147. //
  148. lstrcpyU(pArgs->szPassword, pszPassword);
  149. CmEncodePassword(pArgs->szPassword);
  150. CmWipePassword(pszPassword);
  151. CmFree(pszPassword);
  152. }
  153. else
  154. {
  155. lstrcpyU(pArgs->szPassword, TEXT(""));
  156. }
  157. return;
  158. }
  159. //+----------------------------------------------------------------------------
  160. //
  161. // Function: DeObfuscatePasswordEdit
  162. //
  163. // Synopsis: Undoes the work of ObfuscatePasswordEdit by updating the password
  164. // edit with the plain text password
  165. //
  166. // Arguments: pArgs - Ptr to global Args struct
  167. //
  168. // Returns: Nothing
  169. //
  170. // History: nickball Created 04/13/00
  171. //
  172. //+----------------------------------------------------------------------------
  173. void DeObfuscatePasswordEdit(ArgsStruct *pArgs)
  174. {
  175. MYDBGASSERT(pArgs);
  176. if (NULL == pArgs)
  177. {
  178. return;
  179. }
  180. HWND hwndEdit = GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  181. if (NULL == hwndEdit)
  182. {
  183. return;
  184. }
  185. //
  186. // Make sure we don't trigger EN_CHANGE notifications
  187. //
  188. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  189. pArgs->fIgnoreChangeNotification = TRUE;
  190. //
  191. // Update the edit control
  192. //
  193. CmDecodePassword(pArgs->szPassword);
  194. SetWindowTextU(hwndEdit, pArgs->szPassword);
  195. CmEncodePassword(pArgs->szPassword);
  196. //
  197. // Restore EN_CHANGE notifications
  198. //
  199. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  200. }
  201. //+----------------------------------------------------------------------------
  202. //
  203. // Function: ObfuscatePasswordEdit
  204. //
  205. // Synopsis: Helper routine to mangle password edit contents by replacing
  206. // them with an equivalent number of *s
  207. //
  208. // Arguments: pArgs - Ptr to global Args struct
  209. //
  210. // Returns: Nothing
  211. //
  212. // NOTE: This function assumes that pArgs->szPassword has been previously
  213. // updated with GetPasswordFromEdit. This assumption is made
  214. // because it is critical to the Odfuscate/DeObfuscate sequence,
  215. // which will breakdown if the latest password is not cached in
  216. // memory (pArgs) before the edit contents are modified.
  217. //
  218. // History: nickball Created 04/13/00
  219. //
  220. //+----------------------------------------------------------------------------
  221. void ObfuscatePasswordEdit(ArgsStruct *pArgs)
  222. {
  223. MYDBGASSERT(pArgs);
  224. if (NULL == pArgs)
  225. {
  226. return;
  227. }
  228. HWND hwndEdit = GetDlgItem(pArgs->hwndMainDlg, IDC_MAIN_PASSWORD_EDIT);
  229. if (NULL == hwndEdit)
  230. {
  231. return;
  232. }
  233. //
  234. // Generate a buffer of the same length as the current password, but
  235. // containing only asterisks.
  236. //
  237. LPTSTR pszDummy = CmStrCpyAlloc(pArgs->szPassword);
  238. MYDBGASSERT(pszDummy);
  239. if (pszDummy)
  240. {
  241. //
  242. // Make sure we don't trigger EN_CHANGE notifications
  243. //
  244. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  245. pArgs->fIgnoreChangeNotification = TRUE;
  246. LPTSTR pszTmp = pszDummy;
  247. while (*pszTmp)
  248. {
  249. *pszTmp++ = TEXT('*');
  250. }
  251. //
  252. // Update the edit control with the modified buffer
  253. //
  254. SetWindowTextU(hwndEdit, pszDummy);
  255. CmFree(pszDummy);
  256. //
  257. // Restore EN_CHANGE notifications
  258. //
  259. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  260. }
  261. }
  262. //+----------------------------------------------------------------------------
  263. //
  264. // Function: InitConnect
  265. //
  266. // Synopsis: Init routine for the connection. Assumes that we have the profile
  267. // initialized and the basic integrity of the profile verified.
  268. //
  269. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  270. //
  271. // Returns: BOOL - True if init succeeds.
  272. //
  273. // History: nickball Created 03/10/00
  274. //
  275. //+----------------------------------------------------------------------------
  276. BOOL InitConnect(ArgsStruct *pArgs)
  277. {
  278. //
  279. // If this is an AUTODIAL, add the process ID to the watch list
  280. //
  281. if ((pArgs->dwFlags & FL_AUTODIAL) &&
  282. pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMonitorCallingProgram, 1))
  283. {
  284. CMTRACE(TEXT("InitConnect() Adding calling process to watch list"));
  285. AddWatchProcessId(pArgs, GetCurrentProcessId());
  286. }
  287. //
  288. // Do we want tunneling?
  289. //
  290. pArgs->fTunnelPrimary = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryTunnelPrimary);
  291. pArgs->fTunnelReferences = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryTunnelReferences);
  292. //
  293. // Now we can determine our connect type
  294. //
  295. GetConnectType(pArgs);
  296. //
  297. // Set fUseTunneling. If not obvious (eg. direct VPN) then
  298. // base the initial value upon the primary phone number.
  299. //
  300. if (pArgs->IsDirectConnect())
  301. {
  302. pArgs->fUseTunneling = TRUE;
  303. }
  304. else
  305. {
  306. pArgs->fUseTunneling = UseTunneling(pArgs, 0);
  307. }
  308. //
  309. // Load the path for the VPN file if we have one
  310. //
  311. LPTSTR pszTemp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryTunnelFile);
  312. if (pszTemp && pszTemp[0])
  313. {
  314. //
  315. // Now expand the relative path to a full path
  316. //
  317. pArgs->pszVpnFile = CmBuildFullPathFromRelative(pArgs->piniProfile->GetFile(), pszTemp);
  318. MYDBGASSERT(pArgs->pszVpnFile && pArgs->pszVpnFile[0]);
  319. }
  320. CmFree(pszTemp);
  321. TCHAR szTmp[MAX_PATH];
  322. MYVERIFY(GetModuleFileNameU(NULL, szTmp, MAX_PATH));
  323. pArgs->Log.Log(PREINIT_EVENT, szTmp);
  324. //
  325. // Run any init time actions that we may have.
  326. //
  327. CActionList PreInitActList;
  328. PreInitActList.Append(pArgs->piniService, c_pszCmSectionPreInit);
  329. if (!PreInitActList.RunAccordType(pArgs->hwndMainDlg, pArgs, FALSE)) // fStatusMsgOnFailure = FALSE
  330. {
  331. //
  332. // Fail the connection
  333. //
  334. return FALSE;
  335. }
  336. return TRUE;
  337. }
  338. //+----------------------------------------------------------------------------
  339. //
  340. // Function: CheckStartupInfo
  341. //
  342. // Synopsis: Sub-routine to initialize startup info if necessary and perform
  343. // any other functions specific to this juncture in the init sequence.
  344. //
  345. // Arguments: HWND hwndDlg - HWND of main dlg
  346. // ArgStruct *pArgs - Ptr to global Args struct
  347. //
  348. // Returns: Nothing
  349. //
  350. // History: nickball Created 10/28/99
  351. //
  352. //+----------------------------------------------------------------------------
  353. void CheckStartupInfo(IN HWND hwndDlg, IN ArgsStruct *pArgs)
  354. {
  355. MYDBGASSERT(pArgs);
  356. if (NULL == pArgs)
  357. {
  358. return;
  359. }
  360. if (!pArgs->fStartupInfoLoaded)
  361. {
  362. //
  363. // When no one is logged on the IsWindowVisible will not return true when ICS is dialing
  364. //
  365. if (IsLogonAsSystem() || IsWindowVisible(hwndDlg))
  366. {
  367. //
  368. // The code is here to make sure FutureSplash starts with
  369. // the frame associated with Initial/Interactive state
  370. // and not Frame 1
  371. //
  372. if (NULL != pArgs->pCtr)
  373. {
  374. pArgs->pCtr->MapStateToFrame(PS_Interactive);
  375. }
  376. //
  377. // If we're doing unattended, and the behavior isn't explicitly turned off,
  378. // hide the UI while we do our unattended dial. Note: Be sure to set hide
  379. // state before first paint message is processed by system.
  380. //
  381. if (pArgs->dwFlags & FL_UNATTENDED)
  382. {
  383. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideUnattended, TRUE))
  384. {
  385. ShowWindow(hwndDlg, SW_HIDE);
  386. }
  387. }
  388. //
  389. // Post a message to ourselves to begin loading startup info.
  390. //
  391. PostMessageU(hwndDlg, WM_LOADSTARTUPINFO, (WPARAM)0, (LPARAM)0);
  392. }
  393. }
  394. }
  395. //+----------------------------------------------------------------------------
  396. //
  397. // Function: UpdateError
  398. //
  399. // Synopsis: Simple sub-routine to update the UI and program state in the
  400. // event of an error.
  401. //
  402. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  403. // DWORD dwErr - The error code
  404. //
  405. // Returns: Nothing
  406. //
  407. // History: nickball Created 05/31/99
  408. //
  409. //+----------------------------------------------------------------------------
  410. VOID UpdateError(ArgsStruct *pArgs, DWORD dwErr)
  411. {
  412. MYDBGASSERT(pArgs);
  413. if (pArgs)
  414. {
  415. //
  416. // Update the status display providing that the special case error code
  417. // ERROR_INVALID_DLL is not being used. This code is only used by CM to
  418. // designate that a Connect Action failed. Because the display is
  419. // updated by the action list, we must ensure that we don't overwrite.
  420. //
  421. if (ERROR_INVALID_DLL != dwErr)
  422. {
  423. CheckConnectionError(pArgs->hwndMainDlg, dwErr, pArgs, IsDialingTunnel(pArgs));
  424. }
  425. //
  426. // Update the logon dialog controls
  427. //
  428. SetInteractive(pArgs->hwndMainDlg, pArgs);
  429. //
  430. // Update the program state
  431. //
  432. pArgs->psState = PS_Error;
  433. }
  434. }
  435. //+----------------------------------------------------------------------------
  436. //
  437. // Function: UpdateTable
  438. //
  439. // Synopsis: Encapsulates updating to Connection Table according to our
  440. // current state
  441. //
  442. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  443. // CmConnectState CmState - The state we are now in.
  444. //
  445. // Returns: HRESULT - Failure code.
  446. //
  447. // History: nickball Created Header 2/9/98
  448. //
  449. //+----------------------------------------------------------------------------
  450. HRESULT UpdateTable(ArgsStruct *pArgs, CmConnectState CmState)
  451. {
  452. MYDBGASSERT(pArgs);
  453. MYDBGASSERT(pArgs->pConnTable);
  454. HRESULT hrRet = E_FAIL;
  455. //
  456. // Set the state as appropriate
  457. //
  458. switch (CmState)
  459. {
  460. case CM_CONNECTING:
  461. hrRet = pArgs->pConnTable->AddEntry(pArgs->szServiceName, pArgs->fAllUser);
  462. break;
  463. case CM_CONNECTED:
  464. hrRet = pArgs->pConnTable->SetConnected(pArgs->szServiceName, pArgs->hrcRasConn, pArgs->hrcTunnelConn);
  465. break;
  466. case CM_DISCONNECTING:
  467. hrRet = pArgs->pConnTable->SetDisconnecting(pArgs->szServiceName);
  468. break;
  469. case CM_DISCONNECTED:
  470. hrRet = pArgs->pConnTable->ClearEntry(pArgs->szServiceName);
  471. break;
  472. default:
  473. MYDBGASSERT(FALSE);
  474. break;
  475. }
  476. return hrRet;
  477. }
  478. //+----------------------------------------------------------------------------
  479. //
  480. // Function: EndMainDialog
  481. //
  482. // Synopsis: Simple helper to encapsulate EndDialog call and associated clean
  483. // up.
  484. //
  485. // Arguments: HWND hwndDlg - HWND of main dialog
  486. // ArgsStruct *pArgs - Ptr to global Args struct
  487. // int nResult - int to be passed on the EndDialog
  488. //
  489. // Returns: Nothing
  490. //
  491. // History: nickball Created 2/23/98
  492. //
  493. //+----------------------------------------------------------------------------
  494. void EndMainDialog(HWND hwndDlg, ArgsStruct *pArgs, int nResult)
  495. {
  496. //
  497. // Kill timer if we have one
  498. //
  499. if (pArgs->nTimerId)
  500. {
  501. KillTimer(hwndDlg,pArgs->nTimerId);
  502. pArgs->nTimerId = 0;
  503. }
  504. //
  505. // Cleanup future splash
  506. //
  507. if (pArgs->pCtr)
  508. {
  509. CleanupCtr(pArgs->pCtr);
  510. pArgs->pCtr = NULL;
  511. }
  512. //
  513. // Release our dialog specific data
  514. //
  515. pArgs->fStartupInfoLoaded = FALSE;
  516. OnMainExit(pArgs);
  517. //
  518. // hasta la vista, final
  519. //
  520. EndDialog(hwndDlg, nResult);
  521. }
  522. //+----------------------------------------------------------------------------
  523. //
  524. // Function: GetWatchCount
  525. //
  526. // Synopsis: Determines the number of processes in the watch list by searching
  527. // for the first NULL entry.
  528. //
  529. // Arguments: ArgStruct *pArgs - Ptr to global Args struct
  530. //
  531. // Returns: DWORD - Number of processes in list
  532. //
  533. // History: nickball Created Header 2/10/98
  534. //
  535. //+----------------------------------------------------------------------------
  536. DWORD GetWatchCount(const ArgsStruct *pArgs)
  537. {
  538. MYDBGASSERT(pArgs);
  539. DWORD dwCnt = 0;
  540. if (pArgs && pArgs->phWatchProcesses)
  541. {
  542. for (DWORD dwIdx = 0; pArgs->phWatchProcesses[dwIdx]; dwIdx++)
  543. {
  544. dwCnt++;
  545. }
  546. }
  547. return dwCnt;
  548. }
  549. //+----------------------------------------------------------------------------
  550. //
  551. // Function: AddWatchProcess
  552. //
  553. // Synopsis: Adds the given process handle to our list. The list is allocated
  554. // and reallocated as needed to accomodate new entries.
  555. //
  556. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  557. // HANDLE hProcess - The process handle to be added to the list
  558. //
  559. // Returns: Nothing
  560. //
  561. // History: nickball Created Header 2/10/98
  562. // tomkel Fixed PREFIX issues 11/21/2000
  563. //
  564. //+----------------------------------------------------------------------------
  565. void AddWatchProcess(ArgsStruct *pArgs, HANDLE hProcess)
  566. {
  567. MYDBGASSERT(pArgs);
  568. MYDBGASSERT(hProcess);
  569. if (NULL == hProcess || NULL == pArgs)
  570. {
  571. return;
  572. }
  573. //
  574. // Get count and Allocate room for 2 more, 1 new, 1 NULL
  575. //
  576. DWORD dwCnt = GetWatchCount(pArgs);
  577. HANDLE *phTmp = (HANDLE *) CmMalloc((dwCnt+2)*sizeof(HANDLE));
  578. if (NULL != phTmp)
  579. {
  580. //
  581. // Copy the existing list, and add the new handle
  582. //
  583. if (NULL != pArgs->phWatchProcesses)
  584. {
  585. CopyMemory(phTmp,pArgs->phWatchProcesses,sizeof(HANDLE)*dwCnt);
  586. }
  587. phTmp[dwCnt] = hProcess;
  588. //
  589. // Fix up the pointers
  590. //
  591. CmFree(pArgs->phWatchProcesses);
  592. pArgs->phWatchProcesses = phTmp;
  593. }
  594. }
  595. //+----------------------------------------------------------------------------
  596. //
  597. // Function: AddWatchProcessId
  598. //
  599. // Synopsis: Given a process Id, adds a handle for the given process to the w
  600. // atch process list.
  601. //
  602. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct.
  603. // DWORD dwProcessId - The ID of the process to be added
  604. //
  605. // Returns: Nothing
  606. //
  607. // History: nickball Created Header 2/10/98
  608. //
  609. //+----------------------------------------------------------------------------
  610. void AddWatchProcessId(ArgsStruct *pArgs, DWORD dwProcessId)
  611. {
  612. MYDBGASSERT(pArgs);
  613. MYDBGASSERT(dwProcessId);
  614. if (NULL == pArgs || NULL == dwProcessId)
  615. {
  616. return;
  617. }
  618. //
  619. // Open the process Id to obtain handle
  620. //
  621. HANDLE hProcess = OpenProcess(SYNCHRONIZE | PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
  622. //
  623. // Add to the watch process list
  624. //
  625. if (hProcess)
  626. {
  627. AddWatchProcess(pArgs,hProcess);
  628. }
  629. else
  630. {
  631. CMTRACE1(TEXT("AddWatchProcess() OpenProcess() failed, GLE=%u."), GetLastError());
  632. }
  633. }
  634. //+----------------------------------------------------------------------------
  635. //
  636. // Function: CleanupConnect
  637. //
  638. // Synopsis: Helper function encapsulating release of resource allocated duri
  639. // ng connect.
  640. //
  641. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  642. //
  643. // Returns: Nothing
  644. //
  645. // History: nickball Created 9/25/98
  646. //
  647. //+----------------------------------------------------------------------------
  648. void CleanupConnect(ArgsStruct *pArgs)
  649. {
  650. MYDBGASSERT(pArgs);
  651. if (NULL == pArgs)
  652. {
  653. return;
  654. }
  655. pArgs->m_ShellDll.Unload();
  656. //
  657. // Unlink RAS and TAPI DLLs
  658. //
  659. UnlinkFromRas(&pArgs->rlsRasLink);
  660. UnlinkFromTapi(&pArgs->tlsTapiLink);
  661. //
  662. // un-init password encryption, only if it is initialized
  663. //
  664. if (pArgs->fInitSecureCalled)
  665. {
  666. DeInitSecure();
  667. pArgs->fInitSecureCalled = FALSE;
  668. }
  669. //
  670. // Cleanup WatchProcess handles
  671. //
  672. ProcessCleanup(pArgs);
  673. //
  674. // Release all paths loaded for connect.
  675. //
  676. if (pArgs->pszRasPbk)
  677. {
  678. CmFree(pArgs->pszRasPbk);
  679. pArgs->pszRasPbk = NULL;
  680. }
  681. if (pArgs->pszRasHiddenPbk)
  682. {
  683. CmFree(pArgs->pszRasHiddenPbk);
  684. pArgs->pszRasHiddenPbk = NULL;
  685. }
  686. if(pArgs->pszVpnFile)
  687. {
  688. CmFree(pArgs->pszVpnFile);
  689. pArgs->pszVpnFile = NULL;
  690. }
  691. if (pArgs->pRasDialExtensions)
  692. {
  693. CmFree(pArgs->pRasDialExtensions);
  694. pArgs->pRasDialExtensions = NULL;
  695. }
  696. if (pArgs->pRasDialParams)
  697. {
  698. CmFree(pArgs->pRasDialParams);
  699. pArgs->pRasDialParams = NULL;
  700. }
  701. if (pArgs->pszCurrentAccessPoint)
  702. {
  703. CmFree(pArgs->pszCurrentAccessPoint);
  704. pArgs->pszCurrentAccessPoint = NULL;
  705. }
  706. //
  707. // Cleanup Help by killing the help file window if any and releasing the help file
  708. // string.
  709. //
  710. if (pArgs->pszHelpFile)
  711. {
  712. CmWinHelp((HWND)NULL, (HWND)NULL, pArgs->pszHelpFile, HELP_QUIT, 0);
  713. CmFree(pArgs->pszHelpFile);
  714. pArgs->pszHelpFile = NULL;
  715. }
  716. //
  717. // Release Ini objects
  718. //
  719. ReleaseIniObjects(pArgs);
  720. //
  721. // Release OLE links if any
  722. //
  723. if (pArgs->olsOle32Link.hInstOle32 && pArgs->olsOle32Link.pfnOleUninitialize)
  724. {
  725. pArgs->olsOle32Link.pfnOleUninitialize();
  726. }
  727. UnlinkFromOle32(&pArgs->olsOle32Link);
  728. //
  729. // Release stats and table classes
  730. //
  731. if (pArgs->pConnStatistics)
  732. {
  733. delete pArgs->pConnStatistics;
  734. }
  735. if (pArgs->pConnTable)
  736. {
  737. MYVERIFY(SUCCEEDED(pArgs->pConnTable->Close()));
  738. delete pArgs->pConnTable;
  739. }
  740. }
  741. //
  742. // Releases any resources allocated during initialization
  743. //
  744. void OnMainExit(ArgsStruct *pArgs)
  745. {
  746. //
  747. // Release bitmap resources for main dlg
  748. //
  749. ReleaseBitmapData(&pArgs->BmpData);
  750. if (pArgs->hMasterPalette)
  751. {
  752. UnrealizeObject(pArgs->hMasterPalette);
  753. DeleteObject(pArgs->hMasterPalette);
  754. pArgs->hMasterPalette = NULL;
  755. }
  756. //
  757. // Release icon resources
  758. //
  759. if (pArgs->hBigIcon)
  760. {
  761. DeleteObject(pArgs->hBigIcon);
  762. pArgs->hBigIcon = NULL;
  763. }
  764. if (pArgs->hSmallIcon)
  765. {
  766. DeleteObject(pArgs->hSmallIcon);
  767. pArgs->hSmallIcon = NULL;
  768. }
  769. if (pArgs->pszResetPasswdExe)
  770. {
  771. CmFree(pArgs->pszResetPasswdExe);
  772. pArgs->pszResetPasswdExe = NULL;
  773. }
  774. if (pArgs->uiCurrentDnsTunnelAddr)
  775. {
  776. CmFree(pArgs->pucDnsTunnelIpAddr_list);
  777. pArgs->pucDnsTunnelIpAddr_list = NULL;
  778. }
  779. if (pArgs->rgwRandomDnsIndex)
  780. {
  781. CmFree(pArgs->rgwRandomDnsIndex);
  782. pArgs->rgwRandomDnsIndex = NULL;
  783. }
  784. }
  785. //
  786. // GetPhoneByIdx: get phone number, etc. information from .cmp file
  787. //
  788. LPTSTR GetPhoneByIdx(ArgsStruct *pArgs,
  789. UINT nIdx,
  790. LPTSTR *ppszDesc,
  791. LPTSTR *ppszDUN,
  792. LPDWORD pdwCountryID,
  793. LPTSTR *ppszRegionName,
  794. LPTSTR *ppszServiceType,
  795. LPTSTR *ppszPhoneBookFile,
  796. LPTSTR *ppszCanonical,
  797. DWORD *pdwPhoneInfoFlags)
  798. {
  799. MYDBGASSERT(ppszCanonical);
  800. MYDBGASSERT(pdwPhoneInfoFlags);
  801. //
  802. // Note: ppszCanonical and pdwPhoneInfoFlags are now required parameters.
  803. // While somewhat unfortunate, this is necessary to retain the integrity
  804. // of the retrieved data as legacy handling forces us to return data
  805. // that may not be an exact representation of the profile contents.
  806. // For example, the ppszCanonical and pdwPhoneInfoFlags value may be modified
  807. // overridden in certain situations. Please see comments below for details.
  808. //
  809. int nMaxPhoneLen = 0;
  810. BOOL bTmp = FALSE;
  811. // service profile: .CMP file
  812. CIni iniTmp(pArgs->piniProfile->GetHInst(),pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  813. iniTmp.SetEntryFromIdx(nIdx);
  814. //
  815. // Set the read flags
  816. //
  817. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA)
  818. {
  819. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  820. if (pszICSDataReg)
  821. {
  822. iniTmp.SetReadICSData(TRUE);
  823. iniTmp.SetICSDataPath(pszICSDataReg);
  824. }
  825. CmFree(pszICSDataReg);
  826. }
  827. LPTSTR pszTmp = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhonePrefix);
  828. if (ppszDesc)
  829. {
  830. *ppszDesc = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneDescPrefix);
  831. }
  832. if (ppszDUN)
  833. {
  834. *ppszDUN = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneDunPrefix);
  835. }
  836. if (pdwCountryID)
  837. {
  838. *pdwCountryID = iniTmp.GPPI(c_pszCmSection,c_pszCmEntryPhoneCountryPrefix);
  839. }
  840. if (ppszPhoneBookFile)
  841. {
  842. LPTSTR pszPb = iniTmp.GPPS(c_pszCmSection,c_pszCmEntryPhoneSourcePrefix);
  843. //
  844. // If the value is empty, just store the ptr
  845. //
  846. if ((!*pszPb))
  847. {
  848. *ppszPhoneBookFile = pszPb;
  849. }
  850. else
  851. {
  852. *ppszPhoneBookFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszPb);
  853. CmFree(pszPb);
  854. }
  855. }
  856. if (ppszRegionName)
  857. {
  858. *ppszRegionName = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryRegion);
  859. }
  860. if (ppszServiceType)
  861. {
  862. *ppszServiceType = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryServiceType);
  863. }
  864. //
  865. // Get the extended form of the telephone number.
  866. //
  867. if (ppszCanonical)
  868. {
  869. *ppszCanonical = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryPhoneCanonical);
  870. }
  871. //
  872. // Set the phoneinfo flags
  873. //
  874. if (pdwPhoneInfoFlags)
  875. {
  876. *pdwPhoneInfoFlags = 0;
  877. //
  878. // Get the dial as long distance flag. Check CMS if no value found.
  879. //
  880. int iTmp = iniTmp.GPPI(c_pszCmSection, c_pszCmEntryUseDialingRules, -1);
  881. if (-1 == iTmp)
  882. {
  883. iTmp = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryUseDialingRules, 1);
  884. }
  885. if (iTmp)
  886. {
  887. *pdwPhoneInfoFlags |= PIF_USE_DIALING_RULES;
  888. }
  889. }
  890. //
  891. // Truncate phone string if we have one.
  892. // Note: Admin can override our default, but we
  893. // must stay within RAS_MaxPhoneNumber chars.
  894. //
  895. if (pszTmp && *pszTmp)
  896. {
  897. int nDefaultPhoneLen = (OS_NT ? MAX_PHONE_LENNT : MAX_PHONE_LEN95);
  898. nMaxPhoneLen = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPhoneNumber, nDefaultPhoneLen);
  899. nMaxPhoneLen = __min(nMaxPhoneLen, RAS_MaxPhoneNumber);
  900. if ((int)lstrlenU(pszTmp) > nMaxPhoneLen)
  901. {
  902. pszTmp[nMaxPhoneLen] = TEXT('\0');
  903. }
  904. }
  905. //
  906. // Special handling for the case where we have a Phone number
  907. // but the CanonicalPhone value doesn't exist. This indicates
  908. // that its either a legacy profile or a hand-edit.
  909. //
  910. if (*pszTmp && ppszCanonical && *ppszCanonical && (!(**ppszCanonical)))
  911. {
  912. //
  913. // This block is for handling LEGACY numbers only. If we detect a
  914. // canonically formatted number (begins with "+"), then we re-format
  915. // the number to fit our new scheme. Hand-edits are not modified,
  916. // but PIF_USE_DIALING_RULES is turned off, which overrides the
  917. // default setting for the flag (if any) specified in
  918. // the .CMS
  919. //
  920. if (pszTmp == CmStrchr(pszTmp, TEXT('+')))
  921. {
  922. *pdwPhoneInfoFlags |= PIF_USE_DIALING_RULES;
  923. if (*ppszCanonical)
  924. {
  925. CmFree(*ppszCanonical);
  926. }
  927. *ppszCanonical = CmStrCpyAlloc(pszTmp);
  928. StripCanonical(pszTmp);
  929. }
  930. else
  931. {
  932. *pdwPhoneInfoFlags &= ~PIF_USE_DIALING_RULES; // #284702
  933. }
  934. }
  935. return (pszTmp);
  936. }
  937. // write phone number dialing options to .CMP file
  938. void PutPhoneByIdx(ArgsStruct *pArgs,
  939. UINT nIdx,
  940. LPCTSTR pszPhone,
  941. LPCTSTR pszDesc,
  942. LPCTSTR pszDUN,
  943. DWORD dwCountryID,
  944. LPCTSTR pszRegionName,
  945. LPCTSTR pszServiceType,
  946. LPCTSTR pszPhoneBookFile,
  947. LPCTSTR pszCanonical,
  948. DWORD dwPhoneInfoFlags)
  949. {
  950. CIni iniTmp(pArgs->piniProfile->GetHInst(), pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  951. iniTmp.SetEntryFromIdx(nIdx);
  952. //
  953. // Set the write flags
  954. //
  955. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_WRITE_ICS_DATA)
  956. {
  957. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  958. if (pszICSDataReg)
  959. {
  960. iniTmp.SetWriteICSData(TRUE);
  961. iniTmp.SetICSDataPath(pszICSDataReg);
  962. }
  963. CmFree(pszICSDataReg);
  964. }
  965. //
  966. // Store the raw form of the number
  967. //
  968. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhonePrefix, pszPhone);
  969. //
  970. // Store the canonical form of the number
  971. //
  972. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneCanonical, pszCanonical);
  973. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneDescPrefix, pszDesc);
  974. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneDunPrefix, pszDUN);
  975. iniTmp.WPPI(c_pszCmSection, c_pszCmEntryPhoneCountryPrefix, dwCountryID);
  976. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryRegion, pszRegionName);
  977. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryServiceType, pszServiceType);
  978. //
  979. // If there is a phonebookfile path, convert it to relative form
  980. //
  981. if (pszPhoneBookFile && *pszPhoneBookFile)
  982. {
  983. LPTSTR pszTmp = ReducePathToRelative(pArgs, pszPhoneBookFile);
  984. if (pszTmp)
  985. {
  986. iniTmp.WPPS(c_pszCmSection, c_pszCmEntryPhoneSourcePrefix, pszTmp);
  987. }
  988. CmFree(pszTmp);
  989. }
  990. iniTmp.WPPB(c_pszCmSection, c_pszCmEntryUseDialingRules, (dwPhoneInfoFlags & PIF_USE_DIALING_RULES));
  991. }
  992. //+----------------------------------------------------------------------------
  993. //
  994. // Function: LoadPhoneInfoFromProfile
  995. //
  996. // Synopsis: Load phone number information for profile to the dial info structure
  997. //
  998. // Arguments: ArgsStruct *pArgs -
  999. //
  1000. // Returns: Nothing
  1001. //
  1002. // History: fengsun Created Header 3/5/98
  1003. //
  1004. //+----------------------------------------------------------------------------
  1005. void LoadPhoneInfoFromProfile(ArgsStruct *pArgs)
  1006. {
  1007. for (int nPhoneIdx=0; nPhoneIdx<MAX_PHONE_NUMBERS; nPhoneIdx++)
  1008. {
  1009. LPTSTR pszDUN = NULL;
  1010. LPTSTR pszDesc = NULL;
  1011. LPTSTR pszPhoneBookFile = NULL;
  1012. LPTSTR pszRegionName = NULL;
  1013. LPTSTR pszServiceType = NULL;
  1014. LPTSTR pszCanonical = NULL;
  1015. DWORD dwCountryID;
  1016. DWORD dwPhoneInfoFlags;
  1017. //
  1018. // get phone number by index; Phone0, Phone1 , etc...
  1019. //
  1020. LPTSTR pszPhone = GetPhoneByIdx(pArgs,
  1021. nPhoneIdx,
  1022. &pszDesc,
  1023. &pszDUN,
  1024. &dwCountryID,
  1025. &pszRegionName,
  1026. &pszServiceType,
  1027. &pszPhoneBookFile,
  1028. &pszCanonical,
  1029. &dwPhoneInfoFlags);
  1030. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber,
  1031. CELEMS(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber),
  1032. pszPhone, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1033. pArgs->aDialInfo[nPhoneIdx].dwCountryID = dwCountryID;
  1034. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szDUN,
  1035. CELEMS(pArgs->aDialInfo[nPhoneIdx].szDUN),
  1036. pszDUN, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1037. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szPhoneBookFile,
  1038. CELEMS(pArgs->aDialInfo[nPhoneIdx].szPhoneBookFile),
  1039. pszPhoneBookFile, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1040. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szDesc,
  1041. CELEMS(pArgs->aDialInfo[nPhoneIdx].szDesc),
  1042. pszDesc, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1043. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szRegionName,
  1044. CELEMS(pArgs->aDialInfo[nPhoneIdx].szRegionName),
  1045. pszRegionName, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1046. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szServiceType,
  1047. CELEMS(pArgs->aDialInfo[nPhoneIdx].szServiceType),
  1048. pszServiceType, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1049. (void)StringCchCopyEx(pArgs->aDialInfo[nPhoneIdx].szCanonical,
  1050. CELEMS(pArgs->aDialInfo[nPhoneIdx].szCanonical),
  1051. pszCanonical, NULL, NULL, STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE);
  1052. pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags = dwPhoneInfoFlags;
  1053. //
  1054. // Cleanup
  1055. //
  1056. CmFree(pszDUN);
  1057. CmFree(pszPhone);
  1058. CmFree(pszDesc);
  1059. CmFree(pszPhoneBookFile);
  1060. CmFree(pszRegionName);
  1061. CmFree(pszServiceType);
  1062. CmFree(pszCanonical);
  1063. } // for loop
  1064. }
  1065. //+----------------------------------------------------------------------------
  1066. //
  1067. // Function: LoadDialInfo
  1068. //
  1069. // Synopsis: load dialup information
  1070. //
  1071. // Arguments: ArgsStruct *pArgs - Ptr to glbal Args struct
  1072. // HWND hwndDlg - HWND of main dialog
  1073. // BOOL fInstallModem - Whether we should check modem isntall
  1074. // BOOL fAlwaysMunge - Whether we should munge the phone number
  1075. //
  1076. // Returns: DWORD - ERROR_SUCCESS if load successfuly
  1077. // ERROR_PORT_NOT_AVAILABLE if can not find any modem
  1078. // ERROR_BAD_PHONE_NUMBER either there is no primary phone #
  1079. // or failed to convert it to dialable #
  1080. //
  1081. // History: 10/24/97 fengsun Created Header and change return type to DWORD
  1082. // 02/08/99 nickball Added fAlwaysMunge
  1083. //
  1084. //+----------------------------------------------------------------------------
  1085. DWORD LoadDialInfo(ArgsStruct *pArgs, HWND hwndDlg, BOOL fInstallModem, BOOL fAlwaysMunge)
  1086. {
  1087. DWORD dwRet = ERROR_SUCCESS;
  1088. if (pArgs->bDialInfoLoaded)
  1089. {
  1090. if (pArgs->aDialInfo[0].szDialablePhoneNumber[0] == TEXT('\0') &&
  1091. pArgs->aDialInfo[1].szDialablePhoneNumber[0] == TEXT('\0'))
  1092. {
  1093. return ERROR_BAD_PHONE_NUMBER;
  1094. }
  1095. else
  1096. {
  1097. //
  1098. // If fAlways munge is set, then stick around.
  1099. //
  1100. if (!fAlwaysMunge)
  1101. {
  1102. return ERROR_SUCCESS;
  1103. }
  1104. }
  1105. }
  1106. //
  1107. // Don't need to repeat ourselves
  1108. //
  1109. if (!pArgs->bDialInfoLoaded)
  1110. {
  1111. pArgs->fNoDialingRules = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmNoDialingRules);
  1112. //
  1113. // Do a full test on just the modem
  1114. //
  1115. if (fInstallModem)
  1116. {
  1117. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM, hwndDlg, pArgs->szServiceName);
  1118. if (pArgs->dwExitCode != ERROR_SUCCESS)
  1119. {
  1120. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1121. goto LoadDialInfoExit;
  1122. }
  1123. }
  1124. //
  1125. // Establish TAPI link before we continue
  1126. //
  1127. if (!LinkToTapi(&pArgs->tlsTapiLink, "TAPI32") )
  1128. {
  1129. //
  1130. // Link to TAPI failed.
  1131. // If unattended, return with failure.
  1132. // Otherwise, try to install components and LinkToTapi again
  1133. //
  1134. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  1135. if (!(pArgs->dwFlags & FL_UNATTENDED))
  1136. {
  1137. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM | CC_RNA | CC_RASRUNNING,
  1138. hwndDlg, pArgs->szServiceName);
  1139. }
  1140. if (pArgs->dwExitCode != ERROR_SUCCESS || !LinkToTapi(&pArgs->tlsTapiLink, "TAPI32"))
  1141. {
  1142. pArgs->szDeviceType[0] = TEXT('\0');
  1143. pArgs->szDeviceName[0] = TEXT('\0');
  1144. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1145. goto LoadDialInfoExit;
  1146. }
  1147. }
  1148. //
  1149. // RasEnumDevice and LineInitialize is SLOW. It takes 50% of the start-up time
  1150. //
  1151. if (!PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName))
  1152. {
  1153. //
  1154. // Because pick modem failed we need to check if we have RAS/Modem installed
  1155. //
  1156. ClearComponentsChecked();
  1157. //
  1158. // No modem is installed.
  1159. // If unattended or caller does not want to install modem, return with failure.
  1160. // Otherwise, try to install the modem and call pick modem again
  1161. //
  1162. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  1163. if (!(pArgs->dwFlags & FL_UNATTENDED) && fInstallModem)
  1164. {
  1165. pArgs->dwExitCode = CheckAndInstallComponents(CC_MODEM | CC_RNA | CC_RASRUNNING,
  1166. hwndDlg, pArgs->szServiceName);
  1167. }
  1168. if (pArgs->dwExitCode != ERROR_SUCCESS ||
  1169. !PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName))
  1170. {
  1171. pArgs->szDeviceType[0] = TEXT('\0');
  1172. pArgs->szDeviceName[0] = TEXT('\0');
  1173. dwRet = ERROR_PORT_NOT_AVAILABLE;
  1174. goto LoadDialInfoExit;
  1175. }
  1176. }
  1177. }
  1178. //
  1179. // See if munge is required and Cleanup as needed
  1180. //
  1181. if (!pArgs->bDialInfoLoaded || TRUE == fAlwaysMunge)
  1182. {
  1183. MungeDialInfo(pArgs);
  1184. pArgs->bDialInfoLoaded = TRUE;
  1185. }
  1186. if (pArgs->aDialInfo[0].szDialablePhoneNumber[0] == TEXT('\0') &&
  1187. pArgs->aDialInfo[1].szDialablePhoneNumber[0] == TEXT('\0'))
  1188. {
  1189. dwRet = ERROR_BAD_PHONE_NUMBER;
  1190. }
  1191. LoadDialInfoExit:
  1192. return dwRet;
  1193. }
  1194. //+----------------------------------------------------------------------------
  1195. //
  1196. // Function: MungeDialInfo
  1197. //
  1198. // Synopsis: Encapsulates the munging of the phone numbers prior to dialing
  1199. //
  1200. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  1201. //
  1202. // Returns: Nothing - Check Dialable string and fNeedConfigureTapi
  1203. //
  1204. // History: 02/08/99 nickball Created - pulled from LoadDialInfo
  1205. //
  1206. //+----------------------------------------------------------------------------
  1207. VOID MungeDialInfo(ArgsStruct *pArgs)
  1208. {
  1209. for (int nPhoneIdx=0; nPhoneIdx<MAX_PHONE_NUMBERS; nPhoneIdx++)
  1210. {
  1211. //
  1212. // If dialing rules is disabled, then just use the NonCanonical #
  1213. //
  1214. if (pArgs->fNoDialingRules)
  1215. {
  1216. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1217. pArgs->aDialInfo[nPhoneIdx].szPhoneNumber, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1218. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1219. pArgs->aDialInfo[nPhoneIdx].szPhoneNumber, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1220. pArgs->aDialInfo[nPhoneIdx].szCanonical[0] = TEXT('\0');
  1221. continue;
  1222. }
  1223. LPTSTR pszDialableString= NULL;
  1224. //
  1225. // Retrieve the number based upon dialing rules and munge it.
  1226. //
  1227. LPTSTR pszPhone;
  1228. if (pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags & PIF_USE_DIALING_RULES)
  1229. {
  1230. pszPhone = CmStrCpyAlloc(pArgs->aDialInfo[nPhoneIdx].szCanonical);
  1231. }
  1232. else
  1233. {
  1234. pszPhone = CmStrCpyAlloc(pArgs->aDialInfo[nPhoneIdx].szPhoneNumber);
  1235. }
  1236. if (pszPhone && pszPhone[0])
  1237. {
  1238. //
  1239. // If we can't munge the number, display an error
  1240. //
  1241. if (pArgs->szDeviceName[0] &&
  1242. ERROR_SUCCESS != MungePhone(pArgs->szDeviceName,
  1243. &pszPhone,
  1244. &pArgs->tlsTapiLink,
  1245. g_hInst,
  1246. pArgs->aDialInfo[nPhoneIdx].dwPhoneInfoFlags & PIF_USE_DIALING_RULES,
  1247. &pszDialableString,
  1248. pArgs->fAccessPointsEnabled))
  1249. {
  1250. CmFree(pszPhone);
  1251. pszPhone = CmStrCpyAlloc(TEXT("")); // CmFmtMsg(g_hInst,IDMSG_CANTFORMAT);
  1252. pszDialableString = CmStrCpyAlloc(TEXT("")); // CmFmtMsg(g_hInst,IDMSG_CANTFORMAT);
  1253. }
  1254. else if (!pszDialableString || pszDialableString[0] == '\0')
  1255. {
  1256. //
  1257. // So what happened now? pszPhone is not empty, but after
  1258. // we munge the phone, which means applying TAPI rules,
  1259. // pszDialbleString becomes empty. This means only one
  1260. // thing: TAPI isn't intialized.
  1261. //
  1262. // Note: If you uninstall TAPI between launching the app.
  1263. // and pressing connect, all bets are off with the above.
  1264. //
  1265. // This flag will be reset in CheckTapi(), which will put
  1266. // up a TAPI configuration dialog and ask the user to fill
  1267. // up such information
  1268. //
  1269. pArgs->fNeedConfigureTapi = TRUE;
  1270. }
  1271. }
  1272. // Copy the munged number
  1273. //
  1274. // Unless explicitly disabled we always apply TAPI rules
  1275. // in order to pick up TONE/PULSE, etc.
  1276. //
  1277. if (NULL != pszDialableString)
  1278. {
  1279. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1280. pszDialableString, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1281. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1282. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1283. }
  1284. else
  1285. {
  1286. if (NULL != pszPhone)
  1287. {
  1288. //
  1289. // Just do it on WIN32 because our TAPI checks were done above
  1290. //
  1291. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber,
  1292. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDialablePhoneNumber));
  1293. lstrcpynU(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber,
  1294. pszPhone, CELEMS(pArgs->aDialInfo[nPhoneIdx].szDisplayablePhoneNumber));
  1295. }
  1296. }
  1297. CmFree(pszPhone);
  1298. CmFree(pszDialableString);
  1299. } // for loop
  1300. }
  1301. //+---------------------------------------------------------------------------
  1302. //
  1303. // Function: LoadHelpFileInfo
  1304. //
  1305. // Synopsis: Load the help file name
  1306. //
  1307. // Arguments: pArgs [the ptr to ArgsStruct]
  1308. //
  1309. // Returns: NONE
  1310. //
  1311. // History: henryt Created 3/5/97
  1312. // byao Modified 3/20/97 to handle empty helpfile string
  1313. //----------------------------------------------------------------------------
  1314. void LoadHelpFileInfo(ArgsStruct *pArgs)
  1315. {
  1316. MYDBGASSERT(pArgs);
  1317. //
  1318. // Look for a custom helpfile name, otherwise use default.
  1319. //
  1320. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryHelpFile);
  1321. if (NULL == pszTmp || 0 == pszTmp[0])
  1322. {
  1323. CmFree(pszTmp);
  1324. pszTmp = CmStrCpyAlloc(c_pszDefaultHelpFile);
  1325. }
  1326. //
  1327. // Make sure that any relative path is converted to full
  1328. //
  1329. pArgs->pszHelpFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  1330. CmFree(pszTmp);
  1331. }
  1332. //
  1333. // CopyPhone:
  1334. //
  1335. void CopyPhone(ArgsStruct *pArgs,
  1336. LPRASENTRY preEntry,
  1337. DWORD dwEntry)
  1338. {
  1339. LPTSTR pszPhone = NULL;
  1340. LPTSTR pszCanonical = NULL;
  1341. LPTSTR pszTmp;
  1342. LPTSTR pszDescription = NULL;
  1343. BOOL Setcountry = FALSE;
  1344. DWORD dwPhoneInfoFlags = 0;
  1345. pszPhone = GetPhoneByIdx(pArgs,(UINT) dwEntry, &pszDescription,
  1346. NULL, NULL, NULL,
  1347. NULL, NULL, &pszCanonical, &dwPhoneInfoFlags);
  1348. //
  1349. // If "Use Dialing Rules" turn of CountryAndAreaCodes option
  1350. //
  1351. if (dwPhoneInfoFlags & PIF_USE_DIALING_RULES)
  1352. {
  1353. //
  1354. // We want to use dialing rules, so parse the canonical form
  1355. // of the number to get the country and area codes for the entry
  1356. //
  1357. pszTmp = CmStrchr(pszCanonical,TEXT('+'));
  1358. if (pszTmp)
  1359. {
  1360. preEntry->dwCountryCode = CmAtol(pszTmp+1);
  1361. //
  1362. // NOTE: Currently CM uses code and ID interchangeably
  1363. // The countryID value in the .CMP is actually the country
  1364. // code used when constructing the phone number in its
  1365. // canonical format. This is probably not entirely correct
  1366. // but we maitain consistency with it here by using the
  1367. // country code parsed from the number as the country ID.
  1368. //
  1369. preEntry->dwCountryID = preEntry->dwCountryCode;
  1370. preEntry->dwfOptions |= RASEO_UseCountryAndAreaCodes;
  1371. Setcountry = TRUE;
  1372. }
  1373. if (Setcountry)
  1374. {
  1375. pszTmp = CmStrchr(pszCanonical,'('); //strip out area code
  1376. if (pszTmp)
  1377. {
  1378. (void)StringCchPrintfEx(preEntry->szAreaCode, CELEMS(preEntry->szAreaCode), NULL, NULL,
  1379. (STRSAFE_IGNORE_NULLS | STRSAFE_NULL_ON_FAILURE), TEXT("%u"), CmAtol(pszTmp+1));
  1380. }
  1381. pszTmp = CmStrchr(pszCanonical,')');
  1382. if (pszTmp)
  1383. {
  1384. ++pszTmp;
  1385. while(*pszTmp == ' ')
  1386. ++pszTmp; //remove whitespace
  1387. }
  1388. else
  1389. {
  1390. // no area code
  1391. preEntry->szAreaCode[0]=TEXT('\0');
  1392. pszTmp = CmStrchr(pszCanonical,' ');
  1393. if (pszTmp)
  1394. {
  1395. while(*pszTmp == ' ')
  1396. ++pszTmp; // skip past space - may need MBCS change
  1397. }
  1398. }
  1399. }
  1400. }
  1401. else
  1402. {
  1403. //
  1404. // Use the straight up phone number and don't apply rules
  1405. //
  1406. preEntry->dwfOptions &= ~RASEO_UseCountryAndAreaCodes;
  1407. pszTmp = pszPhone;
  1408. }
  1409. if ((NULL != pszTmp) && *pszTmp)
  1410. {
  1411. lstrcpynU(preEntry->szLocalPhoneNumber, pszTmp, CELEMS(preEntry->szLocalPhoneNumber));
  1412. }
  1413. else
  1414. {
  1415. lstrcpynU(preEntry->szLocalPhoneNumber, TEXT(" "), CELEMS(preEntry->szLocalPhoneNumber));//prevent zero from appearing
  1416. }
  1417. CmFree(pszPhone);
  1418. CmFree(pszCanonical);
  1419. CmFree(pszDescription);
  1420. }
  1421. //+----------------------------------------------------------------------------
  1422. //
  1423. // Function: AppendStatusPane
  1424. //
  1425. // Synopsis: Append the text to the main dialog status window
  1426. //
  1427. // Arguments: HWND hwndDlg - The main dialog window handle
  1428. // DWORD dwMsgId - The resource id of the message
  1429. //
  1430. // Returns: Nothing
  1431. //
  1432. // History: Created Header 10/24/97
  1433. //
  1434. //+----------------------------------------------------------------------------
  1435. void AppendStatusPane(HWND hwndDlg,
  1436. DWORD dwMsgId)
  1437. {
  1438. LPTSTR pszTmp = CmFmtMsg(g_hInst,dwMsgId);
  1439. if (pszTmp != NULL)
  1440. {
  1441. AppendStatusPane(hwndDlg,pszTmp);
  1442. CmFree(pszTmp);
  1443. }
  1444. }
  1445. //
  1446. // AppendStatusPane: Update the original status, append new message 'pszMsg'
  1447. // at the end
  1448. //
  1449. void AppendStatusPane(HWND hwndDlg,
  1450. LPCTSTR pszMsg)
  1451. {
  1452. size_t nLines;
  1453. //
  1454. // Get the existing message
  1455. //
  1456. LPTSTR pszStatus = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_STATUS_DISPLAY);
  1457. LPTSTR pszTmp = CmStrrchr(pszStatus, TEXT('\n'));
  1458. if (!pszTmp)
  1459. {
  1460. // empty message, so simply display 'pszMsg'
  1461. CmFree(pszStatus);
  1462. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY,pszMsg);
  1463. //
  1464. // force an update right away
  1465. //
  1466. UpdateWindow(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY));
  1467. return;
  1468. }
  1469. pszTmp[1] = 0;
  1470. CmStrCatAlloc(&pszStatus,pszMsg); // append pszMsg at the end of old message
  1471. nLines = 0;
  1472. pszTmp = pszStatus + lstrlenU(pszStatus);
  1473. while (pszTmp != pszStatus)
  1474. {
  1475. pszTmp--;
  1476. if (*pszTmp == '\n')
  1477. {
  1478. if (++nLines == 2)
  1479. {
  1480. lstrcpyU(pszStatus,pszTmp+1);
  1481. break;
  1482. }
  1483. }
  1484. }
  1485. SetDlgItemTextU(hwndDlg,IDC_MAIN_STATUS_DISPLAY,pszStatus);
  1486. SendDlgItemMessageU(hwndDlg,IDC_MAIN_STATUS_DISPLAY,EM_SCROLL,SB_PAGEDOWN,0);
  1487. CmFree(pszStatus);
  1488. //
  1489. // force an update right away
  1490. //
  1491. UpdateWindow(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY));
  1492. }
  1493. // bitmap logo loading code - took this out of LoadFromFile so it can
  1494. // be called in multiple cases - like when the FS OC loading code
  1495. // fails, we can degrade gracefully with this.
  1496. VOID LoadLogoBitmap(ArgsStruct * pArgs,
  1497. HWND hwndDlg)
  1498. {
  1499. LPTSTR pszTmp;
  1500. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryLogo);
  1501. if (*pszTmp)
  1502. {
  1503. //
  1504. // Make sure we have a full path (if appropriate) and load logo bitmap
  1505. //
  1506. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  1507. pArgs->BmpData.hDIBitmap = CmLoadBitmap(g_hInst, pszFile);
  1508. CmFree(pszFile);
  1509. }
  1510. CmFree(pszTmp);
  1511. if (!pArgs->BmpData.hDIBitmap)
  1512. {
  1513. pArgs->BmpData.hDIBitmap = CmLoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_APP));
  1514. }
  1515. //
  1516. // If we have a handle, create a new Device Dependent bitmap
  1517. //
  1518. if (pArgs->BmpData.hDIBitmap)
  1519. {
  1520. pArgs->BmpData.phMasterPalette = &pArgs->hMasterPalette;
  1521. pArgs->BmpData.bForceBackground = TRUE; // paint as a background app
  1522. if (CreateBitmapData(pArgs->BmpData.hDIBitmap, &pArgs->BmpData, hwndDlg, TRUE))
  1523. {
  1524. SendDlgItemMessageU(hwndDlg,IDC_MAIN_BITMAP,STM_SETIMAGE,IMAGE_BITMAP,
  1525. (LPARAM) &pArgs->BmpData);
  1526. }
  1527. }
  1528. }
  1529. const LONG MAX_SECTION = 512;
  1530. HRESULT LoadFutureSplash(ArgsStruct * pArgs,
  1531. HWND hwndDlg)
  1532. {
  1533. // set up the Future Splash OC container.
  1534. LPCTSTR pszFile = pArgs->piniBoth->GetFile();
  1535. TCHAR achSections[MAX_SECTION] = {0};
  1536. HRESULT hr;
  1537. LPTSTR pszVal = NULL;
  1538. LPTSTR pszTmp = NULL;
  1539. LPICMOCCtr pCtr;
  1540. pArgs->pCtr = new CICMOCCtr(hwndDlg, ::GetDlgItem(hwndDlg, IDC_MAIN_BITMAP));
  1541. if (!pArgs->pCtr)
  1542. {
  1543. goto MemoryError;
  1544. }
  1545. if (!pArgs->pCtr->Initialized())
  1546. {
  1547. hr = E_FAIL;
  1548. goto Cleanup;
  1549. }
  1550. pCtr = pArgs->pCtr;
  1551. if (!::GetPrivateProfileStringU(
  1552. c_pszCmSectionAnimatedLogo,
  1553. 0,
  1554. TEXT(""),
  1555. achSections,
  1556. NElems(achSections),
  1557. pszFile))
  1558. {
  1559. hr = E_FAIL;
  1560. goto Cleanup;
  1561. }
  1562. pszVal = (LPTSTR) CmMalloc(INTERNET_MAX_URL_LENGTH * sizeof(TCHAR));
  1563. if (NULL == pszVal)
  1564. {
  1565. hr = E_OUTOFMEMORY;
  1566. goto Cleanup;
  1567. }
  1568. pszTmp = achSections;
  1569. while (pszTmp[0])
  1570. {
  1571. // if this fails, we keep on looping, looking for
  1572. // the next one.
  1573. if (::GetPrivateProfileStringU(
  1574. c_pszCmSectionAnimatedLogo,
  1575. pszTmp,
  1576. TEXT(""),
  1577. pszVal,
  1578. NElems(pszVal),
  1579. pszFile))
  1580. {
  1581. if (lstrcmpiU(pszTmp, c_pszCmEntryAniMovie) == 0) // is this the 'movie' entry?
  1582. {
  1583. //
  1584. // Build full path from .CMP and relative path
  1585. //
  1586. LPTSTR pszMovieFileName = CmBuildFullPathFromRelative(pArgs->piniProfile->GetFile(), pszVal);
  1587. if (!pszMovieFileName)
  1588. {
  1589. hr = S_FALSE;
  1590. CmFree(pszMovieFileName);
  1591. goto Cleanup;
  1592. }
  1593. //
  1594. // Does this file exist?
  1595. //
  1596. if (FALSE == FileExists(pszMovieFileName))
  1597. {
  1598. hr = S_FALSE;
  1599. CmFree(pszMovieFileName);
  1600. goto Cleanup;
  1601. }
  1602. lstrcpyU(pszVal, pszMovieFileName); // store the full pathname back
  1603. CmFree(pszMovieFileName);
  1604. }
  1605. hr = pCtr->AddPropertyToBag(pszTmp, pszVal);
  1606. if (S_OK != hr)
  1607. goto Cleanup;
  1608. }
  1609. // get the next key name.
  1610. pszTmp += (lstrlenU(pszTmp) + 1);
  1611. }
  1612. // create the Future Splash OC.
  1613. hr = pCtr->CreateFSOC(&pArgs->olsOle32Link);
  1614. if (S_OK != hr)
  1615. {
  1616. goto Cleanup;
  1617. }
  1618. // now, do the state mappings, no matter what happens, we won't
  1619. // fail on this. just keep on going.
  1620. pCtr->SetFrameMapping(PS_Interactive,
  1621. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1622. c_pszCmEntryAniPsInteractive,
  1623. -1,
  1624. pszFile));
  1625. pCtr->SetFrameMapping(PS_Dialing,
  1626. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1627. c_pszCmEntryAniPsDialing0,
  1628. -1,
  1629. pszFile));
  1630. pCtr->SetFrameMapping(PS_RedialFrame,
  1631. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1632. c_pszCmEntryAniPsDialing1,
  1633. -1,
  1634. pszFile));
  1635. pCtr->SetFrameMapping(PS_Pausing,
  1636. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1637. c_pszCmEntryAniPsPausing,
  1638. -1,
  1639. pszFile));
  1640. pCtr->SetFrameMapping(PS_Authenticating,
  1641. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1642. c_pszCmEntryAniPsAuthenticating,
  1643. -1,
  1644. pszFile));
  1645. pCtr->SetFrameMapping(PS_Online,
  1646. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1647. c_pszCmEntryAniPsOnline,
  1648. -1,
  1649. pszFile));
  1650. pCtr->SetFrameMapping(PS_TunnelDialing,
  1651. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1652. c_pszCmEntryAniPsTunnel,
  1653. -1,
  1654. pszFile));
  1655. pCtr->SetFrameMapping(PS_Error,
  1656. ::GetPrivateProfileIntU(c_pszCmSectionAnimatedActions,
  1657. c_pszCmEntryAniPsError,
  1658. -1,
  1659. pszFile));
  1660. Cleanup:
  1661. if (pszVal)
  1662. {
  1663. CmFree(pszVal);
  1664. }
  1665. return hr;
  1666. MemoryError:
  1667. hr = E_OUTOFMEMORY;
  1668. goto Cleanup;
  1669. }
  1670. //+---------------------------------------------------------------------------
  1671. //
  1672. // Function: LoadProperties
  1673. //
  1674. // Synopsis: This func loads CM Properties from cmp/cms, registry, password
  1675. // cache, etc, into its internal variables. This func should
  1676. // only be called once. This should not be specific to the main
  1677. // sign-in dlg. DO NOT do any icon/bitmap stuff, dlg specific
  1678. // stuff here.
  1679. //
  1680. // Arguments: pArgs [the ptr to ArgsStruct]
  1681. //
  1682. // Returns: NONE
  1683. //
  1684. // History: henryt Created 5/2/97
  1685. //
  1686. // t-urama Modified 08/02/00 Added Access Points
  1687. //----------------------------------------------------------------------------
  1688. void LoadProperties(
  1689. ArgsStruct *pArgs
  1690. )
  1691. {
  1692. LPTSTR pszTmp = NULL;
  1693. LPTSTR pszUserName = NULL;
  1694. UINT nTmp;
  1695. CMTRACE(TEXT("Begin LoadProperties()"));
  1696. //
  1697. // First make sure we can use the RAS CredStore
  1698. // This flag is used in the calls below
  1699. //
  1700. if (OS_NT5)
  1701. {
  1702. pArgs->bUseRasCredStore = TRUE;
  1703. }
  1704. //
  1705. // Upgrade userinfo if necessary. Note that we have
  1706. // an upgrade from CM 1.0/1.1 cmp data and we also
  1707. // have an upgrade of CM 1.2 registry data to
  1708. // the method used in CM 1.3 on Win2k which uses both
  1709. // the registry and RAS credential storage.
  1710. //
  1711. int iUpgradeType = NeedToUpgradeUserInfo(pArgs);
  1712. if (c_iUpgradeFromRegToRas == iUpgradeType)
  1713. {
  1714. UpgradeUserInfoFromRegToRasAndReg(pArgs);
  1715. }
  1716. else if (c_iUpgradeFromCmp == iUpgradeType)
  1717. {
  1718. UpgradeUserInfoFromCmp(pArgs);
  1719. }
  1720. //
  1721. // Need to refresh Credential support. The TRUE flag also sets the current creds
  1722. // type inside the function. If an error occurs we can keep executing.
  1723. //
  1724. if(FALSE == RefreshCredentialTypes(pArgs, TRUE))
  1725. {
  1726. CMTRACE(TEXT("LoadProperties() - Error refreshing credential types."));
  1727. }
  1728. if (IsTunnelEnabled(pArgs))
  1729. {
  1730. //
  1731. // do we use the same username/password for tunneling?
  1732. // This value is set by ISP, CM does not change it
  1733. //
  1734. pArgs->fUseSameUserName = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName);
  1735. //
  1736. // read in inet username
  1737. // Special case where the same user name isn't being used, and internet globals don't exist
  1738. // Then we have to read the user name from the user creds store in order to pre-populate
  1739. //
  1740. DWORD dwRememberedCredType = pArgs->dwCurrentCredentialType;
  1741. pszUserName = NULL;
  1742. if ((FALSE == pArgs->fUseSameUserName) &&
  1743. (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType) &&
  1744. (FALSE == (BOOL)(CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)))
  1745. {
  1746. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  1747. }
  1748. GetUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszUserName);
  1749. //
  1750. // Restore credential store
  1751. //
  1752. pArgs->dwCurrentCredentialType = dwRememberedCredType;
  1753. if (pszUserName)
  1754. {
  1755. //
  1756. // check username length
  1757. //
  1758. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  1759. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  1760. {
  1761. CmFree(pszUserName);
  1762. pArgs->szInetUserName[0] = TEXT('\0');
  1763. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  1764. }
  1765. else
  1766. {
  1767. lstrcpyU(pArgs->szInetUserName, pszUserName);
  1768. CmFree(pszUserName);
  1769. }
  1770. }
  1771. else
  1772. {
  1773. *pArgs->szInetUserName = TEXT('\0');
  1774. }
  1775. //
  1776. // Read in inet password unless we are reconnecting in which case, we
  1777. // already have the correct password, and we want to use it and dial
  1778. // automatically.
  1779. //
  1780. if (!(pArgs->dwFlags & FL_RECONNECT))
  1781. {
  1782. LPTSTR pszPassword = NULL;
  1783. GetUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszPassword);
  1784. if (!pszPassword)
  1785. {
  1786. CmWipePassword(pArgs->szInetPassword);
  1787. }
  1788. else
  1789. {
  1790. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  1791. if ((UINT)lstrlenU(pszPassword) > __min(PWLEN, nTmp))
  1792. {
  1793. CmFree(pszPassword);
  1794. pszPassword = CmStrCpyAlloc(TEXT(""));
  1795. }
  1796. lstrcpyU(pArgs->szInetPassword, pszPassword);
  1797. CmEncodePassword(pArgs->szInetPassword); // Never leave a PWD in plain text on heap
  1798. CmWipePassword(pszPassword);
  1799. CmFree(pszPassword);
  1800. }
  1801. }
  1802. }
  1803. //
  1804. // The presence of either lpRasNoUser or lpEapLogonInfo indicates
  1805. // that we retrieved credentials via WinLogon. We ignore cached
  1806. // creds in this situation.
  1807. //
  1808. if ((!pArgs->lpRasNoUser) && (!pArgs->lpEapLogonInfo))
  1809. {
  1810. //
  1811. // get username, domain, etc. from CMS file
  1812. //
  1813. GetUserInfo(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  1814. if (pszUserName)
  1815. {
  1816. //
  1817. // check username length
  1818. //
  1819. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  1820. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  1821. {
  1822. CmFree(pszUserName);
  1823. pszUserName = CmStrCpyAlloc(TEXT(""));
  1824. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUserName);
  1825. }
  1826. lstrcpyU(pArgs->szUserName, pszUserName);
  1827. CmFree(pszUserName);
  1828. }
  1829. else
  1830. {
  1831. *pArgs->szUserName = TEXT('\0');
  1832. }
  1833. //
  1834. // Read in the standard password unless we are reconnecting in which case
  1835. // we already have the correct password, and we want to use it and dial
  1836. // automatically.
  1837. //
  1838. if (!(pArgs->dwFlags & FL_RECONNECT))
  1839. {
  1840. pszTmp = NULL;
  1841. GetUserInfo(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp);
  1842. if (pszTmp)
  1843. {
  1844. //
  1845. // max length for user password
  1846. //
  1847. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryMaxPassword,PWLEN);
  1848. if ((UINT)lstrlenU(pszTmp) > __min(PWLEN,nTmp))
  1849. {
  1850. CmFree(pszTmp);
  1851. pszTmp = CmStrCpyAlloc(TEXT(""));
  1852. }
  1853. lstrcpyU(pArgs->szPassword, pszTmp);
  1854. CmEncodePassword(pArgs->szPassword); // Never leave a PWD in plain text on heap
  1855. CmWipePassword(pszTmp);
  1856. CmFree(pszTmp);
  1857. }
  1858. else
  1859. {
  1860. CmWipePassword(pArgs->szPassword);
  1861. }
  1862. }
  1863. //
  1864. // Load domain info
  1865. //
  1866. LPTSTR pszDomain = NULL;
  1867. GetUserInfo(pArgs, UD_ID_DOMAIN, (PVOID*)&pszDomain);
  1868. if (pszDomain)
  1869. {
  1870. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  1871. if (nTmp <= 0)
  1872. {
  1873. nTmp = DNLEN;
  1874. }
  1875. if ((UINT)lstrlenU(pszDomain) > __min(DNLEN, nTmp))
  1876. {
  1877. CmFree(pszDomain);
  1878. pszDomain = CmStrCpyAlloc(TEXT(""));
  1879. }
  1880. lstrcpyU(pArgs->szDomain, pszDomain);
  1881. CmFree(pszDomain);
  1882. }
  1883. else
  1884. {
  1885. *pArgs->szDomain = TEXT('\0');
  1886. }
  1887. }
  1888. //
  1889. // fDialAutomatically,
  1890. // fRememberMainPassword
  1891. //
  1892. if (pArgs->fHideDialAutomatically)
  1893. {
  1894. pArgs->fDialAutomatically = FALSE;
  1895. }
  1896. else
  1897. {
  1898. PVOID pv = &pArgs->fDialAutomatically;
  1899. GetUserInfo(pArgs, UD_ID_NOPROMPT, &pv);
  1900. }
  1901. if (pArgs->fHideRememberPassword)
  1902. {
  1903. pArgs->fRememberMainPassword = FALSE;
  1904. }
  1905. else
  1906. {
  1907. //
  1908. // For Win2K+ this gets trickier because we use the RAS cred store and
  1909. // we know which creds were saved. Thus we need to modify this flag according
  1910. // to what credentials we actually have, insted of what was retrieved from the registry/file.
  1911. // This needs to be done after calling the function that refreshes credential types (above).
  1912. //
  1913. if (OS_NT5)
  1914. {
  1915. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  1916. {
  1917. pArgs->fRememberMainPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)? TRUE: FALSE);
  1918. }
  1919. else
  1920. {
  1921. pArgs->fRememberMainPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)? TRUE: FALSE);
  1922. }
  1923. }
  1924. else
  1925. {
  1926. PVOID pv = &pArgs->fRememberMainPassword;
  1927. GetUserInfo(pArgs, UD_ID_REMEMBER_PWD, &pv);
  1928. }
  1929. }
  1930. //
  1931. // remember non-tunnel password?
  1932. //
  1933. if (pArgs->fHideRememberInetPassword)
  1934. {
  1935. pArgs->fRememberInetPassword = FALSE;
  1936. }
  1937. else
  1938. {
  1939. //
  1940. // For Win2K+ this gets trickier because we use the RAS cred store and
  1941. // we know which creds were saved. Thus we need to modify this flag according
  1942. // to what credentials we actually have, insted of what was retrieved from the registry/file.
  1943. // This needs to be done after calling the function that refreshes credential types (above).
  1944. //
  1945. if (OS_NT5)
  1946. {
  1947. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  1948. {
  1949. pArgs->fRememberInetPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)? TRUE: FALSE);
  1950. }
  1951. else
  1952. {
  1953. pArgs->fRememberInetPassword = ((BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)? TRUE: FALSE);
  1954. }
  1955. }
  1956. else
  1957. {
  1958. PVOID pv = &pArgs->fRememberInetPassword;
  1959. GetUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, &pv);
  1960. }
  1961. }
  1962. //
  1963. // Make sure that the passwords are empty if we don't want to remember them
  1964. // unless we are reconnecting in which case we will just use what we have
  1965. // from the previous connection. When the log on type is ICS don't want
  1966. // to clear the passwords either.
  1967. //
  1968. if ((!(pArgs->dwFlags & FL_RECONNECT)) &&
  1969. (!pArgs->lpRasNoUser) &&
  1970. (!pArgs->lpEapLogonInfo) &&
  1971. (CM_LOGON_TYPE_ICS != pArgs->dwWinLogonType))
  1972. {
  1973. //
  1974. // NULL the password if dial-auto is disabled.
  1975. //
  1976. if (!pArgs->fRememberMainPassword)
  1977. {
  1978. CmWipePassword(pArgs->szPassword);
  1979. }
  1980. if (!pArgs->fRememberInetPassword)
  1981. {
  1982. CmWipePassword(pArgs->szInetPassword);
  1983. }
  1984. }
  1985. //
  1986. // has references
  1987. //
  1988. pszTmp = pArgs->piniService->GPPS(c_pszCmSectionIsp, c_pszCmEntryIspReferences);
  1989. pArgs->fHasRefs = (pszTmp && *pszTmp ? TRUE : FALSE);
  1990. CmFree(pszTmp);
  1991. //
  1992. // do we have valid pbk's?
  1993. //
  1994. pArgs->fHasValidTopLevelPBK = ValidTopLevelPBK(pArgs);
  1995. if (pArgs->fHasRefs)
  1996. {
  1997. pArgs->fHasValidReferencedPBKs = ValidReferencedPBKs(pArgs);
  1998. }
  1999. //
  2000. // Get idle settings for auto disconnect
  2001. // 1.0 profile has a BOOL flag "Idle", if FALSE, IdleTimeout is ignored
  2002. //
  2003. if (!pArgs->piniBothNonFav->GPPB(c_pszCmSection, c_pszCmEntryIdle, TRUE))
  2004. {
  2005. //
  2006. // If this is a 1.0 profile and Idle==0, set IdleTimeout to 0, so CMMOM works correctly
  2007. //
  2008. pArgs->dwIdleTimeout = 0; // never timeout
  2009. pArgs->piniProfile->WPPI(c_pszCmSection, c_pszCmEntryIdle, TRUE); // write back
  2010. pArgs->piniProfile->WPPI(c_pszCmSection, c_pszCmEntryIdleTimeout, 0); // write back
  2011. }
  2012. else
  2013. {
  2014. pArgs->dwIdleTimeout = (int) pArgs->piniBothNonFav->GPPI(c_pszCmSection,
  2015. c_pszCmEntryIdleTimeout,
  2016. DEFAULT_IDLETIMEOUT);
  2017. }
  2018. //
  2019. // get redial count
  2020. // 1.0 profile has a BOOL flag "Redial", if FALSE, RedialCount is ignored
  2021. //
  2022. if (!pArgs->piniBothNonFav->GPPB(c_pszCmSection, c_pszCmEntryRedial, TRUE))
  2023. {
  2024. //
  2025. // If this is a 1.0 profile and Redial==0, set RetryCount to 0
  2026. //
  2027. pArgs->nMaxRedials = 0;
  2028. pArgs->piniBothNonFav->WPPI(c_pszCmSection, c_pszCmEntryRedialCount, 0); // write back
  2029. }
  2030. else
  2031. {
  2032. pArgs->nMaxRedials = (int) pArgs->piniBothNonFav->GPPI(c_pszCmSection,
  2033. c_pszCmEntryRedialCount,
  2034. DEFAULT_MAX_REDIALS);
  2035. }
  2036. //
  2037. // Get the redial delay value
  2038. //
  2039. pArgs->nRedialDelay = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryRedialDelay,DEFAULT_REDIAL_DELAY);
  2040. //
  2041. // should we enable ISDN dial on demand?
  2042. //
  2043. pArgs->dwIsdnDialMode = pArgs->piniService->GPPI(c_pszCmSection,
  2044. c_pszCmEntryIsdnDialMode,
  2045. CM_ISDN_MODE_SINGLECHANNEL);
  2046. //
  2047. // Get the Tapi location from the registry
  2048. //
  2049. if (pArgs->fAccessPointsEnabled)
  2050. {
  2051. pArgs->tlsTapiLink.dwTapiLocationForAccessPoint = pArgs->piniProfile->GPPI(c_pszCmSection,
  2052. c_pszCmEntryTapiLocation);
  2053. }
  2054. CMTRACE(TEXT("End LoadProperties()"));
  2055. }
  2056. //+---------------------------------------------------------------------------
  2057. //
  2058. // Function: LoadIconsAndBitmaps
  2059. //
  2060. // Synopsis: This func loads icon and bitmap settings. It should be part
  2061. // of the main dlg init.
  2062. //
  2063. // Arguments: pArgs [the ptr to ArgsStruct]
  2064. // hwndDlg [the main dlg]
  2065. //
  2066. // Returns: NONE
  2067. //
  2068. // History: henryt Copied from LoadFromFile() 5/2/97
  2069. //
  2070. //----------------------------------------------------------------------------
  2071. void LoadIconsAndBitmaps(
  2072. ArgsStruct *pArgs,
  2073. HWND hwndDlg
  2074. )
  2075. {
  2076. LPTSTR pszTmp;
  2077. UINT nTmp;
  2078. // Load large icon name
  2079. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryBigIcon);
  2080. if (*pszTmp)
  2081. {
  2082. //
  2083. // Make sure we have a full path (if appropriate) and load big icon
  2084. //
  2085. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  2086. pArgs->hBigIcon = CmLoadIcon(g_hInst, pszFile);
  2087. CmFree(pszFile);
  2088. }
  2089. CmFree(pszTmp);
  2090. // Use default (EXE) large icon if no user icon found
  2091. if (!pArgs->hBigIcon)
  2092. {
  2093. pArgs->hBigIcon = CmLoadIcon(g_hInst, MAKEINTRESOURCE(IDI_APP));
  2094. }
  2095. SendMessageU(hwndDlg,WM_SETICON,ICON_BIG,(LPARAM) pArgs->hBigIcon);
  2096. // Load small icon name
  2097. pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntrySmallIcon);
  2098. if (*pszTmp)
  2099. {
  2100. //
  2101. // Make sure we have a full path (if appropriate) and load small icon
  2102. //
  2103. LPTSTR pszFile = CmConvertRelativePath(pArgs->piniService->GetFile(), pszTmp);
  2104. pArgs->hSmallIcon = CmLoadSmallIcon(g_hInst, pszFile);
  2105. CmFree(pszFile);
  2106. }
  2107. CmFree(pszTmp);
  2108. // Use default (EXE) small icon if no user icon found
  2109. if (!pArgs->hSmallIcon)
  2110. {
  2111. pArgs->hSmallIcon = CmLoadSmallIcon(g_hInst, MAKEINTRESOURCE(IDI_APP));
  2112. }
  2113. SendMessageU(hwndDlg,WM_SETICON,ICON_SMALL,(LPARAM) pArgs->hSmallIcon);
  2114. //
  2115. // this is where the Bitmap gets loaded in. Check to see first if we're doing
  2116. // the Future Splash thang. if so, no bitmap
  2117. //
  2118. // Note that we do not load FutureSplash if this is WinLogon. This is because
  2119. // Future Splash Animations can have imbedded actions and thus could be used
  2120. // to launch web pages, etc. from WinLogon as the system account. Definitely
  2121. // would be a security hole.
  2122. //
  2123. nTmp = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryAnimatedLogo);
  2124. if (!nTmp || IsLogonAsSystem())
  2125. {
  2126. //
  2127. // either there was no 'Animated Logo' entry, or it was 0, which means
  2128. // we go ahead and load the bitmap.
  2129. //
  2130. LoadLogoBitmap(pArgs, hwndDlg);
  2131. }
  2132. else
  2133. {
  2134. //
  2135. // if, for any reason, loading FS OC fails, go ahead and
  2136. // degrade and load the logo bitmap.
  2137. //
  2138. if (S_OK != LoadFutureSplash(pArgs, hwndDlg))
  2139. {
  2140. LoadLogoBitmap(pArgs, hwndDlg);
  2141. }
  2142. }
  2143. }
  2144. //+----------------------------------------------------------------------------
  2145. //
  2146. // Function: DoRasHangup
  2147. //
  2148. // Synopsis: Hangup the given RAS device handle
  2149. //
  2150. // Arguments: prlsRasLink - Ptr to RAS linkage struct
  2151. // hRasConnection - The RAS device to hangup
  2152. // hwndDlg - The main dlg to display "Disconnecting .. " msg
  2153. // Only used if fWaitForComplete is TRUE
  2154. // Optional, default = NULL
  2155. // fWaitForComplete - Whether to wait for Hangup to complete on 95
  2156. // If set to TRUE, will wait until hRasConnection
  2157. // is invalid. Optional, default = FALSE
  2158. // pfWaiting - Ptr to boolean value indicating our wait state
  2159. // and whether Timer and Ras messages should be
  2160. // ignored. Optional, default = NULL
  2161. //
  2162. // Returns: DWORD - ERROR_SUCCESS if success or error code
  2163. //
  2164. // Note: pArgs is removed so that the Disconnect path can use this function
  2165. // thus concentrating the timing mess in one place.
  2166. //
  2167. // History: fengsun Created Header 10/22/97
  2168. // fengsun Add fWaitForComplete 12/18/97
  2169. // nickball Removed pArgs dependency
  2170. //
  2171. //+----------------------------------------------------------------------------
  2172. DWORD DoRasHangup(RasLinkageStruct *prlsRasLink,
  2173. HRASCONN hRasConnection,
  2174. HWND hwndDlg,
  2175. BOOL fWaitForComplete,
  2176. LPBOOL pfWaiting)
  2177. {
  2178. DWORD dwRes = ERROR_SUCCESS;
  2179. MYDBGASSERT(hRasConnection != NULL);
  2180. MYDBGASSERT(prlsRasLink->pfnHangUp != NULL);
  2181. //
  2182. // Do we need to check the return value
  2183. // now that RAS is going to disconnect modem too?
  2184. //
  2185. dwRes = prlsRasLink->pfnHangUp(hRasConnection);
  2186. CMTRACE1(TEXT("DoRasHangup() RasHangup() returned %u."), dwRes);
  2187. // On Win32 RasHangup returns immediately, so loop until we
  2188. // are certain that the disconnected state had been reached
  2189. if ((dwRes == ERROR_SUCCESS) && prlsRasLink->pfnGetConnectStatus)
  2190. {
  2191. RASCONNSTATUS rcs;
  2192. CMTRACE(TEXT("DoRasHangup() Waiting for hangup to complete"));
  2193. //
  2194. // On 95 Wait for HANGUP_TIMEOUT seconds
  2195. // On NT wait until the connection is released
  2196. // This will cause this to loop till the connection status
  2197. // is RASCS_Disconnected
  2198. //
  2199. #define HANGUP_TIMEOUT 60 // timeout for 95 hangup
  2200. if (pfWaiting)
  2201. {
  2202. //
  2203. // Keep the message looping to avoid freezing CM
  2204. // But do not handle WM_TIMER and RAS msg
  2205. //
  2206. MYDBGASSERT(!*pfWaiting);
  2207. *pfWaiting = TRUE;
  2208. }
  2209. if (fWaitForComplete && hwndDlg)
  2210. {
  2211. //
  2212. // Display the disconnecting message, if we have to wait
  2213. //
  2214. LPTSTR pszTmp = CmLoadString(g_hInst,IDMSG_DISCONNECTING);
  2215. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTmp);
  2216. CmFree(pszTmp);
  2217. }
  2218. DWORD dwStartWaitTime = GetTickCount();
  2219. HCURSOR hWaitCursor = LoadCursorU(NULL,IDC_WAIT);
  2220. ZeroMemory(&rcs,sizeof(rcs));
  2221. rcs.dwSize = sizeof(rcs);
  2222. while ((dwRes = prlsRasLink->pfnGetConnectStatus(hRasConnection,&rcs)) == ERROR_SUCCESS)
  2223. {
  2224. //
  2225. // If it is NT, or do not need to wait for hangup to complete,
  2226. // RASCS_Disconnected state is considered hangup complete
  2227. //
  2228. if (rcs.rasconnstate == RASCS_Disconnected &&
  2229. (!fWaitForComplete || OS_NT))
  2230. {
  2231. break;
  2232. }
  2233. //
  2234. // We only have time out for 95/98
  2235. //
  2236. if (OS_W9X && (GetTickCount() - dwStartWaitTime >= HANGUP_TIMEOUT * 1000))
  2237. {
  2238. CMTRACE(TEXT("DoRasHangup() Wait timed out"));
  2239. break;
  2240. }
  2241. //
  2242. // Try to dispatch message, however, some time the wait cursor is
  2243. // changed back to arrow
  2244. //
  2245. MSG msg;
  2246. while (PeekMessageU(&msg, NULL, 0, 0, PM_REMOVE))
  2247. {
  2248. if (msg.message != WM_SETCURSOR)
  2249. {
  2250. TranslateMessage(&msg);
  2251. DispatchMessageU(&msg);
  2252. if (GetCursor() != hWaitCursor)
  2253. {
  2254. SetCursor(hWaitCursor);
  2255. }
  2256. }
  2257. }
  2258. Sleep(500);
  2259. }
  2260. if (dwRes == ERROR_INVALID_HANDLE)
  2261. {
  2262. dwRes = ERROR_SUCCESS;
  2263. }
  2264. else
  2265. {
  2266. CMTRACE1(TEXT("MyRasHangup() RasGetConnectStatus(), GLE=%u."), dwRes);
  2267. }
  2268. if (pfWaiting)
  2269. {
  2270. *pfWaiting = FALSE;
  2271. }
  2272. }
  2273. CMTRACE(TEXT("DoRasHangup() completed"));
  2274. return dwRes;
  2275. }
  2276. //+----------------------------------------------------------------------------
  2277. //
  2278. // Function: MyRasHangup
  2279. //
  2280. // Synopsis: Simple wrapper for DoRasHangup, that takes pArgs as a param.
  2281. //
  2282. // Arguments: pArgs - Ptr to global Args struct
  2283. // hRasConnection - The RAS device to hangup
  2284. // hwndDlg - The main dlg to display "Disconnecting .. " msg
  2285. // Only used if fWaitForComplete is TRUE
  2286. // Optional, default = NULL
  2287. // fWaitForComplete - Whether to wait for Hangup to complete on 95
  2288. // If set to TRUE, will wait until hRasConnection
  2289. // is invalid. Optional, default = FALSE
  2290. //
  2291. // Returns: DWORD - ERROR_SUCCESS if success or error code
  2292. //
  2293. // History: nickball Implemented as wrapper 2/11/98
  2294. //
  2295. //+----------------------------------------------------------------------------
  2296. DWORD MyRasHangup(ArgsStruct *pArgs,
  2297. HRASCONN hRasConnection,
  2298. HWND ,
  2299. BOOL fWaitForComplete)
  2300. {
  2301. CMTRACE(TEXT("MyRasHangup() calling DoRasHangup()"));
  2302. return DoRasHangup(&pArgs->rlsRasLink, hRasConnection, NULL, fWaitForComplete, &pArgs->fIgnoreTimerRasMsg);
  2303. }
  2304. //+----------------------------------------------------------------------------
  2305. //
  2306. // Function: HangupCM
  2307. //
  2308. // Synopsis: hangup both dial-up and tunnel connection, if exist
  2309. //
  2310. // Arguments: ArgsStruct *pArgs -
  2311. // hwndDlg the main dlg to display "Disconnecting .. " msg
  2312. // fWaitForComplete: Whether to wait for Hangup to complete on 95
  2313. // If set to TRUE, will wait until hRasConnection
  2314. // is invalid.
  2315. //
  2316. // Returns: DWORD -
  2317. //
  2318. // History: fengsun Created Header 10/22/97
  2319. // fengsun Add fWaitForComplete 12/18/97
  2320. //
  2321. //+----------------------------------------------------------------------------
  2322. DWORD HangupCM(ArgsStruct *pArgs,
  2323. HWND hwndDlg,
  2324. BOOL fWaitForComplete,
  2325. BOOL fUpdateTable)
  2326. {
  2327. MYDBGASSERT(pArgs);
  2328. MYDBGASSERT(hwndDlg);
  2329. CMTRACE(TEXT("HangupCM()"));
  2330. if (!pArgs)
  2331. {
  2332. CMTRACE(TEXT("HangupCM() invalid parameter."));
  2333. return (ERROR_INVALID_PARAMETER);
  2334. }
  2335. DWORD dwRes = ERROR_SUCCESS;
  2336. //
  2337. // If change password dialog is up tell it to go away
  2338. //
  2339. if (pArgs->hWndChangePassword)
  2340. {
  2341. CMTRACE(TEXT("HangupCM() Terminating ChangePassword dialog"));
  2342. PostMessage(pArgs->hWndChangePassword, WM_COMMAND, IDCANCEL, 0);
  2343. }
  2344. //
  2345. // If Callback number dialog is up tell it to go away too.
  2346. //
  2347. if (pArgs->hWndCallbackNumber)
  2348. {
  2349. CMTRACE(TEXT("HangupCM() Terminating CallbackNumber dialog"));
  2350. PostMessage(pArgs->hWndCallbackNumber, WM_COMMAND, IDCANCEL, 0);
  2351. }
  2352. //
  2353. // If Callback number dialog is up tell it to go away too.
  2354. //
  2355. if (pArgs->hWndRetryAuthentication)
  2356. {
  2357. CMTRACE(TEXT("HangupCM() Terminating RetryAuthentication dialog"));
  2358. PostMessage(pArgs->hWndRetryAuthentication, WM_COMMAND, IDCANCEL, 0);
  2359. }
  2360. //
  2361. // If table updates are desired set the entry to the disconnecting state
  2362. // Note: In the case of redial, we don't want to modify the table state
  2363. // even though we are hanging up because technically we are still connecting.
  2364. //
  2365. if (fUpdateTable)
  2366. {
  2367. UpdateTable(pArgs, CM_DISCONNECTING);
  2368. }
  2369. //
  2370. // Check the RasLink pointer and hang up the device, tunnel first
  2371. //
  2372. #ifdef DEBUG
  2373. if (!pArgs->rlsRasLink.pfnHangUp)
  2374. {
  2375. CMTRACE(TEXT("HangupCM() can't hang up."));
  2376. }
  2377. #endif
  2378. //
  2379. // Show wait cursor before hanging up
  2380. //
  2381. HCURSOR hPrev;
  2382. if (hwndDlg)
  2383. {
  2384. hPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  2385. ShowCursor(TRUE);
  2386. }
  2387. //
  2388. // The assumption is that we have been connected, why else would we call
  2389. // hangup. So release statistics handles, hooks, etc.
  2390. //
  2391. if (pArgs->pConnStatistics)
  2392. {
  2393. pArgs->pConnStatistics->Close();
  2394. }
  2395. //
  2396. // Hangup connections
  2397. //
  2398. if (pArgs->rlsRasLink.pfnHangUp && pArgs->hrcTunnelConn)
  2399. {
  2400. //
  2401. // first, hangup tunnel connection
  2402. //
  2403. CMTRACE(TEXT("HangupCM() calling MyRasHangup() for tunnel connection"));
  2404. dwRes = MyRasHangup(pArgs, pArgs->hrcTunnelConn, hwndDlg, fWaitForComplete);
  2405. #ifdef DEBUG
  2406. if (dwRes != ERROR_SUCCESS)
  2407. {
  2408. CMTRACE1(TEXT("MyRasHangup failed, GLE=%u."), GetLastError());
  2409. }
  2410. #endif
  2411. pArgs->hrcTunnelConn = NULL;
  2412. }
  2413. //
  2414. // If we have a valid link and handle, hangup the modem
  2415. //
  2416. if (pArgs->rlsRasLink.pfnHangUp && pArgs->hrcRasConn)
  2417. {
  2418. CMTRACE(TEXT("HangupCM() calling MyRasHangup() for dial-up connection"));
  2419. dwRes = MyRasHangup(pArgs, pArgs->hrcRasConn);
  2420. }
  2421. // Restore cursor
  2422. if (hwndDlg)
  2423. {
  2424. ShowCursor(FALSE);
  2425. SetCursor(hPrev);
  2426. }
  2427. pArgs->hrcRasConn = NULL;
  2428. //
  2429. // Update the Connection table if asked
  2430. //
  2431. if (fUpdateTable)
  2432. {
  2433. UpdateTable(pArgs, CM_DISCONNECTED);
  2434. }
  2435. return (dwRes);
  2436. }
  2437. //+----------------------------------------------------------------------------
  2438. //
  2439. // Function: CleanupZapThread
  2440. //
  2441. // Synopsis: Simple helper to deal with signaling an event to stop Zap thread
  2442. // and waiting for the thread to terminate.
  2443. //
  2444. // Arguments: HANDLE hEvent - The event handle
  2445. // HANDLE hThread - Handle to the Zap thread.
  2446. //
  2447. // Returns: static void - Nothing
  2448. //
  2449. // History: nickball Created 3/5/98
  2450. //
  2451. //+----------------------------------------------------------------------------
  2452. static void CleanupZapThread(HANDLE hEvent,
  2453. HANDLE hThread)
  2454. {
  2455. MYDBGASSERT(hEvent);
  2456. MYDBGASSERT(hThread);
  2457. //
  2458. // If we have an event, then it is assumed that have a Zap thread running
  2459. //
  2460. if (hEvent)
  2461. {
  2462. //
  2463. // Signal termination to notify thread that we are done
  2464. //
  2465. BOOL bRes = SetEvent(hEvent);
  2466. #ifdef DEBUG
  2467. if (!bRes)
  2468. {
  2469. CMTRACE1(TEXT("CleanupZapThread() SetEvent() failed, GLE=%u."), GetLastError());
  2470. }
  2471. #endif
  2472. if (hThread)
  2473. {
  2474. //
  2475. // Wait for thread to terminate, but pump messages in the mean time
  2476. //
  2477. BOOL bDone = FALSE;
  2478. DWORD dwWaitCode;
  2479. while (FALSE == bDone)
  2480. {
  2481. dwWaitCode = MsgWaitForMultipleObjects(1, &hThread, FALSE, MAX_OBJECT_WAIT, QS_ALLINPUT);
  2482. switch(dwWaitCode)
  2483. {
  2484. //
  2485. // Thread has terminated, or time is up, we're done here
  2486. //
  2487. case -1:
  2488. CMTRACE1(TEXT("CleanupZapThread() MsgWaitForMultipleObjects returned an error GLE=%u."),
  2489. GetLastError());
  2490. case WAIT_TIMEOUT:
  2491. case WAIT_OBJECT_0:
  2492. bDone = TRUE;
  2493. break;
  2494. //
  2495. // If there is a message in the queue, process it
  2496. //
  2497. case WAIT_OBJECT_0+1:
  2498. {
  2499. MSG msg;
  2500. while (PeekMessageU(&msg, 0, 0, 0, PM_REMOVE))
  2501. {
  2502. TranslateMessage(&msg);
  2503. DispatchMessageU(&msg);
  2504. }
  2505. break;
  2506. }
  2507. //
  2508. // Unexpected, report, but continue
  2509. //
  2510. default:
  2511. MYDBGASSERT(FALSE);
  2512. }
  2513. }
  2514. //
  2515. // We are done with the thread, close the handle
  2516. //
  2517. bRes = CloseHandle(hThread);
  2518. #ifdef DEBUG
  2519. if (!bRes)
  2520. {
  2521. CMTRACE1(TEXT("CleanupZapThread() CloseHandle(hThread) failed, GLE=%u."), GetLastError());
  2522. }
  2523. #endif
  2524. }
  2525. //
  2526. // Close our event handle
  2527. //
  2528. bRes = CloseHandle(hEvent);
  2529. #ifdef DEBUG
  2530. if (!bRes)
  2531. {
  2532. CMTRACE1(TEXT("CleanupZapThread() CloseHandle(hEvent) failed, GLE=%u."), GetLastError());
  2533. }
  2534. #endif
  2535. }
  2536. }
  2537. //+----------------------------------------------------------------------------
  2538. //
  2539. // Function: OnConnectedCM
  2540. //
  2541. // Synopsis: Process WM_CONNECTED_CM which indicates that we are connected and
  2542. // connect processing such as connect actions can begin
  2543. //
  2544. // Arguments: HWND hwndDlg - HWND of main dialog
  2545. // ArgsStruct *pArgs - Ptr to global Args struct
  2546. //
  2547. // Returns: Nothing
  2548. //
  2549. // History: nickball Created 03/05/98
  2550. //
  2551. //+----------------------------------------------------------------------------
  2552. void OnConnectedCM(HWND hwndDlg, ArgsStruct *pArgs)
  2553. {
  2554. HANDLE hEvent = NULL;
  2555. HANDLE hThread = NULL;
  2556. CActionList ConnectActList;
  2557. CActionList AutoActList;
  2558. //
  2559. // Check to see if we are in a valid state to connect. if not just abort.
  2560. //
  2561. MYDBGASSERT(pArgs);
  2562. if (pArgs->hrcRasConn == NULL && pArgs->hrcTunnelConn == NULL)
  2563. {
  2564. CMTRACE(TEXT("Bogus OnConnectCM msg received"));
  2565. goto OnConnectedCMExit;
  2566. }
  2567. //
  2568. // Set state to online
  2569. //
  2570. if (IsDialingTunnel(pArgs))
  2571. {
  2572. //
  2573. // This is a patch, it is only a patch - #187202
  2574. // UI should not be tied to RASENTRY type, but it is for now so we
  2575. // have to make sure that it is set back to RASET_Internet once we
  2576. // have our tunnel connection connected.
  2577. //
  2578. if (OS_NT5)
  2579. {
  2580. LPRASENTRY pRasEntry = MyRGEP(pArgs->pszRasPbk, pArgs->szServiceName, &pArgs->rlsRasLink);
  2581. CMASSERTMSG(pRasEntry, TEXT("OnConnectedCM() - MyRGEP() failed."));
  2582. //
  2583. // Set the type back and save the RASENTRY
  2584. //
  2585. if (pRasEntry)
  2586. {
  2587. ((LPRASENTRY_V500)pRasEntry)->dwType = RASET_Internet;
  2588. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  2589. {
  2590. DWORD dwTmp = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  2591. pArgs->szServiceName,
  2592. pRasEntry,
  2593. pRasEntry->dwSize,
  2594. NULL,
  2595. 0);
  2596. CMTRACE2(TEXT("OnConnectedCM() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  2597. MYDBGSTR(pArgs->szServiceName), dwTmp);
  2598. CMASSERTMSG(dwTmp == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  2599. }
  2600. }
  2601. CmFree(pRasEntry);
  2602. }
  2603. pArgs->psState = PS_TunnelOnline;
  2604. }
  2605. else
  2606. {
  2607. //
  2608. // Set dial index back to primary number
  2609. //
  2610. pArgs->nDialIdx = 0;
  2611. pArgs->psState = PS_Online;
  2612. //
  2613. // Make sure to update the stored username back to just the Username as RAS has saved the exact username
  2614. // that we dialed with including realm info.
  2615. //
  2616. if (OS_NT5)
  2617. {
  2618. if (!pArgs->fUseTunneling || pArgs->fUseSameUserName)
  2619. {
  2620. if (0 != lstrcmpi(pArgs->szUserName, pArgs->pRasDialParams->szUserName))
  2621. {
  2622. MYVERIFY(SaveUserInfo(pArgs, UD_ID_USERNAME, pArgs->szUserName));
  2623. }
  2624. }
  2625. else
  2626. {
  2627. if (0 != lstrcmpi(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName))
  2628. {
  2629. MYVERIFY(SaveUserInfo(pArgs, UD_ID_INET_USERNAME, pArgs->szInetUserName));
  2630. }
  2631. }
  2632. }
  2633. }
  2634. pArgs->dwStateStartTime = GetTickCount();
  2635. // pszMsg = GetDurMsg(g_hInst,pArgs->dwStateStartTime); // connect duration
  2636. pArgs->nLastSecondsDisplay = (UINT) -1;
  2637. //
  2638. // added by byao: for PPTP connection
  2639. //
  2640. if (pArgs->fUseTunneling && pArgs->psState == PS_Online)
  2641. {
  2642. //
  2643. // Now do the second dial: PPTP dialup
  2644. //
  2645. pArgs->psState = PS_TunnelDialing;
  2646. pArgs->dwStateStartTime = GetTickCount();
  2647. pArgs->nLastSecondsDisplay = (UINT) -1;
  2648. DWORD dwRes = DoTunnelDial(hwndDlg, pArgs);
  2649. if (ERROR_SUCCESS != dwRes)
  2650. {
  2651. HangupCM(pArgs, hwndDlg);
  2652. UpdateError(pArgs, dwRes);
  2653. SetLastError(dwRes);
  2654. }
  2655. goto OnConnectedCMExit;
  2656. }
  2657. //
  2658. // If this W95, then we need to Zap the RNA "Connected To" dialog
  2659. //
  2660. if (OS_W95)
  2661. {
  2662. // LPTSTR pszTmp = GetEntryName(pArgs, pArgs->pszRasPbk, pArgs->piniService);
  2663. LPTSTR pszTmp = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  2664. //
  2665. // Create an event for signalling Zap thread to snuff itself out
  2666. //
  2667. hEvent = CreateEventU(NULL, TRUE, FALSE, NULL);
  2668. if (hEvent)
  2669. {
  2670. hThread = ZapRNAConnectedTo(pszTmp, hEvent);
  2671. }
  2672. #ifdef DEBUG
  2673. if (!hEvent)
  2674. {
  2675. CMTRACE1(TEXT("OnConnectedCM() CreateEvent failed, GLE=%u."), GetLastError());
  2676. }
  2677. #endif
  2678. CmFree(pszTmp);
  2679. }
  2680. pArgs->Log.Log(CONNECT_EVENT);
  2681. //
  2682. // If connection actions are enabled, update the list and run it
  2683. //
  2684. CMTRACE(TEXT("Connect Actions enabled: processsing Run List"));
  2685. ConnectActList.Append(pArgs->piniService, c_pszCmSectionOnConnect);
  2686. if (!ConnectActList.RunAccordType(hwndDlg, pArgs))
  2687. {
  2688. //
  2689. // Connect action failed
  2690. // Run disconnect action
  2691. //
  2692. TCHAR szTmp[MAX_PATH];
  2693. MYVERIFY(GetModuleFileNameU(g_hInst, szTmp, MAX_PATH));
  2694. pArgs->Log.Log(DISCONNECT_EVENT, szTmp);
  2695. //
  2696. // Do not let disconnect action description overwrite the failure message
  2697. // Save the status pane text and restore it after disconnect actions
  2698. // 162942: Connect Action failed message is not displayed
  2699. //
  2700. TCHAR szFailedMsg[256] = TEXT("");
  2701. GetWindowTextU(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY),
  2702. szFailedMsg, sizeof(szFailedMsg)/sizeof(szFailedMsg[0]));
  2703. CActionList DisconnectActList;
  2704. DisconnectActList.Append(pArgs->piniService, c_pszCmSectionOnDisconnect);
  2705. DisconnectActList.RunAccordType(hwndDlg, pArgs, FALSE); // fStatusMsgOnFailure = FALSE
  2706. HangupCM(pArgs, hwndDlg);
  2707. //
  2708. // Restore the connect action failure message
  2709. //
  2710. if (szFailedMsg[0] != TEXT('\0'))
  2711. {
  2712. SetWindowTextU(GetDlgItem(hwndDlg, IDC_MAIN_STATUS_DISPLAY),szFailedMsg);
  2713. }
  2714. pArgs->dwExitCode = ERROR_CANCELLED;
  2715. SetInteractive(hwndDlg,pArgs);
  2716. goto OnConnectedCMExit;
  2717. }
  2718. //
  2719. // Always run AutoApps if there are any. Used to only do this in the
  2720. // non-autodial case, which was un-intuitive to our admin users.
  2721. //
  2722. AutoActList.Append(pArgs->piniService, c_pszCmSectionOnIntConnect);
  2723. AutoActList.RunAutoApp(hwndDlg, pArgs);
  2724. //
  2725. // Connect to the connection monitor
  2726. //
  2727. if (SUCCEEDED(UpdateTable(pArgs, CM_CONNECTED)))
  2728. {
  2729. if (SUCCEEDED(ConnectMonitor(pArgs)))
  2730. {
  2731. EndMainDialog(hwndDlg, pArgs, 0); // TRUE);
  2732. //
  2733. // SUCCESS We're fully connected, update error code
  2734. // as it may contain an interim value such as a
  2735. // failed primary number dial.
  2736. //
  2737. pArgs->dwExitCode = ERROR_SUCCESS;
  2738. }
  2739. else
  2740. {
  2741. HangupCM(pArgs, hwndDlg);
  2742. AppendStatusPane(hwndDlg,IDMSG_CMMON_LAUNCH_FAIL);
  2743. SetInteractive(hwndDlg,pArgs);
  2744. goto OnConnectedCMExit;
  2745. }
  2746. }
  2747. //
  2748. // Update changed password if needed
  2749. //
  2750. if (pArgs->fChangedPassword && pArgs->fRememberMainPassword)
  2751. {
  2752. //
  2753. // Note: fRememberMainPassword should never be set in the
  2754. // WinLogon case. Complain if we have WinLogon specific data.
  2755. //
  2756. MYDBGASSERT(!pArgs->lpRasNoUser);
  2757. MYDBGASSERT(!pArgs->lpEapLogonInfo);
  2758. //
  2759. // If the password has changed, then update storage
  2760. //
  2761. CmDecodePassword(pArgs->szPassword); // convert to plain text 1st
  2762. SaveUserInfo(pArgs, UD_ID_PASSWORD, (PVOID)pArgs->szPassword);
  2763. if (pArgs->fUseSameUserName)
  2764. {
  2765. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pArgs->szPassword);
  2766. }
  2767. CmEncodePassword(pArgs->szPassword); // restore internal encoding
  2768. if (pArgs->fUseSameUserName)
  2769. {
  2770. //
  2771. // Just in case somebody doesn't reload it. Note: Encoded above.
  2772. //
  2773. lstrcpyU(pArgs->szInetPassword, pArgs->szPassword);
  2774. }
  2775. pArgs->fChangedPassword = FALSE;
  2776. }
  2777. OnConnectedCMExit:
  2778. if (hEvent)
  2779. {
  2780. MYDBGASSERT(OS_W9X);
  2781. CleanupZapThread(hEvent, hThread);
  2782. }
  2783. return;
  2784. }
  2785. //+----------------------------------------------------------------------------
  2786. //
  2787. // Function: SetTcpWindowSizeOnWin2k
  2788. //
  2789. // Synopsis: This function is basically a wrapper to load the RasSetEntryTcpWindowSize
  2790. // API (which was QFE-ed and shipped in SP3 for Win2k) and call it.
  2791. // It should fail gracefully if the API is not present.
  2792. //
  2793. // Arguments: HMODULE hInstRas - module handle for Rasapi32.dll
  2794. // LPCTSTR pszConnectoid - name of the connectoid to set the window size for
  2795. // LPCTSTR pszPhonebook - phonebook that the connectoid lives in
  2796. // DWORD dwTcpWindowSize - size to set, note that calling with 0
  2797. // sets it to the system default
  2798. //
  2799. // Returns: DWORD - win32 error code or ERROR_SUCCESS if successful
  2800. //
  2801. // History: quintinb Created 02/14/2001
  2802. //
  2803. //+----------------------------------------------------------------------------
  2804. DWORD SetTcpWindowSizeOnWin2k(HMODULE hInstRas, LPCTSTR pszConnectoid, LPCTSTR pszPhonebook, DWORD dwTcpWindowSize)
  2805. {
  2806. //
  2807. // Check inputs, note that pszPhonebook could be NULL
  2808. //
  2809. if ((NULL == hInstRas) || (NULL == pszConnectoid) || (TEXT('\0') == pszConnectoid[0]))
  2810. {
  2811. CMASSERTMSG(FALSE, TEXT("SetTcpWindowSizeOnWin2k -- Invalid arguments passed."));
  2812. return ERROR_BAD_ARGUMENTS;
  2813. }
  2814. //
  2815. // Check to make sure we are only calling this on Win2k
  2816. //
  2817. if ((FALSE == OS_NT5) || OS_NT51)
  2818. {
  2819. CMASSERTMSG(FALSE, TEXT("SetTcpWindowSizeOnWin2k -- This function should only be called on Win2k."));
  2820. return -1;
  2821. }
  2822. //
  2823. // See if we can load the new RAS function to set the Window size
  2824. //
  2825. LPCSTR c_pszDwSetEntryPropertiesPrivate = "DwSetEntryPropertiesPrivate";
  2826. typedef DWORD (WINAPI *pfnDwSetEntryPropertiesPrivateSpec)(IN LPCWSTR, IN LPCWSTR, IN DWORD, IN PVOID);
  2827. DWORD dwReturn;
  2828. pfnDwSetEntryPropertiesPrivateSpec pfnDwSetEntryPropertiesPrivate = (pfnDwSetEntryPropertiesPrivateSpec)GetProcAddress(hInstRas, c_pszDwSetEntryPropertiesPrivate);
  2829. if (pfnDwSetEntryPropertiesPrivate)
  2830. {
  2831. RASENTRY_EX_0 PrivateRasEntryExtension;
  2832. PrivateRasEntryExtension.dwTcpWindowSize = dwTcpWindowSize;
  2833. dwReturn = (pfnDwSetEntryPropertiesPrivate)(pszConnectoid, pszPhonebook, 0, &PrivateRasEntryExtension); // 0 = struct version num
  2834. MYDBGASSERT(ERROR_SUCCESS == dwReturn);
  2835. }
  2836. else
  2837. {
  2838. dwReturn = GetLastError();
  2839. }
  2840. return dwReturn;
  2841. }
  2842. //+----------------------------------------------------------------------------
  2843. //
  2844. // Function: DoRasDial
  2845. //
  2846. // Synopsis: Call RasDial to dial the PPP connection
  2847. //
  2848. // Arguments: HWND hwndDlg - Main signon window
  2849. // ArgsStruct *pArgs -
  2850. // DWORD dwEntry - The index in pArgs->aDialInfo
  2851. //
  2852. // Returns: DWORD -
  2853. // ERROR_SUCCESS if success
  2854. // ERROR_NOT_ENOUGH_MEMORY
  2855. // E_UNEXPECTED, unexpected error, such as tunnel address not found
  2856. // Otherwise, RAS error
  2857. //
  2858. // History: fengsun Created Header 3/6/98
  2859. //
  2860. //+----------------------------------------------------------------------------
  2861. DWORD DoRasDial(HWND hwndDlg,
  2862. ArgsStruct *pArgs,
  2863. DWORD dwEntry)
  2864. {
  2865. LPRASENTRY preRasEntry = NULL;
  2866. LPRASSUBENTRY rgRasSubEntry = NULL;
  2867. LPRASEAPUSERIDENTITY lpRasEapUserIdentity = NULL;
  2868. DWORD dwSubEntryCount;
  2869. LPTSTR pszUsername;
  2870. LPTSTR pszPassword;
  2871. LPTSTR pszDomain = NULL;
  2872. LPTSTR pszRasPbk;
  2873. LPTSTR pszTmp;
  2874. CIni *piniService = NULL;
  2875. DWORD dwRes = ERROR_SUCCESS; // the return value of this function
  2876. DWORD dwTmp;
  2877. LPBYTE pbEapAuthData = NULL; // Ptr to Eap Data
  2878. DWORD dwEapAuthDataSize = 0; // The size of the EAP blob if any
  2879. MYDBGASSERT(pArgs->hrcRasConn == NULL);
  2880. MYDBGASSERT(!pArgs->IsDirectConnect());
  2881. pArgs->hrcRasConn = NULL;
  2882. if (!pArgs->aDialInfo[dwEntry].szDialablePhoneNumber[0])
  2883. {
  2884. CMASSERTMSG(FALSE, TEXT("DoRasDial() szDialablePhoneNumber[0] is empty."));
  2885. return ERROR_BAD_PHONE_NUMBER;
  2886. }
  2887. //
  2888. // set pArgs->fUseTunneling accordingly every time DoRasDial() is called
  2889. // since we can switch from phonenumber0 to phonenumber1 and vice versa.
  2890. //
  2891. pArgs->fUseTunneling = UseTunneling(pArgs, dwEntry);
  2892. //
  2893. // we need to work with the correct service file(the top-level service
  2894. // or a referenced service).
  2895. //
  2896. //
  2897. if (!(piniService = GetAppropriateIniService(pArgs, dwEntry)))
  2898. {
  2899. return ERROR_NOT_ENOUGH_MEMORY;
  2900. }
  2901. //
  2902. // If it's NT and we're tunneling, we create the connectoid in a hidden ras pbk, not the
  2903. // rasphone.pbk in the system.
  2904. //
  2905. if (OS_NT && pArgs->fUseTunneling)
  2906. {
  2907. if (!pArgs->pszRasHiddenPbk)
  2908. {
  2909. pArgs->pszRasHiddenPbk = CreateRasPrivatePbk(pArgs);
  2910. }
  2911. pszRasPbk = pArgs->pszRasHiddenPbk;
  2912. }
  2913. else
  2914. {
  2915. pszRasPbk = pArgs->pszRasPbk;
  2916. }
  2917. //
  2918. // Setup dial params
  2919. //
  2920. if (!pArgs->pRasDialParams)
  2921. {
  2922. pArgs->pRasDialParams = AllocateAndInitRasDialParams();
  2923. if (!pArgs->pRasDialParams)
  2924. {
  2925. CMTRACE(TEXT("DoRasDial: failed to alloc a ras dial params"));
  2926. return ERROR_NOT_ENOUGH_MEMORY;
  2927. }
  2928. }
  2929. else
  2930. {
  2931. InitRasDialParams(pArgs->pRasDialParams);
  2932. }
  2933. //
  2934. // Get the connectoid name.
  2935. //
  2936. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  2937. if (!pszConnectoid)
  2938. {
  2939. return ERROR_NOT_ENOUGH_MEMORY;
  2940. }
  2941. lstrcpynU(pArgs->pRasDialParams->szEntryName, pszConnectoid, sizeof(pArgs->pRasDialParams->szEntryName)/sizeof(TCHAR));
  2942. CmFree(pszConnectoid);
  2943. //
  2944. // Generate the default connectoid
  2945. //
  2946. preRasEntry = CreateRASEntryStruct(pArgs,
  2947. pArgs->aDialInfo[dwEntry].szDUN,
  2948. piniService,
  2949. FALSE,
  2950. pszRasPbk,
  2951. &pbEapAuthData,
  2952. &dwEapAuthDataSize);
  2953. if (!preRasEntry)
  2954. {
  2955. dwRes = GetLastError();
  2956. goto exit;
  2957. }
  2958. //
  2959. // Force update of the phone number to make sure that we pick up any manual
  2960. // changes in country, etc.
  2961. //
  2962. CopyPhone(pArgs, preRasEntry, dwEntry);
  2963. //
  2964. // Handle NT specifics for Idle Disconnect and IDSN
  2965. //
  2966. if (OS_NT || OS_MIL)
  2967. {
  2968. //
  2969. // set NT idle disconnect
  2970. //
  2971. if (OS_NT)
  2972. {
  2973. SetNtIdleDisconnectInRasEntry(pArgs, preRasEntry);
  2974. }
  2975. else
  2976. {
  2977. MYVERIFY(DisableSystemIdleDisconnect(preRasEntry));
  2978. }
  2979. //
  2980. // if we're using isdn and we want to dial all channels/on demand,
  2981. // set isdn dial mode
  2982. //
  2983. if (pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL &&
  2984. !lstrcmpiU(pArgs->szDeviceType, RASDT_Isdn))
  2985. {
  2986. MYVERIFY(SetIsdnDualChannelEntries(pArgs,
  2987. preRasEntry,
  2988. &rgRasSubEntry,
  2989. &dwSubEntryCount));
  2990. }
  2991. else
  2992. {
  2993. //
  2994. // Delete any additional sub entries since we only need one
  2995. //
  2996. if (pArgs->rlsRasLink.pfnDeleteSubEntry) // available on NT5 & Millennium currently
  2997. {
  2998. DWORD dwSubEntryIndex = (OS_MIL ? 1 : 2); // NT & Millennium dual-channel differences
  2999. DWORD dwReturn = pArgs->rlsRasLink.pfnDeleteSubEntry(pszRasPbk,
  3000. pArgs->pRasDialParams->szEntryName,
  3001. dwSubEntryIndex);
  3002. CMTRACE1(TEXT("DoRasDial -- Called RasDeleteSubEntry to delete a second sub entry if it exists, dwReturn=%d"), dwReturn);
  3003. }
  3004. }
  3005. }
  3006. else if (OS_W95)
  3007. {
  3008. //
  3009. // fix another Win95 RAS bug -- byao, 8/16/97
  3010. // The Before and After terminal window options will be switched each
  3011. // time you call RasSetEntryProperties
  3012. // This is fixed in Memphis, so it's only in Win95 Golden and OSR2
  3013. //
  3014. BOOL fTerminalAfterDial, fTerminalBeforeDial;
  3015. fTerminalBeforeDial = (BOOL) (preRasEntry->dwfOptions & RASEO_TerminalBeforeDial);
  3016. fTerminalAfterDial = (BOOL) (preRasEntry->dwfOptions & RASEO_TerminalAfterDial);
  3017. //
  3018. // switch them
  3019. //
  3020. if (fTerminalBeforeDial)
  3021. {
  3022. preRasEntry->dwfOptions |= RASEO_TerminalAfterDial;
  3023. }
  3024. else
  3025. {
  3026. preRasEntry->dwfOptions &= ~RASEO_TerminalAfterDial;
  3027. }
  3028. if (fTerminalAfterDial)
  3029. {
  3030. preRasEntry->dwfOptions |= RASEO_TerminalBeforeDial;
  3031. }
  3032. else
  3033. {
  3034. preRasEntry->dwfOptions &= ~RASEO_TerminalBeforeDial;
  3035. }
  3036. }
  3037. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  3038. {
  3039. #ifdef DEBUG
  3040. LPRASENTRY_V500 lpRasEntry50;
  3041. if (OS_NT5)
  3042. {
  3043. lpRasEntry50 = (LPRASENTRY_V500) preRasEntry;
  3044. }
  3045. #endif
  3046. //
  3047. // use 1 on Millennium to signify that we want to use the modem cpl settings
  3048. // for the modem speaker such instead of the cached copy that DUN keeps.
  3049. // Note we only do this for a dialup connection and not a tunnel since there
  3050. // is no modem speaker to worry about. See Millennium bug 127371.
  3051. //
  3052. LPBYTE lpDeviceInfo = OS_MIL ? (LPBYTE)1 : NULL;
  3053. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryProperties(pszRasPbk,
  3054. pArgs->pRasDialParams->szEntryName,
  3055. preRasEntry,
  3056. preRasEntry->dwSize,
  3057. lpDeviceInfo,
  3058. 0);
  3059. CMTRACE2(TEXT("DoRasDial() RasSetEntryProperties(*pszPhoneBook=%s) returns %u."),
  3060. MYDBGSTR(pArgs->pRasDialParams->szEntryName), dwResDbg);
  3061. CMASSERTMSG(dwResDbg == ERROR_SUCCESS, TEXT("RasSetEntryProperties failed"));
  3062. //
  3063. // set the subentries for isdn dual channel/dial on demand
  3064. //
  3065. if (pArgs->dwIsdnDialMode != CM_ISDN_MODE_SINGLECHANNEL &&
  3066. rgRasSubEntry &&
  3067. pArgs->rlsRasLink.pfnSetSubEntryProperties)
  3068. {
  3069. UINT i;
  3070. for (i=0; i< dwSubEntryCount; i++)
  3071. {
  3072. #ifdef DEBUG
  3073. dwResDbg =
  3074. #endif
  3075. pArgs->rlsRasLink.pfnSetSubEntryProperties(pszRasPbk,
  3076. pArgs->pRasDialParams->szEntryName,
  3077. i+1,
  3078. &rgRasSubEntry[i],
  3079. rgRasSubEntry[i].dwSize,
  3080. NULL,
  3081. 0);
  3082. CMTRACE2(TEXT("DoRasDial: RasSetSubEntryProps(index=%u) returned %u"), i+1, dwResDbg);
  3083. CMASSERTMSG(!dwResDbg, TEXT("RasSetSubEntryProperties failed"));
  3084. }
  3085. CmFree(rgRasSubEntry);
  3086. }
  3087. }
  3088. //
  3089. // Set the TCP Window size -- the NTT DoCoMo fix for Win2k. The Win2k version of this fix
  3090. // must be written through a private RAS API that must be called after the phonebook entry
  3091. // exists ie. after we call RasSetEntryProperties ... otherwise it won't work on the first
  3092. // dial.
  3093. //
  3094. if (OS_NT5 && !OS_NT51)
  3095. {
  3096. //
  3097. // Figure out the DUN setting name to use and then build up TCP/IP&DunName.
  3098. //
  3099. LPTSTR pszDunSetting = GetDunSettingName(pArgs, dwEntry, FALSE);
  3100. LPTSTR pszSection = CmStrCpyAlloc(c_pszCmSectionDunTcpIp);
  3101. pszSection = CmStrCatAlloc(&pszSection, TEXT("&"));
  3102. if (pszDunSetting && pszSection)
  3103. {
  3104. pszSection = CmStrCatAlloc(&pszSection, pszDunSetting);
  3105. if (pszSection)
  3106. {
  3107. DWORD dwTcpWindowSize = piniService->GPPI(pszSection, c_pszCmEntryDunTcpIpTcpWindowSize, 0);
  3108. (void)SetTcpWindowSizeOnWin2k(pArgs->rlsRasLink.hInstRas, pArgs->szServiceName, pszRasPbk, dwTcpWindowSize);
  3109. }
  3110. else
  3111. {
  3112. CMASSERTMSG(FALSE, TEXT("DoRasDial -- unable to allocate section name for setting TcpWindowSize"));
  3113. }
  3114. }
  3115. else
  3116. {
  3117. CMASSERTMSG(FALSE, TEXT("DoRasDial -- unable to allocate section name or dun setting name for setting TcpWindowSize"));
  3118. }
  3119. CmFree (pszDunSetting);
  3120. CmFree (pszSection);
  3121. }
  3122. //
  3123. // On NT5, check for EAP configuration and update the connectoid accordingly.
  3124. //
  3125. if (OS_NT5)
  3126. {
  3127. if (pbEapAuthData && dwEapAuthDataSize && pArgs->rlsRasLink.pfnSetCustomAuthData)
  3128. {
  3129. dwTmp = pArgs->rlsRasLink.pfnSetCustomAuthData(pszRasPbk,
  3130. pArgs->pRasDialParams->szEntryName,
  3131. pbEapAuthData,
  3132. dwEapAuthDataSize);
  3133. CMTRACE1(TEXT("DoRasDial() - SetCustomAuthData returns %u"), dwTmp);
  3134. if (ERROR_SUCCESS != dwTmp)
  3135. {
  3136. dwRes = dwTmp;
  3137. goto exit;
  3138. }
  3139. }
  3140. }
  3141. //
  3142. // Prepare Phone Number
  3143. //
  3144. lstrcpynU(pArgs->pRasDialParams->szPhoneNumber,
  3145. pArgs->aDialInfo[dwEntry].szDialablePhoneNumber,
  3146. sizeof(pArgs->pRasDialParams->szPhoneNumber)/sizeof(TCHAR));
  3147. //
  3148. // Prepare user info
  3149. //
  3150. // #165775 - RADIUS/CHAP authentication requires that we omit the
  3151. // user specified domain from the dial params and pre-pend it to
  3152. // the user name instead when doing same-name logon. - nickball
  3153. //
  3154. if (!pArgs->fUseTunneling || pArgs->fUseSameUserName)
  3155. {
  3156. pszUsername = pArgs->szUserName;
  3157. pszPassword = pArgs->szPassword;
  3158. pszDomain = pArgs->szDomain;
  3159. }
  3160. else
  3161. {
  3162. //
  3163. // if there's no username or password, we need to ask the user for it.
  3164. //
  3165. if (!*pArgs->szInetUserName &&
  3166. !pArgs->fHideInetUsername &&
  3167. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUserNameOptional) ||
  3168. !*pArgs->szInetPassword &&
  3169. !pArgs->fHideInetPassword &&
  3170. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional))
  3171. {
  3172. //
  3173. // We need to collect data from user, determine the dlg template ID
  3174. //
  3175. UINT uiTemplateID = IDD_INTERNET_SIGNIN;
  3176. if (pArgs->fHideInetUsername)
  3177. {
  3178. uiTemplateID = IDD_INTERNET_SIGNIN_NO_UID;
  3179. }
  3180. else if (pArgs->fHideInetPassword)
  3181. {
  3182. uiTemplateID = IDD_INTERNET_SIGNIN_NO_PWD;
  3183. }
  3184. //
  3185. // Now load the dialog
  3186. //
  3187. CInetSignInDlg SignInDlg(pArgs);
  3188. if (IDCANCEL == SignInDlg.DoDialogBox(g_hInst, uiTemplateID, hwndDlg))
  3189. {
  3190. dwRes = ERROR_CANCELLED;
  3191. goto exit;
  3192. }
  3193. }
  3194. pszUsername = pArgs->szInetUserName;
  3195. pszPassword = pArgs->szInetPassword;
  3196. }
  3197. //
  3198. // Apply suffix, prefix, to username as necessary
  3199. //
  3200. pszTmp = ApplyPrefixSuffixToBufferAlloc(pArgs, piniService, pszUsername);
  3201. MYDBGASSERT(pszTmp);
  3202. if (pszTmp)
  3203. {
  3204. //
  3205. // Apply domain to username as necessary. Note: Reassigns pszUsername
  3206. //
  3207. pszUsername = ApplyDomainPrependToBufferAlloc(pArgs, piniService, pszTmp, (pArgs->aDialInfo[dwEntry].szDUN));
  3208. MYDBGASSERT(pszUsername);
  3209. if (pszUsername)
  3210. {
  3211. lstrcpynU(pArgs->pRasDialParams->szUserName, pszUsername, sizeof(pArgs->pRasDialParams->szUserName)/sizeof(TCHAR));
  3212. }
  3213. CmFree(pszUsername);
  3214. CmFree(pszTmp);
  3215. }
  3216. pszUsername = NULL;
  3217. pszTmp = NULL;
  3218. //
  3219. // Update RasDialPArams with domain info if we have any
  3220. //
  3221. if (pszDomain)
  3222. {
  3223. lstrcpyU(pArgs->pRasDialParams->szDomain, pszDomain);
  3224. }
  3225. //
  3226. // Prepare the password
  3227. //
  3228. CmDecodePassword(pszPassword);
  3229. //
  3230. // Convert password: all upper case, all lower case, or no conversion
  3231. //
  3232. ApplyPasswordHandlingToBuffer(pArgs, pszPassword);
  3233. //
  3234. // Encode password to minimize plain text exposure time, especially crucial
  3235. // when running things like connect actions, which can both take time and
  3236. // potentially crash.
  3237. //
  3238. CmEncodePassword(pszPassword);
  3239. if (pArgs->rlsRasLink.pfnDial)
  3240. {
  3241. LPTSTR pszDunSetting = GetDunSettingName(pArgs, dwEntry, FALSE);
  3242. LPTSTR pszPhoneBook = GetCMSforPhoneBook(pArgs, dwEntry);
  3243. pArgs->Log.Log(PREDIAL_EVENT,
  3244. pArgs->pRasDialParams->szUserName,
  3245. pArgs->pRasDialParams->szDomain,
  3246. SAFE_LOG_ARG(pszPhoneBook),
  3247. SAFE_LOG_ARG(pszDunSetting),
  3248. pArgs->tlsTapiLink.szDeviceName,
  3249. pArgs->aDialInfo[dwEntry].szDialablePhoneNumber);
  3250. CmFree(pszDunSetting);
  3251. CmFree(pszPhoneBook);
  3252. //
  3253. // Run pre-dial connect action before calling RasDial
  3254. //
  3255. CActionList PreDialActList;
  3256. PreDialActList.Append(pArgs->piniService, c_pszCmSectionPreDial);
  3257. if (!PreDialActList.RunAccordType(hwndDlg, pArgs))
  3258. {
  3259. //
  3260. // Some pre-tunnel connect action failed
  3261. //
  3262. dwRes = ERROR_INVALID_DLL; // Only used for failed CA
  3263. }
  3264. else
  3265. {
  3266. //
  3267. // Set state and tick counters.
  3268. //
  3269. pArgs->psState = PS_Dialing;
  3270. pArgs->dwStateStartTime = GetTickCount();
  3271. pArgs->nLastSecondsDisplay = (UINT) -1;
  3272. //
  3273. // Record the initial Dial-Up Adapter Statistic info
  3274. // open the registry key for the perfmon data
  3275. //
  3276. if (pArgs->pConnStatistics)
  3277. {
  3278. pArgs->pConnStatistics->InitStatistics();
  3279. }
  3280. if (OS_NT)
  3281. {
  3282. BOOL fUsePausedStates = TRUE;
  3283. BOOL fUseCustomScripting = !!(preRasEntry->dwfOptions & RASEO_CustomScript); // OS_NT51 (whistler+) only
  3284. if (OS_NT4)
  3285. {
  3286. //
  3287. // If a script is specified, then explcitly don't handle
  3288. // pause states. This is because we can't handle the script
  3289. // pause state. On W2K, RAS is smart enough not to send us
  3290. // the scripting pause state because we have the terminal
  3291. // option turned off.
  3292. //
  3293. if (preRasEntry->szScript[0] != TEXT('\0'))
  3294. {
  3295. fUsePausedStates = FALSE;
  3296. }
  3297. }
  3298. dwRes = SetRasDialExtensions(pArgs, fUsePausedStates, fUseCustomScripting);
  3299. if (dwRes != ERROR_SUCCESS)
  3300. {
  3301. goto exit;
  3302. }
  3303. //
  3304. // On NT5, we may be getting credentials via EAP
  3305. //
  3306. if (OS_NT5 && ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey)
  3307. {
  3308. //
  3309. // We're using EAP, get credentials from EAP through RAS
  3310. //
  3311. dwRes = GetEapUserId(pArgs,
  3312. hwndDlg,
  3313. pszRasPbk,
  3314. pbEapAuthData,
  3315. dwEapAuthDataSize,
  3316. ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey,
  3317. &lpRasEapUserIdentity);
  3318. if (ERROR_SUCCESS != dwRes)
  3319. {
  3320. goto exit;
  3321. }
  3322. }
  3323. }
  3324. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szUserName is %s"), pArgs->pRasDialParams->szUserName);
  3325. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szDomain is %s"), pArgs->pRasDialParams->szDomain);
  3326. CMTRACE1(TEXT("DoRasDial: pArgs->pRasDialParams->szPhoneNumber is %s"), pArgs->pRasDialParams->szPhoneNumber);
  3327. //
  3328. // Decode the password, and fill dial params, then re-encode both the pArgs
  3329. // version of the password and the dial params copy.
  3330. //
  3331. CmDecodePassword(pszPassword);
  3332. lstrcpynU(pArgs->pRasDialParams->szPassword, pszPassword, sizeof(pArgs->pRasDialParams->szPassword)/sizeof(TCHAR));
  3333. //
  3334. // Write the RasDialParams if necessary.
  3335. // We must keep this, even though RasSetEntryDialParams() is expensive. Inverse uses the
  3336. // information stored in the DialParams structure. However, since this can cause problems
  3337. // with EAP (overwriting the saved PIN for instance) we will make the storing of the
  3338. // credential information configurable by a CMS flag. Specifically, the WriteRasDialParams
  3339. // flag in the [Connection Manager] section. If the flag is 1, then we will write the
  3340. // RasDialParams and otherwise we won't. Note that the flag defaults to 0.
  3341. // Please see bug 399976 for reference.
  3342. //
  3343. if (piniService->GPPI(c_pszCmSection, c_pszCmEntryWriteDialParams))
  3344. {
  3345. //
  3346. // Note that since we throw the connectoid away if we are on NT and
  3347. // doing a double dial, there is no point in making an expensive set
  3348. // dial params call on it.
  3349. //
  3350. if ((!pArgs->fUseTunneling && pArgs->fRememberMainPassword) ||
  3351. (pArgs->fUseTunneling && pArgs->fRememberInetPassword && OS_W9X))
  3352. {
  3353. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryDialParams(pszRasPbk, pArgs->pRasDialParams, FALSE);
  3354. CMTRACE1(TEXT("DoRasDial() SetEntryDialParams returns %u."), dwResDbg);
  3355. }
  3356. else
  3357. {
  3358. //
  3359. // Forget the password, note that the DialParams contain the password but we set the
  3360. // fRemovePassword flag to TRUE so the password will be removed anyway.
  3361. //
  3362. DWORD dwResDbg = pArgs->rlsRasLink.pfnSetEntryDialParams(pszRasPbk,
  3363. pArgs->pRasDialParams, TRUE);
  3364. CMTRACE1(TEXT("DoRasDial() SetEntryDialParams returns %u."), dwResDbg);
  3365. }
  3366. }
  3367. //
  3368. // Do the dial (PPP)
  3369. //
  3370. if (OS_NT)
  3371. {
  3372. lstrcpyU(pArgs->pRasDialParams->szCallbackNumber, TEXT("*"));
  3373. }
  3374. //
  3375. // check to ensure we're not already in a Cancel operation
  3376. //
  3377. LONG lInConnectOrCancel = InterlockedExchange(&(pArgs->lInConnectOrCancel), IN_CONNECT_OR_CANCEL);
  3378. CMASSERTMSG(((NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel) || (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)),
  3379. TEXT("DoRasDial - synch variable has unexpected value!"));
  3380. if (NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel)
  3381. {
  3382. dwRes = pArgs->rlsRasLink.pfnDial(pArgs->pRasDialExtensions,
  3383. pszRasPbk,
  3384. pArgs->pRasDialParams,
  3385. GetRasCallBackType(),
  3386. GetRasCallBack(pArgs),
  3387. &pArgs->hrcRasConn);
  3388. }
  3389. else
  3390. {
  3391. // this is a rare stress case - deliberately did not set dwRes to error value.
  3392. CMTRACE(TEXT("DoRasDial() did not dial, we are already in a Cancel operation"));
  3393. }
  3394. (void) InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  3395. CmEncodePassword(pArgs->pRasDialParams->szPassword);
  3396. CmEncodePassword(pszPassword);
  3397. CMTRACE1(TEXT("DoRasDial() RasDial() returns %u."), dwRes);
  3398. if (dwRes != ERROR_SUCCESS)
  3399. {
  3400. pArgs->hrcRasConn = NULL;
  3401. goto exit;
  3402. }
  3403. }
  3404. }
  3405. exit:
  3406. if (lpRasEapUserIdentity)
  3407. {
  3408. MYDBGASSERT(OS_NT5); // NO EAP down-level
  3409. //
  3410. // A RasEapUserIdentity struct was allocated, free it via the
  3411. // appropriate free mechanism. In the WinLogon case we will always
  3412. // perform the allocation, otherwise we have to go through RAS API.
  3413. //
  3414. if (pArgs->lpEapLogonInfo)
  3415. {
  3416. CmFree(lpRasEapUserIdentity);
  3417. }
  3418. else
  3419. {
  3420. if (pArgs->rlsRasLink.pfnFreeEapUserIdentity)
  3421. {
  3422. pArgs->rlsRasLink.pfnFreeEapUserIdentity(lpRasEapUserIdentity);
  3423. }
  3424. }
  3425. }
  3426. CmFree(pbEapAuthData);
  3427. CmFree(preRasEntry);
  3428. delete piniService;
  3429. return dwRes;
  3430. }
  3431. //+---------------------------------------------------------------------------
  3432. //
  3433. // Function: DoTunnelDial
  3434. //
  3435. // Synopsis: call RasDial to dial up to the tunnel server
  3436. //
  3437. // Arguments: hwndDlg [dlg window handle]
  3438. // pargs pointer to ArgValue structure
  3439. //
  3440. // Returns: DWORD -
  3441. // ERROR_SUCCESS if success
  3442. // ERROR_NOT_ENOUGH_MEMORY
  3443. // E_UNEXPECTED, unexpected error, such as phone entry not found
  3444. // Otherwise, RAS error
  3445. //
  3446. // History: byao Created 3/1/97
  3447. // fengsun change return type to DWORD 3/6/98
  3448. //
  3449. //----------------------------------------------------------------------------
  3450. DWORD DoTunnelDial(IN HWND hwndDlg, IN ArgsStruct *pArgs)
  3451. {
  3452. LPRASENTRY preRasEntry = NULL;
  3453. LPRASEAPUSERIDENTITY lpRasEapUserIdentity = NULL;
  3454. LPTSTR pszVpnSetting = NULL;
  3455. LPBYTE pbEapAuthData = NULL; // Ptr to Eap Data
  3456. DWORD dwEapAuthDataSize = 0; // The size of the EAP blob if any
  3457. LPTSTR pszPassword = pArgs->szPassword;
  3458. DWORD dwRes = (DWORD)E_UNEXPECTED;
  3459. DWORD dwTmp;
  3460. MYDBGASSERT(pArgs->hrcTunnelConn == NULL);
  3461. pArgs->hrcTunnelConn = NULL;
  3462. //
  3463. // What's the tunnel end point? Do this now so that the UI can be updated
  3464. // properly if lana wait or pre-tunnel actions are time consuming.
  3465. //
  3466. LPTSTR pszTunnelIP = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  3467. if (pszTunnelIP)
  3468. {
  3469. if (lstrlenU(pszTunnelIP) > RAS_MaxPhoneNumber)
  3470. {
  3471. pszTunnelIP[0] = TEXT('\0');
  3472. }
  3473. pArgs->SetPrimaryTunnel(pszTunnelIP);
  3474. CmFree(pszTunnelIP);
  3475. }
  3476. //
  3477. // See if tunnel server was specified
  3478. //
  3479. if (!(pArgs->GetTunnelAddress()[0]))
  3480. {
  3481. CMASSERTMSG(FALSE, TEXT("DoTunnelDial() TunnelAddress is invalid."));
  3482. return ERROR_BAD_ADDRESS_SPECIFIED;
  3483. }
  3484. CMTRACE1(TEXT("DoTunnelDial() - TunnelAddress is %s"), pArgs->GetTunnelAddress());
  3485. //
  3486. // Caution should be used when changing this if statement. We want this to happen both for direct connect
  3487. // and for double dial connections. You can still get into the LANA situation with two CM
  3488. // connections dialed independently (one to the internet and the other a tunnel), doing the lana
  3489. // wait for direct connections prevents the lana registration problem from occuring in this situation.
  3490. // Note that the Lana wait isn't necessary on Win98 SE or Win98 Millennium because the DUN bug
  3491. // is fixed. Thus we have reversed the default and will only do the LANA wait if the reg key exists
  3492. // and specifies that the wait should be performed.
  3493. //
  3494. if (OS_W9X)
  3495. {
  3496. //
  3497. // Sets us up to wait for Vredir to register LANA for connection to internet
  3498. // Note: Returns FALSE if the user hits cancel while we are waiting. In this
  3499. // event, we should not continue the tunnel dial.
  3500. //
  3501. if (FALSE == LanaWait(pArgs, hwndDlg))
  3502. {
  3503. return ERROR_SUCCESS;
  3504. }
  3505. }
  3506. LPTSTR pszDunSetting = GetDunSettingName(pArgs, -1, TRUE);
  3507. pArgs->Log.Log(PRETUNNEL_EVENT,
  3508. pArgs->szUserName,
  3509. pArgs->szDomain,
  3510. SAFE_LOG_ARG(pszDunSetting),
  3511. pArgs->tlsTapiLink.szDeviceName,
  3512. pArgs->GetTunnelAddress());
  3513. CmFree(pszDunSetting);
  3514. CActionList PreTunnelActList;
  3515. if (PreTunnelActList.Append(pArgs->piniService, c_pszCmSectionPreTunnel))
  3516. {
  3517. CMTRACE(TEXT("DoTunnelDial() - Running Pre-Tunnel actions"));
  3518. if (!PreTunnelActList.RunAccordType(hwndDlg, pArgs))
  3519. {
  3520. //
  3521. // Some pre-tunnel connect action failed
  3522. //
  3523. dwRes = ERROR_INVALID_DLL; // Only used for failed CA
  3524. goto exit;
  3525. }
  3526. //
  3527. // Now that pre-tunnel actions have run, what's the tunnel end point?
  3528. // We perform this read again here in the event that the pre-tunnel
  3529. // action modified the tunnel address. Note: This is an exception to
  3530. // the rule that the .CMS should not be modified on the client side,
  3531. // especially by 3rd parties.
  3532. //
  3533. // REVIEW: It probably isn't necessary to re-read this with the new VPN tab. However, some people might still
  3534. // be using the connect action solution that ITG gave out and we want to be careful not to break them if
  3535. // we haven't already. Thus we will continue to re-read this for Whistler but we should remove it afterwards.
  3536. // quintinb 11-01-00
  3537. pszTunnelIP = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  3538. if (pszTunnelIP)
  3539. {
  3540. if (lstrlenU(pszTunnelIP) > RAS_MaxPhoneNumber)
  3541. {
  3542. pszTunnelIP[0] = TEXT('\0');
  3543. }
  3544. pArgs->SetPrimaryTunnel(pszTunnelIP);
  3545. CmFree(pszTunnelIP);
  3546. }
  3547. //
  3548. // See if tunnel server was specified
  3549. //
  3550. if (!(pArgs->GetTunnelAddress()[0]))
  3551. {
  3552. CMASSERTMSG(FALSE, TEXT("DoTunnelDial() TunnelAddress is invalid."));
  3553. dwRes = (DWORD)ERROR_BAD_ADDRESS_SPECIFIED;
  3554. goto exit;
  3555. }
  3556. CMTRACE1(TEXT("DoTunnelDial() - TunnelAddress is %s"), pArgs->GetTunnelAddress());
  3557. }
  3558. //
  3559. // Setup dial params
  3560. //
  3561. if (!pArgs->pRasDialParams)
  3562. {
  3563. pArgs->pRasDialParams = AllocateAndInitRasDialParams();
  3564. if (!pArgs->pRasDialParams)
  3565. {
  3566. CMTRACE(TEXT("DoTunnelDial: failed to alloc a ras dial params"));
  3567. dwRes = ERROR_NOT_ENOUGH_MEMORY;
  3568. goto exit;
  3569. }
  3570. }
  3571. else
  3572. {
  3573. InitRasDialParams(pArgs->pRasDialParams);
  3574. }
  3575. //
  3576. // Get the connectoid name
  3577. //
  3578. LPTSTR pszConnectoid;
  3579. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, TRUE);
  3580. if (!pszConnectoid)
  3581. {
  3582. dwRes = (DWORD)ERROR_NOT_ENOUGH_MEMORY;
  3583. goto exit;
  3584. }
  3585. lstrcpyU(pArgs->pRasDialParams->szEntryName, pszConnectoid);
  3586. CmFree(pszConnectoid);
  3587. //
  3588. // We'll create the RAS connectoid if the RAS connectoid doesn't exist.
  3589. // NOTE: Tunnel settings should always be taken from the top-level CMS.
  3590. // so use it when creating the connectoid.
  3591. //
  3592. pszVpnSetting = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelDun, TEXT(""));
  3593. preRasEntry = CreateRASEntryStruct(pArgs,
  3594. (pszVpnSetting ? pszVpnSetting : TEXT("")),
  3595. pArgs->piniService,
  3596. TRUE,
  3597. pArgs->pszRasPbk,
  3598. &pbEapAuthData,
  3599. &dwEapAuthDataSize);
  3600. CmFree(pszVpnSetting);
  3601. if (!preRasEntry)
  3602. {
  3603. dwRes = GetLastError();
  3604. goto exit;
  3605. }
  3606. //
  3607. // If this is Millennium we need to disable Idle disconnect so that it doesn't
  3608. // fight with ours.
  3609. //
  3610. if (OS_MIL)
  3611. {
  3612. MYVERIFY(DisableSystemIdleDisconnect(preRasEntry));
  3613. }
  3614. //
  3615. // We need to delete a second sub entry if it exists. See 406637 for details
  3616. //
  3617. if (pArgs->rlsRasLink.pfnDeleteSubEntry) // available on NT5 & Millennium currently
  3618. {
  3619. DWORD dwReturn = pArgs->rlsRasLink.pfnDeleteSubEntry(pArgs->pszRasPbk,
  3620. pArgs->pRasDialParams->szEntryName,
  3621. (OS_MIL ? 1 : 2)); // see comment in DoRasDial
  3622. CMTRACE1(TEXT("DoTunnelDial -- Called RasDeleteSubEntry to delete a second sub entry if it exists, dwReturn=%d"), dwReturn);
  3623. }
  3624. //
  3625. // On NT5, we have to set the connection type to VPN instead of Internet
  3626. //
  3627. if (OS_NT5)
  3628. {
  3629. MYDBGASSERT(preRasEntry->dwSize >= sizeof(RASENTRY_V500));
  3630. ((LPRASENTRY_V500)preRasEntry)->dwType = RASET_Vpn;
  3631. ((LPRASENTRY_V500)preRasEntry)->szDeviceName[0] = TEXT('\0'); // let RAS pickup the tunnel device
  3632. }
  3633. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  3634. {
  3635. #ifdef DEBUG
  3636. LPRASENTRY_V500 lpRasEntry50;
  3637. if (OS_NT5)
  3638. {
  3639. lpRasEntry50 = (LPRASENTRY_V500) preRasEntry;
  3640. }
  3641. #endif
  3642. dwRes = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  3643. pArgs->pRasDialParams->szEntryName,
  3644. preRasEntry,
  3645. preRasEntry->dwSize,
  3646. NULL,
  3647. 0);
  3648. CMTRACE2(TEXT("DoTunnelDial() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  3649. MYDBGSTR(pArgs->pRasDialParams->szEntryName,), dwRes);
  3650. CMASSERTMSG(dwRes == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  3651. }
  3652. //
  3653. // Set the TCP Window size -- the NTT DoCoMo fix for Win2k. The Win2k version of this fix
  3654. // must be written through a private RAS API that must be called after the phonebook entry
  3655. // exists ie. after we call RasSetEntryProperties ... otherwise it won't work on the first
  3656. // dial.
  3657. //
  3658. if (OS_NT5 && !OS_NT51)
  3659. {
  3660. //
  3661. // Figure out the DUN setting name to use and then build up TCP/IP&DunName.
  3662. //
  3663. LPTSTR pszDunSetting = GetDunSettingName(pArgs, -1, TRUE);
  3664. LPTSTR pszSection = CmStrCpyAlloc(c_pszCmSectionDunTcpIp);
  3665. pszSection = CmStrCatAlloc(&pszSection, TEXT("&"));
  3666. if (pszDunSetting && pszSection)
  3667. {
  3668. pszSection = CmStrCatAlloc(&pszSection, pszDunSetting);
  3669. if (pszSection)
  3670. {
  3671. DWORD dwTcpWindowSize = pArgs->piniService->GPPI(pszSection, c_pszCmEntryDunTcpIpTcpWindowSize, 0);
  3672. (void)SetTcpWindowSizeOnWin2k(pArgs->rlsRasLink.hInstRas, pArgs->szServiceName, pArgs->pszRasPbk, dwTcpWindowSize);
  3673. }
  3674. else
  3675. {
  3676. CMASSERTMSG(FALSE, TEXT("DoTunnelDial -- unable to allocate section name for setting TcpWindowSize"));
  3677. }
  3678. }
  3679. else
  3680. {
  3681. CMASSERTMSG(FALSE, TEXT("DoTunnelDial -- unable to allocate section name or dun setting name for setting TcpWindowSize"));
  3682. }
  3683. CmFree (pszDunSetting);
  3684. CmFree (pszSection);
  3685. }
  3686. //
  3687. // On NT5, check for EAP configuration and update the connectoid accordingly.
  3688. //
  3689. if (OS_NT5)
  3690. {
  3691. if (pbEapAuthData && dwEapAuthDataSize && pArgs->rlsRasLink.pfnSetCustomAuthData)
  3692. {
  3693. dwTmp = pArgs->rlsRasLink.pfnSetCustomAuthData(pArgs->pszRasPbk,
  3694. pArgs->pRasDialParams->szEntryName,
  3695. pbEapAuthData,
  3696. dwEapAuthDataSize);
  3697. if (ERROR_SUCCESS != dwTmp)
  3698. {
  3699. CMTRACE(TEXT("DoTunnelDial() - SetCustomAuthData failed"));
  3700. dwRes = dwTmp;
  3701. goto exit;
  3702. }
  3703. }
  3704. }
  3705. //
  3706. // Phone Number for PPTP is the DNS name of IP addr of PPTP server
  3707. //
  3708. lstrcpynU(pArgs->pRasDialParams->szPhoneNumber,pArgs->GetTunnelAddress(), sizeof(pArgs->pRasDialParams->szPhoneNumber));
  3709. //
  3710. // Prepare User Name and Domain
  3711. //
  3712. lstrcpyU(pArgs->pRasDialParams->szUserName, pArgs->szUserName);
  3713. lstrcpyU(pArgs->pRasDialParams->szDomain, pArgs->szDomain);
  3714. //
  3715. // Prepare the password
  3716. //
  3717. CmDecodePassword(pszPassword);
  3718. //
  3719. // Convert password: all upper case, all lower case, or no conversion
  3720. //
  3721. ApplyPasswordHandlingToBuffer(pArgs, pszPassword);
  3722. //
  3723. // Re-encode password while we take care of other business.
  3724. //
  3725. CmEncodePassword(pszPassword);
  3726. if (pArgs->rlsRasLink.pfnDial)
  3727. {
  3728. if (pArgs->IsDirectConnect())
  3729. {
  3730. //
  3731. // Record the initial Dial-Up Adapter Statistic info.
  3732. //
  3733. if (pArgs->pConnStatistics)
  3734. {
  3735. pArgs->pConnStatistics->InitStatistics();
  3736. }
  3737. }
  3738. if (OS_NT)
  3739. {
  3740. MYDBGASSERT(TEXT('\0') == preRasEntry->szScript[0]); // we should never have a script on a tunnel connection
  3741. dwRes = SetRasDialExtensions(pArgs, TRUE, FALSE); // TRUE == fUsePausedStates, FALSE == fEnableCustomScripting
  3742. if (dwRes != ERROR_SUCCESS)
  3743. {
  3744. goto exit;
  3745. }
  3746. //
  3747. // On NT5, we may be getting credentials via EAP
  3748. //
  3749. if (OS_NT5 && ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey)
  3750. {
  3751. //
  3752. // We're using EAP, get credentials from EAP through RAS
  3753. //
  3754. dwRes = GetEapUserId(pArgs,
  3755. hwndDlg,
  3756. pArgs->pszRasPbk,
  3757. pbEapAuthData,
  3758. dwEapAuthDataSize,
  3759. ((LPRASENTRY_V500)preRasEntry)->dwCustomAuthKey,
  3760. &lpRasEapUserIdentity);
  3761. if (ERROR_SUCCESS != dwRes)
  3762. {
  3763. goto exit;
  3764. }
  3765. }
  3766. }
  3767. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szUserName is %s"), pArgs->pRasDialParams->szUserName);
  3768. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szDomain is %s"), pArgs->pRasDialParams->szDomain);
  3769. CMTRACE1(TEXT("DoTunnelDial: pArgs->pRasDialParams->szPhoneNumber is %s"), pArgs->pRasDialParams->szPhoneNumber);
  3770. //
  3771. // Decode the password before dialing, then re-encode along
  3772. // with the dial params, which we persist in memory for use
  3773. // in pause states, etc.
  3774. //
  3775. CmDecodePassword(pszPassword);
  3776. lstrcpyU(pArgs->pRasDialParams->szPassword, pArgs->szPassword);
  3777. //
  3778. // Do the dial (PPTP or L2TP)
  3779. //
  3780. dwRes = pArgs->rlsRasLink.pfnDial(pArgs->pRasDialExtensions,
  3781. pArgs->pszRasPbk,
  3782. pArgs->pRasDialParams,
  3783. GetRasCallBackType(),
  3784. GetRasCallBack(pArgs),
  3785. &pArgs->hrcTunnelConn);
  3786. CmEncodePassword(pszPassword);
  3787. CmEncodePassword(pArgs->pRasDialParams->szPassword);
  3788. CMTRACE1(TEXT("DoTunnelDial() RasDial() returns %u."), dwRes);
  3789. //
  3790. // NT5 - Reset the connection type so that it will display properly in
  3791. // the Connections Folder. This is a temporary solution to #187202
  3792. //
  3793. if (OS_NT5)
  3794. {
  3795. MYDBGASSERT(preRasEntry->dwSize >= sizeof(RASENTRY_V500));
  3796. ((LPRASENTRY_V500)preRasEntry)->dwType = RASET_Internet;
  3797. if (pArgs->rlsRasLink.pfnSetEntryProperties)
  3798. {
  3799. dwTmp = pArgs->rlsRasLink.pfnSetEntryProperties(pArgs->pszRasPbk,
  3800. pArgs->pRasDialParams->szEntryName,
  3801. preRasEntry,
  3802. preRasEntry->dwSize,
  3803. NULL,
  3804. 0);
  3805. CMTRACE2(TEXT("DoTunnelDial() RasSetEntryProperties(*lpszEntry=%s) returns %u."),
  3806. MYDBGSTR(pArgs->pRasDialParams->szEntryName,), dwTmp);
  3807. CMASSERTMSG(dwTmp == ERROR_SUCCESS, TEXT("RasSetEntryProperties for VPN failed"));
  3808. }
  3809. }
  3810. if (dwRes != ERROR_SUCCESS)
  3811. {
  3812. pArgs->hrcTunnelConn = NULL;
  3813. goto exit;
  3814. }
  3815. }
  3816. exit:
  3817. if (lpRasEapUserIdentity)
  3818. {
  3819. MYDBGASSERT(OS_NT5); // NO EAP down-level
  3820. //
  3821. // A RasEapUserIdentity struct was allocated, free it via the
  3822. // appropriate free mechanism. In the WinLogon case we will always
  3823. // perform the allocation, otherwise we have to go through RAS API.
  3824. //
  3825. if (pArgs->lpEapLogonInfo)
  3826. {
  3827. CmFree(lpRasEapUserIdentity);
  3828. }
  3829. else
  3830. {
  3831. if (pArgs->rlsRasLink.pfnFreeEapUserIdentity)
  3832. {
  3833. pArgs->rlsRasLink.pfnFreeEapUserIdentity(lpRasEapUserIdentity);
  3834. }
  3835. }
  3836. }
  3837. CmFree(preRasEntry); // Now we can release the RAS entry structure. #187202
  3838. CmFree(pbEapAuthData);
  3839. return dwRes;
  3840. }
  3841. //+---------------------------------------------------------------------------
  3842. //
  3843. // Function: CheckConnect
  3844. //
  3845. // Synopsis: double check to make sure all required fields are filled in, such
  3846. // as username, password, modem, etc.
  3847. //
  3848. // Arguments: hwndDlg [dlg window handle]
  3849. // pArgs pointer to ArgValue structure
  3850. // pnCtrlFocus: The button whose value is missing will have the focus
  3851. //
  3852. // Returns: True is ready to connect
  3853. //
  3854. // History: byao Modified 3/7/97
  3855. // nickball return BOOLEAN 9/9/98
  3856. //
  3857. //----------------------------------------------------------------------------
  3858. BOOL CheckConnect(HWND hwndDlg,
  3859. ArgsStruct *pArgs,
  3860. UINT *pnCtrlFocus,
  3861. BOOL fShowMsg)
  3862. {
  3863. LPTSTR pszTmp;
  3864. BOOL bEnable = TRUE;
  3865. int nId = 0;
  3866. UINT nCtrlFocus;
  3867. BOOL bSavedNoNotify = pArgs->fIgnoreChangeNotification;
  3868. pArgs->fIgnoreChangeNotification = TRUE;
  3869. MYDBGASSERT(*pArgs->piniProfile->GetFile());
  3870. //
  3871. // If tunneling, see if we have a tunneling device specified
  3872. //
  3873. if (bEnable && IsTunnelEnabled(pArgs))
  3874. {
  3875. lstrcpyU(pArgs->szTunnelDeviceType, RASDT_Vpn);
  3876. //
  3877. // Get Tunnel device name from profile
  3878. //
  3879. LPTSTR pszTunnelDevice = pArgs->piniProfile->GPPS(c_pszCmSection, c_pszCmEntryTunnelDevice);
  3880. if (pszTunnelDevice)
  3881. {
  3882. lstrcpyU(pArgs->szTunnelDeviceName, pszTunnelDevice);
  3883. CmFree(pszTunnelDevice);
  3884. }
  3885. //
  3886. // If we don't have a tunnel device, pick one
  3887. //
  3888. if (pArgs->szTunnelDeviceName[0] == TEXT('\0'))
  3889. {
  3890. //
  3891. // If we can't pick a tunnel device make sure tunneling is installed
  3892. //
  3893. if (!PickTunnelDevice(pArgs,pArgs->szTunnelDeviceType,pArgs->szTunnelDeviceName))
  3894. {
  3895. //
  3896. // Disable the connect/setting button during component checking and installation
  3897. //
  3898. EnableWindow(GetDlgItem(hwndDlg,IDOK),FALSE);
  3899. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),FALSE);
  3900. //
  3901. // Install the PPTP and pick tunnel device one more time
  3902. //
  3903. DWORD dwComponentsToCheck = CC_PPTP | CC_RNA | CC_RASRUNNING
  3904. | CC_TCPIP| CC_CHECK_BINDINGS;
  3905. if (TRUE == pArgs->bDoNotCheckBindings)
  3906. {
  3907. dwComponentsToCheck &= ~CC_CHECK_BINDINGS;
  3908. }
  3909. //
  3910. // PPTP is not installed.
  3911. // If not unattended, try to install the PPTP and call PickTunnel again
  3912. //
  3913. pArgs->dwExitCode = ERROR_PORT_NOT_AVAILABLE;
  3914. if (!(pArgs->dwFlags & FL_UNATTENDED))
  3915. {
  3916. pArgs->dwExitCode = CheckAndInstallComponents(dwComponentsToCheck,
  3917. hwndDlg, pArgs->szServiceName);
  3918. }
  3919. if (pArgs->dwExitCode != ERROR_SUCCESS ||
  3920. !PickTunnelDevice(pArgs,pArgs->szTunnelDeviceType,pArgs->szTunnelDeviceName))
  3921. {
  3922. bEnable = FALSE;
  3923. nId = GetPPTPMsgId();
  3924. nCtrlFocus = IDCANCEL;
  3925. }
  3926. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),TRUE);
  3927. }
  3928. pArgs->piniProfile->WPPS(c_pszCmSection, c_pszCmEntryTunnelDevice, pArgs->szTunnelDeviceName);
  3929. }
  3930. }
  3931. //
  3932. // Next, check the username.
  3933. //
  3934. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  3935. {
  3936. if (bEnable &&
  3937. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUserNameOptional))
  3938. {
  3939. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_USERNAME_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  3940. {
  3941. bEnable = FALSE;
  3942. nId = IDMSG_NEED_USERNAME;
  3943. nCtrlFocus = IDC_MAIN_USERNAME_EDIT;
  3944. }
  3945. }
  3946. }
  3947. //
  3948. // Next, check the password.
  3949. //
  3950. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  3951. {
  3952. if (!pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional))
  3953. {
  3954. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  3955. {
  3956. if (bEnable)
  3957. {
  3958. bEnable = FALSE;
  3959. nId = IDMSG_NEED_PASSWORD;
  3960. nCtrlFocus = IDC_MAIN_PASSWORD_EDIT;
  3961. }
  3962. //
  3963. // Disable "Remember password" check box
  3964. //
  3965. if (!pArgs->fHideRememberPassword)
  3966. {
  3967. pArgs->fRememberMainPassword = FALSE;
  3968. CheckDlgButton(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX, FALSE);
  3969. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  3970. if (pArgs->fGlobalCredentialsSupported)
  3971. {
  3972. //
  3973. // Also disable the option buttons
  3974. //
  3975. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  3976. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  3977. }
  3978. }
  3979. //
  3980. // disable the "dial automatically..." checkbox
  3981. //
  3982. if (!pArgs->fHideDialAutomatically)
  3983. {
  3984. pArgs->fDialAutomatically = FALSE;
  3985. pArgs->fRememberMainPassword = FALSE;
  3986. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, FALSE);
  3987. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  3988. }
  3989. }
  3990. else
  3991. {
  3992. //
  3993. // Enable the "Remember password" checkbox
  3994. //
  3995. if (!pArgs->fHideRememberPassword)
  3996. {
  3997. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), TRUE);
  3998. }
  3999. //
  4000. // Enable the "dial automatically..." checkbox
  4001. // if HideDialAutomatically is not set
  4002. // and if Password is not optional, Remember Password must be true
  4003. //
  4004. if ((!pArgs->fHideDialAutomatically) &&
  4005. (pArgs->fRememberMainPassword ||
  4006. pArgs->piniService->GPPB(c_pszCmSection,
  4007. c_pszCmEntryPwdOptional)))
  4008. {
  4009. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), TRUE);
  4010. }
  4011. }
  4012. }
  4013. }
  4014. //
  4015. // Next, check the domain.
  4016. //
  4017. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT))
  4018. {
  4019. if (bEnable &&
  4020. !pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryDomainOptional, TRUE))
  4021. {
  4022. if (!SendDlgItemMessageU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, WM_GETTEXTLENGTH, 0, (LPARAM)0))
  4023. {
  4024. bEnable = FALSE;
  4025. nId = IDMSG_NEED_DOMAIN;
  4026. nCtrlFocus = IDC_MAIN_DOMAIN_EDIT;
  4027. }
  4028. }
  4029. }
  4030. //
  4031. // Check whether primary phone number is empty -- a quick fix for bug 3123 -byao (4/11/97)
  4032. //
  4033. if (!pArgs->IsDirectConnect())
  4034. {
  4035. //
  4036. // Its not a direct connection, so we must check the phonenumber. If both
  4037. // szPhoneNumber and szCanonical are blank then we don't have a number.
  4038. //
  4039. if (bEnable &&
  4040. IsBlankString(pArgs->aDialInfo[0].szPhoneNumber) &&
  4041. IsBlankString(pArgs->aDialInfo[0].szCanonical))
  4042. {
  4043. bEnable = FALSE;
  4044. if (pArgs->fNeedConfigureTapi)
  4045. {
  4046. nId = IDMSG_NEED_CONFIGURE_TAPI;
  4047. }
  4048. else
  4049. {
  4050. //
  4051. // If direct and dial-up,the message should include the
  4052. // possibility of direct connection, otherwise use
  4053. // the standard need a phone number message
  4054. //
  4055. if (pArgs->IsBothConnTypeSupported())
  4056. {
  4057. nId = IDMSG_NEED_PHONE_DIRECT;
  4058. }
  4059. else
  4060. {
  4061. nId = IDMSG_NEED_PHONE_DIAL;
  4062. }
  4063. }
  4064. nCtrlFocus = IDC_MAIN_PROPERTIES_BUTTON;
  4065. }
  4066. }
  4067. //
  4068. // If tunneling is enabled and we are using a VPN file, make sure
  4069. // the user has selected a tunnel endpoint.
  4070. //
  4071. if (bEnable && IsTunnelEnabled(pArgs) && pArgs->pszVpnFile)
  4072. {
  4073. LPTSTR pszTunnelAddress = pArgs->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  4074. if ((NULL == pszTunnelAddress) || (TEXT('\0') == pszTunnelAddress[0]))
  4075. {
  4076. bEnable = FALSE;
  4077. nId = IDMSG_PICK_VPN_ADDRESS;
  4078. nCtrlFocus = IDC_MAIN_PROPERTIES_BUTTON;
  4079. }
  4080. CmFree(pszTunnelAddress);
  4081. }
  4082. if (bEnable)
  4083. {
  4084. //
  4085. // well, now we can set the focus to the 'connect' button
  4086. // Display ready to dial message
  4087. //
  4088. nCtrlFocus = IDOK;
  4089. nId = IDMSG_READY;
  4090. }
  4091. if (pnCtrlFocus)
  4092. {
  4093. *pnCtrlFocus = nCtrlFocus;
  4094. }
  4095. pszTmp = CmFmtMsg(g_hInst,nId);
  4096. if (NULL == pszTmp)
  4097. {
  4098. return FALSE;
  4099. }
  4100. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTmp);
  4101. //
  4102. // If necessary, throw a message box at the user.
  4103. //
  4104. if (!bEnable && fShowMsg)
  4105. {
  4106. MessageBoxEx(hwndDlg,
  4107. pszTmp,
  4108. pArgs->szServiceName,
  4109. MB_OK|MB_ICONINFORMATION,
  4110. LANG_USER_DEFAULT);
  4111. }
  4112. CmFree(pszTmp);
  4113. pArgs->fIgnoreChangeNotification = bSavedNoNotify;
  4114. //
  4115. // Something went wrong in the config. we need to recheck the
  4116. // configs next time we run CM.
  4117. //
  4118. if (GetPPTPMsgId() == nId) // not an assignment, stay left
  4119. {
  4120. ClearComponentsChecked();
  4121. }
  4122. return bEnable;
  4123. }
  4124. void MainSetDefaultButton(HWND hwndDlg,
  4125. UINT nCtrlId)
  4126. {
  4127. switch (nCtrlId)
  4128. {
  4129. case IDCANCEL:
  4130. case IDC_MAIN_PROPERTIES_BUTTON:
  4131. break;
  4132. default:
  4133. nCtrlId = IDOK;
  4134. break;
  4135. }
  4136. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)nCtrlId, 0);
  4137. }
  4138. //+---------------------------------------------------------------------------
  4139. //
  4140. // Function: SetMainDlgUserInfo
  4141. //
  4142. // Synopsis: Set user info in the main dlg.
  4143. //
  4144. // Arguments: pArgs - the ArgStruct *
  4145. // hwndDlg - the main dlg
  4146. //
  4147. // Returns: NONE
  4148. //
  4149. // History: henryt Created 5/5/97
  4150. //
  4151. //----------------------------------------------------------------------------
  4152. void SetMainDlgUserInfo(
  4153. ArgsStruct *pArgs,
  4154. HWND hwndDlg
  4155. )
  4156. {
  4157. HWND hwndTemp = NULL;
  4158. //
  4159. // Fill in the edit controls that exist
  4160. // Set the textbox modification flag. For Win9x compatibily issues we have to explicitly
  4161. // call SendMessageU instead of using the Edit_SetModify macro. The flag is used to see
  4162. // if the user has manually changed the contents of the edit boxes.
  4163. //
  4164. if (pArgs->fAccessPointsEnabled)
  4165. {
  4166. //
  4167. // This fuction populates the combo box passed to it with info from the reg
  4168. //
  4169. ShowAccessPointInfoFromReg(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  4170. }
  4171. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  4172. if (hwndTemp)
  4173. {
  4174. SetDlgItemTextU(hwndDlg, IDC_MAIN_USERNAME_EDIT, pArgs->szUserName);
  4175. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4176. }
  4177. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  4178. if (hwndTemp)
  4179. {
  4180. CmDecodePassword(pArgs->szPassword);
  4181. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, pArgs->szPassword);
  4182. CmEncodePassword(pArgs->szPassword);
  4183. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4184. }
  4185. hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT);
  4186. if (hwndTemp) // !pArgs->fHideDomain)
  4187. {
  4188. SetDlgItemTextU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, pArgs->szDomain);
  4189. SendMessageU(hwndTemp, EM_SETMODIFY, (WPARAM)FALSE, 0L);
  4190. }
  4191. }
  4192. //+---------------------------------------------------------------------------
  4193. //
  4194. // Function: OnResetPassword
  4195. //
  4196. // Synopsis: Handle reset password.
  4197. //
  4198. // Arguments: pArgs - the ArgStruct *
  4199. // hwndDlg - the main dlg
  4200. //
  4201. // Returns: BOOL -- TRUE if SUCCEEDED
  4202. //
  4203. // History: henryt Created 5/6/97
  4204. //
  4205. //----------------------------------------------------------------------------
  4206. BOOL OnResetPassword(HWND hwndDlg, ArgsStruct *pArgs)
  4207. {
  4208. LPTSTR pszArgs = NULL;
  4209. LPTSTR pszCmd = NULL;
  4210. BOOL bReturn = FALSE;
  4211. MYDBGASSERT(pArgs);
  4212. MYDBGASSERT(pArgs->pszResetPasswdExe);
  4213. //
  4214. // Get the latest password data from the edit control
  4215. // and obfuscate its contents so that connect actions
  4216. // can't retrieve it.
  4217. //
  4218. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  4219. ObfuscatePasswordEdit(pArgs);
  4220. if (pArgs && pArgs->pszResetPasswdExe)
  4221. {
  4222. if (CmParsePath(pArgs->pszResetPasswdExe, pArgs->piniService->GetFile(), &pszCmd, &pszArgs))
  4223. {
  4224. pArgs->Log.Log(PASSWORD_RESET_EVENT, pszCmd);
  4225. SHELLEXECUTEINFO ShellExInfo;
  4226. ZeroMemory(&ShellExInfo, sizeof(SHELLEXECUTEINFO));
  4227. //
  4228. // Fill in the Execute Struct
  4229. //
  4230. ShellExInfo.cbSize = sizeof(SHELLEXECUTEINFO);
  4231. ShellExInfo.hwnd = hwndDlg;
  4232. ShellExInfo.lpVerb = TEXT("open");
  4233. ShellExInfo.lpFile = pszCmd;
  4234. ShellExInfo.lpParameters = pszArgs;
  4235. ShellExInfo.nShow = SW_SHOWNORMAL;
  4236. bReturn = pArgs->m_ShellDll.ExecuteEx(&ShellExInfo);
  4237. }
  4238. CmFree(pszCmd);
  4239. CmFree(pszArgs);
  4240. }
  4241. #ifdef DEBUG
  4242. CMASSERTMSG(bReturn, TEXT("OnResetPassword() - ShellExecute failed."));
  4243. #endif
  4244. DeObfuscatePasswordEdit(pArgs);
  4245. return bReturn;
  4246. }
  4247. //+---------------------------------------------------------------------------
  4248. //
  4249. // Function: OnCustom
  4250. //
  4251. // Synopsis: Handle custom button
  4252. //
  4253. // Arguments: pArgs - the ArgStruct *
  4254. // hwndDlg - the main dlg
  4255. //
  4256. // Returns: NONE
  4257. //
  4258. // History: t-adnani Created 6/26/99
  4259. //
  4260. //----------------------------------------------------------------------------
  4261. void OnCustom(
  4262. HWND hwndDlg,
  4263. ArgsStruct *pArgs)
  4264. {
  4265. MYDBGASSERT(pArgs);
  4266. if (NULL == pArgs)
  4267. {
  4268. return;
  4269. }
  4270. pArgs->Log.Log(CUSTOM_BUTTON_EVENT);
  4271. //
  4272. // Get the latest password data from the edit control
  4273. // and obfuscate its contents so that connect actions
  4274. // can't retrieve it.
  4275. //
  4276. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  4277. ObfuscatePasswordEdit(pArgs);
  4278. //
  4279. // Run the CustomButton actions
  4280. //
  4281. int iTextBoxLength = (int) SendDlgItemMessage(hwndDlg, IDC_MAIN_STATUS_DISPLAY, WM_GETTEXTLENGTH, 0, (LPARAM)0) + 1;
  4282. TCHAR *pszTextBoxContents = (TCHAR *) CmMalloc(iTextBoxLength * sizeof(TCHAR));
  4283. if (pszTextBoxContents)
  4284. {
  4285. GetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTextBoxContents, iTextBoxLength);
  4286. }
  4287. CActionList CustomActList;
  4288. CustomActList.Append(pArgs->piniService, c_pszCmSectionCustom);
  4289. if (!CustomActList.RunAccordType(hwndDlg, pArgs))
  4290. {
  4291. //
  4292. // Connect action failed
  4293. //
  4294. }
  4295. else
  4296. {
  4297. if (pszTextBoxContents)
  4298. {
  4299. SetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, pszTextBoxContents);
  4300. }
  4301. }
  4302. CmFree(pszTextBoxContents);
  4303. DeObfuscatePasswordEdit(pArgs);
  4304. }
  4305. //----------------------------------------------------------------------------
  4306. //
  4307. // Function: SetupInternalInfo
  4308. //
  4309. // Synopsis: Load system dll's and init ArgsStruct with info from cmp/cms.
  4310. //
  4311. // Arguments: pArgs - the ArgStruct *
  4312. // hwndDlg - the main dlg
  4313. //
  4314. // Returns: NONE
  4315. //
  4316. // History: henryt created 8/13/97
  4317. //
  4318. //----------------------------------------------------------------------------
  4319. BOOL SetupInternalInfo(
  4320. ArgsStruct *pArgs,
  4321. HWND hwndDlg
  4322. )
  4323. {
  4324. HCURSOR hcursorPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  4325. BOOL fRet = FALSE;
  4326. //
  4327. // should we check if TCP is bound to PPP?
  4328. //
  4329. pArgs->bDoNotCheckBindings = pArgs->piniService->GPPB(c_pszCmSection,
  4330. c_pszCmEntryDoNotCheckBindings,
  4331. FALSE);
  4332. DWORD dwComponentsToCheck = CC_RNA | CC_TCPIP | CC_RASRUNNING
  4333. | CC_SCRIPTING | CC_CHECK_BINDINGS;
  4334. if (TRUE == pArgs->bDoNotCheckBindings)
  4335. {
  4336. //
  4337. // Do not check if TCP is bound to PPP
  4338. //
  4339. dwComponentsToCheck &= ~CC_CHECK_BINDINGS;
  4340. }
  4341. #if 0 // Don't do this until the user gets into the app.
  4342. /*
  4343. //
  4344. // If current connection type is dial-up (not Direct means Dial-up),
  4345. // then check modem
  4346. //
  4347. if (!pArgs->IsDirectConnect())
  4348. {
  4349. dwComponentsToCheck |= CC_MODEM;
  4350. }
  4351. */
  4352. #endif
  4353. if (TRUE == IsTunnelEnabled(pArgs))
  4354. {
  4355. dwComponentsToCheck |= CC_PPTP;
  4356. }
  4357. //
  4358. // should we check OS components, regardless what is in the registry key
  4359. // Default is use the registry key
  4360. //
  4361. BOOL fIgnoreRegKey = pArgs->piniService->GPPB(c_pszCmSection,
  4362. c_pszCmEntryCheckOsComponents,
  4363. FALSE);
  4364. //
  4365. // If fIgnoreRegKey is TRUE, Do not bother looking ComponentsChecked from registry.
  4366. // in 'Unattended Dialing' mode, check only, do not try to install
  4367. //
  4368. pArgs->dwExitCode = CheckAndInstallComponents( dwComponentsToCheck,
  4369. hwndDlg, pArgs->szServiceName, fIgnoreRegKey, pArgs->dwFlags & FL_UNATTENDED);
  4370. if (pArgs->dwExitCode != ERROR_SUCCESS )
  4371. {
  4372. goto done;
  4373. }
  4374. //
  4375. // If we haven't loaded RAS yet, do so now.
  4376. //
  4377. if (!IsRasLoaded(&(pArgs->rlsRasLink)))
  4378. {
  4379. if (!LinkToRas(&pArgs->rlsRasLink))
  4380. {
  4381. if (pArgs->dwFlags & FL_UNATTENDED)
  4382. {
  4383. goto done;
  4384. }
  4385. //
  4386. // Something terrible happened! We want to check our configs and install
  4387. // necessary components now.
  4388. //
  4389. dwComponentsToCheck = CC_RNA | CC_RASRUNNING | CC_TCPIP;
  4390. if (TRUE != pArgs->bDoNotCheckBindings)
  4391. {
  4392. dwComponentsToCheck |= CC_CHECK_BINDINGS;
  4393. }
  4394. pArgs->dwExitCode = CheckAndInstallComponents(dwComponentsToCheck, hwndDlg, pArgs->szServiceName);
  4395. if (pArgs->dwExitCode != ERROR_SUCCESS || !LinkToRas(&pArgs->rlsRasLink))
  4396. {
  4397. goto done;
  4398. }
  4399. }
  4400. }
  4401. //
  4402. // Load properties data
  4403. //
  4404. LoadProperties(pArgs);
  4405. //
  4406. // Get phone info(phone #'s, etc)
  4407. // CheckConnect will check for empty phone number
  4408. //
  4409. LoadPhoneInfoFromProfile(pArgs);
  4410. fRet = TRUE;
  4411. done:
  4412. SetCursor(hcursorPrev);
  4413. return fRet;
  4414. }
  4415. //----------------------------------------------------------------------------
  4416. //
  4417. // Function: OnMainLoadStartupInfo
  4418. //
  4419. // Synopsis: Load the startup info for the main dlg(after WM_INITDIALOG).
  4420. // This includes loading system dll's and setting up the UI.
  4421. //
  4422. // Arguments: hwndDlg - the main dlg
  4423. // pArgs - the ArgStruct *
  4424. //
  4425. // Returns: NONE
  4426. //
  4427. // History: henryt created 8/13/97
  4428. //
  4429. //----------------------------------------------------------------------------
  4430. void OnMainLoadStartupInfo(
  4431. HWND hwndDlg,
  4432. ArgsStruct *pArgs
  4433. )
  4434. {
  4435. UINT i;
  4436. UINT nCtrlFocus;
  4437. BOOL fSaveNoNotify = pArgs->fIgnoreChangeNotification;
  4438. pArgs->fStartupInfoLoaded = TRUE;
  4439. //
  4440. // if failed to load dll's, etc...
  4441. //
  4442. if (!SetupInternalInfo(pArgs, hwndDlg))
  4443. {
  4444. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL,0);
  4445. return;
  4446. }
  4447. //
  4448. // Set the length limit for the edit controls that exist
  4449. //
  4450. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  4451. {
  4452. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  4453. if (i <= 0)
  4454. {
  4455. i = UNLEN; // username
  4456. }
  4457. SendDlgItemMessageU(hwndDlg, IDC_MAIN_USERNAME_EDIT, EM_SETLIMITTEXT, __min(UNLEN, i), 0);
  4458. }
  4459. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  4460. {
  4461. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  4462. if (i <= 0)
  4463. {
  4464. i = PWLEN; // password
  4465. }
  4466. SendDlgItemMessageU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, EM_SETLIMITTEXT, __min(PWLEN, i), 0);
  4467. }
  4468. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  4469. {
  4470. i = (UINT)pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  4471. if (i <= 0)
  4472. {
  4473. i = DNLEN; // domain
  4474. }
  4475. SendDlgItemMessageU(hwndDlg, IDC_MAIN_DOMAIN_EDIT, EM_SETLIMITTEXT, __min(DNLEN, i), 0);
  4476. }
  4477. //
  4478. // if there's no service msg text, we need to hide and disable the control
  4479. // so that context help doesn't work.
  4480. //
  4481. if (!GetWindowTextLengthU(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY)))
  4482. {
  4483. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY), SW_HIDE);
  4484. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY), FALSE);
  4485. }
  4486. //
  4487. // display the user info
  4488. //
  4489. pArgs->fIgnoreChangeNotification = TRUE;
  4490. SetMainDlgUserInfo(pArgs, hwndDlg);
  4491. pArgs->fIgnoreChangeNotification = fSaveNoNotify;
  4492. //
  4493. // init "Remember password"
  4494. //
  4495. if (pArgs->fHideRememberPassword)
  4496. {
  4497. //
  4498. // disable and hide the checkbox if the ISP doesn't use this feature
  4499. //
  4500. //ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), SW_HIDE);
  4501. //EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  4502. }
  4503. else
  4504. {
  4505. CheckDlgButton(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX,
  4506. pArgs->fRememberMainPassword);
  4507. //
  4508. // Don't care if the pArgs->fRememberMainPassword is set
  4509. // since controls will get disabled later
  4510. // Set the save as option buttons according to what the current
  4511. // deafult is
  4512. //
  4513. SetCredentialUIOptionBasedOnDefaultCreds(pArgs, hwndDlg);
  4514. }
  4515. //
  4516. // init "Dial automatically..."
  4517. //
  4518. if (pArgs->fHideDialAutomatically)
  4519. {
  4520. //
  4521. // disable and hide the checkbox if the ISP doesn't use this feature
  4522. //
  4523. //ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), SW_HIDE);
  4524. //EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  4525. }
  4526. else
  4527. {
  4528. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, pArgs->fDialAutomatically);
  4529. }
  4530. //
  4531. // Check the main dlg status and set the default button and focus accordingly
  4532. //
  4533. BOOL bReady = CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  4534. MainSetDefaultButton(hwndDlg, nCtrlFocus);
  4535. SetFocus(GetDlgItem(hwndDlg, nCtrlFocus));
  4536. //
  4537. // Check if we want to dial without prompting user
  4538. // if so, send the button click to connect button
  4539. // We also want to dial if the user isn't logged on (ICS case)
  4540. //
  4541. if (bReady)
  4542. {
  4543. if (pArgs->fDialAutomatically ||
  4544. pArgs->dwFlags & FL_RECONNECT ||
  4545. pArgs->dwFlags & FL_UNATTENDED ||
  4546. ((CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType) && (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseWinLogonCredentials, TRUE))))
  4547. {
  4548. PostMessageU(hwndDlg, WM_COMMAND, IDOK, 0);
  4549. }
  4550. }
  4551. else
  4552. {
  4553. //
  4554. // there are settings missing.
  4555. // silently fail in unattended dial, set exit code
  4556. //
  4557. if (pArgs->dwFlags & FL_UNATTENDED)
  4558. {
  4559. pArgs->dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  4560. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL,0);
  4561. }
  4562. }
  4563. CM_SET_TIMING_INTERVAL("OnMainLoadStartupInfo - Complete");
  4564. }
  4565. //+----------------------------------------------------------------------------
  4566. //
  4567. // Function: CreateCustomButtonNextToTextBox
  4568. //
  4569. // Synopsis: Creates a pushbutton next to the specified text box
  4570. //
  4571. // Arguments: HWND hwndDlg - Dialog Handle
  4572. // HWND hwndTextBox - TextBox Handle
  4573. // LPTSTR pszTitle - Push Button Title
  4574. // LPTSTR pszToolTip - Push Button Tooltip
  4575. // UINT uButtonID - Control ID of Button to create
  4576. //
  4577. // Returns: Nothing
  4578. //
  4579. // History: t-adnani Created Header 6/28/99
  4580. //
  4581. //+----------------------------------------------------------------------------
  4582. void CreateCustomButtonNextToTextBox(
  4583. HWND hwndDlg, // Dialog Handle
  4584. HWND hwndTextBox, // TextBox Handle
  4585. LPTSTR pszTitle, // Caption
  4586. LPTSTR pszToolTip, // ToolTip Text
  4587. UINT uButtonID // ButtonID
  4588. )
  4589. {
  4590. RECT rt;
  4591. POINT pt1, pt2, ptTextBox1, ptTextBox2;
  4592. HFONT hfont;
  4593. HWND hwndButton;
  4594. //
  4595. // Get the rectangle and convert to points before we reduce its size.
  4596. //
  4597. GetWindowRect(hwndTextBox, &rt);
  4598. pt1.x = rt.left;
  4599. pt1.y = rt.top;
  4600. pt2.x = rt.right;
  4601. pt2.y = rt.bottom;
  4602. ScreenToClient(hwndDlg, &pt1);
  4603. ScreenToClient(hwndDlg, &pt2);
  4604. //
  4605. // Then calculate the points for reduction
  4606. //
  4607. ptTextBox1.x = rt.left;
  4608. ptTextBox1.y = rt.top;
  4609. ptTextBox2.x = rt.right;
  4610. ptTextBox2.y = rt.bottom;
  4611. ScreenToClient(hwndDlg, &ptTextBox1);
  4612. ScreenToClient(hwndDlg, &ptTextBox2);
  4613. //
  4614. // Make the text box smaller
  4615. //
  4616. MoveWindow(hwndTextBox, ptTextBox1.x, ptTextBox1.y,
  4617. ptTextBox2.x - ptTextBox1.x - CUSTOM_BUTTON_WIDTH - 7,
  4618. ptTextBox2.y - ptTextBox1.y, TRUE);
  4619. //
  4620. // Create the button
  4621. //
  4622. hwndButton = CreateWindowExU(0,
  4623. TEXT("button"),
  4624. pszTitle,
  4625. BS_PUSHBUTTON|WS_VISIBLE|WS_CHILD|WS_TABSTOP,
  4626. pt2.x - CUSTOM_BUTTON_WIDTH,
  4627. ptTextBox1.y,
  4628. CUSTOM_BUTTON_WIDTH,
  4629. ptTextBox2.y-ptTextBox1.y,
  4630. hwndDlg,
  4631. (HMENU)UIntToPtr(uButtonID),
  4632. g_hInst,
  4633. NULL);
  4634. if (NULL == hwndButton)
  4635. {
  4636. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() CreateWindowExU() failed, GLE=%u."),GetLastError());
  4637. }
  4638. //
  4639. // Set the font on the button
  4640. //
  4641. hfont = (HFONT)SendMessageU(hwndTextBox, WM_GETFONT, 0, 0);
  4642. if (NULL == hfont)
  4643. {
  4644. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() WM_GETFONT failed, GLE=%u."),GetLastError());
  4645. return;
  4646. }
  4647. SendMessageU(hwndButton, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(TRUE,0));
  4648. if (pszToolTip == NULL)
  4649. {
  4650. return;
  4651. }
  4652. //
  4653. // do the tool tip
  4654. //
  4655. HWND hwndTT = CreateWindowExU(0, TOOLTIPS_CLASS, TEXT(""), TTS_ALWAYSTIP,
  4656. CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
  4657. hwndDlg, (HMENU) NULL, g_hInst, NULL);
  4658. CMTRACE2(TEXT("CreateCustomButtonNextToTextBox() hwndTT is %u and IsWindow returns %u"),hwndTT, IsWindow(hwndButton));
  4659. if (NULL == hwndTT)
  4660. {
  4661. CMTRACE1(TEXT("CreateCustomButtonNextToTextBox() CreateWindowExU() failed, GLE=%u."),GetLastError());
  4662. MYDBGASSERT(hwndTT);
  4663. return;
  4664. }
  4665. TOOLINFO ti; // tool information
  4666. ti.cbSize = sizeof(TOOLINFO);
  4667. ti.uFlags = TTF_IDISHWND | TTF_CENTERTIP | TTF_SUBCLASS;
  4668. ti.hwnd = hwndDlg;
  4669. ti.hinst = g_hInst;
  4670. ti.uId = (UINT_PTR) hwndButton;
  4671. ti.lpszText = pszToolTip;
  4672. SendMessageU(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
  4673. CMTRACE2(TEXT("CreateCustomButtonNextToTextBox() hwndTT is %u and IsWindow returns %u"),hwndTT, IsWindow(hwndButton));
  4674. return;
  4675. }
  4676. //+---------------------------------------------------------------------------
  4677. //
  4678. // Function: OnMainInit
  4679. //
  4680. // Synopsis: Process the WM_INITDIALOG message
  4681. // initialization function for Main dialog box
  4682. //
  4683. // Arguments: hwndDlg - the main dlg
  4684. // pArgs - the ArgStruct *
  4685. //
  4686. // Returns: NONE
  4687. //
  4688. // History: byao Modified 5/9/97
  4689. // Added code to handle "Unattended Dial" and "Dial with Connectoid"
  4690. //
  4691. //----------------------------------------------------------------------------
  4692. void OnMainInit(HWND hwndDlg,
  4693. ArgsStruct *pArgs)
  4694. {
  4695. RECT rDlg;
  4696. RECT rWorkArea;
  4697. LPTSTR pszTitle;
  4698. SetForegroundWindow(hwndDlg);
  4699. //
  4700. // load the icons and bitmaps
  4701. //
  4702. LoadIconsAndBitmaps(pArgs, hwndDlg);
  4703. //
  4704. // Use long sevice name as title text for signin window,
  4705. //
  4706. pszTitle = CmStrCpyAlloc(pArgs->szServiceName);
  4707. SetWindowTextU(hwndDlg, pszTitle);
  4708. CmFree(pszTitle);
  4709. //
  4710. // Set the msg for the main dlg for profile dialing
  4711. //
  4712. LPTSTR pszMsg = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryServiceMessage);
  4713. SetDlgItemTextU(hwndDlg, IDC_MAIN_MESSAGE_DISPLAY, pszMsg);
  4714. CmFree(pszMsg);
  4715. //
  4716. // Show "remember password" checkbox?
  4717. //
  4718. if (IsLogonAsSystem())
  4719. {
  4720. //
  4721. // If the program is running in the system account, hide the checkbox
  4722. // Bug 196184: big security hole logging onto box with cm
  4723. //
  4724. pArgs->fHideRememberPassword = TRUE;
  4725. //
  4726. // Another big security hole by launching help files from winlogon.
  4727. // See NTRAID 429678 for details.
  4728. //
  4729. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_HELP_BUTTON), FALSE);
  4730. }
  4731. else
  4732. {
  4733. pArgs->fHideRememberPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberPwd);
  4734. }
  4735. //
  4736. // See if the Internet Password should be hidden, take HideRemember
  4737. // value as the default if no actual value is specified in the .CMS
  4738. // The Internet Password can be saved regardless of the logon context
  4739. //
  4740. pArgs->fHideRememberInetPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberInetPwd, pArgs->fHideRememberPassword);
  4741. //
  4742. // show "dial automatically" checkbox?
  4743. //
  4744. // if "hide remember password", then we also want to hide "dial automatically"
  4745. //
  4746. pArgs->fHideDialAutomatically = (pArgs->fHideRememberPassword?
  4747. TRUE :
  4748. pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideDialAuto));
  4749. // Get the dialog rect and the available work area.
  4750. GetWindowRect(hwndDlg,&rDlg);
  4751. if (SystemParametersInfoA(SPI_GETWORKAREA,0,&rWorkArea,0))
  4752. {
  4753. MoveWindow(hwndDlg,
  4754. rWorkArea.left + ((rWorkArea.right-rWorkArea.left)-(rDlg.right-rDlg.left))/2,
  4755. rWorkArea.top + ((rWorkArea.bottom-rWorkArea.top)-(rDlg.bottom-rDlg.top))/2,
  4756. rDlg.right-rDlg.left,
  4757. rDlg.bottom-rDlg.top,
  4758. FALSE);
  4759. }
  4760. //
  4761. // hide all the hidden controls asap
  4762. //
  4763. if (pArgs->fHideRememberPassword)
  4764. {
  4765. //
  4766. // disable and hide the checkbox if the ISP doesn't use this feature
  4767. //
  4768. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), SW_HIDE);
  4769. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  4770. //
  4771. // Even though we are hiding the remember password box,
  4772. // we should not hide these two controls as they might not exist on the
  4773. // dialog. fGlobalCredentialsSupported controls which dialog templates get loaded and
  4774. // if the flag is FALSE then the dialog template doesn't have these controls
  4775. // thus there is no reason to hide them.
  4776. //
  4777. if (pArgs->fGlobalCredentialsSupported)
  4778. {
  4779. //
  4780. // Also hide the option buttons
  4781. //
  4782. ShowWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), SW_HIDE);
  4783. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  4784. ShowWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), SW_HIDE);
  4785. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  4786. }
  4787. }
  4788. else
  4789. {
  4790. //
  4791. // Here we don't care if pArgs->fRememberMainPassword is set, because
  4792. // these controls will get disabled later, but we still need to set
  4793. // the default option.
  4794. //
  4795. SetCredentialUIOptionBasedOnDefaultCreds(pArgs, hwndDlg );
  4796. }
  4797. if (pArgs->fHideDialAutomatically)
  4798. {
  4799. //
  4800. // disable and hide the checkbox if the ISP doesn't use this feature
  4801. //
  4802. ShowWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), SW_HIDE);
  4803. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  4804. }
  4805. //
  4806. // Show the custom button?
  4807. //
  4808. // NT #368810
  4809. // If logged on in the system account, don't do dynamic buttons
  4810. //
  4811. if (!IsLogonAsSystem() && GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  4812. {
  4813. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryCustomButtonText);
  4814. if (pszTmp && *pszTmp)
  4815. {
  4816. LPTSTR pszToolTip = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryCustomButtonToolTip);
  4817. CMTRACE(TEXT("Creating Custom Button"));
  4818. CreateCustomButtonNextToTextBox(hwndDlg,
  4819. GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT),
  4820. pszTmp,
  4821. *pszToolTip ? pszToolTip : NULL,
  4822. IDC_MAIN_CUSTOM);
  4823. CmFree(pszToolTip);
  4824. }
  4825. CmFree(pszTmp);
  4826. }
  4827. //
  4828. // Show the reset password button?
  4829. //
  4830. if (!IsLogonAsSystem() && GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  4831. {
  4832. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection, c_pszCmEntryResetPassword);
  4833. if (pszTmp && *pszTmp)
  4834. {
  4835. DWORD dwTmp;
  4836. DWORD dwLen = (MAX_PATH * 2);
  4837. pArgs->pszResetPasswdExe = (LPTSTR) CmMalloc(sizeof(TCHAR) * dwLen);
  4838. if (pArgs->pszResetPasswdExe)
  4839. {
  4840. //
  4841. // Expand any environment strings that may exist
  4842. //
  4843. CMTRACE1(TEXT("Expanding ResetPassword environment string as %s"), pszTmp);
  4844. dwTmp = ExpandEnvironmentStringsU(pszTmp, pArgs->pszResetPasswdExe, dwLen);
  4845. MYDBGASSERT(dwTmp <= dwLen);
  4846. //
  4847. // As long as expansion succeeded, pass along the result
  4848. //
  4849. if (dwTmp <= dwLen)
  4850. {
  4851. pszTitle = CmLoadString(g_hInst, IDS_RESETPASSWORD);
  4852. CMTRACE((TEXT("Showing ResetPassword button for %s"), pArgs->pszResetPasswdExe));
  4853. CreateCustomButtonNextToTextBox(hwndDlg,
  4854. GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT),
  4855. pszTitle,
  4856. (LPTSTR)MAKEINTRESOURCE(IDS_NEW_PASSWORD_TOOLTIP),
  4857. IDC_MAIN_RESET_PASSWORD);
  4858. CmFree(pszTitle);
  4859. }
  4860. }
  4861. }
  4862. CmFree(pszTmp);
  4863. }
  4864. //
  4865. // Notify user that we are intializing
  4866. //
  4867. AppendStatusPane(hwndDlg,IDMSG_INITIALIZING);
  4868. //
  4869. // Initialize system menu
  4870. //
  4871. HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
  4872. MYDBGASSERT(hMenu);
  4873. // Delete size and maximize menuitems. These are
  4874. // not appropriate for a dialog with a no-resize frame.
  4875. DeleteMenu(hMenu, SC_SIZE, MF_BYCOMMAND);
  4876. DeleteMenu(hMenu, SC_MAXIMIZE, MF_BYCOMMAND);
  4877. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED);
  4878. //
  4879. // See if we are hiding any InetLogon controls
  4880. //
  4881. if (IsTunnelEnabled(pArgs) && !pArgs->fUseSameUserName)
  4882. {
  4883. pArgs->fHideInetUsername = pArgs->piniService->GPPB(c_pszCmSection,
  4884. c_pszCmEntryHideInetUserName);
  4885. pArgs->fHideInetPassword = pArgs->piniService->GPPB(c_pszCmSection,
  4886. c_pszCmEntryHideInetPassword);
  4887. }
  4888. //
  4889. // set timer
  4890. //
  4891. pArgs->nTimerId = SetTimer(hwndDlg,1,TIMER_RATE,NULL);
  4892. }
  4893. //
  4894. // map state to frame: splash????
  4895. //
  4896. VOID MapStateToFrame(ArgsStruct * pArgs)
  4897. {
  4898. static ProgState psOldFrame = PS_Interactive;
  4899. ProgState psNewFrame = pArgs->psState;
  4900. if (psNewFrame == PS_Dialing || psNewFrame == PS_TunnelDialing)
  4901. {
  4902. //
  4903. // If we are dialing anything other than the primary number
  4904. // switch the state to RedialFrame
  4905. // RedialFrame is a misnomer - this is the frame that is displayed
  4906. // when dialing backup number. It is not used when Redialing the
  4907. // primary number again
  4908. //
  4909. if (pArgs->nDialIdx > 0)
  4910. {
  4911. psNewFrame = PS_RedialFrame;
  4912. }
  4913. }
  4914. if (pArgs->pCtr && psNewFrame != psOldFrame)
  4915. {
  4916. psOldFrame = psNewFrame;
  4917. //
  4918. // don't check for failure here - nothing we can do.
  4919. //
  4920. pArgs->pCtr->MapStateToFrame(psOldFrame);
  4921. }
  4922. }
  4923. //
  4924. // SetInteractive: enable most of the windows and buttons so user can interact with
  4925. // connection manager again
  4926. //
  4927. void SetInteractive(HWND hwndDlg,
  4928. ArgsStruct *pArgs)
  4929. {
  4930. if (pArgs->dwFlags & FL_UNATTENDED)
  4931. {
  4932. //
  4933. // When we are unattended mode we don't want to put the UI into
  4934. // interactive mode and wait for user input. Since the unattended
  4935. // UI is now hidden, this would put up the UI waiting for user
  4936. // interaction even though the UI was invisible. Instead we
  4937. // will set the state to Interactive and post a message to cancel
  4938. // the dialer.
  4939. //
  4940. CMTRACE(TEXT("SetInteractive called while in unattended mode, posting a message to cancel"));
  4941. pArgs->psState = PS_Interactive;
  4942. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL, ERROR_CANCELLED);
  4943. }
  4944. else
  4945. {
  4946. pArgs->psState = PS_Interactive;
  4947. MapStateToFrame(pArgs);
  4948. pArgs->dwStateStartTime = GetTickCount();
  4949. EnableWindow(GetDlgItem(hwndDlg,IDOK),TRUE);
  4950. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),TRUE);
  4951. //
  4952. // Enable edit controls as necessary
  4953. //
  4954. if (GetDlgItem(hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO))
  4955. {
  4956. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_STATIC),TRUE);
  4957. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_COMBO),TRUE);
  4958. }
  4959. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  4960. {
  4961. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_EDIT),TRUE);
  4962. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_STATIC),TRUE);
  4963. }
  4964. if (GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT))
  4965. {
  4966. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_EDIT),TRUE);
  4967. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_STATIC),TRUE);
  4968. }
  4969. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  4970. {
  4971. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_EDIT),TRUE);
  4972. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_STATIC),TRUE);
  4973. }
  4974. if (pArgs->hwndResetPasswdButton)
  4975. {
  4976. EnableWindow(pArgs->hwndResetPasswdButton, TRUE);
  4977. }
  4978. if (!pArgs->fHideRememberPassword)
  4979. {
  4980. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), TRUE);
  4981. if (pArgs->fGlobalCredentialsSupported && pArgs->fRememberMainPassword)
  4982. {
  4983. //
  4984. // Also enable the option buttons
  4985. //
  4986. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), TRUE);
  4987. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), TRUE);
  4988. }
  4989. }
  4990. if ((!pArgs->fHideDialAutomatically) &&
  4991. (pArgs->fRememberMainPassword ||
  4992. pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryPwdOptional)))
  4993. {
  4994. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), TRUE);
  4995. }
  4996. //
  4997. // Set the default button
  4998. //
  4999. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDOK, 0);
  5000. SetFocus(GetDlgItem(hwndDlg,IDOK));
  5001. }
  5002. DeObfuscatePasswordEdit(pArgs);
  5003. }
  5004. //+----------------------------------------------------------------------------
  5005. //
  5006. // Function: SetWatchHandles
  5007. //
  5008. // Synopsis: Handles the messy details of Duplicating each of the Watch
  5009. // handles so that they can be accessed by the CMMON process.
  5010. // The list of handles is assumed to be NULL terminated.
  5011. //
  5012. // Arguments: HANDLE *phOldHandles - Ptr to the current handle list.
  5013. // HANDLE *phNewHandles - Ptr to storage for duplicted handles.
  5014. // HWND hwndMon - HWND in the target process.
  5015. //
  5016. // Returns: BOOL - TRUE on success
  5017. //
  5018. // History: nickball Created 2/11/98
  5019. //
  5020. //+----------------------------------------------------------------------------
  5021. BOOL
  5022. SetWatchHandles(
  5023. IN HANDLE *phOldHandles,
  5024. OUT HANDLE *phNewHandles,
  5025. IN HWND hwndMon)
  5026. {
  5027. MYDBGASSERT(phOldHandles);
  5028. MYDBGASSERT(phNewHandles);
  5029. MYDBGASSERT(hwndMon);
  5030. BOOL bReturn = TRUE;
  5031. if (NULL == phOldHandles || NULL == phNewHandles || NULL == hwndMon)
  5032. {
  5033. return FALSE;
  5034. }
  5035. //
  5036. // First we need to get the Handle of our current process
  5037. //
  5038. DWORD dwProcessId = GetCurrentProcessId();
  5039. HANDLE hSourceProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  5040. //
  5041. // Now the handle of the target process
  5042. //
  5043. GetWindowThreadProcessId(hwndMon, &dwProcessId);
  5044. HANDLE hTargetProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
  5045. //
  5046. // Loop through our handles list and duplicate
  5047. //
  5048. DWORD dwIdx = 0;
  5049. for (dwIdx = 0; phOldHandles[dwIdx]; dwIdx++)
  5050. {
  5051. if (FALSE == DuplicateHandle(hSourceProcess, phOldHandles[dwIdx], // Val
  5052. hTargetProcess, &phNewHandles[dwIdx], // Ptr
  5053. NULL, FALSE, DUPLICATE_SAME_ACCESS))
  5054. {
  5055. CMTRACE1(TEXT("SetWatchHandles() - DuplicateHandles failed on item %u"), dwIdx);
  5056. MYDBGASSERT(FALSE);
  5057. bReturn = FALSE;
  5058. break;
  5059. }
  5060. }
  5061. MYDBGASSERT(dwIdx); // Don't call if you don't have handles to duplicate
  5062. //
  5063. // Cleanup
  5064. //
  5065. if (!bReturn)
  5066. {
  5067. // we failed during Handle Duplication... must clean up
  5068. while (dwIdx > 0)
  5069. {
  5070. CloseHandle(phNewHandles[--dwIdx]);
  5071. }
  5072. }
  5073. CloseHandle(hTargetProcess);
  5074. CloseHandle(hSourceProcess);
  5075. return bReturn;
  5076. }
  5077. //+----------------------------------------------------------------------------
  5078. //
  5079. // Function: ConnectMonitor
  5080. //
  5081. // Synopsis: Encapsulates the details of launching CMMON, waiting for load
  5082. // verification, and providing it with connect data.
  5083. //
  5084. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  5085. //
  5086. // Returns: HRESULT - Failure code
  5087. //
  5088. // History: nickball Created 2/9/98
  5089. //
  5090. //+----------------------------------------------------------------------------
  5091. HRESULT ConnectMonitor(ArgsStruct *pArgs)
  5092. {
  5093. LRESULT lRes = ERROR_SUCCESS;
  5094. BOOL fMonReady = FALSE;
  5095. HWND hwndMon = NULL;
  5096. TCHAR szDesktopName[MAX_PATH];
  5097. TCHAR szWinDesktop[MAX_PATH];
  5098. //
  5099. // Determine if CMMON is running
  5100. //
  5101. if (SUCCEEDED(pArgs->pConnTable->GetMonitorWnd(&hwndMon)))
  5102. {
  5103. fMonReady = IsWindow(hwndMon);
  5104. }
  5105. //
  5106. // If not, launch it
  5107. //
  5108. if (FALSE == fMonReady)
  5109. {
  5110. //
  5111. // Create launch event
  5112. //
  5113. HANDLE hEvent = CreateEventU(NULL, TRUE, FALSE, c_pszCmMonReadyEvent);
  5114. if (NULL == hEvent)
  5115. {
  5116. MYDBGASSERT(FALSE);
  5117. lRes = GetLastError();
  5118. }
  5119. else
  5120. {
  5121. STARTUPINFO StartupInfo;
  5122. PROCESS_INFORMATION ProcessInfo;
  5123. TCHAR szCommandLine[2 * MAX_PATH + 3];
  5124. //
  5125. // Launch c_pszCmMonExeName
  5126. //
  5127. ZeroMemory(&ProcessInfo, sizeof(ProcessInfo));
  5128. ZeroMemory(&StartupInfo, sizeof(StartupInfo));
  5129. StartupInfo.cb = sizeof(StartupInfo);
  5130. //
  5131. // If this is win2k or whistler, then we don't want to launch cmmon32.exe onto the users
  5132. // desktop since it is a security hole to have a system process with a window on the users
  5133. // desktop. This window could be attacked by WM_TIMER and other messages ...
  5134. // But in case of ICS (no user is logged on), just launch CMMON in normally by leaving
  5135. // StartupInfo.lpDesktop = NULL. By leaving this NULL the new process inherits
  5136. // the desktop and window station of its parent process.This makes it work with
  5137. // ICS when no user is logged-on. Otherwise CM never gets the event back from
  5138. // CMMON because it's on a different desktop.
  5139. //
  5140. if (OS_NT5 && IsLogonAsSystem() && (CM_LOGON_TYPE_ICS != pArgs->dwWinLogonType))
  5141. {
  5142. DWORD cb;
  5143. HDESK hDesk = GetThreadDesktop(GetCurrentThreadId());
  5144. //
  5145. // Get the name of the desktop. Normally returns default or Winlogon or system or WinNT
  5146. //
  5147. szDesktopName[0] = 0;
  5148. if (GetUserObjectInformation(hDesk, UOI_NAME, szDesktopName, sizeof(szDesktopName), &cb))
  5149. {
  5150. lstrcpyU(szWinDesktop, TEXT("Winsta0\\"));
  5151. lstrcatU(szWinDesktop, szDesktopName);
  5152. StartupInfo.lpDesktop = szWinDesktop;
  5153. StartupInfo.wShowWindow = SW_SHOW;
  5154. CMTRACE1(TEXT("ConnectMonitor - running under system account, so launching cmmon32.exe onto Desktop = %s"), MYDBGSTR(StartupInfo.lpDesktop));
  5155. }
  5156. else
  5157. {
  5158. //
  5159. // If we are here, cmmon32.exe probably isn't going to be able to communicate with
  5160. // cmdial32.dll which means the handoff between the two will fail and the call will be
  5161. // aborted.
  5162. //
  5163. CMASSERTMSG(FALSE, TEXT("ConnectMonitor -- GetUserObjectInformation failed."));
  5164. }
  5165. }
  5166. else if (OS_NT4 && IsLogonAsSystem())
  5167. {
  5168. //
  5169. // We are less concerned about the security risk on NT4 and more concerned with the loss
  5170. // of the functionality that cmmon32.exe provides to the user. Thus we will push the
  5171. // cmmon32.exe window onto the user's desktop.
  5172. //
  5173. StartupInfo.lpDesktop = TEXT("Winsta0\\Default");
  5174. StartupInfo.wShowWindow = SW_SHOW;
  5175. CMTRACE1(TEXT("ConnectMonitor - running on system account on NT4, so launching cmmon32.exe onto Desktop = %s"), MYDBGSTR(StartupInfo.lpDesktop ));
  5176. }
  5177. ZeroMemory(&szCommandLine, sizeof(szCommandLine));
  5178. szCommandLine[0] = TEXT('"');
  5179. if (0 == GetSystemDirectoryU(szCommandLine + 1, 2 * MAX_PATH))
  5180. {
  5181. lRes = GetLastError();
  5182. CMTRACE1(TEXT("ConnectMonitor() GetSystemDirectoryU(), GLE=%u."), lRes);
  5183. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5184. }
  5185. //
  5186. // Set Application name to NULL, set command line to the executable name
  5187. // Thus CreateProcess will search the path for the executable
  5188. //
  5189. lstrcatU(szCommandLine, TEXT("\\"));
  5190. lstrcatU(szCommandLine, c_pszCmMonExeName);
  5191. lstrcatU(szCommandLine, TEXT("\""));
  5192. CMTRACE1(TEXT("ConnectMonitor() - Launching %s"), szCommandLine);
  5193. if (NULL == CreateProcessU(NULL, szCommandLine,
  5194. NULL, NULL, FALSE, 0,
  5195. NULL, NULL,
  5196. &StartupInfo, &ProcessInfo))
  5197. {
  5198. lRes = GetLastError();
  5199. CMTRACE2(TEXT("ConnectMonitor() CreateProcess() of %s failed, GLE=%u."),
  5200. c_pszCmMonExeName, lRes);
  5201. }
  5202. else
  5203. {
  5204. //
  5205. // Wait for event to be signaled, that CMMON is up
  5206. //
  5207. DWORD dwWait = WaitForSingleObject(hEvent, MAX_OBJECT_WAIT);
  5208. if (WAIT_OBJECT_0 != dwWait)
  5209. {
  5210. if (WAIT_TIMEOUT == dwWait)
  5211. {
  5212. lRes = ERROR_TIMEOUT;
  5213. }
  5214. else
  5215. {
  5216. lRes = GetLastError();
  5217. }
  5218. }
  5219. else
  5220. {
  5221. fMonReady = TRUE;
  5222. }
  5223. //
  5224. // Close Process handles. Note, we don't use these handles for
  5225. // duplicating handles in order to maintain a common code path
  5226. // regardless of whether CMMON was up already.
  5227. //
  5228. CloseHandle(ProcessInfo.hProcess);
  5229. CloseHandle(ProcessInfo.hThread);
  5230. }
  5231. CloseHandle(hEvent);
  5232. }
  5233. }
  5234. if (fMonReady)
  5235. {
  5236. //
  5237. // Get the hwnd for CMMON. Note: CMMON is expected to set
  5238. // the hwnd in the table before it signals the ready event.
  5239. //
  5240. if (FAILED(pArgs->pConnTable->GetMonitorWnd(&hwndMon)))
  5241. {
  5242. CMTRACE(TEXT("ConnectMonitor() - No Monitor HWND in table"));
  5243. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5244. }
  5245. //
  5246. // Make sure the HWND for CMMON is valid before trying to send data.
  5247. //
  5248. if (!IsWindow(hwndMon))
  5249. {
  5250. MSG msg;
  5251. HANDLE hHandle = GetCurrentProcess();
  5252. //
  5253. // Sometimes it takes a few ticks for us to get a positive response
  5254. // from IsWindow, so loop and pump messages while we are waiting.
  5255. //
  5256. while (hHandle && (MsgWaitForMultipleObjects(1, &hHandle, FALSE,
  5257. MAX_OBJECT_WAIT,
  5258. QS_ALLINPUT) == (WAIT_OBJECT_0 + 1)))
  5259. {
  5260. while (PeekMessageU(&msg, NULL, 0, 0, PM_REMOVE))
  5261. {
  5262. CMTRACE(TEXT("ConnectMonitor() - Waiting for IsWindow(hwndMon) - got Message"));
  5263. TranslateMessage(&msg);
  5264. DispatchMessageU(&msg);
  5265. }
  5266. //
  5267. // If the window is valid, we can go. Otherwise, keep pumping.
  5268. //
  5269. if (IsWindow(hwndMon))
  5270. {
  5271. break;
  5272. }
  5273. }
  5274. if (FALSE == IsWindow(hwndMon))
  5275. {
  5276. CMTRACE(TEXT("ConnectMonitor() - Monitor HWND in table is not valid"));
  5277. return HRESULT_FROM_WIN32(ERROR_NOT_FOUND);
  5278. }
  5279. }
  5280. //
  5281. // Allocate buffer for CONNECTED_INFO, including extension for Watch Process list
  5282. //
  5283. DWORD dwWatchCount = GetWatchCount(pArgs);
  5284. DWORD dwDataSize = sizeof(CM_CONNECTED_INFO) + (dwWatchCount * sizeof(HANDLE));
  5285. LPCM_CONNECTED_INFO pInfo = (LPCM_CONNECTED_INFO) CmMalloc(dwDataSize);
  5286. //
  5287. // Allocate the COPYDATASTRUCT
  5288. //
  5289. COPYDATASTRUCT *pCopyData = (COPYDATASTRUCT*) CmMalloc(sizeof(COPYDATASTRUCT));
  5290. if (NULL == pInfo || NULL == pCopyData)
  5291. {
  5292. lRes = ERROR_NOT_ENOUGH_MEMORY;
  5293. }
  5294. else
  5295. {
  5296. //
  5297. // Fill in the CONNECTED_INFO
  5298. //
  5299. lstrcpyU(pInfo->szEntryName, pArgs->szServiceName);
  5300. lstrcpyU(pInfo->szProfilePath, pArgs->piniProfile->GetFile());
  5301. //
  5302. // Provide any password data that we have
  5303. //
  5304. lstrcpynU(pInfo->szPassword, pArgs->szPassword,
  5305. sizeof(pInfo->szPassword)/sizeof(pInfo->szPassword[0]));
  5306. lstrcpynU(pInfo->szUserName, pArgs->szUserName,
  5307. sizeof(pInfo->szUserName)/sizeof(pInfo->szUserName[0]));
  5308. lstrcpynU(pInfo->szInetPassword, pArgs->szInetPassword,
  5309. sizeof(pInfo->szInetPassword)/sizeof(pInfo->szInetPassword[0]));
  5310. //
  5311. // And the RAS phonebook
  5312. //
  5313. if (pArgs->pszRasPbk)
  5314. {
  5315. lstrcpynU(pInfo->szRasPhoneBook, pArgs->pszRasPbk,
  5316. sizeof(pInfo->szRasPhoneBook)/sizeof(pInfo->szRasPhoneBook[0]));
  5317. }
  5318. else
  5319. {
  5320. pInfo->szRasPhoneBook[0] = L'\0';
  5321. }
  5322. pInfo->dwCmFlags = pArgs->dwFlags;
  5323. //
  5324. // Need to know about global creds for Fast User Switching
  5325. //
  5326. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  5327. {
  5328. pInfo->dwCmFlags |= FL_GLOBALCREDS;
  5329. CMTRACE(TEXT("ConnectMonitor - we have globalcreds!!"));
  5330. }
  5331. //
  5332. // For W95, we must pass initial statistics data to CMMON
  5333. //
  5334. pInfo->dwInitBytesRecv = -1; // default to no stats
  5335. pInfo->dwInitBytesSend = -1; // default to no stats
  5336. if (pArgs->pConnStatistics)
  5337. {
  5338. //
  5339. // Get reg based stat data if available
  5340. //
  5341. if (pArgs->pConnStatistics->IsAvailable())
  5342. {
  5343. pInfo->dwInitBytesRecv = pArgs->pConnStatistics->GetInitBytesRead();
  5344. pInfo->dwInitBytesSend = pArgs->pConnStatistics->GetInitBytesWrite();
  5345. }
  5346. //
  5347. // Note: Adapter info is good, even if stats aren't available
  5348. //
  5349. pInfo->fDialup2 = pArgs->pConnStatistics->IsDialupTwo();
  5350. }
  5351. //
  5352. // Update the watch process list at the end of the CONNECTED_INFO struct
  5353. //
  5354. if (dwWatchCount)
  5355. {
  5356. if (FALSE == SetWatchHandles(pArgs->phWatchProcesses, &pInfo->ahWatchHandles[0], hwndMon))
  5357. {
  5358. pInfo->ahWatchHandles[0] = NULL;
  5359. }
  5360. }
  5361. //
  5362. // Send CONNECTED_INFO to CMMON
  5363. //
  5364. pCopyData->dwData = CMMON_CONNECTED_INFO;
  5365. pCopyData->cbData = dwDataSize;
  5366. pCopyData->lpData = (PVOID) pInfo;
  5367. SendMessageU(hwndMon, WM_COPYDATA, NULL, (LPARAM) pCopyData);
  5368. }
  5369. //
  5370. // Release allocations
  5371. //
  5372. if (pInfo)
  5373. {
  5374. CmFree(pInfo);
  5375. }
  5376. if (pCopyData)
  5377. {
  5378. CmFree(pCopyData);
  5379. }
  5380. }
  5381. return HRESULT_FROM_WIN32(lRes);
  5382. }
  5383. //+----------------------------------------------------------------------------
  5384. //
  5385. // Function: CreateConnTable
  5386. //
  5387. // Synopsis: Initializes our CConnectionTable ptr and creates a new ConnTable
  5388. // or opens an existing one as needed
  5389. //
  5390. // Arguments: ArgsStruct *pArgs - Ptr to global args struct containing.
  5391. //
  5392. // Returns: HRESULT - Failure code
  5393. //
  5394. // History: nickball Created 2/9/98
  5395. //
  5396. //+----------------------------------------------------------------------------
  5397. HRESULT CreateConnTable(ArgsStruct *pArgs)
  5398. {
  5399. HRESULT hrRet = E_FAIL;
  5400. pArgs->pConnTable = new CConnectionTable();
  5401. if (pArgs->pConnTable)
  5402. {
  5403. //
  5404. // We have our class, now create/open the connection table.
  5405. //
  5406. hrRet = pArgs->pConnTable->Open();
  5407. if (FAILED(hrRet))
  5408. {
  5409. hrRet = pArgs->pConnTable->Create();
  5410. if (HRESULT_CODE(hrRet) == ERROR_ALREADY_EXISTS)
  5411. {
  5412. CMTRACE1(TEXT("CreateConnTable -- ConnTable creation failed with error 0x%x. Strange since the Open failed too..."), hrRet);
  5413. }
  5414. else
  5415. {
  5416. CMTRACE1(TEXT("CreateConnTable -- ConnTable creation failed with error 0x%x"), hrRet);
  5417. }
  5418. }
  5419. }
  5420. else
  5421. {
  5422. hrRet = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  5423. }
  5424. MYDBGASSERT(SUCCEEDED(hrRet));
  5425. return hrRet;
  5426. }
  5427. #if 0 // NT 301988
  5428. /*
  5429. //+----------------------------------------------------------------------------
  5430. //
  5431. // Function: HandleMainConnectRequest
  5432. //
  5433. // Synopsis: Helper routine to handle the possibility that there may be a
  5434. // connect in progress on this service.
  5435. //
  5436. // Arguments: HWND hwndDlg - HWND of main dialog
  5437. // ArgsStruct *pArgs - Ptr to global Args struct
  5438. //
  5439. // Returns: BOOL - TRUE if we have fully handled the request
  5440. // and it is ok to terminate this instance.
  5441. //
  5442. // History: nickball Created 2/23/98
  5443. //
  5444. //+----------------------------------------------------------------------------
  5445. BOOL HandleMainConnectRequest(HWND hwndDlg, ArgsStruct *pArgs)
  5446. {
  5447. MYDBGASSERT(pArgs);
  5448. BOOL fResolved = FALSE;
  5449. LPCM_CONNECTION pConnection = GetConnection(pArgs);
  5450. //
  5451. // If no conection found, then there is no work to be done here, continue.
  5452. //
  5453. if (pConnection)
  5454. {
  5455. //
  5456. // If we are in any state besides RECONNECT, we can handle it here
  5457. //
  5458. if (CM_RECONNECTPROMPT != pConnection->CmState)
  5459. {
  5460. fResolved = TRUE;
  5461. if (pArgs->dwFlags & FL_DESKTOP)
  5462. {
  5463. //
  5464. // Caller is from the desktop, notify the user and we're done
  5465. //
  5466. NotifyUserOfExistingConnection(hwndDlg, pConnection, TRUE);
  5467. }
  5468. else
  5469. {
  5470. BOOL fSuccess = TRUE;
  5471. //
  5472. // We have a programmatic caller, if connected just bump the ref count
  5473. // and return successfully. Otherwise we return failure so that the
  5474. // caller doesn't erroneously believe that there is a connection.
  5475. //
  5476. if (CM_CONNECTED != pConnection->CmState)
  5477. {
  5478. fSuccess = FALSE;
  5479. }
  5480. else
  5481. {
  5482. UpdateTable(pArgs, CM_CONNECTING);
  5483. }
  5484. //
  5485. // Terminate this connect instance.
  5486. //
  5487. EndMainDialog(hwndDlg, pArgs, 0); // fSuccess);
  5488. }
  5489. }
  5490. else
  5491. {
  5492. //
  5493. // We're in reconnect mode and going to connect.
  5494. //
  5495. if (!(pArgs->dwFlags & FL_RECONNECT))
  5496. {
  5497. //
  5498. // This request is not a reconnect request from CMMON,
  5499. // make that sure the dialog is no longer displayed.
  5500. //
  5501. HangupNotifyCmMon(pArgs->pConnTable, pConnection->szEntry);
  5502. }
  5503. else
  5504. {
  5505. //
  5506. // We are handling a reconnect for CMMON, reduce the usage
  5507. // count so it is in sync when we begin connecting.
  5508. //
  5509. pArgs->pConnTable->RemoveEntry(pConnection->szEntry);
  5510. }
  5511. }
  5512. CmFree(pConnection);
  5513. }
  5514. return fResolved;
  5515. }
  5516. */
  5517. #endif
  5518. //
  5519. // OnMainConnect: Command Handler when user clicked on 'Connect' Button in
  5520. // Main Dialog Box
  5521. //
  5522. void OnMainConnect(HWND hwndDlg,
  5523. ArgsStruct *pArgs)
  5524. {
  5525. CM_SET_TIMING_INTERVAL("OnMainConnect - Begin");
  5526. //
  5527. // If we aren't ready to dial, set focus appropriately and bail
  5528. //
  5529. UINT nCtrlFocus;
  5530. if (FALSE == CheckConnect(hwndDlg, pArgs, &nCtrlFocus, TRUE))
  5531. {
  5532. MainSetDefaultButton(hwndDlg, nCtrlFocus);
  5533. SetFocus(GetDlgItem(hwndDlg, nCtrlFocus));
  5534. return;
  5535. }
  5536. (void) InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  5537. //
  5538. // Access Points - Disable AP combo box before connecting
  5539. //
  5540. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_STATIC),FALSE);
  5541. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_ACCESSPOINT_COMBO),FALSE);
  5542. //
  5543. // Store the current access point to reg.
  5544. //
  5545. if (pArgs->fAccessPointsEnabled)
  5546. {
  5547. WriteUserInfoToReg(pArgs, UD_ID_CURRENTACCESSPOINT, (PVOID)(pArgs->pszCurrentAccessPoint));
  5548. }
  5549. //
  5550. // Assume success unless something contradictory happens
  5551. //
  5552. pArgs->dwExitCode = ERROR_SUCCESS;
  5553. HCURSOR hPrev = SetCursor(LoadCursorU(NULL,IDC_WAIT));
  5554. LPTSTR pszMsg = CmFmtMsg(g_hInst, IDMSG_WORKING);
  5555. if (pszMsg)
  5556. {
  5557. SetDlgItemTextA(hwndDlg, IDC_MAIN_STATUS_DISPLAY, "");
  5558. AppendStatusPane(hwndDlg,pszMsg);
  5559. CmFree(pszMsg);
  5560. }
  5561. //
  5562. // We're connecting, update the table.
  5563. //
  5564. UpdateTable(pArgs, CM_CONNECTING);
  5565. //
  5566. // Clear out everything on the status panel
  5567. //
  5568. SetDlgItemTextA(hwndDlg, IDC_MAIN_STATUS_DISPLAY, "");
  5569. //
  5570. // Set the default button to Cancel
  5571. //
  5572. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDCANCEL, 0);
  5573. SetFocus(GetDlgItem(hwndDlg,IDCANCEL));
  5574. BOOL fSaveUPD = TRUE;
  5575. BOOL fSaveOtherUserInfo = TRUE;
  5576. //
  5577. // We want to save and/or delete credentials only when the user is logged on.
  5578. // This is taken care of by the functions that get called here. As long as
  5579. // the user is logged on, we try to mark, delete credentials and
  5580. // potentially resave credential info. From this level we shouldn't
  5581. // worry if we have the ras cred store or how the creds are really stored.
  5582. //
  5583. if (CM_LOGON_TYPE_USER == pArgs->dwWinLogonType)
  5584. {
  5585. //
  5586. // If this is NT4 or Win9X the GetAndStoreUserInfo takes care of storing
  5587. // the user info w/o the credential store.
  5588. //
  5589. if (OS_NT5)
  5590. {
  5591. //
  5592. // For Win2K+ we use the RAS API to save the credentials. The call saves
  5593. // and deletes user and global creds based on the current state and the
  5594. // user's choices (whether to save a password, etc.)
  5595. //
  5596. TryToDeleteAndSaveCredentials(pArgs, hwndDlg);
  5597. //
  5598. // Parameter to GetAndStoreUserInfo() - doesn't save Username, Password, Domain
  5599. //
  5600. fSaveUPD = FALSE;
  5601. }
  5602. }
  5603. else
  5604. {
  5605. //
  5606. // User isn't logged on, thus we don't want to save anything
  5607. //
  5608. fSaveUPD = FALSE;
  5609. fSaveOtherUserInfo = FALSE;
  5610. }
  5611. //
  5612. // Gets the userinfo from the edit boxes into the pArgs structure ans saves the other
  5613. // user flags. This is also saves the credentials on NT4 & Win 9x if the 3rd parameter is true
  5614. //
  5615. // 3rd parameter (fSaveUPD) - used to save Username, Domain, Password.
  5616. // 4th param (fSaveOtherUserInfo) - used to save user info flags. (remember password,
  5617. // dial automatically, etc.)
  5618. //
  5619. GetAndStoreUserInfo(pArgs, hwndDlg, fSaveUPD, fSaveOtherUserInfo);
  5620. //
  5621. // Vars for RAS
  5622. //
  5623. pArgs->nDialIdx = 0;
  5624. //
  5625. // Set our redial counter with the maximum. The max value is read
  5626. // in when we initialize the dialog. It is just a place holder
  5627. // nRedialCnt is the var used/modified to regulate the re-dial process.
  5628. //
  5629. pArgs->nRedialCnt = pArgs->nMaxRedials;
  5630. //
  5631. // Disable username controls before dialing
  5632. //
  5633. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_EDIT),FALSE);
  5634. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_USERNAME_STATIC),FALSE);
  5635. //
  5636. // Disable password controls before dialing
  5637. //
  5638. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_EDIT),FALSE);
  5639. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PASSWORD_STATIC),FALSE);
  5640. //
  5641. // Disable domain controls before dialing
  5642. //
  5643. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_EDIT),FALSE);
  5644. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_DOMAIN_STATIC),FALSE);
  5645. //
  5646. // disable all other buttons
  5647. //
  5648. EnableWindow(GetDlgItem(hwndDlg,IDOK),FALSE);
  5649. EnableWindow(GetDlgItem(hwndDlg,IDC_MAIN_PROPERTIES_BUTTON),FALSE);
  5650. if (pArgs->hwndResetPasswdButton)
  5651. {
  5652. EnableWindow(pArgs->hwndResetPasswdButton, FALSE);
  5653. }
  5654. if (!pArgs->fHideRememberPassword)
  5655. {
  5656. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPASSWORD_CHECKBOX), FALSE);
  5657. if (pArgs->fGlobalCredentialsSupported)
  5658. {
  5659. //
  5660. // Also disable the option buttons
  5661. //
  5662. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  5663. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  5664. }
  5665. }
  5666. if (!pArgs->fHideDialAutomatically)
  5667. {
  5668. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX), FALSE);
  5669. }
  5670. //
  5671. // Try to check the Advanced Tab settings (ICF/ICS) and see if we need to enable or disable
  5672. // them based on what's configured in the .cms file. This is only on WinXP+ & if the user is logged in
  5673. //
  5674. VerifyAdvancedTabSettings(pArgs);
  5675. //
  5676. // Dial the number
  5677. //
  5678. DWORD dwResult = ERROR_SUCCESS;
  5679. pArgs->Log.Log(PRECONNECT_EVENT, pArgs->GetTypeOfConnection());
  5680. //
  5681. // Run the Pre-Connect actions
  5682. //
  5683. CActionList PreConnActList;
  5684. PreConnActList.Append(pArgs->piniService, c_pszCmSectionPreConnect);
  5685. if (!PreConnActList.RunAccordType(hwndDlg, pArgs))
  5686. {
  5687. //
  5688. // Connect action failed
  5689. //
  5690. UpdateTable(pArgs, CM_DISCONNECTED);
  5691. dwResult = ERROR_INVALID_DLL; // Only used for failed CA
  5692. }
  5693. else
  5694. {
  5695. if (pArgs->IsDirectConnect())
  5696. {
  5697. MYDBGASSERT(pArgs->hrcRasConn == NULL);
  5698. pArgs->fUseTunneling = TRUE;
  5699. pArgs->psState = PS_TunnelDialing;
  5700. pArgs->dwStateStartTime = GetTickCount();
  5701. pArgs->nLastSecondsDisplay = (UINT) -1;
  5702. dwResult = DoTunnelDial(hwndDlg,pArgs);
  5703. }
  5704. else
  5705. {
  5706. //
  5707. // If the DynamicPhoneNumber flag is set, then we need to re-read
  5708. // the phoneinfo from the profile and make sure it re-munged.
  5709. //
  5710. BOOL bDynamicNum = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmDynamicPhoneNumber);
  5711. if (bDynamicNum)
  5712. {
  5713. LoadPhoneInfoFromProfile(pArgs);
  5714. }
  5715. //
  5716. // Load dial info(phone #'s, etc)
  5717. // In the auto-dial case we pass FALSE for fInstallModem so that
  5718. // LoadDialInfo does not try to install a modem because it would
  5719. // require user intervention
  5720. //
  5721. dwResult = LoadDialInfo(pArgs, hwndDlg, !(pArgs->dwFlags & FL_UNATTENDED), bDynamicNum);
  5722. //
  5723. // Close TAPI before we dial, this will be cleaned up when we unlink,
  5724. // but there is no reason to keep TAPI tied up while we're dialing.
  5725. //
  5726. CloseTapi(&pArgs->tlsTapiLink);
  5727. if (dwResult == ERROR_SUCCESS)
  5728. {
  5729. dwResult = DoRasDial(hwndDlg,pArgs,pArgs->nDialIdx);
  5730. }
  5731. //
  5732. // If modem is not installed and LoadDialInfo failed to install modem, dwResult will be
  5733. // ERROR_PORT_NOT_AVAILABLE. Ideally, we should disable the connect button and display
  5734. // a different error message.
  5735. //
  5736. }
  5737. }
  5738. if (ERROR_SUCCESS != dwResult)
  5739. {
  5740. HangupCM(pArgs, hwndDlg);
  5741. UpdateError(pArgs, dwResult);
  5742. if (IsLogonAsSystem() && BAD_SCARD_PIN(dwResult))
  5743. {
  5744. //
  5745. // Disable the Connect button to avoid smartcard lockout. Also propagate
  5746. // the error back to our caller (RAS) so that they can End the 'choose
  5747. // connectoid' dialog and return to winlogon, where the user can enter
  5748. // the correct PIN.
  5749. //
  5750. pArgs->dwSCardErr = dwResult;
  5751. EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE);
  5752. SendMessageU(hwndDlg, DM_SETDEFID, (WPARAM)IDCANCEL, 0);
  5753. SetFocus(GetDlgItem(hwndDlg, IDCANCEL));
  5754. }
  5755. SetLastError(dwResult);
  5756. }
  5757. SetCursor(hPrev);
  5758. CM_SET_TIMING_INTERVAL("OnMainConnect - End");
  5759. }
  5760. //+---------------------------------------------------------------------------
  5761. //
  5762. // Function: UseTunneling
  5763. //
  5764. // Synopsis: Check to see if we should do tunneling based on fTunnelPrimary
  5765. // and fTunnelReferences.
  5766. //
  5767. // Arguments: pArgs [the ArgStruct ptr]
  5768. // dwEntry [the phone index]
  5769. //
  5770. // Returns: TRUE if we tunnel, FALSE otherwise.
  5771. //
  5772. // History: henryt Created 3/5/97
  5773. //
  5774. //----------------------------------------------------------------------------
  5775. BOOL UseTunneling(
  5776. ArgsStruct *pArgs,
  5777. DWORD dwEntry
  5778. )
  5779. {
  5780. LPTSTR pszRefPhoneSource = NULL;
  5781. BOOL fPhoneNumIsFromPrimaryPBK;
  5782. LPTSTR pszTmp;
  5783. CIni iniTmp(pArgs->piniProfile->GetHInst(),pArgs->piniProfile->GetFile(), pArgs->piniProfile->GetRegPath());
  5784. BOOL fUseTunneling = FALSE;
  5785. //
  5786. // Set the read flags
  5787. //
  5788. if (pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA)
  5789. {
  5790. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  5791. if (pszICSDataReg)
  5792. {
  5793. iniTmp.SetReadICSData(TRUE);
  5794. iniTmp.SetICSDataPath(pszICSDataReg);
  5795. }
  5796. CmFree(pszICSDataReg);
  5797. }
  5798. iniTmp.SetEntryFromIdx(dwEntry);
  5799. pszRefPhoneSource = iniTmp.GPPS(c_pszCmSection, c_pszCmEntryPhoneSourcePrefix);
  5800. //
  5801. // If PhoneSource[0|1] is not empty, verify its existence
  5802. //
  5803. if (*pszRefPhoneSource)
  5804. {
  5805. //
  5806. // pszRefPhoneSource is either a relative or full path.
  5807. // CmConvertRelativePath() will do the conversion to a full path properly
  5808. //
  5809. pszTmp = CmConvertRelativePath(pArgs->piniService->GetFile(), pszRefPhoneSource);
  5810. if (!pszTmp || FALSE == FileExists(pszTmp))
  5811. {
  5812. CmFree(pszRefPhoneSource);
  5813. CmFree(pszTmp);
  5814. return fUseTunneling;
  5815. }
  5816. //
  5817. // Is the phone # from the primary(top level) phone book?
  5818. //
  5819. fPhoneNumIsFromPrimaryPBK = (lstrcmpiU(pszTmp, pArgs->piniService->GetFile()) == 0);
  5820. CmFree(pszTmp);
  5821. fUseTunneling =
  5822. ((fPhoneNumIsFromPrimaryPBK && pArgs->fTunnelPrimary) ||
  5823. (!fPhoneNumIsFromPrimaryPBK && pArgs->fTunnelReferences));
  5824. }
  5825. else
  5826. {
  5827. // the phone # is not from a phone book. the user probably typed it in
  5828. // him/herself.
  5829. fUseTunneling = pArgs->fTunnelPrimary;
  5830. }
  5831. CmFree(pszRefPhoneSource);
  5832. return fUseTunneling;
  5833. }
  5834. //
  5835. // OnMainProperties: command handler for 'Properties' button in the main dialog box
  5836. //
  5837. int OnMainProperties(HWND hwndDlg,
  5838. ArgsStruct *pArgs)
  5839. {
  5840. CMTRACE(TEXT("Begin OnMainProperties()"));
  5841. //
  5842. // do the settings dlg.
  5843. //
  5844. BOOL bCachedAccessPointsEnabled = pArgs->fAccessPointsEnabled;
  5845. int iRet = DoPropertiesPropSheets(hwndDlg, pArgs);
  5846. //
  5847. // We need to re-enumerate the access points and re-check connecting because
  5848. // the user may have added or deleted an access point and then hit cancel.
  5849. //
  5850. if (pArgs->hwndMainDlg)
  5851. {
  5852. if (bCachedAccessPointsEnabled != pArgs->fAccessPointsEnabled)
  5853. {
  5854. CMTRACE(TEXT("Access points state changed, returning to the main dialog which needs to relaunch itself with the proper template."));
  5855. iRet = ID_OK_RELAUNCH_MAIN_DLG;
  5856. }
  5857. else
  5858. {
  5859. //
  5860. // If the user canceled, then we want to set the accesspoint back to what it was on the main dialog
  5861. // since the user may have changed it on the properties dialog but then canceled.
  5862. //
  5863. if (pArgs->fAccessPointsEnabled)
  5864. {
  5865. if (0 == iRet) // user hit cancel
  5866. {
  5867. ChangedAccessPoint(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  5868. }
  5869. ShowAccessPointInfoFromReg(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO);
  5870. }
  5871. UINT nCtrlFocus;
  5872. CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  5873. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  5874. SetFocus(GetDlgItem(hwndDlg,nCtrlFocus));
  5875. }
  5876. }
  5877. CMTRACE(TEXT("End OnMainProperties()"));
  5878. return iRet;
  5879. }
  5880. //
  5881. // user pressed the cancel button!!!!!
  5882. //
  5883. void OnMainCancel(HWND hwndDlg,
  5884. ArgsStruct *pArgs)
  5885. {
  5886. CMTRACE1(TEXT("OnMainCancel(), state is %d"), pArgs->psState);
  5887. //
  5888. // Re-entrancy protection. If we're in the middle of a RasDial, wait 2 seconds.
  5889. // If the "semaphore" is still held, exit. (This is only likely to happen during
  5890. // a stress situation, so failing the cancel is acceptable.)
  5891. //
  5892. LONG lInConnectOrCancel;
  5893. int SleepTimeInMilliseconds = 0;
  5894. do
  5895. {
  5896. lInConnectOrCancel = InterlockedExchange(&(pArgs->lInConnectOrCancel), IN_CONNECT_OR_CANCEL);
  5897. CMASSERTMSG(((NOT_IN_CONNECT_OR_CANCEL == lInConnectOrCancel) || (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)),
  5898. TEXT("OnMainCancel - synch variable has unexpected value!"));
  5899. Sleep(50);
  5900. SleepTimeInMilliseconds += 50;
  5901. }
  5902. while ((IN_CONNECT_OR_CANCEL == lInConnectOrCancel) && (SleepTimeInMilliseconds < 2000));
  5903. if (IN_CONNECT_OR_CANCEL == lInConnectOrCancel)
  5904. {
  5905. CMTRACE(TEXT("OnMainCancel - waited 2 seconds for system for InRasDial mutex to be freed, leaving Cancel"));
  5906. return;
  5907. }
  5908. //
  5909. // Terminate Lana
  5910. //
  5911. if (PS_TunnelDialing == pArgs->psState && pArgs->uLanaMsgId)
  5912. {
  5913. MYDBGASSERT(OS_W9X);
  5914. PostMessageU(hwndDlg, pArgs->uLanaMsgId, 0, 0);
  5915. }
  5916. if (pArgs->psState != PS_Interactive && pArgs->psState != PS_Error)
  5917. {
  5918. pArgs->Log.Log(ONCANCEL_EVENT);
  5919. //
  5920. // Run OnCancel connect actions. If we are dialing, this is a cancel
  5921. // dialing event. Note: The assumption here is CM never post itself
  5922. // an IDCANCEL message when dialing
  5923. //
  5924. CActionList OnCancelActList;
  5925. OnCancelActList.Append(pArgs->piniService, c_pszCmSectionOnCancel);
  5926. //
  5927. // fStatusMsgOnFailure = FALSE
  5928. //
  5929. OnCancelActList.RunAccordType(hwndDlg, pArgs, FALSE);
  5930. }
  5931. switch (pArgs->psState)
  5932. {
  5933. case PS_Dialing:
  5934. case PS_TunnelDialing:
  5935. case PS_Authenticating:
  5936. case PS_TunnelAuthenticating:
  5937. // fall through
  5938. case PS_Pausing:
  5939. //
  5940. // we should also try to hangup for ps_pausing since cm could be
  5941. // in the middle or redialing the tunnel server. we need to
  5942. // hangup the first ppp connection.
  5943. //
  5944. //
  5945. // Set fWaitForComplete to TRUE.
  5946. // This will cause HangupCM to block until the ras handle is invalid.
  5947. // Otherwise, HangupCM will return while the device is in use.
  5948. //
  5949. HangupCM(pArgs,hwndDlg, TRUE); // fWaitForComplete = TRUE
  5950. //
  5951. // Display cancelled message
  5952. //
  5953. AppendStatusPane(hwndDlg, IDMSG_CANCELED);
  5954. SetInteractive(hwndDlg,pArgs);
  5955. break;
  5956. case PS_Online:
  5957. //
  5958. // If pArgs->fUseTunneling is TRUE, CM actually does not have the PS_Online state
  5959. //
  5960. MYDBGASSERT(!pArgs->fUseTunneling);
  5961. if (pArgs->fUseTunneling)
  5962. {
  5963. break;
  5964. }
  5965. case PS_TunnelOnline:
  5966. {
  5967. TCHAR szTmp[MAX_PATH];
  5968. MYVERIFY(GetModuleFileNameU(g_hInst, szTmp, MAX_PATH));
  5969. pArgs->Log.Log(DISCONNECT_EVENT, szTmp);
  5970. CActionList DisconnectActList;
  5971. DisconnectActList.Append(pArgs->piniService, c_pszCmSectionOnDisconnect);
  5972. //
  5973. // fStatusMsgOnFailure = FALSE
  5974. //
  5975. DisconnectActList.RunAccordType(hwndDlg, pArgs, FALSE);
  5976. HangupCM(pArgs,hwndDlg);
  5977. pArgs->dwExitCode = ERROR_CANCELLED;
  5978. // fall through
  5979. }
  5980. case PS_Error:
  5981. case PS_Interactive:
  5982. pArgs->dwExitCode = ERROR_CANCELLED;
  5983. EndMainDialog(hwndDlg, pArgs, 0); // FALSE);
  5984. break;
  5985. default:
  5986. MYDBGASSERT(FALSE);
  5987. break;
  5988. }
  5989. //
  5990. // We're definitely not waiting for a callback anymore.
  5991. //
  5992. pArgs->fWaitingForCallback = FALSE;
  5993. //
  5994. // We are exiting Cancel state
  5995. //
  5996. (void)InterlockedExchange(&(pArgs->lInConnectOrCancel), NOT_IN_CONNECT_OR_CANCEL);
  5997. }
  5998. void OnMainEnChange(HWND hwndDlg,
  5999. ArgsStruct *pArgs)
  6000. {
  6001. CheckConnect(hwndDlg, pArgs, NULL);
  6002. }
  6003. //+----------------------------------------------------------------------------
  6004. //
  6005. // Function: OnRasErrorMessage
  6006. //
  6007. // Synopsis: Process RAS error message
  6008. //
  6009. // Arguments: HWND hwndDlg - Main Dialog window handle
  6010. // ArgsStruct *pArgs -
  6011. // DWORD dwError - RAS error code
  6012. //
  6013. // Returns: Nothing
  6014. //
  6015. // History: fengsun Created Header 10/24/97
  6016. //
  6017. //+----------------------------------------------------------------------------
  6018. void OnRasErrorMessage(HWND hwndDlg,
  6019. ArgsStruct *pArgs,
  6020. DWORD dwError)
  6021. {
  6022. //
  6023. // Save off whether we are tunneling, before we change state
  6024. //
  6025. BOOL bTunneling = IsDialingTunnel(pArgs);
  6026. //
  6027. // Set the progstate to Error if user did not cancel dialing.
  6028. // Note: Set here to ensure that we don't inadvertantly update the status on
  6029. // timer ticks thereby overwriting the error message. Additionally we do this
  6030. // following SetInteractive in the no-redial case below.
  6031. //
  6032. if (ERROR_CANCELLED != dwError)
  6033. {
  6034. CMTRACE(TEXT("OnRasErrorMessage - Entering PS_Error state"));
  6035. pArgs->psState = PS_Error;
  6036. }
  6037. //
  6038. // Set the "ErrorCode" property
  6039. //
  6040. pArgs->dwExitCode = dwError;
  6041. lstrcpyU(pArgs->szLastErrorSrc, TEXT("RAS"));
  6042. pArgs->Log.Log(ONERROR_EVENT, pArgs->dwExitCode, pArgs->szLastErrorSrc);
  6043. //
  6044. // Run On-Error connect actions
  6045. //
  6046. CActionList OnErrorActList;
  6047. OnErrorActList.Append(pArgs->piniService, c_pszCmSectionOnError);
  6048. //
  6049. // fStatusMsgOnFailure = FALSE
  6050. //
  6051. OnErrorActList.RunAccordType(hwndDlg, pArgs, FALSE);
  6052. LPTSTR pszRasErrMsg = NULL;
  6053. //
  6054. // See if the error is recoverable (re-dialable)
  6055. // CheckConnectionError also display error msg in the status window
  6056. // Get the ras err msg also. we'll display it ourself.
  6057. //
  6058. BOOL bDoRedial = !CheckConnectionError(hwndDlg, dwError, pArgs, bTunneling, &pszRasErrMsg);
  6059. //
  6060. // Whether CM get ERROR_PORT_NOT_AVAILABLE because of modem change
  6061. //
  6062. BOOL fNewModem = FALSE;
  6063. if (dwError == ERROR_PORT_NOT_AVAILABLE && !IsDialingTunnel(pArgs))
  6064. {
  6065. //
  6066. // Modem is not avaliable. See if the modem is changed
  6067. //
  6068. BOOL fSameModem = TRUE;
  6069. if (PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName, &fSameModem))
  6070. {
  6071. if (!fSameModem)
  6072. {
  6073. //
  6074. // If the modem is changed, use the new modem.
  6075. // bDoRedial is still FALSE here so we will not
  6076. // increase redial count or use the backup number
  6077. //
  6078. fNewModem = TRUE;
  6079. }
  6080. }
  6081. //
  6082. // if PickModem failed, do not try to install modem here
  6083. // cnetcfg return ERROR_CANCELLED, even if modem is intalled
  6084. //
  6085. }
  6086. //
  6087. // should we try another tunnel dns addr?
  6088. //
  6089. BOOL fTryAnotherTunnelDnsAddr = FALSE;
  6090. if (bDoRedial)
  6091. {
  6092. //
  6093. // The error is recoverable
  6094. //
  6095. CMTRACE1(TEXT("OnRasErrorMessage - Recoverable error %u received."), dwError);
  6096. //
  6097. // If we're dialing a tunnel, try a different IP address on failure.
  6098. //
  6099. if (PS_TunnelDialing == pArgs->psState)
  6100. {
  6101. fTryAnotherTunnelDnsAddr = TryAnotherTunnelDnsAddress(pArgs);
  6102. }
  6103. //
  6104. // If we're trying a different IP, then don't count this as a normal
  6105. // redial. Otherwise, bump the indices and move on to the next number.
  6106. if (!fTryAnotherTunnelDnsAddr)
  6107. {
  6108. //
  6109. // we display the ras error only if:
  6110. // (1) we're not redialing OR
  6111. // (2) we're not redialing a tunnel OR
  6112. // (3) we're redialing a tunnel but NOT redialing with a different
  6113. // tunnel dns ip addr.
  6114. //
  6115. if (pszRasErrMsg)
  6116. {
  6117. AppendStatusPane(hwndDlg, pszRasErrMsg);
  6118. }
  6119. // should we redial?
  6120. //
  6121. if (pArgs->nRedialCnt)
  6122. {
  6123. //
  6124. // We have not reached the retry limit, try to redial
  6125. //
  6126. pArgs->nRedialCnt--;
  6127. pArgs->nDialIdx++;
  6128. //
  6129. // If ndx now matches count, or if the next number is empty
  6130. // (not dialable) this our last number to dial on this pass.
  6131. // Adjust the re-dial counter if it applies.
  6132. //
  6133. if (pArgs->nDialIdx == MAX_PHONE_NUMBERS ||
  6134. !pArgs->aDialInfo[pArgs->nDialIdx].szDialablePhoneNumber[0])
  6135. {
  6136. pArgs->nDialIdx = 0;
  6137. }
  6138. }
  6139. else
  6140. {
  6141. //
  6142. // Last redial try failed
  6143. //
  6144. bDoRedial = FALSE;
  6145. }
  6146. }
  6147. }
  6148. else
  6149. {
  6150. CMTRACE1(TEXT("OnRasErrorMessage - Non-recoverable error %u received."), dwError);
  6151. //
  6152. // we display the ras error only if:
  6153. // (1) we're not redialing OR
  6154. // (2) we're not redialing a tunnel OR
  6155. // (3) we're redialing a tunnel but NOT redialing with a different
  6156. // tunnel dns ip addr.
  6157. //
  6158. if (pszRasErrMsg)
  6159. {
  6160. AppendStatusPane(hwndDlg, pszRasErrMsg);
  6161. }
  6162. }
  6163. bDoRedial |= fNewModem; // fNewModem only true if not dialing tunnel
  6164. //
  6165. // Perform Hangup here
  6166. //
  6167. if (IsDialingTunnel(pArgs) && bDoRedial)
  6168. {
  6169. //
  6170. // For tunnel dialing, only hangup tunnel connection, Do not hangup
  6171. // PPP connection before retry.
  6172. //
  6173. MyRasHangup(pArgs,pArgs->hrcTunnelConn);
  6174. pArgs->hrcTunnelConn = NULL;
  6175. if (pArgs->IsDirectConnect())
  6176. {
  6177. //
  6178. // The statistic is stopped in HangupCM
  6179. // Since we do not call HangupCM, we have to close it here
  6180. //
  6181. if (pArgs->pConnStatistics)
  6182. {
  6183. pArgs->pConnStatistics->Close();
  6184. }
  6185. }
  6186. }
  6187. else
  6188. {
  6189. if (OS_NT)
  6190. {
  6191. HangupCM(pArgs, hwndDlg, FALSE, !bDoRedial);
  6192. }
  6193. else
  6194. {
  6195. //
  6196. // On win9x, in some PPP case, when CM get Tunnel RAS error message,
  6197. // RasHangup will not release the PPP RAS handle until this
  6198. // message returns. See bug 39718
  6199. //
  6200. PostMessageU(hwndDlg, WM_HANGUP_CM, !bDoRedial, dwError);
  6201. }
  6202. }
  6203. //
  6204. // If we want re-dial enter pause state, otherwise just SetInteractive
  6205. //
  6206. if (bDoRedial)
  6207. {
  6208. //
  6209. // If the state is PS_Error, we will use the timer we set before the call.
  6210. // However we will not check whether the timer expired here.
  6211. //
  6212. if (fTryAnotherTunnelDnsAddr)
  6213. {
  6214. //
  6215. // if we want to try another tunnel dns addr, we don't want to display
  6216. // any error msg or pause, just retry with another addr without the
  6217. // user realizing it.
  6218. //
  6219. pArgs->dwStateStartTime = GetTickCount() + (pArgs->nRedialDelay * 1000);
  6220. }
  6221. else
  6222. {
  6223. //
  6224. // NT #360488 - nickball
  6225. //
  6226. // Reset the timer so that we pause for the redial delay before
  6227. // trying to connect again. ErrorEx (now unused), conditioned this
  6228. // code on the error state not being PS_Error, however, this was
  6229. // broken when we started setting the state to PS_Error at the
  6230. // beginning of this function. Because ErrorEx is not longer used,
  6231. // we can restore the timer reset to all states.
  6232. //
  6233. pArgs->dwStateStartTime = GetTickCount();
  6234. pArgs->nLastSecondsDisplay = (UINT) -1;
  6235. }
  6236. pArgs->psState = PS_Pausing;
  6237. }
  6238. else
  6239. {
  6240. SetInteractive(hwndDlg,pArgs);
  6241. if (ERROR_CANCELLED != dwError)
  6242. {
  6243. CMTRACE(TEXT("OnRasErrorMessage - Restoring PS_Error state"));
  6244. pArgs->psState = PS_Error;
  6245. }
  6246. pArgs->dwExitCode = dwError;
  6247. // in 'unattended dial' mode, exit ICM
  6248. if (pArgs->dwFlags & FL_UNATTENDED)
  6249. {
  6250. PostMessageU(hwndDlg, WM_COMMAND, IDCANCEL, dwError);
  6251. }
  6252. }
  6253. if (pszRasErrMsg)
  6254. {
  6255. CmFree(pszRasErrMsg);
  6256. }
  6257. }
  6258. //+----------------------------------------------------------------------------
  6259. //
  6260. // Function: OnRasNotificationMessage
  6261. //
  6262. // Synopsis: Message handler for RAS status/error messages.
  6263. //
  6264. // Arguments: HWND hwndDlg - Main Dialog window handle
  6265. // ArgsStruct *pArgs - Ptr to global Args struct
  6266. // WPARAM wParam - RAS status message
  6267. // LPARAM lParam - RAS error message. ERROR_SUCCESS if none.
  6268. //
  6269. // Returns: Error code if applicable.
  6270. //
  6271. // History: nickball Created Header 05/19/99
  6272. //
  6273. //+----------------------------------------------------------------------------
  6274. DWORD OnRasNotificationMessage(HWND hwndDlg,
  6275. ArgsStruct *pArgs,
  6276. WPARAM wParam,
  6277. LPARAM lParam)
  6278. {
  6279. CMTRACE2(TEXT("OnRasNotificationMessage() wParam=%u, lParam=%u"), wParam, lParam);
  6280. if (pArgs->fIgnoreTimerRasMsg)
  6281. {
  6282. CMTRACE(TEXT("OnRasNotificationMessage() ignoring Ras and Timer messages"));
  6283. return ERROR_SUCCESS;
  6284. }
  6285. //
  6286. // If we have an error notification from RAS, handle it.
  6287. //
  6288. if (ERROR_SUCCESS != lParam)
  6289. {
  6290. //
  6291. // If 2nd subchannel on multilinked ISDN fails, default to single channel.
  6292. //
  6293. if (OS_NT5)
  6294. {
  6295. if ((pArgs->dwRasSubEntry > 1) &&
  6296. (CM_ISDN_MODE_DUALCHANNEL_FALLBACK == pArgs->dwIsdnDialMode))
  6297. {
  6298. PostMessageU(hwndDlg, WM_CONNECTED_CM,0,0);
  6299. return ERROR_SUCCESS;
  6300. }
  6301. }
  6302. //
  6303. // Skip PENDING notifications
  6304. //
  6305. if (PENDING == lParam)
  6306. {
  6307. CMTRACE(TEXT("OnRasNotificationMessage() Skipping PENDING notification."));
  6308. return ERROR_SUCCESS;
  6309. }
  6310. //
  6311. // If we're already in the interactive or error state, then
  6312. // ignore any subsequent error notifications from RAS.
  6313. //
  6314. // For example: RAS often sends a ERROR_USER_DISCONNECTION
  6315. // notification when we call RasHangup.
  6316. //
  6317. if (pArgs->psState == PS_Interactive || pArgs->psState == PS_Error)
  6318. {
  6319. CMTRACE1(TEXT("OnRasNotificationMessage() Ignoring error because pArgs->psState is %u."), pArgs->psState);
  6320. return ERROR_SUCCESS;
  6321. }
  6322. CMTRACE(TEXT("OnRasNotificationMessage() Handling error message."));
  6323. OnRasErrorMessage(hwndDlg, pArgs, (DWORD)lParam);
  6324. }
  6325. else
  6326. {
  6327. // We have a RAS status update, act accordingly
  6328. switch (wParam)
  6329. {
  6330. case RASCS_Authenticate:
  6331. CMTRACE(TEXT("RASCS_Authenticate"));
  6332. if (IsDialingTunnel(pArgs)) // PPTP dialing
  6333. pArgs->psState = PS_TunnelAuthenticating;
  6334. else
  6335. pArgs->psState = PS_Authenticating;
  6336. pArgs->dwStateStartTime = GetTickCount();
  6337. pArgs->nLastSecondsDisplay = (UINT) -1;
  6338. break;
  6339. case RASCS_Connected:
  6340. {
  6341. CMTRACE(TEXT("RASCS_Connected"));
  6342. //
  6343. // Post a message to ourselves to indicate that we are connected
  6344. //
  6345. PostMessageU(hwndDlg, WM_CONNECTED_CM,0,0);
  6346. break;
  6347. }
  6348. //
  6349. // Pause states are dealt with explicity below
  6350. //
  6351. case (RASCS_PAUSED + 4): // 4100 - RASCS_InvokeEapUI
  6352. case RASCS_Interactive:
  6353. case RASCS_RetryAuthentication:
  6354. case RASCS_CallbackSetByCaller:
  6355. case RASCS_PasswordExpired:
  6356. break;
  6357. //
  6358. // Callback handling states
  6359. //
  6360. case RASCS_PrepareForCallback:
  6361. pArgs->fWaitingForCallback = TRUE;
  6362. pArgs->psState = PS_Pausing;
  6363. break;
  6364. case RASCS_CallbackComplete:
  6365. pArgs->fWaitingForCallback = FALSE;
  6366. break;
  6367. //
  6368. // The following status codes are not handled explicitly
  6369. //
  6370. case RASCS_Disconnected:
  6371. break;
  6372. case RASCS_SubEntryConnected:
  6373. break;
  6374. case RASCS_SubEntryDisconnected:
  6375. break;
  6376. case RASCS_OpenPort:
  6377. break;
  6378. case RASCS_PortOpened:
  6379. break;
  6380. case RASCS_ConnectDevice:
  6381. break;
  6382. case RASCS_DeviceConnected:
  6383. break;
  6384. case RASCS_AllDevicesConnected:
  6385. break;
  6386. case RASCS_AuthNotify:
  6387. break;
  6388. case RASCS_AuthRetry:
  6389. break;
  6390. case RASCS_AuthCallback:
  6391. break;
  6392. case RASCS_AuthChangePassword:
  6393. break;
  6394. case RASCS_AuthProject:
  6395. break;
  6396. case RASCS_AuthLinkSpeed:
  6397. break;
  6398. case RASCS_AuthAck:
  6399. break;
  6400. case RASCS_ReAuthenticate:
  6401. break;
  6402. case RASCS_Authenticated:
  6403. break;
  6404. case RASCS_WaitForModemReset:
  6405. break;
  6406. case RASCS_WaitForCallback:
  6407. break;
  6408. case RASCS_Projected:
  6409. break;
  6410. case RASCS_StartAuthentication:
  6411. break;
  6412. case RASCS_LogonNetwork:
  6413. break;
  6414. default:
  6415. CMTRACE(TEXT("OnRasNotificationMessage() - message defaulted"));
  6416. break;
  6417. }
  6418. }
  6419. if (wParam & RASCS_PAUSED)
  6420. {
  6421. //
  6422. // Screen out unsupported states
  6423. //
  6424. switch (wParam)
  6425. {
  6426. case RASCS_Interactive: // for scripts -- NTRAID 378224
  6427. case (RASCS_PAUSED + 4): // 4100 - RASCS_InvokeEapUI
  6428. case RASCS_PasswordExpired:
  6429. case RASCS_RetryAuthentication:
  6430. case RASCS_CallbackSetByCaller:
  6431. PostMessageU(hwndDlg, WM_PAUSE_RASDIAL, wParam, lParam);
  6432. break;
  6433. default:
  6434. MYDBGASSERT(FALSE);
  6435. return (ERROR_INTERACTIVE_MODE); // unhandled pause state
  6436. }
  6437. }
  6438. return ERROR_SUCCESS;
  6439. }
  6440. // timer: check the current connection manager status, update the status message
  6441. // on the screen
  6442. void OnMainTimer(HWND hwndDlg,
  6443. ArgsStruct *pArgs)
  6444. {
  6445. //
  6446. // If timer ID is null, don't process messages
  6447. //
  6448. if (NULL == pArgs->nTimerId)
  6449. {
  6450. return;
  6451. }
  6452. //
  6453. // Timer is good, check StartupInfoLoad
  6454. //
  6455. LPTSTR pszMsg = NULL;
  6456. DWORD dwSeconds = (GetTickCount() - pArgs->dwStateStartTime) / 1000;
  6457. CheckStartupInfo(hwndDlg, pArgs);
  6458. // CMTRACE1(TEXT("OnMainTimer() pArgs->psState is %u"), pArgs->psState);
  6459. //
  6460. // Update future splash if any
  6461. //
  6462. MapStateToFrame(pArgs);
  6463. switch (pArgs->psState)
  6464. {
  6465. case PS_Dialing:
  6466. if (pArgs->nLastSecondsDisplay != dwSeconds)
  6467. {
  6468. pszMsg = CmFmtMsg(g_hInst,
  6469. IDMSG_DIALING,
  6470. pArgs->aDialInfo[pArgs->nDialIdx].szDisplayablePhoneNumber,
  6471. pArgs->szDeviceName,
  6472. dwSeconds);
  6473. //
  6474. // Clear the status window
  6475. //
  6476. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6477. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6478. }
  6479. break;
  6480. case PS_TunnelDialing:
  6481. if (pArgs->nLastSecondsDisplay != dwSeconds)
  6482. {
  6483. pszMsg = CmFmtMsg(g_hInst,
  6484. IDMSG_TUNNELDIALING,
  6485. pArgs->GetTunnelAddress(),
  6486. dwSeconds);
  6487. //
  6488. // Clear the status window
  6489. //
  6490. SetDlgItemText(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6491. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6492. }
  6493. break;
  6494. case PS_Pausing:
  6495. //
  6496. // Special case of pausing is when we're waiting for the server to call us back.
  6497. //
  6498. if (pArgs->fWaitingForCallback)
  6499. {
  6500. //
  6501. // Notify the user of this fact
  6502. //
  6503. pszMsg = CmFmtMsg(g_hInst,
  6504. IDMSG_WAITING_FOR_CALLBACK,
  6505. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  6506. //
  6507. // Clear the status window
  6508. //
  6509. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6510. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6511. break;
  6512. }
  6513. if (GetTickCount()-pArgs->dwStateStartTime <= pArgs->nRedialDelay * 1000)
  6514. {
  6515. //
  6516. // Update the display if not timeout
  6517. //
  6518. if (pArgs->nLastSecondsDisplay != dwSeconds)
  6519. {
  6520. pszMsg = CmFmtMsg(g_hInst,IDMSG_PAUSING,dwSeconds);
  6521. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6522. }
  6523. }
  6524. else
  6525. {
  6526. DWORD dwRes;
  6527. if (pArgs->IsDirectConnect() || pArgs->hrcRasConn != NULL)
  6528. {
  6529. //
  6530. // For the first tunnel try, CM does not hangup ppp connection
  6531. //
  6532. MYDBGASSERT(pArgs->fUseTunneling);
  6533. pArgs->psState = PS_TunnelDialing;
  6534. pArgs->dwStateStartTime = GetTickCount();
  6535. pArgs->nLastSecondsDisplay = (UINT) -1;
  6536. dwRes = DoTunnelDial(hwndDlg,pArgs);
  6537. //
  6538. // Update the status right away because there are times
  6539. // that things happen so quickly that the main status
  6540. // display doesn't have a chance to display the tunnel
  6541. // dialing info...
  6542. //
  6543. pszMsg = CmFmtMsg(g_hInst,
  6544. IDMSG_TUNNELDIALING,
  6545. pArgs->GetTunnelAddress(),
  6546. 0);
  6547. //
  6548. // Clear the status window
  6549. //
  6550. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6551. }
  6552. else
  6553. {
  6554. dwRes = DoRasDial(hwndDlg,pArgs,pArgs->nDialIdx);
  6555. }
  6556. if (dwRes == ERROR_SUCCESS)
  6557. {
  6558. MapStateToFrame(pArgs);
  6559. pArgs->dwStateStartTime = GetTickCount();
  6560. pArgs->nLastSecondsDisplay = (UINT) -1;
  6561. }
  6562. else
  6563. {
  6564. HangupCM(pArgs, hwndDlg);
  6565. UpdateError(pArgs, dwRes);
  6566. SetLastError(dwRes);
  6567. }
  6568. }
  6569. break;
  6570. case PS_Authenticating:
  6571. if (pArgs->nLastSecondsDisplay != dwSeconds)
  6572. {
  6573. //
  6574. // Get the appropriate username based on whether we're
  6575. // tunneling and using the same credentials for dial-up.
  6576. //
  6577. LPTSTR pszTmpUserName;
  6578. if (pArgs->fUseTunneling && (!pArgs->fUseSameUserName))
  6579. {
  6580. pszTmpUserName = pArgs->szInetUserName;
  6581. }
  6582. else
  6583. {
  6584. pszTmpUserName = pArgs->szUserName;
  6585. }
  6586. //
  6587. // If username is still blank, use the RasDialParams as a
  6588. // backup. This can occur in cases such as EAP
  6589. //
  6590. if (TEXT('\0') == *pszTmpUserName)
  6591. {
  6592. pszTmpUserName = pArgs->pRasDialParams->szUserName;
  6593. }
  6594. pszMsg = CmFmtMsg(g_hInst,
  6595. IDMSG_CHECKINGPASSWORD,
  6596. pszTmpUserName,
  6597. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  6598. //
  6599. // Clear the status window
  6600. //
  6601. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6602. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6603. }
  6604. break;
  6605. case PS_TunnelAuthenticating:
  6606. if (pArgs->nLastSecondsDisplay != dwSeconds)
  6607. {
  6608. LPTSTR pszTmpUserName = pArgs->szUserName;
  6609. //
  6610. // If username is still blank, use the RasDialParams as a
  6611. // backup. This can occur in cases such as EAP
  6612. //
  6613. if (TEXT('\0') == *pszTmpUserName)
  6614. {
  6615. pszTmpUserName = pArgs->pRasDialParams->szUserName;
  6616. }
  6617. pszMsg = CmFmtMsg(g_hInst,
  6618. IDMSG_CHECKINGPASSWORD,
  6619. pszTmpUserName,
  6620. (GetTickCount()-pArgs->dwStateStartTime)/1000);
  6621. //
  6622. // Clear the status window
  6623. //
  6624. SetDlgItemTextU(hwndDlg, IDC_MAIN_STATUS_DISPLAY, TEXT(""));
  6625. pArgs->nLastSecondsDisplay = (UINT) dwSeconds;
  6626. }
  6627. break;
  6628. case PS_Online:
  6629. //
  6630. // If pArgs->fUseTunneling is TRUE, CM actually does not have the PS_Online state
  6631. //
  6632. MYDBGASSERT(!pArgs->fUseTunneling);
  6633. case PS_TunnelOnline:
  6634. //
  6635. // The dialog should be ended by now
  6636. //
  6637. MYDBGASSERT(!"The dialog should be ended by now");
  6638. break;
  6639. case PS_Error:
  6640. case PS_Interactive:
  6641. default:
  6642. break;
  6643. }
  6644. // If we have a status message as a result of the above, display it
  6645. if (pszMsg)
  6646. {
  6647. AppendStatusPane(hwndDlg,pszMsg);
  6648. CmFree(pszMsg);
  6649. }
  6650. }
  6651. //
  6652. // MainDlgProc: main dialog box message processing function
  6653. //
  6654. INT_PTR CALLBACK MainDlgProc(HWND hwndDlg,
  6655. UINT uMsg,
  6656. WPARAM wParam,
  6657. LPARAM lParam)
  6658. {
  6659. ArgsStruct *pArgs = (ArgsStruct *) GetWindowLongU(hwndDlg,DWLP_USER);
  6660. static const DWORD adwHelp[] = {IDC_MAIN_NOPROMPT_CHECKBOX, IDH_LOGON_AUTOCONN,
  6661. IDC_MAIN_NOPASSWORD_CHECKBOX, IDH_LOGON_SAVEPW,
  6662. IDC_MAIN_USERNAME_STATIC,IDH_LOGON_NAME,
  6663. IDC_MAIN_USERNAME_EDIT,IDH_LOGON_NAME,
  6664. IDC_MAIN_PASSWORD_STATIC,IDH_LOGON_PSWD,
  6665. IDC_MAIN_PASSWORD_EDIT,IDH_LOGON_PSWD,
  6666. IDC_MAIN_DOMAIN_STATIC, IDH_LOGON_DOMAIN,
  6667. IDC_MAIN_DOMAIN_EDIT, IDH_LOGON_DOMAIN,
  6668. IDC_MAIN_RESET_PASSWORD, IDH_LOGON_NEW,
  6669. IDC_MAIN_MESSAGE_DISPLAY,IDH_LOGON_SVCMSG,
  6670. IDC_MAIN_STATUS_LABEL,IDH_LOGON_CONNECT_STAT,
  6671. IDC_MAIN_STATUS_DISPLAY,IDH_LOGON_CONNECT_STAT,
  6672. IDOK,IDH_LOGON_CONNECT,
  6673. IDCANCEL,IDH_LOGON_CANCEL,
  6674. IDC_MAIN_PROPERTIES_BUTTON,IDH_LOGON_PROPERTIES,
  6675. IDC_MAIN_HELP_BUTTON,IDH_CMHELP,
  6676. IDC_MAIN_ACCESSPOINT_COMBO, IDH_LOGON_ACCESSPOINTS,
  6677. IDC_MAIN_ACCESSPOINT_STATIC, IDH_LOGON_ACCESSPOINTS,
  6678. IDC_OPT_CREDS_SINGLE_USER, IDH_LOGON_SAVEFORME,
  6679. IDC_OPT_CREDS_ALL_USER, IDH_LOGON_SAVEFORALL,
  6680. 0,0};
  6681. //
  6682. // Dialog box message processing
  6683. //
  6684. switch (uMsg)
  6685. {
  6686. case WM_PAINT:
  6687. CheckStartupInfo(hwndDlg, pArgs);
  6688. break;
  6689. case WM_INITDIALOG:
  6690. CM_SET_TIMING_INTERVAL("WM_INITDIALOG - Begin");
  6691. UpdateFont(hwndDlg);
  6692. //
  6693. // Extract args and perform main initialization
  6694. //
  6695. pArgs = (ArgsStruct *) lParam;
  6696. if (pArgs)
  6697. {
  6698. pArgs->hwndMainDlg = hwndDlg;
  6699. }
  6700. SetWindowLongU(hwndDlg,DWLP_USER, (LONG_PTR) pArgs);
  6701. OnMainInit(hwndDlg, pArgs);
  6702. CM_SET_TIMING_INTERVAL("WM_INITDIALOG - End");
  6703. return (FALSE);
  6704. case WM_ENDSESSION:
  6705. //
  6706. // Windows system is shutting down or logging off
  6707. //
  6708. if ((BOOL)wParam == TRUE)
  6709. {
  6710. //
  6711. // Just cancel
  6712. //
  6713. OnMainCancel(hwndDlg, pArgs);
  6714. }
  6715. return 0;
  6716. case WM_COMMAND:
  6717. switch (LOWORD(wParam))
  6718. {
  6719. case IDOK:
  6720. OnMainConnect(hwndDlg,pArgs);
  6721. //
  6722. // Check if there is an error, and if it's unattended dial,
  6723. // we just exit silently -- byao 5/9/97
  6724. //
  6725. if ((PS_Interactive == pArgs->psState || PS_Error == pArgs->psState) &&
  6726. (pArgs->dwFlags & FL_UNATTENDED))
  6727. {
  6728. OnMainCancel(hwndDlg, pArgs);
  6729. }
  6730. return (TRUE);
  6731. case IDC_MAIN_PROPERTIES_BUTTON:
  6732. if (ID_OK_RELAUNCH_MAIN_DLG == OnMainProperties(hwndDlg,pArgs))
  6733. {
  6734. //
  6735. // We want to relaunch the logon UI with Access Points enabled or disabled depending
  6736. // on the change the user made in the properties dialog.
  6737. //
  6738. EndMainDialog(hwndDlg, pArgs, ID_OK_RELAUNCH_MAIN_DLG);
  6739. }
  6740. return (TRUE);
  6741. case IDC_MAIN_HELP_BUTTON:
  6742. {
  6743. UINT nCtrlFocus = IsWindowEnabled(GetDlgItem(hwndDlg,IDOK)) ? IDOK : IDCANCEL;
  6744. CmWinHelp(hwndDlg,hwndDlg,pArgs->pszHelpFile,HELP_FORCEFILE,0);
  6745. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  6746. return (TRUE);
  6747. }
  6748. case IDC_MAIN_NOPROMPT_CHECKBOX:
  6749. pArgs->fDialAutomatically = !pArgs->fDialAutomatically;
  6750. if (TRUE == pArgs->fDialAutomatically)
  6751. {
  6752. MYDBGASSERT(!pArgs->fHideDialAutomatically);
  6753. //
  6754. // Display message explaining Dial Automatically
  6755. //
  6756. LPTSTR pszTmp = pArgs->piniService->GPPS(c_pszCmSection,
  6757. c_pszCmEntryDialAutoMessage);
  6758. if (pszTmp && *pszTmp)
  6759. {
  6760. MessageBoxEx(hwndDlg,
  6761. pszTmp,
  6762. pArgs->szServiceName,
  6763. MB_OK|MB_ICONWARNING,
  6764. LANG_USER_DEFAULT);
  6765. }
  6766. CmFree(pszTmp);
  6767. }
  6768. break;
  6769. case IDC_MAIN_NOPASSWORD_CHECKBOX:
  6770. pArgs->fRememberMainPassword = !(pArgs->fRememberMainPassword);
  6771. if (!pArgs->piniService->GPPB(c_pszCmSection,
  6772. c_pszCmEntryPwdOptional))
  6773. {
  6774. //
  6775. // If password is not optional, enable/disable
  6776. // Dial Automatically according to state of
  6777. // "Remember password"
  6778. //
  6779. EnableWindow(GetDlgItem(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX),
  6780. pArgs->fRememberMainPassword);
  6781. if (FALSE == pArgs->fRememberMainPassword)
  6782. {
  6783. //
  6784. // Reset Dial Automatically if user
  6785. // unchecks Save Password and password
  6786. // is not optional
  6787. //
  6788. CheckDlgButton(hwndDlg, IDC_MAIN_NOPROMPT_CHECKBOX, FALSE);
  6789. pArgs->fDialAutomatically = FALSE;
  6790. if (pArgs->fGlobalCredentialsSupported)
  6791. {
  6792. //
  6793. // Also disable the option buttons
  6794. //
  6795. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), FALSE);
  6796. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), FALSE);
  6797. }
  6798. //
  6799. // Since we aren't remembering the main password
  6800. // see if we need to not remember Inet passwords
  6801. //
  6802. if (pArgs->fUseSameUserName)
  6803. {
  6804. pArgs->fRememberInetPassword = FALSE;
  6805. CmWipePassword(pArgs->szInetPassword);
  6806. }
  6807. //
  6808. // If the password edit hasn't been edited by the user, then we
  6809. // mostly likely have 16 *'s which doesn't help the user when
  6810. // they try to connect. Thus we need to clear the edit box
  6811. //
  6812. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  6813. if (hwndPassword)
  6814. {
  6815. pArgs->fIgnoreChangeNotification = TRUE;
  6816. BOOL fPWFieldModified = (BOOL) SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L);
  6817. if (FALSE == fPWFieldModified)
  6818. {
  6819. CmWipePassword(pArgs->szPassword);
  6820. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  6821. }
  6822. pArgs->fIgnoreChangeNotification = FALSE;
  6823. }
  6824. }
  6825. else
  6826. {
  6827. //
  6828. // Save Password option is Enabled
  6829. //
  6830. if (pArgs->fGlobalCredentialsSupported)
  6831. {
  6832. //
  6833. // Also enable the option buttons
  6834. //
  6835. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_SINGLE_USER), TRUE);
  6836. EnableWindow(GetDlgItem(hwndDlg, IDC_OPT_CREDS_ALL_USER), TRUE);
  6837. }
  6838. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  6839. if (hwndPassword)
  6840. {
  6841. BOOL fPWFieldModified = (BOOL) SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L);
  6842. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  6843. {
  6844. //
  6845. // Try to reload current creds now that the user has enabled the save
  6846. // password option, unless the password field has been edited
  6847. //
  6848. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_CHECKED);
  6849. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_UNCHECKED);
  6850. if (FALSE == fPWFieldModified)
  6851. {
  6852. //
  6853. // Set the 3rd param to TRUE in order to bypass the check
  6854. // that it's called when we are in the local credential mode.
  6855. //
  6856. SwitchToGlobalCreds(pArgs, hwndDlg, TRUE);
  6857. }
  6858. }
  6859. else
  6860. {
  6861. if (pArgs->fGlobalCredentialsSupported)
  6862. {
  6863. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_UNCHECKED);
  6864. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_CHECKED);
  6865. }
  6866. if (FALSE == fPWFieldModified)
  6867. {
  6868. //
  6869. // Set the 3rd param to TRUE in order to bypass the check
  6870. // that it's called when we are in the global credential mode.
  6871. //
  6872. SwitchToLocalCreds(pArgs, hwndDlg, TRUE);
  6873. }
  6874. }
  6875. }
  6876. }
  6877. }
  6878. break;
  6879. case IDC_OPT_CREDS_SINGLE_USER:
  6880. {
  6881. //
  6882. // FALSE - allows the function to only execute if we are currently using
  6883. // the global credential store and the user now wants to switch.
  6884. //
  6885. SwitchToLocalCreds(pArgs, hwndDlg, FALSE);
  6886. break;
  6887. }
  6888. case IDC_OPT_CREDS_ALL_USER:
  6889. {
  6890. //
  6891. // FALSE - allows the function to only execute if we are currently using
  6892. // the local credential store and the user now wants to switch.
  6893. //
  6894. SwitchToGlobalCreds(pArgs, hwndDlg, FALSE);
  6895. break;
  6896. }
  6897. case IDC_MAIN_RESET_PASSWORD:
  6898. OnResetPassword(hwndDlg, pArgs);
  6899. break;
  6900. case IDC_MAIN_CUSTOM:
  6901. OnCustom(hwndDlg, pArgs);
  6902. break;
  6903. case IDCANCEL:
  6904. OnMainCancel(hwndDlg,pArgs);
  6905. return (TRUE);
  6906. case IDC_MAIN_PASSWORD_EDIT:
  6907. case IDC_MAIN_USERNAME_EDIT:
  6908. case IDC_MAIN_DOMAIN_EDIT:
  6909. if ((HIWORD(wParam) == EN_CHANGE))
  6910. {
  6911. if (!pArgs->fIgnoreChangeNotification)
  6912. {
  6913. OnMainEnChange(hwndDlg,pArgs);
  6914. return (TRUE);
  6915. }
  6916. }
  6917. break;
  6918. case IDC_MAIN_ACCESSPOINT_COMBO:
  6919. if (CBN_SELENDOK == HIWORD(wParam))
  6920. {
  6921. if (ChangedAccessPoint(pArgs, hwndDlg, IDC_MAIN_ACCESSPOINT_COMBO))
  6922. {
  6923. UINT nCtrlFocus;
  6924. CheckConnect(hwndDlg,pArgs,&nCtrlFocus);
  6925. MainSetDefaultButton(hwndDlg,nCtrlFocus);
  6926. }
  6927. }
  6928. default:
  6929. break;
  6930. }
  6931. break;
  6932. case WM_HELP:
  6933. CmWinHelp((HWND) (((LPHELPINFO) lParam)->hItemHandle),
  6934. (HWND) (((LPHELPINFO) lParam)->hItemHandle),
  6935. pArgs->pszHelpFile,
  6936. HELP_WM_HELP,
  6937. (ULONG_PTR) (LPSTR) adwHelp);
  6938. return (TRUE);
  6939. case WM_CONTEXTMENU:
  6940. {
  6941. POINT pt = {LOWORD(lParam), HIWORD(lParam)};
  6942. HWND hwndCtrl;
  6943. ScreenToClient(hwndDlg, &pt);
  6944. hwndCtrl = ChildWindowFromPoint(hwndDlg, pt);
  6945. if (!hwndCtrl || HaveContextHelp(hwndDlg, hwndCtrl))
  6946. {
  6947. CmWinHelp((HWND) wParam,
  6948. hwndCtrl,
  6949. pArgs->pszHelpFile,
  6950. HELP_CONTEXTMENU,
  6951. (ULONG_PTR)adwHelp);
  6952. }
  6953. return (TRUE);
  6954. }
  6955. case WM_SIZE:
  6956. //
  6957. // Dynamicly Enable/Disable system menu
  6958. //
  6959. {
  6960. HMENU hMenu = GetSystemMenu(hwndDlg, FALSE);
  6961. MYDBGASSERT(hMenu);
  6962. //
  6963. // if the dlg is minimized, then disable the minimized menu
  6964. //
  6965. if (wParam == SIZE_MINIMIZED)
  6966. {
  6967. EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_GRAYED);
  6968. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_ENABLED);
  6969. }
  6970. else if (wParam != SIZE_MAXHIDE && wParam != SIZE_MAXSHOW)
  6971. {
  6972. EnableMenuItem(hMenu, SC_MINIMIZE, MF_BYCOMMAND | MF_ENABLED);
  6973. EnableMenuItem(hMenu, SC_RESTORE, MF_BYCOMMAND | MF_GRAYED);
  6974. }
  6975. }
  6976. break;
  6977. case WM_TIMER:
  6978. //
  6979. // Ignore the timer, if a (pre)connect action is running
  6980. //
  6981. if (!pArgs->fIgnoreTimerRasMsg)
  6982. {
  6983. OnMainTimer(hwndDlg,pArgs);
  6984. }
  6985. break;
  6986. case WM_PALETTEISCHANGING:
  6987. CMTRACE2(TEXT("MainDlgProc() got WM_PALETTEISCHANGING message, wParam=0x%x, hwndDlg=0x%x."),
  6988. wParam, hwndDlg);
  6989. break;
  6990. case WM_PALETTECHANGED:
  6991. {
  6992. //
  6993. // If its not our window that changed the palette, and we have a bitmap
  6994. //
  6995. if (IsWindowVisible(hwndDlg) && (wParam != (WPARAM) hwndDlg) && pArgs->BmpData.hDIBitmap)
  6996. {
  6997. //
  6998. // Handle the palette change.
  6999. //
  7000. // Note: We used to pass a flag indicating whether another
  7001. // bitmap was being displayed, but given that we select the
  7002. // paletted as a background app. this is no longer needed
  7003. //
  7004. CMTRACE2(TEXT("MainDlgProc() handling WM_PALETTECHANGED message, wParam=0x%x, hwndDlg=0x%x."),
  7005. wParam, hwndDlg);
  7006. PaletteChanged(&pArgs->BmpData, hwndDlg, IDC_MAIN_BITMAP);
  7007. }
  7008. return TRUE;
  7009. }
  7010. case WM_QUERYNEWPALETTE:
  7011. if (IsWindowVisible(hwndDlg))
  7012. {
  7013. CMTRACE2(TEXT("MainDlgProc() handling WM_QUERYNEWPALETTE message, wParam=0x%x, hwndDlg=0x%x."),
  7014. wParam, hwndDlg);
  7015. QueryNewPalette(&pArgs->BmpData, hwndDlg, IDC_MAIN_BITMAP);
  7016. }
  7017. return TRUE;
  7018. case WM_LOADSTARTUPINFO:
  7019. OnMainLoadStartupInfo(hwndDlg, pArgs);
  7020. break;
  7021. case WM_HANGUP_CM:
  7022. MYDBGASSERT(OS_W9X);
  7023. HangupCM(pArgs, hwndDlg, FALSE, (BOOL)wParam);
  7024. break;
  7025. case WM_CONNECTED_CM:
  7026. OnConnectedCM(hwndDlg, pArgs);
  7027. break;
  7028. case WM_PAUSE_RASDIAL:
  7029. OnPauseRasDial(hwndDlg, pArgs, wParam, lParam);
  7030. break;
  7031. default:
  7032. break;
  7033. }
  7034. if (pArgs && (uMsg == pArgs->uMsgId))
  7035. {
  7036. OnRasNotificationMessage(hwndDlg, pArgs, wParam, lParam);
  7037. return (TRUE);
  7038. }
  7039. return (FALSE);
  7040. }
  7041. //+---------------------------------------------------------------------------
  7042. //
  7043. // Function: ProcessCleanup
  7044. //
  7045. // Synopsis: Helper function to encapsulate closing Watch process handles
  7046. //
  7047. // Arguments: pArgs - pointer to global args struct
  7048. //
  7049. // Returns: Nothing
  7050. //
  7051. // History: a-nichb - Created - 4/30/97
  7052. //
  7053. //----------------------------------------------------------------------------
  7054. void ProcessCleanup(ArgsStruct* pArgs)
  7055. {
  7056. BOOL bRes;
  7057. if (pArgs->phWatchProcesses)
  7058. {
  7059. DWORD dwIdx;
  7060. for (dwIdx=0;pArgs->phWatchProcesses[dwIdx];dwIdx++)
  7061. {
  7062. bRes = CloseHandle(pArgs->phWatchProcesses[dwIdx]);
  7063. #ifdef DEBUG
  7064. if (!bRes)
  7065. {
  7066. CMTRACE1(TEXT("ProcessCleanup() CloseHandle() failed, GLE=%u."), GetLastError());
  7067. }
  7068. #endif
  7069. }
  7070. CmFree(pArgs->phWatchProcesses);
  7071. }
  7072. }
  7073. //+---------------------------------------------------------------------------
  7074. //
  7075. // Function: CheckProfileIntegrity
  7076. //
  7077. // Synopsis: Helper function to verify that we have valid profile.
  7078. // Verifies that we have a .CMP file name and that the
  7079. // .CMS file exists.
  7080. //
  7081. // Arguments: pArgs - pointer to global args struct
  7082. //
  7083. // Returns: TRUE if profile is valid
  7084. //
  7085. // History: a-nichb - Created - 5/8/97
  7086. // byao - Modified - 6/3/97 Added CMS/CMP file version check
  7087. //----------------------------------------------------------------------------
  7088. BOOL CheckProfileIntegrity(ArgsStruct* pArgs)
  7089. {
  7090. LPTSTR pszTmp = NULL;
  7091. LPCTSTR pszCmsFile = NULL;
  7092. DWORD dwCmsVersion, dwCmpVersion, dwCmVersion;
  7093. int iMsgId = 0;
  7094. //
  7095. // Make sure that we have a profile name and a CMS that exists
  7096. //
  7097. if (!(*pArgs->piniProfile->GetFile()))
  7098. {
  7099. iMsgId = IDMSG_DAMAGED_PROFILE;
  7100. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run without a .cmp file."));
  7101. }
  7102. //
  7103. // If profile is good, check CMS
  7104. //
  7105. if (0 == iMsgId)
  7106. {
  7107. pszCmsFile = pArgs->piniService->GetFile();
  7108. if (!*pszCmsFile || FALSE == FileExists(pszCmsFile))
  7109. {
  7110. iMsgId = IDMSG_DAMAGED_PROFILE;
  7111. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run without a valid .cms file."));
  7112. }
  7113. }
  7114. //
  7115. // Now check the CMS/CMP file version
  7116. //
  7117. if (0 == iMsgId)
  7118. {
  7119. dwCmsVersion = pArgs->piniService->GPPI(c_pszCmSectionProfileFormat, c_pszVersion);
  7120. dwCmpVersion = pArgs->piniProfile->GPPI(c_pszCmSectionProfileFormat, c_pszVersion);
  7121. if (dwCmsVersion != dwCmpVersion)
  7122. {
  7123. iMsgId = IDMSG_DAMAGED_PROFILE;
  7124. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run with different version numbers."));
  7125. }
  7126. if (0 == iMsgId)
  7127. {
  7128. if (dwCmsVersion > PROFILEVERSION || dwCmpVersion > PROFILEVERSION)
  7129. {
  7130. //
  7131. // CM has older version than either CMS or CMP file
  7132. //
  7133. iMsgId = IDMSG_WRONG_PROFILE_VERSION;
  7134. CMASSERTMSG(FALSE, TEXT("CheckProfileIntegrity() can't run with a newer CMS/CMP file."));
  7135. }
  7136. }
  7137. }
  7138. //
  7139. // Report any problems to the user
  7140. //
  7141. if (iMsgId)
  7142. {
  7143. pszTmp = CmFmtMsg(g_hInst, iMsgId);
  7144. MessageBoxEx(NULL, pszTmp, pArgs->szServiceName, MB_OK|MB_ICONSTOP, LANG_USER_DEFAULT);//13309
  7145. CmFree(pszTmp);
  7146. pArgs->dwExitCode = ERROR_WRONG_INFO_SPECIFIED;
  7147. return FALSE;
  7148. }
  7149. return TRUE;
  7150. }
  7151. //+----------------------------------------------------------------------------
  7152. //
  7153. // Function: GetConnectType
  7154. //
  7155. // Synopsis: Encapsulates determination of connect type based upon tunneling,
  7156. // etc.
  7157. //
  7158. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  7159. //
  7160. // Returns: Nothing
  7161. //
  7162. // History: nickball Created 2/9/98
  7163. //
  7164. //+----------------------------------------------------------------------------
  7165. void GetConnectType(ArgsStruct *pArgs)
  7166. {
  7167. //
  7168. // If tunneling is not enabled, the decision is a simple one
  7169. //
  7170. if (!IsTunnelEnabled(pArgs))
  7171. {
  7172. //
  7173. // Only support dial-up, if tunnel is not enabled
  7174. //
  7175. pArgs->SetBothConnTypeSupported(FALSE);
  7176. pArgs->SetDirectConnect(FALSE);
  7177. }
  7178. else
  7179. {
  7180. //
  7181. // Load connection type info for CM 1.1, default is support both
  7182. //
  7183. int iSupportDialup = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDialup, 1);
  7184. int iSupportDirect = pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryDirect, 1);
  7185. if (iSupportDialup == TRUE && iSupportDirect == TRUE)
  7186. {
  7187. pArgs->SetBothConnTypeSupported(TRUE);
  7188. if (pArgs->piniBoth->GPPI(c_pszCmSection, c_pszCmEntryConnectionType, 0))
  7189. {
  7190. pArgs->SetDirectConnect(TRUE);
  7191. }
  7192. else
  7193. {
  7194. pArgs->SetDirectConnect(FALSE);
  7195. }
  7196. }
  7197. else
  7198. {
  7199. pArgs->SetBothConnTypeSupported(FALSE);
  7200. pArgs->SetDirectConnect(iSupportDirect == TRUE);
  7201. }
  7202. }
  7203. }
  7204. //+----------------------------------------------------------------------------
  7205. //
  7206. // Function: _ArgsStruct::GetTypeOfConnection
  7207. //
  7208. // Synopsis: Figures out what type of connection we are doing (dialup,
  7209. // double dial, or direct) and returns one of the connection define
  7210. // values listed in icm.h.
  7211. //
  7212. // Arguments: None
  7213. //
  7214. // Returns: DWORD - value indicating the type of connection, see icm.h for values
  7215. //
  7216. // History: quintinb Created 04/20/00
  7217. //
  7218. //+----------------------------------------------------------------------------
  7219. DWORD _ArgsStruct::GetTypeOfConnection()
  7220. {
  7221. DWORD dwType = 0;
  7222. if (this->IsDirectConnect())
  7223. {
  7224. return DIRECT_CONNECTION;
  7225. }
  7226. else
  7227. {
  7228. //
  7229. // Its not direct, so see if the primary phone
  7230. // number is for a tunneling scenario.
  7231. //
  7232. if (this->fUseTunneling) // Ambiguous during Pre-Init action.
  7233. {
  7234. return DOUBLE_DIAL_CONNECTION;
  7235. }
  7236. else
  7237. {
  7238. return DIAL_UP_CONNECTION;
  7239. }
  7240. }
  7241. }
  7242. //+----------------------------------------------------------------------------
  7243. //
  7244. // Function: _ArgsStruct::GetProperty
  7245. //
  7246. // Synopsis: get the cm property by name
  7247. // This function is used by connect actions
  7248. //
  7249. // Arguments: const TCHAR* pszName - name of the property
  7250. // BOOL *pbValidPropertyName - ptr to bool to indicate validity of property
  7251. //
  7252. // Returns: LPTSTR - Value of the property. Caller should use CmFree
  7253. // to free the memory
  7254. //
  7255. // History: fengsun Created Header 07/07/98
  7256. // nickball pbValidPropertyName 07/27/99
  7257. //
  7258. //+----------------------------------------------------------------------------
  7259. LPTSTR _ArgsStruct::GetProperty(const TCHAR* pszName, BOOL *pbValidPropertyName)
  7260. {
  7261. *pbValidPropertyName = TRUE;
  7262. //
  7263. // This function could be called with in RasCustomHangup.
  7264. // Some information of pArgs may bot be loaded
  7265. //
  7266. MYDBGASSERT(pszName);
  7267. MYDBGASSERT(pszName[0]);
  7268. if (pszName == NULL)
  7269. {
  7270. return NULL;
  7271. }
  7272. //
  7273. // Type - Dial-up only, VPN only, double-dial
  7274. //
  7275. if (lstrcmpiU(pszName, TEXT("ConnectionType")) == 0)
  7276. {
  7277. LPTSTR pszValue = (LPTSTR)CmMalloc(64*sizeof(TCHAR)); // large enough to hold the error code
  7278. MYDBGASSERT(pszValue);
  7279. if (pszValue)
  7280. {
  7281. wsprintfU(pszValue, TEXT("%u"), this->GetTypeOfConnection());
  7282. }
  7283. return pszValue;
  7284. }
  7285. //
  7286. // UserPrefix
  7287. //
  7288. if (lstrcmpiU(pszName,TEXT("UserPrefix")) == 0)
  7289. {
  7290. LPTSTR pszUsernamePrefix = NULL;
  7291. LPTSTR pszUsernameSuffix = NULL;
  7292. //
  7293. // Retrieve the suffix and prefix as they are a logical pair,
  7294. // but we only return the allocated PREFIX in this case.
  7295. //
  7296. CIni *piniService = GetAppropriateIniService(this, this->nDialIdx);
  7297. GetPrefixSuffix(this, piniService, &pszUsernamePrefix, &pszUsernameSuffix);
  7298. CmFree(pszUsernameSuffix);
  7299. delete piniService;
  7300. return pszUsernamePrefix;
  7301. }
  7302. //
  7303. // UserSuffix
  7304. //
  7305. if (lstrcmpiU(pszName,TEXT("UserSuffix")) == 0)
  7306. {
  7307. LPTSTR pszUsernamePrefix = NULL;
  7308. LPTSTR pszUsernameSuffix = NULL;
  7309. //
  7310. // Retrieve the suffix and prefix as they are a logical pair,
  7311. // but we only return the allocated SUFFIX in this case.
  7312. //
  7313. CIni *piniService = GetAppropriateIniService(this, this->nDialIdx);
  7314. GetPrefixSuffix(this, piniService, &pszUsernamePrefix, &pszUsernameSuffix);
  7315. CmFree(pszUsernamePrefix);
  7316. delete piniService;
  7317. return pszUsernameSuffix;
  7318. }
  7319. //
  7320. // UserName
  7321. //
  7322. if (lstrcmpiU(pszName,TEXT("UserName")) == 0)
  7323. {
  7324. LPTSTR pszValue = NULL;
  7325. //
  7326. // We want to get the value by calling GetUserInfo so that we don't break
  7327. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7328. // value directly out of the Args Structure.
  7329. //
  7330. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7331. {
  7332. GetUserInfo(this, UD_ID_USERNAME, (PVOID*)&pszValue);
  7333. }
  7334. else
  7335. {
  7336. pszValue = CmStrCpyAlloc(this->szUserName);
  7337. }
  7338. return pszValue;
  7339. }
  7340. //
  7341. // InetUserName
  7342. //
  7343. if (lstrcmpiU(pszName,TEXT("InetUserName")) == 0)
  7344. {
  7345. LPTSTR pszValue = NULL;
  7346. //
  7347. // If we aren't doing a double dial, then the InetUserName doesn't make
  7348. // sense and thus should be zero. Also if UseSameUserName is
  7349. // set then we want to return the UserName and skip trying to
  7350. // find the InetUserName
  7351. //
  7352. if (this->fUseTunneling && (FALSE == this->IsDirectConnect()))
  7353. {
  7354. if (this->piniService->GPPB(c_pszCmSection, c_pszCmEntryUseSameUserName))
  7355. {
  7356. //
  7357. // We want to get the value by calling GetUserInfo so that we don't break
  7358. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7359. // value directly out of the Args Structure.
  7360. //
  7361. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7362. {
  7363. GetUserInfo(this, UD_ID_USERNAME, (PVOID*)&pszValue);
  7364. }
  7365. else
  7366. {
  7367. pszValue = CmStrCpyAlloc(this->szUserName);
  7368. }
  7369. }
  7370. else
  7371. {
  7372. //
  7373. // We want to get the value by calling GetUserInfo so that we don't break
  7374. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7375. // value directly out of the Args Structure.
  7376. //
  7377. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7378. {
  7379. GetUserInfo(this, UD_ID_INET_USERNAME, (PVOID*)&pszValue);
  7380. }
  7381. else
  7382. {
  7383. pszValue = CmStrCpyAlloc(this->szInetUserName);
  7384. }
  7385. }
  7386. }
  7387. return pszValue;
  7388. }
  7389. //
  7390. // Domain
  7391. //
  7392. if (lstrcmpiU(pszName,TEXT("Domain")) == 0)
  7393. {
  7394. LPTSTR pszValue = NULL;
  7395. //
  7396. // We want to get the value by calling GetUserInfo so that we don't break
  7397. // existing scenarios. Otherwise for Winlogon and ICS case we'll just take the
  7398. // value directly out of the Args Structure.
  7399. //
  7400. if (CM_LOGON_TYPE_USER == this->dwWinLogonType)
  7401. {
  7402. GetUserInfo(this, UD_ID_DOMAIN, (PVOID*)&pszValue);
  7403. }
  7404. else
  7405. {
  7406. pszValue = CmStrCpyAlloc(this->szDomain);
  7407. }
  7408. return pszValue;
  7409. }
  7410. //
  7411. // Profile
  7412. //
  7413. if (lstrcmpiU(pszName,TEXT("Profile")) == 0)
  7414. {
  7415. return CmStrCpyAlloc(this->piniProfile->GetFile());
  7416. }
  7417. //
  7418. // ServiceDir
  7419. //
  7420. if (lstrcmpiU(pszName, TEXT("ServiceDir")) == 0)
  7421. {
  7422. LPTSTR pszServiceDir = NULL;
  7423. // start with the file name of the Service
  7424. LPCTSTR pszService = this->piniService->GetFile();
  7425. if (pszService)
  7426. {
  7427. // find out where the filename.cmp portion starts
  7428. LPTSTR pszTmp = CmStrrchr(pszService, TEXT('\\'));
  7429. size_t nSize = pszTmp - pszService + 1;
  7430. // alloc enough space for the directory name (and terminating NULL)
  7431. pszServiceDir = (LPTSTR)CmMalloc( nSize * sizeof(TCHAR));
  7432. if (pszServiceDir)
  7433. {
  7434. lstrcpynU(pszServiceDir, pszService, nSize);
  7435. //
  7436. // The Win32 lstrcpyN function enforces a terminating NULL,
  7437. // so the above works without requiring any further code.
  7438. //
  7439. }
  7440. }
  7441. return pszServiceDir;
  7442. }
  7443. //
  7444. // ServiceName
  7445. //
  7446. if (lstrcmpiU(pszName,c_pszCmEntryServiceName) == 0)
  7447. {
  7448. MYDBGASSERT(this->szServiceName[0]);
  7449. return CmStrCpyAlloc(this->szServiceName);
  7450. }
  7451. //
  7452. // DialRasPhoneBook
  7453. //
  7454. if (lstrcmpiU(pszName, TEXT("DialRasPhoneBook")) == 0)
  7455. {
  7456. //
  7457. // We want to return NULL if this was a direct connection
  7458. // and we want to return the hidden ras phonebook path if
  7459. // this was a double dial connection (tunnel over a PPP
  7460. // connection that we dialed).
  7461. //
  7462. if (this->IsDirectConnect())
  7463. {
  7464. return NULL;
  7465. }
  7466. else
  7467. {
  7468. if (this->fUseTunneling)
  7469. {
  7470. return CreateRasPrivatePbk(this);
  7471. }
  7472. else
  7473. {
  7474. return CmStrCpyAlloc(this->pszRasPbk);
  7475. }
  7476. }
  7477. }
  7478. //
  7479. // DialRasEntry
  7480. //
  7481. if (lstrcmpiU(pszName, TEXT("DialRasEntry")) == 0)
  7482. {
  7483. if (this->IsDirectConnect())
  7484. {
  7485. return NULL;
  7486. }
  7487. else
  7488. {
  7489. return GetRasConnectoidName(this, this->piniService, FALSE);
  7490. }
  7491. }
  7492. //
  7493. // TunnelRasPhoneBook
  7494. //
  7495. if (lstrcmpiU(pszName, TEXT("TunnelRasPhoneBook")) == 0)
  7496. {
  7497. //
  7498. // If we are not tunneling then we want to make sure that we
  7499. // return NULL for the tunnel entry name and the tunnel
  7500. // phonebook
  7501. //
  7502. if (this->fUseTunneling)
  7503. {
  7504. CMTRACE1(TEXT("GetProperty - TunnelRasPhoneBook is %s"), this->pszRasPbk);
  7505. return CmStrCpyAlloc(this->pszRasPbk);
  7506. }
  7507. else
  7508. {
  7509. CMTRACE(TEXT("GetProperty - TunnelRasPhoneBook returns NULL"));
  7510. return NULL;
  7511. }
  7512. }
  7513. //
  7514. // TunnelRasEntry
  7515. //
  7516. if (lstrcmpiU(pszName, TEXT("TunnelRasEntry")) == 0)
  7517. {
  7518. //
  7519. // If we are not tunneling then we want to make sure that we
  7520. // return NULL for the tunnel entry name and the tunnel
  7521. // phonebook
  7522. //
  7523. if (this->fUseTunneling)
  7524. {
  7525. return GetRasConnectoidName(this, this->piniService, TRUE);
  7526. }
  7527. else
  7528. {
  7529. return NULL;
  7530. }
  7531. }
  7532. //
  7533. // AutoRedial, TRUE or FALSE
  7534. ///
  7535. if (lstrcmpiU(pszName, TEXT("AutoRedial")) == 0)
  7536. {
  7537. //
  7538. // Return TRUE for the first try.
  7539. //
  7540. return CmStrCpyAlloc( this->nRedialCnt != this->nMaxRedials
  7541. ? TEXT("1") : TEXT("0"));
  7542. }
  7543. if (lstrcmpiU(pszName, TEXT("LastErrorSource")) == 0)
  7544. {
  7545. return CmStrCpyAlloc(this->szLastErrorSrc);
  7546. }
  7547. //
  7548. // PopName, as the city name in phone-book
  7549. //
  7550. if (lstrcmpiU(pszName, TEXT("PopName")) == 0)
  7551. {
  7552. if (this->IsDirectConnect())
  7553. {
  7554. //
  7555. // Ensure no POP description on DirectConnect #324951
  7556. //
  7557. return NULL;
  7558. }
  7559. else
  7560. {
  7561. //
  7562. // the szDesc is in the format of "CityName (BaudMin - BaudMax bps)"
  7563. // We could save the CityNme when we load the phone number from phonebook
  7564. // But we have to change cmpbk code then.
  7565. //
  7566. LPTSTR pszDesc = CmStrCpyAlloc(this->aDialInfo[nDialIdx].szDesc);
  7567. //
  7568. // The city name is followed by " ("
  7569. //
  7570. LPTSTR pszEnd = CmStrStr(pszDesc, TEXT(" ("));
  7571. if (pszEnd == NULL)
  7572. {
  7573. CmFree(pszDesc);
  7574. return NULL;
  7575. }
  7576. *pszEnd = TEXT('\0');
  7577. return pszDesc;
  7578. }
  7579. }
  7580. //
  7581. // The current favorite
  7582. //
  7583. if (lstrcmpiU(pszName, TEXT("CurrentFavorite")) == 0)
  7584. {
  7585. return CmStrCpyAlloc(this->pszCurrentAccessPoint);
  7586. }
  7587. //
  7588. // The current tunnel server address
  7589. //
  7590. if (lstrcmpiU(pszName, TEXT("TunnelServerAddress")) == 0)
  7591. {
  7592. if (this->fUseTunneling)
  7593. {
  7594. return this->piniBothNonFav->GPPS(c_pszCmSection, c_pszCmEntryTunnelAddress);
  7595. }
  7596. else
  7597. {
  7598. return NULL;
  7599. }
  7600. }
  7601. //
  7602. // The canonical number if there is one and if not then the szPhonenumber field itself.
  7603. //
  7604. if (lstrcmpiU(pszName, TEXT("PhoneNumberDialed")) == 0)
  7605. {
  7606. if (this->IsDirectConnect())
  7607. {
  7608. return NULL;
  7609. }
  7610. else
  7611. {
  7612. if (this->aDialInfo[nDialIdx].szCanonical[0])
  7613. {
  7614. return CmStrCpyAlloc(this->aDialInfo[nDialIdx].szCanonical);
  7615. }
  7616. else
  7617. {
  7618. return CmStrCpyAlloc(this->aDialInfo[nDialIdx].szPhoneNumber);
  7619. }
  7620. }
  7621. }
  7622. //
  7623. // ErrorCode in decimal
  7624. //
  7625. if (lstrcmpiU(pszName, TEXT("ErrorCode")) == 0)
  7626. {
  7627. LPTSTR pszValue = (LPTSTR)CmMalloc(64*sizeof(TCHAR)); // large enough to hold the error code
  7628. MYDBGASSERT(pszValue);
  7629. if (pszValue)
  7630. {
  7631. wsprintfU(pszValue, TEXT("%d"), this->dwExitCode);
  7632. }
  7633. return pszValue;
  7634. }
  7635. CMTRACE1(TEXT("%%%s%% not a macro, may be environment variable"), pszName);
  7636. *pbValidPropertyName = FALSE;
  7637. return NULL;
  7638. }
  7639. //+----------------------------------------------------------------------------
  7640. //
  7641. // Function: GetMainDlgTemplate
  7642. //
  7643. // Synopsis: Encapsulates determining which template is to be used
  7644. // for the main dialog.
  7645. //
  7646. // Arguments: ArgsStruct *pArgs - Ptr to global Args struct
  7647. //
  7648. // Returns: UINT - Dlg template ID.
  7649. //
  7650. // History: nickball Created 9/25/98
  7651. // tomkel 01/30/2001 Added support for global credentials UI
  7652. // by using pArgs->fGlobalCredentialsSupported
  7653. //
  7654. //+----------------------------------------------------------------------------
  7655. UINT GetMainDlgTemplate(ArgsStruct *pArgs)
  7656. {
  7657. MYDBGASSERT(pArgs);
  7658. if (NULL == pArgs)
  7659. {
  7660. MYDBGASSERT(pArgs);
  7661. return 0;
  7662. }
  7663. UINT uiNewMainDlgID = 0;
  7664. DWORD dwNewTemplateMask = 0;
  7665. UINT i = 0;
  7666. //
  7667. // Currently there are 24 dialogs used in this function. If you add more dialogs
  7668. // make sure to increase the size of the array and the loop. The dialog templates
  7669. // aren't in any particular order, since we loop through all of them
  7670. // comparing the masks until we find the correct one.
  7671. //
  7672. DWORD rdwTemplateIDs[24][2] = {
  7673. {CMTM_FAVS | CMTM_U_P_D | CMTM_GCOPT, IDD_MAIN_ALL_USERDATA_FAV_GCOPT},
  7674. {CMTM_FAVS | CMTM_U_P_D, IDD_MAIN_ALL_USERDATA_FAV},
  7675. {CMTM_FAVS | CMTM_UID, IDD_MAIN_UID_ONLY_FAV},
  7676. {CMTM_FAVS | CMTM_PWD | CMTM_GCOPT, IDD_MAIN_PWD_ONLY_FAV_GCOPT},
  7677. {CMTM_FAVS | CMTM_PWD, IDD_MAIN_PWD_ONLY_FAV},
  7678. {CMTM_FAVS | CMTM_DMN, IDD_MAIN_DMN_ONLY_FAV},
  7679. {CMTM_FAVS | CMTM_UID_AND_PWD | CMTM_GCOPT, IDD_MAIN_UID_AND_PWD_FAV_GCOPT},
  7680. {CMTM_FAVS | CMTM_UID_AND_PWD, IDD_MAIN_UID_AND_PWD_FAV},
  7681. {CMTM_FAVS | CMTM_UID_AND_DMN, IDD_MAIN_UID_AND_DMN_FAV},
  7682. {CMTM_FAVS | CMTM_PWD_AND_DMN | CMTM_GCOPT, IDD_MAIN_PWD_AND_DMN_FAV_GCOPT},
  7683. {CMTM_FAVS | CMTM_PWD_AND_DMN, IDD_MAIN_PWD_AND_DMN_FAV},
  7684. {CMTM_FAVS, IDD_MAIN_NO_USERDATA_FAV},
  7685. {CMTM_U_P_D | CMTM_GCOPT, IDD_MAIN_ALL_USERDATA_GCOPT},
  7686. {CMTM_U_P_D, IDD_MAIN_ALL_USERDATA},
  7687. {CMTM_UID, IDD_MAIN_UID_ONLY},
  7688. {CMTM_PWD | CMTM_GCOPT, IDD_MAIN_PWD_ONLY_GCOPT},
  7689. {CMTM_PWD, IDD_MAIN_PWD_ONLY},
  7690. {CMTM_DMN, IDD_MAIN_DMN_ONLY},
  7691. {CMTM_UID_AND_PWD | CMTM_GCOPT, IDD_MAIN_UID_AND_PWD_GCOPT},
  7692. {CMTM_UID_AND_PWD, IDD_MAIN_UID_AND_PWD},
  7693. {CMTM_UID_AND_DMN, IDD_MAIN_UID_AND_DMN},
  7694. {CMTM_PWD_AND_DMN | CMTM_GCOPT, IDD_MAIN_PWD_AND_DMN_GCOPT},
  7695. {CMTM_PWD_AND_DMN, IDD_MAIN_PWD_AND_DMN},
  7696. {0, IDD_MAIN_NO_USERDATA}};
  7697. //
  7698. // Set the mask according to the pArgs flags for each value.
  7699. //
  7700. if (!pArgs->fHideUserName)
  7701. {
  7702. dwNewTemplateMask |= CMTM_UID;
  7703. }
  7704. //
  7705. // If the password edit is not displayed, there is no need to
  7706. // check for the global creds flag since there are no such dialogs
  7707. //
  7708. if (!pArgs->fHidePassword)
  7709. {
  7710. dwNewTemplateMask |= CMTM_PWD;
  7711. //
  7712. // Since we show the password field, lets check if we should display
  7713. // the global creds option as well.
  7714. //
  7715. if (pArgs->fGlobalCredentialsSupported)
  7716. {
  7717. dwNewTemplateMask |= CMTM_GCOPT;
  7718. }
  7719. }
  7720. if (!pArgs->fHideDomain)
  7721. {
  7722. dwNewTemplateMask |= CMTM_DMN;
  7723. }
  7724. if (pArgs->fAccessPointsEnabled)
  7725. {
  7726. dwNewTemplateMask |= CMTM_FAVS;
  7727. }
  7728. //
  7729. // Now find the corresponding template id
  7730. //
  7731. for (i = 0; i < 24; i++)
  7732. {
  7733. if (rdwTemplateIDs[i][0] == dwNewTemplateMask)
  7734. {
  7735. uiNewMainDlgID = rdwTemplateIDs[i][1];
  7736. break;
  7737. }
  7738. }
  7739. if (0 == uiNewMainDlgID)
  7740. {
  7741. MYDBGASSERT(FALSE);
  7742. uiNewMainDlgID = IDD_MAIN_NO_USERDATA;
  7743. }
  7744. return uiNewMainDlgID;
  7745. }
  7746. //+----------------------------------------------------------------------------
  7747. //
  7748. // Function: Connect
  7749. //
  7750. // Synopsis: The main dialing (connect path) replaces the winmain from the
  7751. // original CMMGR32.EXE
  7752. //
  7753. // Arguments: HWND hwndParent - window handle of parent
  7754. // LPCTSTR lpszEntry - Ptr to the name of the connection entry
  7755. // LPTSTR lpszPhonebook - Ptr to the name of the phonebook
  7756. // LPRASDIALDLG lpRasDialDlg - RasDialDlg data - ignored
  7757. // LPRASENTRYDLG lpRasEntryDlg - RasEntryDlg data - ignored
  7758. // LPCMDIALINFO lpCmInfo - CM specific dial info such as flags
  7759. // DWORD dwFlags - Flags for AllUser, SingleUser, EAP, etc.
  7760. // PVOID pvLogonBlob - Ptr to blob passed by RAS at WinLogon on W2K
  7761. //
  7762. // Returns: Nothing
  7763. //
  7764. // Note: RasDialDlg->hwndOwner and RasDialDlg->hwndOwner are honored, but they
  7765. // are currently passed in via the hwndParent parameter as appropriate by
  7766. // the caller, CmCustomDialDlg.
  7767. //
  7768. // History: nickball Created 02/06/98
  7769. // nickball hwndParent 11/10/98
  7770. // nickball Passed down dwFlags instead of BOOL 07/13/99
  7771. //
  7772. //+----------------------------------------------------------------------------
  7773. HRESULT Connect(HWND hwndParent,
  7774. LPCTSTR pszEntry,
  7775. LPTSTR lpszPhonebook,
  7776. LPRASDIALDLG, // lpRasDialDlg,
  7777. LPRASENTRYDLG, // lpRasEntryDlg,
  7778. LPCMDIALINFO lpCmInfo,
  7779. DWORD dwFlags,
  7780. PVOID pvLogonBlob)
  7781. {
  7782. MYDBGASSERT(pszEntry);
  7783. MYDBGASSERT(pszEntry[0]);
  7784. MYDBGASSERT(lpCmInfo);
  7785. CMTRACE(TEXT("Connect()"));
  7786. if (NULL == pszEntry || NULL == lpCmInfo)
  7787. {
  7788. return E_POINTER;
  7789. }
  7790. if (0 == pszEntry[0])
  7791. {
  7792. return E_INVALIDARG;
  7793. }
  7794. HRESULT hrRes = S_OK;
  7795. //
  7796. // Allocate our args struct from the heap. Not on our stack.
  7797. //
  7798. ArgsStruct* pArgs = (ArgsStruct*) CmMalloc(sizeof(ArgsStruct));
  7799. if (NULL == pArgs)
  7800. {
  7801. hrRes = HRESULT_FROM_WIN32(ERROR_ALLOCATING_MEMORY);
  7802. goto done;
  7803. }
  7804. //
  7805. // Clear and init global args struct
  7806. //
  7807. hrRes = InitArgsForConnect(pArgs, lpszPhonebook, lpCmInfo, (dwFlags & RCD_AllUsers));
  7808. if (FAILED(hrRes))
  7809. {
  7810. goto done;
  7811. }
  7812. //
  7813. // Setup the connection table
  7814. //
  7815. hrRes = CreateConnTable(pArgs);
  7816. if (FAILED(hrRes))
  7817. {
  7818. goto done;
  7819. }
  7820. //
  7821. // Initialize the profile
  7822. //
  7823. hrRes = InitProfile(pArgs, pszEntry);
  7824. if (FAILED(hrRes))
  7825. {
  7826. goto done;
  7827. }
  7828. //
  7829. // Make sure we have a .cmp name and that the specified .cms exists
  7830. //
  7831. if (FALSE == CheckProfileIntegrity(pArgs))
  7832. {
  7833. // CheckProfileIntegrity() will set pArgs->dwExitCode accordingly
  7834. goto done;
  7835. }
  7836. //
  7837. // Initialize logging
  7838. //
  7839. (VOID) InitLogging(pArgs, pszEntry, TRUE); // TRUE => write a banner;
  7840. // ignore return value
  7841. //
  7842. // Pick up any pre-existing credentials (eg. WinLogon, Reconnect)
  7843. //
  7844. hrRes = InitCredentials(pArgs, lpCmInfo, dwFlags, pvLogonBlob);
  7845. if (S_OK != hrRes)
  7846. {
  7847. goto done;
  7848. }
  7849. //
  7850. // Now that credential support and existance flags are initialized we need
  7851. // to initialize the read/write flags in order to support global user
  7852. // info. This can only be called only after InitCredentials
  7853. //
  7854. SetIniObjectReadWriteFlags(pArgs);
  7855. //
  7856. // Calling InitConnect depends on having the Ini objects read/write flags initialized correctly
  7857. // thus this calls needs to happen after SetIniObjectReadWriteFlags. This is important in case
  7858. // of ICS where it needs to be able to read data correctly from the ICSData reg key or default to
  7859. // the .cms/.cmp files.
  7860. //
  7861. if (!InitConnect(pArgs))
  7862. {
  7863. goto done;
  7864. }
  7865. //
  7866. // Register Classes
  7867. //
  7868. RegisterBitmapClass(g_hInst);
  7869. RegisterWindowClass(g_hInst);
  7870. //
  7871. // Get the helpfile path
  7872. //
  7873. LoadHelpFileInfo(pArgs);
  7874. //
  7875. // If we are in FL_PROPERTIES mode, just get the settings from the
  7876. // profile. Otherwise go ahead and launch the MainDlgProc
  7877. //
  7878. if (pArgs->dwFlags & FL_PROPERTIES)
  7879. {
  7880. if (*pArgs->piniProfile->GetFile() && SetupInternalInfo(pArgs, NULL))
  7881. {
  7882. OnMainProperties(hwndParent, pArgs);
  7883. }
  7884. }
  7885. else
  7886. {
  7887. //
  7888. // Need to call OleInitialize()? See if we need FutureSplash. We don't display
  7889. // animations at WinLogon because of the security implications.
  7890. //
  7891. if (pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryAnimatedLogo) && !IsLogonAsSystem())
  7892. {
  7893. if (!pArgs->olsOle32Link.hInstOle32)
  7894. {
  7895. if (LinkToOle32(&pArgs->olsOle32Link, "OLE32"))
  7896. {
  7897. if (pArgs->olsOle32Link.pfnOleInitialize(NULL) != S_OK)
  7898. {
  7899. //
  7900. // Note: it's not fatal to fail OleInitialize().
  7901. // We will just load the normal bitmap then.
  7902. //
  7903. CMTRACE(TEXT("Connect() OleInitialize failed"));
  7904. }
  7905. }
  7906. else
  7907. {
  7908. CMTRACE(TEXT("Connect() LinkToOle32 failed"));
  7909. }
  7910. }
  7911. }
  7912. //
  7913. // Launch main dialog
  7914. //
  7915. INT_PTR iMainDlgReturn = 0;
  7916. do
  7917. {
  7918. iMainDlgReturn = DialogBoxParamU(g_hInst,
  7919. MAKEINTRESOURCE(GetMainDlgTemplate(pArgs)),
  7920. hwndParent,
  7921. (DLGPROC) MainDlgProc,
  7922. (LPARAM) pArgs);
  7923. if (0 != pArgs->dwSCardErr)
  7924. {
  7925. //
  7926. // User entered a bad smartcard PIN. We exit immediately to avoid
  7927. // locking up the smartcard with multiple incorrect retries.
  7928. //
  7929. MYDBGASSERT(BAD_SCARD_PIN(pArgs->dwSCardErr));
  7930. hrRes = pArgs->dwSCardErr;
  7931. goto done;
  7932. }
  7933. } while (ID_OK_RELAUNCH_MAIN_DLG == iMainDlgReturn);
  7934. }
  7935. done:
  7936. //
  7937. // Now that we are done, we should clear up all the messes :)
  7938. //
  7939. CleanupConnect(pArgs);
  7940. //
  7941. // Un-initialize logging
  7942. //
  7943. (VOID) pArgs->Log.DeInit();
  7944. // ignore return value
  7945. //
  7946. // If hRes isn't already set, use the exitcode value
  7947. //
  7948. if (S_OK == hrRes)
  7949. {
  7950. hrRes = HRESULT_FROM_WIN32(pArgs->dwExitCode);
  7951. }
  7952. //
  7953. // Release pArgs, and exit completely
  7954. //
  7955. CmFree(pArgs);
  7956. return hrRes;
  7957. }
  7958. //
  7959. // Define funtion prototypes for EAP functions
  7960. // that are implemented in the actual EAP dll.
  7961. //
  7962. typedef DWORD (WINAPI* pfnRasEapGetIdentity)(
  7963. DWORD,
  7964. HWND,
  7965. DWORD,
  7966. const WCHAR*,
  7967. const WCHAR*,
  7968. PBYTE,
  7969. DWORD,
  7970. PBYTE,
  7971. DWORD,
  7972. PBYTE*,
  7973. DWORD*,
  7974. WCHAR**
  7975. );
  7976. typedef DWORD (WINAPI* pfnRasEapFreeMemory)(
  7977. PBYTE
  7978. );
  7979. //+----------------------------------------------------------------------------
  7980. //
  7981. // Function: CmEapGetIdentity
  7982. //
  7983. // Synopsis: Given EapUserData, looks up and calls RasEapGetIdentity for
  7984. // the current EAP. Designed to handle the WinLogon case when we
  7985. // want to use the EapUserData passed to us, rather then letting
  7986. // RasGetEapUserIdentity look it up. Because it is only used in
  7987. // this case we pass RAS_EAP_FLAG_LOGON this enables other EAPs
  7988. // to disregard the data if necessary.
  7989. //
  7990. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  7991. // LPTSTR lpszPhonebook - Ptr to the RAS phonebook
  7992. // LPBYTE pbEapAuthData - Eap auth data blob
  7993. // DWORD dwEapAuthDataSize - size of the Eap auth data blob
  7994. // DWORD dwCustomAuthKey - The EAP identifier
  7995. // LPRASEAPUSERIDENTITY* ppRasEapUserIdentity - Identity data
  7996. //
  7997. // Returns: Error Code
  7998. //
  7999. // History: nickball Created 07/16/99
  8000. // nickball ppRasEapUserIdentity 07/30/99
  8001. //
  8002. //+----------------------------------------------------------------------------
  8003. static DWORD CmEapGetIdentity(ArgsStruct *pArgs,
  8004. LPTSTR pszRasPbk,
  8005. LPBYTE pbEapAuthData,
  8006. DWORD dwEapAuthDataSize,
  8007. DWORD dwCustomAuthKey,
  8008. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity)
  8009. {
  8010. MYDBGASSERT(OS_NT5);
  8011. MYDBGASSERT(pArgs);
  8012. MYDBGASSERT(ppRasEapUserIdentity);
  8013. MYDBGASSERT(pArgs->lpEapLogonInfo);
  8014. if (NULL == pArgs || NULL == pArgs->lpEapLogonInfo || NULL == ppRasEapUserIdentity)
  8015. {
  8016. return ERROR_INVALID_PARAMETER;
  8017. }
  8018. DWORD dwErr = ERROR_SUCCESS;
  8019. DWORD dwTmp = 0;
  8020. DWORD dwSize = 0;
  8021. DWORD cbDataOut = 0;
  8022. LPBYTE pbDataOut = NULL;
  8023. WCHAR* pwszIdentity = NULL;
  8024. HKEY hKeyEap = NULL;
  8025. HINSTANCE hInst = NULL;
  8026. LPWSTR pszwPath = NULL;
  8027. pfnRasEapFreeMemory pfnEapFreeMemory = NULL;
  8028. pfnRasEapGetIdentity pfnEapGetIdentity = NULL;
  8029. //
  8030. // First we have to locate the Identity DLL for our EAP. Step one is to
  8031. // build the reg key name using the base path and EAP number.
  8032. //
  8033. WCHAR szwTmp[MAX_PATH];
  8034. wsprintfU(szwTmp, TEXT("%s\\%u"), c_pszRasEapRegistryLocation, dwCustomAuthKey);
  8035. //
  8036. // Now we can open the EAP key
  8037. //
  8038. dwErr = RegOpenKeyExU(HKEY_LOCAL_MACHINE,
  8039. szwTmp,
  8040. 0,
  8041. KEY_QUERY_VALUE ,
  8042. &hKeyEap);
  8043. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), szwTmp, dwErr);
  8044. if (ERROR_SUCCESS != dwErr)
  8045. {
  8046. return dwErr;
  8047. }
  8048. //
  8049. // See if the EAP supports RasEapGetIdentity
  8050. //
  8051. dwSize = sizeof(dwSize);
  8052. dwErr = RegQueryValueExU(hKeyEap,
  8053. c_pszInvokeUsernameDialog,
  8054. NULL,
  8055. NULL,
  8056. (BYTE*)&dwTmp,
  8057. &dwSize);
  8058. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), c_pszInvokeUsernameDialog, dwErr);
  8059. if ((dwErr) || (0 != dwTmp))
  8060. {
  8061. dwErr = ERROR_INVALID_FUNCTION_FOR_ENTRY;
  8062. goto CmEapGetIdentityExit;
  8063. }
  8064. //
  8065. // Next we need to retrieve the path of the EAP's identity DLL
  8066. //
  8067. dwSize = sizeof(szwTmp);
  8068. dwErr = RegQueryValueExU(hKeyEap, c_pszRasEapValueNameIdentity, NULL,
  8069. NULL, (LPBYTE) szwTmp, &dwSize);
  8070. CMTRACE2(TEXT("CmEapGetIdentity - Opening %s returns %u"), c_pszRasEapValueNameIdentity, dwErr);
  8071. if (ERROR_SUCCESS != dwErr)
  8072. {
  8073. return dwErr;
  8074. }
  8075. pszwPath = (LPWSTR) CmMalloc(MAX_PATH * sizeof(TCHAR));
  8076. if (NULL == pszwPath)
  8077. {
  8078. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  8079. goto CmEapGetIdentityExit;
  8080. }
  8081. ExpandEnvironmentStringsU(szwTmp, pszwPath, MAX_PATH);
  8082. //
  8083. // Finally we have the path to the identity DLL. Now we can load the DLL
  8084. // and get the address of the RasEapGetIdentity and RasEapFreeMemory funcs.
  8085. //
  8086. CMTRACE1(TEXT("CmEapGetIdentity - Loading EAP Identity DLL %s"), pszwPath);
  8087. hInst = LoadLibraryExU(pszwPath, NULL, 0);
  8088. if (NULL == hInst)
  8089. {
  8090. dwErr = GetLastError();
  8091. goto CmEapGetIdentityExit;
  8092. }
  8093. pfnEapFreeMemory = (pfnRasEapFreeMemory) GetProcAddress(hInst, "RasEapFreeMemory");
  8094. pfnEapGetIdentity = (pfnRasEapGetIdentity) GetProcAddress(hInst, "RasEapGetIdentity");
  8095. if (pfnEapGetIdentity && pfnEapFreeMemory)
  8096. {
  8097. dwErr = pfnEapGetIdentity(dwCustomAuthKey,
  8098. pArgs->hwndMainDlg,
  8099. RAS_EAP_FLAG_LOGON | RAS_EAP_FLAG_PREVIEW,
  8100. pszRasPbk,
  8101. pArgs->pRasDialParams->szEntryName,
  8102. pbEapAuthData,
  8103. dwEapAuthDataSize,
  8104. (LPBYTE) pArgs->lpEapLogonInfo,
  8105. pArgs->lpEapLogonInfo->dwSize,
  8106. &pbDataOut,
  8107. &cbDataOut,
  8108. &pwszIdentity);
  8109. CMTRACE3(TEXT("CmEapGetIdentity - RasEapGetIdentity returns %u, cbDataOut is %u, pwszIdentity is %s"), dwErr, cbDataOut, pwszIdentity);
  8110. if (ERROR_SUCCESS == dwErr)
  8111. {
  8112. //
  8113. // If data was returned, use it. Otherwise, use the
  8114. // blob that was given to us by RAS at WinLogon.
  8115. //
  8116. if (cbDataOut)
  8117. {
  8118. dwSize = cbDataOut;
  8119. }
  8120. else
  8121. {
  8122. CMTRACE(TEXT("CmEapGetIdentity - there was no pbDataOut from the EAP, using lpEapLogonInfo"));
  8123. CMTRACE1(TEXT("CmEapGetIdentity - pArgs->lpEapLogonInfo->dwSize is %u"), pArgs->lpEapLogonInfo->dwSize);
  8124. CMTRACE1(TEXT("CmEapGetIdentity - dwLogonInfoSize is %u"), pArgs->lpEapLogonInfo->dwLogonInfoSize);
  8125. CMTRACE1(TEXT("CmEapGetIdentity - dwOffsetLogonInfo is %u"), pArgs->lpEapLogonInfo->dwOffsetLogonInfo);
  8126. CMTRACE1(TEXT("CmEapGetIdentity - dwPINInfoSize is %u"), pArgs->lpEapLogonInfo->dwPINInfoSize);
  8127. CMTRACE1(TEXT("CmEapGetIdentity - dwOffsetPINInfo is %u"), pArgs->lpEapLogonInfo->dwOffsetPINInfo);
  8128. dwSize = pArgs->lpEapLogonInfo->dwSize;
  8129. pbDataOut = (LPBYTE) pArgs->lpEapLogonInfo; // Note: pbDataOut is not our memory
  8130. }
  8131. //
  8132. // Allocate the structure.
  8133. //
  8134. *ppRasEapUserIdentity = (LPRASEAPUSERIDENTITY) CmMalloc((sizeof(RASEAPUSERIDENTITY) - 1) + dwSize);
  8135. if (NULL == *ppRasEapUserIdentity)
  8136. {
  8137. dwErr = ERROR_NOT_ENOUGH_MEMORY;
  8138. goto CmEapGetIdentityExit;
  8139. }
  8140. if (pbDataOut) // no crashy
  8141. {
  8142. CMTRACE1(TEXT("CmEapGetIdentity - filling *ppRasEapUserIdentity with pbDataOut of size %u"), dwSize);
  8143. lstrcpyn((*ppRasEapUserIdentity)->szUserName, pwszIdentity, UNLEN);
  8144. (*ppRasEapUserIdentity)->szUserName[UNLEN] = 0;
  8145. (*ppRasEapUserIdentity)->dwSizeofEapInfo = dwSize;
  8146. CopyMemory((*ppRasEapUserIdentity)->pbEapInfo, pbDataOut, dwSize);
  8147. CMTRACE1(TEXT("CmEapGetIdentity - *ppRasEapUserIdentity filled with pbDataOut of size %u"), dwSize);
  8148. }
  8149. else
  8150. {
  8151. dwErr = ERROR_INVALID_DATA;
  8152. MYDBGASSERT(FALSE);
  8153. goto CmEapGetIdentityExit;
  8154. }
  8155. }
  8156. }
  8157. else
  8158. {
  8159. dwErr = GetLastError();
  8160. }
  8161. CmEapGetIdentityExit:
  8162. //
  8163. // Cleanup our temporary buffers
  8164. //
  8165. if (NULL != pfnEapFreeMemory)
  8166. {
  8167. //
  8168. // If cbDataOut is 0 then pbDataOut points at
  8169. // EapLogonInfo, which is not ours to free.
  8170. //
  8171. if (cbDataOut && (NULL != pbDataOut))
  8172. {
  8173. pfnEapFreeMemory(pbDataOut);
  8174. }
  8175. if (NULL != pwszIdentity)
  8176. {
  8177. pfnEapFreeMemory((BYTE*)pwszIdentity);
  8178. }
  8179. }
  8180. if (NULL != hKeyEap)
  8181. {
  8182. RegCloseKey(hKeyEap);
  8183. }
  8184. if (hInst)
  8185. {
  8186. FreeLibrary(hInst);
  8187. }
  8188. CmFree(pszwPath);
  8189. CMTRACE1(TEXT("CmEapGetIdentity - returns %u"), dwErr);
  8190. return dwErr;
  8191. }
  8192. //+----------------------------------------------------------------------------
  8193. //
  8194. // Function: GetEapUserId
  8195. //
  8196. // Synopsis: Helper func to deal with the details of calling out to RAS for EAP
  8197. // credentials.
  8198. //
  8199. // Arguments: ArgsStruct *pArgs - Ptr to global args struct
  8200. // HWND hwndDlg - Window handle of dialog to own any UI
  8201. // LPTSTR lpszPhonebook - Ptr to the RAS phonebook
  8202. // LPBYTE pbEapAuthData - Eap auth data blob
  8203. // DWORD dwEapAuthDataSize - Size of the Eap auth data blob.
  8204. // DWORD dwCustomAuthKey - The EAP identifier
  8205. // LPRASEAPUSERIDENTITY* ppRasEapUserIdentity - Ptr to RAS EAP identity
  8206. // struct to be allocated on our behalf.
  8207. //
  8208. // Returns: Error Code
  8209. //
  8210. // History: nickball Created 05/22/99
  8211. // nickball ppRasEapUserIdentity 07/30/99
  8212. //
  8213. //+----------------------------------------------------------------------------
  8214. static DWORD GetEapUserId(ArgsStruct *pArgs,
  8215. HWND hwndDlg,
  8216. LPTSTR pszRasPbk,
  8217. LPBYTE pbEapAuthData,
  8218. DWORD dwEapAuthDataSize,
  8219. DWORD dwCustomAuthKey,
  8220. LPRASEAPUSERIDENTITY* ppRasEapUserIdentity)
  8221. {
  8222. MYDBGASSERT(OS_NT5);
  8223. MYDBGASSERT(pArgs);
  8224. MYDBGASSERT(ppRasEapUserIdentity);
  8225. MYDBGASSERT(0 == *ppRasEapUserIdentity); // should always be NULL
  8226. DWORD dwRet = ERROR_SUCCESS;
  8227. if (NULL == pArgs ||
  8228. NULL == pArgs->rlsRasLink.pfnGetEapUserIdentity ||
  8229. NULL == ppRasEapUserIdentity)
  8230. {
  8231. return ERROR_INVALID_PARAMETER;
  8232. }
  8233. *ppRasEapUserIdentity = 0;
  8234. //
  8235. // If we have data from WinLogon, then use our own version of
  8236. // GetEapIdentity. Under the covers, RasGetEapUserIdentity calls
  8237. // GetEapUserData (which potentially prompts the user) and then
  8238. // GetEapIdentity. Because we already have the equivalent
  8239. // (from WinLogon) of the data retrieved by GetEapUserData,
  8240. // we can call RasGetEapIdentity directly. This enables us
  8241. // to prevent an unnecessary prompt for the identity info that
  8242. // the user already gave at WinLogon.
  8243. //
  8244. if (pArgs->lpEapLogonInfo)
  8245. {
  8246. dwRet = CmEapGetIdentity(pArgs,
  8247. pszRasPbk,
  8248. pbEapAuthData,
  8249. dwEapAuthDataSize,
  8250. dwCustomAuthKey,
  8251. ppRasEapUserIdentity);
  8252. }
  8253. else
  8254. {
  8255. DWORD dwEapIdentityFlags = 0;
  8256. //
  8257. // Note: In the case that we are called from WinLogon,
  8258. // but without EAP data, but the connection is configured for EAP
  8259. // we send the RAS_EAP_FLAG_LOGON flag down to the EAP so it knows
  8260. // what to do.
  8261. //
  8262. if (IsLogonAsSystem() && (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType))
  8263. {
  8264. dwEapIdentityFlags |= RAS_EAP_FLAG_LOGON;
  8265. }
  8266. //
  8267. // In case we don't want UI set the - RAS_EAP_FLAG_NON_INTERACTIVE
  8268. // same as RASEAPF_NonInteractive
  8269. //
  8270. if (pArgs->dwFlags & FL_UNATTENDED)
  8271. {
  8272. dwEapIdentityFlags |= RAS_EAP_FLAG_NON_INTERACTIVE;
  8273. }
  8274. else
  8275. {
  8276. //
  8277. // Always prompt for EAP credentials. Otherwise when the PIN is saved
  8278. // the user has no way of un-saving it because TLS will cache it and
  8279. // won't display the prompt if it has everything it needs.
  8280. //
  8281. dwEapIdentityFlags = RAS_EAP_FLAG_PREVIEW;
  8282. }
  8283. //
  8284. // Our smartcard PIN retry story: If called from winlogon with an EAP blob,
  8285. // we never retry because we have no way to sending the corrected PIN back
  8286. // to winlogon. In other cases, we retry once only.
  8287. // Retrying oftener greatly increases the chance of locking the smartcard.
  8288. //
  8289. DWORD dwMaxTries = 3; // essentially arbitrary number. (If a smartcard: most do lock you out after 3 tries.)
  8290. DWORD dwCurrentTry = 0;
  8291. do
  8292. {
  8293. dwRet = pArgs->rlsRasLink.pfnGetEapUserIdentity(
  8294. pszRasPbk,
  8295. pArgs->pRasDialParams->szEntryName,
  8296. dwEapIdentityFlags, // See Note above
  8297. hwndDlg,
  8298. ppRasEapUserIdentity);
  8299. }
  8300. while ((dwCurrentTry++ < dwMaxTries) && (ERROR_SUCCESS != dwRet) && (ERROR_CANCELLED != dwRet));
  8301. //
  8302. // We also clear the password and domain in this case because
  8303. // they become irrelevant and we don't want to mix CAD credentials
  8304. // with smartcard credentials. Specifically, we don't want a clash
  8305. // between the UPN username that EAP usually produces and the
  8306. // standard username, domain provided with CAD at WinLogon.
  8307. //
  8308. lstrcpy(pArgs->pRasDialParams->szPassword, TEXT(""));
  8309. lstrcpy(pArgs->pRasDialParams->szDomain, TEXT(""));
  8310. }
  8311. switch (dwRet)
  8312. {
  8313. //
  8314. // If user id isn't required, succeed
  8315. //
  8316. case ERROR_INVALID_FUNCTION_FOR_ENTRY:
  8317. dwRet = ERROR_SUCCESS;
  8318. break;
  8319. //
  8320. // Retrieve the EAP credential data and store in dial params
  8321. //
  8322. case ERROR_SUCCESS:
  8323. //
  8324. // Copy Eap info to Dial Params and Dial Extensions for dialing
  8325. //
  8326. CMTRACE(TEXT("GetEapUserId() setting dial extension with *ppRasEapUserIdentity->pbEapInfo"));
  8327. lstrcpy(pArgs->pRasDialParams->szUserName, (*ppRasEapUserIdentity)->szUserName);
  8328. ((LPRASDIALEXTENSIONS_V500) pArgs->pRasDialExtensions)->RasEapInfo.dwSizeofEapInfo =
  8329. (*ppRasEapUserIdentity)->dwSizeofEapInfo;
  8330. ((LPRASDIALEXTENSIONS_V500) pArgs->pRasDialExtensions)->RasEapInfo.pbEapInfo =
  8331. (*ppRasEapUserIdentity)->pbEapInfo;
  8332. break;
  8333. default:
  8334. break;
  8335. }
  8336. if (ERROR_SUCCESS == dwRet)
  8337. {
  8338. //
  8339. // We have a user (identity) now, update internal and external records
  8340. // so that this information can be reported out. If we're dialing a
  8341. // tunnel, or its not a tunneling profile, store the name in the
  8342. // UserName cache, otherwise its the dial-up portion of double-dial
  8343. // and we store the identity in the InetUserName cache. #388199
  8344. //
  8345. if ((!UseTunneling(pArgs, pArgs->nDialIdx)) || IsDialingTunnel(pArgs))
  8346. {
  8347. lstrcpy(pArgs->szUserName, pArgs->pRasDialParams->szUserName);
  8348. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pArgs->pRasDialParams->szUserName);
  8349. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pArgs->pRasDialParams->szDomain);
  8350. }
  8351. else
  8352. {
  8353. lstrcpy(pArgs->szInetUserName, pArgs->pRasDialParams->szUserName);
  8354. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  8355. }
  8356. }
  8357. CMTRACE2(TEXT("GetEapUserId() returns %u (0x%x)"), dwRet, dwRet);
  8358. return dwRet;
  8359. }
  8360. //+----------------------------------------------------------------------------
  8361. //
  8362. // Func: ShowAccessPointInfoFromReg
  8363. //
  8364. // Desc: Get the access points from the registry and populate the combo box
  8365. // passed as input to the function
  8366. //
  8367. // Args: ArgsStruct *pArgs - Ptr to global args struct
  8368. // HWND hwndCombo - Handle to the combo box to puopulate
  8369. //
  8370. // Return: BOOL - Success or failure
  8371. //
  8372. // Notes:
  8373. //
  8374. // History: t-urama 07/28/2000 Created
  8375. //-----------------------------------------------------------------------------
  8376. BOOL ShowAccessPointInfoFromReg(ArgsStruct *pArgs, HWND hwndParent, UINT uiComboID)
  8377. {
  8378. MYDBGASSERT(pArgs);
  8379. if ((NULL == pArgs) || (NULL == hwndParent) || (NULL == pArgs->pszCurrentAccessPoint))
  8380. {
  8381. return FALSE;
  8382. }
  8383. LPTSTR pszKeyName = NULL;
  8384. DWORD dwTypeTmp;
  8385. DWORD dwSizeTmp = 1;
  8386. HKEY hKeyCm;
  8387. DWORD dwRes = 1;
  8388. DWORD dwIndex = 0;
  8389. PFILETIME pftLastWriteTime = NULL;
  8390. LPTSTR pszRegPath = BuildUserInfoSubKey(pArgs->szServiceName, pArgs->fAllUser);
  8391. MYDBGASSERT(pszRegPath);
  8392. if (NULL == pszRegPath)
  8393. {
  8394. return FALSE;
  8395. }
  8396. CmStrCatAlloc(&pszRegPath, TEXT("\\"));
  8397. CmStrCatAlloc(&pszRegPath, c_pszRegKeyAccessPoints);
  8398. MYDBGASSERT(pszRegPath);
  8399. if (NULL == pszRegPath)
  8400. {
  8401. return FALSE;
  8402. }
  8403. //
  8404. // Open the sub key under HKCU
  8405. //
  8406. dwRes = RegOpenKeyExU(HKEY_CURRENT_USER,
  8407. pszRegPath,
  8408. 0,
  8409. KEY_READ,
  8410. &hKeyCm);
  8411. //
  8412. // If we opened the key successfully, retrieve the value
  8413. //
  8414. if (ERROR_SUCCESS == dwRes)
  8415. {
  8416. HWND hwndCombo = GetDlgItem(hwndParent, uiComboID);
  8417. if (hwndCombo)
  8418. {
  8419. SendDlgItemMessageU(hwndParent, uiComboID, CB_RESETCONTENT, 0, 0L);
  8420. do
  8421. {
  8422. dwSizeTmp = 1;
  8423. do
  8424. {
  8425. CmFree(pszKeyName);
  8426. dwSizeTmp = dwSizeTmp + MAX_PATH;
  8427. MYDBGASSERT(dwSizeTmp < 320);
  8428. if (dwSizeTmp > 320)
  8429. {
  8430. RegCloseKey(hKeyCm);
  8431. goto ShowError;
  8432. }
  8433. pszKeyName = (LPTSTR) CmMalloc((dwSizeTmp + 1) * sizeof(TCHAR));
  8434. if (NULL == pszKeyName)
  8435. {
  8436. RegCloseKey(hKeyCm);
  8437. goto ShowError;
  8438. }
  8439. dwRes = RegEnumKeyExU(hKeyCm,
  8440. dwIndex,
  8441. pszKeyName,
  8442. &dwSizeTmp,
  8443. NULL,
  8444. NULL,
  8445. NULL,
  8446. pftLastWriteTime);
  8447. } while (ERROR_MORE_DATA == dwRes);
  8448. // now write the name of the sub key to the combo box
  8449. if (ERROR_SUCCESS == dwRes )
  8450. {
  8451. SendDlgItemMessageU(hwndParent, uiComboID, CB_ADDSTRING,
  8452. 0, (LPARAM)pszKeyName);
  8453. }
  8454. if (ERROR_SUCCESS != dwRes && ERROR_NO_MORE_ITEMS != dwRes)
  8455. {
  8456. CMTRACE1(TEXT("ShowAccessPointInfoFromReg() failed, GLE=%u."), GetLastError());
  8457. RegCloseKey(hKeyCm);
  8458. goto ShowError;
  8459. }
  8460. dwIndex ++;
  8461. } while(ERROR_NO_MORE_ITEMS != dwRes);
  8462. DWORD dwIdx = (DWORD)SendDlgItemMessageU(hwndParent,
  8463. uiComboID,
  8464. CB_FINDSTRINGEXACT,
  8465. 0,
  8466. (LPARAM)pArgs->pszCurrentAccessPoint);
  8467. if (dwIdx != CB_ERR)
  8468. {
  8469. SendDlgItemMessageU(hwndParent, uiComboID, CB_SETCURSEL, (WPARAM)dwIdx, 0L);
  8470. }
  8471. else
  8472. {
  8473. LPTSTR pszDefaultAccessPointName = CmLoadString(g_hInst, IDS_DEFAULT_ACCESSPOINT);
  8474. CMASSERTMSG(pszDefaultAccessPointName, TEXT("ShowAccessPointInfoFromReg -- CmLoadString of IDS_DEFAULT_ACCESSPOINT failed"));
  8475. if (pszDefaultAccessPointName)
  8476. {
  8477. dwIdx = (DWORD)SendDlgItemMessageU(hwndParent,
  8478. uiComboID,
  8479. CB_FINDSTRINGEXACT,
  8480. 0,
  8481. (LPARAM)pszDefaultAccessPointName);
  8482. if (dwIdx != CB_ERR)
  8483. {
  8484. SendDlgItemMessageU(hwndParent, uiComboID, CB_SETCURSEL, (WPARAM)dwIdx, 0L);
  8485. ChangedAccessPoint(pArgs, hwndParent, uiComboID);
  8486. }
  8487. CmFree(pszDefaultAccessPointName);
  8488. }
  8489. }
  8490. }
  8491. CmFree(pszKeyName);
  8492. CmFree(pszRegPath);
  8493. RegCloseKey(hKeyCm);
  8494. return TRUE;
  8495. }
  8496. ShowError:
  8497. CmFree(pszRegPath);
  8498. CmFree(pszKeyName);
  8499. return FALSE;
  8500. }
  8501. //+----------------------------------------------------------------------------
  8502. //
  8503. // Func: ChangedAccessPoint
  8504. //
  8505. // Desc: Changes the values of access point relevant stuff in pArgs
  8506. // if the value of the current access point changes
  8507. //
  8508. // Args: ArgsStruct *pArgs - Ptr to global args struct
  8509. //
  8510. // Return: BOOL - True if the access point has changed
  8511. //
  8512. // Notes:
  8513. //
  8514. // History: t-urama 07/28/2000 Created
  8515. //-----------------------------------------------------------------------------
  8516. BOOL ChangedAccessPoint(ArgsStruct *pArgs, HWND hwndDlg, UINT uiComboID)
  8517. {
  8518. BOOL bReturn = FALSE;
  8519. MYDBGASSERT(pArgs);
  8520. MYDBGASSERT(hwndDlg);
  8521. if ((NULL == pArgs) || (NULL == hwndDlg) || (NULL == pArgs->pszCurrentAccessPoint))
  8522. {
  8523. return FALSE;
  8524. }
  8525. HWND hwndCombo = GetDlgItem(hwndDlg, uiComboID);
  8526. if (hwndCombo)
  8527. {
  8528. LPTSTR pszAccessPoint = NULL;
  8529. LRESULT lRes = 0;
  8530. LRESULT lResTextLen = 0;
  8531. //
  8532. // Need to get the currently selected text from the combobox.
  8533. // Previously we used GetWindowTextU(hwndCombo, szAccessPoint, MAX_PATH+1), but it
  8534. // incorrectly returned the text.
  8535. // First get the selected index, find out the string length, allocate memory
  8536. //
  8537. lRes = SendMessageU(hwndCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
  8538. if (CB_ERR != lRes)
  8539. {
  8540. lResTextLen = SendMessageU(hwndCombo, CB_GETLBTEXTLEN, (WPARAM)lRes, (LPARAM)0);
  8541. if (CB_ERR != lResTextLen)
  8542. {
  8543. pszAccessPoint = (LPTSTR)CmMalloc(sizeof(TCHAR)*(lResTextLen+1));
  8544. if (NULL != pszAccessPoint)
  8545. {
  8546. //
  8547. // Retrieve the text.
  8548. //
  8549. lRes = SendMessageU(hwndCombo, CB_GETLBTEXT, (WPARAM)lRes, (LPARAM)pszAccessPoint);
  8550. if (CB_ERR != lRes)
  8551. {
  8552. if (0 != lstrcmpiU(pArgs->pszCurrentAccessPoint, pszAccessPoint))
  8553. {
  8554. CmFree(pArgs->pszCurrentAccessPoint);
  8555. pArgs->pszCurrentAccessPoint = CmStrCpyAlloc(pszAccessPoint);
  8556. if (pArgs->pszCurrentAccessPoint)
  8557. {
  8558. LPTSTR pszRegPath = FormRegPathFromAccessPoint(pArgs);
  8559. if (pszRegPath)
  8560. {
  8561. pArgs->piniBoth->SetPrimaryRegPath(pszRegPath);
  8562. pArgs->piniProfile->SetRegPath(pszRegPath);
  8563. CmFree(pszRegPath);
  8564. //
  8565. // First we determine our connect type
  8566. //
  8567. GetConnectType(pArgs);
  8568. //
  8569. // Set fUseTunneling. If not obvious (eg. direct VPN) then
  8570. // base the initial value upon the primary phone number.
  8571. //
  8572. if (pArgs->IsDirectConnect())
  8573. {
  8574. pArgs->fUseTunneling = TRUE;
  8575. }
  8576. else
  8577. {
  8578. pArgs->fUseTunneling = UseTunneling(pArgs, 0);
  8579. }
  8580. //
  8581. // Make sure we re-munge the phone number we are about to load.
  8582. //
  8583. pArgs->bDialInfoLoaded = FALSE;
  8584. //
  8585. // get new values for redial count, idle timeout, and the tapi location
  8586. //
  8587. LoadProperties(pArgs);
  8588. //
  8589. // get new values for phone info
  8590. //
  8591. LoadPhoneInfoFromProfile(pArgs);
  8592. PickModem(pArgs, pArgs->szDeviceType, pArgs->szDeviceName);
  8593. CMTRACE1(TEXT("ChangedAccessPoint() - Changed Access point to %s"), pArgs->pszCurrentAccessPoint);
  8594. bReturn = TRUE;
  8595. }
  8596. else
  8597. {
  8598. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- FormRegPathFromAccessPoint returned NULL"));
  8599. }
  8600. }
  8601. else
  8602. {
  8603. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- CmStrCpyAlloc returned NULL trying to copy the current access point."));
  8604. }
  8605. } // else, nothing to do if the favorites are the same
  8606. }
  8607. else
  8608. {
  8609. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETLBTEXT,...) returned CB_ERR"));
  8610. }
  8611. }
  8612. else
  8613. {
  8614. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- Unable to allocate memory"));
  8615. }
  8616. CmFree(pszAccessPoint);
  8617. }
  8618. else
  8619. {
  8620. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETLBTEXTLEN,...) returned CB_ERR"));
  8621. }
  8622. }
  8623. else
  8624. {
  8625. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- SendMessageU(hwndCombo, CB_GETCURSEL,...) returned CB_ERR"));
  8626. }
  8627. }
  8628. else
  8629. {
  8630. CMASSERTMSG(FALSE, TEXT("ChangedAccessPoint -- Unable to get the combo HWND"));
  8631. }
  8632. return bReturn;
  8633. }
  8634. //----------------------------------------------------------------------------
  8635. //
  8636. // Function: FindEntryCredentialsForCM
  8637. //
  8638. // Synopsis: The algorithm and most of the code is taken from RAS and modified
  8639. // for use by CM.
  8640. //
  8641. // This routine determines whether per-user or per-connection credentials exist or
  8642. // both.
  8643. //
  8644. // The logic is a little complicated because RasGetCredentials had to
  8645. // support legacy usage of the API.
  8646. //
  8647. // Here's how it works. If only one set of credentials is stored for a
  8648. // connection, then RasGetCredentials will return that set regardless of
  8649. // whether the RASCM_DefaultCreds flag is set. If two sets of credentials
  8650. // are saved, then RasGetCredentials will return the per-user credentials
  8651. // if the RASCM_DefaultCreds bit is set, and the per-connection credentials
  8652. // otherwise.
  8653. //
  8654. // Here is the algorithm for loading the credentials
  8655. //
  8656. // 1. Call RasGetCredentials with the RASCM_DefaultCreds bit cleared
  8657. // 1a. If nothing is returned, no credentials are saved
  8658. // 1b. If the RASCM_DefaultCreds bit is set on return, then only
  8659. // global credentials are saved.
  8660. //
  8661. // 2. Call RasGetCredentials with the RASCM_DefaultCreds bit set
  8662. // 2a. If the RASCM_DefaultCreds bit is set on return, then
  8663. // both global and per-connection credentials are saved.
  8664. // 2b. Otherwise, only per-user credentials are saved.
  8665. //
  8666. // Arguments: pArgs - pointer to the ArgStruct
  8667. // pszPhoneBook - path to the phone book. Could be NULL.
  8668. // *pfUser - out param set true if per user creds found
  8669. // *pfGlobal - out param set true if global creds found
  8670. //
  8671. // Returns: BOOL - TRUE is succeeds else FALSE
  8672. //
  8673. // History: 01/31/2001 tomkel Created
  8674. //
  8675. //----------------------------------------------------------------------------
  8676. DWORD FindEntryCredentialsForCM(ArgsStruct *pArgs, LPTSTR pszPhoneBook,
  8677. BOOL *pfUser, BOOL *pfGlobal)
  8678. {
  8679. RASCREDENTIALS rc1 = {0};
  8680. RASCREDENTIALS rc2 = {0};
  8681. BOOL fUseLogonDomain = FALSE;
  8682. DWORD dwErr = ERROR_INVALID_PARAMETER;
  8683. LPTSTR pszConnectoid = NULL;
  8684. CMTRACE(TEXT("FindEntryCredentialsForCM() - Begin"));
  8685. if (NULL == pArgs || NULL == pfUser || NULL == pfGlobal)
  8686. {
  8687. MYDBGASSERT(pArgs && pfUser && pfGlobal);
  8688. CMTRACE(TEXT("FindEntryCredentialsForCM() - Error! Invalid Parameter."));
  8689. return dwErr;
  8690. }
  8691. //
  8692. // Initialize the out params
  8693. //
  8694. *pfUser = FALSE;
  8695. *pfGlobal = FALSE;
  8696. //
  8697. // After setting the OUT params, check if RAS dll have been loaded and if we can use the ras creds store
  8698. //
  8699. if (NULL == pArgs->rlsRasLink.pfnGetCredentials || FALSE == pArgs->bUseRasCredStore)
  8700. {
  8701. CMTRACE(TEXT("FindEntryCredentialsForCM() - RAS Creds store not supported on this platform."));
  8702. return ERROR_NOT_SUPPORTED;
  8703. }
  8704. //
  8705. // Set the size of the structures
  8706. //
  8707. rc1.dwSize = sizeof(rc1);
  8708. rc2.dwSize = sizeof(rc2);
  8709. //
  8710. // The third parameter is used only on Win9x (for tunneling) thus we set it to FALSE
  8711. // since this function is called on Win2K+
  8712. //
  8713. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  8714. if (pszConnectoid)
  8715. {
  8716. do
  8717. {
  8718. //
  8719. // Look up per-user cached username, password, and domain.
  8720. // See comment '1.' in the function header
  8721. //
  8722. rc1.dwMask = RASCM_UserName | RASCM_Password | RASCM_Domain;
  8723. dwErr = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &rc1);
  8724. CMTRACE2(TEXT("FindEntryCredentialsForCM() - Per-User RasGetCredentials=%d,m=%d"), dwErr, rc1.dwMask);
  8725. if (dwErr != NO_ERROR)
  8726. {
  8727. break;
  8728. }
  8729. if (0 == rc1.dwMask)
  8730. {
  8731. //
  8732. // See 1a. in the function header comments
  8733. //
  8734. dwErr = ERROR_SUCCESS;
  8735. break;
  8736. }
  8737. else if (rc1.dwMask & RASCM_DefaultCreds)
  8738. {
  8739. //
  8740. // See 1b. in the function header comments
  8741. //
  8742. *pfGlobal = TRUE;
  8743. //
  8744. // Assumed password was not encoded by RasGetCredentials()
  8745. //
  8746. CmEncodePassword(rc1.szPassword);
  8747. dwErr = ERROR_SUCCESS;
  8748. break;
  8749. }
  8750. //
  8751. // Look up global per-user cached username, password, domain.
  8752. // See comment 2. in the function header
  8753. //
  8754. rc2.dwMask =
  8755. RASCM_UserName | RASCM_Password | RASCM_Domain | RASCM_DefaultCreds;
  8756. dwErr = pArgs->rlsRasLink.pfnGetCredentials(pszPhoneBook, pszConnectoid, &rc2);
  8757. CMTRACE2(TEXT("FindEntryCredentialsForCM() - Global RasGetCredentials=%d,m=%d"), dwErr, rc2.dwMask);
  8758. if (dwErr != ERROR_SUCCESS)
  8759. {
  8760. break;
  8761. }
  8762. if (rc2.dwMask & RASCM_DefaultCreds)
  8763. {
  8764. //
  8765. // See 2a. in the function header comments
  8766. //
  8767. *pfGlobal = TRUE;
  8768. if (rc1.dwMask & RASCM_Password)
  8769. {
  8770. *pfUser = TRUE;
  8771. }
  8772. //
  8773. // Assumed password was not encoded by RasGetCredentials()
  8774. //
  8775. CmEncodePassword(rc1.szPassword);
  8776. CmEncodePassword(rc2.szPassword);
  8777. }
  8778. else
  8779. {
  8780. //
  8781. // See 2b. in the function header comments
  8782. //
  8783. if (rc1.dwMask & RASCM_Password)
  8784. {
  8785. *pfUser = TRUE;
  8786. }
  8787. //
  8788. // Assumed password was not encoded by RasGetCredentials()
  8789. //
  8790. CmEncodePassword(rc1.szPassword);
  8791. }
  8792. }while (FALSE);
  8793. }
  8794. //
  8795. // Cleanup
  8796. //
  8797. ZeroMemory(rc1.szPassword, sizeof(rc1.szPassword));
  8798. ZeroMemory(rc2.szPassword, sizeof(rc2.szPassword));
  8799. CmFree(pszConnectoid);
  8800. CMTRACE(TEXT("FindEntryCredentialsForCM() - End"));
  8801. return dwErr;
  8802. }
  8803. //----------------------------------------------------------------------------
  8804. //
  8805. // Function: InitializeCredentialSupport
  8806. //
  8807. // Synopsis: Helper function to initialize user and global credential
  8808. // support. Some of the flags are redundantly initialized
  8809. // (to FALSE). That is done on purpose for clarity.
  8810. //
  8811. // Arguments: pArgs - the ArgStruct *
  8812. //
  8813. // Returns: BOOL - TRUE is succeeds else FALSE
  8814. //
  8815. // History: 01/31/2001 tomkel Created
  8816. //
  8817. //----------------------------------------------------------------------------
  8818. BOOL InitializeCredentialSupport(ArgsStruct *pArgs)
  8819. {
  8820. BOOL fGlobalCreds = FALSE;
  8821. BOOL fGlobalUserSettings = FALSE;
  8822. if (NULL == pArgs)
  8823. {
  8824. MYDBGASSERT(pArgs);
  8825. return FALSE;
  8826. }
  8827. //
  8828. // By default the the Internet Connection Sharing & Internet Connection
  8829. // Firewall (ICS) tab is disabled.
  8830. //
  8831. pArgs->bShowHNetCfgAdvancedTab = FALSE;
  8832. //
  8833. // User profile read/write support when user is logged off or using dial-up
  8834. // This flag determines if the user info needs to be also saved or loaded from
  8835. // the .cmp file
  8836. //
  8837. pArgs->dwGlobalUserInfo = 0;
  8838. //
  8839. // Credential existance flags - here we cannot yet determine which creds exist
  8840. // that is done in a later call to RefreshCredentialTypes
  8841. //
  8842. pArgs->dwExistingCredentials = 0;
  8843. //
  8844. // Default for which credential store to use - set based on the existance flag so
  8845. // this will also get set appropriatelly after a call to RefreshCredentialTypes
  8846. //
  8847. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  8848. //
  8849. // Deletion flags - used to mark a set of creds for deletion. Since the
  8850. // user can Cancel out of a dialog we don't want to commit the changed
  8851. // until we actually do a dial.
  8852. //
  8853. pArgs->dwDeleteCredentials = 0;
  8854. //
  8855. // Check if this is WindowsXP. We want display the Advanced tab for single-user and
  8856. // all-user profiles
  8857. //
  8858. if (OS_NT51)
  8859. {
  8860. if (IsLogonAsSystem())
  8861. {
  8862. //
  8863. // LocalSystem - winlogon or ICS (in both cases user is logged off)
  8864. // WinLogon - creds are passed through MSGina
  8865. // ICS - need to use glocal creds store
  8866. // pArgs->dwWinLogonType was intialized in InitCredentials()
  8867. // We don't want to read ICSData info if this is a single user profile
  8868. //
  8869. if (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType || FALSE == pArgs->fAllUser)
  8870. {
  8871. pArgs->fGlobalCredentialsSupported = FALSE;
  8872. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  8873. pArgs->dwGlobalUserInfo = 0;
  8874. }
  8875. else
  8876. {
  8877. pArgs->fGlobalCredentialsSupported = TRUE;
  8878. pArgs->dwCurrentCredentialType = CM_CREDS_GLOBAL;
  8879. pArgs->dwGlobalUserInfo |= CM_GLOBAL_USER_INFO_READ_ICS_DATA ;
  8880. }
  8881. CMTRACE(TEXT("InitializeCredentialSupport() - LocalSystem - Global creds OK."));
  8882. }
  8883. else
  8884. {
  8885. //
  8886. // User is logged on
  8887. //
  8888. //
  8889. // By default we want to we want to display the tab. By negating
  8890. // this value we can then correctly save it in the Args structure. This
  8891. // needs to be initialized for everyone
  8892. //
  8893. const TCHAR* const c_pszCmEntryHideICFICSAdvancedTab = TEXT("HideAdvancedTab");
  8894. pArgs->bShowHNetCfgAdvancedTab = !(pArgs->piniService->GPPB(c_pszCmSection,
  8895. c_pszCmEntryHideICFICSAdvancedTab,
  8896. FALSE));
  8897. //
  8898. // If this an all-user profile then we want to see if the profile enables
  8899. // global user settings and displays global credential options.
  8900. // These two features are disabled for single user profiles with the exception of
  8901. // showing the Advanced (ICS) tab
  8902. //
  8903. if (pArgs->fAllUser)
  8904. {
  8905. //
  8906. // If ICS is enabled then we need to support global user settings.
  8907. // Otherwise we read the setting from the file
  8908. //
  8909. if (pArgs->bShowHNetCfgAdvancedTab)
  8910. {
  8911. fGlobalUserSettings = TRUE;
  8912. }
  8913. else
  8914. {
  8915. //
  8916. // See if we support global user settings. By default is it off except if ICS is enabled
  8917. //
  8918. const TCHAR* const c_pszCmEntryGlobalUserSettings = TEXT("GlobalUserSettings");
  8919. fGlobalUserSettings = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryGlobalUserSettings, FALSE);
  8920. }
  8921. //
  8922. // Read the info from the .cms file. By default global credentials are supported
  8923. //
  8924. const TCHAR* const c_pszCmEntryHideGlobalCredentials = TEXT("GlobalCredentials");
  8925. fGlobalCreds = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideGlobalCredentials, TRUE);
  8926. }
  8927. //
  8928. // Check to see if we are going to be hiding the Save Password option, if so then
  8929. // we don't want to support global credentials
  8930. //
  8931. pArgs->fHideRememberPassword = pArgs->piniService->GPPB(c_pszCmSection, c_pszCmEntryHideRememberPwd);
  8932. if (fGlobalCreds && FALSE == pArgs->fHideRememberPassword)
  8933. {
  8934. //
  8935. // Global creds are supported
  8936. //
  8937. //
  8938. // Pick a default for creds type - it might change after calling RefreshCredentialTypes
  8939. //
  8940. pArgs->fGlobalCredentialsSupported = TRUE;
  8941. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  8942. if (fGlobalUserSettings)
  8943. {
  8944. pArgs->dwGlobalUserInfo |= CM_GLOBAL_USER_INFO_WRITE_ICS_DATA;
  8945. }
  8946. CMTRACE(TEXT("InitializeCredentialSupport() - User, global creds, show global UI."));
  8947. }
  8948. else
  8949. {
  8950. //
  8951. // Global creds not supported
  8952. //
  8953. pArgs->fGlobalCredentialsSupported = FALSE;
  8954. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  8955. pArgs->dwGlobalUserInfo = 0;
  8956. CMTRACE(TEXT("InitializeCredentialSupport() - User, no global creds, normal UI."));
  8957. }
  8958. }
  8959. }
  8960. else
  8961. {
  8962. //
  8963. // Single user or not WindowsXP
  8964. //
  8965. pArgs->fGlobalCredentialsSupported = FALSE;
  8966. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  8967. pArgs->dwGlobalUserInfo = 0;
  8968. CMTRACE(TEXT("InitializeCredentialSupport() - Single User profile or not WindowsXP. Global creds not supported"));
  8969. }
  8970. return TRUE;
  8971. }
  8972. //----------------------------------------------------------------------------
  8973. //
  8974. // Function: RefreshCredentialTypes
  8975. //
  8976. // Synopsis: This refreshes credential info. If fSetCredsDefault is TRUE
  8977. // then we also need to set the default type:
  8978. // pArgs->dwCurrentCredentialType.
  8979. //
  8980. //
  8981. // Arguments: pArgs - the ArgStruct *
  8982. // fSetCredsDefault- used to set the default creds type
  8983. //
  8984. // Returns: BOOL - TRUE is succeeds else FALSE
  8985. //
  8986. // History: 01/31/2001 tomkel Created
  8987. //
  8988. //----------------------------------------------------------------------------
  8989. BOOL RefreshCredentialTypes(ArgsStruct *pArgs, BOOL fSetCredsDefault)
  8990. {
  8991. DWORD dwRC = ERROR_INVALID_PARAMETER;
  8992. LPTSTR pszPrivatePbk = NULL;
  8993. if (NULL == pArgs)
  8994. {
  8995. MYDBGASSERT(pArgs);
  8996. return FALSE;
  8997. }
  8998. //
  8999. // This should be run on Win2K+ whether this is an all user profile or not
  9000. // The call that actually determines which credentials exist makes sure we
  9001. // can use the ras cred store
  9002. //
  9003. if (OS_NT5)
  9004. {
  9005. BOOL fUserCredsExist = FALSE;
  9006. BOOL fGlobalCredsExist = FALSE;
  9007. //
  9008. // See if the main creds exist. Inside the function we determine whether
  9009. // we can use the RAS cred store
  9010. //
  9011. dwRC = FindEntryCredentialsForCM(pArgs,
  9012. pArgs->pszRasPbk,
  9013. &fUserCredsExist,
  9014. &fGlobalCredsExist);
  9015. if (ERROR_SUCCESS == dwRC)
  9016. {
  9017. CMTRACE2(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned: (Main) User=%d, Global=%d"),
  9018. fUserCredsExist, fGlobalCredsExist);
  9019. }
  9020. else
  9021. {
  9022. CMTRACE(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned an error. (Main)"));
  9023. }
  9024. //
  9025. // Set the existence flags
  9026. //
  9027. if (fUserCredsExist)
  9028. {
  9029. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_USER;
  9030. }
  9031. else
  9032. {
  9033. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  9034. }
  9035. if (fGlobalCredsExist)
  9036. {
  9037. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_GLOBAL;
  9038. }
  9039. else
  9040. {
  9041. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  9042. }
  9043. fUserCredsExist = FALSE;
  9044. fGlobalCredsExist = FALSE;
  9045. pszPrivatePbk = CreateRasPrivatePbk(pArgs);
  9046. if (pszPrivatePbk)
  9047. {
  9048. //
  9049. // See if the Internet creds exist - by using the private phonebook
  9050. // Inside the function we determine whether we can use the RAS cred store
  9051. //
  9052. dwRC = FindEntryCredentialsForCM(pArgs,
  9053. pszPrivatePbk,
  9054. &fUserCredsExist,
  9055. &fGlobalCredsExist);
  9056. if (ERROR_SUCCESS == dwRC)
  9057. {
  9058. CMTRACE2(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned: (Internet) User=%d, Global=%d"),
  9059. fUserCredsExist, fGlobalCredsExist);
  9060. }
  9061. else
  9062. {
  9063. CMTRACE(TEXT("RefreshCredentialTypes() - FindEntryCredentialsForCM returned an error. (Internet)"));
  9064. }
  9065. }
  9066. //
  9067. // Set the flags whether or not we successfully created a private pbk
  9068. //
  9069. if (fUserCredsExist)
  9070. {
  9071. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_USER;
  9072. }
  9073. else
  9074. {
  9075. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  9076. }
  9077. if (fGlobalCredsExist)
  9078. {
  9079. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_GLOBAL;
  9080. }
  9081. else
  9082. {
  9083. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  9084. }
  9085. //
  9086. // If we don't support Global Creds then explicitly set
  9087. // the existance to FALSE. This can occur if the .cms flag
  9088. // is set not to support global creds, but there are actually
  9089. // global creds on the system.
  9090. //
  9091. if (FALSE == pArgs->fGlobalCredentialsSupported)
  9092. {
  9093. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  9094. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  9095. CMTRACE(TEXT("RefreshCredentialTypes() - Global Credentials are disabled."));
  9096. }
  9097. if (fSetCredsDefault)
  9098. {
  9099. pArgs->dwCurrentCredentialType = GetCurrentCredentialType(pArgs);
  9100. CMTRACE1(TEXT("RefreshCredentialTypes() - Set default Credentials = %d"), pArgs->dwCurrentCredentialType);
  9101. }
  9102. }
  9103. CmFree(pszPrivatePbk);
  9104. return TRUE;
  9105. }
  9106. //----------------------------------------------------------------------------
  9107. //
  9108. // Function: GetCurrentCredentialType
  9109. //
  9110. // Synopsis: Gets the default credentials based on which ones exist based
  9111. // on which flags are set. This function should be called only
  9112. // after RefreshCredentialTypes since that function actually
  9113. // queries the RAS creds store. This one only looks up the cached
  9114. // status of those creds and determines the default according to
  9115. // what credentials exist.
  9116. //
  9117. // Arguments: pArgs - the ArgStruct *
  9118. // fSetCredsDefault- used to set the default creds type
  9119. //
  9120. // Returns: BOOL - TRUE is succeeds else FALSE
  9121. //
  9122. // History: 01/31/2001 tomkel Created
  9123. //
  9124. //----------------------------------------------------------------------------
  9125. DWORD GetCurrentCredentialType(ArgsStruct *pArgs)
  9126. {
  9127. DWORD dwReturn = CM_CREDS_USER;
  9128. if (NULL == pArgs)
  9129. {
  9130. MYDBGASSERT(pArgs);
  9131. return dwReturn;
  9132. }
  9133. //
  9134. // If Global creds aren't supported as in WinLogon case or single-user
  9135. // profiles or anything below WinXP, the default is User Creds Store
  9136. //
  9137. if (FALSE == pArgs->fGlobalCredentialsSupported)
  9138. {
  9139. return dwReturn;
  9140. }
  9141. //
  9142. // Normal Rules when a user is logged on
  9143. //
  9144. if (CM_LOGON_TYPE_USER == pArgs->dwWinLogonType)
  9145. {
  9146. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)
  9147. {
  9148. //
  9149. // Doesn't matter if main global creds exist since main user credentials
  9150. // have precendence if both exist
  9151. //
  9152. dwReturn = CM_CREDS_USER;
  9153. }
  9154. else if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)
  9155. {
  9156. dwReturn = CM_CREDS_GLOBAL;
  9157. }
  9158. else
  9159. {
  9160. //
  9161. // If none of them exist then we want to default to user creds
  9162. //
  9163. dwReturn = CM_CREDS_USER;
  9164. }
  9165. }
  9166. else
  9167. {
  9168. //
  9169. // In any other case dafult to global creds - (ICS scenario)
  9170. //
  9171. dwReturn = CM_CREDS_GLOBAL;
  9172. }
  9173. return dwReturn;
  9174. }
  9175. //----------------------------------------------------------------------------
  9176. //
  9177. // Function: DeleteSavedCredentials
  9178. //
  9179. // Synopsis: Helper function to delete credentials from the RAS store.
  9180. //
  9181. // Arguments: pArgs - the ArgStruct *
  9182. // dwCredsType - Normal or Internet credentials
  9183. // fDeleteGlobal - specifies whether to delete global credentials.
  9184. // If TRUE we delete user, domain name,
  9185. // password as well
  9186. // fDeleteIdentity - specifies whether to delete the user and
  9187. // domain names in addition to the password
  9188. //
  9189. // Returns: BOOL - TRUE is succeeds else FALSE
  9190. //
  9191. // History: 01/31/2001 tomkel Created
  9192. //
  9193. //----------------------------------------------------------------------------
  9194. BOOL DeleteSavedCredentials(ArgsStruct *pArgs, DWORD dwCredsType, BOOL fDeleteGlobal, BOOL fDeleteIdentity)
  9195. {
  9196. RASCREDENTIALS rc;
  9197. BOOL fReturn = FALSE;
  9198. DWORD dwErr = ERROR_INVALID_PARAMETER;
  9199. LPTSTR pszConnectoid = NULL;
  9200. CMTRACE2(TEXT("DeleteSavedCredentials() - Begin: %d %d"), fDeleteGlobal, fDeleteIdentity );
  9201. if (NULL == pArgs)
  9202. {
  9203. MYDBGASSERT(pArgs);
  9204. return fReturn;
  9205. }
  9206. //
  9207. // Check if globals should be deleted in case globals are not supported.
  9208. // This can be in case of global creds are disabled on WinXP or this is
  9209. // Win2K or the platform < Win2K where RASSetCredentials isn't even supported.
  9210. // Thus we still should return TRUE
  9211. //
  9212. if ((fDeleteGlobal && FALSE == pArgs->fGlobalCredentialsSupported) ||
  9213. (NULL == pArgs->rlsRasLink.pfnSetCredentials) ||
  9214. (FALSE == pArgs->bUseRasCredStore))
  9215. {
  9216. CMTRACE(TEXT("DeleteSavedCredentials() - Global Creds not supported or do not have ras store on this platform."));
  9217. return TRUE;
  9218. }
  9219. //
  9220. // We don't support deleting globals on Win2K (that is caught by the above if since Win2K
  9221. // will not have global credentials supported. Otherwise on Win2K we can delete the main
  9222. // user creds. On WinXP anything is fine.
  9223. //
  9224. if (OS_NT5)
  9225. {
  9226. ZeroMemory(&rc, sizeof(rc));
  9227. rc.dwSize = sizeof(RASCREDENTIALS);
  9228. rc.dwMask = RASCM_Password;
  9229. if (fDeleteIdentity)
  9230. {
  9231. rc.dwMask |= (RASCM_UserName | RASCM_Domain);
  9232. }
  9233. if (fDeleteGlobal && pArgs->fGlobalCredentialsSupported)
  9234. {
  9235. rc.dwMask |= RASCM_UserName | RASCM_Domain | RASCM_DefaultCreds;
  9236. }
  9237. //
  9238. // The third parameter is used only on Win9x (for tunneling) thus we set it to FALSE
  9239. // since this function is called on Win2K+
  9240. //
  9241. pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  9242. if (pszConnectoid)
  9243. {
  9244. if (CM_CREDS_TYPE_INET == dwCredsType)
  9245. {
  9246. LPTSTR pszPrivatePbk = CreateRasPrivatePbk(pArgs);
  9247. if (pszPrivatePbk)
  9248. {
  9249. dwErr = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePbk,
  9250. pszConnectoid,
  9251. &rc,
  9252. TRUE );
  9253. CmFree(pszPrivatePbk);
  9254. }
  9255. }
  9256. else
  9257. {
  9258. dwErr = pArgs->rlsRasLink.pfnSetCredentials(pArgs->pszRasPbk,
  9259. pszConnectoid,
  9260. &rc,
  9261. TRUE );
  9262. }
  9263. if (ERROR_SUCCESS == dwErr)
  9264. {
  9265. fReturn = TRUE;
  9266. }
  9267. }
  9268. CMTRACE1(TEXT("DeleteSavedCredentials() - End: RasSetCredentials=%d"), dwErr );
  9269. }
  9270. else
  9271. {
  9272. CMTRACE(TEXT("DeleteSavedCredentials() - Platform is less than Win2K"));
  9273. }
  9274. CmFree(pszConnectoid);
  9275. return fReturn;
  9276. }
  9277. //+---------------------------------------------------------------------------
  9278. //
  9279. // Function: SetCredentialUIOptionBasedOnDefaultCreds
  9280. //
  9281. // Synopsis: Selects (checks) the appropriate UI option for saving credentials
  9282. // based on the current credential store default.
  9283. //
  9284. // Arguments: pArgs - ptr to ArgsStruct
  9285. // hwndDlg - handle to the dialog window
  9286. //
  9287. // Returns: NONE
  9288. //
  9289. // History: 02/05/2001 tomkel Created
  9290. //
  9291. //----------------------------------------------------------------------------
  9292. VOID SetCredentialUIOptionBasedOnDefaultCreds(ArgsStruct *pArgs, HWND hwndDlg)
  9293. {
  9294. if (NULL == pArgs || NULL == hwndDlg)
  9295. {
  9296. MYDBGASSERT(pArgs && hwndDlg);
  9297. return;
  9298. }
  9299. //
  9300. // fGlobalCredentialsSupported controls which dialog templates get loaded and
  9301. // if the flag is FALSE then the dialog template doesn't have these controls
  9302. // thus there is no reason to set them.
  9303. //
  9304. if (pArgs->fGlobalCredentialsSupported)
  9305. {
  9306. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  9307. {
  9308. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_UNCHECKED);
  9309. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_CHECKED);
  9310. }
  9311. else
  9312. {
  9313. //
  9314. // CM_CREDS_USER
  9315. //
  9316. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_SINGLE_USER, BST_CHECKED);
  9317. CheckDlgButton(hwndDlg, IDC_OPT_CREDS_ALL_USER, BST_UNCHECKED);
  9318. }
  9319. }
  9320. return;
  9321. }
  9322. //+---------------------------------------------------------------------------
  9323. //
  9324. // Function: RefreshCredentialInfo
  9325. //
  9326. // Synopsis: This is a slimmed down version of LoadProperties. It only
  9327. // loads user info from cmp/cms, registry, password
  9328. // cache, etc, into its internal variables.
  9329. //
  9330. //
  9331. // Arguments: pArgs - ptr to ArgsStruct
  9332. // dwCredsType - type of credentials to refresh
  9333. //
  9334. // Returns: NONE
  9335. //
  9336. // History: 02/05/2001 tomkel Created
  9337. //
  9338. //----------------------------------------------------------------------------
  9339. VOID RefreshCredentialInfo(ArgsStruct *pArgs, DWORD dwCredsType)
  9340. {
  9341. LPTSTR pszTmp = NULL;
  9342. LPTSTR pszUserName = NULL;
  9343. UINT nTmp;
  9344. CMTRACE(TEXT("RefreshCredentialInfo() - Begin"));
  9345. if (NULL == pArgs)
  9346. {
  9347. MYDBGASSERT(pArgs);
  9348. return;
  9349. }
  9350. if (IsTunnelEnabled(pArgs))
  9351. {
  9352. if (CM_CREDS_TYPE_BOTH == dwCredsType || CM_CREDS_TYPE_INET == dwCredsType)
  9353. {
  9354. //
  9355. // read in inet username
  9356. // Special case where the same user name isn't being used, and internet globals don't exist
  9357. // Then we have to read the user name from the user creds store in order to pre-populate
  9358. //
  9359. DWORD dwRememberedCredType = pArgs->dwCurrentCredentialType;
  9360. pszUserName = NULL;
  9361. if ((FALSE == pArgs->fUseSameUserName) &&
  9362. (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType) &&
  9363. (FALSE == (BOOL)(CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)))
  9364. {
  9365. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  9366. }
  9367. GetUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID*)&pszUserName);
  9368. //
  9369. // Restore credential store
  9370. //
  9371. pArgs->dwCurrentCredentialType = dwRememberedCredType;
  9372. if (pszUserName)
  9373. {
  9374. //
  9375. // check username length
  9376. //
  9377. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  9378. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  9379. {
  9380. CmFree(pszUserName);
  9381. pArgs->szInetUserName[0] = TEXT('\0');
  9382. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szInetUserName);
  9383. }
  9384. else
  9385. {
  9386. lstrcpyU(pArgs->szInetUserName, pszUserName);
  9387. CmFree(pszUserName);
  9388. }
  9389. }
  9390. else
  9391. {
  9392. *pArgs->szInetUserName = TEXT('\0');
  9393. }
  9394. //
  9395. // Read in inet password unless we are reconnecting in which case, we
  9396. // already have the correct password, and we want to use it and dial
  9397. // automatically.
  9398. //
  9399. if (!(pArgs->dwFlags & FL_RECONNECT))
  9400. {
  9401. LPTSTR pszPassword = NULL;
  9402. GetUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID*)&pszPassword);
  9403. if (!pszPassword)
  9404. {
  9405. CmWipePassword(pArgs->szInetPassword);
  9406. }
  9407. else
  9408. {
  9409. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxPassword, PWLEN);
  9410. if ((UINT)lstrlenU(pszPassword) > __min(PWLEN, nTmp))
  9411. {
  9412. CmFree(pszPassword);
  9413. pszPassword = CmStrCpyAlloc(TEXT(""));
  9414. }
  9415. lstrcpyU(pArgs->szInetPassword, pszPassword);
  9416. CmEncodePassword(pArgs->szInetPassword); // Never leave a PWD in plain text on heap
  9417. CmWipePassword(pszPassword);
  9418. CmFree(pszPassword);
  9419. }
  9420. }
  9421. }
  9422. }
  9423. if (CM_CREDS_TYPE_BOTH == dwCredsType || CM_CREDS_TYPE_MAIN == dwCredsType)
  9424. {
  9425. //
  9426. // The presence of either lpRasNoUser or lpEapLogonInfo indicates
  9427. // that we retrieved credentials via WinLogon. We ignore cached
  9428. // creds in this situation.
  9429. //
  9430. if ((!pArgs->lpRasNoUser) && (!pArgs->lpEapLogonInfo))
  9431. {
  9432. //
  9433. // get username, domain, etc. from CMS file
  9434. //
  9435. GetUserInfo(pArgs, UD_ID_USERNAME, (PVOID*)&pszUserName);
  9436. if (pszUserName)
  9437. {
  9438. //
  9439. // check username length
  9440. //
  9441. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxUserName, UNLEN);
  9442. if ((UINT)lstrlenU(pszUserName) > __min(UNLEN, nTmp))
  9443. {
  9444. CmFree(pszUserName);
  9445. pszUserName = CmStrCpyAlloc(TEXT(""));
  9446. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUserName);
  9447. }
  9448. lstrcpyU(pArgs->szUserName, pszUserName);
  9449. CmFree(pszUserName);
  9450. }
  9451. else
  9452. {
  9453. *pArgs->szUserName = TEXT('\0');
  9454. }
  9455. //
  9456. // Read in the standard password unless we are reconnecting in which case
  9457. // we already have the correct password, and we want to use it and dial
  9458. // automatically.
  9459. //
  9460. if (!(pArgs->dwFlags & FL_RECONNECT))
  9461. {
  9462. pszTmp = NULL;
  9463. GetUserInfo(pArgs, UD_ID_PASSWORD, (PVOID*)&pszTmp);
  9464. if (pszTmp)
  9465. {
  9466. //
  9467. // max length for user password
  9468. //
  9469. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection,c_pszCmEntryMaxPassword,PWLEN);
  9470. if ((UINT)lstrlenU(pszTmp) > __min(PWLEN,nTmp))
  9471. {
  9472. CmFree(pszTmp);
  9473. pszTmp = CmStrCpyAlloc(TEXT(""));
  9474. }
  9475. lstrcpyU(pArgs->szPassword, pszTmp);
  9476. CmEncodePassword(pArgs->szPassword); // Never leave a PWD in plain text on heap
  9477. CmWipePassword(pszTmp);
  9478. CmFree(pszTmp);
  9479. }
  9480. else
  9481. {
  9482. CmWipePassword(pArgs->szPassword);
  9483. }
  9484. }
  9485. //
  9486. // Load domain info
  9487. //
  9488. LPTSTR pszDomain = NULL;
  9489. GetUserInfo(pArgs, UD_ID_DOMAIN, (PVOID*)&pszDomain);
  9490. if (pszDomain)
  9491. {
  9492. nTmp = (int) pArgs->piniService->GPPI(c_pszCmSection, c_pszCmEntryMaxDomain, DNLEN);
  9493. if (nTmp <= 0)
  9494. {
  9495. nTmp = DNLEN;
  9496. }
  9497. if ((UINT)lstrlenU(pszDomain) > __min(DNLEN, nTmp))
  9498. {
  9499. CmFree(pszDomain);
  9500. pszDomain = CmStrCpyAlloc(TEXT(""));
  9501. }
  9502. lstrcpyU(pArgs->szDomain, pszDomain);
  9503. CmFree(pszDomain);
  9504. }
  9505. else
  9506. {
  9507. *pArgs->szDomain = TEXT('\0');
  9508. }
  9509. }
  9510. }
  9511. CMTRACE(TEXT("RefreshCredentialInfo() - End"));
  9512. return;
  9513. }
  9514. //+---------------------------------------------------------------------------
  9515. //
  9516. // Function: GetAndStoreUserInfo
  9517. //
  9518. // Synopsis: Most of this code existed in the OnMainConnect function.
  9519. // Gets the username, domain, password from the edit boxes and saves them
  9520. // to the internal structure pArgs->szUserName, pArgs->szPassword, pArgs->szDomain
  9521. // if the fSaveOtherUserInfo is TRUE then it also saves them to the appropriate
  9522. // place (RAS store, reg, etc.)
  9523. //
  9524. // Arguments: pArgs - ptr to ArgsStruct
  9525. // hwndDlg - handle to the dialog window
  9526. // fSaveUPD - save UserName, Password, Domain (U, P, D)
  9527. // fSaveOtherUserInfo - flag whether to save other userinfo (excluding U, P, D)
  9528. //
  9529. // Returns: NONE
  9530. //
  9531. // History: 02/05/2001 tomkel Created
  9532. //
  9533. //----------------------------------------------------------------------------
  9534. VOID GetAndStoreUserInfo(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSaveUPD, BOOL fSaveOtherUserInfo)
  9535. {
  9536. if (NULL == pArgs || NULL == hwndDlg)
  9537. {
  9538. MYDBGASSERT(pArgs && hwndDlg);
  9539. return;
  9540. }
  9541. //
  9542. // Process UserName info, if any
  9543. //
  9544. if (GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT))
  9545. {
  9546. LPTSTR pszUsername = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  9547. //
  9548. // save the user info
  9549. //
  9550. if (fSaveUPD)
  9551. {
  9552. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pszUsername);
  9553. }
  9554. lstrcpyU(pArgs->szUserName, pszUsername);
  9555. CmFree(pszUsername);
  9556. }
  9557. else
  9558. {
  9559. //
  9560. // In case the user name field is hidden then just re-save what's in the
  9561. // structure. This needs to be done since all of the credentials might have
  9562. // been deleted from the ras cred store
  9563. //
  9564. if (fSaveUPD)
  9565. {
  9566. SaveUserInfo(pArgs, UD_ID_USERNAME, (PVOID)pArgs->szUserName);
  9567. }
  9568. }
  9569. //
  9570. // Update password related flags
  9571. //
  9572. if (!pArgs->fHideRememberPassword)
  9573. {
  9574. //
  9575. // save "Remember password"
  9576. //
  9577. if (fSaveOtherUserInfo)
  9578. {
  9579. SaveUserInfo(pArgs, UD_ID_REMEMBER_PWD,
  9580. (PVOID)&pArgs->fRememberMainPassword);
  9581. }
  9582. }
  9583. if (!pArgs->fHideDialAutomatically)
  9584. {
  9585. //
  9586. // save "Dial automatically..."
  9587. //
  9588. if (fSaveOtherUserInfo)
  9589. {
  9590. SaveUserInfo(pArgs, UD_ID_NOPROMPT,
  9591. (PVOID)&pArgs->fDialAutomatically);
  9592. }
  9593. }
  9594. //
  9595. // Process Password info, if any. If field is hidden, then don't save anything.
  9596. //
  9597. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  9598. if (hwndPassword)
  9599. {
  9600. BOOL fSavePassword = TRUE;
  9601. //
  9602. // We don't want to copy the password into pArgs structure if fSaveUPD isn't true,
  9603. // because it will be obfuscated in this case. The password is already in the structure
  9604. // on Win2K+
  9605. //
  9606. if (fSaveUPD)
  9607. {
  9608. //
  9609. // Get the latest password data from the edit control
  9610. // and obfuscate its contents so that connect actions
  9611. // can't retrieve it.
  9612. //
  9613. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  9614. ObfuscatePasswordEdit(pArgs);
  9615. //
  9616. // Check if we have 16 *'s
  9617. //
  9618. CmDecodePassword(pArgs->szPassword);
  9619. if ((0 == lstrcmpU(c_pszSavedPasswordToken, pArgs->szPassword)) &&
  9620. (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L)))
  9621. {
  9622. //
  9623. // We have 16 *'s and the user hasn't modified the editbox. This
  9624. // password is from the RAS cred store, so we don't want to save the 16 *'s
  9625. //
  9626. fSavePassword = FALSE;
  9627. }
  9628. CmEncodePassword(pArgs->szPassword);
  9629. }
  9630. //
  9631. // For winlogon we need to take the password from the edit box
  9632. //
  9633. if (CM_LOGON_TYPE_WINLOGON == pArgs->dwWinLogonType)
  9634. {
  9635. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  9636. }
  9637. //
  9638. // Update persistent storage
  9639. // No need to delete the password here as it was done by the calling function
  9640. //
  9641. if (pArgs->fRememberMainPassword)
  9642. {
  9643. //
  9644. // If the password has changed, then update storage
  9645. // Always save password - 303382
  9646. //
  9647. if (fSaveUPD && fSavePassword)
  9648. {
  9649. CmDecodePassword(pArgs->szPassword);
  9650. SaveUserInfo(pArgs, UD_ID_PASSWORD, (PVOID)pArgs->szPassword);
  9651. CmEncodePassword(pArgs->szPassword);
  9652. }
  9653. //
  9654. // Check DialAutomatically and carry remember state
  9655. // over to InetPassword if it isn't remembered already.
  9656. //
  9657. // Need to check if this is a double-dial scenario. Also need to check if we are
  9658. // allowed to save UPD, otherwise we don't want to change the state mainly
  9659. // (pArgs->fRememberInetPassword)
  9660. //
  9661. if (pArgs->fDialAutomatically && fSaveUPD &&
  9662. (DOUBLE_DIAL_CONNECTION == pArgs->GetTypeOfConnection()))
  9663. {
  9664. //
  9665. // Carry remember state from DialAutomatically over to
  9666. // InetPassword if it isn't already remembered.
  9667. //
  9668. if (!pArgs->fRememberInetPassword)
  9669. {
  9670. pArgs->fRememberInetPassword = TRUE;
  9671. CmDecodePassword(pArgs->szInetPassword);
  9672. if (fSavePassword)
  9673. {
  9674. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pArgs->szInetPassword);
  9675. }
  9676. CmEncodePassword(pArgs->szInetPassword);
  9677. }
  9678. }
  9679. }
  9680. else
  9681. {
  9682. //
  9683. // If we don't have the ras cred store then the password wasn't deleted
  9684. // so we must deleted by calling this function
  9685. //
  9686. if (fSavePassword) // No need to check fSaveUPD, taken care of ras creds store check
  9687. {
  9688. if (FALSE == pArgs->bUseRasCredStore)
  9689. {
  9690. DeleteUserInfo(pArgs, UD_ID_PASSWORD);
  9691. }
  9692. }
  9693. }
  9694. if (fSaveUPD)
  9695. {
  9696. BOOL fSaveInetPassword = TRUE;
  9697. //
  9698. // Check if we have 16 *'s for Internet Password. First, decode and then encode pw
  9699. //
  9700. CmDecodePassword(pArgs->szInetPassword);
  9701. if (0 == lstrcmpU(c_pszSavedPasswordToken, pArgs->szInetPassword))
  9702. {
  9703. //
  9704. // We have 16 *'s This password is from the RAS cred store, so we don't want to save the 16 *'s
  9705. //
  9706. fSaveInetPassword = FALSE;
  9707. }
  9708. CmEncodePassword(pArgs->szInetPassword);
  9709. //
  9710. // Check to see if we should re-save Internet creds
  9711. // This needs to be done here in case the user has switched between
  9712. // global and local credentials using the option buttons while having Internet
  9713. // credentials set in the Internet Login (CInetPage) property sheet. By switching
  9714. // the options, the user switched the current credential store
  9715. // (pArgs->dwCurrentCredentialType) so in order not to lose that data, we need to
  9716. // re-save the internet creds. Re-saving puts them in the correct (global or local)
  9717. // ras cred store.
  9718. // When the username is the same and we saved the main password (SaveUserInfo)
  9719. // this also saves the password to the Internet creds store
  9720. //
  9721. if (pArgs->fUseSameUserName)
  9722. {
  9723. if (fSaveInetPassword)
  9724. {
  9725. if (pArgs->fRememberMainPassword)
  9726. {
  9727. //
  9728. // Save the UserName into the InetUserName field
  9729. // Password has been saved when saving UD_ID_PASSWORD. There is a special
  9730. // case that also saves the main password as the internet password
  9731. //
  9732. SaveUserInfo(pArgs, UD_ID_INET_USERNAME, (PVOID)pArgs->szUserName);
  9733. pArgs->fRememberInetPassword = TRUE;
  9734. }
  9735. else
  9736. {
  9737. if (FALSE == pArgs->bUseRasCredStore)
  9738. {
  9739. DeleteUserInfo(pArgs, UD_ID_INET_PASSWORD);
  9740. pArgs->fRememberInetPassword = FALSE;
  9741. }
  9742. }
  9743. }
  9744. }
  9745. else
  9746. {
  9747. if (fSaveInetPassword)
  9748. {
  9749. if(pArgs->fRememberInetPassword)
  9750. {
  9751. CmDecodePassword(pArgs->szInetPassword);
  9752. SaveUserInfo(pArgs, UD_ID_INET_PASSWORD, (PVOID)pArgs->szInetPassword);
  9753. CmEncodePassword(pArgs->szInetPassword);
  9754. }
  9755. else
  9756. {
  9757. if (FALSE == pArgs->bUseRasCredStore)
  9758. {
  9759. DeleteUserInfo(pArgs, UD_ID_INET_PASSWORD);
  9760. }
  9761. }
  9762. }
  9763. //
  9764. // Need to save username in either case so we can pre-populate this
  9765. //
  9766. SaveUserInfo(pArgs, UD_ID_INET_USERNAME,
  9767. (PVOID)pArgs->szInetUserName);
  9768. }
  9769. }
  9770. }
  9771. //
  9772. // This should be saved in all cases except ICS
  9773. //
  9774. if (fSaveOtherUserInfo)
  9775. {
  9776. SaveUserInfo(pArgs, UD_ID_REMEMBER_INET_PASSWORD, (PVOID)&pArgs->fRememberInetPassword);
  9777. }
  9778. //
  9779. // Process Domain info, if any
  9780. //
  9781. if (GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT)) // !pArgs->fHideDomain)
  9782. {
  9783. LPTSTR pszDomain = CmGetWindowTextAlloc(hwndDlg,IDC_MAIN_DOMAIN_EDIT);
  9784. //
  9785. // save the user info
  9786. //
  9787. if (fSaveUPD)
  9788. {
  9789. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pszDomain);
  9790. }
  9791. lstrcpyU(pArgs->szDomain, pszDomain);
  9792. CmFree(pszDomain);
  9793. }
  9794. else
  9795. {
  9796. //
  9797. // In case the domain field is hidden then just re-save what's in the
  9798. // structure. This needs to be done since all of the credentials might have
  9799. // been deleted from the ras cred store.
  9800. //
  9801. if (fSaveUPD)
  9802. {
  9803. SaveUserInfo(pArgs, UD_ID_DOMAIN, (PVOID)pArgs->szDomain);
  9804. }
  9805. }
  9806. return;
  9807. }
  9808. //+---------------------------------------------------------------------------
  9809. //
  9810. // Function: SetIniObjectReadWriteFlags
  9811. //
  9812. // Synopsis: If the read or write flags are set we need to enable reading and/or
  9813. // writing to the .CMP file. Each instance of the CIni class may
  9814. // or may not use the .cmp file. It can also be using the .CMP as either
  9815. // the primary file or normal file. See InitProfileFromName function
  9816. // in init.cpp for detailed comments about these instances.
  9817. //
  9818. // pArgs->piniProfile - uses .CMP as a regular file
  9819. // pArgs->piniService - doesn't use .CMP file at all
  9820. // pArgs->piniBoth - uses .CMP as a primary file
  9821. // pArgs->piniBothNonFav - uses .CMP as a primary file
  9822. //
  9823. // Arguments: pArgs - ptr to ArgsStruct
  9824. //
  9825. // Returns: NONE
  9826. //
  9827. // History: 02/14/2001 tomkel Created
  9828. //
  9829. //----------------------------------------------------------------------------
  9830. VOID SetIniObjectReadWriteFlags(ArgsStruct *pArgs)
  9831. {
  9832. if (NULL == pArgs)
  9833. {
  9834. MYDBGASSERT(pArgs);
  9835. return;
  9836. }
  9837. BOOL fWriteICSInfo = FALSE;
  9838. BOOL fReadGlobalICSInfo = FALSE;
  9839. //
  9840. // Get the read flag
  9841. //
  9842. fReadGlobalICSInfo = ((BOOL)(pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_READ_ICS_DATA) ? TRUE : FALSE);
  9843. //
  9844. // Get the write flag.
  9845. //
  9846. fWriteICSInfo = ((BOOL)(pArgs->dwGlobalUserInfo & CM_GLOBAL_USER_INFO_WRITE_ICS_DATA) ? TRUE : FALSE);
  9847. if (fReadGlobalICSInfo || fWriteICSInfo)
  9848. {
  9849. LPTSTR pszICSDataReg = BuildICSDataInfoSubKey(pArgs->szServiceName);
  9850. if (pszICSDataReg)
  9851. {
  9852. //
  9853. // Now that there is a reg key and at least one of the above flags is TRUE,
  9854. // then we want to set the read and write flags in the classes. By default
  9855. // they are set to FALSE in the constructors, so we don't have to
  9856. // explicitly set them if we don't need this functionality.
  9857. //
  9858. // Set ICSData reg key
  9859. //
  9860. pArgs->piniProfile->SetICSDataPath(pszICSDataReg);
  9861. pArgs->piniBoth->SetICSDataPath(pszICSDataReg);
  9862. pArgs->piniBothNonFav->SetICSDataPath(pszICSDataReg);
  9863. //
  9864. // Set Write flag since we have a reg key
  9865. //
  9866. pArgs->piniProfile->SetWriteICSData(fWriteICSInfo);
  9867. pArgs->piniBoth->SetWriteICSData(fWriteICSInfo);
  9868. pArgs->piniBothNonFav->SetWriteICSData(fWriteICSInfo);
  9869. //
  9870. // Set Read flag since we have a reg key
  9871. //
  9872. pArgs->piniProfile->SetReadICSData(fReadGlobalICSInfo);
  9873. pArgs->piniBoth->SetReadICSData(fReadGlobalICSInfo);
  9874. pArgs->piniBothNonFav->SetReadICSData(fReadGlobalICSInfo);
  9875. }
  9876. CmFree(pszICSDataReg);
  9877. }
  9878. return;
  9879. }
  9880. //----------------------------------------------------------------------------
  9881. //
  9882. // Function: TryToDeleteAndSaveCredentials
  9883. //
  9884. // Synopsis: Used on Win2K and WinXP+. This function uses the RAS Credential
  9885. // store to save and delete credentials based on user's selection.
  9886. // First we need to determine if the user is saving their password.
  9887. // Then appropriately delete or prompt to delete existing credentials.
  9888. // If we aren't saving any credentials, then delete all of them.
  9889. // The special case is if the user is deleting his local credentials
  9890. // and global credentials exist on the system. Then we have to prompt
  9891. // if we should delete the global creds as well.
  9892. // Toward the botton of the function we get the info from the UI.
  9893. // If the password is 16 *'s then we don't save the password After
  9894. // getting info from the UI, we save it in the RAS Cred store.
  9895. // Internet credentials are saved if we are using the same user
  9896. // name. Otherwise we leave the Internet creds. They were saved
  9897. // on the Inet properties page. There is a scenario where the user
  9898. // saved the internet creds on the property page and then switched
  9899. // the way credentials should be saved (global vs. local) which might cause
  9900. // the internet password to be stored under in the wrong (global vs. local)
  9901. // ras store. If the passwords are disjoined (pArgs->fUseSameUserName is FALSE)
  9902. // there isn't much we can do.
  9903. //
  9904. // NOTE: We only want to delete credentials if and only if the existence
  9905. // flag are set! This is to prevent from deleting mainly global credentials
  9906. // in a certain profile where global credentials are disabled.
  9907. //
  9908. //
  9909. // Arguments: pArgs - ptr to ArgsStruct
  9910. // hwndDlg - HWND to dialog
  9911. //
  9912. // Returns: NONE
  9913. //
  9914. // History: 03/24/2001 tomkel Created
  9915. //
  9916. //----------------------------------------------------------------------------
  9917. VOID TryToDeleteAndSaveCredentials(ArgsStruct *pArgs, HWND hwndDlg)
  9918. {
  9919. if (NULL == pArgs || NULL == hwndDlg)
  9920. {
  9921. MYDBGASSERT(pArgs && hwndDlg);
  9922. return;
  9923. }
  9924. //
  9925. // Check if this is Win2K+ (That's where RAS Creds store is supported)
  9926. //
  9927. if (!OS_NT5)
  9928. {
  9929. MYDBGASSERT(FALSE);
  9930. return;
  9931. }
  9932. BOOL fSave = FALSE;
  9933. BOOL fResaveInetUserCreds = FALSE;
  9934. RASCREDENTIALS rc = {0};
  9935. RASCREDENTIALS rcInet={0};
  9936. rc.dwSize = sizeof(rc);
  9937. rcInet.dwSize = sizeof(rcInet);
  9938. //
  9939. // See if we want to save the credentials
  9940. //
  9941. if (pArgs->fRememberMainPassword)
  9942. {
  9943. //
  9944. // Which password are we saving?
  9945. //
  9946. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  9947. {
  9948. //
  9949. // Delete User creds w/o asking. No need to check for existence since these
  9950. // are just user (main & inet) creds.
  9951. //
  9952. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  9953. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  9954. rc.dwMask = RASCM_DefaultCreds;
  9955. //
  9956. // Delete Internet User creds w/o asking
  9957. // It doesn't matter that we aren't using the same user name
  9958. // If we are saving globals, then user creds must always be deleted! This applies for main and Internet.
  9959. //
  9960. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  9961. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  9962. }
  9963. else
  9964. {
  9965. //
  9966. // Trying to save User creds. if there is currently no saved per-user password
  9967. // and the user opts to save the password himself, then ask whether the global
  9968. // password should be deleted if it exists.
  9969. //
  9970. if ((CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials) &&
  9971. !(CM_EXIST_CREDS_MAIN_USER & pArgs->dwExistingCredentials))
  9972. {
  9973. LPTSTR pszTmp = CmLoadString(g_hInst, IDMSG_DELETE_GLOBAL_CREDS);
  9974. if (pszTmp)
  9975. {
  9976. if (IDYES == MessageBoxEx(hwndDlg, pszTmp, pArgs->szServiceName,
  9977. MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2,
  9978. LANG_USER_DEFAULT))
  9979. {
  9980. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  9981. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  9982. //
  9983. // Check for existence before deleting. If they don't exist, no need to
  9984. // delete them.
  9985. //
  9986. if ((CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials))
  9987. {
  9988. //
  9989. // Delete Internet Global creds if we are using the same creds
  9990. //
  9991. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  9992. {
  9993. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  9994. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  9995. }
  9996. }
  9997. }
  9998. }
  9999. CmFree(pszTmp);
  10000. }
  10001. }
  10002. //
  10003. // User chose to save password. Cache username, password, and
  10004. // domain.
  10005. //
  10006. fSave = TRUE;
  10007. rc.dwMask |= RASCM_UserName | RASCM_Password | RASCM_Domain;
  10008. }
  10009. else
  10010. {
  10011. //
  10012. // Don't save password
  10013. //
  10014. //
  10015. // Check which option button is currently selected
  10016. //
  10017. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType)
  10018. {
  10019. //
  10020. // User is trying to delete his local creds. Delete the user creds.
  10021. // No need to check if they exist since these are local user creds.
  10022. //
  10023. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10024. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  10025. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10026. {
  10027. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10028. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  10029. }
  10030. //
  10031. // Check if global creds exist and if so prompt the user asking if he wants
  10032. // to delete the globals as well
  10033. //
  10034. if (CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials)
  10035. {
  10036. int iMsgBoxResult = 0;
  10037. LPTSTR pszTmp = CmLoadString(g_hInst, IDMSG_DELETE_ALL_CREDS);
  10038. if (pszTmp)
  10039. {
  10040. //
  10041. // Set the default to the 2nd button (NO), thus the user won't
  10042. // accidentally delete the global creds.
  10043. //
  10044. iMsgBoxResult = MessageBoxEx(hwndDlg, pszTmp, pArgs->szServiceName,
  10045. MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2,
  10046. LANG_USER_DEFAULT);
  10047. if (IDYES == iMsgBoxResult)
  10048. {
  10049. //
  10050. // Delete global creds
  10051. //
  10052. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10053. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  10054. if (CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)
  10055. {
  10056. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10057. {
  10058. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10059. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  10060. }
  10061. }
  10062. }
  10063. }
  10064. CmFree(pszTmp);
  10065. pszTmp = NULL;
  10066. }
  10067. //
  10068. // We need to resave username or domain info, even if it existed in case the
  10069. // user has updated it.
  10070. //
  10071. fSave = TRUE;
  10072. rc.dwMask |= RASCM_UserName | RASCM_Domain;
  10073. }
  10074. else
  10075. {
  10076. //
  10077. // Delete both sets of credentials
  10078. //
  10079. //
  10080. // Check if we need to resave User Name and Domain. The call that deletes the
  10081. // user creds doesn't wipe out User Name and Domain so there is no need to re-save.
  10082. //
  10083. if (FALSE == (BOOL)(pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER))
  10084. {
  10085. //
  10086. // Resave the username, and domain since user creds didn't exist
  10087. // and we want to pre-populate this info next time CM is loaded
  10088. //
  10089. fSave = TRUE;
  10090. rc.dwMask |= RASCM_UserName | RASCM_Domain;
  10091. }
  10092. if (CM_EXIST_CREDS_MAIN_GLOBAL & pArgs->dwExistingCredentials)
  10093. {
  10094. //
  10095. // Delete the global credentials.
  10096. // Note from RAS codebase: Note that we have to delete the global identity
  10097. // as well because we do not support deleting
  10098. // just the global password. This is so that
  10099. // RasSetCredentials can emulate RasSetDialParams.
  10100. //
  10101. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10102. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_GLOBAL;
  10103. }
  10104. if (CM_EXIST_CREDS_INET_GLOBAL & pArgs->dwExistingCredentials)
  10105. {
  10106. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10107. {
  10108. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_DELETE_GLOBALS, CM_DELETE_SAVED_CREDS_DELETE_IDENTITY);
  10109. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_GLOBAL;
  10110. //
  10111. // If we don't have Inet user creds then we need to cache the username for Inet creds
  10112. //
  10113. if (FALSE == (BOOL)(CM_EXIST_CREDS_INET_USER & pArgs->dwExistingCredentials))
  10114. {
  10115. fResaveInetUserCreds = TRUE;
  10116. }
  10117. }
  10118. }
  10119. //
  10120. // Delete the password saved per-user. Keep the user name
  10121. // and domain saved, however.
  10122. //
  10123. if (CM_EXIST_CREDS_MAIN_USER & pArgs->dwExistingCredentials)
  10124. {
  10125. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_MAIN, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10126. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_MAIN_USER;
  10127. }
  10128. if (CM_EXIST_CREDS_INET_USER & pArgs->dwExistingCredentials)
  10129. {
  10130. if (pArgs->fUseSameUserName || (FALSE == pArgs->fRememberInetPassword))
  10131. {
  10132. DeleteSavedCredentials(pArgs, CM_CREDS_TYPE_INET, CM_DELETE_SAVED_CREDS_KEEP_GLOBALS, CM_DELETE_SAVED_CREDS_KEEP_IDENTITY);
  10133. pArgs->dwExistingCredentials &= ~CM_EXIST_CREDS_INET_USER;
  10134. }
  10135. }
  10136. }
  10137. }
  10138. //
  10139. // Gets the info from the UI into pArgs and copy them into the RASCREDENTIALS structure
  10140. //
  10141. GetUserInfoFromDialog(pArgs, hwndDlg, &rc);
  10142. //
  10143. // See if we need to save anything
  10144. //
  10145. if (fSave)
  10146. {
  10147. LPTSTR pszConnectoid = GetRasConnectoidName(pArgs, pArgs->piniService, FALSE);
  10148. DWORD dwCurrentMask = rc.dwMask;
  10149. DWORD dwInetCurrentMask = rc.dwMask & ~RASCM_Domain; // Don't need domain info
  10150. if (pszConnectoid && pArgs->rlsRasLink.pfnSetCredentials)
  10151. {
  10152. DWORD dwRet = (DWORD)-1; // Some non ERROR_SUCCESS value
  10153. DWORD dwRetInet = (DWORD)-1; // Some non ERROR_SUCCESS value
  10154. LPTSTR pszPhoneBook = pArgs->pszRasPbk;
  10155. LPTSTR pszPrivatePhoneBook = CreateRasPrivatePbk(pArgs);
  10156. CopyMemory((LPVOID)&rcInet, (LPVOID)&rc, sizeof(rcInet));
  10157. //
  10158. // Save the creds
  10159. //
  10160. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &rc, FALSE);
  10161. if (ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRet)
  10162. {
  10163. //
  10164. // Then the phonebook entry doesn't exist yet, lets create it.
  10165. //
  10166. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  10167. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  10168. {
  10169. pRasEntry->dwSize = sizeof(RASENTRY);
  10170. dwRet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  10171. //
  10172. // Lets try to set the credentials one more time ...
  10173. //
  10174. if (ERROR_SUCCESS == dwRet)
  10175. {
  10176. //
  10177. // dwMask needs to be reassigned, the previous call modified it
  10178. //
  10179. rc.dwMask = dwCurrentMask;
  10180. dwRet = pArgs->rlsRasLink.pfnSetCredentials(pszPhoneBook, pszConnectoid, &rc, FALSE);
  10181. }
  10182. CmFree(pRasEntry);
  10183. }
  10184. }
  10185. //
  10186. // Now try to save Internet creds
  10187. //
  10188. if (ERROR_SUCCESS == dwRet && pszPrivatePhoneBook)
  10189. {
  10190. //
  10191. // If we aren't using the credentials for main and Inet, then there
  10192. // is no need to resave Internet credentials, because they were saved on
  10193. // the Inet-Dialog page and they weren't deleted above.
  10194. //
  10195. if (pArgs->fUseSameUserName)
  10196. {
  10197. //
  10198. // dwMask needs to be reassigned, the previous call modified it
  10199. //
  10200. rcInet.dwMask = dwInetCurrentMask;
  10201. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10202. }
  10203. else
  10204. {
  10205. if (fResaveInetUserCreds)
  10206. {
  10207. rcInet.dwMask = dwInetCurrentMask;
  10208. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10209. }
  10210. if (pArgs->fDialAutomatically &&
  10211. (DOUBLE_DIAL_CONNECTION == pArgs->GetTypeOfConnection()))
  10212. {
  10213. //
  10214. // Carry remember state from DialAutomatically over to
  10215. // InetPassword if it isn't already remembered.
  10216. //
  10217. if (FALSE == pArgs->fRememberInetPassword)
  10218. {
  10219. pArgs->fRememberInetPassword = TRUE;
  10220. CmDecodePassword(pArgs->szInetPassword);
  10221. //
  10222. // Compare to 16 *'s. We don't want to resave if we have 16 *'s
  10223. // otherwise the user will get an auth-retry.
  10224. //
  10225. if (0 != lstrcmpU(c_pszSavedPasswordToken, pArgs->szInetPassword))
  10226. {
  10227. //
  10228. // No need to save the domain
  10229. //
  10230. rcInet.dwMask = dwInetCurrentMask;
  10231. lstrcpyU(rcInet.szUserName, pArgs->szInetUserName);
  10232. lstrcpyU(rcInet.szPassword, pArgs->szInetPassword);
  10233. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10234. }
  10235. CmEncodePassword(pArgs->szInetPassword);
  10236. }
  10237. }
  10238. }
  10239. }
  10240. if ((ERROR_CANNOT_FIND_PHONEBOOK_ENTRY == dwRetInet) && pszPrivatePhoneBook)
  10241. {
  10242. //
  10243. // Then the phonebook entry doesn't exist yet, lets create it.
  10244. //
  10245. LPRASENTRY pRasEntry = (LPRASENTRY)CmMalloc(sizeof(RASENTRY));
  10246. if (pRasEntry && pArgs->rlsRasLink.pfnSetEntryProperties)
  10247. {
  10248. pRasEntry->dwSize = sizeof(RASENTRY);
  10249. dwRetInet = pArgs->rlsRasLink.pfnSetEntryProperties(pszPrivatePhoneBook, pszConnectoid, pRasEntry, pRasEntry->dwSize, NULL, 0);
  10250. //
  10251. // Lets try to set the credentials one more time ...
  10252. //
  10253. if (ERROR_SUCCESS == dwRetInet)
  10254. {
  10255. //
  10256. // dwMask needs to be reassigned, the previous call modifies the mask
  10257. //
  10258. rcInet.dwMask = dwInetCurrentMask;
  10259. dwRetInet = pArgs->rlsRasLink.pfnSetCredentials(pszPrivatePhoneBook, pszConnectoid, &rcInet, FALSE);
  10260. }
  10261. CmFree(pRasEntry);
  10262. }
  10263. }
  10264. if (ERROR_SUCCESS == dwRet)
  10265. {
  10266. //
  10267. // Only set the existance flags if we are saving the password and everything
  10268. // succeeded
  10269. //
  10270. if (pArgs->fRememberMainPassword)
  10271. {
  10272. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType)
  10273. {
  10274. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_GLOBAL;
  10275. if (pArgs->fUseSameUserName && (ERROR_SUCCESS == dwRetInet))
  10276. {
  10277. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_GLOBAL;
  10278. }
  10279. }
  10280. else
  10281. {
  10282. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_MAIN_USER;
  10283. if (pArgs->fUseSameUserName && (ERROR_SUCCESS == dwRetInet))
  10284. {
  10285. pArgs->dwExistingCredentials |= CM_EXIST_CREDS_INET_USER;
  10286. }
  10287. }
  10288. }
  10289. }
  10290. CmFree(pszPrivatePhoneBook);
  10291. }
  10292. CmFree(pszConnectoid);
  10293. }
  10294. ZeroMemory(rc.szPassword, sizeof(rc.szPassword));
  10295. ZeroMemory(rcInet.szPassword, sizeof(rcInet.szPassword));
  10296. return;
  10297. }
  10298. //----------------------------------------------------------------------------
  10299. //
  10300. // Function: GetUserInfoFromDialog
  10301. //
  10302. // Synopsis: Gets the user information from the editboxes into pArgs
  10303. // structure. Then it copies the info into rascredentials
  10304. // structure. If the password is 16 *'s then we clear
  10305. // the password mask in the rascredentials in order not to save
  10306. // the password.
  10307. //
  10308. // Arguments: pArgs - ptr to ArgsStruct
  10309. // hwndDlg - HWND to dialog
  10310. // prc - [IN/OUT] rascredentials structure
  10311. //
  10312. // Returns: NONE
  10313. //
  10314. // History: 03/24/2001 tomkel Created
  10315. //
  10316. //----------------------------------------------------------------------------
  10317. VOID GetUserInfoFromDialog(ArgsStruct *pArgs, HWND hwndDlg, RASCREDENTIALS *prc)
  10318. {
  10319. if (NULL == pArgs || NULL == hwndDlg || NULL == prc)
  10320. {
  10321. MYDBGASSERT(pArgs && hwndDlg && prc);
  10322. return;
  10323. }
  10324. //
  10325. // Process Password info, if any.
  10326. //
  10327. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  10328. if (hwndPassword)
  10329. {
  10330. //
  10331. // Get the latest password data from the edit control
  10332. // and obfuscate its contents so that connect actions
  10333. // can't retrieve it.
  10334. //
  10335. GetPasswordFromEdit(pArgs); // fills pArgs->szPassword
  10336. ObfuscatePasswordEdit(pArgs); // sets *'s into the password edit box
  10337. //
  10338. // Check if we have 16 *'s
  10339. //
  10340. CmDecodePassword(pArgs->szPassword);
  10341. if ((0 == lstrcmpU(c_pszSavedPasswordToken, pArgs->szPassword)) &&
  10342. (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L)))
  10343. {
  10344. //
  10345. // We have 16 *'s and the user hasn't modified the editbox. This
  10346. // password is from the RAS cred store, so we don't want to save the 16 *'s
  10347. //
  10348. prc->dwMask &= ~RASCM_Password;
  10349. }
  10350. CmEncodePassword(pArgs->szPassword);
  10351. }
  10352. //
  10353. // Process UserName info, if any
  10354. //
  10355. HWND hwndUserName = GetDlgItem(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  10356. if (hwndUserName)
  10357. {
  10358. LPTSTR pszUsername = CmGetWindowTextAlloc(hwndDlg, IDC_MAIN_USERNAME_EDIT);
  10359. lstrcpyU(pArgs->szUserName, pszUsername);
  10360. CmFree(pszUsername);
  10361. }
  10362. //
  10363. // Process Domain info, if any
  10364. //
  10365. HWND hwndDomain = GetDlgItem(hwndDlg, IDC_MAIN_DOMAIN_EDIT);
  10366. if (hwndDomain)
  10367. {
  10368. LPTSTR pszDomain = CmGetWindowTextAlloc(hwndDlg,IDC_MAIN_DOMAIN_EDIT);
  10369. lstrcpyU(pArgs->szDomain, pszDomain);
  10370. CmFree(pszDomain);
  10371. }
  10372. //
  10373. // This needs to be separate because in some cases
  10374. // the editboxes will not exist on the dialog, but we still need to save the info
  10375. // from the pArgs structure into RASCREDENTIALS.
  10376. //
  10377. lstrcpyU(prc->szUserName, pArgs->szUserName);
  10378. lstrcpyU(prc->szDomain, pArgs->szDomain);
  10379. CmDecodePassword(pArgs->szPassword);
  10380. lstrcpyU(prc->szPassword, pArgs->szPassword);
  10381. CmEncodePassword(pArgs->szPassword);
  10382. }
  10383. //----------------------------------------------------------------------------
  10384. //
  10385. // Function: SwitchToLocalCreds
  10386. //
  10387. // Synopsis: Clear the password, but only if it wasn't recently modified
  10388. // only then we can reuse and resave it. That's because when
  10389. // we switch credential stores, the value of the szPassword
  10390. // is what was read from the RAS cred store (16 *'s). It doesn't
  10391. // make sense to save this value into a new user RAS creds store. If the
  10392. // password already existed there, then it's fine.
  10393. // In case the user modified the password text box and then decided
  10394. // to swich, the modification flag will be on, so we'll assume that the
  10395. // user entered a valid password and that it wasn't read in from the
  10396. // creds store.
  10397. // The actual deletion of credential happnes once the user clicks
  10398. // the connect button. Here we just clear things out of memory
  10399. // and update the UI. We also need to update the remember Internet
  10400. // flag based on if the Internet credential exist. This is so the
  10401. // UI stays consistent with what credentials are loaded in memory.
  10402. //
  10403. // Arguments: pArgs - ptr to ArgsStruct
  10404. // hwndDlg - HWND to dialog
  10405. // fSwitchToGlobal - used to ignore the check which credential
  10406. // store is currently active
  10407. //
  10408. // Returns: NONE
  10409. //
  10410. // History: 03/24/2001 tomkel Created
  10411. //
  10412. //----------------------------------------------------------------------------
  10413. VOID SwitchToLocalCreds(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSwitchToLocal)
  10414. {
  10415. if (NULL == pArgs || NULL == hwndDlg)
  10416. {
  10417. return;
  10418. }
  10419. //
  10420. // Switching to using Single-User credentials
  10421. //
  10422. //
  10423. // Check that previously the default was the Global creds store
  10424. //
  10425. if (CM_CREDS_GLOBAL == pArgs->dwCurrentCredentialType || fSwitchToLocal)
  10426. {
  10427. pArgs->dwCurrentCredentialType = CM_CREDS_USER;
  10428. HWND hwndTemp = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  10429. BOOL fPWChanged = FALSE;
  10430. if (hwndTemp)
  10431. {
  10432. //
  10433. // Don't use Edit_GetModify. This needs need to run on Win9x so call
  10434. // SendMessageU
  10435. //
  10436. fPWChanged = (BOOL) SendMessageU(hwndTemp, EM_GETMODIFY, 0L, 0L);
  10437. if (FALSE == fPWChanged)
  10438. {
  10439. pArgs->fIgnoreChangeNotification = TRUE;
  10440. CmWipePassword(pArgs->szPassword);
  10441. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  10442. pArgs->fIgnoreChangeNotification = FALSE;
  10443. }
  10444. }
  10445. if (FALSE == fPWChanged)
  10446. {
  10447. //
  10448. // Only if Password field didn't change
  10449. //
  10450. if (OS_NT51)
  10451. {
  10452. //
  10453. // Wipe the Internet password - since we are switching from globals
  10454. // or we are using the same user name the Inet password will get re-populated
  10455. // from the main password, otherwise the user needs to set this password in
  10456. // the InetDialog.
  10457. //
  10458. CmWipePassword(pArgs->szInetPassword);
  10459. pArgs->fRememberInetPassword = FALSE;
  10460. //
  10461. // Only reload if main user creds exist
  10462. //
  10463. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_USER)
  10464. {
  10465. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  10466. {
  10467. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  10468. pArgs->fRememberInetPassword = TRUE;
  10469. }
  10470. else
  10471. {
  10472. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_MAIN);
  10473. }
  10474. }
  10475. else
  10476. {
  10477. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  10478. {
  10479. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  10480. pArgs->fRememberInetPassword = TRUE;
  10481. }
  10482. else
  10483. {
  10484. pArgs->fRememberInetPassword = FALSE;
  10485. }
  10486. }
  10487. }
  10488. else
  10489. {
  10490. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  10491. }
  10492. }
  10493. else
  10494. {
  10495. if (OS_NT51)
  10496. {
  10497. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_USER)
  10498. {
  10499. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  10500. pArgs->fRememberInetPassword = TRUE;
  10501. }
  10502. else
  10503. {
  10504. pArgs->fRememberInetPassword = FALSE;
  10505. }
  10506. }
  10507. else
  10508. {
  10509. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_INET);
  10510. }
  10511. }
  10512. }
  10513. }
  10514. //----------------------------------------------------------------------------
  10515. //
  10516. // Function: SwitchToGlobalCreds
  10517. //
  10518. // Synopsis: Clear the password and reload the credentials if they exist.
  10519. // Otherwise we clear the password if it hasn't been modified by
  10520. // the user.
  10521. //
  10522. // Arguments: pArgs - ptr to ArgsStruct
  10523. // hwndDlg - HWND to dialog
  10524. // fSwitchToGlobal - used to ignore the check which credential
  10525. // store is currently active
  10526. //
  10527. // Returns: NONE
  10528. //
  10529. // History: 03/24/2001 tomkel Created
  10530. //
  10531. //----------------------------------------------------------------------------
  10532. VOID SwitchToGlobalCreds(ArgsStruct *pArgs, HWND hwndDlg, BOOL fSwitchToGlobal)
  10533. {
  10534. if (NULL == pArgs || NULL == hwndDlg)
  10535. {
  10536. return;
  10537. }
  10538. //
  10539. // This should only be called on WinXP+
  10540. //
  10541. if (!OS_NT51)
  10542. {
  10543. MYDBGASSERT(FALSE);
  10544. return;
  10545. }
  10546. //
  10547. // Switching to using Global credentials
  10548. //
  10549. //
  10550. // Check that previously the default was the User creds store
  10551. //
  10552. if (CM_CREDS_USER == pArgs->dwCurrentCredentialType || fSwitchToGlobal)
  10553. {
  10554. pArgs->dwCurrentCredentialType = CM_CREDS_GLOBAL;
  10555. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_MAIN_GLOBAL)
  10556. {
  10557. CmWipePassword(pArgs->szPassword);
  10558. CmWipePassword(pArgs->szInetPassword);
  10559. pArgs->fRememberInetPassword = FALSE;
  10560. //
  10561. // Globals exist
  10562. //
  10563. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)
  10564. {
  10565. //
  10566. // Both exist - reload both
  10567. //
  10568. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_BOTH);
  10569. pArgs->fRememberInetPassword = TRUE;
  10570. }
  10571. else
  10572. {
  10573. //
  10574. // User Globals - exist, reload
  10575. // Internet Globals - don't exist, clear password
  10576. //
  10577. ReloadCredentials(pArgs, hwndDlg, CM_CREDS_TYPE_MAIN);
  10578. }
  10579. }
  10580. else
  10581. {
  10582. HWND hwndPassword = GetDlgItem(hwndDlg, IDC_MAIN_PASSWORD_EDIT);
  10583. pArgs->fIgnoreChangeNotification = TRUE;
  10584. CmWipePassword(pArgs->szInetPassword);
  10585. pArgs->fRememberInetPassword = FALSE;
  10586. if (pArgs->dwExistingCredentials & CM_EXIST_CREDS_INET_GLOBAL)
  10587. {
  10588. //
  10589. // User Globals - don't exist - clear password
  10590. // Internet Globals - exist - reload
  10591. //
  10592. RefreshCredentialInfo(pArgs, CM_CREDS_TYPE_INET);
  10593. //
  10594. // In case user inet creds didn't exist, we should
  10595. //
  10596. pArgs->fRememberInetPassword = TRUE;
  10597. }
  10598. //
  10599. // Clear the main password only if it wasn't recently modified
  10600. //
  10601. if (hwndPassword)
  10602. {
  10603. if (FALSE == SendMessageU(hwndPassword, EM_GETMODIFY, 0L, 0L))
  10604. {
  10605. CmWipePassword(pArgs->szPassword);
  10606. SetDlgItemTextU(hwndDlg, IDC_MAIN_PASSWORD_EDIT, TEXT(""));
  10607. }
  10608. }
  10609. pArgs->fIgnoreChangeNotification = FALSE;
  10610. }
  10611. }
  10612. }
  10613. //----------------------------------------------------------------------------
  10614. //
  10615. // Function: ReloadCredentials
  10616. //
  10617. // Synopsis: Wrapper to reload credentials into the editboxes
  10618. //
  10619. // Arguments: pArgs - ptr to ArgsStruct
  10620. // hwndDlg - HWND to dialog
  10621. // dwWhichCredType - type of credential to reload
  10622. //
  10623. // Returns: NONE
  10624. //
  10625. // History: 03/24/2001 tomkel Created
  10626. //
  10627. //----------------------------------------------------------------------------
  10628. VOID ReloadCredentials(ArgsStruct *pArgs, HWND hwndDlg, DWORD dwWhichCredType)
  10629. {
  10630. if (NULL == pArgs || NULL == hwndDlg)
  10631. {
  10632. MYDBGASSERT(pArgs && hwndDlg);
  10633. return;
  10634. }
  10635. pArgs->fIgnoreChangeNotification = TRUE;
  10636. RefreshCredentialInfo(pArgs, dwWhichCredType);
  10637. SetMainDlgUserInfo(pArgs, hwndDlg);
  10638. pArgs->fIgnoreChangeNotification = FALSE;
  10639. }
  10640. //----------------------------------------------------------------------------
  10641. //
  10642. // Function: VerifyAdvancedTabSettings
  10643. //
  10644. // Synopsis: Verifies and possibly modifed the connection's ICF/ICS settings
  10645. // based on what was configured in the .cms file. These functions
  10646. // depend on the hnetcfg objects and private/internal interfaces.
  10647. // We got them from the homenet team.
  10648. // Some parts of the code were taken from:
  10649. // nt\net\homenet\config\dll\saui.cpp
  10650. //
  10651. // Arguments: pArgs - ptr to ArgsStruct
  10652. //
  10653. // Returns: NONE
  10654. //
  10655. // History: 04/26/2001 tomkel Created
  10656. //
  10657. //----------------------------------------------------------------------------
  10658. VOID VerifyAdvancedTabSettings(ArgsStruct *pArgs)
  10659. {
  10660. #ifndef _WIN64
  10661. HRESULT hr;
  10662. IHNetConnection *pHNetConn = NULL;
  10663. IHNetCfgMgr *pHNetCfgMgr = NULL;
  10664. INetConnectionUiUtilities* pncuu = NULL;
  10665. BOOL fCOMInitialized = FALSE;
  10666. BOOL fEnableICF = FALSE;
  10667. BOOL fDisableICS = FALSE;
  10668. BOOL fAllowUserToModifySettings = TRUE;
  10669. if (OS_NT51)
  10670. {
  10671. CMTRACE(TEXT("VerifyAdvancedTabSettings()"));
  10672. //
  10673. // Check rights - taken from saui.cpp
  10674. //
  10675. if (FALSE == IsAdmin())
  10676. {
  10677. return;
  10678. }
  10679. fEnableICF = pArgs->piniService->GPPB(c_pszCmSection,
  10680. c_pszCmEntryEnableICF,
  10681. FALSE);
  10682. fDisableICS = pArgs->piniService->GPPB(c_pszCmSection,
  10683. c_pszCmEntryDisableICS,
  10684. FALSE);
  10685. if (fEnableICF || fDisableICS)
  10686. {
  10687. hr = CoInitialize(NULL);
  10688. if (S_OK == hr)
  10689. {
  10690. CMTRACE(TEXT("VerifyAdvancedTabSettings - Correctly Initialized COM."));
  10691. fCOMInitialized = TRUE;
  10692. }
  10693. else if (S_FALSE == hr)
  10694. {
  10695. CMTRACE(TEXT("VerifyAdvancedTabSettings - This concurrency model is already initialized. CoInitialize returned S_FALSE."));
  10696. fCOMInitialized = TRUE;
  10697. hr = S_OK;
  10698. }
  10699. else if (RPC_E_CHANGED_MODE == hr)
  10700. {
  10701. CMTRACE1(TEXT("VerifyAdvancedTabSettings - Using different concurrency model. Did not initialize COM - RPC_E_CHANGED_MODE. hr=0x%x"), hr);
  10702. hr = S_OK;
  10703. }
  10704. else
  10705. {
  10706. CMTRACE1(TEXT("VerifyAdvancedTabSettings - Failed to Initialized COM. hr=0x%x"), hr);
  10707. }
  10708. if (SUCCEEDED(hr))
  10709. {
  10710. //
  10711. // Check user permissions. Needed to initialize COM first
  10712. // Check if ZAW is denying access to the Shared Access UI - taken from saui.cpp
  10713. //
  10714. hr = HrCreateNetConnectionUtilities(&pncuu);
  10715. if (SUCCEEDED(hr) && pncuu)
  10716. {
  10717. fEnableICF = (BOOL)(fEnableICF && pncuu->UserHasPermission(NCPERM_PersonalFirewallConfig));
  10718. fDisableICS = (BOOL)(fDisableICS && pncuu->UserHasPermission(NCPERM_ShowSharedAccessUi));
  10719. if ((FALSE == fEnableICF) && (FALSE == fDisableICS))
  10720. {
  10721. goto done;
  10722. }
  10723. }
  10724. //
  10725. // Create the home networking configuration manager
  10726. //
  10727. hr = CoCreateInstance(CLSID_HNetCfgMgr, NULL, CLSCTX_ALL,
  10728. IID_IHNetCfgMgr, (void**)&pHNetCfgMgr);
  10729. if (SUCCEEDED(hr))
  10730. {
  10731. //
  10732. // Convert the entry to an IHNetConnection
  10733. //
  10734. CMTRACE(TEXT("VerifyAdvancedTabSettings - Created CLSID_HNetCfgMgr object."));
  10735. GUID *pGuid = NULL;
  10736. LPRASENTRY pRasEntry = MyRGEP(pArgs->pszRasPbk, pArgs->szServiceName, &pArgs->rlsRasLink);
  10737. if (pRasEntry && sizeof(RASENTRY_V501) >= pRasEntry->dwSize)
  10738. {
  10739. //
  10740. // Get the pGuid value
  10741. //
  10742. pGuid = &(((LPRASENTRY_V501)pRasEntry)->guidId);
  10743. hr = pHNetCfgMgr->GetIHNetConnectionForGuid(pGuid, FALSE, TRUE, &pHNetConn);
  10744. if (SUCCEEDED(hr) && pHNetConn)
  10745. {
  10746. if (fEnableICF)
  10747. {
  10748. EnableInternetFirewall(pHNetConn);
  10749. }
  10750. if (fDisableICS)
  10751. {
  10752. DisableSharing(pHNetConn);
  10753. }
  10754. }
  10755. else
  10756. {
  10757. CMTRACE1(TEXT("VerifyAdvancedTabSettings() - Call to pHNetCfgMgr->GetIHNetConnectionForGuid returned an error. hr=0x%x"), hr);
  10758. }
  10759. }
  10760. else
  10761. {
  10762. CMTRACE(TEXT("VerifyAdvancedTabSettings - Failed to LoadRAS Entry."));
  10763. }
  10764. CmFree(pRasEntry);
  10765. pRasEntry = NULL;
  10766. }
  10767. else
  10768. {
  10769. CMTRACE(TEXT("VerifyAdvancedTabSettings - Failed to create CLSID_HNetCfgMgr object."));
  10770. }
  10771. }
  10772. }
  10773. done:
  10774. //
  10775. // Clean up and Uninitilize COM
  10776. //
  10777. if (pHNetConn)
  10778. {
  10779. pHNetConn->Release();
  10780. pHNetConn = NULL;
  10781. }
  10782. if (pHNetCfgMgr)
  10783. {
  10784. pHNetCfgMgr->Release();
  10785. pHNetCfgMgr = NULL;
  10786. }
  10787. if (pncuu)
  10788. {
  10789. pncuu->Release();
  10790. pncuu = NULL;
  10791. }
  10792. if (fCOMInitialized)
  10793. {
  10794. CoUninitialize();
  10795. }
  10796. }
  10797. #endif // _WIN64
  10798. }
  10799. //----------------------------------------------------------------------------
  10800. //
  10801. // Function: FindINetConnectionByGuid
  10802. //
  10803. // Synopsis: Retrieves the INetConnection that corresponds to the given GUID.
  10804. //
  10805. // Arguments: pGuid - the guid of the connection
  10806. // ppNetCon - receives the interface
  10807. //
  10808. // Returns: HRESULT
  10809. //
  10810. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  10811. //
  10812. //----------------------------------------------------------------------------
  10813. HRESULT FindINetConnectionByGuid(GUID *pGuid, INetConnection **ppNetCon)
  10814. {
  10815. HRESULT hr;
  10816. INetConnectionManager *pManager = NULL;
  10817. IEnumNetConnection *pEnum = NULL;
  10818. INetConnection *pConn = NULL;
  10819. if (NULL == ppNetCon)
  10820. {
  10821. hr = E_INVALIDARG;
  10822. }
  10823. else if (NULL == pGuid)
  10824. {
  10825. hr = E_POINTER;
  10826. }
  10827. else
  10828. {
  10829. //
  10830. // Get the net connections manager
  10831. //
  10832. hr = CoCreateInstance(
  10833. CLSID_ConnectionManager,
  10834. NULL,
  10835. CLSCTX_ALL,
  10836. IID_INetConnectionManager,
  10837. (void**)&pManager);
  10838. if (S_OK == hr)
  10839. {
  10840. //
  10841. // Get the enumeration of connections
  10842. //
  10843. SetProxyBlanket(pManager);
  10844. hr = pManager->EnumConnections(NCME_DEFAULT, &pEnum);
  10845. pManager->Release();
  10846. }
  10847. if (S_OK == hr)
  10848. {
  10849. //
  10850. // Search for the connection with the correct guid
  10851. //
  10852. ULONG ulCount;
  10853. BOOLEAN fFound = FALSE;
  10854. SetProxyBlanket(pEnum);
  10855. do
  10856. {
  10857. NETCON_PROPERTIES *pProps = NULL;
  10858. hr = pEnum->Next(1, &pConn, &ulCount);
  10859. if (SUCCEEDED(hr) && 1 == ulCount)
  10860. {
  10861. SetProxyBlanket(pConn);
  10862. hr = pConn->GetProperties(&pProps);
  10863. if (S_OK == hr)
  10864. {
  10865. if (IsEqualGUID(pProps->guidId, *pGuid))
  10866. {
  10867. fFound = TRUE;
  10868. *ppNetCon = pConn;
  10869. (*ppNetCon)->AddRef();
  10870. }
  10871. if (pProps)
  10872. {
  10873. CoTaskMemFree (pProps->pszwName);
  10874. CoTaskMemFree (pProps->pszwDeviceName);
  10875. CoTaskMemFree (pProps);
  10876. }
  10877. }
  10878. pConn->Release();
  10879. }
  10880. }
  10881. while (FALSE == fFound && SUCCEEDED(hr) && 1 == ulCount);
  10882. //
  10883. // Normalize hr
  10884. //
  10885. hr = (fFound ? S_OK : E_FAIL);
  10886. pEnum->Release();
  10887. }
  10888. }
  10889. return hr;
  10890. }
  10891. //----------------------------------------------------------------------------
  10892. //
  10893. // Function: SetProxyBlanket
  10894. //
  10895. // Synopsis: Sets the standard COM security settings on the proxy for an object.
  10896. //
  10897. // Arguments: pUnk - the object to set the proxy blanket on
  10898. //
  10899. // Returns: None. Even if the CoSetProxyBlanket calls fail, pUnk remains
  10900. // in a usable state. Failure is expected in certain contexts, such
  10901. // as when, for example, we're being called w/in the netman process --
  10902. // in this case, we have direct pointers to the netman objects, instead
  10903. // of going through a proxy.
  10904. //
  10905. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  10906. //
  10907. //----------------------------------------------------------------------------
  10908. VOID SetProxyBlanket(IUnknown *pUnk)
  10909. {
  10910. HRESULT hr;
  10911. if (NULL == pUnk)
  10912. {
  10913. return;
  10914. }
  10915. hr = CoSetProxyBlanket(
  10916. pUnk,
  10917. RPC_C_AUTHN_WINNT, // use NT default security
  10918. RPC_C_AUTHZ_NONE, // use NT default authentication
  10919. NULL, // must be null if default
  10920. RPC_C_AUTHN_LEVEL_CALL, // call
  10921. RPC_C_IMP_LEVEL_IMPERSONATE,
  10922. NULL, // use process token
  10923. EOAC_NONE
  10924. );
  10925. if (SUCCEEDED(hr))
  10926. {
  10927. IUnknown * pUnkSet = NULL;
  10928. hr = pUnk->QueryInterface(&pUnkSet);
  10929. if (SUCCEEDED(hr))
  10930. {
  10931. hr = CoSetProxyBlanket(
  10932. pUnkSet,
  10933. RPC_C_AUTHN_WINNT, // use NT default security
  10934. RPC_C_AUTHZ_NONE, // use NT default authentication
  10935. NULL, // must be null if default
  10936. RPC_C_AUTHN_LEVEL_CALL, // call
  10937. RPC_C_IMP_LEVEL_IMPERSONATE,
  10938. NULL, // use process token
  10939. EOAC_NONE
  10940. );
  10941. pUnkSet->Release();
  10942. }
  10943. }
  10944. }
  10945. //----------------------------------------------------------------------------
  10946. //
  10947. // Function: EnableInternetFirewall
  10948. //
  10949. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  10950. // This is part of the internal api.
  10951. //
  10952. // Arguments: pHNetConn - HNetConnection
  10953. //
  10954. // Returns: None.
  10955. //
  10956. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  10957. //
  10958. //----------------------------------------------------------------------------
  10959. VOID EnableInternetFirewall(IHNetConnection *pHNetConn)
  10960. {
  10961. HRESULT hr = S_FALSE;
  10962. BOOLEAN bEnabled = FALSE;
  10963. if (NULL == pHNetConn)
  10964. {
  10965. return;
  10966. }
  10967. hr = InternalGetFirewallEnabled(pHNetConn, &bEnabled);
  10968. if (SUCCEEDED(hr) && !bEnabled)
  10969. {
  10970. IHNetFirewalledConnection* pFirewalledConnection = NULL;
  10971. hr = pHNetConn->Firewall(&pFirewalledConnection);
  10972. if (SUCCEEDED(hr))
  10973. {
  10974. if (pFirewalledConnection)
  10975. {
  10976. pFirewalledConnection->Release();
  10977. pFirewalledConnection = NULL;
  10978. }
  10979. }
  10980. }
  10981. }
  10982. //----------------------------------------------------------------------------
  10983. //
  10984. // Function: InternalGetFirewallEnabled
  10985. //
  10986. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  10987. //
  10988. // Arguments: pHNetConnection - HNetConnection
  10989. // pbEnabled - [out] whether the Firewall is enabled
  10990. //
  10991. // Returns: HRESULT
  10992. //
  10993. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  10994. //
  10995. //----------------------------------------------------------------------------
  10996. HRESULT InternalGetFirewallEnabled(IHNetConnection *pHNetConnection, BOOLEAN *pbEnabled)
  10997. {
  10998. HRESULT hr;
  10999. HNET_CONN_PROPERTIES* pProps = NULL;
  11000. if (NULL == pHNetConnection)
  11001. {
  11002. hr = E_INVALIDARG;
  11003. }
  11004. else if (NULL == pbEnabled)
  11005. {
  11006. hr = E_POINTER;
  11007. }
  11008. else
  11009. {
  11010. *pbEnabled = FALSE;
  11011. hr = pHNetConnection->GetProperties(&pProps);
  11012. if (SUCCEEDED(hr))
  11013. {
  11014. if (pProps->fFirewalled)
  11015. {
  11016. *pbEnabled = TRUE;
  11017. }
  11018. CoTaskMemFree(pProps);
  11019. }
  11020. }
  11021. return hr;
  11022. }
  11023. //----------------------------------------------------------------------------
  11024. //
  11025. // Function: DisableSharing
  11026. //
  11027. // Synopsis: Taken from : CNetSharingConfiguration::EnableInternetFirewall
  11028. //
  11029. // Arguments: pHNetConn - HNetConnection
  11030. //
  11031. // Returns: HRESULT
  11032. //
  11033. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11034. //
  11035. //----------------------------------------------------------------------------
  11036. STDMETHODIMP DisableSharing(IHNetConnection *pHNetConn)
  11037. {
  11038. HRESULT hr;
  11039. BOOLEAN bEnabled = FALSE;
  11040. SHARINGCONNECTIONTYPE Type;
  11041. if (NULL == pHNetConn)
  11042. {
  11043. return E_INVALIDARG;
  11044. }
  11045. hr = InternalGetSharingEnabled(pHNetConn, &bEnabled, &Type);
  11046. if (SUCCEEDED(hr) && bEnabled )
  11047. {
  11048. switch(Type)
  11049. {
  11050. case ICSSHARINGTYPE_PUBLIC:
  11051. {
  11052. IHNetIcsPublicConnection* pPublicConnection = NULL;
  11053. hr = pHNetConn->GetControlInterface(
  11054. __uuidof(IHNetIcsPublicConnection),
  11055. reinterpret_cast<void**>(&pPublicConnection) );
  11056. if (SUCCEEDED(hr))
  11057. {
  11058. hr = pPublicConnection->Unshare();
  11059. if (pPublicConnection)
  11060. {
  11061. pPublicConnection->Release();
  11062. pPublicConnection = NULL;
  11063. }
  11064. }
  11065. }
  11066. break;
  11067. case ICSSHARINGTYPE_PRIVATE:
  11068. {
  11069. IHNetIcsPrivateConnection* pPrivateConnection = NULL;
  11070. hr = pHNetConn->GetControlInterface(
  11071. __uuidof(IHNetIcsPrivateConnection),
  11072. reinterpret_cast<void**>(&pPrivateConnection) );
  11073. if (SUCCEEDED(hr))
  11074. {
  11075. hr = pPrivateConnection->RemoveFromIcs();
  11076. if (pPrivateConnection)
  11077. {
  11078. pPrivateConnection->Release();
  11079. pPrivateConnection = NULL;
  11080. }
  11081. }
  11082. }
  11083. break;
  11084. default:
  11085. hr = E_UNEXPECTED;
  11086. }
  11087. }
  11088. return hr;
  11089. }
  11090. //----------------------------------------------------------------------------
  11091. //
  11092. // Function: InternalGetSharingEnabled
  11093. //
  11094. // Synopsis: Returns whether sharing is enabled on a given connection
  11095. //
  11096. // Arguments: pHNetConnection - HNetConnection
  11097. // pbEnabled - [out] returns the value
  11098. // pType - type of connection
  11099. //
  11100. // Returns: HRESULT
  11101. //
  11102. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\hnapi.cpp
  11103. //
  11104. //----------------------------------------------------------------------------
  11105. HRESULT InternalGetSharingEnabled(IHNetConnection *pHNetConnection, BOOLEAN *pbEnabled, SHARINGCONNECTIONTYPE* pType)
  11106. {
  11107. HRESULT hr;
  11108. HNET_CONN_PROPERTIES* pProps;
  11109. if (NULL == pHNetConnection)
  11110. {
  11111. hr = E_INVALIDARG;
  11112. }
  11113. else if ((NULL == pbEnabled) || (NULL == pType))
  11114. {
  11115. hr = E_POINTER;
  11116. }
  11117. else
  11118. {
  11119. *pbEnabled = FALSE;
  11120. *pType = ICSSHARINGTYPE_PUBLIC;
  11121. hr = pHNetConnection->GetProperties(&pProps);
  11122. if (SUCCEEDED(hr))
  11123. {
  11124. if (pProps->fIcsPublic)
  11125. {
  11126. *pbEnabled = TRUE;
  11127. *pType = ICSSHARINGTYPE_PUBLIC;
  11128. }
  11129. else if (pProps->fIcsPrivate)
  11130. {
  11131. *pbEnabled = TRUE;
  11132. *pType = ICSSHARINGTYPE_PRIVATE;
  11133. }
  11134. CoTaskMemFree(pProps);
  11135. }
  11136. }
  11137. return hr;
  11138. }
  11139. //----------------------------------------------------------------------------
  11140. //
  11141. // Function: HrCreateNetConnectionUtilities
  11142. //
  11143. // Synopsis: Returns the pointer to the connection ui utilities object
  11144. //
  11145. // Arguments: ppncuu - pointer to INetConnectionUiUtilities object
  11146. //
  11147. // Returns: HRESULT
  11148. //
  11149. // History: 04/26/2001 tomkel Taken & modified from nt\net\homenet\config\dll\saui.cpp
  11150. //
  11151. //----------------------------------------------------------------------------
  11152. HRESULT APIENTRY HrCreateNetConnectionUtilities(INetConnectionUiUtilities ** ppncuu)
  11153. {
  11154. HRESULT hr = E_INVALIDARG;
  11155. if (ppncuu)
  11156. {
  11157. hr = CoCreateInstance (CLSID_NetConnectionUiUtilities, NULL,
  11158. CLSCTX_INPROC_SERVER,
  11159. IID_INetConnectionUiUtilities, (void**)ppncuu);
  11160. }
  11161. return hr;
  11162. }
  11163. //+----------------------------------------------------------------------------
  11164. //
  11165. // Function: IsMemberOfGroup
  11166. //
  11167. // Synopsis: This function return TRUE if the current user is a member of
  11168. // the passed and FALSE passed in Group RID.
  11169. //
  11170. // Arguments: DWORD dwGroupRID -- the RID of the group to check membership of
  11171. // BOOL bUseBuiltinDomainRid -- whether the SECURITY_BUILTIN_DOMAIN_RID
  11172. // RID should be used to build the Group
  11173. // SID
  11174. //
  11175. // Returns: BOOL - TRUE if the user is a member of the specified group
  11176. //
  11177. // History: quintinb Shamelessly stolen from MSDN 02/19/98
  11178. // quintinb Reworked and renamed 06/18/99
  11179. // to apply to more than just Admins
  11180. // quintinb Rewrote to use CheckTokenMemberShip 08/18/99
  11181. // since the MSDN method was no longer
  11182. // correct on NT5 -- 389229
  11183. // tomkel Taken from cmstp and modified for use 05/09/2001
  11184. // here
  11185. //
  11186. //+----------------------------------------------------------------------------
  11187. BOOL IsMemberOfGroup(DWORD dwGroupRID, BOOL bUseBuiltinDomainRid)
  11188. {
  11189. PSID psidGroup = NULL;
  11190. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  11191. BOOL bSuccess = FALSE;
  11192. if (OS_NT5)
  11193. {
  11194. //
  11195. // Make a SID for the Group we are checking for, Note that we if we need the Built
  11196. // in Domain RID (for Groups like Administrators, PowerUsers, Users, etc)
  11197. // then we will have two entries to pass to AllocateAndInitializeSid. Otherwise,
  11198. // (for groups like Authenticated Users) we will only have one.
  11199. //
  11200. BYTE byNum;
  11201. DWORD dwFirstRID;
  11202. DWORD dwSecondRID;
  11203. if (bUseBuiltinDomainRid)
  11204. {
  11205. byNum = 2;
  11206. dwFirstRID = SECURITY_BUILTIN_DOMAIN_RID;
  11207. dwSecondRID = dwGroupRID;
  11208. }
  11209. else
  11210. {
  11211. byNum = 1;
  11212. dwFirstRID = dwGroupRID;
  11213. dwSecondRID = 0;
  11214. }
  11215. if (AllocateAndInitializeSid(&siaNtAuthority, byNum, dwFirstRID, dwSecondRID,
  11216. 0, 0, 0, 0, 0, 0, &psidGroup))
  11217. {
  11218. //
  11219. // Now we need to dynamically load the CheckTokenMemberShip API from
  11220. // advapi32.dll since it is a Win2k only API.
  11221. //
  11222. HMODULE hAdvapi = LoadLibraryExU(TEXT("advapi32.dll"), NULL, 0);
  11223. if (hAdvapi)
  11224. {
  11225. typedef BOOL (WINAPI *pfnCheckTokenMembershipSpec)(HANDLE, PSID, PBOOL);
  11226. pfnCheckTokenMembershipSpec pfnCheckTokenMembership;
  11227. pfnCheckTokenMembership = (pfnCheckTokenMembershipSpec)GetProcAddress(hAdvapi, "CheckTokenMembership");
  11228. if (pfnCheckTokenMembership)
  11229. {
  11230. //
  11231. // Check to see if the user is actually a member of the group in question
  11232. //
  11233. if (!(pfnCheckTokenMembership)(NULL, psidGroup, &bSuccess))
  11234. {
  11235. bSuccess = FALSE;
  11236. CMASSERTMSG(FALSE, TEXT("CheckTokenMemberShip Failed."));
  11237. }
  11238. }
  11239. else
  11240. {
  11241. CMASSERTMSG(FALSE, TEXT("IsMemberOfGroup -- GetProcAddress failed for CheckTokenMemberShip"));
  11242. }
  11243. }
  11244. else
  11245. {
  11246. CMASSERTMSG(FALSE, TEXT("IsMemberOfGroup -- Unable to get the module handle for advapi32.dll"));
  11247. }
  11248. FreeSid (psidGroup);
  11249. if (hAdvapi)
  11250. {
  11251. FreeLibrary(hAdvapi);
  11252. }
  11253. }
  11254. }
  11255. return bSuccess;
  11256. }
  11257. //+----------------------------------------------------------------------------
  11258. //
  11259. // Function: IsAdmin
  11260. //
  11261. // Synopsis: Check to see if the user is a member of the Administrators group
  11262. // or not.
  11263. //
  11264. // Arguments: None
  11265. //
  11266. // Returns: BOOL - TRUE if the current user is an Administrator
  11267. //
  11268. // History: quintinb Created Header 8/18/99
  11269. // tomkel Taken from cmstp 05/09/2001
  11270. //
  11271. //+----------------------------------------------------------------------------
  11272. BOOL IsAdmin(VOID)
  11273. {
  11274. return IsMemberOfGroup(DOMAIN_ALIAS_RID_ADMINS, TRUE); // TRUE == bUseBuiltinDomainRid
  11275. }