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

4082 lines
127 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1993-1996 Microsoft Corporation. All Rights Reserved.
  3. //
  4. // MODULE: conman.cpp
  5. //
  6. // PURPOSE: Defines the CConnectionManager object for Athena.
  7. //
  8. #include "pch.hxx"
  9. #include "conman.h"
  10. #include "error.h"
  11. #include "strconst.h"
  12. #include "rasdlgsp.h"
  13. #include "resource.h"
  14. #include "xpcomm.h"
  15. #include "goptions.h"
  16. #include "thormsgs.h"
  17. #include "wininet.h"
  18. #include "shlwapip.h"
  19. #include "demand.h"
  20. #include "dllmain.h"
  21. #include "browser.h"
  22. #include <urlmon.h>
  23. #include "menures.h"
  24. #include "workoff.h"
  25. #include <sync.h>
  26. ASSERTDATA
  27. #define DEF_HANGUP_WAIT 10 // Seconds
  28. static const TCHAR s_szRasDlgDll[] = "RASDLG.DLL";
  29. #ifdef UNICODE
  30. static const TCHAR s_szRasDialDlg[] = "RasDialDlgW";
  31. static const TCHAR s_szRasEntryDlg[] = "RasEntryDlgW";
  32. #else
  33. static const TCHAR s_szRasDialDlg[] = "RasDialDlgA";
  34. static const TCHAR s_szRasEntryDlg[] = "RasEntryDlgA";
  35. #endif
  36. BOOL FIsPlatformWinNT();
  37. //
  38. // FUNCTION: CConnectionManager::CConnectionManager()
  39. //
  40. // PURPOSE: Constructor
  41. //
  42. CConnectionManager::CConnectionManager()
  43. {
  44. m_cRef = 1;
  45. // Synchronization Objects
  46. InitializeCriticalSection(&m_cs);
  47. m_hMutexDial = INVALID_HANDLE_VALUE;
  48. m_pAcctMan = 0;
  49. m_fSavePassword = 0;
  50. m_fRASLoadFailed = 0;
  51. m_fOffline = 0;
  52. m_dwConnId = 0;
  53. ZeroMemory(&m_rConnInfo, sizeof(CONNINFO));
  54. m_rConnInfo.state = CIS_REFRESH;
  55. *m_szConnectName = 0;
  56. ZeroMemory(&m_rdp, sizeof(RASDIALPARAMS));
  57. m_hInstRas = NULL;
  58. m_hInstRasDlg = NULL;
  59. m_pNotifyList = NULL;
  60. m_pConnListHead = NULL;
  61. m_hInstSensDll = NULL;
  62. m_fMobilityPackFailed = FALSE;
  63. m_pIsDestinationReachable = NULL;
  64. m_pIsNetworkAlive = NULL;
  65. m_fTryAgain = FALSE;
  66. m_fDialerUI = FALSE;
  67. }
  68. //
  69. // FUNCTION: CConnectionManager::~CConnectionManager()
  70. //
  71. // PURPOSE: Destructor
  72. //
  73. CConnectionManager::~CConnectionManager()
  74. {
  75. SafeRelease(m_pAcctMan);
  76. FreeNotifyList();
  77. EnterCriticalSection(&m_cs);
  78. if (m_hInstRas)
  79. FreeLibrary(m_hInstRas);
  80. if (m_hInstRasDlg)
  81. FreeLibrary(m_hInstRasDlg);
  82. if (m_hInstSensDll)
  83. FreeLibrary(m_hInstSensDll);
  84. CloseHandle(m_hMutexDial);
  85. LeaveCriticalSection(&m_cs);
  86. DeleteCriticalSection(&m_cs);
  87. EmptyConnList();
  88. }
  89. //
  90. // FUNCTION: CConnectionManager::HrInit()
  91. //
  92. // PURPOSE: Initalizes the connection manager by attempting to load RAS
  93. // and storing a pointer to the Account Manager object that is
  94. // passed in.
  95. //
  96. // PARAMETERS:
  97. // <in> pAcctMan - Pointer to the account manager object that we will
  98. // use to retrieve account information and register for
  99. // account changes.
  100. //
  101. // RETURN VALUE:
  102. // S_OK Everything is hunky-dorie
  103. // HR_E_ALREADYEXISTS We already exist, can't do it twice.
  104. // HR_S_RASNOTLOADED The system doesn't have RAS installed.
  105. //
  106. HRESULT CConnectionManager::HrInit(IImnAccountManager *pAcctMan)
  107. {
  108. HRESULT hr = S_OK;
  109. // Make a copy of the account manager pointer
  110. if (NULL == pAcctMan)
  111. {
  112. AssertSz(pAcctMan, _T("CConnectionManager::HrInit() - Requires an IAccountManager pointer."));
  113. return (E_INVALIDARG);
  114. }
  115. m_pAcctMan = pAcctMan;
  116. m_pAcctMan->AddRef();
  117. // Register a window class for our advise handling
  118. WNDCLASS wc;
  119. wc.style = 0;
  120. wc.lpfnWndProc = NotifyWndProc;
  121. wc.cbClsExtra = 0;
  122. wc.cbWndExtra = 0;
  123. wc.hInstance = g_hInst;
  124. wc.hIcon = 0;
  125. wc.hCursor = 0;
  126. wc.hbrBackground = 0;
  127. wc.lpszMenuName = 0;
  128. wc.lpszClassName = NOTIFY_HWND;
  129. RegisterClass(&wc);
  130. m_hMutexDial = CreateMutex(NULL, FALSE, NULL);
  131. if (NULL == m_hMutexDial)
  132. return (E_FAIL);
  133. return (S_OK);
  134. }
  135. HRESULT STDMETHODCALLTYPE CConnectionManager::QueryInterface(REFIID riid, LPVOID *ppvObject)
  136. {
  137. if (!ppvObject)
  138. return E_INVALIDARG;
  139. if (IsEqualIID(riid, IID_IUnknown))
  140. *ppvObject = (LPVOID) (IUnknown*) this;
  141. else if (IsEqualIID(riid, IID_IImnAdviseAccount))
  142. *ppvObject = (LPVOID) (IImnAdviseAccount*) this;
  143. else
  144. *ppvObject = NULL;
  145. if (*ppvObject)
  146. {
  147. AddRef();
  148. return (S_OK);
  149. }
  150. else
  151. return (E_NOINTERFACE);
  152. }
  153. ULONG STDMETHODCALLTYPE CConnectionManager::AddRef(void)
  154. {
  155. return (++m_cRef);
  156. }
  157. ULONG STDMETHODCALLTYPE CConnectionManager::Release(void)
  158. {
  159. ULONG cRef = --m_cRef;
  160. if (m_cRef == 0)
  161. {
  162. delete this;
  163. return (0);
  164. }
  165. return (cRef);
  166. }
  167. HRESULT STDMETHODCALLTYPE CConnectionManager::AdviseAccount(DWORD dwAdviseType,
  168. ACTX *pactx)
  169. {
  170. IImnAccount *pAccount;
  171. DWORD dwConnection;
  172. // SendAdvise(CONNNOTIFY_RASACCOUNTSCHANGED, 0);
  173. switch (dwAdviseType)
  174. {
  175. case AN_ACCOUNT_DELETED:
  176. {
  177. if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pactx->pszAccountID, &pAccount)))
  178. {
  179. if (SUCCEEDED(pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  180. {
  181. if (dwConnection == CONNECTION_TYPE_RAS)
  182. {
  183. TCHAR szConnection[CCHMAX_CONNECTOID];
  184. *szConnection = '\0';
  185. if (SUCCEEDED(pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnection,
  186. ARRAYSIZE(szConnection))) && *szConnection)
  187. {
  188. RemoveFromConnList(szConnection);
  189. }
  190. }
  191. }
  192. }
  193. break;
  194. }
  195. }
  196. return (S_OK);
  197. }
  198. void CConnectionManager::EmptyConnList()
  199. {
  200. ConnListNode *pCur;
  201. //Delete all the nodes
  202. while (m_pConnListHead != NULL)
  203. {
  204. pCur = m_pConnListHead;
  205. m_pConnListHead = m_pConnListHead->pNext;
  206. delete pCur;
  207. }
  208. m_pConnListHead = NULL;
  209. }
  210. void CConnectionManager::RemoveFromConnList(LPTSTR pszRasConn)
  211. {
  212. ConnListNode *prev = NULL,
  213. *Cur = m_pConnListHead;
  214. LPTSTR pRasConn;
  215. while (Cur != NULL)
  216. {
  217. if (0 == lstrcmpi(pszRasConn, Cur->pszRasConn))
  218. {
  219. if (prev == NULL)
  220. {
  221. m_pConnListHead = Cur->pNext;
  222. }
  223. else
  224. {
  225. prev->pNext = Cur->pNext;
  226. }
  227. delete Cur;
  228. }
  229. else
  230. {
  231. prev = Cur;
  232. Cur = Cur->pNext;
  233. }
  234. }
  235. }
  236. HRESULT CConnectionManager::AddToConnList(LPTSTR pszRasConn)
  237. {
  238. //We don't have to make sure that this is not already in the list because once
  239. //it is in the list, that means its already connected and so we don't land up in this
  240. //situation after that
  241. ConnListNode *pnext;
  242. HRESULT hres;
  243. IImnAccount *pAccount;
  244. pnext = m_pConnListHead;
  245. m_pConnListHead = new ConnListNode;
  246. if (m_pConnListHead != NULL)
  247. {
  248. m_pConnListHead->pNext = pnext;
  249. StrCpyN(m_pConnListHead->pszRasConn, pszRasConn, ARRAYSIZE(m_pConnListHead->pszRasConn));
  250. hres = S_OK;
  251. }
  252. else
  253. hres = E_FAIL;
  254. return hres;
  255. }
  256. HRESULT CConnectionManager::SearchConnList(LPTSTR pszRasConn)
  257. {
  258. ConnListNode *pCur = m_pConnListHead;
  259. while (pCur != NULL)
  260. {
  261. if (0 == lstrcmpi(pszRasConn, pCur->pszRasConn))
  262. return S_OK;
  263. pCur = pCur->pNext;
  264. }
  265. return E_FAIL;
  266. }
  267. //
  268. // FUNCTION: CConnectionManager::CanConnect()
  269. //
  270. // PURPOSE: Determines if the caller can connect to the given account
  271. // using the existing connection.
  272. //
  273. // PARAMETERS:
  274. // <in> pAccount - Pointer to the account object the caller wants to
  275. // connect to.
  276. //
  277. // RETURN VALUE:
  278. // S_OK - The caller can connect using the existing connection
  279. // S_FALSE - There is no existing connection, so there is no reason the
  280. // caller can't connect.
  281. // E_FAIL - The existing connection is different from the account's
  282. // connection. The user must hang up and dial again to connect
  283. //
  284. HRESULT CConnectionManager::CanConnect(IImnAccount *pAccount)
  285. {
  286. HRESULT hr;
  287. DWORD dwConnection;
  288. IImnAccount *pDefault = 0;
  289. LPRASCONN pConnections = NULL;
  290. ULONG cConnections = 0;
  291. BOOL fFound = 0;
  292. // Check to see if we're working offline
  293. if (IsGlobalOffline())
  294. return (HR_E_OFFLINE);
  295. // If the connection the user is looking for is not RAS, then we just
  296. // return success.
  297. if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  298. {
  299. // If we didn't get the connection information, then we look for the
  300. // connection from the default server of this type
  301. if (FAILED(hr = GetDefaultConnection(pAccount, &pDefault)))
  302. {
  303. // Bug #36071 - If we haven't set up any accounts of this type yet,
  304. // we'd fail. As a result, if you fire a URL to a server
  305. // we'd never try to connect and download. I'm going
  306. // to change this to succeed and we'll see what type
  307. // of bugs that creates.
  308. return (S_OK);
  309. }
  310. // We're going to use the default from now on
  311. pAccount = pDefault;
  312. if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  313. {
  314. // Bug #36071 - If we haven't set up any accounts of this type yet,
  315. // we'd fail. As a result, if you fire a URL to a server
  316. // we'd never try to connect and download. I'm going
  317. // to change this to succeed and we'll see what type
  318. // of bugs that creates.
  319. return (S_OK);
  320. }
  321. }
  322. hr = OEIsDestinationReachable(pAccount, dwConnection);
  323. //I don't think we should be doing this here. Review again
  324. /*
  325. if ((hr == S_OK) && (dwConnection == CONNECTION_TYPE_RAS || dwConnection == CONNECTION_TYPE_INETSETTINGS))
  326. {
  327. m_rConnInfo.fConnected = TRUE;
  328. }
  329. */
  330. //exit:
  331. SafeRelease(pDefault);
  332. return (hr);
  333. }
  334. //
  335. // FUNCTION: CConnectionManager::CanConnect()
  336. //
  337. // PURPOSE: Determines if the caller can connect to the given account
  338. // using the existing connection.
  339. //
  340. // PARAMETERS:
  341. // <in> pszAccount - Pointer to the name of the account the caller wants
  342. // to connect to.
  343. //
  344. // RETURN VALUE:
  345. // S_OK - The caller can connect using the existing connection
  346. // S_FALSE - There is no existing connection, so there is no reason the
  347. // caller can't connect.
  348. // E_FAIL - The existing connection is different from the account's
  349. // connection. The user must hang up and dial again to connect
  350. // E_INVALIDARG - The account doesn't exist
  351. //
  352. HRESULT CConnectionManager::CanConnect(LPTSTR pszAccount)
  353. {
  354. IImnAccount *pAccount = NULL;
  355. HRESULT hr;
  356. // Check to see if we're working offline
  357. if (IsGlobalOffline())
  358. return (HR_E_OFFLINE);
  359. // Look up the account name in the account manager to get the account
  360. // object.
  361. Assert(m_pAcctMan);
  362. if (lstrcmpi(pszAccount, STR_LOCALSTORE) == 0)
  363. return(S_OK);
  364. if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount)))
  365. {
  366. // Call through to the polymorphic version of us
  367. hr = CanConnect(pAccount);
  368. pAccount->Release();
  369. }
  370. else
  371. {
  372. // Bug #36071 - If we haven't set up any accounts of this type yet,
  373. // we'd fail. As a result, if you fire a URL to a server
  374. // we'd never try to connect and download. I'm going
  375. // to change this to succeed and we'll see what type
  376. // of bugs that creates.
  377. hr = S_OK;
  378. }
  379. return (hr);
  380. }
  381. BOOL CConnectionManager::IsAccountDisabled(LPTSTR pszAccount)
  382. {
  383. IImnAccount *pAccount = NULL;
  384. DWORD dw;
  385. // Look up the account name in the account manager to get the account
  386. // object.
  387. Assert(m_pAcctMan);
  388. if (lstrcmpi(pszAccount, STR_LOCALSTORE) == 0)
  389. return(FALSE);
  390. if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount)))
  391. {
  392. if (SUCCEEDED(pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dw)) && dw)
  393. {
  394. if(HideHotmail())
  395. return(TRUE);
  396. }
  397. return(FALSE);
  398. }
  399. return(TRUE);
  400. }
  401. //
  402. // FUNCTION: CConnectionManager::Connect()
  403. //
  404. // PURPOSE: Attempts to establish a connection for the account specified.
  405. //
  406. // PARAMETERS:
  407. // <in> pAccount - Pointer to the account object to connect to.
  408. // <in> hwnd - Handle of the window to show UI over. Only needed if
  409. // fShowUI is TRUE.
  410. // <in> fShowUI - TRUE if the functions are allowed to display UI.
  411. //
  412. // RETURN VALUE:
  413. // S_OK - We're connected
  414. // E_UNEXPECTED - There wasn't enough information in pAccount to figure
  415. // figure out which connection to use.
  416. //
  417. HRESULT CConnectionManager::Connect(IImnAccount *pAccount, HWND hwnd, BOOL fShowUI)
  418. {
  419. HRESULT hr = S_OK;
  420. DWORD dwConnection;
  421. IImnAccount *pDefault = 0;
  422. if (!m_fDialerUI)
  423. {
  424. m_fDialerUI = TRUE;
  425. // Check to see if we're working offline
  426. if (IsGlobalOffline())
  427. {
  428. if (fShowUI)
  429. {
  430. if (IDNO == AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline),
  431. 0, MB_YESNO | MB_ICONEXCLAMATION ))
  432. {
  433. m_fDialerUI = FALSE;
  434. return (HR_E_OFFLINE);
  435. }
  436. else
  437. g_pConMan->SetGlobalOffline(FALSE);
  438. }
  439. else
  440. {
  441. m_fDialerUI = FALSE;
  442. return (HR_E_OFFLINE);
  443. }
  444. }
  445. m_fDialerUI = FALSE;
  446. }
  447. if (CanConnect(pAccount) == S_OK)
  448. {
  449. return S_OK;
  450. }
  451. // If the connection the user is looking for is not RAS, then we just
  452. // return success.
  453. if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  454. {
  455. // If we didn't get the connection information, then we look for the
  456. // connection from the default server of this type
  457. if (FAILED(hr = GetDefaultConnection(pAccount, &pDefault)))
  458. {
  459. // Bug #36071 - If we haven't set up any accounts of this type yet,
  460. // we'd fail. As a result, if you fire a URL to a server
  461. // we'd never try to connect and download. I'm going
  462. // to change this to succeed and we'll see what type
  463. // of bugs that creates.
  464. return (S_OK);
  465. }
  466. // We're going to use the default from now on
  467. pAccount = pDefault;
  468. if (FAILED(hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection)))
  469. {
  470. // Bug #36071 - If we haven't set up any accounts of this type yet,
  471. // we'd fail. As a result, if you fire a URL to a server
  472. // we'd never try to connect and download. I'm going
  473. // to change this to succeed and we'll see what type
  474. // of bugs that creates.
  475. hr = S_OK;
  476. goto exit;
  477. }
  478. }
  479. if (dwConnection == CONNECTION_TYPE_INETSETTINGS)
  480. {
  481. hr = ConnectUsingIESettings(hwnd, fShowUI);
  482. goto exit;
  483. }
  484. if (dwConnection == CONNECTION_TYPE_LAN)
  485. {
  486. //CanConnect already told us that Lan is not present
  487. hr = E_FAIL;
  488. goto exit;
  489. }
  490. if (dwConnection != CONNECTION_TYPE_RAS)
  491. {
  492. hr = S_OK;
  493. goto exit;
  494. }
  495. // Get the name of the connection while we're at it.
  496. TCHAR szConnection[CCHMAX_CONNECTOID];
  497. if (FAILED(hr = pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnection,
  498. ARRAYSIZE(szConnection))))
  499. {
  500. AssertSz(FALSE, _T("CConnectionManager::Connect() - No connection name."));
  501. hr = E_UNEXPECTED;
  502. goto exit;
  503. }
  504. hr = ConnectActual(szConnection, hwnd, fShowUI);
  505. exit:
  506. SafeRelease(pDefault);
  507. return (hr);
  508. }
  509. //
  510. // FUNCTION: CConnectionManager::Connect()
  511. //
  512. // PURPOSE: Attempts to establish a connection for the account specified.
  513. //
  514. // PARAMETERS:
  515. // <in> pszAccount - Name of the account to connect to.
  516. // <in> hwnd - Handle of the window to show UI over. Only needed if
  517. // fShowUI is TRUE.
  518. // <in> fShowUI - TRUE if the functions are allowed to display UI.
  519. //
  520. // RETURN VALUE:
  521. // <???>
  522. //
  523. HRESULT CConnectionManager::Connect(LPTSTR pszAccount, HWND hwnd, BOOL fShowUI)
  524. {
  525. IImnAccount *pAccount = NULL;
  526. HRESULT hr;
  527. // Check to see if we're working offline
  528. if (!m_fDialerUI)
  529. {
  530. m_fDialerUI = TRUE;
  531. // Check to see if we're working offline
  532. if (IsGlobalOffline())
  533. {
  534. if (fShowUI)
  535. {
  536. if (IDNO == AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline),
  537. 0, MB_YESNO | MB_ICONEXCLAMATION ))
  538. {
  539. m_fDialerUI = FALSE;
  540. return (HR_E_OFFLINE);
  541. }
  542. else
  543. g_pConMan->SetGlobalOffline(FALSE);
  544. }
  545. else
  546. {
  547. m_fDialerUI = FALSE;
  548. return (HR_E_OFFLINE);
  549. }
  550. }
  551. m_fDialerUI = FALSE;
  552. }
  553. // Look up the account name in the account manager to get the account
  554. // object.
  555. Assert(m_pAcctMan);
  556. // if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_NAME, pszAccount, &pAccount)))
  557. if (SUCCEEDED(m_pAcctMan->FindAccount(AP_ACCOUNT_ID, pszAccount, &pAccount)))
  558. {
  559. // Call through to the polymorphic version of us
  560. hr = Connect(pAccount, hwnd, fShowUI);
  561. pAccount->Release();
  562. }
  563. else
  564. {
  565. // Bug #36071 - If we haven't set up any accounts of this type yet,
  566. // we'd fail. As a result, if you fire a URL to a server
  567. // we'd never try to connect and download. I'm going
  568. // to change this to succeed and we'll see what type
  569. // of bugs that creates.
  570. hr = S_OK;
  571. }
  572. return (hr);
  573. }
  574. //
  575. // FUNCTION: CConnectionManager::Connect()
  576. //
  577. // PURPOSE: Attempts to establish a connection for the account specified.
  578. //
  579. // PARAMETERS:
  580. // <in> hMenu - Handle of the menu that was used to select the account
  581. // to connect to.
  582. // <in> cmd - Cmd ID from the menu that says which account to use.
  583. // <in> hwnd - Handle to display UI over.
  584. //
  585. // RETURN VALUE:
  586. // <???>
  587. //
  588. HRESULT CConnectionManager::Connect(HMENU hMenu, DWORD cmd, HWND hwnd)
  589. {
  590. MENUITEMINFO mii;
  591. Assert(hMenu && cmd);
  592. Assert(cmd >= (DWORD) ID_CONNECT_FIRST && cmd < ((DWORD) ID_CONNECT_FIRST + GetMenuItemCount(hMenu)));
  593. // Get the account pointer from the menu item
  594. mii.cbSize = sizeof(MENUITEMINFO);
  595. mii.fMask = MIIM_DATA;
  596. mii.dwItemData = 0;
  597. if (GetMenuItemInfo(hMenu, cmd, FALSE, &mii))
  598. {
  599. Assert(mii.dwItemData);
  600. if (mii.dwItemData)
  601. {
  602. return (Connect((IImnAccount *) mii.dwItemData, hwnd, TRUE));
  603. }
  604. }
  605. return (E_UNEXPECTED);
  606. }
  607. HRESULT CConnectionManager::ConnectDefault(HWND hwnd, BOOL fShowUI)
  608. {
  609. IImnEnumAccounts *pEnum = NULL;
  610. IImnAccount *pAcct = NULL;
  611. DWORD dwConn = 0;
  612. TCHAR szAcct[CCHMAX_ACCOUNT_NAME];
  613. TCHAR szConn[CCHMAX_CONNECTOID];
  614. HRESULT hr = E_UNEXPECTED;
  615. // Get the enumerator from the account manager
  616. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum)))
  617. {
  618. pEnum->Reset();
  619. // Walk through all the accounts
  620. while (SUCCEEDED(pEnum->GetNext(&pAcct)))
  621. {
  622. // Get the connection type for this account
  623. if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn)))
  624. {
  625. // If the account is a RAS account, ask for the connectoid name
  626. // and the account name.
  627. if (dwConn == CONNECTION_TYPE_RAS || dwConn == CONNECTION_TYPE_INETSETTINGS)
  628. {
  629. break;
  630. }
  631. }
  632. SafeRelease(pAcct);
  633. }
  634. SafeRelease(pEnum);
  635. }
  636. if (pAcct)
  637. {
  638. hr = Connect(pAcct, hwnd, fShowUI);
  639. SafeRelease(pAcct);
  640. }
  641. return (hr);
  642. }
  643. //
  644. // FUNCTION: CConnectionManager::Disconnect()
  645. //
  646. // PURPOSE: Brings down the current RAS connection.
  647. //
  648. // PARAMETERS:
  649. // <in> hwnd - Handle of the window to display UI over.
  650. // <in> fShowUI - Allows to caller to determine if UI will be displayed
  651. // while disconnecting.
  652. // <in> fForce - Forces the connection down even if we didn't create it.
  653. // <in> fShutdown - TRUE if we're dropping because we're shutting down.
  654. //
  655. // RETURN VALUE:
  656. // S_OK - Everything worked.
  657. // E_FAIL - We didn't create it
  658. //
  659. HRESULT CConnectionManager::Disconnect(HWND hwnd, BOOL fShowUI, BOOL fForce,
  660. BOOL fShutdown)
  661. {
  662. HRESULT hr;
  663. TCHAR szRes[CCHMAX_STRINGRES];
  664. TCHAR szBuf[CCHMAX_STRINGRES];
  665. int idAnswer = IDYES;
  666. // RefreshConnInfo
  667. hr = RefreshConnInfo(FALSE);
  668. if (FAILED(hr))
  669. return hr;
  670. // See if we even have a RAS connection active
  671. if (!m_rConnInfo.hRasConn)
  672. return (S_OK);
  673. /*
  674. if (!(*m_rConnInfo.szCurrentConnectionName))
  675. return S_OK;
  676. */
  677. // The autodialer has it's own shutdown prompt.
  678. if (fShutdown && m_rConnInfo.fAutoDial)
  679. return (S_OK);
  680. if (fShutdown && !m_rConnInfo.fIStartedRas)
  681. return (S_OK);
  682. if (fShutdown)
  683. {
  684. AthLoadString(idsRasPromptDisconnect, szRes, ARRAYSIZE(szRes));
  685. wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, m_rConnInfo.szCurrentConnectionName);
  686. idAnswer = AthMessageBox(hwnd, MAKEINTRESOURCE(idsAthena), szBuf,
  687. 0, MB_YESNO | MB_ICONEXCLAMATION );
  688. }
  689. // Hang up
  690. if (idAnswer == IDYES)
  691. {
  692. SendAdvise(CONNNOTIFY_DISCONNECTING, NULL);
  693. if (S_FALSE == DoAutoDial(hwnd, m_rConnInfo.szCurrentConnectionName, FALSE))
  694. {
  695. InternetHangUpAndWait(m_dwConnId, DEF_HANGUP_WAIT);
  696. /*
  697. RasHangupAndWait(m_rConnInfo.hRasConn, DEF_HANGUP_WAIT);
  698. */
  699. }
  700. EnterCriticalSection(&m_cs);
  701. ZeroMemory(&m_rConnInfo, sizeof(CONNINFO));
  702. m_rConnInfo.state = CIS_CLEAN;
  703. m_dwConnId = 0;
  704. LeaveCriticalSection(&m_cs);
  705. EmptyConnList();
  706. SendAdvise(CONNNOTIFY_DISCONNECTED, NULL);
  707. return (S_OK);
  708. }
  709. return (E_FAIL);
  710. }
  711. //
  712. // FUNCTION: CConnectionManager::IsConnected()
  713. //
  714. // PURPOSE: Allows the client to query whether or not there is an active
  715. // RAS connection that we established.
  716. //
  717. // RETURN VALUE:
  718. // TRUE - We're connected, FALSE - we're not.
  719. //
  720. BOOL CConnectionManager::IsConnected(void)
  721. {
  722. BOOL f=FALSE;
  723. EnterCriticalSection(&m_cs);
  724. RefreshConnInfo();
  725. if (m_rConnInfo.hRasConn)
  726. {
  727. f = (NULL == m_rConnInfo.hRasConn) ? FALSE : TRUE;
  728. }
  729. LeaveCriticalSection(&m_cs);
  730. return f;
  731. }
  732. //
  733. // FUNCTION: CConnectionManager::Advise()
  734. //
  735. // PURPOSE: Allows the user to register to be notified whenever connection
  736. // status changes.
  737. //
  738. // PARAMETERS:
  739. // <in> pNotify - Pointer to the IConnectionNotify interface the client
  740. // would like called when events happen.
  741. //
  742. // RETURN VALUE:
  743. // S_OK - Added ok.
  744. // E_OUTOFMEMORY - Couldn't realloc the array
  745. //
  746. HRESULT CConnectionManager::Advise(IConnectionNotify *pNotify)
  747. {
  748. HRESULT hr = S_OK;
  749. if (!pNotify)
  750. return (E_INVALIDARG);
  751. EnterCriticalSection(&m_cs);
  752. // Check to see if we already have a notify window for this thread
  753. NOTIFYHWND *pTemp = m_pNotifyList;
  754. DWORD dwThread = GetCurrentThreadId();
  755. while (pTemp)
  756. {
  757. if (pTemp->dwThreadId == dwThread)
  758. break;
  759. pTemp = pTemp->pNext;
  760. }
  761. // If we didn't find a notify window for this thread, create one
  762. if (NULL == pTemp)
  763. {
  764. HWND hwndTemp = CreateWindow(NOTIFY_HWND, NULL, WS_OVERLAPPED, 10, 10, 10, 10,
  765. NULL, (HMENU) 0, g_hInst, (LPVOID) this);
  766. if (!hwndTemp)
  767. {
  768. hr = E_OUTOFMEMORY;
  769. goto exit;
  770. }
  771. if (!MemAlloc((LPVOID*) &pTemp, sizeof(NOTIFYHWND)))
  772. {
  773. RemoveProp(hwndTemp, NOTIFY_HWND);
  774. DestroyWindow(hwndTemp);
  775. hr = E_OUTOFMEMORY;
  776. goto exit;
  777. }
  778. pTemp->dwThreadId = dwThread;
  779. pTemp->hwnd = hwndTemp;
  780. pTemp->pNext = m_pNotifyList;
  781. m_pNotifyList = pTemp;
  782. }
  783. // Allocate a NOTIFYLIST node for this caller
  784. NOTIFYLIST *pListTemp;
  785. if (!MemAlloc((LPVOID*) &pListTemp, sizeof(NOTIFYLIST)))
  786. {
  787. hr = E_OUTOFMEMORY;
  788. goto exit;
  789. }
  790. pListTemp->pNotify = pNotify;
  791. // Get the current list for this thread and insert this node at the
  792. // beginning
  793. pListTemp->pNext = (NOTIFYLIST *) GetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA);
  794. // Set this new list to the window
  795. SetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA, (LONG_PTR)pListTemp);
  796. exit:
  797. LeaveCriticalSection(&m_cs);
  798. return (hr);
  799. }
  800. //
  801. // FUNCTION: CConnectionManager::Unadvise()
  802. //
  803. // PURPOSE: Allows a client that has previously registered for notifications
  804. // to unregister itself.
  805. //
  806. // PARAMETERS:
  807. // <in> pNotify - Pointer to the interface that is being called upon
  808. // notifications.
  809. //
  810. // RETURN VALUE:
  811. // E_INVALIDARG - pNotify was not found in the list
  812. // S_OK - Everything's OK
  813. //
  814. HRESULT CConnectionManager::Unadvise(IConnectionNotify *pNotify)
  815. {
  816. DWORD index = 0;
  817. HRESULT hr = S_OK;
  818. EnterCriticalSection(&m_cs);
  819. // Loop through the notify windows we own
  820. NOTIFYHWND *pTemp = m_pNotifyList;
  821. NOTIFYHWND *pHwndPrev = NULL;
  822. while (pTemp)
  823. {
  824. // Get the list of notify callbacks for this window
  825. NOTIFYLIST *pList = (NOTIFYLIST *)GetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA);
  826. if (pList)
  827. {
  828. // Loop through the callbacks looking for this one
  829. NOTIFYLIST *pListT = pList;
  830. NOTIFYLIST *pPrev;
  831. // Check to see if it's the first one
  832. if (pListT->pNotify == pNotify)
  833. {
  834. pList = pListT->pNext;
  835. if (pList)
  836. {
  837. SetWindowLongPtr(pTemp->hwnd, GWLP_USERDATA, (LONG_PTR)pList);
  838. }
  839. else
  840. {
  841. Assert(GetCurrentThreadId() == GetWindowThreadProcessId(pTemp->hwnd, NULL));
  842. RemoveProp(pTemp->hwnd, NOTIFY_HWND);
  843. DestroyWindow(pTemp->hwnd);
  844. if (pHwndPrev)
  845. pHwndPrev->pNext = pTemp->pNext;
  846. else
  847. m_pNotifyList = pTemp->pNext;
  848. MemFree(pTemp);
  849. }
  850. SafeMemFree(pListT);
  851. hr = S_OK;
  852. goto exit;
  853. }
  854. else
  855. {
  856. pPrev = pList;
  857. pListT = pList->pNext;
  858. while (pListT)
  859. {
  860. if (pListT->pNotify == pNotify)
  861. {
  862. pPrev->pNext = pListT->pNext;
  863. SafeMemFree(pListT);
  864. hr = S_OK;
  865. goto exit;
  866. }
  867. pListT = pListT->pNext;
  868. pPrev = pPrev->pNext;
  869. }
  870. }
  871. }
  872. pHwndPrev = pTemp;
  873. pTemp = pTemp->pNext;
  874. }
  875. exit:
  876. LeaveCriticalSection(&m_cs);
  877. return (hr);
  878. }
  879. //
  880. // FUNCTION: CConnectionManager::RasAccountsExist()
  881. //
  882. // PURPOSE: Allows the client to ask whether or not we have any accounts
  883. // configured that require a RAS connection.
  884. //
  885. // RETURN VALUE:
  886. // S_OK - Accounts exist that require RAS
  887. // S_FALSE - No accounts exist that require RAS
  888. //
  889. HRESULT CConnectionManager::RasAccountsExist(void)
  890. {
  891. IImnEnumAccounts *pEnum = NULL;
  892. IImnAccount *pAcct = NULL;
  893. DWORD dwConn;
  894. BOOL fFound = FALSE;
  895. // If no RAS, no accounts
  896. #ifdef SLOWDOWN_STARTUP_TIME
  897. if (FAILED(VerifyRasLoaded()))
  898. return (S_FALSE);
  899. #endif
  900. // We need to walk through the accounts in the Account Manager to see if
  901. // any of them have a connect type of RAS. As soon as we find one, we can
  902. // return success.
  903. Assert(m_pAcctMan);
  904. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum)))
  905. {
  906. pEnum->Reset();
  907. while (!fFound && SUCCEEDED(pEnum->GetNext(&pAcct)))
  908. {
  909. if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn)))
  910. {
  911. if (dwConn == CONNECTION_TYPE_RAS)
  912. {
  913. fFound = TRUE;
  914. }
  915. }
  916. SafeRelease(pAcct);
  917. }
  918. SafeRelease(pEnum);
  919. }
  920. return (fFound ? S_OK : S_FALSE);
  921. }
  922. //
  923. // FUNCTION: CConnectionManager::GetConnectMenu()
  924. //
  925. // PURPOSE: Returns a menu that has all the accounts that require RAS
  926. // connections listed. A pointer to the IImnAccount for each
  927. // account is stored in the menu item's dwItemData parameter.
  928. // As a result, the client MUST call FreeConnectMenu() when then
  929. // menu is no longer being used.
  930. //
  931. // PARAMETERS:
  932. // <out> phMenu - Returns the menu handle
  933. //
  934. // RETURN VALUE:
  935. // S_OK - phMenu contains the menu
  936. // E_FAIL - Something unfortunate happend.
  937. //
  938. HRESULT CConnectionManager::GetConnectMenu(HMENU *phMenu)
  939. {
  940. HMENU hMenu = NULL;
  941. IImnEnumAccounts *pEnum = NULL;
  942. IImnAccount *pAcct = NULL;
  943. DWORD dwConn = 0;
  944. TCHAR szAcct[CCHMAX_ACCOUNT_NAME];
  945. TCHAR szConn[CCHMAX_CONNECTOID];
  946. TCHAR szConnQuoted[CCHMAX_CONNECTOID + 2], szBuf[CCHMAX_CONNECTOID + 2];
  947. TCHAR szMenu[CCHMAX_ACCOUNT_NAME + CCHMAX_CONNECTOID];
  948. MENUITEMINFO mii;
  949. DWORD cAcct = 0;
  950. // Create a menu and add all the RAS based accounts to it
  951. Assert(m_pAcctMan);
  952. hMenu = CreatePopupMenu();
  953. // Get the enumerator from the account manager
  954. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum)))
  955. {
  956. pEnum->Reset();
  957. // Walk through all the accounts
  958. while (SUCCEEDED(pEnum->GetNext(&pAcct)))
  959. {
  960. // Get the connection type for this account
  961. if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn)))
  962. {
  963. // If the account is a RAS account, ask for the connectoid name
  964. // and the account name.
  965. if (dwConn == CONNECTION_TYPE_RAS)
  966. {
  967. pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn));
  968. pAcct->GetPropSz(AP_ACCOUNT_NAME, szAcct, ARRAYSIZE(szAcct));
  969. wnsprintf(szMenu, ARRAYSIZE(szMenu), _T("%s (%s)"), PszEscapeMenuStringA(szAcct, szBuf, sizeof(szBuf) / sizeof(TCHAR)), PszEscapeMenuStringA(szConn, szConnQuoted, sizeof(szConnQuoted) / sizeof(TCHAR)));
  970. // Insert the menu item into the menu
  971. ZeroMemory(&mii, sizeof(MENUITEMINFO));
  972. mii.cbSize = sizeof(MENUITEMINFO);
  973. mii.fMask = MIIM_DATA | MIIM_ID | MIIM_STATE | MIIM_TYPE;
  974. mii.fType = MFT_STRING | MFT_RADIOCHECK;
  975. mii.fState = MFS_ENABLED;
  976. mii.wID = ID_CONNECT_FIRST + cAcct;
  977. mii.dwItemData = (DWORD_PTR) pAcct;
  978. mii.dwTypeData = szMenu;
  979. pAcct->AddRef();
  980. SideAssert(InsertMenuItem(hMenu, cAcct, TRUE, &mii));
  981. cAcct++;
  982. }
  983. }
  984. SafeRelease(pAcct);
  985. }
  986. SafeRelease(pEnum);
  987. }
  988. if (hMenu)
  989. if(GetMenuItemCount(hMenu))
  990. {
  991. *phMenu = hMenu;
  992. return (S_OK);
  993. }
  994. else
  995. {
  996. DestroyMenu(hMenu);
  997. return (E_FAIL);
  998. }
  999. else
  1000. return (E_FAIL);
  1001. }
  1002. //
  1003. // FUNCTION: CConnectionManager::FreeConnectMenu()
  1004. //
  1005. // PURPOSE: Frees the item data stored with the menu returned from
  1006. // GetConnectMenu().
  1007. //
  1008. // PARAMETERS:
  1009. // <in> hMenu - Handle of the menu to free.
  1010. //
  1011. void CConnectionManager::FreeConnectMenu(HMENU hMenu)
  1012. {
  1013. // Walk through the items on this menu and free the pointers stored in
  1014. // the item data.
  1015. MENUITEMINFO mii;
  1016. int cItems = 0;
  1017. Assert(hMenu);
  1018. cItems = GetMenuItemCount(hMenu);
  1019. for (int i = 0; i < cItems; i++)
  1020. {
  1021. mii.cbSize = sizeof(MENUITEMINFO);
  1022. mii.fMask = MIIM_DATA;
  1023. mii.dwItemData = 0;
  1024. if (GetMenuItemInfo(hMenu, i, TRUE, &mii))
  1025. {
  1026. Assert(mii.dwItemData);
  1027. if (mii.dwItemData)
  1028. ((IImnAccount *) mii.dwItemData)->Release();
  1029. }
  1030. }
  1031. DestroyMenu(hMenu);
  1032. }
  1033. //
  1034. // FUNCTION: CConnectionManager::OnActivate()
  1035. //
  1036. // PURPOSE: Called whenever the browser receives a WM_ACTIVATE message.
  1037. // In response, we check the current state of our RAS connection
  1038. // to see if we are still connected / disconnected.
  1039. void CConnectionManager::OnActivate(BOOL fActive)
  1040. {
  1041. BOOL fOfflineChanged = FALSE;
  1042. BOOL fOffline = FALSE;
  1043. if (fActive)
  1044. {
  1045. EnterCriticalSection(&m_cs);
  1046. m_rConnInfo.state = CIS_REFRESH;
  1047. // Check to see if we've gone offline
  1048. if (m_fOffline != IsGlobalOffline())
  1049. {
  1050. fOffline = m_fOffline = (!m_fOffline);
  1051. fOfflineChanged = TRUE;
  1052. }
  1053. LeaveCriticalSection(&m_cs);
  1054. // Do this outside of the critsec
  1055. if (fOfflineChanged)
  1056. SendAdvise(CONNNOTIFY_WORKOFFLINE, (LPVOID) IntToPtr(fOffline));
  1057. }
  1058. }
  1059. //
  1060. // FUNCTION: CConnectionManager::FillRasCombo()
  1061. //
  1062. // PURPOSE: This function enumerates the accounts in the account manager
  1063. // and builds a list of the RAS connections those accounts use.
  1064. // The function then inserts those connections in to the provided
  1065. // combobox.
  1066. //
  1067. // PARAMETERS:
  1068. // <in> hwndCombo - Handle of the combobox to fill
  1069. // <in> fIncludeNone - Inserts a string at the top "Don't dial a connection"
  1070. //
  1071. // RETURN VALUE:
  1072. // BOOL
  1073. //
  1074. BOOL CConnectionManager::FillRasCombo(HWND hwndCombo, BOOL fIncludeNone)
  1075. {
  1076. IImnEnumAccounts *pEnum = NULL;
  1077. IImnAccount *pAcct = NULL;
  1078. DWORD dwConn = 0;
  1079. LPTSTR *rgszConn = NULL;
  1080. TCHAR szConn[CCHMAX_CONNECTOID];
  1081. ULONG cAcct = 0;
  1082. ULONG cConn = 0;
  1083. BOOL fSucceeded = FALSE;
  1084. ULONG ul;
  1085. LPRASENTRYNAME pEntry=NULL;
  1086. DWORD dwSize,
  1087. cEntries,
  1088. dwError;
  1089. HRESULT hr = S_OK;
  1090. int i;
  1091. EnterCriticalSection(&m_cs);
  1092. #ifdef NEVER
  1093. // Find out how many accounts exist
  1094. m_pAcctMan->GetAccountCount(ACCT_NEWS, &cAcct);
  1095. m_pAcctMan->GetAccountCount(ACCT_MAIL, &ul);
  1096. cAcct += ul;
  1097. m_pAcctMan->GetAccountCount(ACCT_DIR_SERV, &ul);
  1098. cAcct += ul;
  1099. if (cAcct == 0)
  1100. {
  1101. fSucceeded = TRUE;
  1102. goto exit;
  1103. }
  1104. // Allocate an array to hold the connection list
  1105. if (!MemAlloc((LPVOID*) &rgszConn, cAcct * sizeof(LPTSTR)))
  1106. goto exit;
  1107. ZeroMemory(rgszConn, cAcct * sizeof(LPTSTR));
  1108. // Get the enumerator from the account manager
  1109. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum)))
  1110. {
  1111. pEnum->Reset();
  1112. // Walk through all the accounts
  1113. while (SUCCEEDED(pEnum->GetNext(&pAcct)))
  1114. {
  1115. // Get the connection type for this account
  1116. if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn)))
  1117. {
  1118. // If the account is a RAS account, ask for the connectoid name
  1119. // and the account name.
  1120. if (dwConn == CONNECTION_TYPE_RAS)
  1121. {
  1122. pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn));
  1123. // Check to see if this connection has already been inserted into
  1124. // our list
  1125. for (ULONG k = 0; k < cConn; k++)
  1126. {
  1127. if (0 == lstrcmpi(szConn, rgszConn[k]))
  1128. break;
  1129. }
  1130. // If we didn't find it, we insert it
  1131. if (k >= cConn)
  1132. {
  1133. rgszConn[cConn] = StringDup(szConn);
  1134. cConn++;
  1135. }
  1136. }
  1137. }
  1138. SafeRelease(pAcct);
  1139. }
  1140. SafeRelease(pEnum);
  1141. }
  1142. // Sort the list
  1143. int i, j, min;
  1144. LPTSTR pszT;
  1145. for (i = 0; i < (int) cConn; i++)
  1146. {
  1147. min = i;
  1148. for (j = i + 1; j < (int) cConn; j++)
  1149. if (0 > lstrcmpi(rgszConn[j], rgszConn[min]))
  1150. min = j;
  1151. pszT = rgszConn[min];
  1152. rgszConn[min] = rgszConn[i];
  1153. rgszConn[i] = pszT;
  1154. }
  1155. // Insert the items into the combo box
  1156. if (fIncludeNone)
  1157. {
  1158. AthLoadString(idsConnNoDial, szConn, ARRAYSIZE(szConn));
  1159. ComboBox_AddString(hwndCombo, szConn);
  1160. }
  1161. for (i = 0; i < (int) cConn; i++)
  1162. ComboBox_AddString(hwndCombo, rgszConn[i]);
  1163. #endif NEVER
  1164. // Make sure the RAS DLL is loaded before we try this
  1165. CHECKHR(hr = VerifyRasLoaded());
  1166. // Allocate RASENTRYNAME
  1167. dwSize = sizeof(RASENTRYNAME);
  1168. CHECKHR(hr = HrAlloc((LPVOID*)&pEntry, dwSize));
  1169. // Ver stamp the entry
  1170. pEntry->dwSize = sizeof(RASENTRYNAME);
  1171. cEntries = 0;
  1172. dwError = RasEnumEntries(NULL, NULL, pEntry, &dwSize, &cEntries);
  1173. if (dwError == ERROR_BUFFER_TOO_SMALL)
  1174. {
  1175. SafeMemFree(pEntry);
  1176. CHECKHR(hr = HrAlloc((LPVOID *)&pEntry, dwSize));
  1177. pEntry->dwSize = sizeof(RASENTRYNAME);
  1178. cEntries = 0;
  1179. dwError = RasEnumEntries(NULL, NULL, pEntry, &dwSize, &cEntries);
  1180. }
  1181. // Error ?
  1182. if (dwError)
  1183. {
  1184. hr = TrapError(IXP_E_RAS_ERROR);
  1185. goto exit;
  1186. }
  1187. // Insert the items into the combo box
  1188. if (fIncludeNone)
  1189. {
  1190. AthLoadString(idsConnNoDial, szConn, ARRAYSIZE(szConn));
  1191. ComboBox_AddString(hwndCombo, szConn);
  1192. }
  1193. for (i = 0; i < (int) cEntries; i++)
  1194. ComboBox_AddString(hwndCombo, pEntry[i].szEntryName);
  1195. fSucceeded = TRUE;
  1196. exit:
  1197. if (rgszConn)
  1198. {
  1199. for (i = 0; i < (int) cConn; i++)
  1200. SafeMemFree(rgszConn[i]);
  1201. MemFree(rgszConn);
  1202. }
  1203. SafeMemFree(pEntry);
  1204. LeaveCriticalSection(&m_cs);
  1205. return (fSucceeded);
  1206. }
  1207. //
  1208. // FUNCTION: CConnectionManager::DoStartupDial()
  1209. //
  1210. // PURPOSE: This function checks to see what the user's startup options
  1211. // are with respect to RAS and performs the actions required
  1212. // (dial, dialog, nada)
  1213. // PARAMETERS:
  1214. // <in> hwndParent - Handle to parent a dialog to
  1215. //
  1216. void CConnectionManager::DoStartupDial(HWND hwndParent)
  1217. {
  1218. DWORD dwStart;
  1219. DWORD dw;
  1220. DWORD dwReturn;
  1221. TCHAR szConn[CCHMAX_CONNECTOID];
  1222. LPRASCONN pConnections = NULL;
  1223. ULONG cConnections = 0;
  1224. DWORD dwDialFlags = 0;
  1225. DWORD dwLanFlags = 0;
  1226. // The first thing to do is figure out what the user's startup option if
  1227. dw = DwGetOption(OPT_DIALUP_START);
  1228. // If the user want's to do nothing, we're done
  1229. if (dw == START_NO_CONNECT)
  1230. return;
  1231. //ConnectUsingIESettings(hwndParent, TRUE);
  1232. if (!m_fDialerUI)
  1233. {
  1234. m_fDialerUI = TRUE;
  1235. // Check to see if we're working offline
  1236. if (IsGlobalOffline())
  1237. {
  1238. if (IDYES == AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline),
  1239. 0, MB_YESNO | MB_ICONEXCLAMATION ))
  1240. {
  1241. g_pConMan->SetGlobalOffline(FALSE);
  1242. }
  1243. else
  1244. {
  1245. goto DialerExit;
  1246. }
  1247. }
  1248. //We do not dial if there is an active connection already existing. Even if it is not the connection
  1249. //InternetDial would have dialed, if we had called. Heres why:
  1250. //1)We don't want to look into the registry to get the default connectoid.
  1251. //Thats why we call InternetDial with NULL and it dials the def connectoid if there is one set
  1252. //Otherwise it dials the first connectoid in the list.
  1253. //Since InternetDial figures out which connectoid to dial, we don't want to do all the work of figuring
  1254. //out if we are already connected to the connectoid we are going to dial.
  1255. //So we just do not dial even if there is one active connection.
  1256. if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)))
  1257. {
  1258. if (cConnections > 0)
  1259. goto DialerExit;
  1260. }
  1261. dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
  1262. if (VerifyMobilityPackLoaded() == S_OK)
  1263. {
  1264. if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN)))
  1265. dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE;
  1266. }
  1267. // Only one caller can be dialing the phone at a time.
  1268. if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0))
  1269. {
  1270. goto DialerExit;
  1271. }
  1272. dwReturn = InternetDialA(hwndParent, NULL, dwDialFlags, &m_dwConnId, 0);
  1273. if (dwReturn == 0)
  1274. {
  1275. m_rConnInfo.fConnected = TRUE;
  1276. m_rConnInfo.fIStartedRas = TRUE;
  1277. m_rConnInfo.fAutoDial = FALSE;
  1278. m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId;
  1279. SendAdvise(CONNNOTIFY_CONNECTED, NULL);
  1280. }
  1281. else
  1282. {
  1283. if (dwReturn == ERROR_USER_DISCONNECTION)
  1284. {
  1285. SendAdvise(CONNNOTIFY_USER_CANCELLED, NULL);
  1286. if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE))
  1287. SetGlobalOffline(TRUE);
  1288. }
  1289. else
  1290. {
  1291. DebugTrace("Error dialing: %d\n", GetLastError());
  1292. DebugTrace("InternetDial returned: %d\n", dwReturn);
  1293. }
  1294. }
  1295. DialerExit:
  1296. m_fDialerUI = FALSE;
  1297. SafeMemFree(pConnections);
  1298. }
  1299. ReleaseMutex(m_hMutexDial);
  1300. }
  1301. HRESULT CConnectionManager::GetDefConnectoid(LPTSTR szConn, DWORD dwSize)
  1302. {
  1303. HRESULT hr = E_FAIL;
  1304. DWORD dwType;
  1305. DWORD dwerr;
  1306. *szConn = '\0';
  1307. if ((dwerr = SHGetValue(HKEY_CURRENT_USER, c_szDefConnPath, c_szRegDefaultConnection, &dwType, szConn, &dwSize))
  1308. == ERROR_SUCCESS)
  1309. {
  1310. hr = S_OK;
  1311. }
  1312. return hr;
  1313. }
  1314. //
  1315. // FUNCTION: CConnectionManager::VerifyRasLoaded()
  1316. //
  1317. // PURPOSE: Checks to see if this object has already loaded the RAS DLL.
  1318. // If not, then the DLL is loaded and the function pointers are
  1319. // fixed up.
  1320. //
  1321. // RETURN VALUE:
  1322. // S_OK - Loaded and ready, sir.
  1323. // hrRasInitFailure - Failed to load.
  1324. //
  1325. HRESULT CConnectionManager::VerifyRasLoaded(void)
  1326. {
  1327. // Locals
  1328. UINT uOldErrorMode;
  1329. // Protected
  1330. EnterCriticalSection(&m_cs);
  1331. // Check to see if we've tried this before
  1332. if (m_fRASLoadFailed)
  1333. goto failure;
  1334. // Bug #20573 - Let's do a little voodoo here. On NT, it appears that they
  1335. // have a key in the registry to show which protocols are
  1336. // supported by RAS service. AKA - if this key doesn't exist,
  1337. // then RAS isn't installed. This may enable us to avoid some
  1338. // special bugs when RAS get's uninstalled on NT.
  1339. if (g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
  1340. {
  1341. HKEY hKey;
  1342. const TCHAR c_szRegKeyRAS[] = _T("SOFTWARE\\Microsoft\\RAS");
  1343. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegKeyRAS, 0, KEY_READ, &hKey))
  1344. {
  1345. goto failure;
  1346. }
  1347. RegCloseKey(hKey);
  1348. }
  1349. // If dll is loaded, lets verify all of my function pointers
  1350. if (!m_hInstRas)
  1351. {
  1352. // Try loading Ras.
  1353. uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  1354. m_hInstRas = LoadLibrary(szRasDll);
  1355. SetErrorMode(uOldErrorMode);
  1356. // Failure ?
  1357. if (!m_hInstRas)
  1358. goto failure;
  1359. // Did we load it
  1360. m_pRasDial = (RASDIALPROC)GetProcAddress(m_hInstRas, szRasDial);
  1361. m_pRasEnumConnections = (RASENUMCONNECTIONSPROC)GetProcAddress(m_hInstRas, szRasEnumConnections);
  1362. m_pRasEnumEntries = (RASENUMENTRIESPROC)GetProcAddress(m_hInstRas, szRasEnumEntries);
  1363. m_pRasGetConnectStatus = (RASGETCONNECTSTATUSPROC)GetProcAddress(m_hInstRas, szRasGetConnectStatus);
  1364. m_pRasGetErrorString = (RASGETERRORSTRINGPROC)GetProcAddress(m_hInstRas, szRasGetErrorString);
  1365. m_pRasHangup = (RASHANGUPPROC)GetProcAddress(m_hInstRas, szRasHangup);
  1366. m_pRasSetEntryDialParams = (RASSETENTRYDIALPARAMSPROC)GetProcAddress(m_hInstRas, szRasSetEntryDialParams);
  1367. m_pRasGetEntryDialParams = (RASGETENTRYDIALPARAMSPROC)GetProcAddress(m_hInstRas, szRasGetEntryDialParams);
  1368. m_pRasEditPhonebookEntry = (RASEDITPHONEBOOKENTRYPROC)GetProcAddress(m_hInstRas, szRasEditPhonebookEntry);
  1369. m_pRasGetEntryProperties = (RASGETENTRYPROPERTIES) GetProcAddress(m_hInstRas, szRasGetEntryProperties);
  1370. }
  1371. if (!m_hInstRasDlg && FIsPlatformWinNT())
  1372. {
  1373. // Try loading Ras.
  1374. uOldErrorMode = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  1375. m_hInstRasDlg = LoadLibrary(s_szRasDlgDll);
  1376. SetErrorMode(uOldErrorMode);
  1377. // Failure ?
  1378. if (!m_hInstRasDlg)
  1379. goto failure;
  1380. m_pRasDialDlg = (RASDIALDLGPROC)GetProcAddress(m_hInstRasDlg, s_szRasDialDlg);
  1381. m_pRasEntryDlg = (RASENTRYDLGPROC)GetProcAddress(m_hInstRasDlg, s_szRasEntryDlg);
  1382. if (!m_pRasDialDlg || !m_pRasEntryDlg)
  1383. goto failure;
  1384. }
  1385. // Make sure all functions have been loaded
  1386. if (m_pRasDial &&
  1387. m_pRasEnumConnections &&
  1388. m_pRasEnumEntries &&
  1389. m_pRasGetConnectStatus &&
  1390. m_pRasGetErrorString &&
  1391. m_pRasHangup &&
  1392. m_pRasSetEntryDialParams &&
  1393. m_pRasGetEntryDialParams &&
  1394. m_pRasEditPhonebookEntry)
  1395. {
  1396. // Protected
  1397. LeaveCriticalSection(&m_cs);
  1398. // Success
  1399. return S_OK;
  1400. }
  1401. failure:
  1402. m_fRASLoadFailed = TRUE;
  1403. // Protected
  1404. LeaveCriticalSection(&m_cs);
  1405. // Otherwise, were hosed
  1406. return (hrRasInitFailure);
  1407. }
  1408. //
  1409. // FUNCTION: CConnectionManager::EnumerateConnections()
  1410. //
  1411. // PURPOSE: Asks RAS for the list of active RAS connections.
  1412. //
  1413. // PARAMETERS:
  1414. // <out> ppRasConn - Returns an array of RASCONN structures for the
  1415. // list of active connections.
  1416. // <out> pcConnections - Number of structures in ppRasCon.
  1417. //
  1418. // RETURN VALUE:
  1419. // S_OK - The data in ppRasConn and pcConnections is valid
  1420. //
  1421. HRESULT CConnectionManager::EnumerateConnections(LPRASCONN *ppRasConn,
  1422. ULONG *pcConnections)
  1423. {
  1424. // Locals
  1425. DWORD dw,
  1426. dwSize;
  1427. BOOL fResult=FALSE;
  1428. HRESULT hr;
  1429. // Check Params
  1430. Assert(ppRasConn && pcConnections);
  1431. // Make sure RAS is loaded
  1432. if (FAILED(hr = VerifyRasLoaded()))
  1433. return (hr);
  1434. // Init
  1435. *ppRasConn = NULL;
  1436. *pcConnections = 0;
  1437. // Sizeof my buffer
  1438. dwSize = sizeof(RASCONN) * 2;
  1439. // Allocate enough for 1 ras connection info object
  1440. if (!MemAlloc((LPVOID *)ppRasConn, dwSize))
  1441. {
  1442. TRAPHR(hrMemory);
  1443. return (E_OUTOFMEMORY);
  1444. }
  1445. ZeroMemory(*ppRasConn, dwSize);
  1446. // Buffer size
  1447. //(*ppRasConn)->dwSize = dwSize;
  1448. (*ppRasConn)->dwSize = sizeof(RASCONN);
  1449. // Enumerate ras connections
  1450. dw = RasEnumConnections(*ppRasConn, &dwSize, pcConnections);
  1451. // Not enough memory ?
  1452. if ((dw == ERROR_BUFFER_TOO_SMALL) || (dw == ERROR_NOT_ENOUGH_MEMORY))
  1453. {
  1454. // Reallocate
  1455. if (!MemRealloc((LPVOID *)ppRasConn, dwSize))
  1456. {
  1457. TRAPHR(hrMemory);
  1458. goto exit;
  1459. }
  1460. // Call enumerate again
  1461. *pcConnections = 0;
  1462. (*ppRasConn)->dwSize = sizeof(RASCONN);
  1463. dw = RasEnumConnections(*ppRasConn, &dwSize, pcConnections);
  1464. }
  1465. // If still failed
  1466. if (dw)
  1467. {
  1468. AssertSz(FALSE, "RasEnumConnections failed");
  1469. return E_FAIL;
  1470. }
  1471. // Success
  1472. hr = S_OK;
  1473. exit:
  1474. // Done
  1475. return S_OK;
  1476. }
  1477. //
  1478. // FUNCTION: CConnectionManager::StartRasDial()
  1479. //
  1480. // PURPOSE: Called when the client actually wants to establish a RAS
  1481. // connection.
  1482. //
  1483. // PARAMETERS:
  1484. // <in> hwndParent - Handle of the window to parent any UI
  1485. // <in> pszConnection - Name of the connection to establish
  1486. //
  1487. // RETURN VALUE:
  1488. // HRESULT
  1489. //
  1490. HRESULT CConnectionManager::StartRasDial(HWND hwndParent, LPTSTR pszConnection)
  1491. {
  1492. HRESULT hr = S_OK;
  1493. // Refresh ConnInfo
  1494. CHECKHR(hr = RefreshConnInfo());
  1495. // Check to see if we need to ask the user for information or credentials
  1496. // before we attempt to dial
  1497. CHECKHR (hr = RasLogon(hwndParent, pszConnection, FALSE));
  1498. // If we can use a system dialog for this, do so.
  1499. if (m_pRasDialDlg)
  1500. {
  1501. RASDIALDLG rdd = {0};
  1502. BOOL fRet;
  1503. rdd.dwSize = sizeof(rdd);
  1504. rdd.hwndOwner = hwndParent;
  1505. #if (WINVER >= 0x401)
  1506. rdd.dwSubEntry = m_rdp.dwSubEntry;
  1507. #else
  1508. rdd.dwSubEntry = 0;
  1509. #endif
  1510. fRet = RasDialDlg(NULL, m_rdp.szEntryName,
  1511. lstrlen(m_rdp.szPhoneNumber) ? m_rdp.szPhoneNumber : NULL,
  1512. &rdd);
  1513. if (fRet)
  1514. {
  1515. // Need to get the current connection handle
  1516. LPRASCONN pConnections = NULL;
  1517. ULONG cConnections = 0;
  1518. if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)))
  1519. {
  1520. for (UINT i = 0; i < cConnections; i++)
  1521. {
  1522. if (0 == lstrcmpi(pConnections[i].szEntryName, m_rdp.szEntryName))
  1523. {
  1524. EnterCriticalSection(&m_cs);
  1525. m_rConnInfo.hRasConn = pConnections[i].hrasconn;
  1526. LeaveCriticalSection(&m_cs);
  1527. break;
  1528. }
  1529. }
  1530. SafeMemFree(pConnections);
  1531. }
  1532. hr = S_OK;
  1533. }
  1534. else
  1535. hr = E_FAIL;
  1536. }
  1537. else
  1538. {
  1539. // We need to use our own RAS UI.
  1540. hr = (HRESULT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasProgress),
  1541. hwndParent, RasProgressDlgProc,
  1542. (LPARAM) this);
  1543. }
  1544. exit:
  1545. // Done
  1546. return hr;
  1547. }
  1548. //
  1549. // FUNCTION: CConnectionManager::RasLogon()
  1550. //
  1551. // PURPOSE: Attempts to load the RAS phonebook entry for the requested
  1552. // connection. If it doesn't exist or there isn't enough info,
  1553. // we present UI to the user to request that information.
  1554. //
  1555. // PARAMETERS:
  1556. // <in> hwnd - Handle to display UI over.
  1557. // <in> pszConnection - Name of the connection to load info for.
  1558. // <in> fForcePrompt - Forces the UI to be displayed.
  1559. //
  1560. // RETURN VALUE:
  1561. // S_OK - prdp contains the requested information
  1562. // hrGetDialParmasFailed - Couldn't get the phonebook entry from RAS
  1563. // hrUserCancel - User canceled
  1564. //
  1565. //
  1566. HRESULT CConnectionManager::RasLogon(HWND hwnd, LPTSTR pszConnection,
  1567. BOOL fForcePrompt)
  1568. {
  1569. // Locals
  1570. HRESULT hr = S_OK;
  1571. DWORD dwRasError;
  1572. // Do we need to prompt for logon information first ?
  1573. ZeroMemory(&m_rdp, sizeof(RASDIALPARAMS));
  1574. m_rdp.dwSize = sizeof(RASDIALPARAMS);
  1575. StrCpyN(m_rdp.szEntryName, pszConnection, ARRAYSIZE(m_rdp.szEntryName));
  1576. // See if we can get the information from RAS
  1577. dwRasError = RasGetEntryDialParams(NULL, &m_rdp, &m_fSavePassword);
  1578. if (dwRasError)
  1579. {
  1580. TCHAR szRes[CCHMAX_STRINGRES], szBuf[CCHMAX_STRINGRES];
  1581. AthLoadString(idshrGetDialParamsFailed, szRes, ARRAYSIZE(szRes));
  1582. wnsprintf(szBuf, ARRAYSIZE(szBuf), szRes, pszConnection);
  1583. AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), szBuf, 0, MB_OK | MB_ICONSTOP);
  1584. hr = TRAPHR(hrGetDialParamsFailed);
  1585. goto exit;
  1586. }
  1587. // NT Supports the UI we need to display. If this exists, then
  1588. // RasDialDlg will take it from here
  1589. if (m_pRasDialDlg)
  1590. {
  1591. goto exit;
  1592. }
  1593. // Do we need to get password / account information?
  1594. if (fForcePrompt || m_fSavePassword == FALSE ||
  1595. FIsStringEmpty(m_rdp.szUserName) || FIsStringEmpty(m_rdp.szPassword))
  1596. {
  1597. // RAS Logon
  1598. hr = (HRESULT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasLogon), hwnd,
  1599. RasLogonDlgProc, (LPARAM) this);
  1600. if (hr == hrUserCancel)
  1601. {
  1602. DisplayRasError(hwnd, hrUserCancel, 0);
  1603. hr = hrUserCancel;
  1604. goto exit;
  1605. }
  1606. }
  1607. exit:
  1608. // Done
  1609. return hr;
  1610. }
  1611. //
  1612. // FUNCTION: CConnectionManager::DisplayRasError()
  1613. //
  1614. // PURPOSE: Displays a message box describing the error that occured while
  1615. // dealing with connections etc.
  1616. //
  1617. // PARAMETERS:
  1618. // <in> hwnd - Handle of the window to display UI over
  1619. // <in> hrRasError - HRESULT to display the error for
  1620. // <in> dwRasError - Error code returned from RAS to display the error for
  1621. //
  1622. void CConnectionManager::DisplayRasError(HWND hwnd, HRESULT hrRasError,
  1623. DWORD dwRasError)
  1624. {
  1625. // Locals
  1626. TCHAR szRasError[256];
  1627. BOOL fRasError = FALSE;
  1628. // No Error
  1629. if (SUCCEEDED(hrRasError))
  1630. return;
  1631. // Look up RAS error
  1632. if (dwRasError)
  1633. {
  1634. if (RasGetErrorString(dwRasError, szRasError, sizeof(szRasError)) == 0)
  1635. fRasError = TRUE;
  1636. else
  1637. *szRasError = _T('\0');
  1638. }
  1639. // General Error
  1640. switch (hrRasError)
  1641. {
  1642. case hrUserCancel:
  1643. break;
  1644. case hrMemory:
  1645. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP);
  1646. break;
  1647. case hrRasInitFailure:
  1648. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasInitFailure), 0, MB_OK | MB_ICONSTOP);
  1649. break;
  1650. case hrRasDialFailure:
  1651. if (fRasError)
  1652. CombinedRasError(hwnd, HR_CODE(hrRasDialFailure), szRasError, dwRasError);
  1653. else
  1654. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasDialFailure), 0, MB_OK | MB_ICONSTOP);
  1655. break;
  1656. case hrRasServerNotFound:
  1657. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrRasServerNotFound), 0, MB_OK | MB_ICONSTOP);
  1658. break;
  1659. case hrGetDialParamsFailed:
  1660. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(hrGetDialParamsFailed), 0, MB_OK | MB_ICONSTOP);
  1661. break;
  1662. case E_FAIL:
  1663. default:
  1664. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsRasError), MAKEINTRESOURCEW(idsRasErrorGeneral), 0, MB_OK | MB_ICONSTOP);
  1665. break;
  1666. }
  1667. }
  1668. //
  1669. // FUNCTION: CConnectionManager::PromptCloseConn()
  1670. //
  1671. // PURPOSE: Asks the user if they want to close the current connection or
  1672. // try to use it.
  1673. //
  1674. // PARAMETERS:
  1675. // <in> hwnd - Parent for the dialog
  1676. //
  1677. // RETURN VALUE:
  1678. // Returns the button that closed the dialog
  1679. //
  1680. UINT CConnectionManager::PromptCloseConnection(HWND hwnd)
  1681. {
  1682. RefreshConnInfo();
  1683. if (DwGetOption(OPT_DIALUP_WARN_SWITCH))
  1684. {
  1685. if (0 == lstrcmpi(m_rConnInfo.szCurrentConnectionName, m_szConnectName))
  1686. return (idrgUseCurrent);
  1687. else
  1688. return (UINT) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddRasCloseConn), hwnd,
  1689. RasCloseConnDlgProc, (LPARAM) this);
  1690. }
  1691. else
  1692. return (idrgDialNew);
  1693. }
  1694. INT_PTR CALLBACK CConnectionManager::RasCloseConnDlgProc(HWND hwnd, UINT uMsg,
  1695. WPARAM wParam, LPARAM lParam)
  1696. {
  1697. // Locals
  1698. CConnectionManager *pThis = NULL;
  1699. TCHAR szRes[255],
  1700. szMsg[255+RAS_MaxEntryName+1];
  1701. TCHAR szConn[CCHMAX_CONNECTOID + 2];
  1702. switch(uMsg)
  1703. {
  1704. case WM_INITDIALOG:
  1705. // The LPARAM contains our this pointer
  1706. pThis = (CConnectionManager*) lParam;
  1707. if (!pThis)
  1708. {
  1709. Assert(pThis);
  1710. EndDialog(hwnd, E_FAIL);
  1711. return (TRUE);
  1712. }
  1713. // Center
  1714. CenterDialog(hwnd);
  1715. // Refresh Connection Info
  1716. pThis->RefreshConnInfo();
  1717. // Set Text
  1718. GetWindowText(GetDlgItem(hwnd, idcCurrentMsg), szRes, sizeof(szRes)/sizeof(TCHAR));
  1719. wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, PszEscapeMenuStringA(pThis->m_rConnInfo.szCurrentConnectionName, szConn, sizeof(szConn) / sizeof(TCHAR)));
  1720. SetWindowText(GetDlgItem(hwnd, idcCurrentMsg), szMsg);
  1721. // Set control
  1722. GetWindowText(GetDlgItem(hwnd, idrgDialNew), szRes, sizeof(szRes)/sizeof(TCHAR));
  1723. wnsprintf(szMsg, ARRAYSIZE(szMsg), szRes, PszEscapeMenuStringA(pThis->m_szConnectName, szConn, sizeof(szConn) / sizeof(TCHAR)));
  1724. SetWindowText(GetDlgItem(hwnd, idrgDialNew), szMsg);
  1725. // Set Default
  1726. CheckDlgButton(hwnd, idrgDialNew, TRUE);
  1727. return (TRUE);
  1728. case WM_COMMAND:
  1729. switch (GET_WM_COMMAND_ID(wParam, lParam))
  1730. {
  1731. case IDOK:
  1732. {
  1733. if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDontWarnCheck)))
  1734. {
  1735. // If the user has this checked, we reset the "Warn before..." option
  1736. SetDwOption(OPT_DIALUP_WARN_SWITCH, 0, NULL, 0);
  1737. }
  1738. EndDialog(hwnd, IsDlgButtonChecked(hwnd, idrgDialNew) ? idrgDialNew : idrgUseCurrent);
  1739. return (TRUE);
  1740. }
  1741. case IDCANCEL:
  1742. EndDialog(hwnd, IDCANCEL);
  1743. return (TRUE);
  1744. }
  1745. return (TRUE);
  1746. }
  1747. return (FALSE);
  1748. }
  1749. //
  1750. // FUNCTION: CConnectionMAanger::CombinedRasError()
  1751. //
  1752. // PURPOSE: <???>
  1753. //
  1754. // PARAMETERS:
  1755. // <???>
  1756. //
  1757. void CConnectionManager::CombinedRasError(HWND hwnd, UINT unids,
  1758. LPTSTR pszRasError, DWORD dwRasError)
  1759. {
  1760. // Locals
  1761. TCHAR szRes[255],
  1762. sz[30];
  1763. LPTSTR pszError=NULL;
  1764. // Load string
  1765. AthLoadString(unids, szRes, sizeof(szRes));
  1766. // Allocate memory for errors
  1767. DWORD cc = lstrlen(szRes) + lstrlen(pszRasError) + 100;
  1768. pszError = SzStrAlloc(cc);
  1769. // Out of Memory ?
  1770. if (!pszError)
  1771. AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), szRes, 0, MB_OK | MB_ICONSTOP);
  1772. // Build Error message
  1773. else
  1774. {
  1775. AthLoadString(idsErrorText, sz, sizeof(sz));
  1776. wnsprintf(pszError, cc, "%s\n\n%s %d: %s", szRes, sz, dwRasError, pszRasError);
  1777. AthMessageBox(hwnd, MAKEINTRESOURCE(idsRasError), pszError, 0, MB_OK | MB_ICONSTOP);
  1778. MemFree(pszError);
  1779. }
  1780. }
  1781. //
  1782. // FUNCTION: CConnectionManager::RasHangupAndWait()
  1783. //
  1784. // PURPOSE: Hangs up on a RAS connection and waits for it to finish before
  1785. // returning.
  1786. //
  1787. // PARAMETERS:
  1788. // <in> hRasConn - Handle of the connection to hang up.
  1789. // <in> dwMaxWaitSeconds - Amount of time to wait.
  1790. //
  1791. // RETURN VALUE:
  1792. // TRUE if we disconnected, FALSE otherwise.
  1793. //
  1794. BOOL CConnectionManager::RasHangupAndWait(HRASCONN hRasConn, DWORD dwMaxWaitSeconds)
  1795. {
  1796. // Locals
  1797. RASCONNSTATUS rcs;
  1798. DWORD dwTicks=GetTickCount();
  1799. // Check Params
  1800. if (!hRasConn)
  1801. return 0;
  1802. // Make sure RAS is loaded
  1803. if (FAILED (VerifyRasLoaded()))
  1804. return FALSE;
  1805. // Call Ras hangup
  1806. if (RasHangup(hRasConn))
  1807. return FALSE;
  1808. // Wait for connection to really close
  1809. ZeroMemory(&rcs, sizeof(RASCONNSTATUS));
  1810. rcs.dwSize = sizeof(RASCONNSTATUS);
  1811. while (RasGetConnectStatus(hRasConn, &rcs) != ERROR_INVALID_HANDLE && rcs.rasconnstate != RASCS_Disconnected)
  1812. {
  1813. // Wait timeout
  1814. if (GetTickCount() - dwTicks >= dwMaxWaitSeconds * 1000)
  1815. break;
  1816. // Sleep and yields
  1817. Sleep(0);
  1818. }
  1819. // Wait 2 seconds for modem to reset
  1820. Sleep(2000);
  1821. // Done
  1822. return TRUE;
  1823. }
  1824. DWORD CConnectionManager::InternetHangUpAndWait(DWORD_PTR hRasConn, DWORD dwMaxWaitSeconds)
  1825. {
  1826. // Locals
  1827. RASCONNSTATUS rcs;
  1828. DWORD dwTicks=GetTickCount();
  1829. DWORD dwret;
  1830. // Check Params
  1831. if (!hRasConn)
  1832. return 0;
  1833. // Make sure RAS is loaded
  1834. if (FAILED (VerifyRasLoaded()))
  1835. return FALSE;
  1836. dwret = InternetHangUp(m_dwConnId, 0);
  1837. if (dwret)
  1838. {
  1839. DebugTrace("InternetHangup failed: %d\n", dwret);
  1840. goto exit;
  1841. }
  1842. // Wait for connection to really close
  1843. ZeroMemory(&rcs, sizeof(RASCONNSTATUS));
  1844. rcs.dwSize = sizeof(RASCONNSTATUS);
  1845. while (RasGetConnectStatus((HRASCONN)hRasConn, &rcs) != ERROR_INVALID_HANDLE && rcs.rasconnstate != RASCS_Disconnected)
  1846. {
  1847. // Wait timeout
  1848. if (GetTickCount() - dwTicks >= dwMaxWaitSeconds * 1000)
  1849. break;
  1850. // Sleep and yields
  1851. Sleep(0);
  1852. }
  1853. // Wait 2 seconds for modem to reset
  1854. Sleep(2000);
  1855. exit:
  1856. return dwret;
  1857. }
  1858. INT_PTR CALLBACK CConnectionManager::RasLogonDlgProc(HWND hwnd, UINT uMsg,
  1859. WPARAM wParam, LPARAM lParam)
  1860. {
  1861. // Locals
  1862. TCHAR sz[255],
  1863. szText[255 + RAS_MaxEntryName + 1];
  1864. DWORD dwRasError;
  1865. CConnectionManager *pThis = (CConnectionManager *)GetWndThisPtr(hwnd);
  1866. switch (uMsg)
  1867. {
  1868. case WM_INITDIALOG:
  1869. // Get lparam
  1870. pThis = (CConnectionManager *)lParam;
  1871. if (!pThis)
  1872. {
  1873. Assert (FALSE);
  1874. EndDialog(hwnd, E_FAIL);
  1875. return (TRUE);
  1876. }
  1877. // Center the window
  1878. CenterDialog(hwnd);
  1879. // Get Window Title
  1880. GetWindowText(hwnd, sz, sizeof(sz));
  1881. wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_szConnectName);
  1882. SetWindowText(hwnd, szText);
  1883. // Word Default
  1884. AthLoadString(idsDefault, sz, sizeof(sz));
  1885. // Set Fields
  1886. Edit_LimitText(GetDlgItem(hwnd, ideUserName), UNLEN);
  1887. Edit_LimitText(GetDlgItem(hwnd, idePassword), PWLEN);
  1888. Edit_LimitText(GetDlgItem(hwnd, idePhone), RAS_MaxPhoneNumber);
  1889. SetDlgItemText(hwnd, ideUserName, pThis->m_rdp.szUserName);
  1890. SetDlgItemText(hwnd, idePassword, pThis->m_rdp.szPassword);
  1891. if (FIsStringEmpty(pThis->m_rdp.szPhoneNumber))
  1892. SetDlgItemText(hwnd, idePhone, sz);
  1893. else
  1894. SetDlgItemText(hwnd, idePhone, pThis->m_rdp.szPhoneNumber);
  1895. CheckDlgButton(hwnd, idchSavePassword, pThis->m_fSavePassword);
  1896. // Save pRas
  1897. SetWndThisPtr(hwnd, pThis);
  1898. return 1;
  1899. case WM_COMMAND:
  1900. switch(GET_WM_COMMAND_ID(wParam, lParam))
  1901. {
  1902. case idbEditConnection:
  1903. pThis->EditPhonebookEntry(hwnd, (pThis->m_szConnectName));
  1904. return 1;
  1905. case IDCANCEL:
  1906. EndDialog(hwnd, hrUserCancel);
  1907. return 1;
  1908. case IDOK:
  1909. AthLoadString(idsDefault, sz, sizeof(sz));
  1910. // Set Fields
  1911. GetDlgItemText(hwnd, ideUserName, pThis->m_rdp.szUserName, UNLEN+1);
  1912. GetDlgItemText(hwnd, idePassword, pThis->m_rdp.szPassword, PWLEN+1);
  1913. GetDlgItemText(hwnd, idePhone, pThis->m_rdp.szPhoneNumber, RAS_MaxPhoneNumber+1);
  1914. if (lstrcmp(pThis->m_rdp.szPhoneNumber, sz) == 0)
  1915. *pThis->m_rdp.szPhoneNumber = _T('\0');
  1916. pThis->m_fSavePassword = IsDlgButtonChecked(hwnd, idchSavePassword);
  1917. // Save Dial Parameters
  1918. dwRasError = (pThis->m_pRasSetEntryDialParams)(NULL, &(pThis->m_rdp), !(pThis->m_fSavePassword));
  1919. if (dwRasError)
  1920. {
  1921. pThis->DisplayRasError(hwnd, hrSetDialParamsFailed, dwRasError);
  1922. return 1;
  1923. }
  1924. EndDialog(hwnd, S_OK);
  1925. return 1;
  1926. }
  1927. break;
  1928. case WM_DESTROY:
  1929. SetWndThisPtr (hwnd, NULL);
  1930. break;
  1931. }
  1932. return 0;
  1933. }
  1934. INT_PTR CALLBACK CConnectionManager::RasProgressDlgProc(HWND hwnd, UINT uMsg,
  1935. WPARAM wParam, LPARAM lParam)
  1936. {
  1937. // Locals
  1938. CConnectionManager *pThis = (CConnectionManager *) GetWndThisPtr(hwnd);
  1939. TCHAR szText[255+RAS_MaxEntryName+1],
  1940. sz[255];
  1941. static TCHAR s_szCancel[40];
  1942. static UINT s_unRasEventMsg=0;
  1943. static BOOL s_fDetails=FALSE;
  1944. static RECT s_rcDialog;
  1945. static BOOL s_fAuthStarted=FALSE;
  1946. DWORD dwRasError,
  1947. cyDetails;
  1948. RASCONNSTATUS rcs;
  1949. RECT rcDetails,
  1950. rcDlg;
  1951. switch (uMsg)
  1952. {
  1953. case WM_INITDIALOG:
  1954. // Get lparam
  1955. pThis = (CConnectionManager *)lParam;
  1956. if (!pThis)
  1957. {
  1958. Assert (FALSE);
  1959. EndDialog(hwnd, E_FAIL);
  1960. return 1;
  1961. }
  1962. // Save this pointer
  1963. SetWndThisPtr (hwnd, pThis);
  1964. // Save Original Size of the dialog
  1965. GetWindowRect (hwnd, &s_rcDialog);
  1966. // Refresh Connection Info
  1967. pThis->RefreshConnInfo();
  1968. // Details enabled
  1969. s_fDetails = DwGetOption(OPT_RASCONNDETAILS);
  1970. // Hide details drop down
  1971. if (s_fDetails == FALSE)
  1972. {
  1973. // Hid
  1974. GetWindowRect (GetDlgItem (hwnd, idcSplitter), &rcDetails);
  1975. // Height of details
  1976. cyDetails = s_rcDialog.bottom - rcDetails.top;
  1977. // Re-size
  1978. MoveWindow (hwnd, s_rcDialog.left,
  1979. s_rcDialog.top,
  1980. s_rcDialog.right - s_rcDialog.left,
  1981. s_rcDialog.bottom - s_rcDialog.top - cyDetails - 1,
  1982. FALSE);
  1983. }
  1984. else
  1985. {
  1986. AthLoadString (idsHideDetails, sz, sizeof (sz));
  1987. SetWindowText (GetDlgItem (hwnd, idbDet), sz);
  1988. }
  1989. // Get registered RAS event message id
  1990. s_unRasEventMsg = RegisterWindowMessageA(RASDIALEVENT);
  1991. if (s_unRasEventMsg == 0)
  1992. s_unRasEventMsg = WM_RASDIALEVENT;
  1993. // Center the window
  1994. CenterDialog (hwnd);
  1995. SetForegroundWindow(hwnd);
  1996. // Get Window Title
  1997. GetWindowText(hwnd, sz, sizeof(sz));
  1998. wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_szConnectName);
  1999. SetWindowText(hwnd, szText);
  2000. // Dialog Xxxxxxx.....
  2001. if (pThis->m_rdp.szPhoneNumber[0])
  2002. {
  2003. AthLoadString(idsRas_Dialing_Param, sz, sizeof(sz)/sizeof(TCHAR));
  2004. wnsprintf(szText, ARRAYSIZE(szText), sz, pThis->m_rdp.szPhoneNumber);
  2005. }
  2006. else
  2007. AthLoadString(idsRas_Dialing, szText, ARRAYSIZE(szText));
  2008. SetWindowText(GetDlgItem(hwnd, ideProgress), szText);
  2009. // Get Cancel Text
  2010. GetWindowText(GetDlgItem(hwnd, IDCANCEL), s_szCancel, sizeof(s_szCancel));
  2011. // Give the list box and hscroll
  2012. SendMessage(GetDlgItem(hwnd, idlbDetails), LB_SETHORIZONTALEXTENT, 600, 0);
  2013. // Dial the connection
  2014. pThis->m_rConnInfo.hRasConn = NULL;
  2015. dwRasError = (pThis->m_pRasDial)(NULL, NULL, &(pThis->m_rdp), 0xFFFFFFFF, hwnd, &(pThis->m_rConnInfo.hRasConn));
  2016. if (dwRasError)
  2017. {
  2018. pThis->FailedRasDial(hwnd, hrRasDialFailure, dwRasError);
  2019. if (!pThis->LogonRetry(hwnd, s_szCancel))
  2020. {
  2021. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,IDCANCEL), NULL);
  2022. return 1;
  2023. }
  2024. }
  2025. return 1;
  2026. case WM_COMMAND:
  2027. switch(GET_WM_COMMAND_ID(wParam,lParam))
  2028. {
  2029. case IDCANCEL:
  2030. SetDwOption(OPT_RASCONNDETAILS, s_fDetails, NULL, 0);
  2031. EnableWindow(GetDlgItem(hwnd, IDCANCEL), FALSE);
  2032. if (pThis)
  2033. pThis->FailedRasDial(hwnd, hrUserCancel, 0);
  2034. EndDialog(hwnd, hrUserCancel);
  2035. return 1;
  2036. case idbDet:
  2037. // Get current location of the dialog
  2038. GetWindowRect (hwnd, &rcDlg);
  2039. // If currently hidden
  2040. if (s_fDetails == FALSE)
  2041. {
  2042. // Re-size
  2043. MoveWindow (hwnd, rcDlg.left,
  2044. rcDlg.top,
  2045. s_rcDialog.right - s_rcDialog.left,
  2046. s_rcDialog.bottom - s_rcDialog.top,
  2047. TRUE);
  2048. AthLoadString (idsHideDetails, sz, sizeof (sz));
  2049. SetWindowText (GetDlgItem (hwnd, idbDet), sz);
  2050. s_fDetails = TRUE;
  2051. }
  2052. else
  2053. {
  2054. // Size of details
  2055. GetWindowRect (GetDlgItem (hwnd, idcSplitter), &rcDetails);
  2056. cyDetails = rcDlg.bottom - rcDetails.top;
  2057. MoveWindow (hwnd, rcDlg.left,
  2058. rcDlg.top,
  2059. s_rcDialog.right - s_rcDialog.left,
  2060. s_rcDialog.bottom - s_rcDialog.top - cyDetails - 1,
  2061. TRUE);
  2062. AthLoadString (idsShowDetails, sz, sizeof (sz));
  2063. SetWindowText (GetDlgItem (hwnd, idbDet), sz);
  2064. s_fDetails = FALSE;
  2065. }
  2066. break;
  2067. }
  2068. break;
  2069. case WM_DESTROY:
  2070. SetWndThisPtr (hwnd, NULL);
  2071. break;
  2072. case CM_INTERNALRECONNECT:
  2073. if (!pThis->LogonRetry(hwnd, s_szCancel))
  2074. {
  2075. SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDCANCEL,IDCANCEL), NULL);
  2076. return 1;
  2077. }
  2078. break;
  2079. default:
  2080. if (!pThis)
  2081. break;
  2082. pThis->RefreshConnInfo();
  2083. if (uMsg == s_unRasEventMsg)
  2084. {
  2085. HWND hwndLB = GetDlgItem(hwnd, idlbDetails);
  2086. // Error ?
  2087. if (lParam)
  2088. {
  2089. // Disconnected
  2090. AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR));
  2091. ListBox_AddString(hwndLB, sz);
  2092. // Log Error
  2093. TCHAR szRasError[512];
  2094. if ((pThis->m_pRasGetErrorString)((UINT) lParam, szRasError, sizeof(szRasError)) == 0)
  2095. {
  2096. TCHAR szError[512 + 255];
  2097. AthLoadString(idsErrorText, sz, sizeof(sz));
  2098. wnsprintf(szError, ARRAYSIZE(szError), "%s %d: %s", sz, lParam, szRasError);
  2099. ListBox_AddString(hwndLB, szError);
  2100. }
  2101. // Select last item
  2102. SendMessage(hwndLB, LB_SETCURSEL, ListBox_GetCount(hwndLB)-1, 0);
  2103. // Show Error
  2104. pThis->FailedRasDial(hwnd, hrRasDialFailure, (DWORD) lParam);
  2105. // Re logon
  2106. PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0);
  2107. }
  2108. // Otherwise, process RAS event
  2109. else
  2110. {
  2111. switch(wParam)
  2112. {
  2113. case RASCS_OpenPort:
  2114. AthLoadString(idsRASCS_OpenPort, sz, sizeof(sz)/sizeof(TCHAR));
  2115. ListBox_AddString(hwndLB, sz);
  2116. break;
  2117. case RASCS_PortOpened:
  2118. AthLoadString(idsRASCS_PortOpened, sz, sizeof(sz)/sizeof(TCHAR));
  2119. ListBox_AddString(hwndLB, sz);
  2120. break;
  2121. case RASCS_ConnectDevice:
  2122. rcs.dwSize = sizeof(RASCONNSTATUS);
  2123. if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0)
  2124. {
  2125. AthLoadString(idsRASCS_ConnectDevice, sz, sizeof(sz)/sizeof(TCHAR));
  2126. wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.szDeviceName, rcs.szDeviceType);
  2127. ListBox_AddString(hwndLB, szText);
  2128. }
  2129. break;
  2130. case RASCS_DeviceConnected:
  2131. rcs.dwSize = sizeof(RASCONNSTATUS);
  2132. if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0)
  2133. {
  2134. AthLoadString(idsRASCS_DeviceConnected, sz, sizeof(sz)/sizeof(TCHAR));
  2135. wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.szDeviceName, rcs.szDeviceType);
  2136. ListBox_AddString(hwndLB, szText);
  2137. }
  2138. break;
  2139. case RASCS_AllDevicesConnected:
  2140. AthLoadString(idsRASCS_AllDevicesConnected, sz, sizeof(sz)/sizeof(TCHAR));
  2141. ListBox_AddString(hwndLB, sz);
  2142. break;
  2143. case RASCS_Authenticate:
  2144. if (s_fAuthStarted == FALSE)
  2145. {
  2146. AthLoadString(idsRas_Authentication, sz, sizeof(sz)/sizeof(TCHAR));
  2147. SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
  2148. ListBox_AddString(hwndLB, sz);
  2149. s_fAuthStarted = TRUE;
  2150. }
  2151. break;
  2152. case RASCS_AuthNotify:
  2153. rcs.dwSize = sizeof(RASCONNSTATUS);
  2154. if (pThis->m_rConnInfo.hRasConn && (pThis->m_pRasGetConnectStatus)(pThis->m_rConnInfo.hRasConn, &rcs) == 0)
  2155. {
  2156. AthLoadString(idsRASCS_AuthNotify, sz, sizeof(sz)/sizeof(TCHAR));
  2157. wnsprintf(szText, ARRAYSIZE(szText), sz, rcs.dwError);
  2158. ListBox_AddString(hwndLB, szText);
  2159. if (rcs.dwError)
  2160. {
  2161. pThis->FailedRasDial(hwnd, hrRasDialFailure, rcs.dwError);
  2162. PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0);
  2163. }
  2164. }
  2165. break;
  2166. case RASCS_AuthRetry:
  2167. AthLoadString(idsRASCS_AuthRetry, sz, sizeof(sz)/sizeof(TCHAR));
  2168. ListBox_AddString(hwndLB, sz);
  2169. break;
  2170. case RASCS_AuthCallback:
  2171. AthLoadString(idsRASCS_AuthCallback, sz, sizeof(sz)/sizeof(TCHAR));
  2172. ListBox_AddString(hwndLB, sz);
  2173. break;
  2174. case RASCS_AuthChangePassword:
  2175. AthLoadString(idsRASCS_AuthChangePassword, sz, sizeof(sz)/sizeof(TCHAR));
  2176. ListBox_AddString(hwndLB, sz);
  2177. break;
  2178. case RASCS_AuthProject:
  2179. AthLoadString(idsRASCS_AuthProject, sz, sizeof(sz)/sizeof(TCHAR));
  2180. ListBox_AddString(hwndLB, sz);
  2181. break;
  2182. case RASCS_AuthLinkSpeed:
  2183. AthLoadString(idsRASCS_AuthLinkSpeed, sz, sizeof(sz)/sizeof(TCHAR));
  2184. ListBox_AddString(hwndLB, sz);
  2185. break;
  2186. case RASCS_AuthAck:
  2187. AthLoadString(idsRASCS_AuthAck, sz, sizeof(sz)/sizeof(TCHAR));
  2188. ListBox_AddString(hwndLB, sz);
  2189. break;
  2190. case RASCS_ReAuthenticate:
  2191. AthLoadString(idsRas_Authenticated, sz, sizeof(sz)/sizeof(TCHAR));
  2192. SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
  2193. AthLoadString(idsRASCS_Authenticated, sz, sizeof(sz)/sizeof(TCHAR));
  2194. ListBox_AddString(hwndLB, sz);
  2195. break;
  2196. case RASCS_PrepareForCallback:
  2197. AthLoadString(idsRASCS_PrepareForCallback, sz, sizeof(sz)/sizeof(TCHAR));
  2198. ListBox_AddString(hwndLB, sz);
  2199. break;
  2200. case RASCS_WaitForModemReset:
  2201. AthLoadString(idsRASCS_WaitForModemReset, sz, sizeof(sz)/sizeof(TCHAR));
  2202. ListBox_AddString(hwndLB, sz);
  2203. break;
  2204. case RASCS_WaitForCallback:
  2205. AthLoadString(idsRASCS_WaitForCallback, sz, sizeof(sz)/sizeof(TCHAR));
  2206. ListBox_AddString(hwndLB, sz);
  2207. break;
  2208. case RASCS_Projected:
  2209. AthLoadString(idsRASCS_Projected, sz, sizeof(sz)/sizeof(TCHAR));
  2210. ListBox_AddString(hwndLB, sz);
  2211. break;
  2212. case RASCS_Disconnected:
  2213. AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR));
  2214. SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
  2215. ListBox_AddString(hwndLB, sz);
  2216. pThis->FailedRasDial(hwnd, hrRasDialFailure, 0);
  2217. PostMessage(hwnd, CM_INTERNALRECONNECT, 0, 0);
  2218. break;
  2219. case RASCS_Connected:
  2220. SetDwOption(OPT_RASCONNDETAILS, s_fDetails, NULL, 0);
  2221. AthLoadString(idsRASCS_Connected, sz, sizeof(sz)/sizeof(TCHAR));
  2222. SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
  2223. ListBox_AddString(hwndLB, sz);
  2224. EndDialog(hwnd, S_OK);
  2225. break;
  2226. }
  2227. // Select last lb item
  2228. SendMessage(hwndLB, LB_SETCURSEL, ListBox_GetCount(hwndLB)-1, 0);
  2229. }
  2230. return 1;
  2231. }
  2232. break;
  2233. }
  2234. // Done
  2235. return 0;
  2236. }
  2237. BOOL CConnectionManager::LogonRetry(HWND hwnd, LPTSTR pszCancel)
  2238. {
  2239. // Locals
  2240. DWORD dwRasError;
  2241. // Refresh
  2242. RefreshConnInfo();
  2243. // Reset Cancel button
  2244. SetWindowText(GetDlgItem(hwnd, IDCANCEL), pszCancel);
  2245. // Empty the listbox
  2246. ListBox_ResetContent(GetDlgItem(hwnd, idlbDetails));
  2247. while(1)
  2248. {
  2249. // If failed...
  2250. if (FAILED(RasLogon(hwnd, m_szConnectName, TRUE)))
  2251. return FALSE;
  2252. // Dial the connection
  2253. m_rConnInfo.hRasConn = NULL;
  2254. dwRasError = RasDial(NULL, NULL, &m_rdp, 0xFFFFFFFF, hwnd, &m_rConnInfo.hRasConn);
  2255. if (dwRasError)
  2256. {
  2257. FailedRasDial(hwnd, hrRasDialFailure, dwRasError);
  2258. continue;
  2259. }
  2260. // Success
  2261. break;
  2262. }
  2263. // Done
  2264. return TRUE;
  2265. }
  2266. // =====================================================================================
  2267. // CConnectionManager::FailedRasDial
  2268. // =====================================================================================
  2269. VOID CConnectionManager::FailedRasDial(HWND hwnd, HRESULT hrRasError, DWORD dwRasError)
  2270. {
  2271. // Locals
  2272. TCHAR sz[255];
  2273. // Refresh
  2274. RefreshConnInfo();
  2275. // Hangup the connection
  2276. if (m_rConnInfo.hRasConn)
  2277. RasHangupAndWait(m_rConnInfo.hRasConn, DEF_HANGUP_WAIT);
  2278. // Disconnected
  2279. AthLoadString(idsRASCS_Disconnected, sz, sizeof(sz)/sizeof(TCHAR));
  2280. SetWindowText(GetDlgItem(hwnd, ideProgress), sz);
  2281. // Save dwRasError
  2282. DisplayRasError(hwnd, hrRasError, dwRasError);
  2283. // NULL it
  2284. m_rConnInfo.hRasConn = NULL;
  2285. // Change dialog button to OK
  2286. AthLoadString(idsOK, sz, sizeof(sz)/sizeof(TCHAR));
  2287. SetWindowText(GetDlgItem(hwnd, IDCANCEL), sz);
  2288. }
  2289. DWORD CConnectionManager::EditPhonebookEntry(HWND hwnd, LPTSTR pszEntryName)
  2290. {
  2291. if (FAILED(VerifyRasLoaded()))
  2292. return (DWORD)E_FAIL;
  2293. if (FIsPlatformWinNT() && m_hInstRasDlg && m_pRasEntryDlg)
  2294. {
  2295. RASENTRYDLG info;
  2296. ZeroMemory(&info, sizeof(RASENTRYDLG));
  2297. info.dwSize = sizeof(RASENTRYDLG);
  2298. info.hwndOwner = hwnd;
  2299. m_pRasEntryDlg(NULL, pszEntryName, &info);
  2300. return info.dwError;
  2301. }
  2302. else
  2303. {
  2304. return RasEditPhonebookEntry(hwnd, NULL, pszEntryName);
  2305. }
  2306. }
  2307. //
  2308. // FUNCTION: CConnectionNotify::SendAdvise()
  2309. //
  2310. // PURPOSE: Sends the specified notification to all the clients that have
  2311. // requested notifications.
  2312. //
  2313. // PARAMETERS:
  2314. // <in> nCode - Notification code to send.
  2315. // <in> pvData - Data to send with the notificaiton. Can be NULL.
  2316. //
  2317. void CConnectionManager::SendAdvise(CONNNOTIFY nCode, LPVOID pvData)
  2318. {
  2319. if (nCode == CONNNOTIFY_CONNECTED)
  2320. DoOfflineTransactions();
  2321. // Loop through each interface and send the notification
  2322. EnterCriticalSection(&m_cs);
  2323. NOTIFYHWND *pTemp = m_pNotifyList;
  2324. while (pTemp)
  2325. {
  2326. Assert(IsWindow(pTemp->hwnd));
  2327. DWORD dwThread = GetCurrentThreadId();
  2328. PostMessage(pTemp->hwnd, CM_NOTIFY, (WPARAM) nCode, (LPARAM) pvData);
  2329. pTemp = pTemp->pNext;
  2330. }
  2331. LeaveCriticalSection(&m_cs);
  2332. }
  2333. void CConnectionManager::FreeNotifyList(void)
  2334. {
  2335. // Loop through the notify windows we own
  2336. NOTIFYHWND *pTemp;
  2337. while (m_pNotifyList)
  2338. {
  2339. // Get the list of notify callbacks for this window
  2340. if (IsWindow(m_pNotifyList->hwnd))
  2341. {
  2342. NOTIFYLIST *pList = (NOTIFYLIST *) GetWindowLongPtr(m_pNotifyList->hwnd, GWLP_USERDATA);
  2343. NOTIFYLIST *pListT;
  2344. // Loop through the callbacks freeing each one
  2345. while (pList)
  2346. {
  2347. pListT = pList->pNext;
  2348. SafeMemFree(pList);
  2349. pList = pListT;
  2350. }
  2351. SetWindowLong(m_pNotifyList->hwnd, GWLP_USERDATA, NULL);
  2352. RemoveProp(m_pNotifyList->hwnd, NOTIFY_HWND);
  2353. if (GetCurrentThreadId() == GetWindowThreadProcessId(m_pNotifyList->hwnd, NULL))
  2354. {
  2355. DestroyWindow(m_pNotifyList->hwnd);
  2356. }
  2357. else
  2358. PostMessage(m_pNotifyList->hwnd, WM_CLOSE, 0, 0L);
  2359. }
  2360. pTemp = m_pNotifyList;
  2361. m_pNotifyList = m_pNotifyList->pNext;
  2362. SafeMemFree(pTemp);
  2363. }
  2364. }
  2365. LRESULT CALLBACK CConnectionManager::NotifyWndProc(HWND hwnd, UINT uMsg,
  2366. WPARAM wParam, LPARAM lParam)
  2367. {
  2368. //CConnectionManager *pThis = (CConnectionManager *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
  2369. CConnectionManager *pThis = (CConnectionManager *)GetProp(hwnd, NOTIFY_HWND);
  2370. // If we're idle, then we should not process any notifications
  2371. if (uMsg != WM_NCCREATE && !pThis)
  2372. return (DefWindowProc(hwnd, uMsg, wParam, lParam));
  2373. switch (uMsg)
  2374. {
  2375. case WM_NCCREATE:
  2376. pThis = (CConnectionManager *) ((LPCREATESTRUCT) lParam)->lpCreateParams;
  2377. //SetWindowLong(hwnd, GWLP_USERDATA, (LONG) pThis);
  2378. SetProp(hwnd, NOTIFY_HWND, (HANDLE)pThis);
  2379. return (TRUE);
  2380. case CM_NOTIFY:
  2381. // This doesn't need to be critsec'd since the message is sent from
  2382. // within a critsec.
  2383. NOTIFYLIST *pList = (NOTIFYLIST *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  2384. while (pList)
  2385. {
  2386. pList->pNotify->OnConnectionNotify((CONNNOTIFY) wParam, (LPVOID) lParam, pThis);
  2387. pList = pList->pNext;
  2388. }
  2389. return (0);
  2390. }
  2391. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  2392. }
  2393. HRESULT CConnectionManager::GetDefaultConnection(IImnAccount *pAccount,
  2394. IImnAccount **ppDefault)
  2395. {
  2396. TCHAR szDefault[CCHMAX_ACCOUNT_NAME];
  2397. ACCTTYPE acctType;
  2398. HRESULT hr = S_OK;
  2399. // Get the type of account from the original account
  2400. if (FAILED(hr = pAccount->GetAccountType(&acctType)))
  2401. {
  2402. // How can an account have no account type?
  2403. Assert(FALSE);
  2404. return (hr);
  2405. }
  2406. // Ask the account manager for the default account of this type
  2407. if (FAILED(hr = g_pAcctMan->GetDefaultAccount(acctType, ppDefault)))
  2408. {
  2409. // No default account of this type?
  2410. Assert(FALSE);
  2411. return (hr);
  2412. }
  2413. return (S_OK);
  2414. }
  2415. BOOL CConnectionManager::IsConnectionUsed(LPTSTR pszConn)
  2416. {
  2417. IImnEnumAccounts *pEnum = NULL;
  2418. IImnAccount *pAcct = NULL;
  2419. DWORD dwConn = 0;
  2420. TCHAR szConn[CCHMAX_CONNECTOID];
  2421. BOOL fFound = FALSE;
  2422. // Get the enumerator from the account manager
  2423. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_ALL, &pEnum)))
  2424. {
  2425. pEnum->Reset();
  2426. // Walk through all the accounts
  2427. while (!fFound && SUCCEEDED(pEnum->GetNext(&pAcct)))
  2428. {
  2429. // Get the connection type for this account
  2430. if (SUCCEEDED(pAcct->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConn)))
  2431. {
  2432. // If the account is a RAS account, ask for the connectoid name
  2433. // and the account name.
  2434. if (dwConn == CONNECTION_TYPE_RAS)
  2435. {
  2436. pAcct->GetPropSz(AP_RAS_CONNECTOID, szConn, ARRAYSIZE(szConn));
  2437. // Check to see if this connection matches
  2438. if (0 == lstrcmpi(szConn, pszConn))
  2439. {
  2440. fFound = TRUE;
  2441. }
  2442. }
  2443. }
  2444. SafeRelease(pAcct);
  2445. }
  2446. SafeRelease(pEnum);
  2447. }
  2448. return (fFound);
  2449. }
  2450. HRESULT CConnectionManager::ConnectActual(LPTSTR pszRasConn, HWND hwndParent, BOOL fShowUI)
  2451. {
  2452. HRESULT hr;
  2453. StrCpyN(m_szConnectName, pszRasConn, ARRAYSIZE(m_szConnectName));
  2454. // RefreshConnInfo
  2455. CHECKHR(hr = RefreshConnInfo());
  2456. // Make sure the RAS DLL is loaded before we try this
  2457. if (FAILED(VerifyRasLoaded()))
  2458. {
  2459. hr = HR_E_UNINITIALIZED;
  2460. goto exit;
  2461. }
  2462. // Check to see if we even can connect
  2463. hr = CanConnectActual(pszRasConn);
  2464. // If we can connect using the current connection, return success
  2465. if (S_OK == hr)
  2466. {
  2467. m_rConnInfo.fConnected = TRUE;
  2468. hr = S_OK;
  2469. goto exit;
  2470. }
  2471. // There is another connection already established ask the user if they
  2472. // want to change.
  2473. if (!m_fDialerUI)
  2474. {
  2475. m_fDialerUI = TRUE;
  2476. if (E_FAIL == hr)
  2477. {
  2478. UINT uAnswer;
  2479. uAnswer = idrgUseCurrent;
  2480. // Check to see if this a voodoo Connection Manager autodialer thing
  2481. if (!ConnectionManagerVoodoo(pszRasConn))
  2482. {
  2483. if (fShowUI)
  2484. uAnswer = PromptCloseConnection(hwndParent);
  2485. // The user canceled from the dialog. Therefore we give up.
  2486. if (IDCANCEL == uAnswer || IDNO == uAnswer)
  2487. {
  2488. hr = hrUserCancel;
  2489. goto exit;
  2490. }
  2491. // The user said they wanted to hang up and dial a new connection.
  2492. else if (idrgDialNew == uAnswer || IDYES == uAnswer)
  2493. {
  2494. Disconnect(hwndParent, fShowUI, TRUE, FALSE);
  2495. }
  2496. // The user said to try to use the current connection.
  2497. else if (idrgUseCurrent == uAnswer)
  2498. {
  2499. // Who are we to tell the user what to do...
  2500. //Save the conn info so we can return true for this connection in CanConnectActual
  2501. AddToConnList(pszRasConn);
  2502. // Send a connect notification since we are getting connected and then return
  2503. hr = S_OK;
  2504. goto NotifyAndExit;
  2505. }
  2506. }
  2507. }
  2508. else
  2509. {
  2510. //I don't see any reason as to why this is there.
  2511. // If we started RAS, then we can close it on a whim.
  2512. Disconnect(hwndParent, fShowUI, FALSE, FALSE);
  2513. }
  2514. // Only one caller can be dialing the phone at a time.
  2515. if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0))
  2516. {
  2517. hr = HR_E_DIALING_INPROGRESS;
  2518. goto exit;
  2519. }
  2520. if (S_FALSE == (hr = DoAutoDial(hwndParent, pszRasConn, TRUE)))
  2521. {
  2522. DWORD dwReturn;
  2523. DWORD dwLanFlags = 0;
  2524. DWORD dwDialFlags = 0;
  2525. dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
  2526. if (VerifyMobilityPackLoaded() == S_OK)
  2527. {
  2528. if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN)))
  2529. dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE;
  2530. }
  2531. dwReturn = InternetDialA(hwndParent, pszRasConn, dwDialFlags,
  2532. &m_dwConnId, 0);
  2533. /*
  2534. // Dial the new connection
  2535. if (SUCCEEDED(hr = StartRasDial(hwndParent, pszRasConn)))
  2536. */
  2537. if (dwReturn == 0)
  2538. {
  2539. m_rConnInfo.fConnected = TRUE;
  2540. m_rConnInfo.fIStartedRas = TRUE;
  2541. m_rConnInfo.fAutoDial = FALSE;
  2542. m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId;
  2543. StrCpyN(m_rConnInfo.szCurrentConnectionName, pszRasConn, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName));
  2544. hr = S_OK;
  2545. }
  2546. else
  2547. {
  2548. if (dwReturn == ERROR_USER_DISCONNECTION)
  2549. {
  2550. hr = HR_E_USER_CANCEL_CONNECT;
  2551. if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE))
  2552. SetGlobalOffline(TRUE);
  2553. }
  2554. else
  2555. {
  2556. DebugTrace("Error dialing: %d\n", GetLastError());
  2557. hr = E_FAIL;
  2558. }
  2559. }
  2560. }
  2561. ReleaseMutex(m_hMutexDial);
  2562. NotifyAndExit:
  2563. // Send the advise after we leave the critsec to make sure we don't deadlock
  2564. if (hr == S_OK)
  2565. {
  2566. SendAdvise(CONNNOTIFY_CONNECTED, NULL);
  2567. }
  2568. exit:
  2569. m_fDialerUI = FALSE;
  2570. }
  2571. return (hr);
  2572. }
  2573. HRESULT CConnectionManager::CanConnectActual(LPTSTR pszRasConn)
  2574. {
  2575. LPRASCONN pConnections = NULL;
  2576. ULONG cConnections = 0;
  2577. BOOL fFound = 0;
  2578. HRESULT hr = E_FAIL;
  2579. TCHAR pszCurConn[CCHMAX_CONNECTOID];
  2580. DWORD dwFlags;
  2581. //Look in our Conection list first
  2582. hr = SearchConnList(pszRasConn);
  2583. if (hr == S_OK)
  2584. return hr;
  2585. // Make sure the RAS DLL is loaded before we try this
  2586. if (FAILED(VerifyRasLoaded()))
  2587. {
  2588. hr = HR_E_UNINITIALIZED;
  2589. goto exit;
  2590. }
  2591. // Find out what we're currently connected to
  2592. if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)))
  2593. {
  2594. // If no connections exist, then just exit
  2595. if (0 == cConnections)
  2596. {
  2597. SafeMemFree(pConnections);
  2598. hr = S_FALSE;
  2599. goto exit;
  2600. }
  2601. // Walk through the existing connections and see if we can find the
  2602. // one we're looking for.
  2603. for (ULONG i = 0; i < cConnections; i++)
  2604. {
  2605. if (0 == lstrcmpi(pszRasConn, pConnections[i].szEntryName))
  2606. {
  2607. // Found it. Return success.
  2608. fFound = TRUE;
  2609. break;
  2610. }
  2611. }
  2612. // Free the list of connections returned from the enumerator
  2613. SafeMemFree(pConnections);
  2614. hr = (fFound ? S_OK : E_FAIL);
  2615. goto exit;
  2616. }
  2617. exit:
  2618. if ((hr != S_OK) && (m_fDialerUI))
  2619. hr = HR_E_DIALING_INPROGRESS;
  2620. return (hr);
  2621. }
  2622. INT_PTR CALLBACK CConnectionManager::RasStartupDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  2623. {
  2624. // Locals
  2625. CConnectionManager *pThis = (CConnectionManager *) GetWndThisPtr(hwnd);
  2626. TCHAR szConn[CCHMAX_CONNECTOID];
  2627. DWORD dwOpt = OPT_DIALUP_LAST_START;
  2628. switch (uMsg)
  2629. {
  2630. case WM_INITDIALOG:
  2631. pThis = (CConnectionManager *)lParam;
  2632. if (!pThis)
  2633. {
  2634. Assert (FALSE);
  2635. EndDialog(hwnd, E_FAIL);
  2636. return 1;
  2637. }
  2638. // Save this pointer
  2639. SetWndThisPtr (hwnd, pThis);
  2640. // Fill in the combo box
  2641. pThis->FillRasCombo(GetDlgItem(hwnd, idcDialupCombo), TRUE);
  2642. // If there are no RAS connections, then don't show the dialog
  2643. if (ComboBox_GetCount(GetDlgItem(hwnd, idcDialupCombo)) <= 1)
  2644. {
  2645. EndDialog(hwnd, 0);
  2646. return (TRUE);
  2647. }
  2648. // If the reason that we're in this dialog is because the user usually autodial's
  2649. // on startup but is now offline, then we should display the normal autodial
  2650. // connectoid
  2651. if (START_CONNECT == DwGetOption(OPT_DIALUP_START))
  2652. dwOpt = OPT_DIALUP_CONNECTION;
  2653. // Initialize the combo box to the last connection
  2654. *szConn = 0;
  2655. GetOption(dwOpt, szConn, ARRAYSIZE(szConn));
  2656. if (0 != *szConn)
  2657. {
  2658. // If we can't find it any longer, then according to the spec, we're
  2659. // supposed to default to the "Ask me" option
  2660. if (CB_ERR == ComboBox_SelectString(GetDlgItem(hwnd, idcDialupCombo), -1, szConn))
  2661. {
  2662. ComboBox_SetCurSel(GetDlgItem(hwnd, idcDialupCombo), 0);
  2663. }
  2664. }
  2665. else
  2666. ComboBox_SetCurSel(GetDlgItem(hwnd, idcDialupCombo), 0);
  2667. CenterDialog(hwnd);
  2668. return (TRUE);
  2669. case WM_COMMAND:
  2670. switch (LOWORD(wParam))
  2671. {
  2672. case IDOK:
  2673. // Get the connection name from the combo box
  2674. ComboBox_GetText(GetDlgItem(hwnd, idcDialupCombo), szConn, ARRAYSIZE(szConn));
  2675. // Check to see if it's the "Don't dial..." string
  2676. TCHAR szRes[CCHMAX_STRINGRES];
  2677. AthLoadString(idsConnNoDial, szRes, ARRAYSIZE(szRes));
  2678. if (0 == lstrcmp(szRes, szConn))
  2679. {
  2680. // It's the don't dial string, so clear the history in the registry
  2681. SetOption(OPT_DIALUP_LAST_START, _T(""), sizeof(TCHAR), NULL, 0);
  2682. // See if the user checked the "Set as default..."
  2683. if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDefaultCheck)))
  2684. {
  2685. // If don't dial is set as default, we clear the startup prompt option
  2686. SetDwOption(OPT_DIALUP_START, START_NO_CONNECT, NULL, 0);
  2687. }
  2688. }
  2689. else
  2690. {
  2691. // Save this connection in the history
  2692. SetOption(OPT_DIALUP_LAST_START, szConn, lstrlen(szConn) + 1, NULL, 0);
  2693. if (BST_CHECKED == Button_GetCheck(GetDlgItem(hwnd, idcDefaultCheck)))
  2694. {
  2695. // If the user want's this as default, then we change the startup
  2696. // option to auto connect to this connection.
  2697. SetDwOption(OPT_DIALUP_START, START_CONNECT, NULL, 0);
  2698. SetOption(OPT_DIALUP_CONNECTION, szConn, lstrlen(szConn) + 1, NULL, 0);
  2699. }
  2700. // Dial the phone
  2701. pThis->ConnectActual(szConn, hwnd, FALSE);
  2702. }
  2703. EndDialog(hwnd, 0);
  2704. return (TRUE);
  2705. case IDCANCEL:
  2706. EndDialog(hwnd, 0);
  2707. return (TRUE);
  2708. }
  2709. break;
  2710. case WM_CLOSE:
  2711. SendMessage(hwnd, WM_COMMAND, IDCANCEL, 0);
  2712. return (TRUE);
  2713. }
  2714. return (FALSE);
  2715. }
  2716. //-------------------------------------------------------------------------------------------
  2717. // Function: FIsPlatformWinNT() - checks if we are running on NT or Win95
  2718. //-------------------------------------------------------------------------------------------
  2719. BOOL FIsPlatformWinNT()
  2720. {
  2721. return (g_OSInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  2722. }
  2723. HRESULT CConnectionManager::RefreshConnInfo(BOOL fSendAdvise)
  2724. {
  2725. // Locals
  2726. HRESULT hr=S_OK;
  2727. LPRASCONN pConnections=NULL;
  2728. ULONG cConnections=0;
  2729. BOOL fFound=FALSE;
  2730. ULONG i;
  2731. // Thread Safety
  2732. EnterCriticalSection(&m_cs);
  2733. // No Refresh needed
  2734. if (CIS_REFRESH != m_rConnInfo.state)
  2735. goto exit;
  2736. // Set this here to prevent an infinite loop and thus a stack fault.
  2737. m_rConnInfo.state = CIS_CLEAN;
  2738. // Make sure the RAS DLL is loaded before we try this
  2739. CHECKHR(hr = VerifyRasLoaded());
  2740. // Find out what we're currently connected to
  2741. CHECKHR(hr = EnumerateConnections(&pConnections, &cConnections));
  2742. // Walk through the existing connections and see if we can find the
  2743. // one we're looking for.
  2744. for (i = 0; i < cConnections; i++)
  2745. {
  2746. // if (m_rConnInfo.hRasConn == pConnections[i].hrasconn)
  2747. //To get around a problem in ConnectActual when we dial using InternetDial
  2748. if (lstrcmp(m_rConnInfo.szCurrentConnectionName, pConnections[i].szEntryName) == 0)
  2749. {
  2750. // Found it. Return success.
  2751. fFound = TRUE;
  2752. m_rConnInfo.fConnected = TRUE;
  2753. m_rConnInfo.fIStartedRas = TRUE;
  2754. m_rConnInfo.hRasConn = pConnections[0].hrasconn;
  2755. m_dwConnId = (DWORD_PTR) m_rConnInfo.hRasConn;
  2756. break;
  2757. }
  2758. }
  2759. // If we didn't find our connection
  2760. if (!fFound)
  2761. {
  2762. // The user hung up. We need to put ourselves in a disconnected
  2763. // state.
  2764. if (cConnections == 0)
  2765. {
  2766. Disconnect(NULL, FALSE, TRUE, FALSE);
  2767. }
  2768. else
  2769. {
  2770. StrCpyN(m_rConnInfo.szCurrentConnectionName, pConnections[0].szEntryName, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName));
  2771. m_rConnInfo.fConnected = TRUE;
  2772. m_rConnInfo.fIStartedRas = FALSE;
  2773. m_rConnInfo.hRasConn = pConnections[0].hrasconn;
  2774. m_dwConnId = (DWORD_PTR) m_rConnInfo.hRasConn;
  2775. if (fSendAdvise)
  2776. SendAdvise(CONNNOTIFY_CONNECTED, NULL);
  2777. }
  2778. }
  2779. exit:
  2780. // Thread Safety
  2781. LeaveCriticalSection(&m_cs);
  2782. // Free the list of connections returned from the enumerator
  2783. SafeMemFree(pConnections);
  2784. // Done
  2785. return hr;
  2786. }
  2787. //
  2788. // FUNCTION: CConnectionManager::IsGlobalOffline()
  2789. //
  2790. // PURPOSE: Checks the state of the WININET global offline setting.
  2791. // Note - this is copied from shdocvw
  2792. //
  2793. // PARAMETERS:
  2794. // void
  2795. //
  2796. // RETURN VALUE:
  2797. // BOOL
  2798. //
  2799. BOOL CConnectionManager::IsGlobalOffline(void)
  2800. {
  2801. DWORD dwState = 0, dwSize = sizeof(DWORD);
  2802. BOOL fRet = FALSE;
  2803. if (InternetQueryOptionA(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState,
  2804. &dwSize))
  2805. {
  2806. if (dwState & INTERNET_STATE_DISCONNECTED_BY_USER)
  2807. fRet = TRUE;
  2808. }
  2809. return (fRet);
  2810. }
  2811. //
  2812. // FUNCTION: CConnectionManager::SetGlobalOffline()
  2813. //
  2814. // PURPOSE: Sets the global offline state for Athena and IE. Note - this
  2815. // function is copied from shdocvw.
  2816. //
  2817. // PARAMETERS:
  2818. // <in> fOffline - TRUE to disconnect, FALSE to allow connections.
  2819. //
  2820. // RETURN VALUE:
  2821. // void
  2822. //
  2823. void CConnectionManager::SetGlobalOffline(BOOL fOffline, HWND hwndParent)
  2824. {
  2825. DWORD dwReturn;
  2826. if (fOffline)
  2827. {
  2828. if (hwndParent)
  2829. {
  2830. //Offer to hangup
  2831. RefreshConnInfo(FALSE);
  2832. if (m_rConnInfo.hRasConn)
  2833. {
  2834. dwReturn = AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena),
  2835. MAKEINTRESOURCEW(idsWorkOfflineHangup), 0,
  2836. MB_YESNOCANCEL);
  2837. if (dwReturn == IDCANCEL)
  2838. return;
  2839. if (dwReturn == IDYES)
  2840. {
  2841. Disconnect(hwndParent, FALSE, TRUE, FALSE);
  2842. }
  2843. }
  2844. }
  2845. }
  2846. SetShellOfflineState(fOffline);
  2847. m_fOffline = fOffline;
  2848. if (!m_fOffline)
  2849. DoOfflineTransactions();
  2850. SendAdvise(CONNNOTIFY_WORKOFFLINE, (LPVOID) IntToPtr(fOffline));
  2851. }
  2852. typedef BOOL (WINAPI *PFNINETDIALHANDLER)(HWND,LPCSTR, DWORD, LPDWORD);
  2853. HRESULT CConnectionManager::DoAutoDial(HWND hwndParent, LPTSTR pszConnectoid, BOOL fDial)
  2854. {
  2855. TCHAR szAutodialDllName[MAX_PATH];
  2856. TCHAR szAutodialFcnName[MAX_PATH];
  2857. HRESULT hr = S_FALSE;
  2858. UINT uError;
  2859. HINSTANCE hInstDialer = 0;
  2860. PFNINETDIALHANDLER pfnDialHandler = NULL;
  2861. DWORD dwRasError = 0;
  2862. BOOL f = 0;
  2863. TCHAR szRegPath[MAX_PATH];
  2864. LPRASCONN pConnections = NULL;
  2865. ULONG cConnections = 0;
  2866. DWORD dwDialFlags = fDial ? INTERNET_CUSTOMDIAL_CONNECT : INTERNET_CUSTOMDIAL_DISCONNECT;
  2867. // Check to see if this connectoid has the autodial values
  2868. if (FAILED(LookupAutoDialHandler(pszConnectoid, szAutodialDllName, szAutodialFcnName)))
  2869. goto exit;
  2870. // If we were able to load those two values, then we're going to let the
  2871. // autodialer take care of dialing the phone.
  2872. uError = SetErrorMode(SEM_NOOPENFILEERRORBOX);
  2873. // Try to load the library that contains the autodialer
  2874. hInstDialer = LoadLibrary(szAutodialDllName);
  2875. SetErrorMode(uError);
  2876. if (!hInstDialer)
  2877. {
  2878. goto exit;
  2879. }
  2880. // Try to load the function address
  2881. pfnDialHandler = (PFNINETDIALHANDLER) GetProcAddress(hInstDialer,
  2882. szAutodialFcnName);
  2883. if (!pfnDialHandler)
  2884. goto exit;
  2885. // Call the dialer
  2886. f = (*pfnDialHandler)(hwndParent, pszConnectoid, dwDialFlags,
  2887. &dwRasError);
  2888. hr = f ? S_OK : E_FAIL;
  2889. m_rConnInfo.fConnected = fDial && f;
  2890. m_rConnInfo.fIStartedRas = TRUE;
  2891. m_rConnInfo.fAutoDial = TRUE;
  2892. if (f && fDial)
  2893. {
  2894. // Need to get the current connection handle
  2895. if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)))
  2896. {
  2897. for (UINT i = 0; i < cConnections; i++)
  2898. {
  2899. if (0 == lstrcmpi(pConnections[i].szEntryName, pszConnectoid))
  2900. {
  2901. EnterCriticalSection(&m_cs);
  2902. m_rConnInfo.hRasConn = pConnections[i].hrasconn;
  2903. m_rConnInfo.state = CIS_REFRESH; // new connection, must refresh conn info
  2904. LeaveCriticalSection(&m_cs);
  2905. break;
  2906. }
  2907. }
  2908. SafeMemFree(pConnections);
  2909. }
  2910. }
  2911. exit:
  2912. if (hInstDialer)
  2913. FreeLibrary(hInstDialer);
  2914. return (hr);
  2915. }
  2916. HRESULT CConnectionManager::LookupAutoDialHandler(LPTSTR pszConnectoid, LPTSTR pszAutodialDllName,
  2917. LPTSTR pszAutodialFcnName)
  2918. {
  2919. HRESULT hr = E_FAIL;
  2920. DWORD dwEntryInfoSize = 0;
  2921. LPRASENTRY pRasEntry = NULL;
  2922. *pszAutodialDllName = 0;
  2923. *pszAutodialFcnName = 0;
  2924. if (m_pRasGetEntryProperties)
  2925. {
  2926. // Find out how big the struct we need to pass in should be
  2927. RasGetEntryProperties(NULL, pszConnectoid, NULL, &dwEntryInfoSize, NULL, NULL);
  2928. if (dwEntryInfoSize)
  2929. {
  2930. // Allocate a buffer big enough for this structure
  2931. if (!MemAlloc((LPVOID*) &pRasEntry, dwEntryInfoSize))
  2932. return (E_OUTOFMEMORY);
  2933. // Request the RASENTRY properties
  2934. pRasEntry->dwSize = sizeof(RASENTRY);
  2935. if (0 != RasGetEntryProperties(NULL, pszConnectoid, pRasEntry, &dwEntryInfoSize, NULL, NULL))
  2936. goto exit;
  2937. // Copy the autodial info to the provided buffers
  2938. if (pRasEntry->szAutodialDll[0])
  2939. StrCpyN(pszAutodialDllName, pRasEntry->szAutodialDll, MAX_PATH);
  2940. if (pRasEntry->szAutodialFunc[0])
  2941. StrCpyN(pszAutodialFcnName, pRasEntry->szAutodialFunc, MAX_PATH);
  2942. // If we got here, we have all the data we need
  2943. if (*pszAutodialDllName && *pszAutodialFcnName)
  2944. hr = S_OK;
  2945. }
  2946. }
  2947. exit:
  2948. SafeMemFree(pRasEntry);
  2949. return (hr);
  2950. }
  2951. // If the current connection is a CM connection, and the target connection is
  2952. // a CM connection, then we let the CM do whatever it is that they do.
  2953. BOOL CConnectionManager::ConnectionManagerVoodoo(LPTSTR pszConnection)
  2954. {
  2955. TCHAR szAutodialDllName[MAX_PATH];
  2956. TCHAR szAutodialFcnName[MAX_PATH];
  2957. // Check to see if the target is a CM connectoid
  2958. if (FAILED(LookupAutoDialHandler(pszConnection, szAutodialDllName, szAutodialFcnName)))
  2959. return (FALSE);
  2960. // Find out if the current connection is a CM connectoid
  2961. if (FAILED(LookupAutoDialHandler(m_rConnInfo.szCurrentConnectionName, szAutodialDllName,
  2962. szAutodialFcnName)))
  2963. return (FALSE);
  2964. return (TRUE);
  2965. }
  2966. HRESULT CConnectionManager::OEIsDestinationReachable(IImnAccount *pAccount, DWORD dwConnType)
  2967. {
  2968. char szServerName[256];
  2969. HRESULT hr = S_FALSE;
  2970. /*
  2971. if ((VerifyMobilityPackLoaded() == S_OK) &&
  2972. (GetServerName(pAccount, szServerName, ARRAYSIZE(szServerName)) == S_OK))
  2973. {
  2974. if (IsDestinationReachable(szServerName, NULL) &&
  2975. (GetLastError() == 0))
  2976. {
  2977. hr = S_OK;
  2978. }
  2979. }
  2980. else
  2981. {
  2982. */
  2983. DWORD dw;
  2984. if (SUCCEEDED(pAccount->GetPropDw(AP_HTTPMAIL_DOMAIN_MSN, &dw)) && dw)
  2985. {
  2986. if(HideHotmail())
  2987. return(hr);
  2988. }
  2989. hr = IsInternetReachable(pAccount, dwConnType);
  2990. /*
  2991. }
  2992. */
  2993. return hr;
  2994. }
  2995. HRESULT CConnectionManager::IsInternetReachable(IImnAccount *pAccount, DWORD dwConnType)
  2996. {
  2997. TCHAR szConnectionName[CCHMAX_CONNECTOID];
  2998. HRESULT hr = S_FALSE;
  2999. DWORD dwFlags;
  3000. switch (dwConnType)
  3001. {
  3002. case CONNECTION_TYPE_RAS:
  3003. {
  3004. if (FAILED(hr = pAccount->GetPropSz(AP_RAS_CONNECTOID, szConnectionName, ARRAYSIZE(szConnectionName))))
  3005. {
  3006. AssertSz(FALSE, _T("CConnectionManager::Connect() - No connection name."));
  3007. break;
  3008. }
  3009. hr = CanConnectActual(szConnectionName);
  3010. break;
  3011. }
  3012. case CONNECTION_TYPE_LAN:
  3013. {
  3014. if (VerifyMobilityPackLoaded() == S_OK)
  3015. {
  3016. if (IsNetworkAlive(&dwFlags) && (!!(dwFlags & NETWORK_ALIVE_LAN)))
  3017. {
  3018. hr = S_OK;
  3019. }
  3020. }
  3021. else
  3022. {
  3023. //If Mobility pack is not loaded we can't figure out if lan indeed present, so like
  3024. //everywhere else we just assume that lan is present
  3025. hr = S_OK;
  3026. }
  3027. break;
  3028. }
  3029. case CONNECTION_TYPE_INETSETTINGS:
  3030. default:
  3031. {
  3032. if (InternetGetConnectedStateExA(&dwFlags, szConnectionName, ARRAYSIZE(szConnectionName), 0))
  3033. hr = S_OK;
  3034. break;
  3035. }
  3036. }
  3037. return hr;
  3038. }
  3039. HRESULT CConnectionManager::GetServerName(IImnAccount *pAcct, LPSTR pServerName, DWORD size)
  3040. {
  3041. HRESULT hr = E_FAIL;
  3042. DWORD dwSrvrType;
  3043. ACCTTYPE accttype;
  3044. //This function will be called only for LAN accounts to avoid confusion with POP accounts having two servers
  3045. // an incoming and an outgoing.
  3046. if (SUCCEEDED(pAcct->GetAccountType(&accttype)))
  3047. {
  3048. switch (accttype)
  3049. {
  3050. case ACCT_MAIL:
  3051. dwSrvrType = AP_IMAP_SERVER;
  3052. break;
  3053. case ACCT_NEWS:
  3054. dwSrvrType = AP_NNTP_SERVER;
  3055. break;
  3056. case ACCT_DIR_SERV:
  3057. dwSrvrType = AP_LDAP_SERVER;
  3058. break;
  3059. default:
  3060. Assert(FALSE);
  3061. goto exit;
  3062. }
  3063. if ((hr = pAcct->GetPropSz(dwSrvrType, pServerName, size)) != S_OK)
  3064. {
  3065. //If the account type is MAIL, we try to get the name of POP server
  3066. //For POP accounts we just try to ping the POP3 server as in most of the cases
  3067. //POP server and SMTP servers are the same. Even if they are not, we assume that if
  3068. //one is reachable the connection is dialed and ISPs network is reachable and hence the other
  3069. //server is reachable too.
  3070. if (accttype == ACCT_MAIL)
  3071. {
  3072. hr = pAcct->GetPropSz(AP_POP3_SERVER, pServerName, size);
  3073. // look for an httpmail server
  3074. if (FAILED(hr))
  3075. hr = pAcct->GetPropSz(AP_HTTPMAIL_SERVER, pServerName, size);
  3076. }
  3077. }
  3078. }
  3079. exit:
  3080. return hr;
  3081. }
  3082. BOOLEAN CConnectionManager::IsSameDestination(LPSTR pszConnectionName, LPSTR pszServerName)
  3083. {
  3084. //We need to find an account with pszConnectionName as the connectoid and pszServerName
  3085. //Return TRUE if we find one FALSE otherwise
  3086. IImnAccount *pAcct;
  3087. BOOLEAN fret = FALSE;
  3088. if (g_pAcctMan && (g_pAcctMan->FindAccount(AP_RAS_CONNECTOID, pszConnectionName, &pAcct) == S_OK))
  3089. {
  3090. //Now check if its server name is what we want.
  3091. //Althoug findAccount finds first account that satisfies the searchdata, this should work fine for a
  3092. //typical OE user. Even if there are two accounts with same connectoids and different servers and if
  3093. //we miss to find the one we want,at the most we will be putting up a connect dialog.
  3094. char myServerName[MAX_PATH];
  3095. if (SUCCEEDED(GetServerName(pAcct, myServerName, sizeof(myServerName))))
  3096. {
  3097. if (lstrcmp(myServerName, pszServerName) == 0)
  3098. {
  3099. fret = TRUE;
  3100. }
  3101. }
  3102. }
  3103. return fret;
  3104. }
  3105. HRESULT CConnectionManager::VerifyMobilityPackLoaded()
  3106. {
  3107. HRESULT hr = REGDB_E_CLASSNOTREG;
  3108. uCLSSPEC classpec;
  3109. if (!m_fMobilityPackFailed)
  3110. {
  3111. HWND hwnd;
  3112. if (!m_hInstSensDll)
  3113. {
  3114. // figure out struct and flags
  3115. classpec.tyspec = TYSPEC_CLSID;
  3116. classpec.tagged_union.clsid = CLSID_MobilityFeature;
  3117. // call jit code
  3118. if (!g_pBrowser)
  3119. {
  3120. goto exit;
  3121. }
  3122. IOleWindow *pOleWnd;
  3123. if (FAILED(g_pBrowser->QueryInterface(IID_IAthenaBrowser, (LPVOID*)&pOleWnd)))
  3124. {
  3125. goto exit;
  3126. }
  3127. pOleWnd->GetWindow(&hwnd);
  3128. hr = FaultInIEFeature(hwnd, &classpec, NULL, FIEF_FLAG_PEEK);
  3129. pOleWnd->Release();
  3130. if(S_OK == hr)
  3131. {
  3132. // Mobile pack is installed
  3133. m_hInstSensDll = LoadLibrary(szSensApiDll);
  3134. if (m_hInstSensDll)
  3135. {
  3136. m_pIsDestinationReachable = (ISDESTINATIONREACHABLE)GetProcAddress(m_hInstSensDll, szIsDestinationReachable);
  3137. m_pIsNetworkAlive = (ISNETWORKALIVE)GetProcAddress(m_hInstSensDll, szIsNetworkAlive);
  3138. }
  3139. if (!m_hInstSensDll || !m_pIsDestinationReachable || !m_pIsNetworkAlive)
  3140. {
  3141. m_fMobilityPackFailed = TRUE;
  3142. }
  3143. else
  3144. {
  3145. m_fMobilityPackFailed = FALSE;
  3146. hr = S_OK;
  3147. }
  3148. }
  3149. }
  3150. else
  3151. hr = S_OK;
  3152. }
  3153. return hr;
  3154. exit:
  3155. m_fMobilityPackFailed = TRUE;
  3156. return hr;
  3157. }
  3158. void CConnectionManager::DoOfflineTransactions()
  3159. {
  3160. char szId[CCHMAX_ACCOUNT_NAME];
  3161. IImnEnumAccounts *pEnum;
  3162. HRESULT hr;
  3163. FOLDERID id, *pid;
  3164. ULONG iAcct, cAcct;
  3165. IImnAccount *pAccount;
  3166. DWORD dwConnection;
  3167. HWND hwnd;
  3168. DWORD cRecords;
  3169. pid = NULL;
  3170. iAcct = 0;
  3171. // If this is getting hit through a news article URL, we won't have a browser and
  3172. // should not play back.
  3173. if (!g_pBrowser || !g_pSync)
  3174. return;
  3175. // Get Record Count
  3176. g_pSync->GetRecordCount(&cRecords);
  3177. // sbailey: perf. fix. - prevent doing that expensive stuff below if there are no transactions.
  3178. if (0 == cRecords)
  3179. return;
  3180. hr = g_pAcctMan->Enumerate(SRV_NNTP | SRV_IMAP | SRV_HTTPMAIL, &pEnum);
  3181. if (SUCCEEDED(hr))
  3182. {
  3183. hr = pEnum->GetCount(&cAcct);
  3184. if (SUCCEEDED(hr) &&
  3185. cAcct > 0 &&
  3186. MemAlloc((void **)&pid, cAcct * sizeof(FOLDERID)))
  3187. {
  3188. while (SUCCEEDED(pEnum->GetNext(&pAccount)))
  3189. {
  3190. hr = pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dwConnection);
  3191. if (SUCCEEDED(hr))
  3192. {
  3193. hr = OEIsDestinationReachable(pAccount, dwConnection);
  3194. if (hr == S_OK)
  3195. {
  3196. hr = pAccount->GetPropSz(AP_ACCOUNT_ID, szId, ARRAYSIZE(szId));
  3197. if (SUCCEEDED(hr))
  3198. {
  3199. hr = g_pStore->FindServerId(szId, &id);
  3200. if (SUCCEEDED(hr))
  3201. {
  3202. pid[iAcct] = id;
  3203. iAcct++;
  3204. }
  3205. }
  3206. }
  3207. }
  3208. pAccount->Release();
  3209. }
  3210. }
  3211. pEnum->Release();
  3212. }
  3213. if (iAcct > 0)
  3214. {
  3215. g_pBrowser->GetWindow(&hwnd);
  3216. g_pBrowser->GetCurrentFolder(&id);
  3217. g_pSync->DoPlayback(hwnd, pid, iAcct, id);
  3218. }
  3219. if (pid != NULL)
  3220. MemFree(pid);
  3221. }
  3222. HRESULT CConnectionManager::ConnectUsingIESettings(HWND hwndParent, BOOL fShowUI)
  3223. {
  3224. TCHAR lpConnection[CCHMAX_CONNECTOID];
  3225. DWORD dwFlags = 0;
  3226. DWORD dwReturn;
  3227. HRESULT hr = E_FAIL;
  3228. if (InternetGetConnectedStateExA(&dwFlags, lpConnection, ARRAYSIZE(lpConnection), 0))
  3229. {
  3230. m_fTryAgain = FALSE;
  3231. return S_OK;
  3232. }
  3233. // Only one caller can be dialing the phone at a time.
  3234. if (WAIT_TIMEOUT == WaitForSingleObject(m_hMutexDial, 0))
  3235. {
  3236. return (HR_E_DIALING_INPROGRESS);
  3237. }
  3238. if (!!(dwFlags & INTERNET_CONNECTION_MODEM) && (*lpConnection))
  3239. {
  3240. if (!m_fDialerUI)
  3241. {
  3242. m_fDialerUI = TRUE;
  3243. //A DEF CONNECTOID IS SET. Dial that one
  3244. if (IsGlobalOffline())
  3245. {
  3246. if (fShowUI)
  3247. {
  3248. if (IDNO == AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsErrWorkingOffline),
  3249. 0, MB_YESNO | MB_ICONEXCLAMATION ))
  3250. {
  3251. hr = HR_E_OFFLINE;
  3252. goto DialExit;
  3253. }
  3254. else
  3255. g_pConMan->SetGlobalOffline(FALSE);
  3256. }
  3257. else
  3258. {
  3259. hr = HR_E_OFFLINE;
  3260. //m_fDialerUI = FALSE;
  3261. goto DialExit;
  3262. }
  3263. }
  3264. if ((hr = PromptCloseConnection(lpConnection, fShowUI, hwndParent)) != S_FALSE)
  3265. goto DialExit;
  3266. {
  3267. DWORD dwDialFlags = 0;
  3268. DWORD dwLanFlags = 0;
  3269. dwDialFlags = INTERNET_AUTODIAL_FORCE_ONLINE;
  3270. if (VerifyMobilityPackLoaded() == S_OK)
  3271. {
  3272. if (!IsNetworkAlive(&dwLanFlags) || (!(dwLanFlags & NETWORK_ALIVE_LAN)))
  3273. dwDialFlags |= INTERNET_DIAL_SHOW_OFFLINE;
  3274. }
  3275. dwReturn = InternetDialA(hwndParent, lpConnection, dwDialFlags,
  3276. &m_dwConnId, 0);
  3277. if (dwReturn == 0)
  3278. {
  3279. m_rConnInfo.fConnected = TRUE;
  3280. m_rConnInfo.fIStartedRas = TRUE;
  3281. m_rConnInfo.fAutoDial = FALSE;
  3282. m_rConnInfo.hRasConn = (HRASCONN)m_dwConnId;
  3283. StrCpyN(m_rConnInfo.szCurrentConnectionName, lpConnection, ARRAYSIZE(m_rConnInfo.szCurrentConnectionName));
  3284. SendAdvise(CONNNOTIFY_CONNECTED, NULL);
  3285. hr = S_OK;
  3286. }
  3287. else
  3288. {
  3289. if (dwReturn == ERROR_USER_DISCONNECTION)
  3290. {
  3291. hr = HR_E_USER_CANCEL_CONNECT;
  3292. if (!!(dwDialFlags & INTERNET_DIAL_SHOW_OFFLINE))
  3293. {
  3294. SetGlobalOffline(TRUE);
  3295. }
  3296. }
  3297. else
  3298. {
  3299. hr = E_FAIL;
  3300. DebugTrace("Error dialing: %d\n", GetLastError());
  3301. }
  3302. }
  3303. }
  3304. DialExit:
  3305. m_fDialerUI = FALSE;
  3306. }
  3307. else
  3308. {
  3309. hr = HR_E_USER_CANCEL_CONNECT;
  3310. }
  3311. }
  3312. else
  3313. {
  3314. if (!m_fTryAgain)
  3315. {
  3316. int err = (int) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddOfferOffline), hwndParent,
  3317. OfferOfflineDlgProc, (LPARAM)this);
  3318. if (err == -1)
  3319. {
  3320. DWORD dwerr = GetLastError();
  3321. hr = S_OK;
  3322. }
  3323. if (!IsGlobalOffline())
  3324. hr = S_OK;
  3325. else
  3326. hr = HR_E_OFFLINE;
  3327. }
  3328. else
  3329. hr = S_OK;
  3330. }
  3331. ReleaseMutex(m_hMutexDial);
  3332. return hr;
  3333. }
  3334. void CConnectionManager::SetTryAgain(BOOL bval)
  3335. {
  3336. m_fTryAgain = bval;
  3337. }
  3338. INT_PTR CALLBACK CConnectionManager::OfferOfflineDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  3339. {
  3340. BOOL retval = 1;
  3341. CConnectionManager *pThis = (CConnectionManager*)GetWndThisPtr(hwnd);
  3342. switch (uMsg)
  3343. {
  3344. case WM_INITDIALOG:
  3345. {
  3346. // Get lparam
  3347. pThis = (CConnectionManager *)lParam;
  3348. if (!pThis)
  3349. {
  3350. Assert (FALSE);
  3351. EndDialog(hwnd, E_FAIL);
  3352. goto exit;
  3353. }
  3354. // Save this pointer
  3355. SetWndThisPtr (hwnd, pThis);
  3356. break;
  3357. }
  3358. case WM_COMMAND:
  3359. {
  3360. switch(GET_WM_COMMAND_ID(wParam, lParam))
  3361. {
  3362. case IDWorkOffline:
  3363. pThis->SetGlobalOffline(TRUE, NULL);
  3364. break;
  3365. case IDTryAgain:
  3366. pThis->SetGlobalOffline(FALSE);
  3367. pThis->SetTryAgain(TRUE);
  3368. break;
  3369. }
  3370. EndDialog(hwnd, S_OK);
  3371. break;
  3372. }
  3373. case WM_CLOSE:
  3374. pThis->SetGlobalOffline(TRUE, NULL);
  3375. EndDialog(hwnd, S_OK);
  3376. break;
  3377. case WM_DESTROY:
  3378. SetWndThisPtr(hwnd, NULL);
  3379. break;
  3380. default:
  3381. retval = 0;
  3382. break;
  3383. }
  3384. exit:
  3385. return retval;
  3386. }
  3387. HRESULT CConnectionManager::PromptCloseConnection(LPTSTR pszRasConn, BOOL fShowUI, HWND hwndParent)
  3388. {
  3389. HRESULT hr = S_FALSE;
  3390. UINT uAnswer;
  3391. LPRASCONN pConnections = NULL;
  3392. ULONG cConnections = 0;
  3393. uAnswer = idrgDialNew;
  3394. // Make sure the RAS DLL is loaded before we try this
  3395. if (FAILED(VerifyRasLoaded()))
  3396. {
  3397. hr = HR_E_UNINITIALIZED;
  3398. goto exit;
  3399. }
  3400. StrCpyN(m_szConnectName, pszRasConn, ARRAYSIZE(m_szConnectName));
  3401. // RefreshConnInfo
  3402. CHECKHR(hr = RefreshConnInfo());
  3403. if (SUCCEEDED(EnumerateConnections(&pConnections, &cConnections)) && (cConnections > 0))
  3404. {
  3405. if (fShowUI)
  3406. uAnswer = PromptCloseConnection(hwndParent);
  3407. // The user canceled from the dialog. Therefore we give up.
  3408. if (IDCANCEL == uAnswer || IDNO == uAnswer)
  3409. {
  3410. hr = HR_E_USER_CANCEL_CONNECT;
  3411. goto exit;
  3412. }
  3413. // The user said they wanted to hang up and dial a new connection.
  3414. else if (idrgDialNew == uAnswer || IDYES == uAnswer)
  3415. {
  3416. Disconnect(hwndParent, fShowUI, TRUE, FALSE);
  3417. hr = S_FALSE;
  3418. goto exit;
  3419. }
  3420. // The user said to try to use the current connection.
  3421. else if (idrgUseCurrent == uAnswer)
  3422. {
  3423. //Save the conn info so we can return true for this connection in CanConnectActual
  3424. AddToConnList(pszRasConn);
  3425. hr = S_OK;
  3426. SendAdvise(CONNNOTIFY_CONNECTED, NULL);
  3427. goto exit;
  3428. }
  3429. }
  3430. else
  3431. {
  3432. Disconnect(NULL, FALSE, TRUE, FALSE);
  3433. hr = S_FALSE;
  3434. }
  3435. exit:
  3436. SafeMemFree(pConnections);
  3437. return hr;
  3438. }