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
968 lines
23 KiB
//
|
|
// compart.cpp
|
|
//
|
|
|
|
|
|
#include "private.h"
|
|
#include "globals.h"
|
|
#include "regsvr.h"
|
|
#include "compart.h"
|
|
#include "helpers.h"
|
|
#include "thdutil.h"
|
|
#include "tim.h"
|
|
#include "cicmutex.h"
|
|
#include "timlist.h"
|
|
#include "cregkey.h"
|
|
|
|
/* e575186e-71a8-4ef4-90da-14ed705e7df2 */
|
|
extern const IID IID_PRIV_CCOMPARTMENTMGR = {
|
|
0xe575186e,
|
|
0x71a8,
|
|
0x4ef4,
|
|
{0x90, 0xda, 0x14, 0xed, 0x70, 0x5e, 0x7d, 0xf2}
|
|
};
|
|
|
|
/* 8b05c1ad-adf0-4a78-a3e2-d38cae3e28be */
|
|
extern const IID IID_PRIV_CGLOBALCOMPARTMENT = {
|
|
0x8b05c1ad,
|
|
0xadf0,
|
|
0x4a78,
|
|
{0xa3, 0xe2, 0xd3, 0x8c, 0xae, 0x3e, 0x28, 0xbe}
|
|
};
|
|
|
|
|
|
DBG_ID_INSTANCE(CCompartment);
|
|
DBG_ID_INSTANCE(CCompartmentMgr);
|
|
DBG_ID_INSTANCE(CEnumCompartment);
|
|
DBG_ID_INSTANCE(CGlobalCompartment);
|
|
|
|
extern CCicMutex g_mutexCompart;
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnsureGlobalCompartment
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL EnsureGlobalCompartment(SYSTHREAD *psfn)
|
|
{
|
|
if (psfn->_pGlobalCompMgr)
|
|
return TRUE;
|
|
|
|
psfn->_pGlobalCompMgr = new CGlobalCompartmentMgr(g_gaApp);
|
|
|
|
if (psfn->_pGlobalCompMgr)
|
|
{
|
|
if (g_gcomplist.Init(psfn))
|
|
return TRUE;
|
|
|
|
delete psfn->_pGlobalCompMgr;
|
|
psfn->_pGlobalCompMgr = NULL;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCompartmentDWORD
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT MyGetCompartmentDWORD(CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD *pdw)
|
|
{
|
|
HRESULT hr;
|
|
ITfCompartment *pComp;
|
|
VARIANT var;
|
|
|
|
if (!pCompMgr)
|
|
return E_FAIL;
|
|
|
|
*pdw = 0;
|
|
if (SUCCEEDED(hr = pCompMgr->GetCompartment(rguid, &pComp)))
|
|
{
|
|
hr = pComp->GetValue(&var);
|
|
if (hr == S_OK)
|
|
{
|
|
Assert(var.vt == VT_I4);
|
|
*pdw = var.lVal;
|
|
// no need to VariantClear because VT_I4
|
|
}
|
|
|
|
pComp->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetCompartmentDWORD
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT MySetCompartmentDWORD(TfClientId tid, CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD dw)
|
|
{
|
|
HRESULT hr;
|
|
ITfCompartment *pComp;
|
|
VARIANT var;
|
|
|
|
if (!pCompMgr)
|
|
return E_FAIL;
|
|
|
|
if (SUCCEEDED(hr = pCompMgr->GetCompartment(rguid, &pComp)))
|
|
{
|
|
var.vt = VT_I4;
|
|
var.lVal = dw;
|
|
hr = pComp->SetValue(tid, &var);
|
|
pComp->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ToggleCompartmentDWORD
|
|
//
|
|
// Toggle DWORD value between 0 and 1.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT MyToggleCompartmentDWORD(TfClientId tid, CCompartmentMgr *pCompMgr, REFGUID rguid, DWORD *pdwOld)
|
|
{
|
|
ITfCompartment *pComp;
|
|
VARIANT var;
|
|
DWORD dw = 0;
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (!pCompMgr)
|
|
return E_FAIL;
|
|
|
|
if (pCompMgr->GetCompartment(rguid, &pComp) == S_OK)
|
|
{
|
|
if (SUCCEEDED(pComp->GetValue(&var)))
|
|
{
|
|
if (var.vt == VT_EMPTY)
|
|
{
|
|
// compartment is uninitialized
|
|
var.vt = VT_I4;
|
|
var.lVal = 0;
|
|
}
|
|
else
|
|
{
|
|
Assert(var.vt == VT_I4);
|
|
}
|
|
|
|
var.lVal = (var.lVal == 0) ? 1 : 0;
|
|
// no need to VariantClear because VT_I4
|
|
|
|
if ((hr = pComp->SetValue(tid, &var)) == S_OK)
|
|
{
|
|
dw = var.lVal;
|
|
}
|
|
}
|
|
|
|
pComp->Release();
|
|
}
|
|
|
|
if (pdwOld)
|
|
*pdwOld = dw;
|
|
|
|
return hr;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCompartmentMgr
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartmentMgr::CCompartmentMgr(TfClientId tidOwner, COMPTYPE cType)
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CCompartmentMgr"), PERF_COMPARTMGR_COUNTER);
|
|
|
|
_tidOwner = tidOwner;
|
|
_cType = cType;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartmentMgr::~CCompartmentMgr()
|
|
{
|
|
CleanUp();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// CleanUp
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCompartmentMgr::CleanUp()
|
|
{
|
|
int nCnt = _rgCompartment.Count();
|
|
int i;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CCompartmentBase *pComp = _rgCompartment.Get(i);
|
|
pComp->Invalid();
|
|
pComp->Release();
|
|
}
|
|
_rgCompartment.Clear();
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetCompartment
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCompartmentMgr::GetCompartment(REFGUID rguid, ITfCompartment **ppcomp)
|
|
{
|
|
CCompartmentBase *pComp;
|
|
|
|
if (!ppcomp)
|
|
return E_INVALIDARG;
|
|
|
|
*ppcomp = NULL;
|
|
|
|
pComp = _Get(rguid);
|
|
if (!pComp)
|
|
return E_OUTOFMEMORY;
|
|
|
|
*ppcomp = pComp;
|
|
pComp->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ClearCompartment
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCompartmentMgr::ClearCompartment(TfClientId tid, REFGUID rguid)
|
|
{
|
|
TfGuidAtom guidatom;
|
|
CCompartmentBase *pComp;
|
|
int iInsert;
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = MyRegisterGUID(rguid, &guidatom)))
|
|
return hr;
|
|
|
|
pComp = _Find(guidatom, &iInsert);
|
|
|
|
if (!pComp)
|
|
return CONNECT_E_NOCONNECTION;
|
|
|
|
if (pComp->_GetAccess() & CA_ONLYOWNERSET)
|
|
{
|
|
if (_tidOwner != tid)
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
_rgCompartment.Remove(iInsert, 1);
|
|
pComp->Invalid();
|
|
pComp->Release();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnumCompartment
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
STDAPI CCompartmentMgr::EnumCompartments(IEnumGUID **ppEnum)
|
|
{
|
|
CEnumCompartment *pEnum;
|
|
|
|
if (!ppEnum)
|
|
return E_INVALIDARG;
|
|
|
|
pEnum = new CEnumCompartment();
|
|
|
|
if (!pEnum)
|
|
return E_OUTOFMEMORY;
|
|
|
|
if (pEnum->_Init(&_rgCompartment))
|
|
*ppEnum = pEnum;
|
|
else
|
|
SafeReleaseClear(pEnum);
|
|
|
|
return pEnum ? S_OK : E_FAIL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Find
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartmentBase *CCompartmentMgr::_Find(TfGuidAtom guidatom, int *piOut)
|
|
{
|
|
CCompartmentBase *pComp;
|
|
CCompartmentBase *pCompMatch;
|
|
int iMin;
|
|
int iMax;
|
|
int iMid;
|
|
|
|
pCompMatch = NULL;
|
|
iMid = -1;
|
|
iMin = 0;
|
|
iMax = _rgCompartment.Count();
|
|
|
|
while (iMin < iMax)
|
|
{
|
|
iMid = (iMin + iMax) / 2;
|
|
pComp = _rgCompartment.Get(iMid);
|
|
Assert(pComp != NULL);
|
|
|
|
if (guidatom < pComp->GetGuidAtom())
|
|
{
|
|
iMax = iMid;
|
|
}
|
|
else if (guidatom > pComp->GetGuidAtom())
|
|
{
|
|
iMin = iMid + 1;
|
|
}
|
|
else // guidatom == pComp->GetGuidAtom().
|
|
{
|
|
pCompMatch = pComp;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!pCompMatch)
|
|
{
|
|
if (iMid >= 0)
|
|
{
|
|
CCompartmentBase *pCompTmp = _rgCompartment.Get(iMid);
|
|
if (pCompTmp->GetGuidAtom() < guidatom)
|
|
{
|
|
iMid++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (piOut)
|
|
*piOut = iMid;
|
|
|
|
return pCompMatch;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// _Get
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartmentBase *CCompartmentMgr::_Get(REFGUID rguid)
|
|
{
|
|
CCompartmentBase *pComp;
|
|
int iInsert;
|
|
TfGuidAtom guidatom;
|
|
|
|
if (FAILED(MyRegisterGUID(rguid, &guidatom)))
|
|
return NULL;
|
|
|
|
pComp = _Find(guidatom, &iInsert);
|
|
|
|
if (!pComp)
|
|
{
|
|
TfPropertyType proptype = TF_PT_NONE;
|
|
|
|
//
|
|
// system predefined compartments does not allow any other type.
|
|
//
|
|
if ((IsEqualGUID(rguid, GUID_COMPARTMENT_KEYBOARD_DISABLED)) ||
|
|
(IsEqualGUID(rguid, GUID_COMPARTMENT_HANDWRITING_OPENCLOSE)) ||
|
|
(IsEqualGUID(rguid, GUID_COMPARTMENT_SPEECH_OPENCLOSE)))
|
|
{
|
|
proptype = TF_PT_DWORD;
|
|
}
|
|
|
|
if (_cType == COMPTYPE_GLOBAL)
|
|
pComp = new CGlobalCompartment(this, rguid, guidatom, proptype);
|
|
else
|
|
pComp = new CCompartment(this, guidatom, proptype);
|
|
|
|
if (pComp)
|
|
{
|
|
if (iInsert < 0)
|
|
iInsert = 0;
|
|
|
|
if (_rgCompartment.Insert(iInsert, 1))
|
|
{
|
|
_rgCompartment.Set(iInsert, pComp);
|
|
}
|
|
else
|
|
{
|
|
delete pComp;
|
|
pComp = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return pComp;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// NotifyGlobalCompartmentChange
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
void CCompartmentMgr::NotifyGlobalCompartmentChange(DWORD dwId)
|
|
{
|
|
Assert(_cType == COMPTYPE_GLOBAL);
|
|
|
|
int nCnt = _rgCompartment.Count();
|
|
|
|
for (int i = 0; i < nCnt; i++)
|
|
{
|
|
CCompartmentBase *pComp = _rgCompartment.Get(i);
|
|
if (dwId == pComp->GetId())
|
|
{
|
|
pComp->MakeNotify();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CGlobalCompartmenMgr
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI CGlobalCompartmentMgr::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
*ppvObj = NULL;
|
|
|
|
if (IsEqualIID(riid, IID_IUnknown) ||
|
|
IsEqualIID(riid, IID_ITfCompartmentMgr))
|
|
{
|
|
*ppvObj = SAFECAST(this, ITfCompartmentMgr *);
|
|
}
|
|
|
|
if (*ppvObj)
|
|
{
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
|
|
}
|
|
|
|
ULONG CGlobalCompartmentMgr::AddRef(void)
|
|
{
|
|
_cRef++;
|
|
return _cRef;
|
|
}
|
|
|
|
ULONG CGlobalCompartmentMgr::Release(void)
|
|
{
|
|
_cRef--;
|
|
if (_cRef <= 0)
|
|
{
|
|
//
|
|
// Calller may call Release() more than AddRef()..
|
|
// We should not call TIM::Release() at this time.
|
|
//
|
|
Assert(0)
|
|
|
|
return 0;
|
|
}
|
|
|
|
return _cRef;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CEnumCompartment
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CEnumCompartment::CEnumCompartment()
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CEnumCompartment"), PERF_ENUMCOMPART_COUNTER);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Init
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CEnumCompartment::_Init(CPtrArray<CCompartmentBase> *prgComp)
|
|
{
|
|
int nCnt = prgComp->Count();
|
|
int i;
|
|
BOOL fRet = FALSE;
|
|
|
|
CicEnterCriticalSection(g_cs);
|
|
|
|
_pga = SGA_Init(nCnt, NULL);
|
|
|
|
if (_pga == NULL)
|
|
goto Exit;
|
|
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
CCompartmentBase *pComp = prgComp->Get(i);
|
|
|
|
if (FAILED((MyGetGUID(pComp->GetGuidAtom(), &_pga->rgGuid[i]))))
|
|
goto Exit;
|
|
}
|
|
|
|
fRet = TRUE;
|
|
|
|
Exit:
|
|
CicLeaveCriticalSection(g_cs);
|
|
return fRet;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCompartmentBase
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
const COMPARTMENTACCESS CCompartmentBase::_c_ca[] = {
|
|
{&GUID_COMPARTMENT_KEYBOARD_DISABLED, CA_ONLYOWNERSET},
|
|
{NULL, 0}
|
|
};
|
|
CCompartmentBase::CCompartmentBase(CCompartmentMgr *pCompMgr, TfGuidAtom guidatom, TfPropertyType proptype)
|
|
{
|
|
Assert(!_fInvalid);
|
|
|
|
_guidatom = guidatom;
|
|
_proptype = proptype;
|
|
_pCompMgr = pCompMgr;
|
|
|
|
int n = 0;
|
|
while (_c_ca[n].pguid)
|
|
{
|
|
if (MyIsEqualTfGuidAtom(guidatom, *_c_ca[n].pguid))
|
|
{
|
|
_dwAccess = _c_ca[n].dwAccess;
|
|
}
|
|
n++;
|
|
}
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CCompartment
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartment::CCompartment(CCompartmentMgr *pCompMgr, TfGuidAtom guidatom, TfPropertyType proptype)
|
|
:CCompartmentBase(pCompMgr, guidatom, proptype)
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CCompartment"), PERF_COMPART_COUNTER);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CCompartment::~CCompartment()
|
|
{
|
|
if (_prop.type == TF_PT_UNKNOWN)
|
|
{
|
|
//
|
|
// #489905
|
|
//
|
|
// we can not call sink anymore after DLL_PROCESS_DETACH.
|
|
//
|
|
if (!DllShutdownInProgress())
|
|
_prop.punk->Release();
|
|
}
|
|
else if (_prop.type == TF_PT_BSTR)
|
|
SysFreeString(_prop.bstr);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Advise
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCompartment::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
|
|
{
|
|
const IID *rgiid;
|
|
|
|
rgiid = &IID_ITfCompartmentEventSink;
|
|
|
|
return GenericAdviseSink(riid,
|
|
punk,
|
|
&rgiid,
|
|
&_rgCompartmentSink,
|
|
1,
|
|
pdwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Unadvise
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCompartment::UnadviseSink(DWORD dwCookie)
|
|
{
|
|
return GenericUnadviseSink(&_rgCompartmentSink, 1, dwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetValue
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCompartment::GetValue(VARIANT *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (_fInvalid)
|
|
{
|
|
Assert(0);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (pvarValue == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
QuickVariantInit(pvarValue);
|
|
|
|
hr = TfPropToVariant(pvarValue, &_prop, ADDREF);
|
|
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
return (pvarValue->vt == VT_EMPTY) ? S_FALSE : S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetValue
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CCompartment::SetValue(TfClientId tid, const VARIANT *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (_fInvalid)
|
|
{
|
|
Assert(0);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (_fInSet)
|
|
return E_UNEXPECTED;
|
|
|
|
if (pvarValue == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (!IsValidCiceroVarType(pvarValue->vt))
|
|
return E_INVALIDARG;
|
|
|
|
if (pvarValue->vt == VT_EMPTY)
|
|
return E_INVALIDARG;
|
|
|
|
if (_GetAccess() & CA_ONLYOWNERSET)
|
|
{
|
|
if (_GetMgr()->_GetTIPOwner() != tid)
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
hr = VariantToTfProp(&_prop, pvarValue, ADDREF, FALSE);
|
|
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
int i;
|
|
int nCnt = _rgCompartmentSink.Count();
|
|
if (nCnt)
|
|
{
|
|
GUID guid;
|
|
if (FAILED(MyGetGUID(_guidatom, &guid)))
|
|
{
|
|
return E_FAIL;
|
|
Assert(0);
|
|
}
|
|
|
|
_fInSet = TRUE;
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
((ITfCompartmentEventSink *)_rgCompartmentSink.GetPtr(i)->pSink)->OnChange(guid);
|
|
}
|
|
_fInSet = FALSE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CGlobalCompartment
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// ctor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGlobalCompartment::CGlobalCompartment(CCompartmentMgr *pCompMgr, REFGUID rguid, TfGuidAtom guidatom, TfPropertyType proptype)
|
|
:CCompartmentBase(pCompMgr, guidatom, proptype)
|
|
{
|
|
Dbg_MemSetThisNameIDCounter(TEXT("CGlobalCompartment"), PERF_GLOBCOMPART_COUNTER);
|
|
_dwId = (DWORD)(-1);
|
|
_guidCompart = rguid;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// dtor
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
CGlobalCompartment::~CGlobalCompartment()
|
|
{
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Advise
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CGlobalCompartment::AdviseSink(REFIID riid, IUnknown *punk, DWORD *pdwCookie)
|
|
{
|
|
const IID *rgiid;
|
|
|
|
if (_dwId == (DWORD)(-1))
|
|
{
|
|
_dwId = g_gcomplist.GetId(_guidCompart);
|
|
if (_dwId == (DWORD)(-1))
|
|
{
|
|
TFPROPERTY prop;
|
|
memset(&prop, 0, sizeof(prop));
|
|
_dwId = g_gcomplist.SetProperty(_guidCompart, &prop);
|
|
if (_dwId == (DWORD)(-1))
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
|
|
rgiid = &IID_ITfCompartmentEventSink;
|
|
|
|
return GenericAdviseSink(riid,
|
|
punk,
|
|
&rgiid,
|
|
&_rgCompartmentSink,
|
|
1,
|
|
pdwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Unadvise
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CGlobalCompartment::UnadviseSink(DWORD dwCookie)
|
|
{
|
|
return GenericUnadviseSink(&_rgCompartmentSink, 1, dwCookie);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// GetValue
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CGlobalCompartment::GetValue(VARIANT *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
TFPROPERTY prop;
|
|
|
|
if (_fInvalid)
|
|
{
|
|
Assert(0);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (pvarValue == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
QuickVariantInit(pvarValue);
|
|
|
|
if (_dwId == (DWORD)(-1))
|
|
{
|
|
_dwId = g_gcomplist.GetId(_guidCompart);
|
|
}
|
|
|
|
memset(&prop, 0, sizeof(TFPROPERTY));
|
|
if (_dwId != (DWORD)(-1))
|
|
g_gcomplist.GetProperty(_guidCompart, &prop);
|
|
|
|
|
|
Assert(prop.type != TF_PT_UNKNOWN);
|
|
|
|
hr = TfPropToVariant(pvarValue, &prop, ADDREF);
|
|
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
return (pvarValue->vt == VT_EMPTY) ? S_FALSE : S_OK;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// SetValue
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
HRESULT CGlobalCompartment::SetValue(TfClientId tid, const VARIANT *pvarValue)
|
|
{
|
|
HRESULT hr;
|
|
TFPROPERTY prop;
|
|
|
|
if (_fInvalid)
|
|
{
|
|
Assert(0);
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (_fInSet)
|
|
return E_UNEXPECTED;
|
|
|
|
if (pvarValue == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (!IsValidCiceroVarType(pvarValue->vt))
|
|
return E_INVALIDARG;
|
|
|
|
if (_GetAccess() & CA_ONLYOWNERSET)
|
|
{
|
|
if (_GetMgr()->_GetTIPOwner() != tid)
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
if (pvarValue->vt == VT_UNKNOWN)
|
|
{
|
|
Assert(0);
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
hr = VariantToTfProp(&prop, pvarValue, NO_ADDREF, FALSE);
|
|
|
|
if (hr != S_OK)
|
|
return hr;
|
|
|
|
_dwId = g_gcomplist.SetProperty(_guidCompart, &prop);
|
|
if (_dwId == (DWORD)(-1))
|
|
return E_FAIL;
|
|
|
|
hr = (prop.type != TF_PT_NONE) ? S_OK : E_FAIL;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// make a notify to the sinks of the current thread.
|
|
//
|
|
if (!MakeNotify())
|
|
return E_FAIL;
|
|
PostTimListMessage(TLF_GCOMPACTIVE,
|
|
0,
|
|
g_msgPrivate,
|
|
TFPRIV_GLOBALCOMPARTMENTSYNC,
|
|
_dwId);
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// EnumThreadProc
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CGlobalCompartment::EnumThreadProc(DWORD dwThreadId, DWORD dwProcessId, void *pv)
|
|
{
|
|
if (dwThreadId != GetCurrentThreadId())
|
|
{
|
|
CGlobalCompartment *_this = (CGlobalCompartment *)pv;
|
|
|
|
PostThreadMessage(dwThreadId,
|
|
g_msgPrivate,
|
|
TFPRIV_GLOBALCOMPARTMENTSYNC,
|
|
_this->_dwId);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// MakeNotify
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
BOOL CGlobalCompartment::MakeNotify()
|
|
{
|
|
int i;
|
|
int nCnt = _rgCompartmentSink.Count();
|
|
if (nCnt)
|
|
{
|
|
GUID guid;
|
|
if (FAILED(MyGetGUID(_guidatom, &guid)))
|
|
{
|
|
Assert(0);
|
|
return FALSE;
|
|
}
|
|
|
|
_fInSet = TRUE;
|
|
for (i = 0; i < nCnt; i++)
|
|
{
|
|
((ITfCompartmentEventSink *)_rgCompartmentSink.GetPtr(i)->pSink)->OnChange(guid);
|
|
}
|
|
_fInSet = FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|