Windows2000/private/shell/browseui/aclmru.cpp
2020-09-30 17:12:32 +02:00

287 lines
6.9 KiB
C++

/* Copyright 1996-1997 Microsoft */
#include <priv.h>
#include "sccls.h"
#include "dbgmem.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:
// 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;}
private:
// Constructor / Destructor (protected so we can't create on stack)
CACLMRU(LPCTSTR pszMRURegKey, BOOL fUseStaertRun);
~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);
// Private variables
DWORD m_cRef; // COM reference count
HKEY m_hKey; // HKey of MRU Location
DWORD m_nMRUIndex; // Current Index into MRU
LPTSTR m_pszMRURegKey; // RegKey Name of MRU Location
BITBOOL m_fInRunMRU : 1; // Are we in the RunMRU?
DWORD m_dwRunMRUIndex; // Index into the Run MRU.
DWORD m_dwRunMRUSize;
HANDLE m_hMRURun;
};
/* IUnknown methods */
HRESULT CACLMRU::QueryInterface(REFIID riid, void **ppvObj)
{
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IEnumString))
{
*ppvObj = SAFECAST(this, IEnumString*);
}
else if (IsEqualIID(riid, IID_IACList))
{
*ppvObj = SAFECAST(this, IACList*);
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
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)
{
HRESULT hr = S_OK;
TraceMsg(AC_GENERAL, "CACLMRU::Reset()");
m_nMRUIndex = 0;
m_fInRunMRU = FALSE;
m_dwRunMRUIndex = 0;
// If we haven't yet opened the key, open it.
if (!m_hKey && (ERROR_SUCCESS != RegCreateKey(HKEY_CURRENT_USER, m_pszMRURegKey, &m_hKey)))
hr = E_FAIL;
return hr;
}
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_fInRunMRU)
{
hr = GetMRUEntry(m_hKey, m_nMRUIndex++, szMRUEntry, SIZECHARS(szMRUEntry), NULL);
if (S_OK != hr)
{
if (m_hMRURun)
m_fInRunMRU = TRUE; // Switch to using the Run MRU List now.
else
hr = S_FALSE; // This will indicate that no more items are in the list.
}
}
if (m_fInRunMRU)
{
if (m_dwRunMRUIndex >= m_dwRunMRUSize)
hr = S_FALSE; // No more.
else
{
if (EVAL(m_hMRURun) && EnumMRUList(m_hMRURun, m_dwRunMRUIndex++, szMRUEntry, ARRAYSIZE(szMRUEntry)) > 0)
{
// 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;
}
else
hr = S_FALSE;
}
}
if (S_OK == hr)
{
DWORD cchSize = lstrlen(szMRUEntry)+1;
// Allocate a return buffer (caller will free it).
pwzMRUEntry = (LPOLESTR)CoTaskMemAlloc(cchSize * SIZEOF(WCHAR));
if (pwzMRUEntry)
{
// Convert the display name into an OLESTR.
#ifdef UNICODE
StrCpyN(pwzMRUEntry, szMRUEntry, cchSize);
#else // ANSI
MultiByteToWideChar(CP_ACP, 0, szMRUEntry, -1, pwzMRUEntry, cchSize);
#endif // ANSI
rgelt[0] = pwzMRUEntry;
*pceltFetched = 1;
}
else
hr = E_OUTOFMEMORY;
}
return hr;
}
/* Constructor / Destructor / CreateInstance */
CACLMRU::CACLMRU(LPCTSTR pszMRURegKey, BOOL fUseStaertRun)
{
DllAddRef();
// Require object to be in heap and Zero-Inited
ASSERT(!m_hKey);
ASSERT(!m_nMRUIndex);
ASSERT(!m_fInRunMRU);
ASSERT(!m_dwRunMRUIndex);
ASSERT(!m_hMRURun);
if (fUseStaertRun)
{
MRUINFO mi = {
SIZEOF(MRUINFO),
26,
MRU_CACHEWRITE,
HKEY_CURRENT_USER,
SZ_REGKEY_TYPEDCMDMRU,
NULL // NOTE: use default string compare
// since this is a GLOBAL MRU
};
m_hMRURun = CreateMRUList(&mi);
if (EVAL(m_hMRURun))
m_dwRunMRUSize = EnumMRUList(m_hMRURun, -1, NULL, 0);
}
// Init Member Variables
Str_SetPtr(&m_pszMRURegKey, pszMRURegKey);
m_cRef = 1;
}
CACLMRU::~CACLMRU()
{
if (m_hKey)
RegCloseKey(m_hKey);
if (m_hMRURun)
FreeMRUList(m_hMRURun);
Str_SetPtr(&m_pszMRURegKey, NULL);
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;
BOOL fUseRunDlgMRU = (StrCmpI(pszMRU, SZ_REGKEY_TYPEDCMDMRU) ? FALSE : TRUE);
CACLMRU *paclSF = new CACLMRU(pszMRU, fUseRunDlgMRU);
if (paclSF)
{
*ppunk = SAFECAST(paclSF, IEnumString *);
return S_OK;
}
return E_OUTOFMEMORY;
}