mirror of
https://github.com/reactos/reactos.git
synced 2025-02-23 08:55:19 +00:00
[BROWSEUI]
- Implement SHEnumClassesOfCategories - Part of the work submitted by Sylvain Deverre. CORE-10838 svn path=/trunk/; revision=71471
This commit is contained in:
parent
49c56d1976
commit
19ee935a70
3 changed files with 337 additions and 7 deletions
|
@ -31,6 +31,7 @@ list(APPEND SOURCE
|
|||
travellog.cpp
|
||||
utility.cpp
|
||||
CProgressDialog.cpp
|
||||
comcat.cpp
|
||||
precomp.h)
|
||||
|
||||
add_library(browseui SHARED
|
||||
|
|
|
@ -136,13 +136,6 @@ extern "C" HRESULT WINAPI GetInfoTip(IUnknown *param8, long paramC, LPTSTR *para
|
|||
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]
|
||||
|
|
336
reactos/dll/win32/browseui/comcat.cpp
Normal file
336
reactos/dll/win32/browseui/comcat.cpp
Normal file
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue