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.
 
 
 
 
 
 

806 lines
26 KiB

/*****************************************************************************\
FILE: EmailAssoc.cpp
DESCRIPTION:
This file implements email to application associations.
BryanSt 3/14/2000
Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
\*****************************************************************************/
#include "priv.h"
#include <atlbase.h> // USES_CONVERSION
#include "util.h"
#include "objctors.h"
#include <comdef.h>
#include <limits.h> // INT_MAX
#include <commctrl.h> // Str_SetPtr
#include "EmailAssoc.h" //
#ifdef FEATURE_EMAILASSOCIATIONS
todo; // Move this into AutoDiscovery.idl when we support the feature.
/*
interface IEmailAssociations;
cpp_quote("#ifndef __LPEMAILASSOCIATIONS_DEFINED")
cpp_quote("#define __LPEMAILASSOCIATIONS_DEFINED")
cpp_quote("//===================================================================")
cpp_quote("//DESCRIPTION:")
cpp_quote("//===================================================================")
[
object,
oleautomation,
dual,
nonextensible,
uuid(2154A5C4-9090-4746-A580-BF650D2404F6), // IID_IEmailAssociations
]
interface IEmailAssociations : IDispatch
{
//------------------------------------------------------------------
// Pointer to an interface of this type
//------------------------------------------------------------------
typedef [unique] IEmailAssociations *LPEMAILASSOCIATIONS; // For C callers
//------------------------------------------------------------------
// Properties
//------------------------------------------------------------------
[id(DISPIDAD_LENGTH), propget, SZ_DISPIDAD_GETLENGTH, displaybind, bindable] HRESULT length([retval, out] long * pnLength);
[id(DISPIDAD_ITEM), propget, SZ_DISPIDAD_GETITEM, displaybind, bindable] HRESULT item([in] long nIndex,[retval, out] BSTR * pbstrEmailAddress);
//------------------------------------------------------------------
// Methods
//------------------------------------------------------------------
}
cpp_quote("#endif // __LPEMAILASSOCIATIONS_DEFINED")
//----------------------------------------------------------------------
// AutoDiscover Accounts Class
//----------------------------------------------------------------------
[
uuid(CE682BA0-C554-43f7-99C6-2F00FE46C8BC), // CLSID_EmailAssociations
helpstring("Neptune AutoDiscover Accounts Class"),
]
coclass EmailAssociations
{
[default] interface IEmailAssociations;
};
*/
class CEmailAssociations : public CImpIDispatch
, public CObjectWithSite
, public IEmailAssociations
{
public:
//////////////////////////////////////////////////////
// Public Interfaces
//////////////////////////////////////////////////////
// *** IUnknown ***
virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
virtual STDMETHODIMP_(ULONG) AddRef(void);
virtual STDMETHODIMP_(ULONG) Release(void);
// *** IEmailAssociations ***
virtual STDMETHODIMP get_length(OUT long * pnLength);
virtual STDMETHODIMP get_item(IN long nIndex, OUT BSTR * pbstrEmailAddress);
// *** IDispatch ***
virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
virtual STDMETHODIMP GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo) { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
virtual STDMETHODIMP GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames, LCID lcid, DISPID * rgdispid) { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
virtual STDMETHODIMP Invoke(DISPID dispidMember,REFIID riid,LCID lcid,WORD wFlags, DISPPARAMS * pdispparams, VARIANT * pvarResult, EXCEPINFO * pexcepinfo,UINT * puArgErr) { return CImpIDispatch::Invoke(dispidMember, riid, lcid, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); }
protected:
CEmailAssociations();
virtual ~CEmailAssociations(void);
// Private Member Variables
int m_cRef;
LPWSTR m_pszDefault;
HKEY m_hkey;
// Private Member Functions
HRESULT _getHkey(void);
// Friend Functions
friend HRESULT CEmailAssociations_CreateInstance(IN IUnknown * punkOuter, REFIID riid, void ** ppvObj);
};
//===========================
// *** Class Internals & Helpers ***
//===========================
HRESULT CEmailAssociations::_getHkey(void)
{
HRESULT hr = S_OK;
if (!m_hkey)
{
DWORD dwError = RegOpenKeyEx(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, 0, KEY_READ, &m_hkey);
hr = HRESULT_FROM_WIN32(dwError);
}
return hr;
}
//===========================
// *** IEmailAssociations Interface ***
//===========================
HRESULT CEmailAssociations::get_length(OUT long * pnLength)
{
HRESULT hr = _getHkey();
if (SUCCEEDED(hr))
{
DWORD dwError = RegQueryInfoKey(m_hkey, NULL, NULL, 0, (ULONG *) pnLength, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
hr = HRESULT_FROM_WIN32(dwError);
}
return hr;
}
HRESULT CEmailAssociations::get_item(IN long nIndex, OUT BSTR * pbstrEmailAddress)
{
HRESULT hr = _getHkey();
*pbstrEmailAddress = NULL;
if (SUCCEEDED(hr))
{
if (0 == nIndex)
{
if (!m_pszDefault)
{
TCHAR szCurrent[MAX_EMAIL_ADDRESSS];
DWORD cb = sizeof(szCurrent);
// We always hand out the default key for index == 0.
DWORD dwError = RegQueryValueEx(m_hkey, NULL, NULL, NULL, (LPBYTE)szCurrent, &cb);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
Str_SetPtr(&m_pszDefault, szCurrent);
}
}
if (m_pszDefault)
{
hr = HrSysAllocString(m_pszDefault, pbstrEmailAddress);
}
else
{
hr = E_FAIL;
}
}
else
{
TCHAR szKeyName[MAX_PATH];
FILETIME ftLastWriteTime;
long nCurrent; // Index counter
DWORD cbSize;
DWORD dwError;
// populate the list
for(nCurrent = 0;
cbSize = ARRAYSIZE(szKeyName), dwError = RegEnumKeyEx(m_hkey, nCurrent, szKeyName, &cbSize, NULL, NULL, NULL, &ftLastWriteTime),
hr = HRESULT_FROM_WIN32(dwError), SUCCEEDED(hr);
nCurrent++)
{
hr = E_FAIL;
// Is this the default key?
if (!StrCmpI(szKeyName, m_pszDefault))
{
// Yes, so skip this index because we already returned it for slot zero (0).
nIndex++;
}
else
{
if (nIndex == (nCurrent + 1)) // Is this the one the user wanted.
{
hr = HrSysAllocString(szKeyName, pbstrEmailAddress);
break;
}
}
} // for
}
}
return hr;
}
//===========================
// *** IUnknown Interface ***
//===========================
HRESULT CEmailAssociations::QueryInterface(REFIID riid, void **ppvObj)
{
static const QITAB qit[] = {
QITABENT(CEmailAssociations, IEmailAssociations),
QITABENT(CEmailAssociations, IDispatch),
{ 0 },
};
return QISearch(this, qit, riid, ppvObj);
}
STDMETHODIMP_(DWORD) CEmailAssociations::AddRef()
{
return ++m_cRef;
}
STDMETHODIMP_(DWORD) CEmailAssociations::Release()
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
//===========================
// *** Class Methods ***
//===========================
CEmailAssociations::CEmailAssociations() : CImpIDispatch(LIBID_AutoDiscovery, 1, 0, IID_IEmailAssociations)
{
DllAddRef();
// This needs to be allocated in Zero Inited Memory.
// Assert that all Member Variables are inited to Zero.
m_pszDefault = NULL;
m_hkey = NULL;
m_cRef = 1;
}
CEmailAssociations::~CEmailAssociations()
{
Str_SetPtr(&m_pszDefault, NULL);
if (m_hkey)
{
RegCloseKey(m_hkey);
}
DllRelease();
}
HRESULT CEmailAssociations_CreateInstance(IN IUnknown * punkOuter, REFIID riid, void ** ppvObj)
{
HRESULT hr = CLASS_E_NOAGGREGATION;
if (NULL == punkOuter)
{
CEmailAssociations * pmf = new CEmailAssociations();
if (pmf)
{
hr = pmf->QueryInterface(riid, ppvObj);
pmf->Release();
}
else
{
*ppvObj = NULL;
hr = E_OUTOFMEMORY;
}
}
return hr;
}
//////////////////////////////////////
// EmailAccount
//
// In these cases, HKEY points to:
// HKCU, "Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>"
//
//////////////////////////////////////
HRESULT EmailAssoc_CreateEmailAccount(IN LPCWSTR pszEmailAddress, OUT HKEY * phkey)
{
HRESULT hr;
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_EXPLOREREMAIL, pszEmailAddress);
DWORD dwError = RegCreateKeyW(HKEY_CURRENT_USER, wzRegKey, phkey);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
hr = EmailAssoc_GetDefaultEmailAccount(wzRegKey, ARRAYSIZE(wzRegKey));
if (FAILED(hr))
{
// We don't have a default email account, so let's set this one.
hr = EmailAssoc_SetDefaultEmailAccount(pszEmailAddress);
}
}
return hr;
}
HRESULT EmailAssoc_OpenEmailAccount(IN LPCWSTR pszEmailAddress, OUT HKEY * phkey)
{
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_EXPLOREREMAIL, pszEmailAddress);
DWORD dwError = RegOpenKeyW(HKEY_CURRENT_USER, wzRegKey, phkey);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_GetEmailAccountProtocol(IN HKEY hkey, IN LPWSTR pszProtocol, IN DWORD cchSize)
{
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszProtocol[0]));
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
DWORD dwError = SHGetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, &dwType, (void *)pszProtocol, &cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_SetEmailAccountProtocol(IN HKEY hkey, IN LPCWSTR pszProtocol)
{
DWORD cbSize = ((lstrlenW(pszProtocol) + 1) * sizeof(pszProtocol[0]));
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, REG_SZ, (void *)pszProtocol, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_GetEmailAccountWebURL(IN HKEY hkey, IN LPWSTR pszURL, IN DWORD cchSize)
{
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszURL[0]));
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
DWORD dwError = SHGetValueW(hkey, SZ_REGVALUE_MAILPROTOCOLS L"\\" SZ_REGVALUE_WEB, SZ_REGVALUE_URL, &dwType, (void *)pszURL, &cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_SetEmailAccountWebURL(IN HKEY hkey, IN LPCWSTR pszURL)
{
DWORD cbSize = ((lstrlenW(pszURL) + 1) * sizeof(pszURL[0]));
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
DWORD dwError = SHSetValueW(hkey, SZ_REGVALUE_MAILPROTOCOLS L"\\" SZ_REGVALUE_WEB, SZ_REGVALUE_URL, REG_SZ, (void *)pszURL, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_GetEmailAccountPreferredApp(IN HKEY hkey, IN LPWSTR pszMailApp, IN DWORD cchSize)
{
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
// Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","Preferred App"="<MailApp | AppID>"
DWORD dwError = SHGetValueW(hkey, NULL, SZ_REGVALUE_PREFERREDAPP, &dwType, (void *)pszMailApp, &cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_SetEmailAccountPreferredApp(IN HKEY hkey, IN LPCWSTR pszMailApp)
{
DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
// Set HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","Preferred App"="<MailApp | AppID>"
DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_PREFERREDAPP, REG_SZ, (void *)pszMailApp, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_GetDefaultEmailAccount(IN LPWSTR pszProtocol, IN DWORD cchSize)
{
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszProtocol[0]));
// Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\","(default)"="<Default Email Account>"
DWORD dwError = SHGetValueW(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, NULL, &dwType, (void *)pszProtocol, &cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_SetDefaultEmailAccount(IN LPCWSTR pszProtocol)
{
DWORD cbSize = ((lstrlenW(pszProtocol) + 1) * sizeof(pszProtocol[0]));
// Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\","(default)"="<Default Email Account>"
DWORD dwError = SHSetValueW(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, NULL, REG_SZ, (void *)pszProtocol, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
//////////////////////////////////////
// MailApp
//
// In these cases, HKEY points to:
// HKLM, "Software\Clients\Mail\<MailApp>"
//
//////////////////////////////////////
HRESULT EmailAssoc_GetDefaultMailApp(IN LPWSTR pszMailApp, IN DWORD cchSize)
{
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
// Get HKLM,"Software\Clients\Mail","(default)"="<MailApp>"
DWORD dwError = SHGetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_MAILCLIENTS, NULL, &dwType, (void *)pszMailApp, &cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_SetDefaultMailApp(IN LPCWSTR pszMailApp)
{
DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
// Set HKLM,"Software\Clients\Mail","(default)"="<MailApp>"
DWORD dwError = SHSetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_MAILCLIENTS, NULL, REG_SZ, (void *)pszMailApp, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_OpenMailApp(IN LPCWSTR pszMailApp, OUT HKEY * phkey)
{
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILCLIENTS, pszMailApp);
// TODO: We may want to support HKCU based "Clients\Mail".
DWORD dwError = RegOpenKeyW(HKEY_LOCAL_MACHINE, wzRegKey, phkey);
return HRESULT_FROM_WIN32(dwError);
}
HRESULT EmailAssoc_GetAppPath(IN HKEY hkey, IN LPTSTR pszAppPath, IN DWORD cchSize)
{
HRESULT hr = E_OUTOFMEMORY;
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszAppPath[0]));
TCHAR szCmdLine[MAX_PATH];
szCmdLine[0] = 0; // This is optional
// TODO: put our values under a "AutoDiscovery" key.
DWORD dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILPATH, &dwType, (void *)pszAppPath, &cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (FAILED(hr))
{
// TODO: Use IQueryAssociations to load the string. Then use ShellExecuteEx() with the "Open"
// verb so we let them load the "Shell\Open\Command" heirarchy.
// Fall back to HKLM, "Software\Clients\Mail\<AppName>\Shell\Open\Command, "(default)"
cbSize = (cchSize * sizeof(pszAppPath[0]));
dwError = SHGetValue(hkey, SZ_REGKEY_SHELLOPENCMD, NULL, &dwType, (void *)pszAppPath, &cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
PathRemoveArgs(pszAppPath);
PathUnquoteSpaces(pszAppPath);
}
}
return hr;
}
HRESULT EmailAssoc_GetAppCmdLine(IN HKEY hkey, IN LPTSTR pszCmdLine, IN DWORD cchSize)
{
TCHAR szPath[MAX_PATH];
HRESULT hr = E_OUTOFMEMORY;
DWORD dwType;
DWORD cbSize = sizeof(szPath);
TCHAR szCmdLine[MAX_PATH];
szCmdLine[0] = 0; // This is optional
// TODO: put our values under a "AutoDiscovery" key.
DWORD dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILPATH, &dwType, (void *)szPath, &cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
cbSize = (cchSize * sizeof(pszCmdLine[0]));
dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILCMDLINE, &dwType, (void *)pszCmdLine, &cbSize);
}
else
{
// TODO: Use IQueryAssociations to load the string. Then use ShellExecuteEx() with the "Open"
// verb so we let them load the "Shell\Open\Command" heirarchy.
// Fall back to HKLM, "Software\Clients\Mail\<AppName>\Shell\Open\Command, "(default)"
cbSize = sizeof(szPath);
dwError = SHGetValue(hkey, SZ_REGKEY_SHELLOPENCMD, NULL, &dwType, (void *)szPath, &cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
LPTSTR pszTempCmdLine = PathGetArgs(szPath);
if (pszCmdLine)
{
StrCpyN(pszCmdLine, pszTempCmdLine, cchSize);
}
else
{
StrCpyN(pszCmdLine, TEXT(""), cchSize);
hr = S_FALSE;
}
}
}
return hr;
}
HRESULT EmailAssoc_GetIconPath(IN HKEY hkey, IN LPTSTR pszIconPath, IN DWORD cchSize)
{
HRESULT hr = EmailAssoc_GetAppPath(hkey, pszIconPath, cchSize);
if (SUCCEEDED(hr))
{
// Get the path we will use for the icon.
if (PathFindFileName(pszIconPath) && !StrCmpI(PathFindFileName(pszIconPath), TEXT("rundll32.exe")))
{
// The icon path is "Rundll32.exe" which will actually run their dll.
// We will want to use the cmdline instead.
hr = EmailAssoc_GetAppCmdLine(hkey, pszIconPath, cchSize);
if (StrChr(pszIconPath, CH_COMMA))
{
StrChr(pszIconPath, CH_COMMA)[0] = 0; // Remove the function name.
}
PathUnquoteSpaces(pszIconPath);
}
}
return hr;
}
BOOL EmailAssoc_DoesMailAppSupportProtocol(IN LPCWSTR pszMailApp, IN LPCWSTR pszProtocol)
{
BOOL fSupports = FALSE;
DWORD dwType;
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
WCHAR wzTemp[MAX_PATH];
DWORD cbSize = sizeof(wzTemp);
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
// Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
// This key is used if the customer wants to force different apps per protocol.
DWORD dwError = SHGetValueW(HKEY_CLASSES_ROOT, wzRegKey, pszMailApp, &dwType, (void *)wzTemp, &cbSize);
if (ERROR_SUCCESS == dwError)
{
fSupports = TRUE;
}
return fSupports;
}
HRESULT EmailAssoc_GetFirstMailAppForProtocol(IN LPCWSTR pszProtocol, IN LPWSTR pszMailApp, IN DWORD cchSize)
{
HRESULT hr;
HKEY hkey;
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
DWORD dwError = RegOpenKey(HKEY_CLASSES_ROOT, wzRegKey, &hkey);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
WCHAR wzTemp[MAX_PATH];
DWORD cbSizeTemp = sizeof(wzTemp);
DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
DWORD dwType;
// Read HKCR,"MailTransport\<Protocol>\Apps","<The First Value>"="<AppName | AppID>"
dwError = SHEnumValueW(hkey, 0, pszMailApp, &cbSize, &dwType, (void *)wzTemp, &cbSizeTemp);
hr = HRESULT_FROM_WIN32(dwError);
RegCloseKey(hkey);
}
return hr;
}
//////////////////////////////////////
// Other
//////////////////////////////////////
HRESULT EmailAssoc_CreateWebAssociation(IN LPCTSTR pszEmail, IN IMailProtocolADEntry * pMailProtocol)
{
BSTR bstrWebBaseEmailURL;
HRESULT hr = pMailProtocol->get_ServerName(&bstrWebBaseEmailURL);
if (SUCCEEDED(hr))
{
HKEY hkey;
hr = EmailAssoc_CreateEmailAccount(pszEmail, &hkey);
if (SUCCEEDED(hr))
{
hr = EmailAssoc_SetEmailAccountWebURL(hkey, bstrWebBaseEmailURL);
if (SUCCEEDED(hr))
{
hr = EmailAssoc_SetEmailAccountProtocol(hkey, SZ_REGDATA_WEB);
}
RegCloseKey(hkey);
}
SysFreeString(bstrWebBaseEmailURL);
}
return hr;
}
HRESULT EmailAssoc_CreateStandardsBaseAssociation(IN LPCTSTR pszEmail, IN LPCTSTR pszProtocol)
{
HKEY hkey;
HRESULT hr = EmailAssoc_CreateEmailAccount(pszEmail, &hkey);
if (SUCCEEDED(hr))
{
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
DWORD cbSize = ((lstrlenW(L"") + 1) * sizeof(WCHAR));
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGVALUE_MAILPROTOCOLS, pszProtocol);
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>\MailProtocols\<protocol>","(default)"=""
DWORD dwError = SHSetValueW(hkey, wzRegKey, NULL, REG_SZ, (void *)L"", cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr))
{
WCHAR wzProtocol[MAX_PATH];
SHTCharToUnicode(pszProtocol, wzProtocol, ARRAYSIZE(wzProtocol));
cbSize = ((lstrlenW(SZ_REGDATA_WEB) + 1) * sizeof(SZ_REGDATA_WEB[0]));
// Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="<protocol>"
DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, REG_SZ, (void *)wzProtocol, cbSize);
hr = HRESULT_FROM_WIN32(dwError);
}
RegCloseKey(hkey);
}
return hr;
}
HRESULT EmailAssoc_GetEmailAccountGetAppFromProtocol(IN LPCWSTR pszProtocol, IN LPWSTR pszMailApp, IN DWORD cchSize)
{
HRESULT hr;
DWORD dwType;
DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
// Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
// This key is used if the customer wants to force different apps per protocol.
DWORD dwError = SHGetValueW(HKEY_CLASSES_ROOT, wzRegKey, NULL, &dwType, (void *)pszMailApp, &cbSize);
hr = HRESULT_FROM_WIN32(dwError);
if (FAILED(hr))
{
// The user didn't force an app based on the protocol, so let's try the default app.
hr = EmailAssoc_GetDefaultMailApp(pszMailApp, cchSize);
// Lets see if the default email add supports this protocol, because we always want
// to give preferense to the user's choosen mail app.
if (FAILED(hr) || !EmailAssoc_DoesMailAppSupportProtocol(pszMailApp, pszProtocol))
{
// It doesn't support the protocol, so lets get the first app that does.
hr = EmailAssoc_GetFirstMailAppForProtocol(pszProtocol, pszMailApp, cchSize);
}
}
return hr;
}
HRESULT EmailAssoc_SetEmailAccountGetAppFromProtocol(IN LPCWSTR pszProtocol, IN LPCWSTR pszMailApp)
{
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
// Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
DWORD dwError = SHSetValueW(HKEY_CLASSES_ROOT, wzRegKey, NULL, REG_SZ, (void *)pszMailApp, cbSize);
return HRESULT_FROM_WIN32(dwError);
}
LPCWSTR g_LegacyAssociations[][2] =
{
{L"Outlook Express", L"POP3"},
{L"Outlook Express", L"IMAP"},
{L"Outlook Express", L"DAVMail"},
{L"Microsoft Outlook", L"POP3"},
{L"Microsoft Outlook", L"IMAP"},
{L"Microsoft Outlook", L"MAPI"},
{L"Eudora", L"POP3"},
{L"Eudora", L"IMAP"},
};
// Description:
// This function will look at what applications are installed and setup the appropriate
// legacy email associations.
HRESULT EmailAssoc_InstallLegacyMailAppAssociations(void)
{
HRESULT hr = S_OK;
for (int nIndex = 0; nIndex < ARRAYSIZE(g_LegacyAssociations); nIndex++)
{
HKEY hkey;
// Is the app installed?
hr = EmailAssoc_OpenMailApp(g_LegacyAssociations[nIndex][0], &hkey);
if (SUCCEEDED(hr))
{
// Yes, so let's install the legacy association.
// TODO: we should use GetFileVersionInfo() and VerQueryValue() to make sure
// these are legacy versions.
//hr = EmailAssoc_GetAppPath(IN HKEY hkey, IN LPTSTR pszAppPath, IN DWORD cchSize);
WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, g_LegacyAssociations[nIndex][1]);
SHSetValueW(HKEY_CLASSES_ROOT, wzRegKey, g_LegacyAssociations[nIndex][0], REG_SZ, (void *)L"", 4);
RegCloseKey(hkey);
}
}
return S_OK; // We succeed any way because we are just trying to upgrade.
}
#endif // FEATURE_EMAILASSOCIATIONS