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.

1221 lines
40 KiB

  1. /*****************************************************************************\
  2. FILE: AutoDiscovery.cpp
  3. DESCRIPTION:
  4. This is AutoDiscovery progress UI for the Outlook Express's email
  5. configuration wizard.
  6. BryanSt 1/18/2000
  7. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  8. \*****************************************************************************/
  9. #include "pch.hxx"
  10. #include <prsht.h>
  11. #include <imnact.h>
  12. #include <icwacct.h>
  13. #include <acctimp.h>
  14. #include "icwwiz.h"
  15. #include "acctui.h"
  16. #include "acctman.h"
  17. #include <dllmain.h>
  18. #include <resource.h>
  19. #include "server.h"
  20. #include "connect.h"
  21. #include <Shlwapi.h>
  22. #include "shlwapip.h"
  23. #include "strconst.h"
  24. #include "demand.h"
  25. #include "hotwiz.h"
  26. #include "shared.h"
  27. #include <AutoDiscovery.h>
  28. #include "AutoDiscoveryUI.h"
  29. ASSERTDATA
  30. #define RECTWIDTH(rect) (rect.right - rect.left)
  31. #define RECTHEIGHT(rect) (rect.bottom - rect.top)
  32. #define MAX_URL_STRING 2048
  33. #define SIZE_STR_AUTODISC_DESC 2048
  34. // These are the wizard control IDs for the Back, Next, and Finished buttons.
  35. #define IDD_WIZARD_BACK_BUTTON 0x3023
  36. #define IDD_WIZARD_NEXT_BUTTON 0x3024
  37. #define IDD_WIZARD_FINISH_BUTTON 0x3025
  38. #define SZ_DLL_AUTODISC TEXT("autodisc.dll")
  39. #define IDA_DOWNLOADINGSETTINGS 801 // In autodisc.dll
  40. #define ATOMICRELEASE(punk) {if (punk) { punk->Release(); punk = NULL;} }
  41. WCHAR g_szInfoURL[MAX_URL_STRING] = {0};
  42. WCHAR g_szWebMailURL[MAX_URL_STRING] = {0};
  43. typedef struct
  44. {
  45. // Default Protocol (POP3, IMAP, DAV, WEB)
  46. int nProtocol; // What is the email protocol? POP3 vs. IMAP vs. DAV vs. WEB
  47. BSTR bstrDisplayName; // What is the user's display name.
  48. BSTR bstrServer1Name; // What is the downloading email server name (POP3, IMAP, DAV, or WEB)
  49. int nServer1Port; // What is that server's port number?
  50. BSTR bstrLoginName; // What is the login name for the POP3 server. (Normall the same as the email address w/out the domain)
  51. BOOL fUsesSSL; // Use SSL when connecting to the POP3 or IMAP server?
  52. BOOL fUsesSPA; // Use SPA when connecting to the POP3 or IMAP server?
  53. // SMTP Protocol (If used)
  54. BSTR bstrServer2Name; // What is the uploading email server name (SMTP)
  55. int nServer2Port; // What is that server's port number?
  56. BOOL fSMTPUsesSSL; // Use SSL when connecting to the SMTP server?
  57. BOOL fAuthSMTP; // Does SMTP need Authentication?
  58. BOOL fAuthSMTPPOP; // Use POP3's auth for SMTP?
  59. BOOL fAuthSMTPSPA; // Use SPA auth for SMTP?
  60. BOOL fUseWebMail; // Is Web Bassed mail the only protocol we recognizer?
  61. BSTR bstrSMTPLoginName; // What is the login name for the SMTP server.
  62. BOOL fDisplayInfoURL; // Is there an URL for Info about the email server/services?
  63. BSTR bstrInfoURL; // If fDisplayInfoURL, this is the URL.
  64. } EMAIL_SERVER_SETTINGS;
  65. class CICWApprentice;
  66. /*****************************************************************************\
  67. Class: CAutoDiscoveryHelper
  68. DESCRIPTION:
  69. StartAutoDiscovery:
  70. hwndParent: This is the caller's hwnd. If we need to display UI, we
  71. will parent it off this hwnd. We also send this hwnd messages on
  72. progress.
  73. \*****************************************************************************/
  74. class CAutoDiscoveryHelper
  75. {
  76. public:
  77. // Public Methods
  78. HRESULT StartAutoDiscovery(IN CICWApprentice *pApp, IN HWND hDlg, IN BOOL fFirstInit);
  79. HRESULT OnCompleted(IN CICWApprentice *pApp, IN ACCTDATA * pData);
  80. HRESULT SetNextButton(HWND hwndButton);
  81. HRESULT RestoreNextButton(HWND hwndButton);
  82. CAutoDiscoveryHelper();
  83. ~CAutoDiscoveryHelper(void);
  84. private:
  85. // Private Member Variables
  86. // Other internal state.
  87. HWND _hwndDlgParent; // parent window for message boxes
  88. TCHAR _szNextText[MAX_PATH]; //
  89. IMailAutoDiscovery * _pMailAutoDiscovery; //
  90. HINSTANCE _hInstAutoDisc; // We use this to get the animation
  91. // Private Member Functions
  92. HRESULT _GetAccountInformation(EMAIL_SERVER_SETTINGS * pEmailServerSettings);
  93. };
  94. CAutoDiscoveryHelper * g_pAutoDiscoveryObject = NULL; // This is the AutoDisc obj used while downloading the settings.
  95. BOOL g_fRequestCancelled = TRUE;
  96. UINT g_uNextPage = ORD_PAGE_AD_MAILNAME; // ORD_PAGE_AD_MAILNAME, ORD_PAGE_AD_MAILSERVER, ORD_PAGE_AD_USEWEBMAIL, ORD_PAGE_AD_GOTOSERVERINFO
  97. //===========================
  98. // *** Class Internals & Helpers ***
  99. //===========================
  100. HRESULT FreeEmailServerSettings(EMAIL_SERVER_SETTINGS * pEmailServerSettings)
  101. {
  102. SysFreeString(pEmailServerSettings->bstrDisplayName); // It's okay to pass NULL to this API
  103. SysFreeString(pEmailServerSettings->bstrServer1Name);
  104. SysFreeString(pEmailServerSettings->bstrLoginName);
  105. SysFreeString(pEmailServerSettings->bstrServer2Name);
  106. SysFreeString(pEmailServerSettings->bstrSMTPLoginName);
  107. SysFreeString(pEmailServerSettings->bstrInfoURL);
  108. return S_OK;
  109. }
  110. BSTR SysAllocStringA(LPCSTR pszStr)
  111. {
  112. BSTR bstrOut = NULL;
  113. if (pszStr)
  114. {
  115. DWORD cchSize = (lstrlenA(pszStr) + 1);
  116. LPWSTR pwszThunkTemp = (LPWSTR) LocalAlloc(LPTR, (sizeof(pwszThunkTemp[0]) * cchSize)); // assumes INFOTIPSIZE number of chars max
  117. if (pwszThunkTemp)
  118. {
  119. SHAnsiToUnicode(pszStr, pwszThunkTemp, cchSize);
  120. bstrOut = SysAllocString(pwszThunkTemp);
  121. LocalFree(pwszThunkTemp);
  122. }
  123. }
  124. return bstrOut;
  125. }
  126. HRESULT ADRestoreNextButton(CICWApprentice *pApp, HWND hDlg)
  127. {
  128. HRESULT hr = S_OK;
  129. g_fRequestCancelled = TRUE;
  130. if (g_pAutoDiscoveryObject)
  131. {
  132. g_pAutoDiscoveryObject->RestoreNextButton(GetDlgItem(GetParent(hDlg), IDD_WIZARD_NEXT_BUTTON));
  133. delete g_pAutoDiscoveryObject;
  134. g_pAutoDiscoveryObject = NULL;
  135. }
  136. return hr;
  137. }
  138. HRESULT CreateAccountName(IN CICWApprentice *pApp, IN ACCTDATA * pData);
  139. HRESULT OnADCompleted(CICWApprentice *pApp, HWND hDlg)
  140. {
  141. HRESULT hr = E_OUTOFMEMORY;
  142. if (g_pAutoDiscoveryObject)
  143. {
  144. ACCTDATA * pData = pApp->GetAccountData();
  145. hr = g_pAutoDiscoveryObject->OnCompleted(pApp, pData);
  146. if (SUCCEEDED(hr))
  147. {
  148. // Set the display name for the account.
  149. CreateAccountName(pApp, pData);
  150. }
  151. else
  152. {
  153. // TODO: If _fUseWebMail is set, we will probably want
  154. // to navigate to a page telling the user to use a web
  155. // page to get their email.
  156. }
  157. }
  158. return hr;
  159. }
  160. #define SZ_HOTMAILDOMAIN "@hotmail.com"
  161. #define CH_EMAILDOMAINSEPARATOR '@'
  162. HRESULT CAutoDiscoveryHelper::StartAutoDiscovery(IN CICWApprentice *pApp, IN HWND hDlg, IN BOOL fFirstInit)
  163. {
  164. HRESULT hr = E_OUTOFMEMORY;
  165. ACCTDATA * pData = pApp->GetAccountData();
  166. if (pData && pData->szEmail)
  167. {
  168. LPCSTR pszEmailDomain = StrChrA(pData->szEmail, CH_EMAILDOMAINSEPARATOR);
  169. if (pszEmailDomain && !StrCmpI(SZ_HOTMAILDOMAIN, pszEmailDomain)) // Is this a HOTMAIL.COM account?
  170. {
  171. // Yes, so skip AutoDiscovery since we don't require the user
  172. // to enter hard settings in that case. (Protocol and server settings never
  173. // change)
  174. hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
  175. }
  176. else
  177. {
  178. WCHAR szEmail[1024];
  179. SHAnsiToUnicode(pData->szEmail, szEmail, ARRAYSIZE(szEmail));
  180. _hwndDlgParent = hDlg;
  181. // Set Animation.
  182. HWND hwndAnimation = GetDlgItem(hDlg, IDC_AUTODISCOVERY_ANIMATION);
  183. if (hwndAnimation)
  184. {
  185. _hInstAutoDisc = LoadLibrary(SZ_DLL_AUTODISC);
  186. if (_hInstAutoDisc)
  187. {
  188. Animate_OpenEx(hwndAnimation, _hInstAutoDisc, IDA_DOWNLOADINGSETTINGS);
  189. }
  190. }
  191. HWND hwndWizard = GetParent(hDlg);
  192. if (hwndWizard)
  193. {
  194. SetNextButton(GetDlgItem(hwndWizard, IDD_WIZARD_NEXT_BUTTON));
  195. }
  196. ATOMICRELEASE(_pMailAutoDiscovery);
  197. // Start the background task.
  198. hr = CoCreateInstance(CLSID_MailAutoDiscovery, NULL, CLSCTX_INPROC_SERVER, IID_IMailAutoDiscovery, (void **)&_pMailAutoDiscovery);
  199. if (SUCCEEDED(hr))
  200. {
  201. hr = _pMailAutoDiscovery->WorkAsync(hDlg, WM_AUTODISCOVERY_FINISHED);
  202. if (SUCCEEDED(hr))
  203. {
  204. BSTR bstrEmail = SysAllocString(szEmail);
  205. if (bstrEmail)
  206. {
  207. hr = _pMailAutoDiscovery->DiscoverMail(bstrEmail);
  208. if (SUCCEEDED(hr))
  209. {
  210. g_fRequestCancelled = FALSE;
  211. }
  212. SysFreeString(bstrEmail);
  213. }
  214. else
  215. {
  216. hr = E_OUTOFMEMORY;
  217. }
  218. }
  219. }
  220. }
  221. }
  222. else
  223. {
  224. hr = E_FAIL;
  225. }
  226. if (FAILED(hr))
  227. {
  228. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  229. }
  230. return hr;
  231. }
  232. HRESULT CAutoDiscoveryHelper::SetNextButton(HWND hwndButton)
  233. {
  234. HRESULT hr = S_OK;
  235. TCHAR szSkipButton[MAX_PATH];
  236. // First, change the "Next" button into "Skip"
  237. // Save the text on the next button before we rename it.
  238. if (hwndButton && !GetWindowText(hwndButton, _szNextText, ARRAYSIZE(_szNextText)))
  239. {
  240. _szNextText[0] = 0; // terminate string in failure case.
  241. }
  242. // Set the next text.
  243. LoadString(g_hInstRes, idsADSkipButton, szSkipButton, ARRAYSIZE(szSkipButton));
  244. SetWindowText(hwndButton, szSkipButton);
  245. return hr;
  246. }
  247. HRESULT CAutoDiscoveryHelper::RestoreNextButton(HWND hwndButton)
  248. {
  249. HRESULT hr = S_OK;
  250. if (_szNextText[0])
  251. {
  252. // Restore the Next button text.
  253. SetWindowText(hwndButton, _szNextText);
  254. }
  255. return hr;
  256. }
  257. /****************************************************\
  258. DESCRIPTION:
  259. \****************************************************/
  260. HRESULT CAutoDiscoveryHelper::OnCompleted(IN CICWApprentice *pApp, IN ACCTDATA *pData)
  261. {
  262. // Step 1. Get all the settings from IMailAutoDiscovery to EMAIL_SERVER_SETTINGS
  263. EMAIL_SERVER_SETTINGS emailServerSettings = {0};
  264. emailServerSettings.nProtocol = -1;
  265. emailServerSettings.nServer1Port = -1;
  266. emailServerSettings.nServer2Port = -1;
  267. HRESULT hr = _GetAccountInformation(&emailServerSettings);
  268. g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
  269. // Did the AutoDiscovery process succeed?
  270. if (SUCCEEDED(hr))
  271. {
  272. if (emailServerSettings.fDisplayInfoURL)
  273. {
  274. g_uNextPage = ORD_PAGE_AD_GOTOSERVERINFO;
  275. StrCpyNW(g_szInfoURL, emailServerSettings.bstrInfoURL, ARRAYSIZE(g_szInfoURL));
  276. }
  277. else if (emailServerSettings.fUseWebMail)
  278. {
  279. g_uNextPage = ORD_PAGE_AD_USEWEBMAIL;
  280. StrCpyNW(g_szWebMailURL, emailServerSettings.bstrServer1Name, ARRAYSIZE(g_szWebMailURL));
  281. }
  282. else
  283. {
  284. g_uNextPage = ORD_PAGE_AD_MAILNAME;
  285. if (pApp && pData && pApp->m_pAcct)
  286. {
  287. // Step 2. Move all the settings from EMAIL_SERVER_SETTINGS to the OE mail account (ACCTDATA).
  288. IImnAccount * pAcct = pApp->m_pAcct;
  289. pData->fLogon = FALSE; // BUGBUG: When is this needed? DAV?
  290. pData->fSPA = emailServerSettings.fUsesSPA;
  291. pData->fServerTypes = emailServerSettings.nProtocol;
  292. Assert(!pData->fCreateNewAccount);
  293. if (emailServerSettings.bstrDisplayName)
  294. {
  295. SHUnicodeToAnsi(emailServerSettings.bstrDisplayName, pData->szName, ARRAYSIZE(pData->szName));
  296. }
  297. if (emailServerSettings.bstrServer1Name)
  298. {
  299. SHUnicodeToAnsi(emailServerSettings.bstrServer1Name, pData->szSvr1, ARRAYSIZE(pData->szSvr1));
  300. }
  301. if (emailServerSettings.bstrLoginName)
  302. {
  303. SHUnicodeToAnsi(emailServerSettings.bstrLoginName, pData->szUsername, ARRAYSIZE(pData->szUsername));
  304. }
  305. if (emailServerSettings.nProtocol & (SRV_POP3 | SRV_IMAP))
  306. {
  307. pAcct->SetPropDw(((emailServerSettings.nProtocol & SRV_POP3) ? AP_POP3_SSL : AP_IMAP_SSL), emailServerSettings.fUsesSSL);
  308. if (-1 != emailServerSettings.nServer1Port)
  309. {
  310. pAcct->SetPropDw(((emailServerSettings.nProtocol & SRV_POP3) ? AP_POP3_PORT : AP_IMAP_PORT), emailServerSettings.nServer1Port);
  311. }
  312. }
  313. if (emailServerSettings.nProtocol & SRV_SMTP)
  314. {
  315. if (emailServerSettings.bstrServer2Name)
  316. {
  317. SHUnicodeToAnsi(emailServerSettings.bstrServer2Name, pData->szSvr2, ARRAYSIZE(pData->szSvr2));
  318. }
  319. if (-1 != emailServerSettings.nServer2Port)
  320. {
  321. pAcct->SetPropDw(AP_SMTP_PORT, emailServerSettings.nServer2Port);
  322. }
  323. pAcct->SetPropDw(AP_SMTP_SSL, emailServerSettings.fSMTPUsesSSL);
  324. if (!emailServerSettings.fAuthSMTP)
  325. {
  326. pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_NONE);
  327. }
  328. else
  329. {
  330. if (emailServerSettings.fAuthSMTPPOP)
  331. {
  332. pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_USE_POP3ORIMAP_SETTINGS);
  333. }
  334. else
  335. {
  336. if (emailServerSettings.fAuthSMTPSPA)
  337. {
  338. pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_SICILY);
  339. }
  340. else
  341. {
  342. pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_USE_SMTP_SETTINGS);
  343. }
  344. if (emailServerSettings.bstrSMTPLoginName)
  345. {
  346. TCHAR szSMTPUserName[CCHMAX_ACCT_PROP_SZ];
  347. WideCharToMultiByte(CP_ACP, 0, emailServerSettings.bstrSMTPLoginName, -1, szSMTPUserName, ARRAYSIZE(szSMTPUserName), NULL, NULL);
  348. pAcct->SetPropSz(AP_SMTP_USERNAME, szSMTPUserName);
  349. }
  350. pAcct->SetPropDw(AP_SMTP_PROMPT_PASSWORD, TRUE);
  351. }
  352. }
  353. }
  354. }
  355. }
  356. // Step 3. Free all the memory in EMAIL_SERVER_SETTINGS
  357. FreeEmailServerSettings(&emailServerSettings);
  358. }
  359. return hr;
  360. }
  361. /****************************************************\
  362. DESCRIPTION:
  363. \****************************************************/
  364. HRESULT CAutoDiscoveryHelper::_GetAccountInformation(EMAIL_SERVER_SETTINGS * pEmailServerSettings)
  365. {
  366. BSTR bstrPreferedProtocol;
  367. HRESULT hr = S_OK;
  368. // We ignore hr because getting the display name is optinal.
  369. _pMailAutoDiscovery->get_DisplayName(&pEmailServerSettings->bstrDisplayName);
  370. hr = _pMailAutoDiscovery->get_PreferedProtocolType(&bstrPreferedProtocol);
  371. // Loop thru the list looking for the first instance of a protocol
  372. // that we support.
  373. if (StrCmpIW(bstrPreferedProtocol, STR_PT_POP) &&
  374. StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) &&
  375. StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL))
  376. {
  377. long nSize;
  378. hr = _pMailAutoDiscovery->get_length(&nSize);
  379. if (SUCCEEDED(hr))
  380. {
  381. VARIANT varIndex;
  382. varIndex.vt = VT_I4;
  383. SysFreeString(bstrPreferedProtocol);
  384. for (long nIndex = 1; (nIndex < nSize); nIndex++)
  385. {
  386. IMailProtocolADEntry * pMailProtocol;
  387. varIndex.lVal = nIndex;
  388. if (SUCCEEDED(_pMailAutoDiscovery->get_item(varIndex, &pMailProtocol)))
  389. {
  390. hr = pMailProtocol->get_Protocol(&bstrPreferedProtocol);
  391. pMailProtocol->Release();
  392. pMailProtocol = NULL;
  393. if (SUCCEEDED(hr))
  394. {
  395. // Is this protocol one of the ones we support?
  396. if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
  397. !StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) ||
  398. !StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL))
  399. {
  400. hr = S_OK;
  401. break;
  402. }
  403. SysFreeString(bstrPreferedProtocol);
  404. bstrPreferedProtocol = NULL;
  405. }
  406. }
  407. }
  408. }
  409. }
  410. // TODO: Handle the Web Based mail case.
  411. if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP)) pEmailServerSettings->nProtocol = (SRV_POP3 | SRV_SMTP);
  412. else if (!StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP)) pEmailServerSettings->nProtocol = (SRV_IMAP | SRV_SMTP);
  413. else if (!StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL)) pEmailServerSettings->nProtocol = SRV_HTTPMAIL;
  414. // We need to reject Web Base Mail. In the future, we may want to give a page
  415. // for them to launch the web browser to read their mail.
  416. if (SUCCEEDED(hr) && bstrPreferedProtocol &&
  417. (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
  418. !StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) ||
  419. !StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL)))
  420. {
  421. VARIANT varIndex;
  422. IMailProtocolADEntry * pMailProtocol;
  423. varIndex.vt = VT_BSTR;
  424. varIndex.bstrVal = bstrPreferedProtocol;
  425. hr = _pMailAutoDiscovery->get_item(varIndex, &pMailProtocol);
  426. if (SUCCEEDED(hr))
  427. {
  428. hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer1Name);
  429. if (SUCCEEDED(hr))
  430. {
  431. BSTR bstrPortNum;
  432. // Having a custom port number is optional.
  433. if (SUCCEEDED(pMailProtocol->get_ServerPort(&bstrPortNum)))
  434. {
  435. pEmailServerSettings->nServer1Port = StrToIntW(bstrPortNum);
  436. SysFreeString(bstrPortNum);
  437. }
  438. if (SUCCEEDED(hr))
  439. {
  440. VARIANT_BOOL vfSPA = VARIANT_FALSE;
  441. if (SUCCEEDED(pMailProtocol->get_UseSPA(&vfSPA)))
  442. {
  443. pEmailServerSettings->fUsesSPA = (VARIANT_TRUE == vfSPA);
  444. }
  445. pMailProtocol->get_LoginName(&pEmailServerSettings->bstrLoginName);
  446. }
  447. VARIANT_BOOL vfSSL = VARIANT_FALSE;
  448. if (SUCCEEDED(pMailProtocol->get_UseSSL(&vfSSL)))
  449. {
  450. pEmailServerSettings->fUsesSSL = (VARIANT_TRUE == vfSSL);
  451. }
  452. }
  453. pMailProtocol->Release();
  454. }
  455. // Is this one of the protocols that requires a second server?
  456. if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
  457. !StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP))
  458. {
  459. varIndex.bstrVal = STR_PT_SMTP;
  460. hr = _pMailAutoDiscovery->get_item(varIndex, &pMailProtocol);
  461. if (SUCCEEDED(hr))
  462. {
  463. hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer2Name);
  464. if (SUCCEEDED(hr))
  465. {
  466. BSTR bstrPortNum;
  467. // Having a custom port number is optional.
  468. if (SUCCEEDED(pMailProtocol->get_ServerPort(&bstrPortNum)))
  469. {
  470. pEmailServerSettings->nServer2Port = StrToIntW(bstrPortNum);
  471. SysFreeString(bstrPortNum);
  472. }
  473. // TODO: Read in _fAuthSMTP and _fAuthSMTPPOP
  474. VARIANT_BOOL vfSPA = VARIANT_FALSE;
  475. if (SUCCEEDED(pMailProtocol->get_UseSPA(&vfSPA)))
  476. {
  477. pEmailServerSettings->fAuthSMTPSPA = (VARIANT_TRUE == vfSPA);
  478. }
  479. VARIANT_BOOL vfAuthSMTP = VARIANT_FALSE;
  480. if (SUCCEEDED(pMailProtocol->get_IsAuthRequired(&vfAuthSMTP)))
  481. {
  482. pEmailServerSettings->fAuthSMTP = (VARIANT_TRUE == vfAuthSMTP);
  483. }
  484. VARIANT_BOOL vfAuthFromPOP = VARIANT_FALSE;
  485. if (SUCCEEDED(pMailProtocol->get_SMTPUsesPOP3Auth(&vfAuthFromPOP)))
  486. {
  487. pEmailServerSettings->fAuthSMTPPOP = (VARIANT_TRUE == vfAuthFromPOP);
  488. }
  489. VARIANT_BOOL vfSSL = VARIANT_FALSE;
  490. if (SUCCEEDED(pMailProtocol->get_UseSSL(&vfSSL)))
  491. {
  492. pEmailServerSettings->fSMTPUsesSSL = (VARIANT_TRUE == vfSSL);
  493. }
  494. pMailProtocol->get_LoginName(&pEmailServerSettings->bstrSMTPLoginName);
  495. }
  496. pMailProtocol->Release();
  497. }
  498. }
  499. SysFreeString(bstrPreferedProtocol);
  500. }
  501. if (SUCCEEDED(hr) && (-1 == pEmailServerSettings->nProtocol))
  502. {
  503. hr = E_FAIL;
  504. }
  505. if (FAILED(hr) && (-1 == pEmailServerSettings->nProtocol))
  506. {
  507. // Does this email account work with web based email?
  508. VARIANT varIndex;
  509. varIndex.vt = VT_BSTR;
  510. varIndex.bstrVal = SysAllocString(STR_PT_WEBBASED);
  511. if (varIndex.bstrVal)
  512. {
  513. IMailProtocolADEntry * pMailProtocol;
  514. if (SUCCEEDED(_pMailAutoDiscovery->get_item(varIndex, &pMailProtocol)))
  515. {
  516. // Yes, web bases mail is supported. So remember that for later.
  517. pEmailServerSettings->fUseWebMail = TRUE;
  518. hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer1Name);
  519. pMailProtocol->Release();
  520. }
  521. VariantClear(&varIndex);
  522. }
  523. }
  524. if (FAILED(hr) && (-1 == pEmailServerSettings->nProtocol))
  525. {
  526. // Did the server provide an INFO URL for the user?
  527. hr = _pMailAutoDiscovery->get_InfoURL(&pEmailServerSettings->bstrInfoURL);
  528. if (SUCCEEDED(hr))
  529. {
  530. pEmailServerSettings->fDisplayInfoURL = TRUE;
  531. }
  532. }
  533. return hr;
  534. }
  535. /****************************************************\
  536. Constructor
  537. \****************************************************/
  538. CAutoDiscoveryHelper::CAutoDiscoveryHelper()
  539. {
  540. DllAddRef();
  541. // ASSERT zero initialized because we can only be created in the heap. (Private destructor)
  542. _hwndDlgParent = NULL;
  543. _szNextText[0] = 0;
  544. _pMailAutoDiscovery = NULL;
  545. _hInstAutoDisc = NULL;
  546. }
  547. /****************************************************\
  548. Destructor
  549. \****************************************************/
  550. CAutoDiscoveryHelper::~CAutoDiscoveryHelper()
  551. {
  552. if (_pMailAutoDiscovery)
  553. {
  554. _pMailAutoDiscovery->Release();
  555. _pMailAutoDiscovery = NULL;
  556. }
  557. if (_hInstAutoDisc)
  558. {
  559. FreeLibrary(_hInstAutoDisc);
  560. }
  561. DllRelease();
  562. }
  563. //===========================
  564. // *** Public APIs ***
  565. //===========================
  566. BOOL CALLBACK AutoDiscoveryInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
  567. {
  568. if (fFirstInit)
  569. {
  570. g_fRequestCancelled = TRUE;
  571. g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
  572. }
  573. if (!g_pAutoDiscoveryObject)
  574. {
  575. Assert(!g_pAutoDiscoveryObject);
  576. g_pAutoDiscoveryObject = new CAutoDiscoveryHelper();
  577. if (g_pAutoDiscoveryObject)
  578. {
  579. g_pAutoDiscoveryObject->StartAutoDiscovery(pApp, hDlg, fFirstInit);
  580. }
  581. }
  582. return TRUE;
  583. }
  584. BOOL CALLBACK AutoDiscoveryOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
  585. {
  586. g_fRequestCancelled = TRUE;
  587. if (fForward)
  588. {
  589. *puNextPage = g_uNextPage;
  590. }
  591. else
  592. {
  593. // If we have the passifier page turned off, we want to skip that page.
  594. if (!SHRegGetBoolUSValue(SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_PASSIFIER, FALSE, TRUE))
  595. {
  596. *puNextPage = ORD_PAGE_AD_MAILADDRESS;
  597. }
  598. }
  599. ADRestoreNextButton(pApp, hDlg);
  600. g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
  601. return(TRUE);
  602. }
  603. BOOL CALLBACK AutoDiscoveryCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
  604. {
  605. return(TRUE);
  606. }
  607. BOOL CALLBACK AutoDiscoveryWMUserProc(CICWApprentice *pApp, HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  608. {
  609. switch (uMsg)
  610. {
  611. case WM_AUTODISCOVERY_FINISHED:
  612. if (FALSE == g_fRequestCancelled)
  613. {
  614. // This is WM_AUTODISCOVERY_FINISHED
  615. BSTR bstXML = (BSTR) lParam;
  616. HRESULT hrAutoDiscoverySucceeded = (HRESULT) wParam;
  617. if (bstXML)
  618. {
  619. SysFreeString(bstXML); // We don't need the XML. This works if NULL
  620. }
  621. if (SUCCEEDED(hrAutoDiscoverySucceeded))
  622. {
  623. OnADCompleted(pApp, hDlg);
  624. }
  625. // Go to the next page.
  626. ADRestoreNextButton(pApp, hDlg);
  627. PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
  628. }
  629. break;
  630. case WM_AUTODISCOVERY_STATUSMSG:
  631. {
  632. // This is WM_AUTODISCOVERY_STATUSMSG
  633. LPWSTR pwzStatusMsg = (BSTR) wParam;
  634. if (pwzStatusMsg)
  635. {
  636. HWND hwndStatusText = GetDlgItem(hDlg, IDC_AUTODISCOVERY_STATUS);
  637. if (hwndStatusText)
  638. {
  639. SetWindowTextW(hwndStatusText, pwzStatusMsg);
  640. }
  641. LocalFree(pwzStatusMsg);
  642. }
  643. }
  644. break;
  645. }
  646. return(TRUE);
  647. }
  648. BOOL CALLBACK AutoDiscoveryCancelProc(CICWApprentice *pApp, HWND hDlg)
  649. {
  650. // This call will clean up our state and retore the back button.
  651. ADRestoreNextButton(pApp, hDlg);
  652. g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
  653. return TRUE;
  654. }
  655. typedef BOOL (* PFN_LINKWINDOW_REGISTERCLASS) (void);
  656. typedef BOOL (* PFN_LINKWINDOW_UNREGISTERCLASS) (IN HINSTANCE hInst);
  657. #define ORD_LINKWINDOW_REGISTERCLASS 258
  658. #define ORD_LINKWINDOW_UNREGISTERCLASS 259
  659. BOOL LinkWindow_RegisterClass_DelayLoad(void)
  660. {
  661. BOOL returnValue = FALSE;
  662. // Delay load the SHELL32.DLL export (ordinal #258). This only works on Win2k and later.
  663. HINSTANCE hInstSHELL32 = LoadLibrary(TEXT("SHELL32.DLL"));
  664. if (hInstSHELL32)
  665. {
  666. PFN_LINKWINDOW_REGISTERCLASS pfnDelayLoad = (PFN_LINKWINDOW_REGISTERCLASS)GetProcAddress(hInstSHELL32, (LPCSTR)ORD_LINKWINDOW_REGISTERCLASS);
  667. if (pfnDelayLoad)
  668. {
  669. returnValue = pfnDelayLoad();
  670. }
  671. FreeLibrary(hInstSHELL32);
  672. }
  673. return returnValue;
  674. }
  675. void LinkWindow_UnregisterClass_DelayLoad(IN HINSTANCE hInst)
  676. {
  677. // Delay load the SHELL32.DLL export (ordinal #259). This only works on Win2k and later.
  678. HINSTANCE hInstSHELL32 = LoadLibrary(TEXT("SHELL32.DLL"));
  679. if (hInstSHELL32)
  680. {
  681. PFN_LINKWINDOW_UNREGISTERCLASS pfnDelayLoad = (PFN_LINKWINDOW_UNREGISTERCLASS)GetProcAddress(hInstSHELL32, (LPCSTR)ORD_LINKWINDOW_UNREGISTERCLASS);
  682. if (pfnDelayLoad)
  683. {
  684. BOOL returnValue = pfnDelayLoad(hInst);
  685. }
  686. FreeLibrary(hInstSHELL32);
  687. }
  688. }
  689. #define LINKWINDOW_CLASSW L"Link Window"
  690. BOOL IsOSNT(void)
  691. {
  692. OSVERSIONINFOA osVerInfoA;
  693. osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
  694. if (!GetVersionExA(&osVerInfoA))
  695. return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
  696. return (VER_PLATFORM_WIN32_NT == osVerInfoA.dwPlatformId);
  697. }
  698. DWORD GetOSVer(void)
  699. {
  700. OSVERSIONINFOA osVerInfoA;
  701. osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
  702. if (!GetVersionExA(&osVerInfoA))
  703. return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
  704. return osVerInfoA.dwMajorVersion;
  705. }
  706. HRESULT ConvertTextToLinkWindow(HWND hDlg, int idControl, int idStringID)
  707. {
  708. WCHAR szTempString[MAX_URL_STRING];
  709. HRESULT hr = S_OK;
  710. HWND hwndText = GetDlgItem(hDlg, idControl);
  711. RECT rcWindow;
  712. HMENU hMenu = (HMENU)IntToPtr(idControl + 10);
  713. LoadStringW(g_hInstRes, idStringID, szTempString, ARRAYSIZE(szTempString));
  714. GetClientRect(hwndText, &rcWindow);
  715. MapWindowPoints(hwndText, hDlg, (POINT*)&rcWindow, 2);
  716. HWND hwndLink = CreateWindowW(LINKWINDOW_CLASSW, szTempString, (WS_TABSTOP | WS_CHILDWINDOW),
  717. rcWindow.left, rcWindow.top, RECTWIDTH(rcWindow), RECTHEIGHT(rcWindow), hDlg, hMenu, g_hInstRes, NULL);
  718. DWORD dwError = GetLastError(); //todo;
  719. if (hwndLink)
  720. {
  721. SetWindowTextW(hwndLink, szTempString);
  722. ShowWindow(hwndLink, SW_SHOW);
  723. }
  724. EnableWindow(hwndText, FALSE);
  725. ShowWindow(hwndText, SW_HIDE);
  726. return hr;
  727. }
  728. HRESULT GetEmailAddress(CICWApprentice *pApp, LPSTR pszEmailAddress, int cchSize)
  729. {
  730. ACCTDATA * pData = pApp->GetAccountData();
  731. StrCpyNA(pszEmailAddress, "", cchSize); // Initialize the string to empty.
  732. if (pData && pData->szEmail)
  733. {
  734. StrCpyNA(pszEmailAddress, pData->szEmail, cchSize); // Initialize the string to empty.
  735. }
  736. return S_OK;
  737. }
  738. HRESULT GetEmailAddressDomain(CICWApprentice *pApp, LPSTR pszEmailAddress, int cchSize)
  739. {
  740. ACCTDATA * pData = pApp->GetAccountData();
  741. StrCpyNA(pszEmailAddress, "", cchSize); // Initialize the string to empty.
  742. if (pData && pData->szEmail)
  743. {
  744. LPCSTR pszEmailDomain = StrChrA(pData->szEmail, CH_EMAILDOMAINSEPARATOR);
  745. if (pszEmailDomain)
  746. {
  747. StrCpyNA(pszEmailAddress, CharNext(pszEmailDomain), cchSize); // Initialize the string to empty.
  748. }
  749. }
  750. return S_OK;
  751. }
  752. BOOL CALLBACK TheInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit, int idControlFirst, LPWSTR pszURL, int cchURLSize)
  753. {
  754. BOOL fReset = fFirstInit;
  755. if (!fReset)
  756. {
  757. WCHAR szPreviousURL[MAX_URL_STRING];
  758. GetWindowTextW(GetDlgItem(hDlg, idControlFirst+1), szPreviousURL, ARRAYSIZE(szPreviousURL));
  759. // If the URL has changed, we need to reload the info.
  760. if (StrCmpIW(pszURL, szPreviousURL))
  761. {
  762. DestroyWindow(GetDlgItem(hDlg, idControlFirst+1+10));
  763. DestroyWindow(GetDlgItem(hDlg, idControlFirst+2+10));
  764. fReset = TRUE;
  765. }
  766. }
  767. if (fReset)
  768. {
  769. // TODO: This won't work on downlevel. So use plain text.
  770. BOOL fLinksSupported = LinkWindow_RegisterClass_DelayLoad();
  771. TCHAR szTempStr1[MAX_URL_STRING*3];
  772. TCHAR szTempStr2[MAX_URL_STRING*3];
  773. CHAR szTempStr3[MAX_PATH];
  774. // Replace the %s in the first line to the domain name.
  775. GetWindowText(GetDlgItem(hDlg, idControlFirst), szTempStr1, ARRAYSIZE(szTempStr1));
  776. GetEmailAddress(pApp, szTempStr3, ARRAYSIZE(szTempStr3));
  777. wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, szTempStr3, szTempStr3);
  778. SetWindowText(GetDlgItem(hDlg, idControlFirst), szTempStr2);
  779. SetWindowTextW(GetDlgItem(hDlg, idControlFirst+1), pszURL);
  780. // We only support Win2k and later because we don't want to worry about
  781. // the fact that the "LinkWindow" class doesn't have an "W" and "A" version.
  782. if (fLinksSupported && IsOSNT() && (5 <= GetOSVer()))
  783. {
  784. ConvertTextToLinkWindow(hDlg, idControlFirst+1, idsADURLLink);
  785. ConvertTextToLinkWindow(hDlg, idControlFirst+2, idsADUseWebMsg);
  786. // Replace the %s in the second line to the URL.
  787. GetWindowText(GetDlgItem(hDlg, idControlFirst+1+10), szTempStr1, ARRAYSIZE(szTempStr1));
  788. wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, pszURL, pszURL);
  789. SetWindowText(GetDlgItem(hDlg, idControlFirst+1+10), szTempStr2);
  790. // Set the hyperlink URL in the Click here link.
  791. GetWindowText(GetDlgItem(hDlg, idControlFirst+2+10), szTempStr1, ARRAYSIZE(szTempStr1));
  792. wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, pszURL);
  793. SetWindowText(GetDlgItem(hDlg, idControlFirst+2+10), szTempStr2);
  794. }
  795. }
  796. return TRUE;
  797. }
  798. BOOL CALLBACK UseWebMailInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
  799. {
  800. return TheInitProc(pApp, hDlg, fFirstInit, IDC_USEWEB_LINE1, g_szWebMailURL, ARRAYSIZE(g_szWebMailURL));
  801. }
  802. BOOL CALLBACK UseWebMailOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
  803. {
  804. if (fForward)
  805. {
  806. *puNextPage = ORD_PAGE_AD_MAILSERVER;
  807. }
  808. else
  809. {
  810. *puNextPage = ORD_PAGE_AD_MAILADDRESS;
  811. }
  812. LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
  813. return(TRUE);
  814. }
  815. BOOL CALLBACK UseWebMailCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
  816. {
  817. LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
  818. return(TRUE);
  819. }
  820. BOOL CALLBACK GotoServerInfoInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
  821. {
  822. return TheInitProc(pApp, hDlg, fFirstInit, IDC_GETINFO_LINE1, g_szInfoURL, ARRAYSIZE(g_szInfoURL));
  823. }
  824. BOOL CALLBACK GotoServerInfoOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
  825. {
  826. if (fForward)
  827. {
  828. *puNextPage = ORD_PAGE_AD_MAILSERVER;
  829. }
  830. else
  831. {
  832. *puNextPage = ORD_PAGE_AD_MAILADDRESS;
  833. }
  834. return(TRUE);
  835. }
  836. BOOL CALLBACK GotoServerInfoCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
  837. {
  838. LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
  839. return(TRUE);
  840. }
  841. BOOL CALLBACK PassifierInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
  842. {
  843. TCHAR szTemplate[1024];
  844. TCHAR szPrivacyText[1024];
  845. TCHAR szEmail[MAX_PATH];
  846. TCHAR szDomain[MAX_PATH];
  847. if (FAILED(GetEmailAddressDomain(pApp, szDomain, ARRAYSIZE(szDomain))))
  848. {
  849. szDomain[0] = 0;
  850. }
  851. // Set the next text.
  852. LoadString(g_hInstRes, ids_ADPassifier_Warning, szTemplate, ARRAYSIZE(szTemplate));
  853. wnsprintf(szPrivacyText, ARRAYSIZE(szPrivacyText), szTemplate, szDomain);
  854. SetWindowText(GetDlgItem(hDlg, IDC_PASSIFIER_PRIVACYWARNING), szPrivacyText);
  855. // Load up the list boxes
  856. IMailAutoDiscovery * pMailAutoDiscovery;
  857. HWND hwndListBox;
  858. if (FAILED(GetEmailAddress(pApp, szEmail, ARRAYSIZE(szEmail))))
  859. {
  860. szEmail[0] = 0;
  861. }
  862. HRESULT hr = CoCreateInstance(CLSID_MailAutoDiscovery, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMailAutoDiscovery, &pMailAutoDiscovery));
  863. if (SUCCEEDED(hr))
  864. {
  865. IAutoDiscoveryProvider * pProviders;
  866. BSTR bstrEmail = SysAllocStringA(szEmail);
  867. hr = pMailAutoDiscovery->getPrimaryProviders(bstrEmail, &pProviders);
  868. if (SUCCEEDED(hr))
  869. {
  870. long nTotal = 0;
  871. VARIANT varIndex;
  872. hwndListBox = GetDlgItem(hDlg, IDC_PASSIFIER_PRIMARYLIST);
  873. if (hwndListBox)
  874. {
  875. varIndex.vt = VT_I4;
  876. pProviders->get_length(&nTotal);
  877. for (varIndex.lVal = 0; (varIndex.lVal < nTotal) && (varIndex.lVal <= 3); varIndex.lVal++)
  878. {
  879. BSTR bstrDomain;
  880. if (SUCCEEDED(pProviders->get_item(varIndex, &bstrDomain)))
  881. {
  882. CHAR szDomain[MAX_PATH];
  883. SHUnicodeToAnsi(bstrDomain, szDomain, ARRAYSIZE(szDomain));
  884. SetWindowTextA(GetDlgItem(hDlg, IDC_PASSIFIER_PRIMARYLIST + varIndex.lVal), szDomain);
  885. SysFreeString(bstrDomain);
  886. }
  887. }
  888. }
  889. pProviders->Release();
  890. }
  891. hr = pMailAutoDiscovery->getSecondaryProviders(bstrEmail, &pProviders);
  892. if (SUCCEEDED(hr))
  893. {
  894. long nTotal = 0;
  895. VARIANT varIndex;
  896. hwndListBox = GetDlgItem(hDlg, IDC_PASSIFIER_SECONDARYLIST);
  897. if (hwndListBox)
  898. {
  899. varIndex.vt = VT_I4;
  900. pProviders->get_length(&nTotal);
  901. for (varIndex.lVal = 0; (varIndex.lVal < nTotal) && (varIndex.lVal <= 3); varIndex.lVal++)
  902. {
  903. BSTR bstrURL; // The secondary servers are URLs
  904. if (SUCCEEDED(pProviders->get_item(varIndex, &bstrURL)))
  905. {
  906. CHAR szURL[MAX_PATH];
  907. CHAR szDomain[MAX_PATH];
  908. DWORD cchSize = ARRAYSIZE(szDomain);
  909. SHUnicodeToAnsi(bstrURL, szURL, ARRAYSIZE(szURL));
  910. UrlGetPart(szURL, szDomain, &cchSize, URL_PART_HOSTNAME, 0);
  911. SetWindowTextA(GetDlgItem(hDlg, IDC_PASSIFIER_SECONDARYLIST + varIndex.lVal), szDomain);
  912. SysFreeString(bstrURL);
  913. }
  914. }
  915. }
  916. pProviders->Release();
  917. }
  918. SysFreeString(bstrEmail);
  919. pMailAutoDiscovery->Release();
  920. }
  921. // Set the manual checkbox
  922. BOOL fManuallyConfigure = SHRegGetBoolUSValue(SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_OEMANUAL, FALSE, FALSE);
  923. CheckDlgButton(hDlg, IDC_PASSIFIER_SKIPCHECKBOX, (fManuallyConfigure ? BST_CHECKED : BST_UNCHECKED));
  924. return TRUE;
  925. }
  926. #define SZ_TRUE TEXT("TRUE")
  927. #define SZ_FALSE TEXT("FALSE")
  928. BOOL CALLBACK PassifierOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
  929. {
  930. if (fForward)
  931. {
  932. BOOL fManuallyConfigure = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_PASSIFIER_SKIPCHECKBOX));
  933. SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_OEMANUAL, REG_SZ,
  934. (LPCVOID)(fManuallyConfigure ? SZ_TRUE : SZ_FALSE), (fManuallyConfigure ? sizeof(SZ_TRUE) : sizeof(SZ_FALSE)));
  935. *puNextPage = (fManuallyConfigure ? ORD_PAGE_AD_MAILSERVER : ORD_PAGE_AD_AUTODISCOVERY);
  936. }
  937. else
  938. {
  939. *puNextPage = ORD_PAGE_AD_MAILADDRESS;
  940. }
  941. return TRUE;
  942. }
  943. BOOL CALLBACK PassifierCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
  944. {
  945. return TRUE;
  946. }