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.
 
 
 
 
 
 

730 lines
19 KiB

#include "private.h"
#include "proputil.h"
#include "immxutil.h"
#include "helpers.h"
//+---------------------------------------------------------------------------
//
// HrVariantToBlob
//
// cbvalue: on sizeof VARTYPE
//
//----------------------------------------------------------------------------
HRESULT HrVariantToBlob(VARIANT *pv, void *pvalue, ULONG *pcbvalue, VARTYPE vt)
{
HRESULT hr = S_OK;
SAFEARRAY *psa = NULL;
void *pdata = NULL;
int lb, ub;
int iElemSize;
ULONG cbvalue;
while (V_VT(pv) == (VT_BYREF | VT_VARIANT))
pv = V_VARIANTREF(pv);
if (V_VT(pv) != (VT_ARRAY | vt))
return E_FAIL;
psa = V_ARRAY(pv);
hr = SafeArrayLock(psa);
if (FAILED(hr))
goto Ret;
hr = SafeArrayGetLBound(psa, 1, (LONG *)&lb);
if (FAILED(hr))
goto Ret;
hr = SafeArrayGetUBound(psa, 1, (LONG *)&ub);
if (FAILED(hr))
goto Ret;
iElemSize = SafeArrayGetElemsize(psa);
cbvalue = ub - lb + 1;
if (cbvalue * iElemSize > *pcbvalue)
{
hr = E_FAIL;
goto Ret;
}
hr = SafeArrayAccessData(psa, (void **)&pdata);
if (FAILED(hr))
goto Ret;
memcpy(pvalue, pdata, cbvalue * iElemSize);
hr = SafeArrayUnaccessData(psa);
if (FAILED(hr))
goto Ret;
*pcbvalue = cbvalue;
Ret:
if (psa) SafeArrayUnlock(psa);
return hr;
}
//+---------------------------------------------------------------------------
//
// HrBlobToVariant
//
// cbvalue: on sizeof VARTYPE
//
//----------------------------------------------------------------------------
HRESULT HrBlobToVariant(const void *value, ULONG cbvalue, VARIANT *pv, VARTYPE vt)
{
HRESULT hr = S_OK;
SAFEARRAY *psa = NULL;
SAFEARRAYBOUND rsabound[1];
void *pdata = NULL;
int iElemSize;
rsabound[0].lLbound = 0;
rsabound[0].cElements = cbvalue;
if (!(psa = SafeArrayCreate(vt, 1, rsabound)))
{
hr = E_OUTOFMEMORY;
goto Ret;
}
iElemSize = SafeArrayGetElemsize(psa);
hr = SafeArrayAccessData(psa, (void **)&pdata);
if (FAILED(hr))
goto Ret;
memcpy(pdata, value, cbvalue * iElemSize);
hr = SafeArrayUnaccessData(psa);
if (FAILED(hr))
goto Ret;
V_VT(pv) = VT_ARRAY | vt;
V_ARRAY(pv) = psa;
psa = NULL;
Ret:
if (psa) SafeArrayDestroy(psa);
return hr;
}
//+---------------------------------------------------------------------------
//
// GetGUIDPropertyData
//
//----------------------------------------------------------------------------
HRESULT GetGUIDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, TfGuidAtom *pguid)
{
VARIANT var;
HRESULT hr = E_FAIL;
*pguid = TF_INVALID_GUIDATOM;
if (SUCCEEDED(pProp->GetValue(ec, pRange, &var)))
{
if (var.vt == VT_I4)
*pguid = (TfGuidAtom)var.lVal;
// no need to VariantClear because VT_I4
hr = S_OK;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// SetGUIDPropertyData
//
//----------------------------------------------------------------------------
HRESULT SetGUIDPropertyData(LIBTHREAD *plt, TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, REFGUID rguid)
{
VARIANT var;
GUID guid = rguid;
var.vt = VT_I4;
GetGUIDATOMFromGUID(plt, guid, (TfGuidAtom *)&var.lVal);
return pProp->SetValue(ec, pRange, &var);
}
//+---------------------------------------------------------------------------
//
// VarToLangId
//
//----------------------------------------------------------------------------
WORD VarToWORD(VARIANT *pv)
{
if (V_VT(pv) == VT_I2)
return (WORD)V_I2(pv);
return 0;
}
//+---------------------------------------------------------------------------
//
// SetLangToVar
//
//----------------------------------------------------------------------------
void SetWORDToVar(VARIANT *pv, WORD w)
{
V_VT(pv) = VT_I2;
V_I2(pv) = w;
}
//+---------------------------------------------------------------------------
//
// GetDWORDPropertyData
//
//----------------------------------------------------------------------------
HRESULT GetDWORDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, DWORD *pdw)
{
VARIANT var;
HRESULT hr = E_FAIL;
if (pProp->GetValue(ec, pRange, &var) == S_OK)
{
Assert(var.vt == VT_I4); // expecting DWORD
*pdw = var.lVal;
// no need to VariantClear because VT_I4
hr = S_OK;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// SetDWORDPropertyData
//
//----------------------------------------------------------------------------
HRESULT SetDWORDPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, DWORD dw)
{
VARIANT var;
if (!dw)
{
return pProp->Clear(ec, pRange);
}
var.vt = VT_I4;
var.lVal = dw;
return pProp->SetValue(ec, pRange, &var);
}
//+---------------------------------------------------------------------------
//
// GetBSTRPropertyData
//
//----------------------------------------------------------------------------
HRESULT GetBSTRPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR *pbstr)
{
VARIANT var = { 0 };
HRESULT hr = E_FAIL;
*pbstr = NULL;
if (pProp->GetValue(ec, pRange, &var) != S_OK)
return E_FAIL;
if (var.vt != VT_BSTR)
goto Exit;
*pbstr = SysAllocString(var.bstrVal);
if (*pbstr)
hr = S_OK;
else
hr = E_OUTOFMEMORY;
Exit:
VariantClear(&var);
return hr;
}
//+---------------------------------------------------------------------------
//
// SetBSTRPropertyData
//
//----------------------------------------------------------------------------
HRESULT SetBSTRPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR bstr)
{
VARIANT var;
HRESULT hr;
if (!bstr)
return pProp->Clear(ec, pRange);
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(bstr);
if (!var.bstrVal)
return E_OUTOFMEMORY;
hr = pProp->SetValue(ec, pRange, &var);
VariantClear(&var);
return hr;
}
//+---------------------------------------------------------------------------
//
// GetUnknownPropertyData
//
//----------------------------------------------------------------------------
HRESULT GetUnknownPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, IUnknown **ppunk)
{
VARIANT var = { 0 };
*ppunk = NULL;
if (pProp->GetValue(ec, pRange, &var) != S_OK)
return E_FAIL;
if (var.vt != VT_UNKNOWN)
goto Exit;
*ppunk = var.punkVal;
(*ppunk)->AddRef();
Exit:
VariantClear(&var);
return (*ppunk == NULL) ? E_FAIL : S_OK;
}
//+---------------------------------------------------------------------------
//
// SetUnknownPropertyData
//
//----------------------------------------------------------------------------
HRESULT SetUnknownPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, IUnknown *punk)
{
VARIANT var;
if (!punk)
return pProp->Clear(ec, pRange);
var.vt = VT_UNKNOWN;
var.punkVal = punk;
return pProp->SetValue(ec, pRange, &var);
}
//+---------------------------------------------------------------------------
//
// GetReadingStrPropertyData
//
//----------------------------------------------------------------------------
HRESULT GetReadingStrPropertyData(TfEditCookie ec, ITfProperty *pProp, ITfRange *pRange, BSTR *pbstr)
{
return GetBSTRPropertyData(ec, pProp, pRange, pbstr);
}
//+---------------------------------------------------------------------------
//
// SetIntAttribute
//
//----------------------------------------------------------------------------
void SetIntAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, int nData)
{
WCHAR wch[32];
NumToW((DWORD)nData, wch);
SetCharAttribute(pElem, pszTag, wch);
}
//+---------------------------------------------------------------------------
//
// SetCharAttribute
//
//----------------------------------------------------------------------------
void SetCharAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, WCHAR *pszData)
{
VARIANT var;
BSTR bstrTmp = SysAllocString(pszTag);
BSTR bstrTmp2;
if (!bstrTmp)
return;
bstrTmp2 = SysAllocString(pszData);
if (bstrTmp2)
{
V_VT(&var) = VT_BSTR;
V_BSTR(&var) = bstrTmp2;
pElem->setAttribute(bstrTmp, var);
}
VariantClear(&var);
SysFreeString(bstrTmp);
}
//+---------------------------------------------------------------------------
//
// GetIntAttribute
//
//----------------------------------------------------------------------------
HRESULT GetIntAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, int *pnRet)
{
WCHAR wch[32];
if (FAILED(GetCharAttribute(pElem, pszTag, wch, ARRAYSIZE(wch))))
return E_FAIL;
*pnRet = (int)WToNum(wch);
return S_OK;
}
//+---------------------------------------------------------------------------
//
// GetCharAttribute
//
//----------------------------------------------------------------------------
HRESULT GetCharAttribute(IXMLDOMElement *pElem, WCHAR *pszTag, WCHAR *pszData, int nSize)
{
BSTR bstrTmp;
VARIANT var;
int nData = 0;
HRESULT hr = E_FAIL;
*pszData = L'\0';
QuickVariantInit(&var);
bstrTmp = SysAllocString(pszTag);
if (!bstrTmp)
return E_OUTOFMEMORY;
if (SUCCEEDED(pElem->getAttribute(bstrTmp, &var)))
{
if (V_VT(&var) == VT_BSTR)
{
if (wcsncpy(pszData, V_BSTR(&var), nSize))
hr = S_OK;
}
}
SysFreeString(bstrTmp);
VariantClear(&var);
return hr;
}
//+---------------------------------------------------------------------------
//
// SetTextAndProperty
//
//----------------------------------------------------------------------------
HRESULT SetTextAndProperty(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, const WCHAR *pchText, LONG cchText, LANGID langid, const GUID *pattr)
{
HRESULT hr;
// Issue: sometimes we want to set TFST_CORRECTION
hr = pRange->SetText(ec, 0, pchText, cchText);
if (SUCCEEDED(hr) && cchText)
{
ITfProperty *pProp = NULL;
// set langid
if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_LANGID, &pProp)))
{
SetLangIdPropertyData(ec, pProp, pRange, langid);
pProp->Release();
}
if (pattr)
{
// set attr
if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp)))
{
hr = SetAttrPropertyData(plt, ec, pProp, pRange, *pattr);
pProp->Release();
}
}
}
return hr;
}
//+---------------------------------------------------------------------------
//
// SetTextAndReading
//
//----------------------------------------------------------------------------
HRESULT SetTextAndReading(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, const WCHAR *pchText, LONG cchText, LANGID langid, const WCHAR *pszRead)
{
ITfProperty *pProp;
HRESULT hr;
hr = SetTextAndProperty(plt, ec, pic, pRange, pchText, cchText, langid, NULL);
if (SUCCEEDED(hr = pic->GetProperty(GUID_PROP_READING, &pProp)))
{
BSTR bstr = SysAllocString(pszRead);
if (bstr)
{
SetBSTRPropertyData(ec, pProp, pRange, bstr);
SysFreeString(bstr);
}
else
{
hr = E_OUTOFMEMORY;
}
pProp->Release();
}
return hr;
}
//+---------------------------------------------------------------------------
//
// IsOwnerAndFocus
//
// This is service function for EnumTrackTextAndFocus.
//
//----------------------------------------------------------------------------
BOOL IsOwnerAndFocus(LIBTHREAD *plt, TfEditCookie ec, REFCLSID rclsid, ITfReadOnlyProperty *pProp, ITfRange *pRange)
{
IEnumTfPropertyValue *pEnumPropVal;
BOOL bRet = FALSE;
VARIANT var;
ULONG iTextOwner;
ULONG iFocus;
TF_PROPERTYVAL rgValue[2];
if (SUCCEEDED(pProp->GetValue(ec, pRange, &var)))
{
Assert(var.vt == VT_UNKNOWN);
if (SUCCEEDED(var.punkVal->QueryInterface(IID_IEnumTfPropertyValue,
(void **)&pEnumPropVal)))
{
if (pEnumPropVal->Next(2, rgValue, NULL) == S_OK)
{
Assert(rgValue[0].varValue.vt == VT_I4);
Assert(rgValue[1].varValue.vt == VT_I4);
// Issue: should we change the spec so the order is guaranteed maintained?
if (IsEqualGUID(rgValue[0].guidId, GUID_PROP_TEXTOWNER))
{
Assert(IsEqualGUID(rgValue[1].guidId, GUID_PROP_COMPOSING));
iTextOwner = 0;
iFocus = 1;
}
else
{
iTextOwner = 1;
iFocus = 0;
}
// does the owner match rclisd?
if (IsEqualTFGUIDATOM(plt, (TfGuidAtom)rgValue[iTextOwner].varValue.lVal, rclsid))
{
// is the focus property set (not VT_EMPTY) and is it set TRUE?
bRet = (rgValue[iFocus].varValue.vt == VT_I4 && rgValue[iFocus].varValue.lVal != 0);
}
}
pEnumPropVal->Release();
}
VariantClear(&var);
}
return bRet;
}
//+---------------------------------------------------------------------------
//
// EnumTrackTextAndFocus
//
//----------------------------------------------------------------------------
HRESULT EnumTrackTextAndFocus(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfReadOnlyProperty **ppProp, IEnumTfRanges **ppEnumTrack)
{
static const GUID *rgguidProp[2] = { &GUID_PROP_TEXTOWNER, &GUID_PROP_COMPOSING };
ITfReadOnlyProperty *pPropTrack = NULL;
HRESULT hr;
*ppEnumTrack = NULL;
*ppProp = NULL;
if (SUCCEEDED(hr = pic->TrackProperties(rgguidProp, ARRAYSIZE(rgguidProp),
0, NULL,
&pPropTrack)))
{
hr = pPropTrack->EnumRanges(ec, ppEnumTrack, pRange);
*ppProp = pPropTrack;
}
return hr;
}
//+---------------------------------------------------------------------------
//
// IsGUIDProp
//
//----------------------------------------------------------------------------
BOOL IsGUIDProp(LIBTHREAD *plt, TfEditCookie ec, REFGUID rclsid, ITfProperty *pProp, ITfRange *pRange)
{
TfGuidAtom guidatom;
if (SUCCEEDED(GetGUIDPropertyData(ec, pProp, pRange, &guidatom)))
{
if (IsEqualTFGUIDATOM(plt, guidatom, rclsid))
{
return TRUE;
}
}
return FALSE;
}
//+---------------------------------------------------------------------------
//
// AdjustRangeByProperty
//
//----------------------------------------------------------------------------
HRESULT AdjustRangeByTextOwner(TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfRange **ppRange, REFCLSID rclsid)
{
ITfProperty *pProp;
ITfRange *pRangeStart = NULL;
ITfRange *pRangeEnd = NULL;
HRESULT hr = E_FAIL;
if (SUCCEEDED(pic->GetProperty(GUID_PROP_TEXTOWNER, &pProp)))
{
BOOL fEmpty = FALSE;
pRange->IsEmpty(ec, &fEmpty);
if (fEmpty)
{
pProp->FindRange(ec, pRange, &pRangeStart, TF_ANCHOR_START);
}
else
{
pProp->FindRange(ec, pRange, &pRangeStart, TF_ANCHOR_START);
pProp->FindRange(ec, pRange, &pRangeEnd, TF_ANCHOR_END);
}
pProp->Release();
}
if (!pRangeStart)
goto Exit;
if (pRangeEnd)
{
pRangeStart->ShiftEndToRange(ec, pRangeEnd, TF_ANCHOR_END);
}
pRangeStart->Clone(ppRange);
hr = S_OK;
Exit:
SafeRelease(pRangeStart);
SafeRelease(pRangeEnd);
return hr;
}
//+---------------------------------------------------------------------------
//
// AdjustRangeByAttribute
//
//----------------------------------------------------------------------------
HRESULT AdjustRangeByAttribute(LIBTHREAD *plt, TfEditCookie ec, ITfContext *pic, ITfRange *pRange, ITfRange **ppRange, const GUID *rgRGuid, int cGuid)
{
ITfProperty *pProp;
ITfRange *pRangeStart = NULL;
ITfRange *pRangeEnd = NULL;
HRESULT hr = E_FAIL;
if (SUCCEEDED(pic->GetProperty(GUID_PROP_ATTRIBUTE, &pProp)))
{
IEnumTfRanges *pEnumProp;
if (SUCCEEDED(pProp->EnumRanges(ec, &pEnumProp, pRange)))
{
ITfRange *pRangeProp;
//
// first range.
//
while (!pRangeStart &&
pEnumProp->Next(1, &pRangeProp, NULL) == S_OK)
{
for ( int i = 0; i < cGuid; i++ )
{
if (IsGUIDProp(plt, ec, rgRGuid[i], pProp, pRangeProp))
{
pRangeProp->Clone(&pRangeStart);
}
}
pRangeProp->Release();
}
if (pRangeStart)
{
//
// last range.
//
while (pEnumProp->Next(1, &pRangeProp, NULL) == S_OK)
{
for ( int i = 0; i < cGuid; i++ )
{
if (IsGUIDProp(plt, ec, rgRGuid[i], pProp, pRangeProp))
{
SafeRelease(pRangeEnd);
pRangeProp->Clone(&pRangeEnd);
}
}
pRangeProp->Release();
}
}
pEnumProp->Release();
}
pProp->Release();
}
if (!pRangeStart)
goto Exit;
if (pRangeEnd)
{
pRangeStart->ShiftEndToRange(ec, pRangeEnd, TF_ANCHOR_END);
}
pRangeStart->Clone(ppRange);
hr = S_OK;
Exit:
SafeRelease(pRangeStart);
SafeRelease(pRangeEnd);
return hr;
}