Author: gadamopoulos
Date: Tue May 31 13:39:42 2016
New Revision: 71471
URL:
http://svn.reactos.org/svn/reactos?rev=71471&view=rev
Log:
[BROWSEUI]
- Implement SHEnumClassesOfCategories
- Part of the work submitted by Sylvain Deverre.
CORE-10838
Added:
trunk/reactos/dll/win32/browseui/comcat.cpp (with props)
Modified:
trunk/reactos/dll/win32/browseui/CMakeLists.txt
trunk/reactos/dll/win32/browseui/browseuiord.cpp
Modified: trunk/reactos/dll/win32/browseui/CMakeLists.txt
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/CMakeLi…
==============================================================================
--- trunk/reactos/dll/win32/browseui/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/browseui/CMakeLists.txt [iso-8859-1] Tue May 31 13:39:42 2016
@@ -31,6 +31,7 @@
travellog.cpp
utility.cpp
CProgressDialog.cpp
+ comcat.cpp
precomp.h)
add_library(browseui SHARED
Modified: trunk/reactos/dll/win32/browseui/browseuiord.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/browseu…
==============================================================================
--- trunk/reactos/dll/win32/browseui/browseuiord.cpp [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/browseui/browseuiord.cpp [iso-8859-1] Tue May 31 13:39:42
2016
@@ -136,13 +136,6 @@
return E_NOTIMPL;
}
-/*************************************************************************
- * SHEnumClassesOfCategories [BROWSEUI.136]
- */
-extern "C" HRESULT WINAPI SHEnumClassesOfCategories(ULONG cImplemented, CATID
*pImplemented, ULONG cRequired, CATID *pRequired, IEnumGUID **out)
-{
- return E_NOTIMPL;
-}
/*************************************************************************
* SHWriteClassesOfCategories [BROWSEUI.137]
Added: trunk/reactos/dll/win32/browseui/comcat.cpp
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/browseui/comcat.…
==============================================================================
--- trunk/reactos/dll/win32/browseui/comcat.cpp (added)
+++ trunk/reactos/dll/win32/browseui/comcat.cpp [iso-8859-1] Tue May 31 13:39:42 2016
@@ -0,0 +1,336 @@
+/*
+ * ReactOS Explorer
+ *
+ * Copyright 2016 Sylvain Deverre <deverre dot sylv at gmail dot com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Wraps the component categories manager enum
+ */
+
+#include "precomp.h"
+
+#define REGPATH
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Discardable\\PostSetup\\Component
Categories"
+#define IMPLEMENTING L"Implementing"
+#define REQUIRING L"Requiring"
+
+typedef struct categoryCacheHeader
+{
+ DWORD dwSize; // size of header only
+ DWORD version; // currently 1
+ SYSTEMTIME writeTime; // time we were written to registry
+ DWORD classCount; // number of classes following
+} CATCACHEHDR, *PCATCACHEHDR;
+
+/*
+ * This class manages a cached explorer component categories items, writing cache if it
+ * doesn't exist yet.
+ * It is used by CSHEnumClassesOfCategories internally.
+ */
+class CComCatCachedCategory
+{
+ public:
+ CComCatCachedCategory();
+ virtual ~CComCatCachedCategory();
+ HRESULT WriteCacheToDSA(HDSA pDest);
+ HRESULT STDMETHODCALLTYPE Initialize(CATID &catID, BOOL reloadCache);
+ private:
+ BOOL LoadFromRegistry();
+ HRESULT LoadFromComCatMgr();
+ HRESULT CacheDSA();
+ CATID fCategory;
+ HDSA fLocalDsa;
+};
+
+CComCatCachedCategory::CComCatCachedCategory()
+{
+ fLocalDsa = DSA_Create(sizeof(GUID), 5);
+}
+
+HRESULT STDMETHODCALLTYPE CComCatCachedCategory::Initialize(CATID &catID, BOOL
reloadCache)
+{
+ HRESULT hr;
+
+ fCategory = catID;
+ if (reloadCache || !LoadFromRegistry())
+ {
+ hr = LoadFromComCatMgr();
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ hr = CacheDSA();
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ }
+ return S_OK;
+}
+
+CComCatCachedCategory::~CComCatCachedCategory()
+{
+ DSA_Destroy(fLocalDsa);
+}
+
+BOOL CComCatCachedCategory::LoadFromRegistry()
+{
+ WCHAR bufKey[MAX_PATH];
+ WCHAR guidStr[MAX_PATH];
+ DWORD dataSize, i;
+ CComHeapPtr<CATCACHEHDR> buffer;
+ GUID *guidArray;
+
+ if (!fLocalDsa)
+ return FALSE;
+
+ dataSize = 0;
+ if (!StringFromGUID2(fCategory, guidStr, MAX_PATH))
+ return FALSE;
+
+ wsprintf(bufKey, L"%s\\%s\\%s", REGPATH , guidStr, L"Enum");
+
+ // Try to read key and get proper value size
+ if (SHGetValue(HKEY_CURRENT_USER, bufKey, IMPLEMENTING, NULL, NULL, &dataSize))
+ return FALSE;
+
+ buffer.Attach((PCATCACHEHDR)CoTaskMemAlloc(dataSize));
+
+ SHGetValue(HKEY_CURRENT_USER, bufKey, IMPLEMENTING, NULL, buffer, &dataSize);
+ guidArray = (GUID*)(buffer + 1);
+ for (i = 0; i < buffer->classCount; i++)
+ {
+ // Add class to cache
+ DSA_InsertItem(fLocalDsa, DSA_APPEND, guidArray + i);
+ }
+
+ return TRUE;
+}
+
+HRESULT CComCatCachedCategory::CacheDSA()
+{
+ WCHAR bufKey[MAX_PATH];
+ WCHAR guidStr[MAX_PATH];
+ UINT elemCount;
+ UINT i;
+ UINT bufferSize;
+ CComHeapPtr<CATCACHEHDR> buffer;
+ GUID *guidArray;
+ GUID *tmp;
+
+ elemCount = DSA_GetItemCount(fLocalDsa);
+ bufferSize = sizeof(CATCACHEHDR) + elemCount * sizeof(GUID);
+ if (!StringFromGUID2(fCategory, guidStr, MAX_PATH))
+ return E_FAIL;
+
+ buffer.Attach((PCATCACHEHDR)CoTaskMemAlloc(bufferSize));
+ if (!buffer)
+ return E_OUTOFMEMORY;
+
+ // Correctly fill cache header
+ buffer->dwSize = sizeof(CATCACHEHDR);
+ buffer->version = 1;
+ GetSystemTime(&buffer->writeTime);
+ buffer->classCount = (DWORD)elemCount;
+
+ guidArray = (GUID*)(buffer + 1);
+ wsprintf(bufKey, L"%s\\%s\\%s", REGPATH , guidStr, L"Enum");
+
+ // Write DSA contents inside the memory buffer allocated
+ for(i = 0; i < elemCount; i++)
+ {
+ tmp = (GUID*)DSA_GetItemPtr(fLocalDsa, i);
+ if (tmp)
+ {
+ guidArray[i] = *tmp;
+ }
+ }
+
+ // Save items to registry
+ SHSetValue(HKEY_CURRENT_USER, bufKey, IMPLEMENTING, REG_BINARY, buffer, bufferSize);
+
+ guidArray = NULL;
+ CoTaskMemFree(buffer);
+ return S_OK;
+}
+
+HRESULT CComCatCachedCategory::LoadFromComCatMgr()
+{
+ HRESULT hr;
+ CComPtr<ICatInformation> pCatInformation;
+ CComPtr<IEnumGUID> pEnumGUID;
+ ULONG pFetched;
+ CLSID tmp;
+
+ // Get component categories manager instance
+ hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER,
+ IID_PPV_ARG(ICatInformation, &pCatInformation));
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ // Get the proper enumerator
+ hr = pCatInformation->EnumClassesOfCategories(1, &fCategory, NULL, NULL,
&pEnumGUID);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+
+ // Enumerate elements
+ do
+ {
+ pFetched = 0;
+ pEnumGUID->Next(1, &tmp, &pFetched);
+ if (pFetched)
+ {
+ if (DSA_InsertItem(fLocalDsa, DSA_APPEND, &tmp) == E_OUTOFMEMORY)
+ return E_OUTOFMEMORY;
+ }
+ }
+ while (pFetched > 0);
+ return S_OK;
+}
+
+HRESULT CComCatCachedCategory::WriteCacheToDSA(HDSA pDest)
+{
+ INT i;
+ for(i = 0; i < DSA_GetItemCount(fLocalDsa); i++)
+ {
+ if (DSA_InsertItem(pDest, DSA_APPEND, DSA_GetItemPtr(fLocalDsa, i)) == DSA_ERR)
+ return E_OUTOFMEMORY;
+ }
+ return S_OK;
+}
+
+class CSHEnumClassesOfCategories :
+ public CComCoClass<CSHEnumClassesOfCategories>,
+ public CComObjectRootEx<CComMultiThreadModelNoCS>,
+ public IEnumGUID
+{
+ private:
+ CComPtr<ICatInformation> fCatInformation;
+ HDSA fDsa;
+ ULONG fCursor;
+
+ public:
+ CSHEnumClassesOfCategories();
+ virtual ~CSHEnumClassesOfCategories();
+ virtual HRESULT STDMETHODCALLTYPE Initialize(ULONG cImplemented, CATID
*pImplemented, ULONG cRequired, CATID *pRequired);
+ // *** IEnumGUID methods ***
+ virtual HRESULT STDMETHODCALLTYPE Clone(IEnumCLSID **ppvOut);
+ virtual HRESULT STDMETHODCALLTYPE Next(ULONG cElt, CLSID *pElts, ULONG
*pFetched);
+ virtual HRESULT STDMETHODCALLTYPE Reset();
+ virtual HRESULT STDMETHODCALLTYPE Skip(ULONG nbElts);
+
+ BEGIN_COM_MAP(CSHEnumClassesOfCategories)
+ COM_INTERFACE_ENTRY_IID(IID_IEnumGUID, IEnumGUID)
+ END_COM_MAP()
+};
+
+CSHEnumClassesOfCategories::CSHEnumClassesOfCategories()
+{
+ fCursor = 0;
+ fDsa = DSA_Create(sizeof(GUID), 5);
+}
+
+CSHEnumClassesOfCategories::~CSHEnumClassesOfCategories()
+{
+ if (fDsa)
+ DSA_Destroy(fDsa);
+}
+
+HRESULT CSHEnumClassesOfCategories::Initialize(ULONG cImplemented, CATID *pImplemented,
ULONG cRequired, CATID *pRequired)
+{
+ UINT i;
+ HRESULT hr;
+
+ if (!fDsa)
+ return E_FAIL;
+
+ if (cRequired > 0 || cImplemented == (ULONG)-1)
+ {
+ FIXME("Implement required categories class enumeration\n");
+ return E_NOTIMPL;
+ }
+
+ // Don't do anything if we have nothing
+ if (cRequired == 0 && cImplemented == (ULONG)-1)
+ return E_FAIL;
+
+ // For each implemented category, create a cache and add it to our local DSA
+ for (i = 0; i < cImplemented; i++)
+ {
+ CComCatCachedCategory cachedCat;
+ hr = cachedCat.Initialize(pImplemented[i], FALSE);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ cachedCat.WriteCacheToDSA(fDsa);
+ }
+ return S_OK;
+}
+
+// *** IEnumGUID methods ***
+
+HRESULT STDMETHODCALLTYPE CSHEnumClassesOfCategories::Clone(IEnumCLSID **ppvOut)
+{
+ return E_NOTIMPL;
+}
+
+HRESULT STDMETHODCALLTYPE CSHEnumClassesOfCategories::Next(ULONG cElt, CLSID *pElts,
ULONG *pFetched)
+{
+ ULONG i;
+ ULONG read;
+ GUID *tmp;
+
+ if (!pElts)
+ return E_INVALIDARG;
+ read = 0;
+ for (i = 0; i < cElt && (fCursor < (ULONG)DSA_GetItemCount(fDsa));
i++)
+ {
+ tmp = (GUID*)DSA_GetItemPtr(fDsa, fCursor + i);
+ if (!tmp)
+ break;
+ pElts[i] = *tmp;
+ read++;
+ }
+ fCursor += read;
+ if (pFetched)
+ *pFetched = read;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE CSHEnumClassesOfCategories::Reset()
+{
+ fCursor = 0;
+ return S_OK;
+}
+
+HRESULT STDMETHODCALLTYPE CSHEnumClassesOfCategories::Skip(ULONG nbElts)
+{
+ if (fCursor + nbElts >= (ULONG)DSA_GetItemCount(fDsa))
+ return E_INVALIDARG;
+ fCursor += nbElts;
+ return S_OK;
+}
+
+/*************************************************************************
+ * SHEnumClassesOfCategories [BROWSEUI.136]
+ */
+extern "C" HRESULT WINAPI SHEnumClassesOfCategories(ULONG cImplemented, CATID
*pImplemented, ULONG cRequired, CATID *pRequired, IEnumGUID **out)
+{
+ HRESULT hr;
+
+ hr = ShellObjectCreatorInit<CSHEnumClassesOfCategories, ULONG, CATID*, ULONG,
CATID*, IEnumGUID>(
+ cImplemented, pImplemented, cRequired, pRequired, IID_IEnumGUID, out);
+ if (FAILED_UNEXPECTEDLY(hr))
+ return hr;
+ return S_OK;
+}
Propchange: trunk/reactos/dll/win32/browseui/comcat.cpp
------------------------------------------------------------------------------
svn:eol-style = native