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

  1. /*****************************************************************************\
  2. FILE: EmailAssoc.cpp
  3. DESCRIPTION:
  4. This file implements email to application associations.
  5. BryanSt 3/14/2000
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include <atlbase.h> // USES_CONVERSION
  10. #include "util.h"
  11. #include "objctors.h"
  12. #include <comdef.h>
  13. #include <limits.h> // INT_MAX
  14. #include <commctrl.h> // Str_SetPtr
  15. #include "EmailAssoc.h" //
  16. #ifdef FEATURE_EMAILASSOCIATIONS
  17. todo; // Move this into AutoDiscovery.idl when we support the feature.
  18. /*
  19. interface IEmailAssociations;
  20. cpp_quote("#ifndef __LPEMAILASSOCIATIONS_DEFINED")
  21. cpp_quote("#define __LPEMAILASSOCIATIONS_DEFINED")
  22. cpp_quote("//===================================================================")
  23. cpp_quote("//DESCRIPTION:")
  24. cpp_quote("//===================================================================")
  25. [
  26. object,
  27. oleautomation,
  28. dual,
  29. nonextensible,
  30. uuid(2154A5C4-9090-4746-A580-BF650D2404F6), // IID_IEmailAssociations
  31. ]
  32. interface IEmailAssociations : IDispatch
  33. {
  34. //------------------------------------------------------------------
  35. // Pointer to an interface of this type
  36. //------------------------------------------------------------------
  37. typedef [unique] IEmailAssociations *LPEMAILASSOCIATIONS; // For C callers
  38. //------------------------------------------------------------------
  39. // Properties
  40. //------------------------------------------------------------------
  41. [id(DISPIDAD_LENGTH), propget, SZ_DISPIDAD_GETLENGTH, displaybind, bindable] HRESULT length([retval, out] long * pnLength);
  42. [id(DISPIDAD_ITEM), propget, SZ_DISPIDAD_GETITEM, displaybind, bindable] HRESULT item([in] long nIndex,[retval, out] BSTR * pbstrEmailAddress);
  43. //------------------------------------------------------------------
  44. // Methods
  45. //------------------------------------------------------------------
  46. }
  47. cpp_quote("#endif // __LPEMAILASSOCIATIONS_DEFINED")
  48. //----------------------------------------------------------------------
  49. // AutoDiscover Accounts Class
  50. //----------------------------------------------------------------------
  51. [
  52. uuid(CE682BA0-C554-43f7-99C6-2F00FE46C8BC), // CLSID_EmailAssociations
  53. helpstring("Neptune AutoDiscover Accounts Class"),
  54. ]
  55. coclass EmailAssociations
  56. {
  57. [default] interface IEmailAssociations;
  58. };
  59. */
  60. class CEmailAssociations : public CImpIDispatch
  61. , public CObjectWithSite
  62. , public IEmailAssociations
  63. {
  64. public:
  65. //////////////////////////////////////////////////////
  66. // Public Interfaces
  67. //////////////////////////////////////////////////////
  68. // *** IUnknown ***
  69. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  70. virtual STDMETHODIMP_(ULONG) AddRef(void);
  71. virtual STDMETHODIMP_(ULONG) Release(void);
  72. // *** IEmailAssociations ***
  73. virtual STDMETHODIMP get_length(OUT long * pnLength);
  74. virtual STDMETHODIMP get_item(IN long nIndex, OUT BSTR * pbstrEmailAddress);
  75. // *** IDispatch ***
  76. virtual STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) { return CImpIDispatch::GetTypeInfoCount(pctinfo); }
  77. virtual STDMETHODIMP GetTypeInfo(UINT itinfo,LCID lcid,ITypeInfo **pptinfo) { return CImpIDispatch::GetTypeInfo(itinfo, lcid, pptinfo); }
  78. virtual STDMETHODIMP GetIDsOfNames(REFIID riid,OLECHAR **rgszNames,UINT cNames, LCID lcid, DISPID * rgdispid) { return CImpIDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgdispid); }
  79. 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); }
  80. protected:
  81. CEmailAssociations();
  82. virtual ~CEmailAssociations(void);
  83. // Private Member Variables
  84. int m_cRef;
  85. LPWSTR m_pszDefault;
  86. HKEY m_hkey;
  87. // Private Member Functions
  88. HRESULT _getHkey(void);
  89. // Friend Functions
  90. friend HRESULT CEmailAssociations_CreateInstance(IN IUnknown * punkOuter, REFIID riid, void ** ppvObj);
  91. };
  92. //===========================
  93. // *** Class Internals & Helpers ***
  94. //===========================
  95. HRESULT CEmailAssociations::_getHkey(void)
  96. {
  97. HRESULT hr = S_OK;
  98. if (!m_hkey)
  99. {
  100. DWORD dwError = RegOpenKeyEx(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, 0, KEY_READ, &m_hkey);
  101. hr = HRESULT_FROM_WIN32(dwError);
  102. }
  103. return hr;
  104. }
  105. //===========================
  106. // *** IEmailAssociations Interface ***
  107. //===========================
  108. HRESULT CEmailAssociations::get_length(OUT long * pnLength)
  109. {
  110. HRESULT hr = _getHkey();
  111. if (SUCCEEDED(hr))
  112. {
  113. DWORD dwError = RegQueryInfoKey(m_hkey, NULL, NULL, 0, (ULONG *) pnLength, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
  114. hr = HRESULT_FROM_WIN32(dwError);
  115. }
  116. return hr;
  117. }
  118. HRESULT CEmailAssociations::get_item(IN long nIndex, OUT BSTR * pbstrEmailAddress)
  119. {
  120. HRESULT hr = _getHkey();
  121. *pbstrEmailAddress = NULL;
  122. if (SUCCEEDED(hr))
  123. {
  124. if (0 == nIndex)
  125. {
  126. if (!m_pszDefault)
  127. {
  128. TCHAR szCurrent[MAX_EMAIL_ADDRESSS];
  129. DWORD cb = sizeof(szCurrent);
  130. // We always hand out the default key for index == 0.
  131. DWORD dwError = RegQueryValueEx(m_hkey, NULL, NULL, NULL, (LPBYTE)szCurrent, &cb);
  132. hr = HRESULT_FROM_WIN32(dwError);
  133. if (SUCCEEDED(hr))
  134. {
  135. Str_SetPtr(&m_pszDefault, szCurrent);
  136. }
  137. }
  138. if (m_pszDefault)
  139. {
  140. hr = HrSysAllocString(m_pszDefault, pbstrEmailAddress);
  141. }
  142. else
  143. {
  144. hr = E_FAIL;
  145. }
  146. }
  147. else
  148. {
  149. TCHAR szKeyName[MAX_PATH];
  150. FILETIME ftLastWriteTime;
  151. long nCurrent; // Index counter
  152. DWORD cbSize;
  153. DWORD dwError;
  154. // populate the list
  155. for(nCurrent = 0;
  156. cbSize = ARRAYSIZE(szKeyName), dwError = RegEnumKeyEx(m_hkey, nCurrent, szKeyName, &cbSize, NULL, NULL, NULL, &ftLastWriteTime),
  157. hr = HRESULT_FROM_WIN32(dwError), SUCCEEDED(hr);
  158. nCurrent++)
  159. {
  160. hr = E_FAIL;
  161. // Is this the default key?
  162. if (!StrCmpI(szKeyName, m_pszDefault))
  163. {
  164. // Yes, so skip this index because we already returned it for slot zero (0).
  165. nIndex++;
  166. }
  167. else
  168. {
  169. if (nIndex == (nCurrent + 1)) // Is this the one the user wanted.
  170. {
  171. hr = HrSysAllocString(szKeyName, pbstrEmailAddress);
  172. break;
  173. }
  174. }
  175. } // for
  176. }
  177. }
  178. return hr;
  179. }
  180. //===========================
  181. // *** IUnknown Interface ***
  182. //===========================
  183. HRESULT CEmailAssociations::QueryInterface(REFIID riid, void **ppvObj)
  184. {
  185. static const QITAB qit[] = {
  186. QITABENT(CEmailAssociations, IEmailAssociations),
  187. QITABENT(CEmailAssociations, IDispatch),
  188. { 0 },
  189. };
  190. return QISearch(this, qit, riid, ppvObj);
  191. }
  192. STDMETHODIMP_(DWORD) CEmailAssociations::AddRef()
  193. {
  194. return ++m_cRef;
  195. }
  196. STDMETHODIMP_(DWORD) CEmailAssociations::Release()
  197. {
  198. if (--m_cRef == 0)
  199. {
  200. delete this;
  201. return 0;
  202. }
  203. return m_cRef;
  204. }
  205. //===========================
  206. // *** Class Methods ***
  207. //===========================
  208. CEmailAssociations::CEmailAssociations() : CImpIDispatch(LIBID_AutoDiscovery, 1, 0, IID_IEmailAssociations)
  209. {
  210. DllAddRef();
  211. // This needs to be allocated in Zero Inited Memory.
  212. // Assert that all Member Variables are inited to Zero.
  213. m_pszDefault = NULL;
  214. m_hkey = NULL;
  215. m_cRef = 1;
  216. }
  217. CEmailAssociations::~CEmailAssociations()
  218. {
  219. Str_SetPtr(&m_pszDefault, NULL);
  220. if (m_hkey)
  221. {
  222. RegCloseKey(m_hkey);
  223. }
  224. DllRelease();
  225. }
  226. HRESULT CEmailAssociations_CreateInstance(IN IUnknown * punkOuter, REFIID riid, void ** ppvObj)
  227. {
  228. HRESULT hr = CLASS_E_NOAGGREGATION;
  229. if (NULL == punkOuter)
  230. {
  231. CEmailAssociations * pmf = new CEmailAssociations();
  232. if (pmf)
  233. {
  234. hr = pmf->QueryInterface(riid, ppvObj);
  235. pmf->Release();
  236. }
  237. else
  238. {
  239. *ppvObj = NULL;
  240. hr = E_OUTOFMEMORY;
  241. }
  242. }
  243. return hr;
  244. }
  245. //////////////////////////////////////
  246. // EmailAccount
  247. //
  248. // In these cases, HKEY points to:
  249. // HKCU, "Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>"
  250. //
  251. //////////////////////////////////////
  252. HRESULT EmailAssoc_CreateEmailAccount(IN LPCWSTR pszEmailAddress, OUT HKEY * phkey)
  253. {
  254. HRESULT hr;
  255. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  256. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_EXPLOREREMAIL, pszEmailAddress);
  257. DWORD dwError = RegCreateKeyW(HKEY_CURRENT_USER, wzRegKey, phkey);
  258. hr = HRESULT_FROM_WIN32(dwError);
  259. if (SUCCEEDED(hr))
  260. {
  261. hr = EmailAssoc_GetDefaultEmailAccount(wzRegKey, ARRAYSIZE(wzRegKey));
  262. if (FAILED(hr))
  263. {
  264. // We don't have a default email account, so let's set this one.
  265. hr = EmailAssoc_SetDefaultEmailAccount(pszEmailAddress);
  266. }
  267. }
  268. return hr;
  269. }
  270. HRESULT EmailAssoc_OpenEmailAccount(IN LPCWSTR pszEmailAddress, OUT HKEY * phkey)
  271. {
  272. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  273. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_EXPLOREREMAIL, pszEmailAddress);
  274. DWORD dwError = RegOpenKeyW(HKEY_CURRENT_USER, wzRegKey, phkey);
  275. return HRESULT_FROM_WIN32(dwError);
  276. }
  277. HRESULT EmailAssoc_GetEmailAccountProtocol(IN HKEY hkey, IN LPWSTR pszProtocol, IN DWORD cchSize)
  278. {
  279. DWORD dwType;
  280. DWORD cbSize = (cchSize * sizeof(pszProtocol[0]));
  281. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
  282. DWORD dwError = SHGetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, &dwType, (void *)pszProtocol, &cbSize);
  283. return HRESULT_FROM_WIN32(dwError);
  284. }
  285. HRESULT EmailAssoc_SetEmailAccountProtocol(IN HKEY hkey, IN LPCWSTR pszProtocol)
  286. {
  287. DWORD cbSize = ((lstrlenW(pszProtocol) + 1) * sizeof(pszProtocol[0]));
  288. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
  289. DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, REG_SZ, (void *)pszProtocol, cbSize);
  290. return HRESULT_FROM_WIN32(dwError);
  291. }
  292. HRESULT EmailAssoc_GetEmailAccountWebURL(IN HKEY hkey, IN LPWSTR pszURL, IN DWORD cchSize)
  293. {
  294. DWORD dwType;
  295. DWORD cbSize = (cchSize * sizeof(pszURL[0]));
  296. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
  297. DWORD dwError = SHGetValueW(hkey, SZ_REGVALUE_MAILPROTOCOLS L"\\" SZ_REGVALUE_WEB, SZ_REGVALUE_URL, &dwType, (void *)pszURL, &cbSize);
  298. return HRESULT_FROM_WIN32(dwError);
  299. }
  300. HRESULT EmailAssoc_SetEmailAccountWebURL(IN HKEY hkey, IN LPCWSTR pszURL)
  301. {
  302. DWORD cbSize = ((lstrlenW(pszURL) + 1) * sizeof(pszURL[0]));
  303. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="WEB"
  304. DWORD dwError = SHSetValueW(hkey, SZ_REGVALUE_MAILPROTOCOLS L"\\" SZ_REGVALUE_WEB, SZ_REGVALUE_URL, REG_SZ, (void *)pszURL, cbSize);
  305. return HRESULT_FROM_WIN32(dwError);
  306. }
  307. HRESULT EmailAssoc_GetEmailAccountPreferredApp(IN HKEY hkey, IN LPWSTR pszMailApp, IN DWORD cchSize)
  308. {
  309. DWORD dwType;
  310. DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
  311. // Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","Preferred App"="<MailApp | AppID>"
  312. DWORD dwError = SHGetValueW(hkey, NULL, SZ_REGVALUE_PREFERREDAPP, &dwType, (void *)pszMailApp, &cbSize);
  313. return HRESULT_FROM_WIN32(dwError);
  314. }
  315. HRESULT EmailAssoc_SetEmailAccountPreferredApp(IN HKEY hkey, IN LPCWSTR pszMailApp)
  316. {
  317. DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
  318. // Set HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","Preferred App"="<MailApp | AppID>"
  319. DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_PREFERREDAPP, REG_SZ, (void *)pszMailApp, cbSize);
  320. return HRESULT_FROM_WIN32(dwError);
  321. }
  322. HRESULT EmailAssoc_GetDefaultEmailAccount(IN LPWSTR pszProtocol, IN DWORD cchSize)
  323. {
  324. DWORD dwType;
  325. DWORD cbSize = (cchSize * sizeof(pszProtocol[0]));
  326. // Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\","(default)"="<Default Email Account>"
  327. DWORD dwError = SHGetValueW(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, NULL, &dwType, (void *)pszProtocol, &cbSize);
  328. return HRESULT_FROM_WIN32(dwError);
  329. }
  330. HRESULT EmailAssoc_SetDefaultEmailAccount(IN LPCWSTR pszProtocol)
  331. {
  332. DWORD cbSize = ((lstrlenW(pszProtocol) + 1) * sizeof(pszProtocol[0]));
  333. // Get HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\","(default)"="<Default Email Account>"
  334. DWORD dwError = SHSetValueW(HKEY_CURRENT_USER, SZ_REGKEY_EXPLOREREMAIL, NULL, REG_SZ, (void *)pszProtocol, cbSize);
  335. return HRESULT_FROM_WIN32(dwError);
  336. }
  337. //////////////////////////////////////
  338. // MailApp
  339. //
  340. // In these cases, HKEY points to:
  341. // HKLM, "Software\Clients\Mail\<MailApp>"
  342. //
  343. //////////////////////////////////////
  344. HRESULT EmailAssoc_GetDefaultMailApp(IN LPWSTR pszMailApp, IN DWORD cchSize)
  345. {
  346. DWORD dwType;
  347. DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
  348. // Get HKLM,"Software\Clients\Mail","(default)"="<MailApp>"
  349. DWORD dwError = SHGetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_MAILCLIENTS, NULL, &dwType, (void *)pszMailApp, &cbSize);
  350. return HRESULT_FROM_WIN32(dwError);
  351. }
  352. HRESULT EmailAssoc_SetDefaultMailApp(IN LPCWSTR pszMailApp)
  353. {
  354. DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
  355. // Set HKLM,"Software\Clients\Mail","(default)"="<MailApp>"
  356. DWORD dwError = SHSetValueW(HKEY_LOCAL_MACHINE, SZ_REGKEY_MAILCLIENTS, NULL, REG_SZ, (void *)pszMailApp, cbSize);
  357. return HRESULT_FROM_WIN32(dwError);
  358. }
  359. HRESULT EmailAssoc_OpenMailApp(IN LPCWSTR pszMailApp, OUT HKEY * phkey)
  360. {
  361. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  362. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILCLIENTS, pszMailApp);
  363. // TODO: We may want to support HKCU based "Clients\Mail".
  364. DWORD dwError = RegOpenKeyW(HKEY_LOCAL_MACHINE, wzRegKey, phkey);
  365. return HRESULT_FROM_WIN32(dwError);
  366. }
  367. HRESULT EmailAssoc_GetAppPath(IN HKEY hkey, IN LPTSTR pszAppPath, IN DWORD cchSize)
  368. {
  369. HRESULT hr = E_OUTOFMEMORY;
  370. DWORD dwType;
  371. DWORD cbSize = (cchSize * sizeof(pszAppPath[0]));
  372. TCHAR szCmdLine[MAX_PATH];
  373. szCmdLine[0] = 0; // This is optional
  374. // TODO: put our values under a "AutoDiscovery" key.
  375. DWORD dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILPATH, &dwType, (void *)pszAppPath, &cbSize);
  376. hr = HRESULT_FROM_WIN32(dwError);
  377. if (FAILED(hr))
  378. {
  379. // TODO: Use IQueryAssociations to load the string. Then use ShellExecuteEx() with the "Open"
  380. // verb so we let them load the "Shell\Open\Command" heirarchy.
  381. // Fall back to HKLM, "Software\Clients\Mail\<AppName>\Shell\Open\Command, "(default)"
  382. cbSize = (cchSize * sizeof(pszAppPath[0]));
  383. dwError = SHGetValue(hkey, SZ_REGKEY_SHELLOPENCMD, NULL, &dwType, (void *)pszAppPath, &cbSize);
  384. hr = HRESULT_FROM_WIN32(dwError);
  385. if (SUCCEEDED(hr))
  386. {
  387. PathRemoveArgs(pszAppPath);
  388. PathUnquoteSpaces(pszAppPath);
  389. }
  390. }
  391. return hr;
  392. }
  393. HRESULT EmailAssoc_GetAppCmdLine(IN HKEY hkey, IN LPTSTR pszCmdLine, IN DWORD cchSize)
  394. {
  395. TCHAR szPath[MAX_PATH];
  396. HRESULT hr = E_OUTOFMEMORY;
  397. DWORD dwType;
  398. DWORD cbSize = sizeof(szPath);
  399. TCHAR szCmdLine[MAX_PATH];
  400. szCmdLine[0] = 0; // This is optional
  401. // TODO: put our values under a "AutoDiscovery" key.
  402. DWORD dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILPATH, &dwType, (void *)szPath, &cbSize);
  403. hr = HRESULT_FROM_WIN32(dwError);
  404. if (SUCCEEDED(hr))
  405. {
  406. cbSize = (cchSize * sizeof(pszCmdLine[0]));
  407. dwError = SHGetValue(hkey, NULL, SZ_REGVALUE_READEMAILCMDLINE, &dwType, (void *)pszCmdLine, &cbSize);
  408. }
  409. else
  410. {
  411. // TODO: Use IQueryAssociations to load the string. Then use ShellExecuteEx() with the "Open"
  412. // verb so we let them load the "Shell\Open\Command" heirarchy.
  413. // Fall back to HKLM, "Software\Clients\Mail\<AppName>\Shell\Open\Command, "(default)"
  414. cbSize = sizeof(szPath);
  415. dwError = SHGetValue(hkey, SZ_REGKEY_SHELLOPENCMD, NULL, &dwType, (void *)szPath, &cbSize);
  416. hr = HRESULT_FROM_WIN32(dwError);
  417. if (SUCCEEDED(hr))
  418. {
  419. LPTSTR pszTempCmdLine = PathGetArgs(szPath);
  420. if (pszCmdLine)
  421. {
  422. StrCpyN(pszCmdLine, pszTempCmdLine, cchSize);
  423. }
  424. else
  425. {
  426. StrCpyN(pszCmdLine, TEXT(""), cchSize);
  427. hr = S_FALSE;
  428. }
  429. }
  430. }
  431. return hr;
  432. }
  433. HRESULT EmailAssoc_GetIconPath(IN HKEY hkey, IN LPTSTR pszIconPath, IN DWORD cchSize)
  434. {
  435. HRESULT hr = EmailAssoc_GetAppPath(hkey, pszIconPath, cchSize);
  436. if (SUCCEEDED(hr))
  437. {
  438. // Get the path we will use for the icon.
  439. if (PathFindFileName(pszIconPath) && !StrCmpI(PathFindFileName(pszIconPath), TEXT("rundll32.exe")))
  440. {
  441. // The icon path is "Rundll32.exe" which will actually run their dll.
  442. // We will want to use the cmdline instead.
  443. hr = EmailAssoc_GetAppCmdLine(hkey, pszIconPath, cchSize);
  444. if (StrChr(pszIconPath, CH_COMMA))
  445. {
  446. StrChr(pszIconPath, CH_COMMA)[0] = 0; // Remove the function name.
  447. }
  448. PathUnquoteSpaces(pszIconPath);
  449. }
  450. }
  451. return hr;
  452. }
  453. BOOL EmailAssoc_DoesMailAppSupportProtocol(IN LPCWSTR pszMailApp, IN LPCWSTR pszProtocol)
  454. {
  455. BOOL fSupports = FALSE;
  456. DWORD dwType;
  457. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  458. WCHAR wzTemp[MAX_PATH];
  459. DWORD cbSize = sizeof(wzTemp);
  460. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
  461. // Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
  462. // This key is used if the customer wants to force different apps per protocol.
  463. DWORD dwError = SHGetValueW(HKEY_CLASSES_ROOT, wzRegKey, pszMailApp, &dwType, (void *)wzTemp, &cbSize);
  464. if (ERROR_SUCCESS == dwError)
  465. {
  466. fSupports = TRUE;
  467. }
  468. return fSupports;
  469. }
  470. HRESULT EmailAssoc_GetFirstMailAppForProtocol(IN LPCWSTR pszProtocol, IN LPWSTR pszMailApp, IN DWORD cchSize)
  471. {
  472. HRESULT hr;
  473. HKEY hkey;
  474. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  475. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
  476. DWORD dwError = RegOpenKey(HKEY_CLASSES_ROOT, wzRegKey, &hkey);
  477. hr = HRESULT_FROM_WIN32(dwError);
  478. if (SUCCEEDED(hr))
  479. {
  480. WCHAR wzTemp[MAX_PATH];
  481. DWORD cbSizeTemp = sizeof(wzTemp);
  482. DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
  483. DWORD dwType;
  484. // Read HKCR,"MailTransport\<Protocol>\Apps","<The First Value>"="<AppName | AppID>"
  485. dwError = SHEnumValueW(hkey, 0, pszMailApp, &cbSize, &dwType, (void *)wzTemp, &cbSizeTemp);
  486. hr = HRESULT_FROM_WIN32(dwError);
  487. RegCloseKey(hkey);
  488. }
  489. return hr;
  490. }
  491. //////////////////////////////////////
  492. // Other
  493. //////////////////////////////////////
  494. HRESULT EmailAssoc_CreateWebAssociation(IN LPCTSTR pszEmail, IN IMailProtocolADEntry * pMailProtocol)
  495. {
  496. BSTR bstrWebBaseEmailURL;
  497. HRESULT hr = pMailProtocol->get_ServerName(&bstrWebBaseEmailURL);
  498. if (SUCCEEDED(hr))
  499. {
  500. HKEY hkey;
  501. hr = EmailAssoc_CreateEmailAccount(pszEmail, &hkey);
  502. if (SUCCEEDED(hr))
  503. {
  504. hr = EmailAssoc_SetEmailAccountWebURL(hkey, bstrWebBaseEmailURL);
  505. if (SUCCEEDED(hr))
  506. {
  507. hr = EmailAssoc_SetEmailAccountProtocol(hkey, SZ_REGDATA_WEB);
  508. }
  509. RegCloseKey(hkey);
  510. }
  511. SysFreeString(bstrWebBaseEmailURL);
  512. }
  513. return hr;
  514. }
  515. HRESULT EmailAssoc_CreateStandardsBaseAssociation(IN LPCTSTR pszEmail, IN LPCTSTR pszProtocol)
  516. {
  517. HKEY hkey;
  518. HRESULT hr = EmailAssoc_CreateEmailAccount(pszEmail, &hkey);
  519. if (SUCCEEDED(hr))
  520. {
  521. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  522. DWORD cbSize = ((lstrlenW(L"") + 1) * sizeof(WCHAR));
  523. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGVALUE_MAILPROTOCOLS, pszProtocol);
  524. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>\MailProtocols\<protocol>","(default)"=""
  525. DWORD dwError = SHSetValueW(hkey, wzRegKey, NULL, REG_SZ, (void *)L"", cbSize);
  526. hr = HRESULT_FROM_WIN32(dwError);
  527. if (SUCCEEDED(hr))
  528. {
  529. WCHAR wzProtocol[MAX_PATH];
  530. SHTCharToUnicode(pszProtocol, wzProtocol, ARRAYSIZE(wzProtocol));
  531. cbSize = ((lstrlenW(SZ_REGDATA_WEB) + 1) * sizeof(SZ_REGDATA_WEB[0]));
  532. // Save HKCU,"Software\Microsoft\Windows\CurrentVersion\Explorer\Email\<EmailAddress>","MailProtocol"="<protocol>"
  533. DWORD dwError = SHSetValueW(hkey, NULL, SZ_REGVALUE_MAILPROTOCOL, REG_SZ, (void *)wzProtocol, cbSize);
  534. hr = HRESULT_FROM_WIN32(dwError);
  535. }
  536. RegCloseKey(hkey);
  537. }
  538. return hr;
  539. }
  540. HRESULT EmailAssoc_GetEmailAccountGetAppFromProtocol(IN LPCWSTR pszProtocol, IN LPWSTR pszMailApp, IN DWORD cchSize)
  541. {
  542. HRESULT hr;
  543. DWORD dwType;
  544. DWORD cbSize = (cchSize * sizeof(pszMailApp[0]));
  545. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  546. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
  547. // Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
  548. // This key is used if the customer wants to force different apps per protocol.
  549. DWORD dwError = SHGetValueW(HKEY_CLASSES_ROOT, wzRegKey, NULL, &dwType, (void *)pszMailApp, &cbSize);
  550. hr = HRESULT_FROM_WIN32(dwError);
  551. if (FAILED(hr))
  552. {
  553. // The user didn't force an app based on the protocol, so let's try the default app.
  554. hr = EmailAssoc_GetDefaultMailApp(pszMailApp, cchSize);
  555. // Lets see if the default email add supports this protocol, because we always want
  556. // to give preferense to the user's choosen mail app.
  557. if (FAILED(hr) || !EmailAssoc_DoesMailAppSupportProtocol(pszMailApp, pszProtocol))
  558. {
  559. // It doesn't support the protocol, so lets get the first app that does.
  560. hr = EmailAssoc_GetFirstMailAppForProtocol(pszProtocol, pszMailApp, cchSize);
  561. }
  562. }
  563. return hr;
  564. }
  565. HRESULT EmailAssoc_SetEmailAccountGetAppFromProtocol(IN LPCWSTR pszProtocol, IN LPCWSTR pszMailApp)
  566. {
  567. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  568. DWORD cbSize = ((lstrlenW(pszMailApp) + 1) * sizeof(pszMailApp[0]));
  569. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s", SZ_REGKEY_MAILTRANSPORT, pszProtocol);
  570. // Read HKCR,"MailTransport\<Protocol>","(Default)"="<AppName | AppID>"
  571. DWORD dwError = SHSetValueW(HKEY_CLASSES_ROOT, wzRegKey, NULL, REG_SZ, (void *)pszMailApp, cbSize);
  572. return HRESULT_FROM_WIN32(dwError);
  573. }
  574. LPCWSTR g_LegacyAssociations[][2] =
  575. {
  576. {L"Outlook Express", L"POP3"},
  577. {L"Outlook Express", L"IMAP"},
  578. {L"Outlook Express", L"DAVMail"},
  579. {L"Microsoft Outlook", L"POP3"},
  580. {L"Microsoft Outlook", L"IMAP"},
  581. {L"Microsoft Outlook", L"MAPI"},
  582. {L"Eudora", L"POP3"},
  583. {L"Eudora", L"IMAP"},
  584. };
  585. // Description:
  586. // This function will look at what applications are installed and setup the appropriate
  587. // legacy email associations.
  588. HRESULT EmailAssoc_InstallLegacyMailAppAssociations(void)
  589. {
  590. HRESULT hr = S_OK;
  591. for (int nIndex = 0; nIndex < ARRAYSIZE(g_LegacyAssociations); nIndex++)
  592. {
  593. HKEY hkey;
  594. // Is the app installed?
  595. hr = EmailAssoc_OpenMailApp(g_LegacyAssociations[nIndex][0], &hkey);
  596. if (SUCCEEDED(hr))
  597. {
  598. // Yes, so let's install the legacy association.
  599. // TODO: we should use GetFileVersionInfo() and VerQueryValue() to make sure
  600. // these are legacy versions.
  601. //hr = EmailAssoc_GetAppPath(IN HKEY hkey, IN LPTSTR pszAppPath, IN DWORD cchSize);
  602. WCHAR wzRegKey[MAXIMUM_SUB_KEY_LENGTH];
  603. wnsprintfW(wzRegKey, ARRAYSIZE(wzRegKey), L"%s\\%s\\Apps", SZ_REGKEY_MAILTRANSPORT, g_LegacyAssociations[nIndex][1]);
  604. SHSetValueW(HKEY_CLASSES_ROOT, wzRegKey, g_LegacyAssociations[nIndex][0], REG_SZ, (void *)L"", 4);
  605. RegCloseKey(hkey);
  606. }
  607. }
  608. return S_OK; // We succeed any way because we are just trying to upgrade.
  609. }
  610. #endif // FEATURE_EMAILASSOCIATIONS