Source code of Windows XP (NT5)
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.

236 lines
4.6 KiB

  1. #include "priv.h"
  2. #include "comcatex.h"
  3. #include "enumband.h"
  4. // Private forward decalarations
  5. typedef HRESULT (CALLBACK* PFNENUMCLSIDPROC)(REFGUID rguid, LPARAM lParam);
  6. typedef struct tagADDCATIDENUM
  7. {
  8. PFNENUMCATIDCLASSES pfnEnum;
  9. const CATID* pcatid;
  10. LPARAM lParam;
  11. } ADDCATIDENUM, *PADDCATIDENUM;
  12. STDMETHODIMP _SHEnumGUIDsWithCallback(IEnumCLSID* peclsid, PFNENUMCLSIDPROC pfnEnum, LPARAM lParam);
  13. STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum);
  14. STDMETHODIMP _AddCATIDEnum(REFCLSID rclsid, LPARAM lParam);
  15. STDMETHODIMP SHEnumClassesImplementingCATID(REFCATID rcatid, PFNENUMCATIDCLASSES pfnEnum, LPARAM lParam)
  16. {
  17. ADDCATIDENUM params;
  18. IEnumCLSID* peclsid;
  19. HRESULT hr;
  20. params.pcatid = &rcatid;
  21. params.pfnEnum = pfnEnum;
  22. params.lParam = lParam;
  23. hr = SHEnumClassesOfCategories(1, (CATID*)&rcatid, 0, NULL, &peclsid);
  24. if (FAILED(hr))
  25. {
  26. return hr;
  27. }
  28. return _SHEnumGUIDsWithCallback(peclsid, _AddCATIDEnum, (LPARAM)&params);
  29. }
  30. //----- Private APIs -----
  31. class CEnumRegGUIDs : public IEnumGUID
  32. {
  33. public:
  34. // *** IUnknown ***
  35. STDMETHOD (QueryInterface)(REFIID riid, PVOID* ppvObj);
  36. STDMETHOD_(ULONG, AddRef)();
  37. STDMETHOD_(ULONG, Release)();
  38. // *** IEnumGUID ***
  39. STDMETHOD (Next)(ULONG celt, LPGUID rgelt, PULONG pceltFetched);
  40. STDMETHOD (Skip)(ULONG celt);
  41. STDMETHOD (Reset)();
  42. STDMETHOD (Clone)(IEnumGUID** ppenum);
  43. protected:
  44. // constructor & destructor
  45. CEnumRegGUIDs(HKEY hk, PCTSTR pszKey);
  46. virtual ~CEnumRegGUIDs();
  47. // data members
  48. HKEY _hkHive;
  49. TCHAR _szKey[MAX_PATH];
  50. HKEY _hkGuids;
  51. ULONG _nCurrent;
  52. ULONG _cRef;
  53. friend STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum);
  54. };
  55. //----- Constructor & Destructor -----
  56. inline CEnumRegGUIDs::CEnumRegGUIDs(HKEY hk, PCTSTR pszKey)
  57. {
  58. _hkHive = hk;
  59. _szKey[0] = TEXT('\0');
  60. StrCpy(_szKey, pszKey);
  61. _hkGuids = NULL;
  62. _nCurrent = 0;
  63. _cRef = 1;
  64. DllAddRef();
  65. }
  66. CEnumRegGUIDs::~CEnumRegGUIDs()
  67. {
  68. if (NULL != _hkGuids)
  69. {
  70. RegCloseKey(_hkGuids);
  71. _hkGuids = NULL;
  72. }
  73. DllRelease();
  74. }
  75. //----- IUnknown -----
  76. HRESULT CEnumRegGUIDs::QueryInterface(REFIID riid, PVOID* ppvObj)
  77. {
  78. static const QITAB qit[] =
  79. {
  80. QITABENT(CEnumRegGUIDs, IEnumGUID), // IID_IEnumGUID
  81. { 0 },
  82. };
  83. return QISearch(this, qit, riid, ppvObj);
  84. }
  85. ULONG CEnumRegGUIDs::AddRef()
  86. {
  87. return ++_cRef;
  88. }
  89. ULONG CEnumRegGUIDs::Release()
  90. {
  91. ASSERT(0 < _cRef);
  92. if (0 != --_cRef)
  93. {
  94. return _cRef;
  95. }
  96. delete this;
  97. return 0;
  98. }
  99. //----- IEnumGUID -----
  100. STDMETHODIMP CEnumRegGUIDs::Next(ULONG celt, LPGUID rgelt, PULONG pceltFetched)
  101. {
  102. TCHAR szGuid[GUIDSTR_MAX];
  103. DWORD cchGuid;
  104. ULONG i, j;
  105. LONG lr;
  106. if (NULL != pceltFetched)
  107. {
  108. *pceltFetched = 0;
  109. }
  110. if (NULL == _hkGuids)
  111. {
  112. lr = RegOpenKeyEx(_hkHive, _szKey, 0, KEY_ENUMERATE_SUB_KEYS, &_hkGuids);
  113. if (ERROR_SUCCESS != lr)
  114. {
  115. return E_FAIL;
  116. }
  117. }
  118. ASSERT(NULL != _hkGuids);
  119. for (i = j = 0; i < celt; i++)
  120. {
  121. cchGuid = ARRAYSIZE(szGuid);
  122. lr = SHEnumKeyEx(_hkGuids, _nCurrent++, szGuid, &cchGuid);
  123. if (ERROR_SUCCESS != lr)
  124. {
  125. continue;
  126. }
  127. GUIDFromString(szGuid, &rgelt[j]);
  128. j++;
  129. }
  130. if (NULL != pceltFetched)
  131. {
  132. *pceltFetched = j;
  133. }
  134. return S_OK;
  135. }
  136. STDMETHODIMP CEnumRegGUIDs::Skip(ULONG celt)
  137. {
  138. _nCurrent += celt;
  139. return S_OK;
  140. }
  141. STDMETHODIMP CEnumRegGUIDs::Reset()
  142. {
  143. _nCurrent = 0;
  144. return S_OK;
  145. }
  146. STDMETHODIMP CEnumRegGUIDs::Clone(IEnumGUID** ppenum)
  147. {
  148. return E_NOTIMPL;
  149. }
  150. STDMETHODIMP _SHEnumGUIDsWithCallback(IEnumCLSID* peclsid, PFNENUMCLSIDPROC pfnEnum, LPARAM lParam)
  151. {
  152. CLSID clsid;
  153. HRESULT hr;
  154. ULONG i;
  155. if (NULL == peclsid || NULL == pfnEnum)
  156. {
  157. return E_INVALIDARG;
  158. }
  159. hr = S_OK;
  160. peclsid->Reset();
  161. while (S_OK == peclsid->Next(1, &clsid, &i))
  162. {
  163. hr = pfnEnum(clsid, lParam);
  164. if (S_OK != hr)
  165. {
  166. break;
  167. }
  168. }
  169. return hr;
  170. }
  171. STDMETHODIMP _SHEnumRegGUIDs(HKEY hk, PCTSTR pszKey, IEnumGUID** ppenum)
  172. {
  173. if (NULL == ppenum)
  174. {
  175. return E_INVALIDARG;
  176. }
  177. *ppenum = new CEnumRegGUIDs(hk, pszKey);
  178. return (NULL != *ppenum) ? S_OK : E_OUTOFMEMORY;
  179. }
  180. STDMETHODIMP _AddCATIDEnum(REFCLSID rclsid, LPARAM lParam)
  181. {
  182. PADDCATIDENUM p = (PADDCATIDENUM)lParam;
  183. ASSERT(NULL != p);
  184. ASSERT(NULL != p->pfnEnum);
  185. return (*p->pfnEnum)(*p->pcatid, rclsid, p->lParam);
  186. }