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.

968 lines
23 KiB

  1. //
  2. // compart.cpp
  3. //
  4. #include "private.h"
  5. #include "globals.h"
  6. #include "regsvr.h"
  7. #include "compart.h"
  8. #include "helpers.h"
  9. #include "thdutil.h"
  10. #include "tim.h"
  11. #include "cicmutex.h"
  12. #include "timlist.h"
  13. #include "cregkey.h"
  14. /* e575186e-71a8-4ef4-90da-14ed705e7df2 */
  15. extern const IID IID_PRIV_CCOMPARTMENTMGR = {
  16. 0xe575186e,
  17. 0x71a8,
  18. 0x4ef4,
  19. {0x90, 0xda, 0x14, 0xed, 0x70, 0x5e, 0x7d, 0xf2}
  20. };
  21. /* 8b05c1ad-adf0-4a78-a3e2-d38cae3e28be */
  22. extern const IID IID_PRIV_CGLOBALCOMPARTMENT = {
  23. 0x8b05c1ad,
  24. 0xadf0,
  25. 0x4a78,
  26. {0xa3, 0xe2, 0xd3, 0x8c, 0xae, 0x3e, 0x28, 0xbe}
  27. };
  28. DBG_ID_INSTANCE(CCompartment);
  29. DBG_ID_INSTANCE(CCompartmentMgr);
  30. DBG_ID_INSTANCE(CEnumCompartment);
  31. DBG_ID_INSTANCE(CGlobalCompartment);
  32. extern CCicMutex g_mutexCompart;
  33. //+---------------------------------------------------------------------------
  34. //
  35. // EnsureGlobalCompartment
  36. //
  37. //----------------------------------------------------------------------------
  38. BOOL EnsureGlobalCompartment(SYSTHREAD *psfn)
  39. {
  40. if (psfn->_pGlobalCompMgr)
  41. return TRUE;
  42. psfn->_pGlobalCompMgr = new CGlobalCompartmentMgr(g_gaApp);
  43. if (psfn->_pGlobalCompMgr)
  44. {
  45. if (g_gcomplist.Init(psfn))
  46. return TRUE;
  47. delete psfn->_pGlobalCompMgr;
  48. psfn->_pGlobalCompMgr = NULL;
  49. }
  50. return FALSE;
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // GetCompartmentDWORD
  55. //
  56. //----------------------------------------------------------------------------
  57. HRESULT MyGetCompartmentDWORD(CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD *pdw)
  58. {
  59. HRESULT hr;
  60. ITfCompartment *pComp;
  61. VARIANT var;
  62. if (!pCompMgr)
  63. return E_FAIL;
  64. *pdw = 0;
  65. if (SUCCEEDED(hr = pCompMgr->GetCompartment(rguid, &pComp)))
  66. {
  67. hr = pComp->GetValue(&var);
  68. if (hr == S_OK)
  69. {
  70. Assert(var.vt == VT_I4);
  71. *pdw = var.lVal;
  72. // no need to VariantClear because VT_I4
  73. }
  74. pComp->Release();
  75. }
  76. return hr;
  77. }
  78. //+---------------------------------------------------------------------------
  79. //
  80. // SetCompartmentDWORD
  81. //
  82. //----------------------------------------------------------------------------
  83. HRESULT MySetCompartmentDWORD(TfClientId tid, CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD dw)
  84. {
  85. HRESULT hr;
  86. ITfCompartment *pComp;
  87. VARIANT var;
  88. if (!pCompMgr)
  89. return E_FAIL;
  90. if (SUCCEEDED(hr = pCompMgr->GetCompartment(rguid, &pComp)))
  91. {
  92. var.vt = VT_I4;
  93. var.lVal = dw;
  94. hr = pComp->SetValue(tid, &var);
  95. pComp->Release();
  96. }
  97. return hr;
  98. }
  99. //+---------------------------------------------------------------------------
  100. //
  101. // ToggleCompartmentDWORD
  102. //
  103. // Toggle DWORD value between 0 and 1.
  104. //
  105. //----------------------------------------------------------------------------
  106. HRESULT MyToggleCompartmentDWORD(TfClientId tid, CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD *pdwOld)
  107. {
  108. ITfCompartment *pComp;
  109. VARIANT var;
  110. DWORD dw = 0;
  111. HRESULT hr = E_FAIL;
  112. if (!pCompMgr)
  113. return E_FAIL;
  114. if (pCompMgr->GetCompartment(rguid, &pComp) == S_OK)
  115. {
  116. if (SUCCEEDED(pComp->GetValue(&var)))
  117. {
  118. if (var.vt == VT_EMPTY)
  119. {
  120. // compartment is uninitialized
  121. var.vt = VT_I4;
  122. var.lVal = 0;
  123. }
  124. else
  125. {
  126. Assert(var.vt == VT_I4);
  127. }
  128. var.lVal = (var.lVal == 0) ? 1 : 0;
  129. // no need to VariantClear because VT_I4
  130. if ((hr = pComp->SetValue(tid, &var)) == S_OK)
  131. {
  132. dw = var.lVal;
  133. }
  134. }
  135. pComp->Release();
  136. }
  137. if (pdwOld)
  138. *pdwOld = dw;
  139. return hr;
  140. }
  141. //////////////////////////////////////////////////////////////////////////////
  142. //
  143. // CCompartmentMgr
  144. //
  145. //////////////////////////////////////////////////////////////////////////////
  146. //+---------------------------------------------------------------------------
  147. //
  148. // ctor
  149. //
  150. //----------------------------------------------------------------------------
  151. CCompartmentMgr::CCompartmentMgr(TfClientId tidOwner, COMPTYPE cType)
  152. {
  153. Dbg_MemSetThisNameIDCounter(TEXT("CCompartmentMgr"), PERF_COMPARTMGR_COUNTER);
  154. _tidOwner = tidOwner;
  155. _cType = cType;
  156. }
  157. //+---------------------------------------------------------------------------
  158. //
  159. // dtor
  160. //
  161. //----------------------------------------------------------------------------
  162. CCompartmentMgr::~CCompartmentMgr()
  163. {
  164. CleanUp();
  165. }
  166. //+---------------------------------------------------------------------------
  167. //
  168. // CleanUp
  169. //
  170. //----------------------------------------------------------------------------
  171. void CCompartmentMgr::CleanUp()
  172. {
  173. int nCnt = _rgCompartment.Count();
  174. int i;
  175. for (i = 0; i < nCnt; i++)
  176. {
  177. CCompartmentBase *pComp = _rgCompartment.Get(i);
  178. pComp->Invalid();
  179. pComp->Release();
  180. }
  181. _rgCompartment.Clear();
  182. }
  183. //+---------------------------------------------------------------------------
  184. //
  185. // GetCompartment
  186. //
  187. //----------------------------------------------------------------------------
  188. STDAPI CCompartmentMgr::GetCompartment(REFGUID rguid, ITfCompartment **ppcomp)
  189. {
  190. CCompartmentBase *pComp;
  191. if (!ppcomp)
  192. return E_INVALIDARG;
  193. *ppcomp = NULL;
  194. pComp = _Get(rguid);
  195. if (!pComp)
  196. return E_OUTOFMEMORY;
  197. *ppcomp = pComp;
  198. pComp->AddRef();
  199. return S_OK;
  200. }
  201. //+---------------------------------------------------------------------------
  202. //
  203. // ClearCompartment
  204. //
  205. //----------------------------------------------------------------------------
  206. STDAPI CCompartmentMgr::ClearCompartment(TfClientId tid, REFGUID rguid)
  207. {
  208. TfGuidAtom guidatom;
  209. CCompartmentBase *pComp;
  210. int iInsert;
  211. HRESULT hr;
  212. if (FAILED(hr = MyRegisterGUID(rguid, &guidatom)))
  213. return hr;
  214. pComp = _Find(guidatom, &iInsert);
  215. if (!pComp)
  216. return CONNECT_E_NOCONNECTION;
  217. if (pComp->_GetAccess() & CA_ONLYOWNERSET)
  218. {
  219. if (_tidOwner != tid)
  220. return E_UNEXPECTED;
  221. }
  222. _rgCompartment.Remove(iInsert, 1);
  223. pComp->Invalid();
  224. pComp->Release();
  225. return S_OK;
  226. }
  227. //+---------------------------------------------------------------------------
  228. //
  229. // EnumCompartment
  230. //
  231. //----------------------------------------------------------------------------
  232. STDAPI CCompartmentMgr::EnumCompartments(IEnumGUID **ppEnum)
  233. {
  234. CEnumCompartment *pEnum;
  235. if (!ppEnum)
  236. return E_INVALIDARG;
  237. pEnum = new CEnumCompartment();
  238. if (!pEnum)
  239. return E_OUTOFMEMORY;
  240. if (pEnum->_Init(&_rgCompartment))
  241. *ppEnum = pEnum;
  242. else
  243. SafeReleaseClear(pEnum);
  244. return pEnum ? S_OK : E_FAIL;
  245. }
  246. //+---------------------------------------------------------------------------
  247. //
  248. // _Find
  249. //
  250. //----------------------------------------------------------------------------
  251. CCompartmentBase *CCompartmentMgr::_Find(TfGuidAtom guidatom, int *piOut)
  252. {
  253. CCompartmentBase *pComp;
  254. CCompartmentBase *pCompMatch;
  255. int iMin;
  256. int iMax;
  257. int iMid;
  258. pCompMatch = NULL;
  259. iMid = -1;
  260. iMin = 0;
  261. iMax = _rgCompartment.Count();
  262. while (iMin < iMax)
  263. {
  264. iMid = (iMin + iMax) / 2;
  265. pComp = _rgCompartment.Get(iMid);
  266. Assert(pComp != NULL);
  267. if (guidatom < pComp->GetGuidAtom())
  268. {
  269. iMax = iMid;
  270. }
  271. else if (guidatom > pComp->GetGuidAtom())
  272. {
  273. iMin = iMid + 1;
  274. }
  275. else // guidatom == pComp->GetGuidAtom().
  276. {
  277. pCompMatch = pComp;
  278. break;
  279. }
  280. }
  281. if (!pCompMatch)
  282. {
  283. if (iMid >= 0)
  284. {
  285. CCompartmentBase *pCompTmp = _rgCompartment.Get(iMid);
  286. if (pCompTmp->GetGuidAtom() < guidatom)
  287. {
  288. iMid++;
  289. }
  290. }
  291. }
  292. if (piOut)
  293. *piOut = iMid;
  294. return pCompMatch;
  295. }
  296. //+---------------------------------------------------------------------------
  297. //
  298. // _Get
  299. //
  300. //----------------------------------------------------------------------------
  301. CCompartmentBase *CCompartmentMgr::_Get(REFGUID rguid)
  302. {
  303. CCompartmentBase *pComp;
  304. int iInsert;
  305. TfGuidAtom guidatom;
  306. if (FAILED(MyRegisterGUID(rguid, &guidatom)))
  307. return NULL;
  308. pComp = _Find(guidatom, &iInsert);
  309. if (!pComp)
  310. {
  311. TfPropertyType proptype = TF_PT_NONE;
  312. //
  313. // system predefined compartments does not allow any other type.
  314. //
  315. if ((IsEqualGUID(rguid, GUID_COMPARTMENT_KEYBOARD_DISABLED)) ||
  316. (IsEqualGUID(rguid, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE)) ||
  317. (IsEqualGUID(rguid, GUID_COMPARTMENT_SPEECH_OPENCLOSE)))
  318. {
  319. proptype = TF_PT_DWORD;
  320. }
  321. if (_cType == COMPTYPE_GLOBAL)
  322. pComp = new CGlobalCompartment(this, rguid, guidatom, proptype);
  323. else
  324. pComp = new CCompartment(this, guidatom, proptype);
  325. if (pComp)
  326. {
  327. if (iInsert < 0)
  328. iInsert = 0;
  329. if (_rgCompartment.Insert(iInsert, 1))
  330. {
  331. _rgCompartment.Set(iInsert, pComp);
  332. }
  333. else
  334. {
  335. delete pComp;
  336. pComp = NULL;
  337. }
  338. }
  339. }
  340. return pComp;
  341. }
  342. //+---------------------------------------------------------------------------
  343. //
  344. // NotifyGlobalCompartmentChange
  345. //
  346. //----------------------------------------------------------------------------
  347. void CCompartmentMgr::NotifyGlobalCompartmentChange(DWORD dwId)
  348. {
  349. Assert(_cType == COMPTYPE_GLOBAL);
  350. int nCnt = _rgCompartment.Count();
  351. for (int i = 0; i < nCnt; i++)
  352. {
  353. CCompartmentBase *pComp = _rgCompartment.Get(i);
  354. if (dwId == pComp->GetId())
  355. {
  356. pComp->MakeNotify();
  357. break;
  358. }
  359. }
  360. }
  361. //////////////////////////////////////////////////////////////////////////////
  362. //
  363. // CGlobalCompartmenMgr
  364. //
  365. //////////////////////////////////////////////////////////////////////////////
  366. STDAPI CGlobalCompartmentMgr::QueryInterface(REFIID riid, void **ppvObj)
  367. {
  368. *ppvObj = NULL;
  369. if (IsEqualIID(riid, IID_IUnknown) ||
  370. IsEqualIID(riid, IID_ITfCompartmentMgr))
  371. {
  372. *ppvObj = SAFECAST(this, ITfCompartmentMgr *);
  373. }
  374. if (*ppvObj)
  375. {
  376. return S_OK;
  377. }
  378. return E_NOINTERFACE;
  379. }
  380. ULONG CGlobalCompartmentMgr::AddRef(void)
  381. {
  382. _cRef++;
  383. return _cRef;
  384. }
  385. ULONG CGlobalCompartmentMgr::Release(void)
  386. {
  387. _cRef--;
  388. if (_cRef <= 0)
  389. {
  390. //
  391. // Calller may call Release() more than AddRef()..
  392. // We should not call TIM::Release() at this time.
  393. //
  394. Assert(0)
  395. return 0;
  396. }
  397. return _cRef;
  398. }
  399. //////////////////////////////////////////////////////////////////////////////
  400. //
  401. // CEnumCompartment
  402. //
  403. //////////////////////////////////////////////////////////////////////////////
  404. //+---------------------------------------------------------------------------
  405. //
  406. // ctor
  407. //
  408. //----------------------------------------------------------------------------
  409. CEnumCompartment::CEnumCompartment()
  410. {
  411. Dbg_MemSetThisNameIDCounter(TEXT("CEnumCompartment"), PERF_ENUMCOMPART_COUNTER);
  412. }
  413. //+---------------------------------------------------------------------------
  414. //
  415. // Init
  416. //
  417. //----------------------------------------------------------------------------
  418. BOOL CEnumCompartment::_Init(CPtrArray<CCompartmentBase> *prgComp)
  419. {
  420. int nCnt = prgComp->Count();
  421. int i;
  422. BOOL fRet = FALSE;
  423. CicEnterCriticalSection(g_cs);
  424. _pga = SGA_Init(nCnt, NULL);
  425. if (_pga == NULL)
  426. goto Exit;
  427. for (i = 0; i < nCnt; i++)
  428. {
  429. CCompartmentBase *pComp = prgComp->Get(i);
  430. if (FAILED((MyGetGUID(pComp->GetGuidAtom(), &_pga->rgGuid[i]))))
  431. goto Exit;
  432. }
  433. fRet = TRUE;
  434. Exit:
  435. CicLeaveCriticalSection(g_cs);
  436. return fRet;
  437. }
  438. //////////////////////////////////////////////////////////////////////////////
  439. //
  440. // CCompartmentBase
  441. //
  442. //////////////////////////////////////////////////////////////////////////////
  443. const COMPARTMENTACCESS CCompartmentBase::_c_ca[] = {
  444. {&GUID_COMPARTMENT_KEYBOARD_DISABLED, CA_ONLYOWNERSET},
  445. {NULL, 0}
  446. };
  447. CCompartmentBase::CCompartmentBase(CCompartmentMgr *pCompMgr, TfGuidAtom guidatom, TfPropertyType proptype)
  448. {
  449. Assert(!_fInvalid);
  450. _guidatom = guidatom;
  451. _proptype = proptype;
  452. _pCompMgr = pCompMgr;
  453. int n = 0;
  454. while (_c_ca[n].pguid)
  455. {
  456. if (MyIsEqualTfGuidAtom(guidatom, *_c_ca[n].pguid))
  457. {
  458. _dwAccess = _c_ca[n].dwAccess;
  459. }
  460. n++;
  461. }
  462. }
  463. //////////////////////////////////////////////////////////////////////////////
  464. //
  465. // CCompartment
  466. //
  467. //////////////////////////////////////////////////////////////////////////////
  468. //+---------------------------------------------------------------------------
  469. //
  470. // ctor
  471. //
  472. //----------------------------------------------------------------------------
  473. CCompartment::CCompartment(CCompartmentMgr *pCompMgr, TfGuidAtom guidatom, TfPropertyType proptype)
  474. :CCompartmentBase(pCompMgr, guidatom, proptype)
  475. {
  476. Dbg_MemSetThisNameIDCounter(TEXT("CCompartment"), PERF_COMPART_COUNTER);
  477. }
  478. //+---------------------------------------------------------------------------
  479. //
  480. // dtor
  481. //
  482. //----------------------------------------------------------------------------
  483. CCompartment::~CCompartment()
  484. {
  485. if (_prop.type == TF_PT_UNKNOWN)
  486. {
  487. //
  488. // #489905
  489. //
  490. // we can not call sink anymore after DLL_PROCESS_DETACH.
  491. //
  492. if (!DllShutdownInProgress())
  493. _prop.punk->Release();
  494. }
  495. else if (_prop.type == TF_PT_BSTR)
  496. SysFreeString(_prop.bstr);
  497. }
  498. //+---------------------------------------------------------------------------
  499. //
  500. // Advise
  501. //
  502. //----------------------------------------------------------------------------
  503. HRESULT CCompartment::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
  504. {
  505. const IID *rgiid;
  506. rgiid = &IID_ITfCompartmentEventSink;
  507. return GenericAdviseSink(riid,
  508. punk,
  509. &rgiid,
  510. &_rgCompartmentSink,
  511. 1,
  512. pdwCookie);
  513. }
  514. //+---------------------------------------------------------------------------
  515. //
  516. // Unadvise
  517. //
  518. //----------------------------------------------------------------------------
  519. HRESULT CCompartment::UnadviseSink(DWORD dwCookie)
  520. {
  521. return GenericUnadviseSink(&_rgCompartmentSink, 1, dwCookie);
  522. }
  523. //+---------------------------------------------------------------------------
  524. //
  525. // GetValue
  526. //
  527. //----------------------------------------------------------------------------
  528. HRESULT CCompartment::GetValue(VARIANT *pvarValue)
  529. {
  530. HRESULT hr;
  531. if (_fInvalid)
  532. {
  533. Assert(0);
  534. return E_UNEXPECTED;
  535. }
  536. if (pvarValue == NULL)
  537. return E_INVALIDARG;
  538. QuickVariantInit(pvarValue);
  539. hr = TfPropToVariant(pvarValue, &_prop, ADDREF);
  540. if (hr != S_OK)
  541. return hr;
  542. return (pvarValue->vt == VT_EMPTY) ? S_FALSE : S_OK;
  543. }
  544. //+---------------------------------------------------------------------------
  545. //
  546. // SetValue
  547. //
  548. //----------------------------------------------------------------------------
  549. HRESULT CCompartment::SetValue(TfClientId tid, const VARIANT *pvarValue)
  550. {
  551. HRESULT hr;
  552. if (_fInvalid)
  553. {
  554. Assert(0);
  555. return E_UNEXPECTED;
  556. }
  557. if (_fInSet)
  558. return E_UNEXPECTED;
  559. if (pvarValue == NULL)
  560. return E_INVALIDARG;
  561. if (!IsValidCiceroVarType(pvarValue->vt))
  562. return E_INVALIDARG;
  563. if (pvarValue->vt == VT_EMPTY)
  564. return E_INVALIDARG;
  565. if (_GetAccess() & CA_ONLYOWNERSET)
  566. {
  567. if (_GetMgr()->_GetTIPOwner() != tid)
  568. return E_UNEXPECTED;
  569. }
  570. hr = VariantToTfProp(&_prop, pvarValue, ADDREF, FALSE);
  571. if (hr != S_OK)
  572. return hr;
  573. int i;
  574. int nCnt = _rgCompartmentSink.Count();
  575. if (nCnt)
  576. {
  577. GUID guid;
  578. if (FAILED(MyGetGUID(_guidatom, &guid)))
  579. {
  580. return E_FAIL;
  581. Assert(0);
  582. }
  583. _fInSet = TRUE;
  584. for (i = 0; i < nCnt; i++)
  585. {
  586. ((ITfCompartmentEventSink *)_rgCompartmentSink.GetPtr(i)->pSink)->OnChange(guid);
  587. }
  588. _fInSet = FALSE;
  589. }
  590. return S_OK;
  591. }
  592. //////////////////////////////////////////////////////////////////////////////
  593. //
  594. // CGlobalCompartment
  595. //
  596. //////////////////////////////////////////////////////////////////////////////
  597. //+---------------------------------------------------------------------------
  598. //
  599. // ctor
  600. //
  601. //----------------------------------------------------------------------------
  602. CGlobalCompartment::CGlobalCompartment(CCompartmentMgr *pCompMgr, REFGUID rguid, TfGuidAtom guidatom, TfPropertyType proptype)
  603. :CCompartmentBase(pCompMgr, guidatom, proptype)
  604. {
  605. Dbg_MemSetThisNameIDCounter(TEXT("CGlobalCompartment"), PERF_GLOBCOMPART_COUNTER);
  606. _dwId = (DWORD)(-1);
  607. _guidCompart = rguid;
  608. }
  609. //+---------------------------------------------------------------------------
  610. //
  611. // dtor
  612. //
  613. //----------------------------------------------------------------------------
  614. CGlobalCompartment::~CGlobalCompartment()
  615. {
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // Advise
  620. //
  621. //----------------------------------------------------------------------------
  622. HRESULT CGlobalCompartment::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
  623. {
  624. const IID *rgiid;
  625. if (_dwId == (DWORD)(-1))
  626. {
  627. _dwId = g_gcomplist.GetId(_guidCompart);
  628. if (_dwId == (DWORD)(-1))
  629. {
  630. TFPROPERTY prop;
  631. memset(&prop, 0, sizeof(prop));
  632. _dwId = g_gcomplist.SetProperty(_guidCompart, &prop);
  633. if (_dwId == (DWORD)(-1))
  634. return E_FAIL;
  635. }
  636. }
  637. rgiid = &IID_ITfCompartmentEventSink;
  638. return GenericAdviseSink(riid,
  639. punk,
  640. &rgiid,
  641. &_rgCompartmentSink,
  642. 1,
  643. pdwCookie);
  644. }
  645. //+---------------------------------------------------------------------------
  646. //
  647. // Unadvise
  648. //
  649. //----------------------------------------------------------------------------
  650. HRESULT CGlobalCompartment::UnadviseSink(DWORD dwCookie)
  651. {
  652. return GenericUnadviseSink(&_rgCompartmentSink, 1, dwCookie);
  653. }
  654. //+---------------------------------------------------------------------------
  655. //
  656. // GetValue
  657. //
  658. //----------------------------------------------------------------------------
  659. HRESULT CGlobalCompartment::GetValue(VARIANT *pvarValue)
  660. {
  661. HRESULT hr;
  662. TFPROPERTY prop;
  663. if (_fInvalid)
  664. {
  665. Assert(0);
  666. return E_UNEXPECTED;
  667. }
  668. if (pvarValue == NULL)
  669. return E_INVALIDARG;
  670. QuickVariantInit(pvarValue);
  671. if (_dwId == (DWORD)(-1))
  672. {
  673. _dwId = g_gcomplist.GetId(_guidCompart);
  674. }
  675. memset(&prop, 0, sizeof(TFPROPERTY));
  676. if (_dwId != (DWORD)(-1))
  677. g_gcomplist.GetProperty(_guidCompart, &prop);
  678. Assert(prop.type != TF_PT_UNKNOWN);
  679. hr = TfPropToVariant(pvarValue, &prop, ADDREF);
  680. if (hr != S_OK)
  681. return hr;
  682. return (pvarValue->vt == VT_EMPTY) ? S_FALSE : S_OK;
  683. }
  684. //+---------------------------------------------------------------------------
  685. //
  686. // SetValue
  687. //
  688. //----------------------------------------------------------------------------
  689. HRESULT CGlobalCompartment::SetValue(TfClientId tid, const VARIANT *pvarValue)
  690. {
  691. HRESULT hr;
  692. TFPROPERTY prop;
  693. if (_fInvalid)
  694. {
  695. Assert(0);
  696. return E_UNEXPECTED;
  697. }
  698. if (_fInSet)
  699. return E_UNEXPECTED;
  700. if (pvarValue == NULL)
  701. return E_INVALIDARG;
  702. if (!IsValidCiceroVarType(pvarValue->vt))
  703. return E_INVALIDARG;
  704. if (_GetAccess() & CA_ONLYOWNERSET)
  705. {
  706. if (_GetMgr()->_GetTIPOwner() != tid)
  707. return E_UNEXPECTED;
  708. }
  709. if (pvarValue->vt == VT_UNKNOWN)
  710. {
  711. Assert(0);
  712. return E_INVALIDARG;
  713. }
  714. hr = VariantToTfProp(&prop, pvarValue, NO_ADDREF, FALSE);
  715. if (hr != S_OK)
  716. return hr;
  717. _dwId = g_gcomplist.SetProperty(_guidCompart, &prop);
  718. if (_dwId == (DWORD)(-1))
  719. return E_FAIL;
  720. hr = (prop.type != TF_PT_NONE) ? S_OK : E_FAIL;
  721. if (SUCCEEDED(hr))
  722. {
  723. //
  724. // make a notify to the sinks of the current thread.
  725. //
  726. if (!MakeNotify())
  727. return E_FAIL;
  728. PostTimListMessage(TLF_GCOMPACTIVE,
  729. 0,
  730. g_msgPrivate,
  731. TFPRIV_GLOBALCOMPARTMENTSYNC,
  732. _dwId);
  733. }
  734. return hr;
  735. }
  736. //+---------------------------------------------------------------------------
  737. //
  738. // EnumThreadProc
  739. //
  740. //----------------------------------------------------------------------------
  741. BOOL CGlobalCompartment::EnumThreadProc(DWORD dwThreadId, DWORD dwProcessId, void *pv)
  742. {
  743. if (dwThreadId != GetCurrentThreadId())
  744. {
  745. CGlobalCompartment *_this = (CGlobalCompartment *)pv;
  746. PostThreadMessage(dwThreadId,
  747. g_msgPrivate,
  748. TFPRIV_GLOBALCOMPARTMENTSYNC,
  749. _this->_dwId);
  750. }
  751. return FALSE;
  752. }
  753. //+---------------------------------------------------------------------------
  754. //
  755. // MakeNotify
  756. //
  757. //----------------------------------------------------------------------------
  758. BOOL CGlobalCompartment::MakeNotify()
  759. {
  760. int i;
  761. int nCnt = _rgCompartmentSink.Count();
  762. if (nCnt)
  763. {
  764. GUID guid;
  765. if (FAILED(MyGetGUID(_guidatom, &guid)))
  766. {
  767. Assert(0);
  768. return FALSE;
  769. }
  770. _fInSet = TRUE;
  771. for (i = 0; i < nCnt; i++)
  772. {
  773. ((ITfCompartmentEventSink *)_rgCompartmentSink.GetPtr(i)->pSink)->OnChange(guid);
  774. }
  775. _fInSet = FALSE;
  776. }
  777. return TRUE;
  778. }