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
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;
|
|
}
|