#include "priv.h" #include "comcatex.h" #include "enumband.h" // Private forward decalarations typedef HRESULT (CALLBACK* PFNENUMCLSIDPROC)(REFGUID rguid, LPARAM lParam); typedef struct tagADDCATIDENUM { PFNENUMCATIDCLASSES pfnEnum; const CATID* pcatid; LPARAM lParam; } ADDCATIDENUM, *PADDCATIDENUM; STDMETHODIMP _SHEnumGUIDsWithCallback(IEnumCLSID* peclsid, PFNENUMCLSIDPROC pfnEnum, LPARAM lParam); STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum); STDMETHODIMP _AddCATIDEnum(REFCLSID rclsid, LPARAM lParam); STDMETHODIMP SHEnumClassesImplementingCATID(REFCATID rcatid, PFNENUMCATIDCLASSES pfnEnum, LPARAM lParam) { ADDCATIDENUM params; IEnumCLSID* peclsid; HRESULT hr; params.pcatid = &rcatid; params.pfnEnum = pfnEnum; params.lParam = lParam; hr = SHEnumClassesOfCategories(1, (CATID*)&rcatid, 0, NULL, &peclsid); if (FAILED(hr)) { return hr; } return _SHEnumGUIDsWithCallback(peclsid, _AddCATIDEnum, (LPARAM)¶ms); } //----- Private APIs ----- class CEnumRegGUIDs : public IEnumGUID { public: // *** IUnknown *** STDMETHOD (QueryInterface)(REFIID riid, PVOID* ppvObj); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // *** IEnumGUID *** STDMETHOD (Next)(ULONG celt, LPGUID rgelt, PULONG pceltFetched); STDMETHOD (Skip)(ULONG celt); STDMETHOD (Reset)(); STDMETHOD (Clone)(IEnumGUID** ppenum); protected: // constructor & destructor CEnumRegGUIDs(HKEY hk, PCTSTR pszKey); virtual ~CEnumRegGUIDs(); // data members HKEY _hkHive; TCHAR _szKey[MAX_PATH]; HKEY _hkGuids; ULONG _nCurrent; ULONG _cRef; friend STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum); }; //----- Constructor & Destructor ----- inline CEnumRegGUIDs::CEnumRegGUIDs(HKEY hk, PCTSTR pszKey) { _hkHive = hk; _szKey[0] = TEXT('\0'); StrCpy(_szKey, pszKey); _hkGuids = NULL; _nCurrent = 0; _cRef = 1; DllAddRef(); } CEnumRegGUIDs::~CEnumRegGUIDs() { if (NULL != _hkGuids) { RegCloseKey(_hkGuids); _hkGuids = NULL; } DllRelease(); } //----- IUnknown ----- HRESULT CEnumRegGUIDs::QueryInterface(REFIID riid, PVOID* ppvObj) { static const QITAB qit[] = { QITABENT(CEnumRegGUIDs, IEnumGUID), // IID_IEnumGUID { 0 }, }; return QISearch(this, qit, riid, ppvObj); } ULONG CEnumRegGUIDs::AddRef() { return ++_cRef; } ULONG CEnumRegGUIDs::Release() { ASSERT(0 < _cRef); if (0 != --_cRef) { return _cRef; } delete this; return 0; } //----- IEnumGUID ----- STDMETHODIMP CEnumRegGUIDs::Next(ULONG celt, LPGUID rgelt, PULONG pceltFetched) { TCHAR szGuid[GUIDSTR_MAX]; DWORD cchGuid; ULONG i, j; LONG lr; if (NULL != pceltFetched) { *pceltFetched = 0; } if (NULL == _hkGuids) { lr = RegOpenKeyEx(_hkHive, _szKey, 0, KEY_ENUMERATE_SUB_KEYS, &_hkGuids); if (ERROR_SUCCESS != lr) { return E_FAIL; } } ASSERT(NULL != _hkGuids); for (i = j = 0; i < celt; i++) { cchGuid = ARRAYSIZE(szGuid); lr = SHEnumKeyEx(_hkGuids, _nCurrent++, szGuid, &cchGuid); if (ERROR_SUCCESS != lr) { continue; } GUIDFromString(szGuid, &rgelt[j]); j++; } if (NULL != pceltFetched) { *pceltFetched = j; } return S_OK; } STDMETHODIMP CEnumRegGUIDs::Skip(ULONG celt) { _nCurrent += celt; return S_OK; } STDMETHODIMP CEnumRegGUIDs::Reset() { _nCurrent = 0; return S_OK; } STDMETHODIMP CEnumRegGUIDs::Clone(IEnumGUID** ppenum) { return E_NOTIMPL; } STDMETHODIMP _SHEnumGUIDsWithCallback(IEnumCLSID* peclsid, PFNENUMCLSIDPROC pfnEnum, LPARAM lParam) { CLSID clsid; HRESULT hr; ULONG i; if (NULL == peclsid || NULL == pfnEnum) { return E_INVALIDARG; } hr = S_OK; peclsid->Reset(); while (S_OK == peclsid->Next(1, &clsid, &i)) { hr = pfnEnum(clsid, lParam); if (S_OK != hr) { break; } } return hr; } STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum) { if (NULL == ppenum) { return E_INVALIDARG; } *ppenum = new CEnumRegGUIDs(hk, pszKey); return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY; } STDMETHODIMP _AddCATIDEnum(REFCLSID rclsid, LPARAM lParam) { PADDCATIDENUM p = (PADDCATIDENUM)lParam; ASSERT(NULL != p); ASSERT(NULL != p->pfnEnum); return (*p->pfnEnum)(*p->pcatid, rclsid, p->lParam); }