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.

286 lines
7.6 KiB

  1. /* Copyright 1996-1997 Microsoft */
  2. #include <priv.h>
  3. #include "sccls.h"
  4. #include "aclisf.h"
  5. #include "shellurl.h"
  6. #define AC_GENERAL TF_GENERAL + TF_AUTOCOMPLETE
  7. //
  8. // CACLMRU -- An AutoComplete List COM object that
  9. // enumerates the Type-in MRU.
  10. //
  11. class CACLMRU
  12. : public IEnumString
  13. , public IACList
  14. , public IACLCustomMRU
  15. {
  16. public:
  17. //////////////////////////////////////////////////////
  18. // Public Interfaces
  19. //////////////////////////////////////////////////////
  20. // *** IUnknown ***
  21. virtual STDMETHODIMP_(ULONG) AddRef(void);
  22. virtual STDMETHODIMP_(ULONG) Release(void);
  23. virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj);
  24. // *** IEnumString ***
  25. virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched);
  26. virtual STDMETHODIMP Skip(ULONG celt) {return E_NOTIMPL;}
  27. virtual STDMETHODIMP Reset(void);
  28. virtual STDMETHODIMP Clone(IEnumString **ppenum) {return E_NOTIMPL;}
  29. // *** IACList ***
  30. virtual STDMETHODIMP Expand(LPCOLESTR pszExpand) {return E_NOTIMPL;}
  31. // *** IACLCustomMRU ***
  32. virtual STDMETHODIMP Initialize(LPCWSTR pszMRURegKey, DWORD dwMax);
  33. virtual STDMETHODIMP AddMRUString(LPCWSTR pszEntry);
  34. private:
  35. // Constructor / Destructor (protected so we can't create on stack)
  36. CACLMRU();
  37. ~CACLMRU(void);
  38. // Instance creator
  39. friend HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  40. friend HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi, LPCTSTR pszMRU);
  41. friend HRESULT CACLCustomMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  42. // Private variables
  43. DWORD m_cRef; // COM reference count
  44. HKEY m_hKey; // HKey of MRU Location
  45. BOOL m_bBackCompat; // true for run dialog and address bar
  46. DWORD m_nMRUIndex; // Current Index into MRU
  47. DWORD m_dwRunMRUSize;
  48. HANDLE m_hMRU;
  49. };
  50. /* IUnknown methods */
  51. HRESULT CACLMRU::QueryInterface(REFIID riid, void **ppvObj)
  52. {
  53. static const QITAB qit[] = {
  54. QITABENT(CACLMRU, IEnumString),
  55. QITABENT(CACLMRU, IACList),
  56. QITABENT(CACLMRU, IACLCustomMRU),
  57. { 0 },
  58. };
  59. return QISearch(this, qit, riid, ppvObj);
  60. }
  61. ULONG CACLMRU::AddRef(void)
  62. {
  63. m_cRef++;
  64. return m_cRef;
  65. }
  66. ULONG CACLMRU::Release(void)
  67. {
  68. ASSERT(m_cRef > 0);
  69. m_cRef--;
  70. if (m_cRef > 0)
  71. {
  72. return m_cRef;
  73. }
  74. delete this;
  75. return 0;
  76. }
  77. /* IEnumString methods */
  78. HRESULT CACLMRU::Reset(void)
  79. {
  80. TraceMsg(AC_GENERAL, "CACLMRU::Reset()");
  81. m_nMRUIndex = 0;
  82. return S_OK;
  83. }
  84. HRESULT CACLMRU::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched)
  85. {
  86. HRESULT hr = S_OK;
  87. TCHAR szMRUEntry[MAX_URL_STRING+1];
  88. LPWSTR pwzMRUEntry = NULL;
  89. *pceltFetched = 0;
  90. if (!celt)
  91. return S_OK;
  92. if (!rgelt)
  93. return S_FALSE;
  94. if (!m_hMRU)
  95. {
  96. hr = GetMRUEntry(m_hKey, m_nMRUIndex++, szMRUEntry, SIZECHARS(szMRUEntry), NULL);
  97. if (S_OK != hr)
  98. {
  99. hr = S_FALSE; // This will indicate that no more items are in the list.
  100. }
  101. }
  102. else
  103. {
  104. hr = S_FALSE;
  105. if (m_nMRUIndex < m_dwRunMRUSize && EnumMRUList(m_hMRU, m_nMRUIndex++, szMRUEntry, ARRAYSIZE(szMRUEntry)) > 0)
  106. {
  107. if (m_bBackCompat)
  108. {
  109. // old MRU format has a slash at the end with the show cmd
  110. LPTSTR pszField = StrRChr(szMRUEntry, NULL, TEXT('\\'));
  111. if (pszField)
  112. pszField[0] = TEXT('\0');
  113. }
  114. hr = S_OK;
  115. }
  116. }
  117. if (S_OK == hr)
  118. {
  119. hr = SHStrDup(szMRUEntry, rgelt);
  120. if (SUCCEEDED(hr))
  121. *pceltFetched = 1;
  122. }
  123. return hr;
  124. }
  125. /* Constructor / Destructor / CreateInstance */
  126. CACLMRU::CACLMRU() : m_cRef(1), m_bBackCompat(TRUE)
  127. {
  128. DllAddRef();
  129. // Require object to be in heap and Zero-Inited
  130. ASSERT(!m_hKey);
  131. ASSERT(!m_nMRUIndex);
  132. ASSERT(!m_hMRU);
  133. }
  134. CACLMRU::~CACLMRU()
  135. {
  136. if (m_hKey)
  137. RegCloseKey(m_hKey);
  138. if (m_hMRU)
  139. FreeMRUList(m_hMRU);
  140. DllRelease();
  141. }
  142. /****************************************************\
  143. FUNCTION: CACLMRU_CreateInstance
  144. DESCRIPTION:
  145. This function create an instance of the AutoComplete
  146. List "MRU". The caller didn't specify which MRU
  147. list to use, so we default to the TYPE-IN CMD
  148. MRU, which is used in the Start->Run dialog and
  149. in AddressBars that are floating or in the Taskbar.
  150. \****************************************************/
  151. HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  152. {
  153. return CACLMRU_CreateInstance(punkOuter, ppunk, poi, SZ_REGKEY_TYPEDCMDMRU);
  154. }
  155. /****************************************************\
  156. FUNCTION: CACLMRU_CreateInstance
  157. DESCRIPTION:
  158. This function create an instance of the AutoComplete
  159. List "MRU". This will point to either the MRU for
  160. a browser or for a non-browser (Start->Run or
  161. the AddressBar in the Taskbar or floating) depending
  162. on the pszMRU parameter.
  163. \****************************************************/
  164. HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi, LPCTSTR pszMRU)
  165. {
  166. *ppunk = NULL;
  167. HRESULT hr = E_OUTOFMEMORY;
  168. BOOL fUseRunDlgMRU = (StrCmpI(pszMRU, SZ_REGKEY_TYPEDCMDMRU) ? FALSE : TRUE);
  169. CACLMRU *paclSF = new CACLMRU();
  170. if (paclSF)
  171. {
  172. hr = paclSF->Initialize(pszMRU, 26);
  173. if (SUCCEEDED(hr))
  174. {
  175. paclSF->AddRef();
  176. *ppunk = SAFECAST(paclSF, IEnumString *);
  177. }
  178. paclSF->Release();
  179. }
  180. return hr;
  181. }
  182. HRESULT CACLCustomMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi)
  183. {
  184. *ppunk = NULL;
  185. CACLMRU *pmru = new CACLMRU();
  186. if (pmru)
  187. {
  188. *ppunk = SAFECAST(pmru, IEnumString *);
  189. return S_OK;
  190. }
  191. return E_OUTOFMEMORY;
  192. }
  193. #define SZ_REGKEY_TYPEDURLMRUW L"Software\\Microsoft\\Internet Explorer\\TypedURLs"
  194. #define SZ_REGKEY_TYPEDCMDMRUW L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU"
  195. HRESULT CACLMRU::Initialize(LPCWSTR pszMRURegKey, DWORD dwMax)
  196. {
  197. HRESULT hr = S_OK;
  198. BOOL bURL = StrCmpIW(pszMRURegKey, SZ_REGKEY_TYPEDURLMRUW) ? FALSE : TRUE;
  199. if (!bURL)
  200. {
  201. MRUINFO mi = {
  202. SIZEOF(MRUINFO),
  203. dwMax,
  204. MRU_CACHEWRITE,
  205. HKEY_CURRENT_USER,
  206. pszMRURegKey,
  207. NULL // NOTE: use default string compare
  208. // since this is a GLOBAL MRU
  209. };
  210. m_bBackCompat = StrCmpIW(pszMRURegKey, SZ_REGKEY_TYPEDCMDMRUW) ? FALSE : TRUE;
  211. m_hMRU = CreateMRUList(&mi);
  212. if (m_hMRU)
  213. m_dwRunMRUSize = EnumMRUList(m_hMRU, -1, NULL, 0);
  214. else
  215. hr = E_FAIL;
  216. }
  217. else
  218. {
  219. m_bBackCompat = TRUE;
  220. if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, pszMRURegKey, 0, NULL, 0, KEY_READ, NULL, &m_hKey, NULL))
  221. hr = E_FAIL;
  222. }
  223. return hr;
  224. }
  225. HRESULT CACLMRU::AddMRUString(LPCWSTR pszEntry)
  226. {
  227. HRESULT hr = E_FAIL;
  228. if (m_hMRU)
  229. {
  230. if (::AddMRUString(m_hMRU, pszEntry) != -1)
  231. hr = S_OK;
  232. }
  233. //else We don't support saving for address bar MRU
  234. return hr;
  235. }