Windows2003-3790/inetcore/outlookexpress/msoeacct/autodiscovery.cpp
2020-09-30 16:53:55 +02:00

1222 lines
40 KiB
C++

/*****************************************************************************\
FILE: AutoDiscovery.cpp
DESCRIPTION:
This is AutoDiscovery progress UI for the Outlook Express's email
configuration wizard.
BryanSt 1/18/2000
Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
\*****************************************************************************/
#include "pch.hxx"
#include <prsht.h>
#include <imnact.h>
#include <icwacct.h>
#include <acctimp.h>
#include "icwwiz.h"
#include "acctui.h"
#include "acctman.h"
#include <dllmain.h>
#include <resource.h>
#include "server.h"
#include "connect.h"
#include <Shlwapi.h>
#include "shlwapip.h"
#include "strconst.h"
#include "demand.h"
#include "hotwiz.h"
#include "shared.h"
#include <AutoDiscovery.h>
#include "AutoDiscoveryUI.h"
ASSERTDATA
#define RECTWIDTH(rect) (rect.right - rect.left)
#define RECTHEIGHT(rect) (rect.bottom - rect.top)
#define MAX_URL_STRING 2048
#define SIZE_STR_AUTODISC_DESC 2048
// These are the wizard control IDs for the Back, Next, and Finished buttons.
#define IDD_WIZARD_BACK_BUTTON 0x3023
#define IDD_WIZARD_NEXT_BUTTON 0x3024
#define IDD_WIZARD_FINISH_BUTTON 0x3025
#define SZ_DLL_AUTODISC TEXT("autodisc.dll")
#define IDA_DOWNLOADINGSETTINGS 801 // In autodisc.dll
#define ATOMICRELEASE(punk) {if (punk) { punk->Release(); punk = NULL;} }
WCHAR g_szInfoURL[MAX_URL_STRING] = {0};
WCHAR g_szWebMailURL[MAX_URL_STRING] = {0};
typedef struct
{
// Default Protocol (POP3, IMAP, DAV, WEB)
int nProtocol; // What is the email protocol? POP3 vs. IMAP vs. DAV vs. WEB
BSTR bstrDisplayName; // What is the user's display name.
BSTR bstrServer1Name; // What is the downloading email server name (POP3, IMAP, DAV, or WEB)
int nServer1Port; // What is that server's port number?
BSTR bstrLoginName; // What is the login name for the POP3 server. (Normall the same as the email address w/out the domain)
BOOL fUsesSSL; // Use SSL when connecting to the POP3 or IMAP server?
BOOL fUsesSPA; // Use SPA when connecting to the POP3 or IMAP server?
// SMTP Protocol (If used)
BSTR bstrServer2Name; // What is the uploading email server name (SMTP)
int nServer2Port; // What is that server's port number?
BOOL fSMTPUsesSSL; // Use SSL when connecting to the SMTP server?
BOOL fAuthSMTP; // Does SMTP need Authentication?
BOOL fAuthSMTPPOP; // Use POP3's auth for SMTP?
BOOL fAuthSMTPSPA; // Use SPA auth for SMTP?
BOOL fUseWebMail; // Is Web Bassed mail the only protocol we recognizer?
BSTR bstrSMTPLoginName; // What is the login name for the SMTP server.
BOOL fDisplayInfoURL; // Is there an URL for Info about the email server/services?
BSTR bstrInfoURL; // If fDisplayInfoURL, this is the URL.
} EMAIL_SERVER_SETTINGS;
class CICWApprentice;
/*****************************************************************************\
Class: CAutoDiscoveryHelper
DESCRIPTION:
StartAutoDiscovery:
hwndParent: This is the caller's hwnd. If we need to display UI, we
will parent it off this hwnd. We also send this hwnd messages on
progress.
\*****************************************************************************/
class CAutoDiscoveryHelper
{
public:
// Public Methods
HRESULT StartAutoDiscovery(IN CICWApprentice *pApp, IN HWND hDlg, IN BOOL fFirstInit);
HRESULT OnCompleted(IN CICWApprentice *pApp, IN ACCTDATA * pData);
HRESULT SetNextButton(HWND hwndButton);
HRESULT RestoreNextButton(HWND hwndButton);
CAutoDiscoveryHelper();
~CAutoDiscoveryHelper(void);
private:
// Private Member Variables
// Other internal state.
HWND _hwndDlgParent; // parent window for message boxes
TCHAR _szNextText[MAX_PATH]; //
IMailAutoDiscovery * _pMailAutoDiscovery; //
HINSTANCE _hInstAutoDisc; // We use this to get the animation
// Private Member Functions
HRESULT _GetAccountInformation(EMAIL_SERVER_SETTINGS * pEmailServerSettings);
};
CAutoDiscoveryHelper * g_pAutoDiscoveryObject = NULL; // This is the AutoDisc obj used while downloading the settings.
BOOL g_fRequestCancelled = TRUE;
UINT g_uNextPage = ORD_PAGE_AD_MAILNAME; // ORD_PAGE_AD_MAILNAME, ORD_PAGE_AD_MAILSERVER, ORD_PAGE_AD_USEWEBMAIL, ORD_PAGE_AD_GOTOSERVERINFO
//===========================
// *** Class Internals & Helpers ***
//===========================
HRESULT FreeEmailServerSettings(EMAIL_SERVER_SETTINGS * pEmailServerSettings)
{
SysFreeString(pEmailServerSettings->bstrDisplayName); // It's okay to pass NULL to this API
SysFreeString(pEmailServerSettings->bstrServer1Name);
SysFreeString(pEmailServerSettings->bstrLoginName);
SysFreeString(pEmailServerSettings->bstrServer2Name);
SysFreeString(pEmailServerSettings->bstrSMTPLoginName);
SysFreeString(pEmailServerSettings->bstrInfoURL);
return S_OK;
}
BSTR SysAllocStringA(LPCSTR pszStr)
{
BSTR bstrOut = NULL;
if (pszStr)
{
DWORD cchSize = (lstrlenA(pszStr) + 1);
LPWSTR pwszThunkTemp = (LPWSTR) LocalAlloc(LPTR, (sizeof(pwszThunkTemp[0]) * cchSize)); // assumes INFOTIPSIZE number of chars max
if (pwszThunkTemp)
{
SHAnsiToUnicode(pszStr, pwszThunkTemp, cchSize);
bstrOut = SysAllocString(pwszThunkTemp);
LocalFree(pwszThunkTemp);
}
}
return bstrOut;
}
HRESULT ADRestoreNextButton(CICWApprentice *pApp, HWND hDlg)
{
HRESULT hr = S_OK;
g_fRequestCancelled = TRUE;
if (g_pAutoDiscoveryObject)
{
g_pAutoDiscoveryObject->RestoreNextButton(GetDlgItem(GetParent(hDlg), IDD_WIZARD_NEXT_BUTTON));
delete g_pAutoDiscoveryObject;
g_pAutoDiscoveryObject = NULL;
}
return hr;
}
HRESULT CreateAccountName(IN CICWApprentice *pApp, IN ACCTDATA * pData);
HRESULT OnADCompleted(CICWApprentice *pApp, HWND hDlg)
{
HRESULT hr = E_OUTOFMEMORY;
if (g_pAutoDiscoveryObject)
{
ACCTDATA * pData = pApp->GetAccountData();
hr = g_pAutoDiscoveryObject->OnCompleted(pApp, pData);
if (SUCCEEDED(hr))
{
// Set the display name for the account.
CreateAccountName(pApp, pData);
}
else
{
// TODO: If _fUseWebMail is set, we will probably want
// to navigate to a page telling the user to use a web
// page to get their email.
}
}
return hr;
}
#define SZ_HOTMAILDOMAIN "@hotmail.com"
#define CH_EMAILDOMAINSEPARATOR '@'
HRESULT CAutoDiscoveryHelper::StartAutoDiscovery(IN CICWApprentice *pApp, IN HWND hDlg, IN BOOL fFirstInit)
{
HRESULT hr = E_OUTOFMEMORY;
ACCTDATA * pData = pApp->GetAccountData();
if (pData && pData->szEmail)
{
LPCSTR pszEmailDomain = StrChrA(pData->szEmail, CH_EMAILDOMAINSEPARATOR);
if (pszEmailDomain && !StrCmpI(SZ_HOTMAILDOMAIN, pszEmailDomain)) // Is this a HOTMAIL.COM account?
{
// Yes, so skip AutoDiscovery since we don't require the user
// to enter hard settings in that case. (Protocol and server settings never
// change)
hr = HRESULT_FROM_WIN32(ERROR_CANCELLED);
}
else
{
WCHAR szEmail[1024];
SHAnsiToUnicode(pData->szEmail, szEmail, ARRAYSIZE(szEmail));
_hwndDlgParent = hDlg;
// Set Animation.
HWND hwndAnimation = GetDlgItem(hDlg, IDC_AUTODISCOVERY_ANIMATION);
if (hwndAnimation)
{
_hInstAutoDisc = LoadLibrary(SZ_DLL_AUTODISC);
if (_hInstAutoDisc)
{
Animate_OpenEx(hwndAnimation, _hInstAutoDisc, IDA_DOWNLOADINGSETTINGS);
}
}
HWND hwndWizard = GetParent(hDlg);
if (hwndWizard)
{
SetNextButton(GetDlgItem(hwndWizard, IDD_WIZARD_NEXT_BUTTON));
}
ATOMICRELEASE(_pMailAutoDiscovery);
// Start the background task.
hr = CoCreateInstance(CLSID_MailAutoDiscovery, NULL, CLSCTX_INPROC_SERVER, IID_IMailAutoDiscovery, (void **)&_pMailAutoDiscovery);
if (SUCCEEDED(hr))
{
hr = _pMailAutoDiscovery->WorkAsync(hDlg, WM_AUTODISCOVERY_FINISHED);
if (SUCCEEDED(hr))
{
BSTR bstrEmail = SysAllocString(szEmail);
if (bstrEmail)
{
hr = _pMailAutoDiscovery->DiscoverMail(bstrEmail);
if (SUCCEEDED(hr))
{
g_fRequestCancelled = FALSE;
}
SysFreeString(bstrEmail);
}
else
{
hr = E_OUTOFMEMORY;
}
}
}
}
}
else
{
hr = E_FAIL;
}
if (FAILED(hr))
{
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
}
return hr;
}
HRESULT CAutoDiscoveryHelper::SetNextButton(HWND hwndButton)
{
HRESULT hr = S_OK;
TCHAR szSkipButton[MAX_PATH];
// First, change the "Next" button into "Skip"
// Save the text on the next button before we rename it.
if (hwndButton && !GetWindowText(hwndButton, _szNextText, ARRAYSIZE(_szNextText)))
{
_szNextText[0] = 0; // terminate string in failure case.
}
// Set the next text.
LoadString(g_hInstRes, idsADSkipButton, szSkipButton, ARRAYSIZE(szSkipButton));
SetWindowText(hwndButton, szSkipButton);
return hr;
}
HRESULT CAutoDiscoveryHelper::RestoreNextButton(HWND hwndButton)
{
HRESULT hr = S_OK;
if (_szNextText[0])
{
// Restore the Next button text.
SetWindowText(hwndButton, _szNextText);
}
return hr;
}
/****************************************************\
DESCRIPTION:
\****************************************************/
HRESULT CAutoDiscoveryHelper::OnCompleted(IN CICWApprentice *pApp, IN ACCTDATA *pData)
{
// Step 1. Get all the settings from IMailAutoDiscovery to EMAIL_SERVER_SETTINGS
EMAIL_SERVER_SETTINGS emailServerSettings = {0};
emailServerSettings.nProtocol = -1;
emailServerSettings.nServer1Port = -1;
emailServerSettings.nServer2Port = -1;
HRESULT hr = _GetAccountInformation(&emailServerSettings);
g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
// Did the AutoDiscovery process succeed?
if (SUCCEEDED(hr))
{
if (emailServerSettings.fDisplayInfoURL)
{
g_uNextPage = ORD_PAGE_AD_GOTOSERVERINFO;
StrCpyNW(g_szInfoURL, emailServerSettings.bstrInfoURL, ARRAYSIZE(g_szInfoURL));
}
else if (emailServerSettings.fUseWebMail)
{
g_uNextPage = ORD_PAGE_AD_USEWEBMAIL;
StrCpyNW(g_szWebMailURL, emailServerSettings.bstrServer1Name, ARRAYSIZE(g_szWebMailURL));
}
else
{
g_uNextPage = ORD_PAGE_AD_MAILNAME;
if (pApp && pData && pApp->m_pAcct)
{
// Step 2. Move all the settings from EMAIL_SERVER_SETTINGS to the OE mail account (ACCTDATA).
IImnAccount * pAcct = pApp->m_pAcct;
pData->fLogon = FALSE; // BUGBUG: When is this needed? DAV?
pData->fSPA = emailServerSettings.fUsesSPA;
pData->fServerTypes = emailServerSettings.nProtocol;
Assert(!pData->fCreateNewAccount);
if (emailServerSettings.bstrDisplayName)
{
SHUnicodeToAnsi(emailServerSettings.bstrDisplayName, pData->szName, ARRAYSIZE(pData->szName));
}
if (emailServerSettings.bstrServer1Name)
{
SHUnicodeToAnsi(emailServerSettings.bstrServer1Name, pData->szSvr1, ARRAYSIZE(pData->szSvr1));
}
if (emailServerSettings.bstrLoginName)
{
SHUnicodeToAnsi(emailServerSettings.bstrLoginName, pData->szUsername, ARRAYSIZE(pData->szUsername));
}
if (emailServerSettings.nProtocol & (SRV_POP3 | SRV_IMAP))
{
pAcct->SetPropDw(((emailServerSettings.nProtocol & SRV_POP3) ? AP_POP3_SSL : AP_IMAP_SSL), emailServerSettings.fUsesSSL);
if (-1 != emailServerSettings.nServer1Port)
{
pAcct->SetPropDw(((emailServerSettings.nProtocol & SRV_POP3) ? AP_POP3_PORT : AP_IMAP_PORT), emailServerSettings.nServer1Port);
}
}
if (emailServerSettings.nProtocol & SRV_SMTP)
{
if (emailServerSettings.bstrServer2Name)
{
SHUnicodeToAnsi(emailServerSettings.bstrServer2Name, pData->szSvr2, ARRAYSIZE(pData->szSvr2));
}
if (-1 != emailServerSettings.nServer2Port)
{
pAcct->SetPropDw(AP_SMTP_PORT, emailServerSettings.nServer2Port);
}
pAcct->SetPropDw(AP_SMTP_SSL, emailServerSettings.fSMTPUsesSSL);
if (!emailServerSettings.fAuthSMTP)
{
pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_NONE);
}
else
{
if (emailServerSettings.fAuthSMTPPOP)
{
pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_USE_POP3ORIMAP_SETTINGS);
}
else
{
if (emailServerSettings.fAuthSMTPSPA)
{
pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_SICILY);
}
else
{
pAcct->SetPropDw(AP_SMTP_USE_SICILY, SMTP_AUTH_USE_SMTP_SETTINGS);
}
if (emailServerSettings.bstrSMTPLoginName)
{
TCHAR szSMTPUserName[CCHMAX_ACCT_PROP_SZ];
WideCharToMultiByte(CP_ACP, 0, emailServerSettings.bstrSMTPLoginName, -1, szSMTPUserName, ARRAYSIZE(szSMTPUserName), NULL, NULL);
pAcct->SetPropSz(AP_SMTP_USERNAME, szSMTPUserName);
}
pAcct->SetPropDw(AP_SMTP_PROMPT_PASSWORD, TRUE);
}
}
}
}
}
// Step 3. Free all the memory in EMAIL_SERVER_SETTINGS
FreeEmailServerSettings(&emailServerSettings);
}
return hr;
}
/****************************************************\
DESCRIPTION:
\****************************************************/
HRESULT CAutoDiscoveryHelper::_GetAccountInformation(EMAIL_SERVER_SETTINGS * pEmailServerSettings)
{
BSTR bstrPreferedProtocol;
HRESULT hr = S_OK;
// We ignore hr because getting the display name is optinal.
_pMailAutoDiscovery->get_DisplayName(&pEmailServerSettings->bstrDisplayName);
hr = _pMailAutoDiscovery->get_PreferedProtocolType(&bstrPreferedProtocol);
// Loop thru the list looking for the first instance of a protocol
// that we support.
if (StrCmpIW(bstrPreferedProtocol, STR_PT_POP) &&
StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) &&
StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL))
{
long nSize;
hr = _pMailAutoDiscovery->get_length(&nSize);
if (SUCCEEDED(hr))
{
VARIANT varIndex;
varIndex.vt = VT_I4;
SysFreeString(bstrPreferedProtocol);
for (long nIndex = 1; (nIndex < nSize); nIndex++)
{
IMailProtocolADEntry * pMailProtocol;
varIndex.lVal = nIndex;
if (SUCCEEDED(_pMailAutoDiscovery->get_item(varIndex, &pMailProtocol)))
{
hr = pMailProtocol->get_Protocol(&bstrPreferedProtocol);
pMailProtocol->Release();
pMailProtocol = NULL;
if (SUCCEEDED(hr))
{
// Is this protocol one of the ones we support?
if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
!StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) ||
!StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL))
{
hr = S_OK;
break;
}
SysFreeString(bstrPreferedProtocol);
bstrPreferedProtocol = NULL;
}
}
}
}
}
// TODO: Handle the Web Based mail case.
if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP)) pEmailServerSettings->nProtocol = (SRV_POP3 | SRV_SMTP);
else if (!StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP)) pEmailServerSettings->nProtocol = (SRV_IMAP | SRV_SMTP);
else if (!StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL)) pEmailServerSettings->nProtocol = SRV_HTTPMAIL;
// We need to reject Web Base Mail. In the future, we may want to give a page
// for them to launch the web browser to read their mail.
if (SUCCEEDED(hr) && bstrPreferedProtocol &&
(!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
!StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP) ||
!StrCmpIW(bstrPreferedProtocol, STR_PT_DAVMAIL)))
{
VARIANT varIndex;
IMailProtocolADEntry * pMailProtocol;
varIndex.vt = VT_BSTR;
varIndex.bstrVal = bstrPreferedProtocol;
hr = _pMailAutoDiscovery->get_item(varIndex, &pMailProtocol);
if (SUCCEEDED(hr))
{
hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer1Name);
if (SUCCEEDED(hr))
{
BSTR bstrPortNum;
// Having a custom port number is optional.
if (SUCCEEDED(pMailProtocol->get_ServerPort(&bstrPortNum)))
{
pEmailServerSettings->nServer1Port = StrToIntW(bstrPortNum);
SysFreeString(bstrPortNum);
}
if (SUCCEEDED(hr))
{
VARIANT_BOOL vfSPA = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_UseSPA(&vfSPA)))
{
pEmailServerSettings->fUsesSPA = (VARIANT_TRUE == vfSPA);
}
pMailProtocol->get_LoginName(&pEmailServerSettings->bstrLoginName);
}
VARIANT_BOOL vfSSL = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_UseSSL(&vfSSL)))
{
pEmailServerSettings->fUsesSSL = (VARIANT_TRUE == vfSSL);
}
}
pMailProtocol->Release();
}
// Is this one of the protocols that requires a second server?
if (!StrCmpIW(bstrPreferedProtocol, STR_PT_POP) ||
!StrCmpIW(bstrPreferedProtocol, STR_PT_IMAP))
{
varIndex.bstrVal = STR_PT_SMTP;
hr = _pMailAutoDiscovery->get_item(varIndex, &pMailProtocol);
if (SUCCEEDED(hr))
{
hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer2Name);
if (SUCCEEDED(hr))
{
BSTR bstrPortNum;
// Having a custom port number is optional.
if (SUCCEEDED(pMailProtocol->get_ServerPort(&bstrPortNum)))
{
pEmailServerSettings->nServer2Port = StrToIntW(bstrPortNum);
SysFreeString(bstrPortNum);
}
// TODO: Read in _fAuthSMTP and _fAuthSMTPPOP
VARIANT_BOOL vfSPA = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_UseSPA(&vfSPA)))
{
pEmailServerSettings->fAuthSMTPSPA = (VARIANT_TRUE == vfSPA);
}
VARIANT_BOOL vfAuthSMTP = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_IsAuthRequired(&vfAuthSMTP)))
{
pEmailServerSettings->fAuthSMTP = (VARIANT_TRUE == vfAuthSMTP);
}
VARIANT_BOOL vfAuthFromPOP = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_SMTPUsesPOP3Auth(&vfAuthFromPOP)))
{
pEmailServerSettings->fAuthSMTPPOP = (VARIANT_TRUE == vfAuthFromPOP);
}
VARIANT_BOOL vfSSL = VARIANT_FALSE;
if (SUCCEEDED(pMailProtocol->get_UseSSL(&vfSSL)))
{
pEmailServerSettings->fSMTPUsesSSL = (VARIANT_TRUE == vfSSL);
}
pMailProtocol->get_LoginName(&pEmailServerSettings->bstrSMTPLoginName);
}
pMailProtocol->Release();
}
}
SysFreeString(bstrPreferedProtocol);
}
if (SUCCEEDED(hr) && (-1 == pEmailServerSettings->nProtocol))
{
hr = E_FAIL;
}
if (FAILED(hr) && (-1 == pEmailServerSettings->nProtocol))
{
// Does this email account work with web based email?
VARIANT varIndex;
varIndex.vt = VT_BSTR;
varIndex.bstrVal = SysAllocString(STR_PT_WEBBASED);
if (varIndex.bstrVal)
{
IMailProtocolADEntry * pMailProtocol;
if (SUCCEEDED(_pMailAutoDiscovery->get_item(varIndex, &pMailProtocol)))
{
// Yes, web bases mail is supported. So remember that for later.
pEmailServerSettings->fUseWebMail = TRUE;
hr = pMailProtocol->get_ServerName(&pEmailServerSettings->bstrServer1Name);
pMailProtocol->Release();
}
VariantClear(&varIndex);
}
}
if (FAILED(hr) && (-1 == pEmailServerSettings->nProtocol))
{
// Did the server provide an INFO URL for the user?
hr = _pMailAutoDiscovery->get_InfoURL(&pEmailServerSettings->bstrInfoURL);
if (SUCCEEDED(hr))
{
pEmailServerSettings->fDisplayInfoURL = TRUE;
}
}
return hr;
}
/****************************************************\
Constructor
\****************************************************/
CAutoDiscoveryHelper::CAutoDiscoveryHelper()
{
DllAddRef();
// ASSERT zero initialized because we can only be created in the heap. (Private destructor)
_hwndDlgParent = NULL;
_szNextText[0] = 0;
_pMailAutoDiscovery = NULL;
_hInstAutoDisc = NULL;
}
/****************************************************\
Destructor
\****************************************************/
CAutoDiscoveryHelper::~CAutoDiscoveryHelper()
{
if (_pMailAutoDiscovery)
{
_pMailAutoDiscovery->Release();
_pMailAutoDiscovery = NULL;
}
if (_hInstAutoDisc)
{
FreeLibrary(_hInstAutoDisc);
}
DllRelease();
}
//===========================
// *** Public APIs ***
//===========================
BOOL CALLBACK AutoDiscoveryInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
{
if (fFirstInit)
{
g_fRequestCancelled = TRUE;
g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
}
if (!g_pAutoDiscoveryObject)
{
Assert(!g_pAutoDiscoveryObject);
g_pAutoDiscoveryObject = new CAutoDiscoveryHelper();
if (g_pAutoDiscoveryObject)
{
g_pAutoDiscoveryObject->StartAutoDiscovery(pApp, hDlg, fFirstInit);
}
}
return TRUE;
}
BOOL CALLBACK AutoDiscoveryOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
{
g_fRequestCancelled = TRUE;
if (fForward)
{
*puNextPage = g_uNextPage;
}
else
{
// If we have the passifier page turned off, we want to skip that page.
if (!SHRegGetBoolUSValue(SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_PASSIFIER, FALSE, TRUE))
{
*puNextPage = ORD_PAGE_AD_MAILADDRESS;
}
}
ADRestoreNextButton(pApp, hDlg);
g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
return(TRUE);
}
BOOL CALLBACK AutoDiscoveryCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
{
return(TRUE);
}
BOOL CALLBACK AutoDiscoveryWMUserProc(CICWApprentice *pApp, HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_AUTODISCOVERY_FINISHED:
if (FALSE == g_fRequestCancelled)
{
// This is WM_AUTODISCOVERY_FINISHED
BSTR bstXML = (BSTR) lParam;
HRESULT hrAutoDiscoverySucceeded = (HRESULT) wParam;
if (bstXML)
{
SysFreeString(bstXML); // We don't need the XML. This works if NULL
}
if (SUCCEEDED(hrAutoDiscoverySucceeded))
{
OnADCompleted(pApp, hDlg);
}
// Go to the next page.
ADRestoreNextButton(pApp, hDlg);
PropSheet_PressButton(GetParent(hDlg), PSBTN_NEXT);
}
break;
case WM_AUTODISCOVERY_STATUSMSG:
{
// This is WM_AUTODISCOVERY_STATUSMSG
LPWSTR pwzStatusMsg = (BSTR) wParam;
if (pwzStatusMsg)
{
HWND hwndStatusText = GetDlgItem(hDlg, IDC_AUTODISCOVERY_STATUS);
if (hwndStatusText)
{
SetWindowTextW(hwndStatusText, pwzStatusMsg);
}
LocalFree(pwzStatusMsg);
}
}
break;
}
return(TRUE);
}
BOOL CALLBACK AutoDiscoveryCancelProc(CICWApprentice *pApp, HWND hDlg)
{
// This call will clean up our state and retore the back button.
ADRestoreNextButton(pApp, hDlg);
g_uNextPage = ORD_PAGE_AD_MAILSERVER; // Assume we fail and we need to ask for the server settings.
return TRUE;
}
typedef BOOL (* PFN_LINKWINDOW_REGISTERCLASS) (void);
typedef BOOL (* PFN_LINKWINDOW_UNREGISTERCLASS) (IN HINSTANCE hInst);
#define ORD_LINKWINDOW_REGISTERCLASS 258
#define ORD_LINKWINDOW_UNREGISTERCLASS 259
BOOL LinkWindow_RegisterClass_DelayLoad(void)
{
BOOL returnValue = FALSE;
// Delay load the SHELL32.DLL export (ordinal #258). This only works on Win2k and later.
HINSTANCE hInstSHELL32 = LoadLibrary(TEXT("SHELL32.DLL"));
if (hInstSHELL32)
{
PFN_LINKWINDOW_REGISTERCLASS pfnDelayLoad = (PFN_LINKWINDOW_REGISTERCLASS)GetProcAddress(hInstSHELL32, (LPCSTR)ORD_LINKWINDOW_REGISTERCLASS);
if (pfnDelayLoad)
{
returnValue = pfnDelayLoad();
}
FreeLibrary(hInstSHELL32);
}
return returnValue;
}
void LinkWindow_UnregisterClass_DelayLoad(IN HINSTANCE hInst)
{
// Delay load the SHELL32.DLL export (ordinal #259). This only works on Win2k and later.
HINSTANCE hInstSHELL32 = LoadLibrary(TEXT("SHELL32.DLL"));
if (hInstSHELL32)
{
PFN_LINKWINDOW_UNREGISTERCLASS pfnDelayLoad = (PFN_LINKWINDOW_UNREGISTERCLASS)GetProcAddress(hInstSHELL32, (LPCSTR)ORD_LINKWINDOW_UNREGISTERCLASS);
if (pfnDelayLoad)
{
BOOL returnValue = pfnDelayLoad(hInst);
}
FreeLibrary(hInstSHELL32);
}
}
#define LINKWINDOW_CLASSW L"Link Window"
BOOL IsOSNT(void)
{
OSVERSIONINFOA osVerInfoA;
osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
if (!GetVersionExA(&osVerInfoA))
return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
return (VER_PLATFORM_WIN32_NT == osVerInfoA.dwPlatformId);
}
DWORD GetOSVer(void)
{
OSVERSIONINFOA osVerInfoA;
osVerInfoA.dwOSVersionInfoSize = sizeof(osVerInfoA);
if (!GetVersionExA(&osVerInfoA))
return VER_PLATFORM_WIN32_WINDOWS; // Default to this.
return osVerInfoA.dwMajorVersion;
}
HRESULT ConvertTextToLinkWindow(HWND hDlg, int idControl, int idStringID)
{
WCHAR szTempString[MAX_URL_STRING];
HRESULT hr = S_OK;
HWND hwndText = GetDlgItem(hDlg, idControl);
RECT rcWindow;
HMENU hMenu = (HMENU)IntToPtr(idControl + 10);
LoadStringW(g_hInstRes, idStringID, szTempString, ARRAYSIZE(szTempString));
GetClientRect(hwndText, &rcWindow);
MapWindowPoints(hwndText, hDlg, (POINT*)&rcWindow, 2);
HWND hwndLink = CreateWindowW(LINKWINDOW_CLASSW, szTempString, (WS_TABSTOP | WS_CHILDWINDOW),
rcWindow.left, rcWindow.top, RECTWIDTH(rcWindow), RECTHEIGHT(rcWindow), hDlg, hMenu, g_hInstRes, NULL);
DWORD dwError = GetLastError(); //todo;
if (hwndLink)
{
SetWindowTextW(hwndLink, szTempString);
ShowWindow(hwndLink, SW_SHOW);
}
EnableWindow(hwndText, FALSE);
ShowWindow(hwndText, SW_HIDE);
return hr;
}
HRESULT GetEmailAddress(CICWApprentice *pApp, LPSTR pszEmailAddress, int cchSize)
{
ACCTDATA * pData = pApp->GetAccountData();
StrCpyNA(pszEmailAddress, "", cchSize); // Initialize the string to empty.
if (pData && pData->szEmail)
{
StrCpyNA(pszEmailAddress, pData->szEmail, cchSize); // Initialize the string to empty.
}
return S_OK;
}
HRESULT GetEmailAddressDomain(CICWApprentice *pApp, LPSTR pszEmailAddress, int cchSize)
{
ACCTDATA * pData = pApp->GetAccountData();
StrCpyNA(pszEmailAddress, "", cchSize); // Initialize the string to empty.
if (pData && pData->szEmail)
{
LPCSTR pszEmailDomain = StrChrA(pData->szEmail, CH_EMAILDOMAINSEPARATOR);
if (pszEmailDomain)
{
StrCpyNA(pszEmailAddress, CharNext(pszEmailDomain), cchSize); // Initialize the string to empty.
}
}
return S_OK;
}
BOOL CALLBACK TheInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit, int idControlFirst, LPWSTR pszURL, int cchURLSize)
{
BOOL fReset = fFirstInit;
if (!fReset)
{
WCHAR szPreviousURL[MAX_URL_STRING];
GetWindowTextW(GetDlgItem(hDlg, idControlFirst+1), szPreviousURL, ARRAYSIZE(szPreviousURL));
// If the URL has changed, we need to reload the info.
if (StrCmpIW(pszURL, szPreviousURL))
{
DestroyWindow(GetDlgItem(hDlg, idControlFirst+1+10));
DestroyWindow(GetDlgItem(hDlg, idControlFirst+2+10));
fReset = TRUE;
}
}
if (fReset)
{
// TODO: This won't work on downlevel. So use plain text.
BOOL fLinksSupported = LinkWindow_RegisterClass_DelayLoad();
TCHAR szTempStr1[MAX_URL_STRING*3];
TCHAR szTempStr2[MAX_URL_STRING*3];
CHAR szTempStr3[MAX_PATH];
// Replace the %s in the first line to the domain name.
GetWindowText(GetDlgItem(hDlg, idControlFirst), szTempStr1, ARRAYSIZE(szTempStr1));
GetEmailAddress(pApp, szTempStr3, ARRAYSIZE(szTempStr3));
wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, szTempStr3, szTempStr3);
SetWindowText(GetDlgItem(hDlg, idControlFirst), szTempStr2);
SetWindowTextW(GetDlgItem(hDlg, idControlFirst+1), pszURL);
// We only support Win2k and later because we don't want to worry about
// the fact that the "LinkWindow" class doesn't have an "W" and "A" version.
if (fLinksSupported && IsOSNT() && (5 <= GetOSVer()))
{
ConvertTextToLinkWindow(hDlg, idControlFirst+1, idsADURLLink);
ConvertTextToLinkWindow(hDlg, idControlFirst+2, idsADUseWebMsg);
// Replace the %s in the second line to the URL.
GetWindowText(GetDlgItem(hDlg, idControlFirst+1+10), szTempStr1, ARRAYSIZE(szTempStr1));
wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, pszURL, pszURL);
SetWindowText(GetDlgItem(hDlg, idControlFirst+1+10), szTempStr2);
// Set the hyperlink URL in the Click here link.
GetWindowText(GetDlgItem(hDlg, idControlFirst+2+10), szTempStr1, ARRAYSIZE(szTempStr1));
wnsprintf(szTempStr2, ARRAYSIZE(szTempStr2), szTempStr1, pszURL);
SetWindowText(GetDlgItem(hDlg, idControlFirst+2+10), szTempStr2);
}
}
return TRUE;
}
BOOL CALLBACK UseWebMailInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
{
return TheInitProc(pApp, hDlg, fFirstInit, IDC_USEWEB_LINE1, g_szWebMailURL, ARRAYSIZE(g_szWebMailURL));
}
BOOL CALLBACK UseWebMailOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
{
if (fForward)
{
*puNextPage = ORD_PAGE_AD_MAILSERVER;
}
else
{
*puNextPage = ORD_PAGE_AD_MAILADDRESS;
}
LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
return(TRUE);
}
BOOL CALLBACK UseWebMailCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
{
LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
return(TRUE);
}
BOOL CALLBACK GotoServerInfoInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
{
return TheInitProc(pApp, hDlg, fFirstInit, IDC_GETINFO_LINE1, g_szInfoURL, ARRAYSIZE(g_szInfoURL));
}
BOOL CALLBACK GotoServerInfoOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
{
if (fForward)
{
*puNextPage = ORD_PAGE_AD_MAILSERVER;
}
else
{
*puNextPage = ORD_PAGE_AD_MAILADDRESS;
}
return(TRUE);
}
BOOL CALLBACK GotoServerInfoCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
{
LinkWindow_UnregisterClass_DelayLoad(g_hInstRes);
return(TRUE);
}
BOOL CALLBACK PassifierInitProc(CICWApprentice *pApp, HWND hDlg, BOOL fFirstInit)
{
TCHAR szTemplate[1024];
TCHAR szPrivacyText[1024];
TCHAR szEmail[MAX_PATH];
TCHAR szDomain[MAX_PATH];
if (FAILED(GetEmailAddressDomain(pApp, szDomain, ARRAYSIZE(szDomain))))
{
szDomain[0] = 0;
}
// Set the next text.
LoadString(g_hInstRes, ids_ADPassifier_Warning, szTemplate, ARRAYSIZE(szTemplate));
wnsprintf(szPrivacyText, ARRAYSIZE(szPrivacyText), szTemplate, szDomain);
SetWindowText(GetDlgItem(hDlg, IDC_PASSIFIER_PRIVACYWARNING), szPrivacyText);
// Load up the list boxes
IMailAutoDiscovery * pMailAutoDiscovery;
HWND hwndListBox;
if (FAILED(GetEmailAddress(pApp, szEmail, ARRAYSIZE(szEmail))))
{
szEmail[0] = 0;
}
HRESULT hr = CoCreateInstance(CLSID_MailAutoDiscovery, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IMailAutoDiscovery, &pMailAutoDiscovery));
if (SUCCEEDED(hr))
{
IAutoDiscoveryProvider * pProviders;
BSTR bstrEmail = SysAllocStringA(szEmail);
hr = pMailAutoDiscovery->getPrimaryProviders(bstrEmail, &pProviders);
if (SUCCEEDED(hr))
{
long nTotal = 0;
VARIANT varIndex;
hwndListBox = GetDlgItem(hDlg, IDC_PASSIFIER_PRIMARYLIST);
if (hwndListBox)
{
varIndex.vt = VT_I4;
pProviders->get_length(&nTotal);
for (varIndex.lVal = 0; (varIndex.lVal < nTotal) && (varIndex.lVal <= 3); varIndex.lVal++)
{
BSTR bstrDomain;
if (SUCCEEDED(pProviders->get_item(varIndex, &bstrDomain)))
{
CHAR szDomain[MAX_PATH];
SHUnicodeToAnsi(bstrDomain, szDomain, ARRAYSIZE(szDomain));
SetWindowTextA(GetDlgItem(hDlg, IDC_PASSIFIER_PRIMARYLIST + varIndex.lVal), szDomain);
SysFreeString(bstrDomain);
}
}
}
pProviders->Release();
}
hr = pMailAutoDiscovery->getSecondaryProviders(bstrEmail, &pProviders);
if (SUCCEEDED(hr))
{
long nTotal = 0;
VARIANT varIndex;
hwndListBox = GetDlgItem(hDlg, IDC_PASSIFIER_SECONDARYLIST);
if (hwndListBox)
{
varIndex.vt = VT_I4;
pProviders->get_length(&nTotal);
for (varIndex.lVal = 0; (varIndex.lVal < nTotal) && (varIndex.lVal <= 3); varIndex.lVal++)
{
BSTR bstrURL; // The secondary servers are URLs
if (SUCCEEDED(pProviders->get_item(varIndex, &bstrURL)))
{
CHAR szURL[MAX_PATH];
CHAR szDomain[MAX_PATH];
DWORD cchSize = ARRAYSIZE(szDomain);
SHUnicodeToAnsi(bstrURL, szURL, ARRAYSIZE(szURL));
UrlGetPart(szURL, szDomain, &cchSize, URL_PART_HOSTNAME, 0);
SetWindowTextA(GetDlgItem(hDlg, IDC_PASSIFIER_SECONDARYLIST + varIndex.lVal), szDomain);
SysFreeString(bstrURL);
}
}
}
pProviders->Release();
}
SysFreeString(bstrEmail);
pMailAutoDiscovery->Release();
}
// Set the manual checkbox
BOOL fManuallyConfigure = SHRegGetBoolUSValue(SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_OEMANUAL, FALSE, FALSE);
CheckDlgButton(hDlg, IDC_PASSIFIER_SKIPCHECKBOX, (fManuallyConfigure ? BST_CHECKED : BST_UNCHECKED));
return TRUE;
}
#define SZ_TRUE TEXT("TRUE")
#define SZ_FALSE TEXT("FALSE")
BOOL CALLBACK PassifierOKProc(CICWApprentice *pApp, HWND hDlg, BOOL fForward, UINT *puNextPage)
{
if (fForward)
{
BOOL fManuallyConfigure = (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_PASSIFIER_SKIPCHECKBOX));
SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_AUTODISCOVERY, SZ_REGVALUE_AUTODISCOVERY_OEMANUAL, REG_SZ,
(LPCVOID)(fManuallyConfigure ? SZ_TRUE : SZ_FALSE), (fManuallyConfigure ? sizeof(SZ_TRUE) : sizeof(SZ_FALSE)));
*puNextPage = (fManuallyConfigure ? ORD_PAGE_AD_MAILSERVER : ORD_PAGE_AD_AUTODISCOVERY);
}
else
{
*puNextPage = ORD_PAGE_AD_MAILADDRESS;
}
return TRUE;
}
BOOL CALLBACK PassifierCmdProc(CICWApprentice *pApp, HWND hDlg, WPARAM wParam, LPARAM lParam)
{
return TRUE;
}