Leaked source code of windows server 2003
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

  1. //
  2. // catmgr.cpp
  3. //
  4. #include "private.h"
  5. #include "globals.h"
  6. #include "regsvr.h"
  7. #include "xstring.h"
  8. #include "cregkey.h"
  9. #include "catmgr.h"
  10. CCatGUIDTbl *CCategoryMgr::_pCatGUIDTbl = NULL;
  11. const TCHAR c_szCategoryKey[] = TEXT("Category\\");
  12. const TCHAR c_szDescription[] = TEXT("Description");
  13. const WCHAR c_wszDescription[] = L"Description";
  14. const TCHAR c_szCategory[] = TEXT("Category\\"); // Category to item mapping
  15. const TCHAR c_szItem[] = TEXT("Item\\"); // Item to category mapping
  16. const TCHAR c_szGuid[] = TEXT("Guid%d");
  17. const TCHAR c_szDword[] = TEXT("Dword");
  18. const TCHAR c_szNULL[] = TEXT("");
  19. DBG_ID_INSTANCE(CCategoryMgr);
  20. DBG_ID_INSTANCE(CEnumCategories);
  21. inline BOOL GetCatKey(REFCLSID rclsid, REFGUID rcatid, LPSTR pszKey, int cchKey, LPCSTR pszItem)
  22. {
  23. int cchFinal;
  24. int cchTipKey;
  25. int cchCatKey;
  26. int cchItem;
  27. cchTipKey = lstrlen(c_szCTFTIPKey);
  28. cchCatKey = lstrlen(c_szCategoryKey);
  29. cchItem = lstrlen(pszItem);
  30. cchFinal = cchTipKey +
  31. CLSID_STRLEN + // rclsid
  32. 1 + // '\\'
  33. cchCatKey +
  34. cchItem +
  35. CLSID_STRLEN +
  36. 1; // '\0'
  37. if (cchFinal > cchKey)
  38. {
  39. if (cchKey > 0)
  40. {
  41. pszKey[0] = '\0';
  42. }
  43. return FALSE;
  44. }
  45. StringCchCopy(pszKey, cchKey, c_szCTFTIPKey);
  46. CLSIDToStringA(rclsid, pszKey + cchTipKey);
  47. StringCchPrintf(pszKey + cchTipKey + CLSID_STRLEN, cchKey - cchTipKey - CLSID_STRLEN, "\\%s%s", c_szCategoryKey, pszItem);
  48. CLSIDToStringA(rcatid, pszKey + cchTipKey + CLSID_STRLEN + 1 + cchCatKey + cchItem);
  49. return TRUE;
  50. }
  51. //
  52. // for inatlib.
  53. //
  54. HRESULT g_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
  55. {
  56. return CCategoryMgr::s_EnumItemsInCategory(rcatid, ppEnum);
  57. }
  58. //////////////////////////////////////////////////////////////////////////////
  59. //
  60. // CCatGUIDTbl
  61. //
  62. //////////////////////////////////////////////////////////////////////////////
  63. //+---------------------------------------------------------------------------
  64. //
  65. // add
  66. //
  67. //----------------------------------------------------------------------------
  68. TfGuidAtom CCatGUIDTbl::Add(REFGUID rguid)
  69. {
  70. UINT uId = _HashFunc(rguid);
  71. UINT iCnt;
  72. if (!_prgCatGUID[uId])
  73. {
  74. _prgCatGUID[uId] = new CStructArray<CATGUIDITEM>;
  75. if (!_prgCatGUID[uId])
  76. return TF_INVALID_GUIDATOM;
  77. }
  78. iCnt = _prgCatGUID[uId]->Count();
  79. if (!ValidGUIDARRAYCount(iCnt))
  80. {
  81. Assert(0);
  82. return TF_INVALID_GUIDATOM;
  83. }
  84. if (!_prgCatGUID[uId]->Insert(iCnt, 1))
  85. {
  86. return TF_INVALID_GUIDATOM;
  87. }
  88. CATGUIDITEM *pItem = _prgCatGUID[uId]->GetPtr(iCnt);
  89. pItem->guid = rguid;
  90. pItem->rgGuidAry[CAT_FORWARD] = NULL;
  91. pItem->rgGuidAry[CAT_BACKWARD] = NULL;
  92. return MAKEGUIDATOM(iCnt, uId);
  93. }
  94. //+---------------------------------------------------------------------------
  95. //
  96. // FindGuid
  97. //
  98. //----------------------------------------------------------------------------
  99. TfGuidAtom CCatGUIDTbl::FindGuid(REFGUID rguid)
  100. {
  101. UINT uId = _HashFunc(rguid);
  102. int nCnt;
  103. int i;
  104. if (!_prgCatGUID[uId])
  105. return TF_INVALID_GUIDATOM;
  106. nCnt = _prgCatGUID[uId]->Count();
  107. if (!ValidGUIDARRAYCount(nCnt))
  108. {
  109. Assert(0);
  110. return TF_INVALID_GUIDATOM;
  111. }
  112. for (i = 0; i < nCnt; i++)
  113. {
  114. CATGUIDITEM *pItem = _prgCatGUID[uId]->GetPtr(i);
  115. if (IsEqualGUID(pItem->guid, rguid))
  116. {
  117. return MAKEGUIDATOM(i, uId);
  118. }
  119. }
  120. return TF_INVALID_GUIDATOM;
  121. }
  122. //+---------------------------------------------------------------------------
  123. //
  124. // GetGuid
  125. //
  126. //----------------------------------------------------------------------------
  127. CATGUIDITEM *CCatGUIDTbl::GetGUID(TfGuidAtom atom)
  128. {
  129. UINT uId = HASHIDFROMGUIDATOM(atom);
  130. int nCnt = IDFROMGUIDATOM(atom);
  131. if (!ValidGUIDHash(uId))
  132. return NULL;
  133. if ((!_prgCatGUID[uId]) || (nCnt >= _prgCatGUID[uId]->Count()))
  134. return NULL;
  135. return _prgCatGUID[uId]->GetPtr(nCnt);
  136. }
  137. //////////////////////////////////////////////////////////////////////////////
  138. //
  139. // CCategoryMgr
  140. //
  141. //////////////////////////////////////////////////////////////////////////////
  142. //+---------------------------------------------------------------------------
  143. //
  144. // ctor
  145. //
  146. //----------------------------------------------------------------------------
  147. CCategoryMgr::CCategoryMgr()
  148. {
  149. Dbg_MemSetThisNameIDCounter(TEXT("CCategoryMgr"), PERF_CATMGR_COUNTER);
  150. }
  151. //+---------------------------------------------------------------------------
  152. //
  153. // dtor
  154. //
  155. //----------------------------------------------------------------------------
  156. CCategoryMgr::~CCategoryMgr()
  157. {
  158. }
  159. //+---------------------------------------------------------------------------
  160. //
  161. // InitGlobal
  162. //
  163. //----------------------------------------------------------------------------
  164. BOOL CCategoryMgr::InitGlobal()
  165. {
  166. if (!_pCatGUIDTbl)
  167. _pCatGUIDTbl = new CCatGUIDTbl;
  168. return _pCatGUIDTbl ? TRUE : FALSE;
  169. }
  170. //----------------------------------------------------------------------------
  171. //
  172. // RegisterCategory
  173. //
  174. //----------------------------------------------------------------------------
  175. STDAPI CCategoryMgr::RegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
  176. {
  177. return s_RegisterCategory(rclsid, rcatid, rguid);
  178. }
  179. HRESULT CCategoryMgr::s_RegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
  180. {
  181. HRESULT hr;
  182. //
  183. // create forward link from category to guids.
  184. //
  185. if (FAILED(hr = _InternalRegisterCategory(rclsid, rcatid, rguid, CAT_FORWARD)))
  186. return hr;
  187. //
  188. // create backward link from guid to categories.
  189. //
  190. if (FAILED(hr = _InternalRegisterCategory(rclsid, rguid, rcatid, CAT_BACKWARD)))
  191. {
  192. _InternalUnregisterCategory(rclsid, rcatid, rguid, CAT_FORWARD);
  193. return hr;
  194. }
  195. return S_OK;
  196. }
  197. //----------------------------------------------------------------------------
  198. //
  199. // UnregisterCategory
  200. //
  201. //----------------------------------------------------------------------------
  202. STDAPI CCategoryMgr::UnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
  203. {
  204. return s_UnregisterCategory(rclsid, rcatid, rguid);
  205. }
  206. HRESULT CCategoryMgr::s_UnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
  207. {
  208. HRESULT hr;
  209. //
  210. // remove forward link from category to guids.
  211. //
  212. if (FAILED(hr = _InternalUnregisterCategory(rclsid, rcatid, rguid, CAT_FORWARD)))
  213. return hr;
  214. //
  215. // remove backward link from guid to categories.
  216. //
  217. if (FAILED(hr = _InternalUnregisterCategory(rclsid, rguid, rcatid, CAT_BACKWARD)))
  218. {
  219. _InternalRegisterCategory(rclsid, rcatid, rguid, CAT_FORWARD);
  220. return hr;
  221. }
  222. return S_OK;
  223. }
  224. //----------------------------------------------------------------------------
  225. //
  226. // EnumCategoriesInItem
  227. //
  228. //----------------------------------------------------------------------------
  229. STDAPI CCategoryMgr::EnumCategoriesInItem(REFGUID rguid, IEnumGUID **ppEnum)
  230. {
  231. return _InternalEnumCategories(rguid, ppEnum, CAT_BACKWARD);
  232. }
  233. HRESULT CCategoryMgr::s_EnumCategoriesInItem(REFGUID rguid, IEnumGUID **ppEnum)
  234. {
  235. return _InternalEnumCategories(rguid, ppEnum, CAT_BACKWARD);
  236. }
  237. //----------------------------------------------------------------------------
  238. //
  239. // EnumItemsinCategory
  240. //
  241. //----------------------------------------------------------------------------
  242. STDAPI CCategoryMgr::EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
  243. {
  244. return _InternalEnumCategories(rcatid, ppEnum, CAT_FORWARD);
  245. }
  246. HRESULT CCategoryMgr::s_EnumItemsInCategory(REFGUID rcatid, IEnumGUID **ppEnum)
  247. {
  248. return _InternalEnumCategories(rcatid, ppEnum, CAT_FORWARD);
  249. }
  250. //----------------------------------------------------------------------------
  251. //
  252. // FindClosestCategory
  253. //
  254. //----------------------------------------------------------------------------
  255. HRESULT CCategoryMgr::FindClosestCategory(REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
  256. {
  257. return s_FindClosestCategory(rguid, pcatid, ppcatidList, ulCount);
  258. }
  259. HRESULT CCategoryMgr::s_FindClosestCategory(REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
  260. {
  261. // GUID catid = GUID_NULL;
  262. if (!pcatid)
  263. return E_INVALIDARG;
  264. if (!ppcatidList || !ulCount)
  265. {
  266. return _GetFirstCategory(rguid, pcatid);
  267. }
  268. for (ULONG ul = 0; ul < ulCount; ul++)
  269. {
  270. if (!ppcatidList[ul])
  271. return E_INVALIDARG;
  272. }
  273. return _InternalFindClosestCategory(rguid,
  274. rguid,
  275. pcatid,
  276. ppcatidList,
  277. ulCount);
  278. }
  279. //----------------------------------------------------------------------------
  280. //
  281. // _GetFirstCategory
  282. //
  283. //----------------------------------------------------------------------------
  284. HRESULT CCategoryMgr::_GetFirstCategory(REFGUID rguid, GUID *pcatid)
  285. {
  286. HRESULT hr;
  287. IEnumGUID *pEnum;
  288. if (SUCCEEDED(hr = _InternalEnumCategories(rguid, &pEnum, CAT_BACKWARD)))
  289. {
  290. // we return S_FALSE if we can not find it and return GUID_NULL.
  291. hr = pEnum->Next(1, pcatid, NULL);
  292. if (hr != S_OK)
  293. *pcatid = GUID_NULL;
  294. pEnum->Release();
  295. }
  296. return hr;
  297. }
  298. //----------------------------------------------------------------------------
  299. //
  300. // _InternalFindClosestCategory
  301. //
  302. //----------------------------------------------------------------------------
  303. HRESULT CCategoryMgr::_InternalFindClosestCategory(REFGUID rguidOrg, REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
  304. {
  305. HRESULT hr;
  306. ULONG ul;
  307. IEnumGUID *pEnum = NULL;
  308. GUID catid = GUID_NULL;
  309. Assert(ppcatidList);
  310. Assert(ulCount);
  311. *pcatid = GUID_NULL;
  312. for (ul = 0; ul < ulCount; ul++)
  313. {
  314. if (IsEqualGUID(*ppcatidList[ul], rguid))
  315. {
  316. *pcatid = rguid;
  317. hr = S_OK;
  318. goto Exit;
  319. }
  320. }
  321. //
  322. // we don't return error. We return success and GUID_NULL.
  323. //
  324. hr = _InternalEnumCategories(rguid, &pEnum, CAT_BACKWARD);
  325. if (hr != S_OK)
  326. {
  327. hr = S_OK;
  328. goto Exit;
  329. }
  330. while (pEnum->Next(1, &catid, NULL) == S_OK)
  331. {
  332. if (IsEqualGUID(rguidOrg, catid))
  333. {
  334. // finally the original guid is categorized by itself.
  335. // it may cause infinte loop so bail it out.
  336. hr = S_OK;
  337. goto Exit;
  338. }
  339. _InternalFindClosestCategory(rguidOrg,
  340. catid,
  341. pcatid,
  342. ppcatidList,
  343. ulCount);
  344. if (!IsEqualGUID(*pcatid, GUID_NULL))
  345. {
  346. hr = S_OK;
  347. goto Exit;
  348. }
  349. }
  350. Exit:
  351. SafeRelease(pEnum);
  352. return hr;
  353. }
  354. //----------------------------------------------------------------------------
  355. //
  356. // RegisterGUIDDesription
  357. //
  358. //----------------------------------------------------------------------------
  359. STDAPI CCategoryMgr::RegisterGUIDDescription(REFCLSID rclsid, REFGUID rguid, const WCHAR *pchDesc, ULONG cch)
  360. {
  361. if (!pchDesc && cch)
  362. return E_INVALIDARG;
  363. return s_RegisterGUIDDescription(rclsid, rguid, WCHtoWSZ(pchDesc, cch));
  364. }
  365. HRESULT CCategoryMgr::s_RegisterGUIDDescription(REFCLSID rclsid, REFGUID rguid, WCHAR *pszDesc)
  366. {
  367. TCHAR szKey[256];
  368. CMyRegKey key;
  369. if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
  370. return E_FAIL;
  371. if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
  372. return E_FAIL;
  373. key.SetValueW(pszDesc, c_wszDescription);
  374. return S_OK;
  375. }
  376. //----------------------------------------------------------------------------
  377. //
  378. // UnregisterGUIDDesription
  379. //
  380. //----------------------------------------------------------------------------
  381. STDAPI CCategoryMgr::UnregisterGUIDDescription(REFCLSID rclsid, REFGUID rguid)
  382. {
  383. return s_UnregisterGUIDDescription(rclsid, rguid);
  384. }
  385. HRESULT CCategoryMgr::s_UnregisterGUIDDescription(REFCLSID rclsid, REFGUID rguid)
  386. {
  387. TCHAR szKey[256];
  388. CMyRegKey key;
  389. if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
  390. return E_FAIL;
  391. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
  392. return E_FAIL;
  393. key.DeleteValueW(c_wszDescription);
  394. return S_OK;
  395. }
  396. //----------------------------------------------------------------------------
  397. //
  398. // GetGUIDDescription
  399. //
  400. //----------------------------------------------------------------------------
  401. STDAPI CCategoryMgr::GetGUIDDescription(REFGUID rguid, BSTR *pbstrDesc)
  402. {
  403. return s_GetGUIDDescription(rguid, pbstrDesc);
  404. }
  405. HRESULT CCategoryMgr::s_GetGUIDDescription(REFGUID rguid, BSTR *pbstrDesc)
  406. {
  407. return s_GetGUIDValue(rguid, c_szDescriptionW, pbstrDesc);
  408. }
  409. HRESULT CCategoryMgr::s_GetGUIDValue(REFGUID rguid, const WCHAR* pszValue, BSTR *pbstrDesc)
  410. {
  411. WCHAR *psz = NULL;
  412. CMyRegKey keyImx;
  413. HRESULT hr = E_FAIL;
  414. int cch;
  415. TCHAR szSubKey[256]; // nb: we can merge szSubKey and szTemp if we switch to a UNICODE build
  416. WCHAR szTemp[256];
  417. if (!pbstrDesc)
  418. return E_INVALIDARG;
  419. *pbstrDesc = NULL;
  420. if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
  421. return hr;
  422. DWORD dwIndex = 0;
  423. while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  424. {
  425. CMyRegKey key;
  426. if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, c_szItem) != S_OK)
  427. continue;
  428. cch = lstrlen(szSubKey);
  429. if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
  430. continue;
  431. CLSIDToStringA(rguid, szSubKey + cch);
  432. if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
  433. continue;
  434. if (key.QueryValueCchW(szTemp, pszValue, ARRAYSIZE(szTemp)) == S_OK)
  435. {
  436. *pbstrDesc = SysAllocString(szTemp);
  437. hr = *pbstrDesc != NULL ? S_OK : E_OUTOFMEMORY;
  438. }
  439. // this was the matching key, so no point in continue successful query or not
  440. break;
  441. }
  442. return hr;
  443. }
  444. //----------------------------------------------------------------------------
  445. //
  446. // RegisterGUIDDesription
  447. //
  448. //----------------------------------------------------------------------------
  449. STDAPI CCategoryMgr::RegisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid, DWORD dw)
  450. {
  451. return s_RegisterGUIDDWORD(rclsid, rguid, dw);
  452. }
  453. HRESULT CCategoryMgr::s_RegisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid, DWORD dw)
  454. {
  455. TCHAR szKey[256];
  456. CMyRegKey key;
  457. if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
  458. return E_FAIL;
  459. if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
  460. return E_FAIL;
  461. key.SetValue(dw, c_szDword);
  462. return S_OK;
  463. }
  464. //----------------------------------------------------------------------------
  465. //
  466. // UnregisterGUIDDesription
  467. //
  468. //----------------------------------------------------------------------------
  469. STDAPI CCategoryMgr::UnregisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid)
  470. {
  471. return s_UnregisterGUIDDWORD(rclsid, rguid);
  472. }
  473. HRESULT CCategoryMgr::s_UnregisterGUIDDWORD(REFCLSID rclsid, REFGUID rguid)
  474. {
  475. TCHAR szKey[256];
  476. CMyRegKey key;
  477. if (!GetCatKey(rclsid, rguid, szKey, ARRAYSIZE(szKey), c_szItem))
  478. return E_FAIL;
  479. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
  480. return E_FAIL;
  481. key.DeleteValue(c_szDword);
  482. return S_OK;
  483. }
  484. //----------------------------------------------------------------------------
  485. //
  486. // GetGUIDDWORD
  487. //
  488. //----------------------------------------------------------------------------
  489. STDAPI CCategoryMgr::GetGUIDDWORD(REFGUID rguid, DWORD *pdw)
  490. {
  491. return s_GetGUIDDWORD(rguid, pdw);
  492. }
  493. HRESULT CCategoryMgr::s_GetGUIDDWORD(REFGUID rguid, DWORD *pdw)
  494. {
  495. CMyRegKey keyImx;
  496. int cch;
  497. HRESULT hr = E_FAIL;
  498. if (!pdw)
  499. return E_INVALIDARG;
  500. *pdw = 0;
  501. if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
  502. return hr;
  503. DWORD dwIndex = 0;
  504. TCHAR szSubKey[256];
  505. while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  506. {
  507. CMyRegKey key;
  508. if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, c_szItem) != S_OK)
  509. continue;
  510. cch = lstrlen(szSubKey);
  511. if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
  512. continue;
  513. CLSIDToStringA(rguid, szSubKey + cch);
  514. if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
  515. continue;
  516. if (key.QueryValue(*pdw, c_szDword) == S_OK)
  517. {
  518. hr = S_OK;
  519. break;
  520. }
  521. }
  522. return hr;
  523. }
  524. //----------------------------------------------------------------------------
  525. //
  526. // RegisterProvider
  527. //
  528. //----------------------------------------------------------------------------
  529. STDAPI CCategoryMgr::RegisterGUID(REFGUID rguid, TfGuidAtom *pguidatom)
  530. {
  531. return s_RegisterGUID(rguid, pguidatom);
  532. }
  533. HRESULT CCategoryMgr::s_RegisterGUID(REFGUID rguid, TfGuidAtom *pguidatom)
  534. {
  535. TfGuidAtom guidatom;
  536. HRESULT hr = E_FAIL;
  537. CicEnterCriticalSection(g_cs);
  538. if (InitGlobal())
  539. {
  540. if ((guidatom = _pCatGUIDTbl->FindGuid(rguid)) != TF_INVALID_GUIDATOM)
  541. {
  542. *pguidatom = guidatom;
  543. hr = S_OK;
  544. }
  545. else if ((guidatom = _pCatGUIDTbl->Add(rguid)) != TF_INVALID_GUIDATOM)
  546. {
  547. *pguidatom = guidatom;
  548. hr = S_OK;
  549. }
  550. }
  551. CicLeaveCriticalSection(g_cs);
  552. return hr;
  553. }
  554. //----------------------------------------------------------------------------
  555. //
  556. // GetGUID
  557. //
  558. //----------------------------------------------------------------------------
  559. STDAPI CCategoryMgr::GetGUID(TfGuidAtom guidatom, GUID *pguid)
  560. {
  561. return s_GetGUID(guidatom, pguid);
  562. }
  563. HRESULT CCategoryMgr::s_GetGUID(TfGuidAtom guidatom, GUID *pguid)
  564. {
  565. CATGUIDITEM *pItem;
  566. HRESULT hr = E_FAIL;
  567. if (!pguid)
  568. return E_INVALIDARG;
  569. CicEnterCriticalSection(g_cs);
  570. if (InitGlobal())
  571. {
  572. pItem = _pCatGUIDTbl->GetGUID(guidatom);
  573. if (!pItem)
  574. {
  575. *pguid = GUID_NULL;
  576. goto Exit;
  577. }
  578. *pguid = pItem->guid;
  579. hr = S_OK;
  580. }
  581. Exit:
  582. CicLeaveCriticalSection(g_cs);
  583. return hr;
  584. }
  585. //----------------------------------------------------------------------------
  586. //
  587. // IsEqualTfGuidAtom
  588. //
  589. //----------------------------------------------------------------------------
  590. STDAPI CCategoryMgr::IsEqualTfGuidAtom(TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
  591. {
  592. return s_IsEqualTfGuidAtom(guidatom, rguid, pfEqual);
  593. }
  594. HRESULT CCategoryMgr::s_IsEqualTfGuidAtom(TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
  595. {
  596. HRESULT hr = E_FAIL;
  597. CATGUIDITEM *pItem;
  598. if (pfEqual == NULL)
  599. return E_INVALIDARG;
  600. *pfEqual = FALSE;
  601. CicEnterCriticalSection(g_cs);
  602. if (InitGlobal())
  603. {
  604. if (pItem = _pCatGUIDTbl->GetGUID(guidatom))
  605. {
  606. *pfEqual = IsEqualGUID(pItem->guid, rguid);
  607. hr = S_OK;
  608. }
  609. }
  610. CicLeaveCriticalSection(g_cs);
  611. return hr;
  612. }
  613. //----------------------------------------------------------------------------
  614. //
  615. // InternalRegisterCategory
  616. //
  617. //----------------------------------------------------------------------------
  618. HRESULT CCategoryMgr::_InternalRegisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid, CATDIRECTION catdir)
  619. {
  620. TCHAR szKey[256];
  621. CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
  622. CMyRegKey key;
  623. CMyRegKey keySub;
  624. if (!GetCatKey(rclsid, rcatid, szKey, ARRAYSIZE(szKey), pszForward))
  625. return E_FAIL;
  626. if (key.Create(HKEY_LOCAL_MACHINE, szKey) != S_OK)
  627. return E_FAIL;
  628. //
  629. // we add this guid and save it.
  630. //
  631. char szValue[CLSID_STRLEN + 1];
  632. CLSIDToStringA(rguid, szValue);
  633. keySub.Create(key, szValue);
  634. _FlushGuidArrayCache(rguid, catdir);
  635. return S_OK;
  636. }
  637. //----------------------------------------------------------------------------
  638. //
  639. // UnregisterCategory
  640. //
  641. //----------------------------------------------------------------------------
  642. HRESULT CCategoryMgr::_InternalUnregisterCategory(REFCLSID rclsid, REFGUID rcatid, REFGUID rguid, CATDIRECTION catdir)
  643. {
  644. TCHAR szKey[256];
  645. CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
  646. CMyRegKey key;
  647. if (!GetCatKey(rclsid, rcatid, szKey, ARRAYSIZE(szKey), pszForward))
  648. return E_FAIL;
  649. if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_ALL_ACCESS) != S_OK)
  650. return E_FAIL;
  651. DWORD dwIndex = 0;
  652. char szValue[CLSID_STRLEN + 1];
  653. CLSIDToStringA(rguid, szValue);
  654. key.RecurseDeleteKey(szValue);
  655. _FlushGuidArrayCache(rguid, catdir);
  656. return S_OK;
  657. }
  658. //----------------------------------------------------------------------------
  659. //
  660. // _FlushGuidArrayCache
  661. //
  662. //----------------------------------------------------------------------------
  663. void CCategoryMgr::_FlushGuidArrayCache(REFGUID rguid, CATDIRECTION catdir)
  664. {
  665. TfGuidAtom guidatom;
  666. CATGUIDITEM *pItem;
  667. CicEnterCriticalSection(g_cs);
  668. if (!_pCatGUIDTbl)
  669. goto Exit;
  670. guidatom = _pCatGUIDTbl->FindGuid(rguid);
  671. if (guidatom == TF_INVALID_GUIDATOM)
  672. goto Exit;
  673. pItem = _pCatGUIDTbl->GetGUID(guidatom);
  674. if (!pItem)
  675. {
  676. Assert(0);
  677. goto Exit;
  678. }
  679. SGA_Release(pItem->rgGuidAry[catdir]);
  680. pItem->rgGuidAry[catdir] = NULL;
  681. Exit:
  682. CicLeaveCriticalSection(g_cs);
  683. }
  684. //----------------------------------------------------------------------------
  685. //
  686. // _InternalEnumCategories
  687. //
  688. //----------------------------------------------------------------------------
  689. HRESULT CCategoryMgr::_InternalEnumCategories(REFGUID rguid, IEnumGUID **ppEnum, CATDIRECTION catdir)
  690. {
  691. CEnumCategories *pEnum;
  692. if (!ppEnum)
  693. return E_INVALIDARG;
  694. pEnum = new CEnumCategories();
  695. if (!pEnum)
  696. return E_OUTOFMEMORY;
  697. if (pEnum->_Init(rguid, catdir))
  698. *ppEnum = pEnum;
  699. else
  700. SafeReleaseClear(pEnum);
  701. return pEnum ? S_OK : E_FAIL;
  702. }
  703. //////////////////////////////////////////////////////////////////////////////
  704. //
  705. // CEnumCategories
  706. //
  707. //////////////////////////////////////////////////////////////////////////////
  708. //+---------------------------------------------------------------------------
  709. //
  710. // ctor
  711. //
  712. //----------------------------------------------------------------------------
  713. CEnumCategories::CEnumCategories()
  714. {
  715. Dbg_MemSetThisNameIDCounter(TEXT("CEnumCategories"), PERF_ENUMCAT_COUNTER);
  716. }
  717. //+---------------------------------------------------------------------------
  718. //
  719. // Init
  720. //
  721. //----------------------------------------------------------------------------
  722. BOOL CEnumCategories::_Init(REFGUID rcatid, CATDIRECTION catdir)
  723. {
  724. int cch;
  725. int nCnt = 0;
  726. BOOL bRet = FALSE;
  727. CMyRegKey keyImx;
  728. TfGuidAtom guidatom;
  729. CATGUIDITEM *pItem;
  730. CONST TCHAR *pszForward = (catdir == CAT_FORWARD) ? c_szCategory : c_szItem;
  731. DWORD dwIndex = 0;
  732. TCHAR szSubKey[256];
  733. ULONG cGuidMax = 64;
  734. ULONG cGuidCurrent = 0;
  735. CicEnterCriticalSection(g_cs);
  736. if (!CCategoryMgr::InitGlobal())
  737. goto LeaveCrtSec;
  738. guidatom = CCategoryMgr::_pCatGUIDTbl->FindGuid(rcatid);
  739. if (guidatom == TF_INVALID_GUIDATOM)
  740. {
  741. guidatom = CCategoryMgr::_pCatGUIDTbl->Add(rcatid);
  742. if (guidatom == TF_INVALID_GUIDATOM)
  743. goto LeaveCrtSec;
  744. }
  745. pItem = CCategoryMgr::_pCatGUIDTbl->GetGUID(guidatom);
  746. Assert(pItem);
  747. if (_pga = pItem->rgGuidAry[catdir])
  748. {
  749. // already have this GUID cached, just reference it
  750. SGA_AddRef(_pga);
  751. bRet = TRUE;
  752. goto LeaveCrtSec;
  753. }
  754. _pga = SGA_Alloc(cGuidMax);
  755. if (!_pga)
  756. goto LeaveCrtSec;
  757. _pga->cRef = 1;
  758. if (keyImx.Open(HKEY_LOCAL_MACHINE, c_szCTFTIPKey, KEY_READ) != S_OK)
  759. goto LeaveCrtSec;
  760. while (keyImx.EnumKey(dwIndex++, szSubKey, ARRAYSIZE(szSubKey)) == S_OK)
  761. {
  762. CMyRegKey key;
  763. if (StringCchPrintf(szSubKey + lstrlen(szSubKey), ARRAYSIZE(szSubKey), "\\%s%s", c_szCategoryKey, pszForward) != S_OK)
  764. continue;
  765. cch = lstrlen(szSubKey);
  766. if (cch + CLSID_STRLEN + 1 > ARRAYSIZE(szSubKey))
  767. continue;
  768. CLSIDToStringA(rcatid, szSubKey + cch);
  769. if (key.Open(keyImx, szSubKey, KEY_READ) != S_OK)
  770. continue;
  771. DWORD dwSize = 0;
  772. DWORD dwIndex2 = 0;
  773. char szValueName[CLSID_STRLEN + 1];
  774. while (key.EnumKey(dwIndex2++, szValueName, ARRAYSIZE(szValueName)) == S_OK)
  775. {
  776. if (lstrlen(szValueName) == CLSID_STRLEN)
  777. {
  778. if (cGuidCurrent >= cGuidMax)
  779. {
  780. cGuidMax += 64;
  781. if (!SGA_ReAlloc(&_pga, cGuidMax))
  782. goto LeaveCrtSec;
  783. }
  784. StringAToCLSID(szValueName, &_pga->rgGuid[cGuidCurrent]);
  785. cGuidCurrent++;
  786. }
  787. }
  788. }
  789. // free up unused memory
  790. if (!SGA_ReAlloc(&_pga, cGuidCurrent))
  791. goto LeaveCrtSec;
  792. bRet = TRUE;
  793. _pga->cGuid = cGuidCurrent;
  794. // put this array in the cache
  795. pItem->rgGuidAry[catdir] = _pga;
  796. SGA_AddRef(pItem->rgGuidAry[catdir]);
  797. LeaveCrtSec:
  798. CicLeaveCriticalSection(g_cs);
  799. return bRet;
  800. }