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.
1019 lines
26 KiB
1019 lines
26 KiB
//
|
|
// catmgr.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include "regsvr.h"
|
|
#include "xstring.h"
|
|
#include "cregkey.h"
|
|
#include "catmgr.h"
|
|
|
|
CCatGUIDTbl *CCategoryMgr::_pCatGUIDTbl = NULL;
|
|
|
|
const TCHAR c_szCategoryKey[] = TEXT("Category\\");
|
|
const TCHAR c_szDescription[] = TEXT("Description");
|
|
const WCHAR c_wszDescription[] = L"Description";
|
|
const TCHAR c_szCategory[] = TEXT("Category\\"); // Category to item mapping
|
|
const TCHAR c_szItem[] = TEXT("Item\\"); // Item to category mapping
|
|
const TCHAR c_szGuid[] = TEXT("Guid%d");
|
|
const TCHAR c_szDword[] = TEXT("Dword");
|
|
const TCHAR c_szNULL[] = TEXT("");
|
|
|
|
DBG_ID_INSTANCE(CCategoryMgr);
|
|
DBG_ID_INSTANCE(CEnumCategories);
|
|
|
|
inline BOOL GetCatKey(REFCLSID rclsid, REFGUID rcatid, LPSTR pszKey, int cchKey, LPCSTR pszItem)
|
|
{
|
|
int cchFinal;
|
|
int cchTipKey;
|
|
int cchCatKey;
|
|
int cchItem;
|
|
|
|
cchTipKey = lstrlen(c_szCTFTIPKey);
|
|
cchCatKey = lstrlen(c_szCategoryKey);
|
|
cchItem = lstrlen(pszItem);
|
|
|
|
cchFinal = cchTipKey +
|
|
CLSID_STRLEN + // rclsid
|
|
1 + // '\\'
|
|
cchCatKey +
|
|
cchItem +
|
|
CLSID_STRLEN +
|
|
1; // '\0'
|
|
|
|
if (cchFinal > cchKey)
|
|
{
|
|
if (cchKey > 0)
|
|
{
|
|
pszKey[0] = '\0';
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
StringCchCopy(pszKey, cchKey, c_szCTFTIPKey);
|
|
CLSIDToStringA(rclsid, pszKey + cchTipKey);
|
|
StringCchPrintf(pszKey + cchTipKey + CLSID_STRLEN, cchKey - cchTipKey - CLSID_STRLEN, "\\%s%s", c_szCategoryKey, pszItem);
|
|
CLSIDToStringA(rcatid, pszKey + cchTipKey + CLSID_STRLEN + 1 + cchCatKey + cchItem);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// for inatlib.
|
|
//
|
|
HRESULT g_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
|
|
{
|
|
return CCategoryMgr::s_EnumItemsInCategory(rcatid, ppEnum);
|
|
}
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCatGUIDTbl
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// add
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
TfGuidAtom CCatGUIDTbl::Add(REFGUID rguid)
|
|
{
|
|
UINT uId = _HashFunc(rguid);
|
|
UINT iCnt;
|
|
|
|
if (!_prgCatGUID[uId])
|
|
{
|
|
_prgCatGUID[uId] = new CStructArray<CATGUIDITEM>;
|
|
if (!_prgCatGUID[uId])
|
|
return TF_INVALID_GUIDATOM;
|
|
}
|
|
|
|
iCnt = _prgCatGUID[uId]->Count();
|
|
if (!ValidGUIDARRAYCount(iCnt))
|
|
{
|
|
Assert(0);
|
|
return TF_INVALID_GUIDATOM;
|
|
}
|
|
|
|
if (!_prgCatGUID[uId]->Insert(iCnt, 1))
|
|
{
|
|
return TF_INVALID_GUIDATOM;
|
|
}
|
|
|
|
CATGUIDITEM *pItem = _prgCatGUID[uId]->GetPtr(iCnt);
|
|
|
|
pItem->guid = rguid;
|
|
pItem->rgGuidAry[CAT_FORWARD] = NULL;
|
|
pItem->rgGuidAry[CAT_BACKWARD] = NULL;
|
|
|
|
return MAKEGUIDATOM(iCnt, uId);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// FindGuid
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
TfGuidAtom CCatGUIDTbl::FindGuid(REFGUID rguid)
|
|
{
|
|
UINT uId = _HashFunc(rguid);
|
|
int nCnt;
|
|
int i;
|
|
|
|
if (!_prgCatGUID[uId])
|
|
return TF_INVALID_GUIDATOM;
|
|
|
|
nCnt = _prgCatGUID[uId]->Count();
|
|
|
|
if (!ValidGUIDARRAYCount(nCnt))
|
|
{
|
|
Assert(0);
|
|
return TF_INVALID_GUIDATOM;
|
|
}
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CATGUIDITEM *pItem = _prgCatGUID[uId]->GetPtr(i);
|
|
if (IsEqualGUID(pItem->guid, rguid))
|
|
{
|
|
return MAKEGUIDATOM(i, uId);
|
|
}
|
|
}
|
|
return TF_INVALID_GUIDATOM;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetGuid
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CATGUIDITEM *CCatGUIDTbl::GetGUID(TfGuidAtom atom)
|
|
{
|
|
UINT uId = HASHIDFROMGUIDATOM(atom);
|
|
int nCnt = IDFROMGUIDATOM(atom);
|
|
|
|
if (!ValidGUIDHash(uId))
|
|
return NULL;
|
|
|
|
if ((!_prgCatGUID[uId]) || (nCnt >= _prgCatGUID[uId]->Count()))
|
|
return NULL;
|
|
|
|
return _prgCatGUID[uId]->GetPtr(nCnt);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCategoryMgr
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCategoryMgr::CCategoryMgr()
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CCategoryMgr"), PERF_CATMGR_COUNTER);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCategoryMgr::~CCategoryMgr()
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// InitGlobal
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CCategoryMgr::InitGlobal()
|
|
{
|
|
if (!_pCatGUIDTbl)
|
|
_pCatGUIDTbl = new CCatGUIDTbl;
|
|
|
|
return _pCatGUIDTbl ? TRUE : FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RegisterCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::RegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
|
|
{
|
|
return s_RegisterCategory(rclsid, rcatid, rguid);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_RegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// create forward link from category to guids.
|
|
//
|
|
if (FAILED(hr = _InternalRegisterCategory(rclsid, rcatid, rguid, CAT_FORWARD)))
|
|
return hr;
|
|
|
|
//
|
|
// create backward link from guid to categories.
|
|
//
|
|
if (FAILED(hr = _InternalRegisterCategory(rclsid, rguid, rcatid, CAT_BACKWARD)))
|
|
{
|
|
_InternalUnregisterCategory(rclsid, rcatid, rguid, CAT_FORWARD);
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UnregisterCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::UnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
|
|
{
|
|
return s_UnregisterCategory(rclsid, rcatid, rguid);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_UnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
|
|
{
|
|
HRESULT hr;
|
|
|
|
//
|
|
// remove forward link from category to guids.
|
|
//
|
|
if (FAILED(hr = _InternalUnregisterCategory(rclsid, rcatid, rguid, CAT_FORWARD)))
|
|
return hr;
|
|
|
|
//
|
|
// remove backward link from guid to categories.
|
|
//
|
|
if (FAILED(hr = _InternalUnregisterCategory(rclsid, rguid, rcatid, CAT_BACKWARD)))
|
|
{
|
|
_InternalRegisterCategory(rclsid, rcatid, rguid, CAT_FORWARD);
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// EnumCategoriesInItem
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::EnumCategoriesInItem(REFGUID rguid, IEnumGUID **ppEnum)
|
|
{
|
|
return _InternalEnumCategories(rguid, ppEnum, CAT_BACKWARD);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_EnumCategoriesInItem(REFGUID rguid, IEnumGUID **ppEnum)
|
|
{
|
|
return _InternalEnumCategories(rguid, ppEnum, CAT_BACKWARD);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// EnumItemsinCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
|
|
{
|
|
return _InternalEnumCategories(rcatid, ppEnum, CAT_FORWARD);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
|
|
{
|
|
return _InternalEnumCategories(rcatid, ppEnum, CAT_FORWARD);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// FindClosestCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::FindClosestCategory(REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
|
|
{
|
|
return s_FindClosestCategory(rguid, pcatid, ppcatidList, ulCount);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_FindClosestCategory(REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
|
|
{
|
|
// GUID catid = GUID_NULL;
|
|
|
|
if (!pcatid)
|
|
return E_INVALIDARG;
|
|
|
|
if (!ppcatidList || !ulCount)
|
|
{
|
|
return _GetFirstCategory(rguid, pcatid);
|
|
}
|
|
|
|
for (ULONG ul = 0; ul < ulCount; ul++)
|
|
{
|
|
if (!ppcatidList[ul])
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return _InternalFindClosestCategory(rguid,
|
|
rguid,
|
|
pcatid,
|
|
ppcatidList,
|
|
ulCount);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// _GetFirstCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::_GetFirstCategory(REFGUID rguid, GUID *pcatid)
|
|
{
|
|
HRESULT hr;
|
|
IEnumGUID *pEnum;
|
|
|
|
if (SUCCEEDED(hr = _InternalEnumCategories(rguid, &pEnum, CAT_BACKWARD)))
|
|
{
|
|
// we return S_FALSE if we can not find it and return GUID_NULL.
|
|
hr = pEnum->Next(1, pcatid, NULL);
|
|
if (hr != S_OK)
|
|
*pcatid = GUID_NULL;
|
|
|
|
pEnum->Release();
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// _InternalFindClosestCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::_InternalFindClosestCategory(REFGUID rguidOrg, REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
|
|
{
|
|
HRESULT hr;
|
|
ULONG ul;
|
|
IEnumGUID *pEnum = NULL;
|
|
GUID catid = GUID_NULL;
|
|
|
|
Assert(ppcatidList);
|
|
Assert(ulCount);
|
|
|
|
*pcatid = GUID_NULL;
|
|
|
|
for (ul = 0; ul < ulCount; ul++)
|
|
{
|
|
if (IsEqualGUID(*ppcatidList[ul], rguid))
|
|
{
|
|
*pcatid = rguid;
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
//
|
|
// we don't return error. We return success and GUID_NULL.
|
|
//
|
|
hr = _InternalEnumCategories(rguid, &pEnum, CAT_BACKWARD);
|
|
if (hr != S_OK)
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
while (pEnum->Next(1, &catid, NULL) == S_OK)
|
|
{
|
|
if (IsEqualGUID(rguidOrg, catid))
|
|
{
|
|
// finally the original guid is categorized by itself.
|
|
// it may cause infinte loop so bail it out.
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
|
|
_InternalFindClosestCategory(rguidOrg,
|
|
catid,
|
|
pcatid,
|
|
ppcatidList,
|
|
ulCount);
|
|
|
|
if (!IsEqualGUID(*pcatid, GUID_NULL))
|
|
{
|
|
hr = S_OK;
|
|
goto Exit;
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
SafeRelease(pEnum);
|
|
return hr;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RegisterGUIDDesription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::RegisterGUIDDescription(REFCLSID rclsid, REFGUID rguid, const WCHAR *pchDesc, ULONG cch)
|
|
{
|
|
if (!pchDesc && cch)
|
|
return E_INVALIDARG;
|
|
|
|
return s_RegisterGUIDDescription(rclsid, rguid, WCHtoWSZ(pchDesc, cch));
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_RegisterGUIDDescription(REFCLSID rclsid, REFGUID rguid, WCHAR *pszDesc)
|
|
{
|
|
TCHAR szKey[256];
|
|
CMyRegKey key;
|
|
|
|
if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
|
|
return E_FAIL;
|
|
|
|
if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
|
|
return E_FAIL;
|
|
|
|
key.SetValueW(pszDesc, c_wszDescription);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UnregisterGUIDDesription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::UnregisterGUIDDescription(REFCLSID rclsid, REFGUID rguid)
|
|
{
|
|
return s_UnregisterGUIDDescription(rclsid, rguid);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_UnregisterGUIDDescription(REFCLSID rclsid, REFGUID rguid)
|
|
{
|
|
TCHAR szKey[256];
|
|
CMyRegKey key;
|
|
|
|
if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
|
|
return E_FAIL;
|
|
|
|
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
|
|
return E_FAIL;
|
|
|
|
key.DeleteValueW(c_wszDescription);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// GetGUIDDescription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::GetGUIDDescription(REFGUID rguid, BSTR *pbstrDesc)
|
|
{
|
|
return s_GetGUIDDescription(rguid, pbstrDesc);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_GetGUIDDescription(REFGUID rguid, BSTR *pbstrDesc)
|
|
{
|
|
return s_GetGUIDValue(rguid, c_szDescriptionW, pbstrDesc);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_GetGUIDValue(REFGUID rguid, const WCHAR* pszValue, BSTR *pbstrDesc)
|
|
{
|
|
WCHAR *psz = NULL;
|
|
CMyRegKey keyImx;
|
|
HRESULT hr = E_FAIL;
|
|
int cch;
|
|
TCHAR szSubKey[256]; // nb: we can merge szSubKey and szTemp if we switch to a UNICODE build
|
|
WCHAR szTemp[256];
|
|
|
|
if (!pbstrDesc)
|
|
return E_INVALIDARG;
|
|
|
|
*pbstrDesc = NULL;
|
|
|
|
if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
|
|
return hr;
|
|
|
|
DWORD dwIndex = 0;
|
|
|
|
while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
|
|
{
|
|
CMyRegKey key;
|
|
|
|
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, c_szItem) != S_OK)
|
|
continue;
|
|
|
|
cch = lstrlen(szSubKey);
|
|
|
|
if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
|
|
continue;
|
|
|
|
CLSIDToStringA(rguid, szSubKey + cch);
|
|
|
|
if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
|
|
continue;
|
|
|
|
if (key.QueryValueCchW(szTemp, pszValue, ARRAYSIZE(szTemp)) == S_OK)
|
|
{
|
|
*pbstrDesc = SysAllocString(szTemp);
|
|
hr = *pbstrDesc != NULL ? S_OK : E_OUTOFMEMORY;
|
|
}
|
|
|
|
// this was the matching key, so no point in continue successful query or not
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RegisterGUIDDesription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::RegisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid, DWORD dw)
|
|
{
|
|
return s_RegisterGUIDDWORD(rclsid, rguid, dw);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_RegisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid, DWORD dw)
|
|
{
|
|
TCHAR szKey[256];
|
|
CMyRegKey key;
|
|
|
|
if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
|
|
return E_FAIL;
|
|
|
|
if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
|
|
return E_FAIL;
|
|
|
|
key.SetValue(dw, c_szDword);
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UnregisterGUIDDesription
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::UnregisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid)
|
|
{
|
|
return s_UnregisterGUIDDWORD(rclsid, rguid);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_UnregisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid)
|
|
{
|
|
TCHAR szKey[256];
|
|
CMyRegKey key;
|
|
|
|
if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
|
|
return E_FAIL;
|
|
|
|
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
|
|
return E_FAIL;
|
|
|
|
key.DeleteValue(c_szDword);
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// GetGUIDDWORD
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::GetGUIDDWORD(REFGUID rguid, DWORD *pdw)
|
|
{
|
|
return s_GetGUIDDWORD(rguid, pdw);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_GetGUIDDWORD(REFGUID rguid, DWORD *pdw)
|
|
{
|
|
CMyRegKey keyImx;
|
|
int cch;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!pdw)
|
|
return E_INVALIDARG;
|
|
|
|
*pdw = 0;
|
|
|
|
if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
|
|
return hr;
|
|
|
|
DWORD dwIndex = 0;
|
|
TCHAR szSubKey[256];
|
|
while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
|
|
{
|
|
CMyRegKey key;
|
|
|
|
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, c_szItem) != S_OK)
|
|
continue;
|
|
|
|
cch = lstrlen(szSubKey);
|
|
|
|
if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
|
|
continue;
|
|
|
|
CLSIDToStringA(rguid, szSubKey + cch);
|
|
|
|
if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
|
|
continue;
|
|
|
|
if (key.QueryValue(*pdw, c_szDword) == S_OK)
|
|
{
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// RegisterProvider
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::RegisterGUID(REFGUID rguid, TfGuidAtom *pguidatom)
|
|
{
|
|
return s_RegisterGUID(rguid, pguidatom);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_RegisterGUID(REFGUID rguid, TfGuidAtom *pguidatom)
|
|
{
|
|
TfGuidAtom guidatom;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (InitGlobal())
|
|
{
|
|
if ((guidatom = _pCatGUIDTbl->FindGuid(rguid)) != TF_INVALID_GUIDATOM)
|
|
{
|
|
*pguidatom = guidatom;
|
|
hr = S_OK;
|
|
}
|
|
else if ((guidatom = _pCatGUIDTbl->Add(rguid)) != TF_INVALID_GUIDATOM)
|
|
{
|
|
*pguidatom = guidatom;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// GetGUID
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::GetGUID(TfGuidAtom guidatom, GUID *pguid)
|
|
{
|
|
return s_GetGUID(guidatom, pguid);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_GetGUID(TfGuidAtom guidatom, GUID *pguid)
|
|
{
|
|
CATGUIDITEM *pItem;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!pguid)
|
|
return E_INVALIDARG;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (InitGlobal())
|
|
{
|
|
pItem = _pCatGUIDTbl->GetGUID(guidatom);
|
|
if (!pItem)
|
|
{
|
|
*pguid = GUID_NULL;
|
|
goto Exit;
|
|
}
|
|
|
|
*pguid = pItem->guid;
|
|
hr = S_OK;
|
|
}
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// IsEqualTfGuidAtom
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCategoryMgr::IsEqualTfGuidAtom(TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
|
|
{
|
|
return s_IsEqualTfGuidAtom(guidatom, rguid, pfEqual);
|
|
}
|
|
|
|
HRESULT CCategoryMgr::s_IsEqualTfGuidAtom(TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
CATGUIDITEM *pItem;
|
|
|
|
if (pfEqual == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
*pfEqual = FALSE;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (InitGlobal())
|
|
{
|
|
if (pItem = _pCatGUIDTbl->GetGUID(guidatom))
|
|
{
|
|
*pfEqual = IsEqualGUID(pItem->guid, rguid);
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
CicLeaveCriticalSection(g_cs);
|
|
return hr;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// InternalRegisterCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::_InternalRegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid, CATDIRECTION catdir)
|
|
{
|
|
TCHAR szKey[256];
|
|
CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
|
|
CMyRegKey key;
|
|
CMyRegKey keySub;
|
|
|
|
if (!GetCatKey(rclsid, rcatid, szKey, ARRAYSIZE(szKey), pszForward))
|
|
return E_FAIL;
|
|
|
|
if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
|
|
return E_FAIL;
|
|
|
|
//
|
|
// we add this guid and save it.
|
|
//
|
|
char szValue[CLSID_STRLEN + 1];
|
|
CLSIDToStringA(rguid, szValue);
|
|
keySub.Create(key, szValue);
|
|
_FlushGuidArrayCache(rguid, catdir);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// UnregisterCategory
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::_InternalUnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid, CATDIRECTION catdir)
|
|
{
|
|
TCHAR szKey[256];
|
|
CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
|
|
CMyRegKey key;
|
|
|
|
if (!GetCatKey(rclsid, rcatid, szKey, ARRAYSIZE(szKey), pszForward))
|
|
return E_FAIL;
|
|
|
|
if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
|
|
return E_FAIL;
|
|
|
|
DWORD dwIndex = 0;
|
|
char szValue[CLSID_STRLEN + 1];
|
|
|
|
CLSIDToStringA(rguid, szValue);
|
|
key.RecurseDeleteKey(szValue);
|
|
_FlushGuidArrayCache(rguid, catdir);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// _FlushGuidArrayCache
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCategoryMgr::_FlushGuidArrayCache(REFGUID rguid, CATDIRECTION catdir)
|
|
{
|
|
TfGuidAtom guidatom;
|
|
CATGUIDITEM *pItem;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (!_pCatGUIDTbl)
|
|
goto Exit;
|
|
|
|
guidatom = _pCatGUIDTbl->FindGuid(rguid);
|
|
if (guidatom == TF_INVALID_GUIDATOM)
|
|
goto Exit;
|
|
|
|
pItem = _pCatGUIDTbl->GetGUID(guidatom);
|
|
if (!pItem)
|
|
{
|
|
Assert(0);
|
|
goto Exit;
|
|
}
|
|
|
|
SGA_Release(pItem->rgGuidAry[catdir]);
|
|
pItem->rgGuidAry[catdir] = NULL;
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
//
|
|
// _InternalEnumCategories
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCategoryMgr::_InternalEnumCategories(REFGUID rguid, IEnumGUID **ppEnum, CATDIRECTION catdir)
|
|
{
|
|
CEnumCategories *pEnum;
|
|
|
|
if (!ppEnum)
|
|
return E_INVALIDARG;
|
|
|
|
pEnum = new CEnumCategories();
|
|
|
|
if (!pEnum)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (pEnum->_Init(rguid, catdir))
|
|
*ppEnum = pEnum;
|
|
else
|
|
SafeReleaseClear(pEnum);
|
|
|
|
return pEnum ? S_OK : E_FAIL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CEnumCategories
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CEnumCategories::CEnumCategories()
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CEnumCategories"), PERF_ENUMCAT_COUNTER);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CEnumCategories::_Init(REFGUID rcatid, CATDIRECTION catdir)
|
|
{
|
|
int cch;
|
|
int nCnt = 0;
|
|
BOOL bRet = FALSE;
|
|
CMyRegKey keyImx;
|
|
TfGuidAtom guidatom;
|
|
CATGUIDITEM *pItem;
|
|
CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
|
|
DWORD dwIndex = 0;
|
|
TCHAR szSubKey[256];
|
|
ULONG cGuidMax = 64;
|
|
ULONG cGuidCurrent = 0;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
if (!CCategoryMgr::InitGlobal())
|
|
goto LeaveCrtSec;
|
|
|
|
guidatom = CCategoryMgr::_pCatGUIDTbl->FindGuid(rcatid);
|
|
if (guidatom == TF_INVALID_GUIDATOM)
|
|
{
|
|
guidatom = CCategoryMgr::_pCatGUIDTbl->Add(rcatid);
|
|
|
|
if (guidatom == TF_INVALID_GUIDATOM)
|
|
goto LeaveCrtSec;
|
|
}
|
|
|
|
pItem = CCategoryMgr::_pCatGUIDTbl->GetGUID(guidatom);
|
|
Assert(pItem);
|
|
|
|
if (_pga = pItem->rgGuidAry[catdir])
|
|
{
|
|
// already have this GUID cached, just reference it
|
|
SGA_AddRef(_pga);
|
|
|
|
bRet = TRUE;
|
|
goto LeaveCrtSec;
|
|
}
|
|
|
|
_pga = SGA_Alloc(cGuidMax);
|
|
if (!_pga)
|
|
goto LeaveCrtSec;
|
|
|
|
_pga->cRef = 1;
|
|
|
|
if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
|
|
goto LeaveCrtSec;
|
|
|
|
while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
|
|
{
|
|
CMyRegKey key;
|
|
|
|
if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, pszForward) != S_OK)
|
|
continue;
|
|
|
|
cch = lstrlen(szSubKey);
|
|
|
|
if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
|
|
continue;
|
|
|
|
CLSIDToStringA(rcatid, szSubKey + cch);
|
|
|
|
if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
|
|
continue;
|
|
|
|
DWORD dwSize = 0;
|
|
DWORD dwIndex2 = 0;
|
|
char szValueName[CLSID_STRLEN + 1];
|
|
while (key.EnumKey(dwIndex2++, szValueName, ARRAYSIZE(szValueName)) == S_OK)
|
|
{
|
|
if (lstrlen(szValueName) == CLSID_STRLEN)
|
|
{
|
|
if (cGuidCurrent >= cGuidMax)
|
|
{
|
|
cGuidMax += 64;
|
|
if (!SGA_ReAlloc(&_pga, cGuidMax))
|
|
goto LeaveCrtSec;
|
|
}
|
|
StringAToCLSID(szValueName, &_pga->rgGuid[cGuidCurrent]);
|
|
cGuidCurrent++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// free up unused memory
|
|
if (!SGA_ReAlloc(&_pga, cGuidCurrent))
|
|
goto LeaveCrtSec;
|
|
|
|
bRet = TRUE;
|
|
_pga->cGuid = cGuidCurrent;
|
|
|
|
// put this array in the cache
|
|
pItem->rgGuidAry[catdir] = _pga;
|
|
SGA_AddRef(pItem->rgGuidAry[catdir]);
|
|
|
|
LeaveCrtSec:
|
|
CicLeaveCriticalSection(g_cs);
|
|
|
|
return bRet;
|
|
}
|