// // 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; 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; }