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.

1992 lines
48 KiB

  1. #include "wininetp.h"
  2. #include "autodial.h"
  3. #include "rashelp.h"
  4. #define TAPI_CURRENT_VERSION 0x00010004
  5. #include <tapi.h>
  6. void PostString(HWND hDlg, LPWSTR pszString);
  7. void GetDialErrorString(DWORD dwError, LPWSTR pszBuffer, DWORD dwLength);
  8. void SetDialError(HWND hDlg, DWORD dwError);
  9. UINT_PTR
  10. SendDialmonMessage(
  11. UINT uMessage,
  12. BOOL fPost
  13. );
  14. // function prototype in inetcpl to launch connections tab
  15. typedef BOOL (WINAPI *LAUNCHCPL)(HWND);
  16. //
  17. // Globals
  18. //
  19. BOOL g_fRegisterWndProc = FALSE;
  20. #define REGSTR_DIAL_AUTOCONNECTW L"AutoConnect"
  21. typedef struct _tagRASCONNSTATEMAP {
  22. RASCONNSTATE rascs;
  23. UINT uResourceID;
  24. } RASCONNSTATEMAP;
  25. RASCONNSTATEMAP rgRasStates[] = {
  26. { RASCS_OpenPort, IDS_DIALING },
  27. { RASCS_AllDevicesConnected, IDS_CONNECTED },
  28. { RASCS_Authenticate, IDS_AUTHENTICATE },
  29. { RASCS_Disconnected, IDS_DISCONNECTED },
  30. { (RASCONNSTATE)0, 0 }
  31. };
  32. PROPMAP g_PropertyMap[] = {
  33. {DIALPROP_USERNAME, PropUserName },
  34. {DIALPROP_PASSWORD, PropPassword },
  35. {DIALPROP_DOMAIN, PropDomain },
  36. {DIALPROP_SAVEPASSWORD, PropSavePassword },
  37. {DIALPROP_PHONENUMBER, PropPhoneNumber },
  38. {DIALPROP_REDIALCOUNT, PropRedialCount },
  39. {DIALPROP_REDIALINTERVAL, PropRedialInterval },
  40. {DIALPROP_LASTERROR, PropLastError },
  41. {DIALPROP_RESOLVEDPHONE, PropResolvedPhone }
  42. };
  43. #define NUM_DIALPROPS (sizeof(g_PropertyMap) / sizeof(PROPMAP))
  44. //////////////////////////////////////////////////////////////////////////////
  45. //
  46. // CDialEngine implementation
  47. //
  48. //////////////////////////////////////////////////////////////////////////////
  49. CDialEngine::CDialEngine()
  50. {
  51. m_cRef = 0;
  52. m_pdes = NULL;
  53. m_rcs = RASCS_Disconnected;
  54. m_fCurrentlyDialing = FALSE;
  55. memset(&m_rdp, 0, sizeof(m_rdp));
  56. memset(&m_rcred, 0, sizeof(m_rcred));
  57. m_fPassword = FALSE;
  58. m_fSavePassword = FALSE;
  59. m_dwError = 0;
  60. // must be initialized to zero -- RasDial will fail (!) if this is anything
  61. // other than 0 when passed in to receive conn handle!!
  62. m_hConn = NULL;
  63. m_rdp.dwSize = sizeof(m_rdp);
  64. EnsureRasLoaded();
  65. if(FALSE == g_fRegisterWndProc)
  66. {
  67. // register window class for dialing engine
  68. WNDCLASS wc;
  69. memset(&wc, 0, sizeof(wc));
  70. wc.lpfnWndProc = CDialEngine::EngineWndProc;
  71. wc.hInstance = GlobalDllHandle;
  72. wc.lpszClassName = "DialEngine";
  73. RegisterClass(&wc);
  74. g_fRegisterWndProc = TRUE;
  75. }
  76. }
  77. CDialEngine::~CDialEngine()
  78. {
  79. SAFE_RELEASE(m_pdes);
  80. if(m_hwnd)
  81. {
  82. DestroyWindow(m_hwnd);
  83. }
  84. }
  85. //
  86. // IUnknown members
  87. //
  88. STDMETHODIMP_(ULONG) CDialEngine::AddRef(void)
  89. {
  90. return ++m_cRef;
  91. }
  92. STDMETHODIMP_(ULONG) CDialEngine::Release(void)
  93. {
  94. if( 0L != --m_cRef )
  95. return m_cRef;
  96. delete this;
  97. return 0L;
  98. }
  99. STDMETHODIMP CDialEngine::QueryInterface(REFIID riid, void ** ppv)
  100. {
  101. *ppv = NULL;
  102. // Validate requested interface
  103. if ((IID_IUnknown == riid) ||
  104. (IID_IDialEngine == riid))
  105. {
  106. *ppv = (IDialEngine *)this;
  107. }
  108. else
  109. {
  110. return E_NOINTERFACE;
  111. }
  112. // Addref through the interface
  113. ((LPUNKNOWN)*ppv)->AddRef();
  114. return S_OK;
  115. }
  116. //
  117. // IDialEngine members
  118. //
  119. STDMETHODIMP
  120. CDialEngine::Initialize(
  121. LPCWSTR pwzConnectoid,
  122. IDialEventSink *pIDES
  123. )
  124. {
  125. DEBUG_ENTER((DBG_DIALUP,
  126. Dword,
  127. "CDialEngine::Initialize",
  128. "%#x (%Q), %#x",
  129. pwzConnectoid,
  130. pwzConnectoid,
  131. pIDES
  132. ));
  133. // save off stuff
  134. m_pdes = pIDES;
  135. m_pdes->AddRef();
  136. StrCpyW(m_rdp.szEntryName, pwzConnectoid);
  137. m_rdp.dwSize = sizeof(m_rdp);
  138. // get stats from RAS
  139. RasEntryDialParamsHelp re;
  140. if(re.GetW(NULL, &m_rdp, &m_fPassword))
  141. {
  142. DEBUG_LEAVE(E_INVALIDARG);
  143. return E_INVALIDARG;
  144. }
  145. if(IsOS(OS_WHISTLERORGREATER))
  146. {
  147. // on whistler, use RasGetCredentials instead to preserve settings
  148. m_rcred.dwSize = sizeof(m_rcred);
  149. m_rcred.dwMask = RASCM_UserName | RASCM_Password;
  150. if(_RasGetCredentialsW(NULL, pwzConnectoid, &m_rcred))
  151. {
  152. DEBUG_LEAVE(E_INVALIDARG);
  153. return E_INVALIDARG;
  154. }
  155. DEBUG_PRINT(DIALUP, INFO, ("Name=<%ws>, PW=<%ws>, dwMask=%x\n", m_rcred.szUserName, m_rcred.szPassword, m_rcred.dwMask));
  156. m_fPassword = (m_rcred.dwMask & RASCM_Password) ? TRUE : FALSE;
  157. }
  158. // read redial properties
  159. GetRedialParameters((LPWSTR)pwzConnectoid, &m_dwTryTotal, &m_dwWaitTotal);
  160. m_dwTryCurrent = 0;
  161. m_dwWaitCurrent = 0;
  162. // register the ras message
  163. m_uRasMsg = RegisterWindowMessageA(RASDIALEVENT);
  164. if(0 == m_uRasMsg)
  165. m_uRasMsg = WM_RASDIALEVENT;
  166. // create the window to get ras callbacks.
  167. m_hwnd = CreateWindowA(
  168. "DialEngine",
  169. "DialEngine",
  170. WS_OVERLAPPED,
  171. CW_USEDEFAULT,
  172. CW_USEDEFAULT,
  173. CW_USEDEFAULT,
  174. CW_USEDEFAULT,
  175. NULL,
  176. NULL,
  177. GlobalDllHandle,
  178. NULL
  179. );
  180. if(NULL == m_hwnd)
  181. {
  182. DEBUG_LEAVE(E_OUTOFMEMORY);
  183. return E_OUTOFMEMORY;
  184. }
  185. // tell window our this pointer
  186. SendMessage(m_hwnd, WM_USER, 0, (LPARAM)this);
  187. // get current connected state from RAS
  188. UpdateRasState();
  189. DEBUG_LEAVE(S_OK);
  190. return S_OK;
  191. }
  192. STDMETHODIMP
  193. CDialEngine::GetProperty(
  194. LPCWSTR pwzProperty,
  195. LPWSTR pwzValue,
  196. DWORD dwBufSize
  197. )
  198. {
  199. DEBUG_ENTER((DBG_DIALUP,
  200. Dword,
  201. "CDialEngine::GetProperty",
  202. "%#x (%Q), %#x, %#x",
  203. pwzProperty,
  204. pwzProperty,
  205. pwzValue,
  206. dwBufSize
  207. ));
  208. HRESULT hr = E_INVALIDARG;
  209. WCHAR * pwzSrc = NULL;
  210. RasEntryPropHelp *pre = new RasEntryPropHelp;
  211. switch(PropertyToOrdinal(pwzProperty))
  212. {
  213. case PropUserName:
  214. pwzSrc = m_rdp.szUserName;
  215. break;
  216. case PropPassword:
  217. if(m_fPassword)
  218. {
  219. pwzSrc = m_rdp.szPassword;
  220. }
  221. else
  222. {
  223. hr = S_FALSE;
  224. }
  225. break;
  226. case PropDomain:
  227. pwzSrc = m_rdp.szDomain;
  228. break;
  229. case PropSavePassword:
  230. if(m_fSavePassword)
  231. {
  232. pwzSrc = L"TRUE";
  233. }
  234. else
  235. {
  236. pwzSrc = L"FALSE";
  237. }
  238. break;
  239. case PropResolvedPhone:
  240. if(ResolvePhoneNumber(pwzValue, dwBufSize))
  241. {
  242. hr = S_OK;
  243. break;
  244. }
  245. //
  246. // failed to get nicely formatted phone number, fall through to basic one
  247. //
  248. case PropPhoneNumber:
  249. if (pre == NULL)
  250. {
  251. hr = E_OUTOFMEMORY;
  252. }
  253. else
  254. {
  255. pre->GetW(m_rdp.szEntryName);
  256. pwzSrc = pre->GetPhoneNumberW();
  257. }
  258. break;
  259. case PropRedialCount:
  260. DEBUG_PRINT(DIALUP, INFO, ("Prop value = %d\n", m_dwTryTotal));
  261. wnsprintfW(pwzValue, dwBufSize, L"%d", m_dwTryTotal);
  262. hr = S_OK;
  263. break;
  264. case PropRedialInterval:
  265. DEBUG_PRINT(DIALUP, INFO, ("Prop value = %d\n", m_dwWaitTotal));
  266. wnsprintfW(pwzValue, dwBufSize, L"%d", m_dwWaitTotal);
  267. hr = S_OK;
  268. break;
  269. case PropLastError:
  270. GetDialErrorString(m_dwError, pwzValue, dwBufSize);
  271. DEBUG_PRINT(DIALUP, INFO, ("Prop value = %ws\n", pwzValue));
  272. hr = S_OK;
  273. break;
  274. }
  275. if(pwzSrc)
  276. {
  277. DEBUG_PRINT(DIALUP, INFO, ("Prop value = %ws\n", pwzSrc));
  278. StrCpyNW(pwzValue, pwzSrc, dwBufSize);
  279. hr = S_OK;
  280. }
  281. if (pre)
  282. delete pre;
  283. DEBUG_LEAVE(hr);
  284. return hr;
  285. }
  286. STDMETHODIMP
  287. CDialEngine::SetProperty(
  288. LPCWSTR pwzProperty,
  289. LPCWSTR pwzValue
  290. )
  291. {
  292. DEBUG_ENTER((DBG_DIALUP,
  293. Dword,
  294. "CDialEngine::SetProperty",
  295. "%#x (%Q), %#x (%Q)",
  296. pwzProperty,
  297. pwzProperty,
  298. pwzValue,
  299. pwzValue
  300. ));
  301. HRESULT hr = E_INVALIDARG;
  302. WCHAR * pwzDest = NULL;
  303. DWORD dwMaxLength = 0;
  304. WCHAR wcNull = 0;
  305. // treat NULL values as emtpy values
  306. if(NULL == pwzValue)
  307. {
  308. pwzValue = &wcNull;
  309. }
  310. switch(PropertyToOrdinal(pwzProperty))
  311. {
  312. case PropUserName:
  313. pwzDest = m_rdp.szUserName;
  314. dwMaxLength = UNLEN;
  315. if(IsOS(OS_WHISTLERORGREATER))
  316. {
  317. StrCpyNW(m_rcred.szUserName, pwzValue, dwMaxLength);
  318. }
  319. break;
  320. case PropPassword:
  321. pwzDest = m_rdp.szPassword;
  322. dwMaxLength = PWLEN;
  323. m_fPassword = TRUE;
  324. if(IsOS(OS_WHISTLERORGREATER))
  325. {
  326. StrCpyNW(m_rcred.szPassword, pwzValue, dwMaxLength);
  327. }
  328. break;
  329. case PropDomain:
  330. pwzDest = m_rdp.szDomain;
  331. dwMaxLength = DNLEN;
  332. break;
  333. case PropSavePassword:
  334. if(!StrCmpIW(pwzValue, L"TRUE"))
  335. {
  336. m_fSavePassword = TRUE;
  337. }
  338. else
  339. {
  340. m_fSavePassword = FALSE;
  341. }
  342. if(FALSE == m_fSavePassword)
  343. {
  344. m_fPassword = FALSE;
  345. }
  346. hr = S_OK;
  347. break;
  348. case PropPhoneNumber:
  349. pwzDest = m_rdp.szPhoneNumber;
  350. dwMaxLength = RAS_MaxPhoneNumber;
  351. break;
  352. case PropRedialCount:
  353. m_dwTryTotal = StrToIntW(pwzValue);
  354. if(0 == m_dwTryTotal)
  355. {
  356. m_dwTryTotal = DEFAULT_DIAL_ATTEMPTS;
  357. }
  358. hr = S_OK;
  359. break;
  360. case PropRedialInterval:
  361. m_dwWaitTotal = StrToIntW(pwzValue);
  362. if(0 == m_dwWaitTotal)
  363. {
  364. m_dwWaitTotal = DEFAULT_DIAL_INTERVAL;
  365. }
  366. hr = S_OK;
  367. break;
  368. default:
  369. hr = E_UNEXPECTED;
  370. break;
  371. }
  372. if(pwzDest)
  373. {
  374. StrCpyNW(pwzDest, pwzValue, dwMaxLength);
  375. hr = S_OK;
  376. }
  377. DEBUG_LEAVE(hr);
  378. return hr;
  379. }
  380. STDMETHODIMP
  381. CDialEngine::StartConnection()
  382. {
  383. DEBUG_ENTER((DBG_DIALUP,
  384. Dword,
  385. "CDialEngine::StartConnection",
  386. NULL
  387. ));
  388. m_dwTryCurrent++;
  389. m_pdes->OnEvent(DIALENG_RedialAttempt, m_dwTryCurrent);
  390. RasDialHelp RasDial(NULL, NULL, &m_rdp, 0xFFFFFFFF, m_hwnd, &m_hConn);
  391. if(0 != RasDial.GetError()) {
  392. // Clean up since RAS may return a connection anyway...
  393. CleanConnection();
  394. m_dwError = ERROR_NO_CONNECTION;
  395. EndOfOperation();
  396. DEBUG_PRINT(DIALUP, INFO, ("Bailing - RasDial error\n"));
  397. DEBUG_LEAVE(E_FAIL);
  398. return E_FAIL;
  399. }
  400. DEBUG_LEAVE(S_OK);
  401. return S_OK;
  402. }
  403. STDMETHODIMP
  404. CDialEngine::Dial()
  405. {
  406. DEBUG_ENTER((DBG_DIALUP,
  407. Dword,
  408. "CDialEngine::Dial",
  409. NULL
  410. ));
  411. HRESULT hr;
  412. if(m_fCurrentlyDialing)
  413. {
  414. DEBUG_PRINT(DIALUP, INFO, ("Bailing - m_fCurentlyDialing\n"));
  415. DEBUG_LEAVE(S_FALSE);
  416. return S_FALSE;
  417. }
  418. // find out if our connection state has changed in the mean time
  419. UpdateRasState();
  420. // we have begun...
  421. m_fCurrentlyDialing = TRUE;
  422. if(m_rcs == RASCS_Connected)
  423. {
  424. DEBUG_PRINT(DIALUP, INFO, ("Bailing - already connected\n"));
  425. m_dwError = ERROR_SUCCESS;
  426. EndOfOperation();
  427. DEBUG_LEAVE(S_FALSE);
  428. return S_FALSE;
  429. }
  430. m_dwError = 0;
  431. m_dwTryCurrent = 0;
  432. hr = StartConnection();
  433. DEBUG_LEAVE(hr);
  434. return hr;
  435. }
  436. STDMETHODIMP
  437. CDialEngine::CleanConnection()
  438. {
  439. DEBUG_ENTER((DBG_DIALUP,
  440. Dword,
  441. "CDialEngine::CleanConnection",
  442. NULL
  443. ));
  444. HRESULT hr = S_FALSE;
  445. // make sure we see if we've connected in the mean time
  446. UpdateRasState();
  447. DEBUG_PRINT(DIALUP, INFO, ("m_hConn=%x\n", m_hConn));
  448. // hang up connection if we got one
  449. if(m_hConn)
  450. {
  451. HRASCONN hConn = m_hConn;
  452. m_hConn = NULL;
  453. _RasHangUp(hConn);
  454. hr = S_OK;
  455. }
  456. DEBUG_LEAVE(hr);
  457. return hr;
  458. }
  459. STDMETHODIMP
  460. CDialEngine::HangUp()
  461. {
  462. DEBUG_ENTER((DBG_DIALUP,
  463. Dword,
  464. "CDialEngine::HangUp",
  465. NULL
  466. ));
  467. HRESULT hr;
  468. // hang up or abort any pending dials
  469. hr = CleanConnection();
  470. // make sure no pending timers
  471. if(m_uTimerId)
  472. {
  473. KillTimer(m_hwnd, m_uTimerId);
  474. m_uTimerId = 0;
  475. }
  476. // calling hangup causes ras events to end
  477. if(0 == m_dwError)
  478. {
  479. m_dwError = ERROR_USER_DISCONNECTION;
  480. }
  481. EndOfOperation();
  482. DEBUG_LEAVE(hr);
  483. return hr;
  484. }
  485. STDMETHODIMP
  486. CDialEngine::GetConnectedState(
  487. DWORD *pdwState)
  488. {
  489. DEBUG_ENTER((DBG_DIALUP,
  490. Dword,
  491. "CDialEngine::GetConnectedState",
  492. NULL
  493. ));
  494. *pdwState = MapRCS(m_rcs);
  495. DEBUG_LEAVE(S_OK);
  496. return S_OK;
  497. }
  498. STDMETHODIMP
  499. CDialEngine::GetConnectHandle(
  500. DWORD_PTR *pdwHandle
  501. )
  502. {
  503. DEBUG_ENTER((DBG_DIALUP,
  504. Dword,
  505. "CDialEngine::GetConnectHandle",
  506. NULL
  507. ));
  508. if(RASCS_Connected == m_rcs)
  509. {
  510. *pdwHandle = (DWORD_PTR)m_hConn;
  511. DEBUG_LEAVE(S_OK);
  512. return S_OK;
  513. }
  514. else
  515. {
  516. *pdwHandle = 0;
  517. DEBUG_LEAVE(S_FALSE);
  518. return S_FALSE;
  519. }
  520. }
  521. //
  522. // private members
  523. //
  524. LONG_PTR CALLBACK
  525. CDialEngine::EngineWndProc(
  526. HWND hwnd,
  527. UINT uMsg,
  528. WPARAM wParam,
  529. LPARAM lParam
  530. )
  531. {
  532. DEBUG_ENTER((DBG_DIALUP,
  533. Dword,
  534. "CDialEngine::EngineWndProc",
  535. "%#x, %#x, %#x, %#x",
  536. hwnd,
  537. uMsg,
  538. wParam,
  539. lParam
  540. ));
  541. CDialEngine * peng = (CDialEngine *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  542. if(uMsg == WM_USER)
  543. {
  544. peng = (CDialEngine *)lParam;
  545. SetWindowLongPtr(hwnd, GWLP_USERDATA, (DWORD_PTR)peng);
  546. }
  547. else if(peng && uMsg == peng->m_uRasMsg)
  548. {
  549. peng->OnRasEvent((RASCONNSTATE)wParam, (DWORD)lParam);
  550. }
  551. else if(peng && uMsg == WM_TIMER)
  552. {
  553. peng->OnTimer();
  554. }
  555. DEBUG_LEAVE(0);
  556. return DefWindowProc(hwnd, uMsg, wParam, lParam);
  557. }
  558. VOID
  559. CDialEngine::OnTimer()
  560. {
  561. DEBUG_ENTER((DBG_DIALUP,
  562. None,
  563. "CDialEngine::OnTimer",
  564. NULL
  565. ));
  566. if(0 == m_dwError)
  567. {
  568. m_dwWaitCurrent--;
  569. if(0 == m_dwWaitCurrent)
  570. {
  571. // kick off dial
  572. KillTimer(m_hwnd, m_uTimerId);
  573. m_uTimerId = 0;
  574. StartConnection();
  575. }
  576. else
  577. {
  578. // update sink
  579. // m_pdes->OnEvent(DIALENG_RedialWait, m_dwWaitCurrent);
  580. }
  581. }
  582. DEBUG_LEAVE(0);
  583. }
  584. VOID
  585. CDialEngine::OnRasEvent(
  586. RASCONNSTATE rcs,
  587. DWORD dwError
  588. )
  589. {
  590. DEBUG_ENTER((DBG_DIALUP,
  591. None,
  592. "CDialEngine::OnRasEvent",
  593. "%#x, %#x",
  594. (DWORD)rcs,
  595. dwError
  596. ));
  597. // save rasconnstate
  598. m_rcs = rcs;
  599. // forward event to UI object
  600. m_pdes->OnEvent(MapRCS(rcs), dwError);
  601. // handle the dial state
  602. if(dwError != SUCCESS) {
  603. // win95 returns this error if authentication failed.
  604. if(ERROR_UNKNOWN == dwError)
  605. dwError = ERROR_AUTHENTICATION_FAILURE;
  606. // save error if we don't already have one
  607. if(0 == m_dwError && dwError)
  608. {
  609. m_dwError = dwError;
  610. }
  611. // clean up connection
  612. CleanConnection();
  613. switch(dwError) {
  614. case ERROR_AUTHENTICATION_FAILURE:
  615. memset(m_rdp.szPassword, 0, ARRAYSIZE(m_rdp.szPassword));
  616. EndOfOperation();
  617. break;
  618. case ERROR_USER_DISCONNECTION:
  619. // we hit cancel and called RasHangUp. Nothing to do here -
  620. // cancel code has cleaned up as necessary.
  621. EndOfOperation();
  622. break;
  623. case ERROR_LINE_BUSY:
  624. case ERROR_NO_ANSWER:
  625. case ERROR_NO_CARRIER:
  626. if(m_dwTryCurrent < m_dwTryTotal)
  627. {
  628. m_dwError = 0;
  629. m_dwWaitCurrent = m_dwWaitTotal;
  630. m_uTimerId = SetTimer(m_hwnd, 1, 1000, NULL);
  631. m_pdes->OnEvent(DIALENG_RedialWait, m_dwWaitCurrent);
  632. break;
  633. }
  634. // fall through
  635. default:
  636. EndOfOperation();
  637. }
  638. } else {
  639. // we're getting status
  640. if(rcs == RASCS_Connected)
  641. {
  642. // we're done
  643. m_dwError = ERROR_SUCCESS;
  644. EndOfOperation();
  645. DEBUG_PRINT(DIALUP, INFO, ("Connected: m_fPassword=%B, m_fSavePassword=%B\n", m_fPassword, m_fSavePassword));
  646. if(IsOS(OS_WHISTLERORGREATER))
  647. {
  648. // delete/write/leave alone semantics
  649. //
  650. // m_fPassword m_fSavePassword result
  651. // T T Write password
  652. // F F Delete password
  653. // T F Leave password alone
  654. // F T Never happens
  655. if(!m_fPassword && !m_fSavePassword)
  656. {
  657. // delete case, only want password mask
  658. m_rcred.dwMask = 0;
  659. }
  660. if(m_fPassword == m_fSavePassword)
  661. {
  662. // write or delete case
  663. // always need password flag
  664. m_rcred.dwMask |= RASCM_Password;
  665. // write or delete, depend on m_fSavePassword
  666. DEBUG_PRINT(DIALUP, INFO, ("Name=<%ws>, PW=<%ws>, dwMask=%x\n", m_rcred.szUserName, m_rcred.szPassword, m_rcred.dwMask));
  667. _RasSetCredentialsW(NULL, m_rdp.szEntryName, &m_rcred, !m_fSavePassword);
  668. }
  669. }
  670. else
  671. {
  672. if(m_fPassword == m_fSavePassword)
  673. {
  674. // save or delete password
  675. RasEntryDialParamsHelp re;
  676. re.SetW(NULL, &m_rdp, !m_fSavePassword);
  677. }
  678. }
  679. // inform dialmon that we've dialed
  680. SendDialmonMessage(WM_SET_CONNECTOID_NAME, TRUE);
  681. }
  682. }
  683. DEBUG_LEAVE(0);
  684. }
  685. DWORD
  686. CDialEngine::MapRCS(RASCONNSTATE rcs)
  687. {
  688. DEBUG_ENTER((DBG_DIALUP,
  689. Dword,
  690. "CDialEngine::MapRCS",
  691. "%#x",
  692. (DWORD)rcs
  693. ));
  694. DEBUG_LEAVE((DWORD)rcs);
  695. return (DWORD)rcs;
  696. }
  697. DIALPROP
  698. CDialEngine::PropertyToOrdinal(LPCWSTR pwzProperty)
  699. {
  700. long i;
  701. for(i=0; i<NUM_DIALPROPS; i++)
  702. {
  703. if(!StrCmpIW(g_PropertyMap[i].pwzProperty, pwzProperty))
  704. {
  705. return g_PropertyMap[i].Prop;
  706. }
  707. }
  708. return PropInvalid;
  709. }
  710. VOID
  711. CDialEngine::UpdateRasState()
  712. {
  713. DEBUG_ENTER((DBG_DIALUP,
  714. None,
  715. "CDialEngine::UpdateRasState",
  716. NULL
  717. ));
  718. DEBUG_PRINT(DIALUP, INFO, ("m_fCurrentlyDialing = %B\n", m_fCurrentlyDialing));
  719. //
  720. // only do this if not dialing. If we are, OnRasEvent will update
  721. // state appropriately.
  722. //
  723. if(FALSE == m_fCurrentlyDialing)
  724. {
  725. RasEnumConnHelp re;
  726. re.Enum();
  727. DEBUG_PRINT(DIALUP, INFO, ("Checking for connections\n"));
  728. // set state to disconnected and try to find a connection
  729. m_rcs = RASCS_Disconnected;
  730. if(0 == re.GetError())
  731. {
  732. DWORD dwCount;
  733. for(dwCount = 0; dwCount < re.GetConnectionsCount(); dwCount++)
  734. {
  735. if(0 == StrCmpW(re.GetEntryW(dwCount), m_rdp.szEntryName))
  736. {
  737. DEBUG_PRINT(DIALUP, INFO, ("Found connection\n"));
  738. m_hConn = re.GetHandle(dwCount);
  739. m_rcs = RASCS_Connected;
  740. }
  741. }
  742. }
  743. }
  744. DEBUG_LEAVE(0);
  745. }
  746. VOID
  747. CDialEngine::EndOfOperation()
  748. {
  749. DEBUG_ENTER((DBG_DIALUP,
  750. None,
  751. "CDialEngine::EndOfOperation",
  752. NULL
  753. ));
  754. if(m_fCurrentlyDialing)
  755. {
  756. // called when a dialing operation is done
  757. m_fCurrentlyDialing = FALSE;
  758. m_dwTryCurrent = 0;
  759. // notify sink that no more events are forthcoming
  760. m_pdes->OnEvent(DIALENG_OperationComplete, m_dwError);
  761. }
  762. DEBUG_LEAVE(0);
  763. }
  764. VOID FAR CALLBACK TapiCallback(
  765. DWORD hDevice,
  766. DWORD dwMsg,
  767. DWORD_PTR dwCallbackInstance,
  768. DWORD_PTR dwParam1,
  769. DWORD_PTR dwParam2,
  770. DWORD_PTR dwParam3
  771. )
  772. {
  773. }
  774. BOOL
  775. CDialEngine::ResolvePhoneNumber(LPWSTR pwzBuffer, DWORD dwLen)
  776. {
  777. char *pszTemp = NULL;
  778. WCHAR szCanonical[128];
  779. CHAR szAnsiCanonical[128];
  780. CHAR *pszResolved;
  781. long lErr, i;
  782. BOOL fResult = FALSE;
  783. RasEntryPropHelp *pre = new RasEntryPropHelp;
  784. if (pre == NULL)
  785. {
  786. goto Cleanup;
  787. }
  788. pszTemp = (char *) ALLOCATE_FIXED_MEMORY(4096);
  789. if (pszTemp == NULL)
  790. {
  791. goto Cleanup;
  792. }
  793. // look up RAS entry
  794. pre->GetW(m_rdp.szEntryName);
  795. if(pre->GetError())
  796. {
  797. goto Cleanup;
  798. }
  799. if(pre->GetOptions() & RASEO_UseCountryAndAreaCodes)
  800. {
  801. PWSTR pszAreaCode = pre->GetAreaCodeW();
  802. HLINEAPP hApp;
  803. DWORD dwNumDevs;
  804. // make TAPI canonical phone number
  805. wnsprintfW(szCanonical, 128, L"+%d (%ws) %ws", pre->GetCountryCode(), pszAreaCode ? pszAreaCode : L"", pre->GetPhoneNumberW());
  806. // ask TAPI to translate it
  807. LPLINETRANSLATEOUTPUT lpOut = (LPLINETRANSLATEOUTPUT)pszTemp;
  808. lpOut->dwTotalSize = 4096;
  809. lErr = lineInitialize(&hApp, GlobalDllHandle, TapiCallback, "Wininet", &dwNumDevs);
  810. if(lErr)
  811. {
  812. goto Cleanup;
  813. }
  814. WideCharToMultiByte(CP_ACP, 0, szCanonical, -1, szAnsiCanonical, 128, NULL, NULL);
  815. lErr = lineTranslateAddress(hApp, 0, TAPI_CURRENT_VERSION, szAnsiCanonical, 0, 0, lpOut);
  816. if(lErr)
  817. {
  818. goto Cleanup;
  819. }
  820. pszResolved = (CHAR *)((char *)lpOut + lpOut->dwDisplayableStringOffset);
  821. i = MultiByteToWideChar(CP_ACP, 0, pszResolved, -1, pwzBuffer, dwLen);
  822. if(0 == i)
  823. {
  824. pwzBuffer[dwLen] = 0; // truncated - null terminate
  825. }
  826. }
  827. else
  828. {
  829. // TAPI resolution not turned on, just return straight phone number
  830. StrCpyNW(pwzBuffer, pre->GetPhoneNumberW(), dwLen);
  831. }
  832. fResult = TRUE;
  833. Cleanup:
  834. if (pre)
  835. delete pre;
  836. if (pszTemp)
  837. FREE_MEMORY(pszTemp);
  838. return fResult;
  839. }
  840. //////////////////////////////////////////////////////////////////////////////
  841. //
  842. // CDialUI implementation
  843. //
  844. //////////////////////////////////////////////////////////////////////////////
  845. CDialUI::CDialUI(HWND hwndParent)
  846. {
  847. m_cRef = 0;
  848. m_pEng = NULL;
  849. m_pdb = NULL;
  850. m_State = UISTATE_Interactive;
  851. m_fOfflineSemantics = FALSE;
  852. m_fSavePassword = FALSE;
  853. m_fPasswordChanged = FALSE;
  854. m_fAutoConnect = FALSE;
  855. m_fCDH = FALSE;
  856. m_fDialedCDH = FALSE;
  857. memset(&m_cdh, 0, sizeof(m_cdh));
  858. if(hwndParent)
  859. {
  860. m_hwndParent = hwndParent;
  861. }
  862. else
  863. {
  864. m_hwndParent = GetDesktopWindow();
  865. }
  866. }
  867. CDialUI::~CDialUI()
  868. {
  869. SAFE_RELEASE(m_pEng);
  870. SAFE_RELEASE(m_pdb);
  871. }
  872. //
  873. // IUnknown members
  874. //
  875. STDMETHODIMP_(ULONG) CDialUI::AddRef(void)
  876. {
  877. return ++m_cRef;
  878. }
  879. STDMETHODIMP_(ULONG) CDialUI::Release(void)
  880. {
  881. if( 0L != --m_cRef )
  882. return m_cRef;
  883. delete this;
  884. return 0L;
  885. }
  886. STDMETHODIMP CDialUI::QueryInterface(REFIID riid, void ** ppv)
  887. {
  888. *ppv=NULL;
  889. // Validate requested interface
  890. if ((IID_IUnknown == riid) ||
  891. (IID_IDialEventSink == riid))
  892. {
  893. *ppv = (IDialEventSink *)this;
  894. }
  895. else
  896. {
  897. return E_NOINTERFACE;
  898. }
  899. // Addref through the interface
  900. ((LPUNKNOWN)*ppv)->AddRef();
  901. return S_OK;
  902. }
  903. //
  904. // IDialUI members
  905. //
  906. DWORD
  907. CDialUI::StartDial(
  908. IN DIALSTATE *pDial,
  909. IN DWORD dwFlags
  910. )
  911. //
  912. //
  913. {
  914. DEBUG_ENTER((DBG_DIALUP,
  915. Dword,
  916. "CDialUI::StartDial",
  917. "%#x, %#x",
  918. pDial,
  919. dwFlags
  920. ));
  921. DWORD dwSize, dwTemp, dwType;
  922. WCHAR szKey[MAX_PATH];
  923. // save passed info
  924. m_dwFlags = dwFlags;
  925. m_pDial = pDial;
  926. m_pDial->dwResult = 0;
  927. // check for connect automatically
  928. dwSize = sizeof(DWORD);
  929. dwTemp = 0;
  930. GetConnKeyW(pDial->params.szEntryName, szKey, ARRAYSIZE(szKey));
  931. if(0 == (dwFlags & INTERNET_DIAL_FORCE_PROMPT) &&
  932. ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szKey,
  933. REGSTR_DIAL_AUTOCONNECTW, &dwType, &dwTemp, &dwSize) && dwTemp)
  934. {
  935. m_fAutoConnect = TRUE;
  936. }
  937. //
  938. // Get some UI going
  939. //
  940. ULONG_PTR uCookie = 0;
  941. SHActivateContext(&uCookie);
  942. if(-1 == DialogBoxParamWrapW(GlobalDllHandle, MAKEINTRESOURCEW(IDD_CONNECT_TO),
  943. m_hwndParent, CDialUI::DialogProc, (LPARAM)this))
  944. {
  945. // couldn't create dialog for some reason - no mem?
  946. m_pDial->dwResult = ERROR_OUTOFMEMORY;
  947. }
  948. if (uCookie)
  949. {
  950. SHDeactivateContext(uCookie);
  951. }
  952. // prop odds and ends back to data so caller is happy
  953. if(!m_fCDH)
  954. {
  955. m_pDial->dwFlags = 0;
  956. if(m_fAutoConnect)
  957. {
  958. m_pDial->dwFlags |= CI_AUTO_CONNECT;
  959. }
  960. if(m_pEng)
  961. {
  962. m_pEng->GetConnectHandle((DWORD_PTR *)&m_pDial->hConn);
  963. }
  964. }
  965. else
  966. {
  967. m_pDial->hConn = (HRASCONN)CDH_HCONN;
  968. }
  969. //
  970. // Clean up
  971. //
  972. SAFE_RELEASE(m_pEng);
  973. DEBUG_LEAVE(m_pDial->dwResult);
  974. return m_pDial->dwResult;
  975. }
  976. STDMETHODIMP
  977. CDialUI::OnEvent(
  978. DWORD dwEvent,
  979. DWORD dwStatus
  980. )
  981. {
  982. DEBUG_ENTER((DBG_DIALUP,
  983. Dword,
  984. "CDialUI::OnEvent",
  985. "%#x, %#x",
  986. dwEvent,
  987. dwStatus
  988. ));
  989. WCHAR pszText[128], pszTemplate[128];
  990. INT idRes;
  991. // find string for this state (if any)
  992. for (int nIndex = 0; rgRasStates[nIndex].uResourceID != 0; nIndex++)
  993. {
  994. if ((RASCONNSTATE)dwEvent == rgRasStates[nIndex].rascs) {
  995. LoadStringWrapW(GlobalDllHandle, rgRasStates[nIndex].uResourceID,
  996. pszText, 128);
  997. PostString(m_hwnd, pszText);
  998. }
  999. }
  1000. switch(dwEvent)
  1001. {
  1002. case DIALENG_RedialAttempt:
  1003. case DIALENG_RedialWait:
  1004. idRes = IDS_REDIAL_ATTEMPT;
  1005. if(dwEvent == DIALENG_RedialWait)
  1006. {
  1007. idRes = IDS_REDIAL_WAIT;
  1008. }
  1009. LoadStringWrapW(GlobalDllHandle, idRes, pszTemplate, 128);
  1010. wnsprintfW(pszText, ARRAYSIZE(pszText), pszTemplate, dwStatus);
  1011. PostString(m_hwnd, pszText);
  1012. break;
  1013. case DIALENG_OperationComplete:
  1014. m_pDial->dwResult = dwStatus;
  1015. if(0 == dwStatus || m_State == UISTATE_Unattended)
  1016. {
  1017. EndDialog(m_hwnd, 0);
  1018. }
  1019. else
  1020. {
  1021. if(dwStatus)
  1022. {
  1023. // get an error - display it
  1024. SetDialError(m_hwnd, dwStatus);
  1025. }
  1026. m_State = UISTATE_Interactive;
  1027. FixUIComponents();
  1028. }
  1029. break;
  1030. }
  1031. DEBUG_LEAVE(0);
  1032. return NOERROR;
  1033. }
  1034. VOID
  1035. CDialUI::FixUIComponents(
  1036. )
  1037. {
  1038. DEBUG_ENTER((DBG_DIALUP,
  1039. None,
  1040. "CDialUI::FixUIComponents",
  1041. NULL
  1042. ));
  1043. WCHAR pszTemp[64];
  1044. int i;
  1045. BOOL fActive = TRUE, fCanSave, fCDHActive = TRUE;
  1046. TCHAR szUser[UNLEN+1];
  1047. DWORD dwLen = UNLEN;
  1048. UINT uIDs[] = {IDC_CONN_TXT, IDC_CONN_LIST, ID_CONNECT, IDC_SETTINGS};
  1049. UINT uCDHIDs[] = {IDC_NAME_TXT, IDC_USER_NAME, IDC_PASSWORD_TXT, IDC_PASSWORD};
  1050. #define NUM_IDS (sizeof(uIDs) / sizeof(UINT))
  1051. #define NUM_CDH_IDS (sizeof(uCDHIDs) / sizeof(UINT))
  1052. //
  1053. // fix cancel button
  1054. //
  1055. if(UISTATE_Dialing == m_State || UISTATE_Unattended == m_State || FALSE == m_fOfflineSemantics)
  1056. {
  1057. i = IDS_CANCEL;
  1058. }
  1059. else
  1060. {
  1061. i = IDS_WORK_OFFLINE;
  1062. }
  1063. LoadStringWrapW(GlobalDllHandle, i, pszTemp, MAX_PATH);
  1064. SetWindowTextWrapW(GetDlgItem(m_hwnd, IDCANCEL), pszTemp);
  1065. //
  1066. // Fix focus
  1067. //
  1068. if(UISTATE_Dialing == m_State || UISTATE_Unattended == m_State)
  1069. {
  1070. SetFocus(GetDlgItem(m_hwnd, IDCANCEL));
  1071. fActive = FALSE;
  1072. }
  1073. //
  1074. // Grey out appropriate stuff
  1075. //
  1076. for(i=0; i<NUM_IDS; i++)
  1077. {
  1078. EnableWindow(GetDlgItem(m_hwnd, uIDs[i]), fActive);
  1079. }
  1080. for(i=0; i<NUM_CDH_IDS; i++)
  1081. {
  1082. EnableWindow(GetDlgItem(m_hwnd, uCDHIDs[i]), fActive && !m_fCDH);
  1083. }
  1084. //
  1085. // fix password and auto check boxes
  1086. //
  1087. fCanSave = (0 != GetUserName(szUser, &dwLen));
  1088. EnableWindow(GetDlgItem(m_hwnd, IDC_SAVE_PASSWORD), fActive && fCanSave);
  1089. //
  1090. // special case - Autoconnect is disabled if save password not checked
  1091. // or password cannot be saved
  1092. //
  1093. EnableWindow(
  1094. GetDlgItem(m_hwnd, IDC_AUTOCONNECT),
  1095. fCanSave && fActive && IsDlgButtonChecked(m_hwnd, IDC_SAVE_PASSWORD));
  1096. DEBUG_LEAVE(0);
  1097. }
  1098. //
  1099. // Other members
  1100. //
  1101. VOID
  1102. CDialUI::OnInitDialog(
  1103. )
  1104. {
  1105. DEBUG_ENTER((DBG_DIALUP,
  1106. None,
  1107. "CDialUI::OnInitDialog",
  1108. NULL
  1109. ));
  1110. TCHAR szUser[UNLEN+1];
  1111. DWORD dwLen = UNLEN;
  1112. BOOL fCanSave;
  1113. // Fill in the connectoid list
  1114. EnumerateConnectoids();
  1115. // Get the engine for this connectoid and get relevant properties
  1116. GetProps();
  1117. // check flags for unattended, etc.
  1118. if(GlobalIsProcessExplorer || (m_dwFlags & INTERNET_DIAL_SHOW_OFFLINE))
  1119. {
  1120. m_fOfflineSemantics = TRUE;
  1121. }
  1122. if(m_dwFlags & (INTERNET_DIAL_UNATTENDED|INTERNET_AUTODIAL_FORCE_UNATTENDED))
  1123. {
  1124. // want unattended dial.. do it if we can, else bail out
  1125. m_State = UISTATE_Unattended;
  1126. if(m_pEng)
  1127. {
  1128. m_pEng->Dial();
  1129. }
  1130. else
  1131. {
  1132. OnCancel();
  1133. }
  1134. }
  1135. // make sure cancel button is correct
  1136. FixUIComponents();
  1137. // Handle autoconnect
  1138. if(m_fAutoConnect)
  1139. {
  1140. CheckDlgButton(m_hwnd, IDC_AUTOCONNECT, BST_CHECKED);
  1141. OnConnect();
  1142. }
  1143. DEBUG_LEAVE(0);
  1144. }
  1145. VOID
  1146. CDialUI::OnSelChange()
  1147. {
  1148. DEBUG_ENTER((DBG_DIALUP,
  1149. None,
  1150. "CDialUI::OnSelChange",
  1151. NULL
  1152. ));
  1153. int iSel;
  1154. HWND hwndList = GetDlgItem(m_hwnd, IDC_CONN_LIST);
  1155. // yank out new name
  1156. iSel = ComboBox_GetCurSel(hwndList);
  1157. if(CB_ERR == iSel)
  1158. iSel = 0;
  1159. SendMessageWrapW(hwndList, CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)m_pDial->params.szEntryName);
  1160. // Fill in props for new connection (will get new engine)
  1161. GetProps();
  1162. DEBUG_LEAVE(0);
  1163. }
  1164. VOID
  1165. CDialUI::OnConnect(
  1166. )
  1167. {
  1168. DEBUG_ENTER((DBG_DIALUP,
  1169. None,
  1170. "CDialUI::OnConnect",
  1171. NULL
  1172. ));
  1173. // If we have a CDH, call it
  1174. if(m_fCDH)
  1175. {
  1176. if(!CallCDH(m_hwnd, m_pDial->params.szEntryName, &m_cdh, 0, &(m_pDial->dwResult)))
  1177. {
  1178. // custom dial handler failed to handle dial request, bail out
  1179. m_pDial->dwResult = ERROR_USER_DISCONNECTION;
  1180. }
  1181. m_fDialedCDH = TRUE;
  1182. EndDialog(m_hwnd, 0);
  1183. DEBUG_LEAVE(0);
  1184. return;
  1185. }
  1186. else
  1187. {
  1188. // If we don't have an engine, repop conn list (may have been deleted)
  1189. // and bail out of dial operation
  1190. if(!m_pEng)
  1191. {
  1192. EnumerateConnectoids();
  1193. DEBUG_LEAVE(0);
  1194. return;
  1195. }
  1196. // Save off properties
  1197. SaveProps();
  1198. }
  1199. // TODO grey stuff
  1200. m_State = UISTATE_Dialing;
  1201. FixUIComponents();
  1202. // Stick phone number in progress box
  1203. WCHAR szString[256], szPhone[128];
  1204. LoadStringWrapW(GlobalDllHandle, IDS_DIALING, szString, 128);
  1205. if(SUCCEEDED(m_pEng->GetProperty(DIALPROP_RESOLVEDPHONE, szPhone, 128)))
  1206. {
  1207. StrNCatW(szString, szPhone, 128);
  1208. PostString(m_hwnd, szString);
  1209. }
  1210. // Start the dialing operation
  1211. m_pEng->Dial();
  1212. DEBUG_LEAVE(0);
  1213. }
  1214. VOID
  1215. CDialUI::OnCancel(
  1216. )
  1217. {
  1218. DEBUG_ENTER((DBG_DIALUP,
  1219. None,
  1220. "CDialUI::OnCancel",
  1221. NULL
  1222. ));
  1223. switch(m_State)
  1224. {
  1225. case UISTATE_Interactive:
  1226. //
  1227. // exit the dialog box
  1228. //
  1229. m_pDial->dwResult = ERROR_USER_DISCONNECTION;
  1230. EndDialog(m_hwnd, 0);
  1231. break;
  1232. case UISTATE_Unattended:
  1233. case UISTATE_Dialing:
  1234. //
  1235. // cancel current dialing operation
  1236. //
  1237. if(m_pEng)
  1238. {
  1239. m_pEng->HangUp();
  1240. }
  1241. m_pDial->dwResult = ERROR_USER_DISCONNECTION;
  1242. //
  1243. // If we were previous "unattended" we aren't any more
  1244. //
  1245. CheckDlgButton(m_hwnd, IDC_AUTOCONNECT, BST_UNCHECKED);
  1246. m_fAutoConnect = FALSE;
  1247. //
  1248. // fix grey stuff
  1249. //
  1250. FixUIComponents();
  1251. break;
  1252. }
  1253. DEBUG_LEAVE(0);
  1254. }
  1255. INT_PTR CALLBACK
  1256. CDialUI::DialogProc(
  1257. HWND hwndDlg,
  1258. UINT uMsg,
  1259. WPARAM wParam,
  1260. LPARAM lParam
  1261. )
  1262. {
  1263. CDialUI * pui = (CDialUI *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  1264. switch(uMsg)
  1265. {
  1266. case WM_INITDIALOG:
  1267. SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
  1268. pui = (CDialUI *)lParam;
  1269. pui->m_hwnd = hwndDlg;
  1270. pui->OnInitDialog();
  1271. return TRUE;
  1272. case WM_COMMAND:
  1273. // handle combo box messages
  1274. if(HIWORD(wParam) == CBN_SELCHANGE) {
  1275. pui->OnSelChange();
  1276. break;
  1277. }
  1278. switch (LOWORD(wParam))
  1279. {
  1280. case ID_CONNECT:
  1281. pui->OnConnect();
  1282. break;
  1283. case IDCANCEL:
  1284. pui->OnCancel();
  1285. break;
  1286. case IDC_SETTINGS:
  1287. {
  1288. HMODULE hInetcpl = LoadLibrary("inetcpl.cpl");
  1289. if(hInetcpl)
  1290. {
  1291. LAUNCHCPL cpl = (LAUNCHCPL)GetProcAddress(hInetcpl, "LaunchConnectionDialog");
  1292. if(cpl)
  1293. {
  1294. cpl(hwndDlg);
  1295. // refresh to new default if any
  1296. AUTODIAL config;
  1297. memset(&config, 0, sizeof(config));
  1298. IsAutodialEnabled(NULL, &config);
  1299. if(config.fEnabled)
  1300. {
  1301. if(config.fHasEntry)
  1302. {
  1303. StrCpyW(pui->m_pDial->params.szEntryName, config.pszEntryName);
  1304. }
  1305. // refresh settings
  1306. pui->EnumerateConnectoids();
  1307. pui->GetProps();
  1308. }
  1309. else
  1310. {
  1311. // nothing to dial... bail out right away.
  1312. pui->OnCancel();
  1313. }
  1314. }
  1315. FreeLibrary(hInetcpl);
  1316. }
  1317. }
  1318. break;
  1319. case IDC_SAVE_PASSWORD:
  1320. EnableWindow(
  1321. GetDlgItem(hwndDlg, IDC_AUTOCONNECT),
  1322. IsDlgButtonChecked(hwndDlg, IDC_SAVE_PASSWORD));
  1323. break;
  1324. case IDC_PASSWORD:
  1325. if(HIWORD(wParam) == EN_CHANGE)
  1326. {
  1327. pui->m_fPasswordChanged = TRUE;
  1328. }
  1329. break;
  1330. }
  1331. break;
  1332. }
  1333. return FALSE;
  1334. }
  1335. VOID
  1336. CDialUI::EnumerateConnectoids(
  1337. )
  1338. {
  1339. DEBUG_ENTER((DBG_DIALUP,
  1340. None,
  1341. "CDialUI::EnumerateConnectoids",
  1342. NULL
  1343. ));
  1344. HWND hwndCombo = GetDlgItem(m_hwnd, IDC_CONN_LIST);
  1345. INET_ASSERT(hwndCombo);
  1346. ComboBox_ResetContent(hwndCombo);
  1347. EnsureRasLoaded();
  1348. DWORD dwEntries, dwRet;
  1349. RasEnumHelp RasEnum;
  1350. dwRet = RasEnum.GetError();
  1351. dwEntries = RasEnum.GetEntryCount();
  1352. if(ERROR_SUCCESS == dwRet)
  1353. {
  1354. // insert connectoid names from buffer into combo box
  1355. DWORD i;
  1356. for(i=0; i<dwEntries; i++)
  1357. {
  1358. SendMessageWrapW(hwndCombo, CB_ADDSTRING, 0, (LPARAM)RasEnum.GetEntryW(i));
  1359. }
  1360. // try to find connectoid from pinfo
  1361. int iSel = (int)SendMessageWrapW(hwndCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)m_pDial->params.szEntryName);
  1362. if(CB_ERR == iSel)
  1363. {
  1364. iSel = 0;
  1365. SendMessageWrapW(hwndCombo, CB_GETLBTEXT, (WPARAM)iSel, (LPARAM)m_pDial->params.szEntryName);
  1366. }
  1367. ComboBox_SetCurSel(hwndCombo, iSel);
  1368. }
  1369. DEBUG_LEAVE(0);
  1370. }
  1371. VOID
  1372. CDialUI::GetProps(
  1373. )
  1374. {
  1375. DEBUG_ENTER((DBG_DIALUP,
  1376. None,
  1377. "CDialUI::GetProps",
  1378. NULL
  1379. ));
  1380. WCHAR wzBuffer[256];
  1381. HRESULT hr;
  1382. CDHINFO cdh;
  1383. SAFE_RELEASE(m_pEng);
  1384. //
  1385. // Find out if new selection is a CDH
  1386. //
  1387. m_fCDH = IsCDH(m_pDial->params.szEntryName, &m_cdh);
  1388. //
  1389. // Query for properties for non-CDH connections
  1390. //
  1391. if(!m_fCDH && SUCCEEDED(InternetGetDialEngineW(m_pDial->params.szEntryName, (IDialEventSink *)this, &m_pEng)))
  1392. {
  1393. if(FAILED(m_pEng->GetProperty(DIALPROP_USERNAME, wzBuffer, 256)))
  1394. {
  1395. *wzBuffer = 0;
  1396. }
  1397. SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_USER_NAME), wzBuffer);
  1398. m_fSavePassword = FALSE;
  1399. hr = m_pEng->GetProperty(DIALPROP_PASSWORD, wzBuffer, 256);
  1400. if(S_OK == hr)
  1401. {
  1402. m_fSavePassword = TRUE;
  1403. }
  1404. else // S_FALSE - no saved password, or error
  1405. {
  1406. *wzBuffer = 0;
  1407. }
  1408. SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_PASSWORD), wzBuffer);
  1409. CheckDlgButton(m_hwnd, IDC_SAVE_PASSWORD, m_fSavePassword ? BST_CHECKED : BST_UNCHECKED);
  1410. if(FAILED(m_pEng->GetProperty(DIALPROP_DOMAIN, wzBuffer, 256)))
  1411. {
  1412. *wzBuffer = 0;
  1413. }
  1414. SetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_DOMAIN), wzBuffer);
  1415. }
  1416. //
  1417. // fix UI based on connectoid type
  1418. //
  1419. FixUIComponents();
  1420. // reset password changed as setting it above will cause the window message
  1421. m_fPasswordChanged = FALSE;
  1422. DEBUG_LEAVE(0);
  1423. }
  1424. VOID
  1425. CDialUI::SaveProps(
  1426. )
  1427. {
  1428. DEBUG_ENTER((DBG_DIALUP,
  1429. None,
  1430. "CDialUI::SaveProps",
  1431. NULL
  1432. ));
  1433. WCHAR wzBuffer[256];
  1434. GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_USER_NAME), wzBuffer, 256);
  1435. m_pEng->SetProperty(DIALPROP_USERNAME, wzBuffer);
  1436. GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_DOMAIN), wzBuffer, 256);
  1437. m_pEng->SetProperty(DIALPROP_DOMAIN, wzBuffer);
  1438. m_fSavePassword = FALSE;
  1439. if(BST_CHECKED == IsDlgButtonChecked(m_hwnd, IDC_SAVE_PASSWORD))
  1440. m_fSavePassword = TRUE;
  1441. if(m_fPasswordChanged || FALSE == m_fSavePassword)
  1442. {
  1443. GetWindowTextWrapW(GetDlgItem(m_hwnd, IDC_PASSWORD), wzBuffer, 256);
  1444. m_pEng->SetProperty(DIALPROP_PASSWORD, wzBuffer);
  1445. m_pEng->SetProperty(DIALPROP_SAVEPASSWORD, m_fSavePassword ? L"TRUE" : L"FALSE");
  1446. m_fPasswordChanged = FALSE;
  1447. }
  1448. m_fAutoConnect = FALSE;
  1449. if(BST_CHECKED == IsDlgButtonChecked(m_hwnd, IDC_AUTOCONNECT))
  1450. m_fAutoConnect = TRUE;
  1451. DEBUG_LEAVE(0);
  1452. }
  1453. //////////////////////////////////////////////////////////////////////////////
  1454. //
  1455. // Helper functions
  1456. //
  1457. //////////////////////////////////////////////////////////////////////////////
  1458. //
  1459. // Add a string to the details edit box
  1460. //
  1461. void PostString(HWND hDlg, LPWSTR pszString)
  1462. {
  1463. HWND hwndEdit = GetDlgItem(hDlg, IDC_DETAILS_LIST);
  1464. WCHAR szCR[] = L"\r\n";
  1465. // move caret to end
  1466. SendMessageWrapW(hwndEdit, EM_SETSEL, 0, -1);
  1467. SendMessageWrapW(hwndEdit, EM_SETSEL, -1, -1);
  1468. // replace selection (nothing) with new string
  1469. SendMessageWrapW(hwndEdit, EM_REPLACESEL, 0, (LPARAM)pszString);
  1470. // move caret to end
  1471. SendMessageWrapW(hwndEdit, EM_SETSEL, 0, -1);
  1472. SendMessageWrapW(hwndEdit, EM_SETSEL, -1, -1);
  1473. // replace selection (nothing) with CR
  1474. SendMessageWrapW(hwndEdit, EM_REPLACESEL, 0, (LPARAM)szCR);
  1475. // scroll to end
  1476. SendMessageWrapW(hwndEdit, EM_SCROLLCARET, 0, 0);
  1477. }
  1478. #define RAS_BOGUS_AUTHFAILCODE_1 84
  1479. #define RAS_BOGUS_AUTHFAILCODE_2 74389484
  1480. DWORD RasErrorToIDS(DWORD dwErr)
  1481. {
  1482. if(dwErr==RAS_BOGUS_AUTHFAILCODE_1 || dwErr==RAS_BOGUS_AUTHFAILCODE_2)
  1483. {
  1484. return IDS_PPPRANDOMFAILURE;
  1485. }
  1486. if((dwErr>=653 && dwErr<=663) || (dwErr==667) || (dwErr>=669 && dwErr<=675))
  1487. {
  1488. return IDS_MEDIAINIERROR;
  1489. }
  1490. switch(dwErr)
  1491. {
  1492. default:
  1493. return IDS_PPPRANDOMFAILURE;
  1494. case ERROR_LINE_BUSY:
  1495. return IDS_PHONEBUSY;
  1496. case ERROR_NO_ANSWER:
  1497. return IDS_NOANSWER;
  1498. case ERROR_NO_DIALTONE:
  1499. return IDS_NODIALTONE;
  1500. case ERROR_HARDWARE_FAILURE: // modem turned off
  1501. case ERROR_PORT_ALREADY_OPEN: // procomm/hypertrm/RAS has COM port
  1502. case ERROR_PORT_OR_DEVICE: // got this when hypertrm had the device open -- jmazner
  1503. return IDS_NODEVICE;
  1504. case ERROR_BUFFER_INVALID: // bad/empty rasdilap struct
  1505. case ERROR_BUFFER_TOO_SMALL: // ditto?
  1506. case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY: // if connectoid name in registry is wrong
  1507. case ERROR_INTERACTIVE_MODE:
  1508. return IDS_TCPINSTALLERROR;
  1509. case ERROR_AUTHENTICATION_FAILURE: // get this on actual CHAP reject
  1510. return IDS_AUTHFAILURE;
  1511. case ERROR_VOICE_ANSWER:
  1512. case ERROR_NO_CARRIER:
  1513. case ERROR_PPP_TIMEOUT: // get this on CHAP timeout
  1514. case ERROR_REMOTE_DISCONNECTION: // Ascend drops connection on auth-fail
  1515. case ERROR_AUTH_INTERNAL: // got this on random POP failure
  1516. case ERROR_PROTOCOL_NOT_CONFIGURED: // get this if LCP fails
  1517. case ERROR_PPP_NO_PROTOCOLS_CONFIGURED: // get this if IPCP addr download gives garbage
  1518. return IDS_PPPRANDOMFAILURE;
  1519. }
  1520. return 0;
  1521. }
  1522. void GetDialErrorString(DWORD dwError, LPWSTR pszBuffer, DWORD dwLength)
  1523. {
  1524. DWORD dwRes;
  1525. dwRes = RasErrorToIDS(dwError);
  1526. if(dwRes) {
  1527. // we have a resource - use it
  1528. LoadStringWrapW(GlobalDllHandle, dwRes, pszBuffer, dwLength);
  1529. } else {
  1530. // couldn't get ras error, try system error
  1531. if(0 == FormatMessageWrapW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, 0, pszBuffer, dwLength, NULL)) {
  1532. // couldn't get system error, get system error E_FAIL == Unknown error
  1533. FormatMessageWrapW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, E_FAIL, 0, pszBuffer, dwLength, NULL);
  1534. }
  1535. }
  1536. }
  1537. void SetDialError(HWND hDlg, DWORD dwError)
  1538. {
  1539. WCHAR szBuf[200];
  1540. GetDialErrorString(dwError, szBuf, 200);
  1541. PostString(hDlg, szBuf);
  1542. }
  1543. BOOL
  1544. FindDialProvider(
  1545. IN LPWSTR pwzConnectoid,
  1546. IN LPWSTR pwzProviderType,
  1547. OUT CLSID * pclsid
  1548. )
  1549. //
  1550. // FindDialProvider - find an engine, UI, or branding provider for a
  1551. // specific connectoid
  1552. //
  1553. {
  1554. DEBUG_ENTER((DBG_DIALUP,
  1555. Bool,
  1556. "FindDialProvider",
  1557. "%#x (%Q), %#x (%Q), %#x",
  1558. pwzConnectoid,
  1559. pwzConnectoid,
  1560. pwzProviderType,
  1561. pwzProviderType,
  1562. pclsid
  1563. ));
  1564. WCHAR szKey[MAX_PATH];
  1565. WCHAR szClsid[64];
  1566. DWORD dwSize;
  1567. // get the key for the connectoid
  1568. GetConnKeyW(pwzConnectoid, szKey, ARRAYSIZE(szKey));
  1569. // read the CLSID string
  1570. dwSize = sizeof(szClsid);
  1571. if(ERROR_SUCCESS != SHGetValueW(
  1572. HKEY_CURRENT_USER,
  1573. szKey,
  1574. pwzProviderType,
  1575. NULL,
  1576. szClsid,
  1577. &dwSize))
  1578. {
  1579. // no provider specified
  1580. DEBUG_PRINT(DIALUP, INFO, ("No provider found.\n"));
  1581. DEBUG_LEAVE(FALSE);
  1582. return FALSE;
  1583. }
  1584. // covert string to clsid
  1585. if(FAILED(CLSIDFromString(szClsid, pclsid)))
  1586. {
  1587. DEBUG_PRINT(DIALUP, INFO, ("Unable to convert clsid.\n"));
  1588. DEBUG_LEAVE(FALSE);
  1589. return FALSE;
  1590. }
  1591. DEBUG_LEAVE(TRUE);
  1592. return TRUE;
  1593. }
  1594. //////////////////////////////////////////////////////////////////////////////
  1595. //
  1596. // Public APIs
  1597. //
  1598. //////////////////////////////////////////////////////////////////////////////
  1599. INTERNETAPI InternetGetDialEngineW(
  1600. IN LPWSTR pwzConnectoid,
  1601. IN IDialEventSink * pdes,
  1602. OUT IDialEngine ** ppde
  1603. )
  1604. {
  1605. DEBUG_ENTER_API((DBG_DIALUP,
  1606. Dword,
  1607. "InternetGetDialEngineW",
  1608. "%#x (%Q), %#x, %#x",
  1609. pwzConnectoid,
  1610. pwzConnectoid,
  1611. pdes,
  1612. ppde
  1613. ));
  1614. HRESULT hr;
  1615. CLSID clsid;
  1616. *ppde = NULL;
  1617. //
  1618. // find engine we're going to use
  1619. //
  1620. if(FindDialProvider(pwzConnectoid, L"DialEngine", &clsid))
  1621. {
  1622. // engine specified, try to create it
  1623. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
  1624. IID_IDialEngine, (void **)ppde);
  1625. }
  1626. if(NULL == *ppde)
  1627. {
  1628. // use default engine
  1629. CDialEngine * pEngine = new CDialEngine();
  1630. if(pEngine)
  1631. {
  1632. hr = pEngine->QueryInterface(IID_IDialEngine, (void **)ppde);
  1633. }
  1634. else
  1635. {
  1636. hr = E_OUTOFMEMORY;
  1637. }
  1638. }
  1639. if(SUCCEEDED(hr))
  1640. {
  1641. hr = (*ppde)->Initialize(pwzConnectoid, pdes);
  1642. if(FAILED(hr))
  1643. {
  1644. (*ppde)->Release();
  1645. *ppde = NULL;
  1646. }
  1647. }
  1648. DEBUG_LEAVE_API(hr);
  1649. return hr;
  1650. }
  1651. #if 0
  1652. //
  1653. // [darrenmi 4/14/00] cleaning up exports of incomplete feature
  1654. //
  1655. INTERNETAPI InternetGetDialBrandingW(
  1656. IN LPWSTR pwzConnectoid,
  1657. OUT IDialBranding ** ppdb
  1658. )
  1659. {
  1660. DEBUG_ENTER_API((DBG_DIALUP,
  1661. Dword,
  1662. "InternetGetDialBrandingW",
  1663. "%#x (%Q), %#x",
  1664. pwzConnectoid,
  1665. pwzConnectoid,
  1666. ppdb
  1667. ));
  1668. HRESULT hr = S_FALSE;
  1669. CLSID clsid;
  1670. *ppdb = NULL;
  1671. //
  1672. // find engine we're going to use
  1673. //
  1674. if(FindDialProvider(pwzConnectoid, L"DialBranding", &clsid))
  1675. {
  1676. // engine specified, try to create it
  1677. hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER,
  1678. IID_IDialBranding, (void **)ppdb);
  1679. }
  1680. if(SUCCEEDED(hr))
  1681. {
  1682. hr = (*ppdb)->Initialize(pwzConnectoid);
  1683. if(FAILED(hr))
  1684. {
  1685. (*ppdb)->Release();
  1686. *ppdb = NULL;
  1687. }
  1688. }
  1689. DEBUG_LEAVE_API(hr);
  1690. return hr;
  1691. }
  1692. #endif