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.

341 lines
8.6 KiB

  1. /*****************************************************************************\
  2. FILE: ACEmail.cpp
  3. DESCRIPTION:
  4. This file implements AutoComplete for Email Addresses.
  5. BryanSt 3/1/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 "MailBox.h"
  14. #define MAX_EMAIL_MRU_SIZE 100
  15. class CACLEmail
  16. : public IEnumString
  17. , public IACList
  18. {
  19. public:
  20. //////////////////////////////////////////////////////
  21. // Public Interfaces
  22. //////////////////////////////////////////////////////
  23. // *** IUnknown ***
  24. virtual STDMETHODIMP_(ULONG) AddRef(void);
  25. virtual STDMETHODIMP_(ULONG) Release(void);
  26. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  27. // *** IEnumString ***
  28. virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
  29. virtual STDMETHODIMP Skip(ULONG celt) {return E_NOTIMPL;}
  30. virtual STDMETHODIMP Reset(void);
  31. virtual STDMETHODIMP Clone(IEnumString **ppenum) {return E_NOTIMPL;}
  32. // *** IACList ***
  33. virtual STDMETHODIMP Expand(LPCOLESTR pszExpand) {return E_NOTIMPL;}
  34. private:
  35. // Constructor / Destructor (protected so we can't create on stack)
  36. CACLEmail(LPCTSTR pszMRURegKey);
  37. ~CACLEmail(void);
  38. HRESULT AddEmail(IN LPCWSTR pszEmailAddress);
  39. // Instance creator
  40. friend HRESULT CACLEmail_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT void ** ppvObj);
  41. friend HRESULT AddEmailToAutoComplete(IN LPCWSTR pszEmailAddress);
  42. // Private variables
  43. DWORD m_cRef; // COM reference count
  44. DWORD m_nMRUIndex; // Current Index into MRU
  45. DWORD m_dwRunMRUIndex; // Index into the Run MRU.
  46. DWORD m_dwRunMRUSize;
  47. HANDLE m_hMRURun;
  48. };
  49. //===========================
  50. // *** IEnumString Interface ***
  51. //===========================
  52. HRESULT CACLEmail::Reset(void)
  53. {
  54. HRESULT hr = S_OK;
  55. m_nMRUIndex = 0;
  56. m_dwRunMRUIndex = 0;
  57. return hr;
  58. }
  59. HRESULT CACLEmail::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
  60. {
  61. HRESULT hr = S_OK;
  62. TCHAR szMRUEntry[MAX_URL_STRING+1];
  63. LPWSTR pwzMRUEntry = NULL;
  64. *pceltFetched = 0;
  65. if (!celt)
  66. return S_OK;
  67. if (!rgelt)
  68. return S_FALSE;
  69. *rgelt = 0;
  70. if (m_dwRunMRUIndex >= m_dwRunMRUSize)
  71. hr = S_FALSE; // No more.
  72. else
  73. {
  74. if (m_hMRURun && EnumMRUList(m_hMRURun, m_dwRunMRUIndex++, szMRUEntry, ARRAYSIZE(szMRUEntry)) > 0)
  75. {
  76. hr = S_OK;
  77. }
  78. else
  79. hr = S_FALSE;
  80. }
  81. if (S_OK == hr)
  82. {
  83. DWORD cchSize = lstrlen(szMRUEntry)+1;
  84. //
  85. // Allocate a return buffer (caller will free it).
  86. //
  87. pwzMRUEntry = (LPOLESTR)CoTaskMemAlloc(cchSize * sizeof(pwzMRUEntry[0]));
  88. if (pwzMRUEntry)
  89. {
  90. //
  91. // Convert the display name into an OLESTR.
  92. //
  93. #ifdef UNICODE
  94. StrCpyN(pwzMRUEntry, szMRUEntry, cchSize);
  95. #else // ANSI
  96. MultiByteToWideChar(CP_ACP, 0, szMRUEntry, -1, pwzMRUEntry, cchSize);
  97. #endif // ANSI
  98. rgelt[0] = pwzMRUEntry;
  99. *pceltFetched = 1;
  100. }
  101. else
  102. hr = E_OUTOFMEMORY;
  103. }
  104. return hr;
  105. }
  106. //===========================
  107. // *** IUnknown Interface ***
  108. //===========================
  109. STDMETHODIMP CACLEmail::QueryInterface(REFIID riid, LPVOID *ppvObj)
  110. {
  111. static const QITAB qit[] = {
  112. QITABENT(CACLEmail, IEnumString),
  113. QITABENT(CACLEmail, IACList),
  114. { 0 },
  115. };
  116. return QISearch(this, qit, riid, ppvObj);
  117. }
  118. ULONG CACLEmail::AddRef(void)
  119. {
  120. m_cRef++;
  121. return m_cRef;
  122. }
  123. ULONG CACLEmail::Release(void)
  124. {
  125. ASSERT(m_cRef > 0);
  126. m_cRef--;
  127. if (m_cRef > 0)
  128. {
  129. return m_cRef;
  130. }
  131. delete this;
  132. return 0;
  133. }
  134. //===========================
  135. // *** Class Methods ***
  136. //===========================
  137. HRESULT CACLEmail::AddEmail(IN LPCWSTR pszEmailAddress)
  138. {
  139. HRESULT hr = S_OK;
  140. if (-1 == AddMRUStringW(m_hMRURun, pszEmailAddress))
  141. {
  142. hr = HRESULT_FROM_WIN32(GetLastError());
  143. }
  144. return hr;
  145. }
  146. CACLEmail::CACLEmail(LPCTSTR pszMRURegKey)
  147. {
  148. DllAddRef();
  149. // Require object to be in heap and Zero-Inited
  150. ASSERT(!m_nMRUIndex);
  151. ASSERT(!m_dwRunMRUIndex);
  152. ASSERT(!m_hMRURun);
  153. MRUINFO mi = {
  154. sizeof(MRUINFO),
  155. MAX_EMAIL_MRU_SIZE,
  156. MRU_CACHEWRITE,
  157. HKEY_CURRENT_USER,
  158. SZ_REGKEY_EMAIL_MRU,
  159. NULL // NOTE: use default string compare
  160. // since this is a GLOBAL MRU
  161. };
  162. m_hMRURun = CreateMRUList(&mi);
  163. if (m_hMRURun)
  164. m_dwRunMRUSize = EnumMRUList(m_hMRURun, -1, NULL, 0);
  165. m_cRef = 1;
  166. }
  167. CACLEmail::~CACLEmail()
  168. {
  169. if (m_hMRURun)
  170. FreeMRUList(m_hMRURun);
  171. DllRelease();
  172. }
  173. /****************************************************\
  174. DESCRIPTION:
  175. This function create an instance of the AutoComplete
  176. List "MRU". This will point to either the MRU for
  177. a browser or for a non-browser (Start->Run or
  178. the AddressBar in the Taskbar or floating) depending
  179. on the pszMRU parameter.
  180. \****************************************************/
  181. HRESULT CACLEmail_CreateInstance(IN IUnknown * punkOuter, IN REFIID riid, OUT void ** ppvObj)
  182. {
  183. HRESULT hr = E_OUTOFMEMORY;
  184. CACLEmail *paclSF = new CACLEmail(NULL);
  185. if (paclSF)
  186. {
  187. hr = paclSF->QueryInterface(riid, ppvObj);
  188. paclSF->Release();
  189. }
  190. else
  191. {
  192. *ppvObj = NULL;
  193. }
  194. return hr;
  195. }
  196. HRESULT AddEmailToAutoComplete(IN LPCWSTR pszEmailAddress)
  197. {
  198. HRESULT hr = E_OUTOFMEMORY;
  199. CACLEmail *paclSF = new CACLEmail(NULL);
  200. if (paclSF)
  201. {
  202. hr = paclSF->AddEmail(pszEmailAddress);
  203. paclSF->Release();
  204. }
  205. return hr;
  206. }
  207. #define SZ_REGKEY_AUTOCOMPLETE_TAB TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\AutoComplete")
  208. #define SZ_REGVALUE_AUTOCOMPLETE_TAB TEXT("Always Use Tab")
  209. #define BOOL_NOT_SET 0x00000005
  210. DWORD _UpdateAutoCompleteFlags(void)
  211. {
  212. DWORD dwACOptions = 0;
  213. if (SHRegGetBoolUSValue(REGSTR_PATH_AUTOCOMPLETE, REGSTR_VAL_USEAUTOAPPEND, FALSE, /*default:*/FALSE))
  214. {
  215. dwACOptions |= ACO_AUTOAPPEND;
  216. }
  217. if (SHRegGetBoolUSValue(REGSTR_PATH_AUTOCOMPLETE, REGSTR_VAL_USEAUTOSUGGEST, FALSE, /*default:*/TRUE))
  218. {
  219. dwACOptions |= ACO_AUTOSUGGEST;
  220. }
  221. // Windows uses the TAB key to move between controls in a dialog. UNIX and other
  222. // operating systems that use AutoComplete have traditionally used the TAB key to
  223. // iterate thru the AutoComplete possibilities. We need to default to disable the
  224. // TAB key (ACO_USETAB) unless the caller specifically wants it. We will also
  225. // turn it on
  226. static BOOL s_fAlwaysUseTab = BOOL_NOT_SET;
  227. if (BOOL_NOT_SET == s_fAlwaysUseTab)
  228. s_fAlwaysUseTab = SHRegGetBoolUSValue(SZ_REGKEY_AUTOCOMPLETE_TAB, SZ_REGVALUE_AUTOCOMPLETE_TAB, FALSE, FALSE);
  229. if (s_fAlwaysUseTab)
  230. dwACOptions |= ACO_USETAB;
  231. return dwACOptions;
  232. }
  233. // TODO: Move this functionality to SHAutoComplete when it's ready.
  234. STDAPI AddEmailAutoComplete(HWND hwndEdit)
  235. {
  236. IUnknown * punkACL = NULL;
  237. DWORD dwACOptions = _UpdateAutoCompleteFlags();
  238. HRESULT hr = CACLEmail_CreateInstance(NULL, IID_PPV_ARG(IUnknown, &punkACL));
  239. if (punkACL) // May fail on low memory.
  240. {
  241. IAutoComplete2 * pac;
  242. // Create the AutoComplete Object
  243. hr = CoCreateInstance(CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IAutoComplete2, &pac));
  244. if (SUCCEEDED(hr)) // May fail because of out of memory
  245. {
  246. if (SHPinDllOfCLSID(&CLSID_ACListISF) &&
  247. SHPinDllOfCLSID(&CLSID_AutoComplete))
  248. {
  249. hr = pac->Init(hwndEdit, punkACL, NULL, NULL);
  250. pac->SetOptions(dwACOptions);
  251. }
  252. else
  253. {
  254. hr = E_FAIL;
  255. }
  256. pac->Release();
  257. }
  258. punkACL->Release();
  259. }
  260. return hr;
  261. }