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.

824 lines
21 KiB

  1. //
  2. // dam.cpp
  3. //
  4. #include "private.h"
  5. #include "tlhelp32.h"
  6. #include "globals.h"
  7. #include "dam.h"
  8. #include "tim.h"
  9. #include "thdutil.h"
  10. #include "timlist.h"
  11. // get CLSID_STRLEN
  12. #include "regsvr.h"
  13. /* ff4619e8-ea5e-43e5-b308-11cd26ab6b3a */
  14. const IID IID_CDisplayAttributeMgr = { 0xff4619e8, 0xea5e, 0x43e5, {0xb3, 0x08, 0x11, 0xcd, 0x26, 0xab, 0x6b, 0x3a} };
  15. const TCHAR c_szDAMCacheKey[] = TEXT("SOFTWARE\\Microsoft\\CTF\\DisplayAttributeCache\\");
  16. const TCHAR c_szDAMNumValue[] = TEXT("CheckNum");
  17. CDispAttrGuidCache *g_pDispAttrGuidCache = NULL;
  18. //
  19. // from aimm1.2\win32\aimmdap.cpp
  20. //
  21. /* 503286E2-5D2A-4D3D-B0D1-EE50D843B79D */
  22. const CLSID CLSID_CAImmDAP = {
  23. 0x503286E2,
  24. 0x5D2A,
  25. 0x4D3D,
  26. {0xB0, 0xD1, 0xEE, 0x50, 0xD8, 0x43, 0xB7, 0x9D}
  27. };
  28. DBG_ID_INSTANCE(CDisplayAttributeMgr);
  29. DBG_ID_INSTANCE(CEnumDisplayAttributeInfo);
  30. //////////////////////////////////////////////////////////////////////////////
  31. //
  32. // CDispAttrGuidCache
  33. //
  34. //////////////////////////////////////////////////////////////////////////////
  35. //+---------------------------------------------------------------------------
  36. //
  37. // StaticUnInit
  38. //
  39. // Caller must hold mutex.
  40. //----------------------------------------------------------------------------
  41. void CDispAttrGuidCache::StaticUnInit()
  42. {
  43. Assert(ISINDLLMAIN()); // for mutex
  44. if (g_pDispAttrGuidCache)
  45. delete g_pDispAttrGuidCache;
  46. g_pDispAttrGuidCache = NULL;
  47. }
  48. //+---------------------------------------------------------------------------
  49. //
  50. // StaticInit
  51. //
  52. //----------------------------------------------------------------------------
  53. void CDispAttrGuidCache::StaticInit()
  54. {
  55. CicEnterCriticalSection(g_cs);
  56. if (!g_pDispAttrGuidCache)
  57. {
  58. g_pDispAttrGuidCache = new CDispAttrGuidCache();
  59. if (g_pDispAttrGuidCache)
  60. g_pDispAttrGuidCache->Load();
  61. }
  62. CicLeaveCriticalSection(g_cs);
  63. }
  64. //+---------------------------------------------------------------------------
  65. //
  66. // Add
  67. //
  68. //----------------------------------------------------------------------------
  69. BOOL CDispAttrGuidCache::Add(REFCLSID clsid, REFGUID guid)
  70. {
  71. BOOL bRet = FALSE;
  72. TfGuidAtom gaGuid;
  73. TfGuidAtom gaClsid;
  74. if (FAILED(MyRegisterGUID(clsid, &gaClsid)))
  75. return bRet;
  76. if (FAILED(MyRegisterGUID(guid, &gaGuid)))
  77. return bRet;
  78. CicEnterCriticalSection(g_cs);
  79. if (!Get(gaGuid, NULL))
  80. {
  81. DISPATTRGUID *pGuid;
  82. if (!_rgDispAttrGuid.Insert(0, 1))
  83. {
  84. goto Exit;
  85. }
  86. pGuid = _rgDispAttrGuid.GetPtr(0);
  87. pGuid->clsid = clsid;
  88. pGuid->gaClsid = gaClsid;
  89. pGuid->guid = guid;
  90. pGuid->gaGuid = gaGuid;
  91. }
  92. bRet = TRUE;
  93. Exit:
  94. CicLeaveCriticalSection(g_cs);
  95. return bRet;
  96. }
  97. //+---------------------------------------------------------------------------
  98. //
  99. // Remove
  100. //
  101. //----------------------------------------------------------------------------
  102. void CDispAttrGuidCache::Remove(TfGuidAtom guidatom)
  103. {
  104. int nCnt = _rgDispAttrGuid.Count();
  105. int i;
  106. for (i = 0; i < nCnt; i++)
  107. {
  108. DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(i);
  109. if (pGuid->gaGuid == guidatom)
  110. {
  111. _rgDispAttrGuid.Remove(i, 1);
  112. return;
  113. }
  114. }
  115. }
  116. //+---------------------------------------------------------------------------
  117. //
  118. // RemoveClsid
  119. //
  120. //----------------------------------------------------------------------------
  121. void CDispAttrGuidCache::RemoveClsid(TfGuidAtom guidatom)
  122. {
  123. int nCnt = _rgDispAttrGuid.Count();
  124. int i;
  125. i = 0;
  126. while (i < nCnt)
  127. {
  128. DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(i);
  129. if (pGuid->gaClsid == guidatom)
  130. {
  131. _rgDispAttrGuid.Remove(i, 1);
  132. nCnt--;
  133. continue;
  134. }
  135. i++;
  136. }
  137. }
  138. //+---------------------------------------------------------------------------
  139. //
  140. // Get
  141. //
  142. //----------------------------------------------------------------------------
  143. BOOL CDispAttrGuidCache::Get(TfGuidAtom guidatom, DISPATTRGUID *pDisp)
  144. {
  145. BOOL bRet;
  146. CicEnterCriticalSection(g_cs);
  147. bRet = InternalGet(guidatom, pDisp);
  148. CicLeaveCriticalSection(g_cs);
  149. return bRet;
  150. }
  151. //+---------------------------------------------------------------------------
  152. //
  153. // InternalGet
  154. //
  155. //----------------------------------------------------------------------------
  156. BOOL CDispAttrGuidCache::InternalGet(TfGuidAtom guidatom, DISPATTRGUID *pDisp)
  157. {
  158. int nCnt;
  159. int i;
  160. BOOL bRet = FALSE;
  161. nCnt = _rgDispAttrGuid.Count();
  162. DISPATTRGUID *pGuid = _rgDispAttrGuid.GetPtr(0);
  163. for (i = 0; i < nCnt; i++)
  164. {
  165. if (pGuid->gaGuid == guidatom)
  166. {
  167. if (pDisp)
  168. *pDisp = *pGuid;
  169. bRet = TRUE;
  170. goto Exit;
  171. }
  172. pGuid++;
  173. }
  174. Exit:
  175. return bRet;
  176. }
  177. //+---------------------------------------------------------------------------
  178. //
  179. // IsClsid
  180. //
  181. //----------------------------------------------------------------------------
  182. BOOL CDispAttrGuidCache::IsClsid(TfGuidAtom gaClsid)
  183. {
  184. BOOL bRet = FALSE;
  185. int nCnt;
  186. int i;
  187. DISPATTRGUID *pGuid;
  188. CicEnterCriticalSection(g_cs);
  189. pGuid = _rgDispAttrGuid.GetPtr(0);
  190. nCnt = _rgDispAttrGuid.Count();
  191. for (i = 0; i < nCnt; i++)
  192. {
  193. if (pGuid->gaClsid == gaClsid)
  194. {
  195. bRet = TRUE;
  196. break;
  197. }
  198. pGuid++;
  199. }
  200. CicLeaveCriticalSection(g_cs);
  201. return bRet;
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Save
  206. //
  207. //----------------------------------------------------------------------------
  208. HRESULT CDispAttrGuidCache::Save()
  209. {
  210. DWORD dw;
  211. HKEY hKeyDAM;
  212. DISPATTRGUID *pDAG;
  213. int nCnt;
  214. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szDAMCacheKey, 0, NULL,
  215. REG_OPTION_NON_VOLATILE,
  216. KEY_ALL_ACCESS,
  217. NULL,
  218. &hKeyDAM,
  219. &dw) != ERROR_SUCCESS)
  220. {
  221. return E_FAIL;
  222. }
  223. nCnt = _rgDispAttrGuid.Count();
  224. if (nCnt)
  225. {
  226. pDAG = _rgDispAttrGuid.GetPtr(0);
  227. RegSetValueEx(hKeyDAM, NULL, 0, REG_BINARY,
  228. (CONST BYTE *)pDAG, sizeof(DISPATTRGUID) * nCnt);
  229. RegSetValueEx(hKeyDAM, c_szDAMNumValue, 0, REG_DWORD,
  230. (LPBYTE)&nCnt, sizeof(DWORD));
  231. }
  232. else
  233. {
  234. RegDeleteValue(hKeyDAM, NULL);
  235. RegDeleteValue(hKeyDAM, c_szDAMNumValue);
  236. }
  237. RegCloseKey(hKeyDAM);
  238. return S_OK;
  239. }
  240. //+---------------------------------------------------------------------------
  241. //
  242. // Load
  243. //
  244. //----------------------------------------------------------------------------
  245. HRESULT CDispAttrGuidCache::Load()
  246. {
  247. HKEY hKeyDAM;
  248. HRESULT hr = E_FAIL;
  249. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szDAMCacheKey, 0,
  250. KEY_READ, &hKeyDAM) != ERROR_SUCCESS)
  251. {
  252. return hr;
  253. }
  254. Assert(_rgDispAttrGuid.Count() == 0);
  255. DWORD dwType = REG_DWORD;
  256. DWORD dwSize = sizeof(DWORD);
  257. DWORD dwCntReg = 0;
  258. //
  259. // Issue: should be removed before release.
  260. // we changed the size of structre so old chace does not match with
  261. // new one. Check the size of structure.
  262. //
  263. if (RegQueryValueEx(hKeyDAM, c_szDAMNumValue, 0, &dwType,
  264. (LPBYTE)&dwCntReg, &dwSize) != ERROR_SUCCESS)
  265. dwCntReg = 0;
  266. dwType = REG_BINARY;
  267. if (RegQueryValueEx(hKeyDAM, NULL, 0, &dwType,
  268. NULL, &dwSize) == ERROR_SUCCESS)
  269. {
  270. DWORD i;
  271. DWORD dwCnt = dwSize / sizeof(DISPATTRGUID);
  272. if (dwCnt != dwCntReg)
  273. goto Exit;
  274. _rgDispAttrGuid.Insert(0, dwCnt);
  275. DISPATTRGUID *pDAG = _rgDispAttrGuid.GetPtr(0);
  276. RegQueryValueEx(hKeyDAM, NULL, 0, &dwType, (BYTE *)pDAG, &dwSize);
  277. for (i = 0; i < dwCnt; i++)
  278. {
  279. if (FAILED(MyRegisterGUID(pDAG[i].clsid, &pDAG[i].gaClsid)))
  280. goto Exit;
  281. if (FAILED(MyRegisterGUID(pDAG[i].guid, &pDAG[i].gaGuid)))
  282. goto Exit;
  283. }
  284. }
  285. hr = S_OK;
  286. Exit:
  287. RegCloseKey(hKeyDAM);
  288. return hr;
  289. }
  290. //////////////////////////////////////////////////////////////////////////////
  291. //
  292. // CDisplayAttributeMgr
  293. //
  294. //////////////////////////////////////////////////////////////////////////////
  295. //+---------------------------------------------------------------------------
  296. //
  297. // ctor
  298. //
  299. //----------------------------------------------------------------------------
  300. CDisplayAttributeMgr::CDisplayAttributeMgr()
  301. {
  302. Dbg_MemSetThisNameID(TEXT("CDisplayAttributeMgr"));
  303. _SetThis(this);
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // dtor
  308. //
  309. //----------------------------------------------------------------------------
  310. CDisplayAttributeMgr::~CDisplayAttributeMgr()
  311. {
  312. int nCnt = _rgDaPrv.Count();
  313. if (nCnt)
  314. {
  315. DAPROVIDERMAP *pDaPrv;
  316. pDaPrv = _rgDaPrv.GetPtr(0);
  317. while(nCnt--)
  318. {
  319. pDaPrv->pPrv->Release();
  320. pDaPrv++;
  321. }
  322. }
  323. _SetThis(NULL); // clear out singleton tls
  324. }
  325. //----------------------------------------------------------------------------
  326. //
  327. // OnUndateinfo
  328. //
  329. // Use kernel32 or ntdll directly to enumerate all threads, because
  330. // we don't have global TIM list.
  331. //
  332. //----------------------------------------------------------------------------
  333. HRESULT CDisplayAttributeMgr::OnUpdateInfo()
  334. {
  335. PostTimListMessage(TLF_TIMACTIVE,
  336. 0,
  337. g_msgPrivate,
  338. TFPRIV_UPDATEDISPATTR,
  339. 0);
  340. return S_OK;
  341. }
  342. //----------------------------------------------------------------------------
  343. //
  344. // EnumThreadProc
  345. //
  346. //----------------------------------------------------------------------------
  347. BOOL CDisplayAttributeMgr::EnumThreadProc(DWORD dwThread, DWORD dwProcessId, void *pv)
  348. {
  349. PostThreadMessage(dwThread, g_msgPrivate, TFPRIV_UPDATEDISPATTR, 0);
  350. return FALSE;
  351. }
  352. //----------------------------------------------------------------------------
  353. //
  354. // EnumDisplayAttributeInfo
  355. //
  356. //----------------------------------------------------------------------------
  357. HRESULT CDisplayAttributeMgr::EnumDisplayAttributeInfo(IEnumTfDisplayAttributeInfo **ppEnum)
  358. {
  359. CEnumDisplayAttributeInfo *pEnum;
  360. if (!ppEnum)
  361. return E_INVALIDARG;
  362. pEnum = new CEnumDisplayAttributeInfo();
  363. if (!pEnum)
  364. return E_OUTOFMEMORY;
  365. if (pEnum->Init())
  366. *ppEnum = pEnum;
  367. else
  368. SafeReleaseClear(pEnum);
  369. return pEnum ? S_OK : E_FAIL;
  370. }
  371. //----------------------------------------------------------------------------
  372. //
  373. // GetDisplayAttributeInfo
  374. //
  375. //----------------------------------------------------------------------------
  376. HRESULT CDisplayAttributeMgr::GetDisplayAttributeInfo(REFGUID guid, ITfDisplayAttributeInfo **ppInfo, CLSID *pclsid)
  377. {
  378. CLSID clsid;
  379. ITfDisplayAttributeProvider *pProvider;
  380. HRESULT hr = E_FAIL;
  381. StaticCacheInit();
  382. if (ppInfo)
  383. *ppInfo = NULL;
  384. if (g_pDispAttrGuidCache)
  385. {
  386. DISPATTRGUID dag;
  387. TfGuidAtom gaGuid;
  388. if (FAILED(MyRegisterGUID(guid, &gaGuid)))
  389. return hr;
  390. if (g_pDispAttrGuidCache->Get(gaGuid, &dag))
  391. {
  392. if (ppInfo)
  393. {
  394. DAPROVIDERMAP *pDaPrv;
  395. int i;
  396. int nCnt = _rgDaPrv.Count();
  397. BOOL bFound = FALSE;
  398. for (i = 0; i < nCnt; i++)
  399. {
  400. pDaPrv = _rgDaPrv.GetPtr(i);
  401. if (pDaPrv->gaClsid == dag.gaClsid)
  402. {
  403. Assert(pDaPrv->pPrv);
  404. hr = pDaPrv->pPrv->GetDisplayAttributeInfo(guid, ppInfo);
  405. bFound = TRUE;
  406. break;
  407. }
  408. }
  409. if (!bFound &&
  410. SUCCEEDED(CoCreateInstance(dag.clsid,
  411. NULL,
  412. CLSCTX_INPROC_SERVER,
  413. IID_ITfDisplayAttributeProvider,
  414. (void**)&pProvider)))
  415. {
  416. hr = pProvider->GetDisplayAttributeInfo(guid, ppInfo);
  417. if (_rgDaPrv.Insert(nCnt, 1))
  418. {
  419. pDaPrv = _rgDaPrv.GetPtr(nCnt);
  420. pDaPrv->gaClsid = dag.gaClsid;
  421. pDaPrv->pPrv = pProvider;
  422. }
  423. else
  424. pProvider->Release();
  425. }
  426. }
  427. else
  428. {
  429. hr = S_OK;
  430. }
  431. if (SUCCEEDED(hr))
  432. {
  433. if (pclsid)
  434. *pclsid = dag.clsid;
  435. return hr;
  436. }
  437. //
  438. // someone removed DisplayAttribute Info. So we clear the cache.
  439. //
  440. g_pDispAttrGuidCache->Clear();
  441. }
  442. }
  443. IEnumGUID *pEnumGUID;
  444. if (FAILED(MyEnumItemsInCategory(GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &pEnumGUID)))
  445. return E_FAIL;
  446. DWORD dwIndex = 0;
  447. BOOL fFound = FALSE;
  448. CThreadInputMgr *ptim = CThreadInputMgr::_GetThis();
  449. if (ptim == NULL)
  450. goto Exit;
  451. while (!fFound && (pEnumGUID->Next(1, &clsid, NULL) == S_OK))
  452. {
  453. if (!IsEqualCLSID(clsid, CLSID_CAImmDAP) &&
  454. (ptim->_IsActiveInputProcessor(clsid) != S_OK))
  455. continue;
  456. //
  457. // Issue:
  458. //
  459. // we may want to load only providers that are enabled in this
  460. // thread. Use CIMEList to check if tips is enabled.
  461. //
  462. if (SUCCEEDED(CoCreateInstance(clsid,
  463. NULL,
  464. CLSCTX_INPROC_SERVER,
  465. IID_ITfDisplayAttributeProvider,
  466. (void**)&pProvider)))
  467. {
  468. IEnumTfDisplayAttributeInfo *pEnumDAI;
  469. if (SUCCEEDED(pProvider->EnumDisplayAttributeInfo(&pEnumDAI)))
  470. {
  471. ITfDisplayAttributeInfo *pInfo;
  472. while (pEnumDAI->Next(1, &pInfo, NULL) == S_OK)
  473. {
  474. GUID guidTemp;
  475. if (SUCCEEDED(pInfo->GetGUID(&guidTemp)))
  476. {
  477. if (g_pDispAttrGuidCache)
  478. g_pDispAttrGuidCache->Add(clsid, guidTemp);
  479. if (IsEqualGUID(guidTemp, guid))
  480. {
  481. if (ppInfo)
  482. *ppInfo = pInfo;
  483. if (pclsid)
  484. *pclsid = clsid;
  485. fFound = TRUE;
  486. hr = S_OK;
  487. break;
  488. }
  489. }
  490. pInfo->Release();
  491. }
  492. pEnumDAI->Release();
  493. }
  494. pProvider->Release();
  495. }
  496. }
  497. Exit:
  498. pEnumGUID->Release();
  499. if (g_pDispAttrGuidCache)
  500. g_pDispAttrGuidCache->Save();
  501. return hr;
  502. }
  503. //----------------------------------------------------------------------------
  504. //
  505. // RegisterGUID
  506. //
  507. //----------------------------------------------------------------------------
  508. HRESULT CDisplayAttributeMgr::_RegisterGUID(const TCHAR *pszKey, REFGUID rguid, WCHAR *pszDesc, ULONG cchDesc)
  509. {
  510. DWORD dw;
  511. HKEY hKeyDAM;
  512. HKEY hKeyItem;
  513. TCHAR achGuid[CLSID_STRLEN+1];
  514. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL,
  515. REG_OPTION_NON_VOLATILE,
  516. KEY_ALL_ACCESS,
  517. NULL,
  518. &hKeyDAM,
  519. &dw) != ERROR_SUCCESS)
  520. {
  521. return E_FAIL;
  522. }
  523. CLSIDToStringA(rguid, achGuid);
  524. if (RegCreateKeyEx(hKeyDAM, achGuid, 0, NULL,
  525. REG_OPTION_NON_VOLATILE,
  526. KEY_ALL_ACCESS,
  527. NULL,
  528. &hKeyItem,
  529. &dw) == ERROR_SUCCESS)
  530. {
  531. int cchDescA = cchDesc * sizeof(WCHAR) + 1;
  532. char *pszDescA = new char[cchDescA];
  533. if (pszDescA)
  534. {
  535. cchDescA = WideCharToMultiByte(CP_ACP, 0,
  536. pszDesc, wcslen(pszDesc),
  537. pszDescA, cchDescA,
  538. NULL, NULL);
  539. *(pszDescA + cchDescA) = L'\0';
  540. RegSetValueEx(hKeyItem, TEXT("Description"), 0, REG_SZ,
  541. (CONST BYTE *)pszDescA, cchDescA);
  542. delete pszDescA;
  543. }
  544. RegCloseKey(hKeyItem);
  545. }
  546. RegCloseKey(hKeyDAM);
  547. return S_OK;
  548. }
  549. //----------------------------------------------------------------------------
  550. //
  551. // UnregisterGUID
  552. //
  553. //----------------------------------------------------------------------------
  554. HRESULT CDisplayAttributeMgr::_UnregisterGUID(const TCHAR *pszKey, REFGUID rguid)
  555. {
  556. DWORD dw;
  557. HKEY hKeyDAM;
  558. TCHAR achGuid[CLSID_STRLEN+1];
  559. if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, pszKey, 0, NULL,
  560. REG_OPTION_NON_VOLATILE,
  561. KEY_ALL_ACCESS,
  562. NULL,
  563. &hKeyDAM,
  564. &dw) != ERROR_SUCCESS)
  565. {
  566. return E_FAIL;
  567. }
  568. CLSIDToStringA(rguid, achGuid);
  569. RegDeleteKey(hKeyDAM, achGuid);
  570. RegCloseKey(hKeyDAM);
  571. return S_OK;
  572. }
  573. //////////////////////////////////////////////////////////////////////////////
  574. //
  575. // CEnumDisplayAttributeInfo
  576. //
  577. //////////////////////////////////////////////////////////////////////////////
  578. //+---------------------------------------------------------------------------
  579. //
  580. // ctor
  581. //
  582. //----------------------------------------------------------------------------
  583. CEnumDisplayAttributeInfo::CEnumDisplayAttributeInfo()
  584. {
  585. Dbg_MemSetThisNameID(TEXT("CEnumDisplayAttributeInfo"));
  586. }
  587. //+---------------------------------------------------------------------------
  588. //
  589. // Init
  590. //
  591. //----------------------------------------------------------------------------
  592. BOOL CEnumDisplayAttributeInfo::Init()
  593. {
  594. IEnumGUID *pEnumGUID;
  595. CLSID clsid;
  596. ULONG uDAMax;
  597. BOOL fRet;
  598. StaticCacheInit();
  599. if (FAILED(MyEnumItemsInCategory(GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &pEnumGUID)))
  600. return FALSE;
  601. fRet = FALSE;
  602. if ((_prgUnk = SUA_Alloc(1)) == NULL)
  603. goto Exit;
  604. _prgUnk->cRef = 1;
  605. _prgUnk->cUnk = 0;
  606. uDAMax = 1;
  607. while (pEnumGUID->Next(1, &clsid, NULL) == S_OK)
  608. {
  609. ITfDisplayAttributeProvider *pProvider;
  610. //
  611. // Issue:
  612. //
  613. // we may want to load only providers that are enabled in this
  614. // thread. Use CIMEList to check if tips is enabled.
  615. //
  616. if (SUCCEEDED(CoCreateInstance(clsid,
  617. NULL,
  618. CLSCTX_INPROC_SERVER,
  619. IID_ITfDisplayAttributeProvider,
  620. (void**)&pProvider)))
  621. {
  622. IEnumTfDisplayAttributeInfo *pEnum;
  623. if (SUCCEEDED(pProvider->EnumDisplayAttributeInfo(&pEnum)))
  624. {
  625. ITfDisplayAttributeInfo *pInfo;
  626. while (pEnum->Next(1, &pInfo, NULL) == S_OK)
  627. {
  628. GUID guidTemp;
  629. if (SUCCEEDED(pInfo->GetGUID(&guidTemp)))
  630. {
  631. if (g_pDispAttrGuidCache)
  632. g_pDispAttrGuidCache->Add(clsid, guidTemp);
  633. }
  634. if (_prgUnk->cUnk >= uDAMax)
  635. {
  636. // need a bigger array
  637. uDAMax *= 2;
  638. if (!SUA_ReAlloc(&_prgUnk, uDAMax))
  639. {
  640. pInfo->Release();
  641. SUA_Release(_prgUnk);
  642. _prgUnk = NULL;
  643. goto Exit;
  644. }
  645. }
  646. _prgUnk->rgUnk[_prgUnk->cUnk++] = pInfo;
  647. }
  648. pEnum->Release();
  649. }
  650. pProvider->Release();
  651. }
  652. }
  653. if (uDAMax > _prgUnk->cUnk)
  654. {
  655. // free up unused mem
  656. SUA_ReAlloc(&_prgUnk, _prgUnk->cUnk);
  657. }
  658. fRet = TRUE;
  659. Exit:
  660. pEnumGUID->Release();
  661. if (g_pDispAttrGuidCache)
  662. g_pDispAttrGuidCache->Save();
  663. return fRet;
  664. }