/* Copyright 1996-1997 Microsoft */ #include #include "sccls.h" #include "aclisf.h" #include "shellurl.h" #define AC_GENERAL TF_GENERAL + TF_AUTOCOMPLETE // // CACLMRU -- An AutoComplete List COM object that // enumerates the Type-in MRU. // class CACLMRU : public IEnumString , public IACList , public IACLCustomMRU { public: ////////////////////////////////////////////////////// // Public Interfaces ////////////////////////////////////////////////////// // *** IUnknown *** virtual STDMETHODIMP_(ULONG) AddRef(void); virtual STDMETHODIMP_(ULONG) Release(void); virtual STDMETHODIMP QueryInterface(REFIID riid, LPVOID * ppvObj); // *** IEnumString *** virtual STDMETHODIMP Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched); virtual STDMETHODIMP Skip(ULONG celt) {return E_NOTIMPL;} virtual STDMETHODIMP Reset(void); virtual STDMETHODIMP Clone(IEnumString **ppenum) {return E_NOTIMPL;} // *** IACList *** virtual STDMETHODIMP Expand(LPCOLESTR pszExpand) {return E_NOTIMPL;} // *** IACLCustomMRU *** virtual STDMETHODIMP Initialize(LPCWSTR pszMRURegKey, DWORD dwMax); virtual STDMETHODIMP AddMRUString(LPCWSTR pszEntry); private: // Constructor / Destructor (protected so we can't create on stack) CACLMRU(); ~CACLMRU(void); // Instance creator friend HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi); friend HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi, LPCTSTR pszMRU); friend HRESULT CACLCustomMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi); // Private variables DWORD m_cRef; // COM reference count HKEY m_hKey; // HKey of MRU Location BOOL m_bBackCompat; // true for run dialog and address bar DWORD m_nMRUIndex; // Current Index into MRU DWORD m_dwRunMRUSize; HANDLE m_hMRU; }; /* IUnknown methods */ HRESULT CACLMRU::QueryInterface(REFIID riid, void **ppvObj) { static const QITAB qit[] = { QITABENT(CACLMRU, IEnumString), QITABENT(CACLMRU, IACList), QITABENT(CACLMRU, IACLCustomMRU), { 0 }, }; return QISearch(this, qit, riid, ppvObj); } ULONG CACLMRU::AddRef(void) { m_cRef++; return m_cRef; } ULONG CACLMRU::Release(void) { ASSERT(m_cRef > 0); m_cRef--; if (m_cRef > 0) { return m_cRef; } delete this; return 0; } /* IEnumString methods */ HRESULT CACLMRU::Reset(void) { TraceMsg(AC_GENERAL, "CACLMRU::Reset()"); m_nMRUIndex = 0; return S_OK; } HRESULT CACLMRU::Next(ULONG celt, LPOLESTR *rgelt, ULONG *pceltFetched) { HRESULT hr = S_OK; TCHAR szMRUEntry[MAX_URL_STRING+1]; LPWSTR pwzMRUEntry = NULL; *pceltFetched = 0; if (!celt) return S_OK; if (!rgelt) return S_FALSE; if (!m_hMRU) { hr = GetMRUEntry(m_hKey, m_nMRUIndex++, szMRUEntry, SIZECHARS(szMRUEntry), NULL); if (S_OK != hr) { hr = S_FALSE; // This will indicate that no more items are in the list. } } else { hr = S_FALSE; if (m_nMRUIndex < m_dwRunMRUSize && EnumMRUList(m_hMRU, m_nMRUIndex++, szMRUEntry, ARRAYSIZE(szMRUEntry)) > 0) { if (m_bBackCompat) { // old MRU format has a slash at the end with the show cmd LPTSTR pszField = StrRChr(szMRUEntry, NULL, TEXT('\\')); if (pszField) pszField[0] = TEXT('\0'); } hr = S_OK; } } if (S_OK == hr) { hr = SHStrDup(szMRUEntry, rgelt); if (SUCCEEDED(hr)) *pceltFetched = 1; } return hr; } /* Constructor / Destructor / CreateInstance */ CACLMRU::CACLMRU() : m_cRef(1), m_bBackCompat(TRUE) { DllAddRef(); // Require object to be in heap and Zero-Inited ASSERT(!m_hKey); ASSERT(!m_nMRUIndex); ASSERT(!m_hMRU); } CACLMRU::~CACLMRU() { if (m_hKey) RegCloseKey(m_hKey); if (m_hMRU) FreeMRUList(m_hMRU); DllRelease(); } /****************************************************\ FUNCTION: CACLMRU_CreateInstance DESCRIPTION: This function create an instance of the AutoComplete List "MRU". The caller didn't specify which MRU list to use, so we default to the TYPE-IN CMD MRU, which is used in the Start->Run dialog and in AddressBars that are floating or in the Taskbar. \****************************************************/ HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi) { return CACLMRU_CreateInstance(punkOuter, ppunk, poi, SZ_REGKEY_TYPEDCMDMRU); } /****************************************************\ FUNCTION: CACLMRU_CreateInstance DESCRIPTION: This function create an instance of the AutoComplete List "MRU". This will point to either the MRU for a browser or for a non-browser (Start->Run or the AddressBar in the Taskbar or floating) depending on the pszMRU parameter. \****************************************************/ HRESULT CACLMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi, LPCTSTR pszMRU) { *ppunk = NULL; HRESULT hr = E_OUTOFMEMORY; BOOL fUseRunDlgMRU = (StrCmpI(pszMRU, SZ_REGKEY_TYPEDCMDMRU) ? FALSE : TRUE); CACLMRU *paclSF = new CACLMRU(); if (paclSF) { hr = paclSF->Initialize(pszMRU, 26); if (SUCCEEDED(hr)) { paclSF->AddRef(); *ppunk = SAFECAST(paclSF, IEnumString *); } paclSF->Release(); } return hr; } HRESULT CACLCustomMRU_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi) { *ppunk = NULL; CACLMRU *pmru = new CACLMRU(); if (pmru) { *ppunk = SAFECAST(pmru, IEnumString *); return S_OK; } return E_OUTOFMEMORY; } #define SZ_REGKEY_TYPEDURLMRUW L"Software\\Microsoft\\Internet Explorer\\TypedURLs" #define SZ_REGKEY_TYPEDCMDMRUW L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\RunMRU" HRESULT CACLMRU::Initialize(LPCWSTR pszMRURegKey, DWORD dwMax) { HRESULT hr = S_OK; BOOL bURL = StrCmpIW(pszMRURegKey, SZ_REGKEY_TYPEDURLMRUW) ? FALSE : TRUE; if (!bURL) { MRUINFO mi = { SIZEOF(MRUINFO), dwMax, MRU_CACHEWRITE, HKEY_CURRENT_USER, pszMRURegKey, NULL // NOTE: use default string compare // since this is a GLOBAL MRU }; m_bBackCompat = StrCmpIW(pszMRURegKey, SZ_REGKEY_TYPEDCMDMRUW) ? FALSE : TRUE; m_hMRU = CreateMRUList(&mi); if (m_hMRU) m_dwRunMRUSize = EnumMRUList(m_hMRU, -1, NULL, 0); else hr = E_FAIL; } else { m_bBackCompat = TRUE; if (ERROR_SUCCESS != RegCreateKeyEx(HKEY_CURRENT_USER, pszMRURegKey, 0, NULL, 0, KEY_READ, NULL, &m_hKey, NULL)) hr = E_FAIL; } return hr; } HRESULT CACLMRU::AddMRUString(LPCWSTR pszEntry) { HRESULT hr = E_FAIL; if (m_hMRU) { if (::AddMRUString(m_hMRU, pszEntry) != -1) hr = S_OK; } //else We don't support saving for address bar MRU return hr; }