📄 compositemoniker.c
字号:
IMoniker_Release(tempInvMk);
IMoniker_Release(mostRigthInvMk);
return res;
}
}
/******************************************************************************
* CompositeMoniker_CommonPrefixWith
******************************************************************************/
static HRESULT WINAPI
CompositeMonikerImpl_CommonPrefixWith(IMoniker* iface, IMoniker* pmkOther,
IMoniker** ppmkPrefix)
{
DWORD mkSys;
HRESULT res1,res2;
IMoniker *tempMk1,*tempMk2,*mostLeftMk1,*mostLeftMk2;
IEnumMoniker *enumMoniker1,*enumMoniker2;
ULONG i,nbCommonMk=0;
/* If the other moniker is a composite, this method compares the components of each composite from left */
/* to right. The returned common prefix moniker might also be a composite moniker, depending on how many */
/* of the leftmost components were common to both monikers. */
if (ppmkPrefix==NULL)
return E_POINTER;
*ppmkPrefix=0;
if (pmkOther==NULL)
return MK_E_NOPREFIX;
IMoniker_IsSystemMoniker(pmkOther,&mkSys);
if((mkSys==MKSYS_GENERICCOMPOSITE)){
IMoniker_Enum(iface,TRUE,&enumMoniker1);
IMoniker_Enum(pmkOther,TRUE,&enumMoniker2);
while(1){
res1=IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
res2=IEnumMoniker_Next(enumMoniker2,1,&mostLeftMk2,NULL);
if ((res1==S_FALSE) && (res2==S_FALSE)){
/* If the monikers are equal, the method returns MK_S_US and sets ppmkPrefix to this moniker.*/
*ppmkPrefix=iface;
IMoniker_AddRef(iface);
return MK_S_US;
}
else if ((res1==S_OK) && (res2==S_OK)){
if (IMoniker_IsEqual(mostLeftMk1,mostLeftMk2)==S_OK)
nbCommonMk++;
else
break;
}
else if (res1==S_OK){
/* If the other moniker is a prefix of this moniker, the method returns MK_S_HIM and sets */
/* ppmkPrefix to the other moniker. */
*ppmkPrefix=pmkOther;
return MK_S_HIM;
}
else{
/* If this moniker is a prefix of the other, this method returns MK_S_ME and sets ppmkPrefix */
/* to this moniker. */
*ppmkPrefix=iface;
return MK_S_ME;
}
}
IEnumMoniker_Release(enumMoniker1);
IEnumMoniker_Release(enumMoniker2);
/* If there is no common prefix, this method returns MK_E_NOPREFIX and sets ppmkPrefix to NULL. */
if (nbCommonMk==0)
return MK_E_NOPREFIX;
IEnumMoniker_Reset(enumMoniker1);
IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
/* if we have more than one commun moniker the result will be a composite moniker */
if (nbCommonMk>1){
/* initialize the common prefix moniker with the composite of two first moniker (from the left)*/
IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
CreateGenericComposite(tempMk1,tempMk2,ppmkPrefix);
IMoniker_Release(tempMk1);
IMoniker_Release(tempMk2);
/* compose all common monikers in a composite moniker */
for(i=0;i<nbCommonMk;i++){
IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
CreateGenericComposite(*ppmkPrefix,tempMk1,&tempMk2);
IMoniker_Release(*ppmkPrefix);
IMoniker_Release(tempMk1);
*ppmkPrefix=tempMk2;
}
return S_OK;
}
else{
/* if we have only one commun moniker the result will be a simple moniker which is the most-left one*/
*ppmkPrefix=tempMk1;
return S_OK;
}
}
else{
/* If the other moniker is not a composite, the method simply compares it to the leftmost component
of this moniker.*/
IMoniker_Enum(iface,TRUE,&enumMoniker1);
IEnumMoniker_Next(enumMoniker1,1,&mostLeftMk1,NULL);
if (IMoniker_IsEqual(pmkOther,mostLeftMk1)==S_OK){
*ppmkPrefix=pmkOther;
return MK_S_HIM;
}
else
return MK_E_NOPREFIX;
}
}
/***************************************************************************************************
* GetAfterCommonPrefix (local function)
* This function returns a moniker that consist of the remainder when the common prefix is removed
***************************************************************************************************/
static VOID GetAfterCommonPrefix(IMoniker* pGenMk,IMoniker* commonMk,IMoniker** restMk)
{
IMoniker *tempMk,*tempMk1,*tempMk2;
IEnumMoniker *enumMoniker1,*enumMoniker2,*enumMoniker3;
ULONG nbRestMk=0;
DWORD mkSys;
HRESULT res1,res2;
*restMk=0;
/* to create an enumerator for pGenMk with current position pointed on the first element after common */
/* prefix: enum the two monikers (left-right) then compare these enumerations (left-right) and stop */
/* on the first difference. */
IMoniker_Enum(pGenMk,TRUE,&enumMoniker1);
IMoniker_IsSystemMoniker(commonMk,&mkSys);
if (mkSys==MKSYS_GENERICCOMPOSITE){
IMoniker_Enum(commonMk,TRUE,&enumMoniker2);
while(1){
res1=IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
res2=IEnumMoniker_Next(enumMoniker2,1,&tempMk2,NULL);
if ((res1==S_FALSE)||(res2==S_FALSE)){
if (res1==S_OK)
nbRestMk++;
IMoniker_Release(tempMk1);
IMoniker_Release(tempMk1);
break;
}
IMoniker_Release(tempMk1);
IMoniker_Release(tempMk1);
}
}
else{
IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
IMoniker_Release(tempMk1);
}
/* count the number of elements in the enumerator after the common prefix */
IEnumMoniker_Clone(enumMoniker1,&enumMoniker3);
for(;IEnumMoniker_Next(enumMoniker3,1,&tempMk,NULL)==S_OK;nbRestMk++)
IMoniker_Release(tempMk);
if (nbRestMk==0)
return;
/* create a generic composite moniker with monikers located after the common prefix */
IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL);
if (nbRestMk==1){
*restMk= tempMk1;
return;
}
else {
IEnumMoniker_Next(enumMoniker1,1,&tempMk2,NULL);
CreateGenericComposite(tempMk1,tempMk2,restMk);
IMoniker_Release(tempMk1);
IMoniker_Release(tempMk2);
while(IEnumMoniker_Next(enumMoniker1,1,&tempMk1,NULL)==S_OK){
CreateGenericComposite(*restMk,tempMk1,&tempMk2);
IMoniker_Release(tempMk1);
IMoniker_Release(*restMk);
*restMk=tempMk2;
}
}
}
/******************************************************************************
* CompositeMoniker_RelativePathTo
******************************************************************************/
static HRESULT WINAPI
CompositeMonikerImpl_RelativePathTo(IMoniker* iface,IMoniker* pmkOther,
IMoniker** ppmkRelPath)
{
HRESULT res;
IMoniker *restOtherMk=0,*restThisMk=0,*invRestThisMk=0,*commonMk=0;
TRACE("(%p,%p,%p)\n",iface,pmkOther,ppmkRelPath);
if (ppmkRelPath==NULL)
return E_POINTER;
*ppmkRelPath=0;
/* This method finds the common prefix of the two monikers and creates two monikers that consist */
/* of the remainder when the common prefix is removed. Then it creates the inverse for the remainder */
/* of this moniker and composes the remainder of the other moniker on the right of it. */
/* finds the common prefix of the two monikers */
res=IMoniker_CommonPrefixWith(iface,pmkOther,&commonMk);
/* if there's no common prefix or the two moniker are equal the relative is the other moniker */
if ((res== MK_E_NOPREFIX)||(res==MK_S_US)){
*ppmkRelPath=pmkOther;
IMoniker_AddRef(pmkOther);
return MK_S_HIM;
}
GetAfterCommonPrefix(iface,commonMk,&restThisMk);
GetAfterCommonPrefix(pmkOther,commonMk,&restOtherMk);
/* if other is a prefix of this moniker the relative path is the inverse of the remainder path of this */
/* moniker when the common prefix is removed */
if (res==MK_S_HIM){
IMoniker_Inverse(restThisMk,ppmkRelPath);
IMoniker_Release(restThisMk);
}
/* if this moniker is a prefix of other moniker the relative path is the remainder path of other moniker */
/* when the common prefix is removed */
else if (res==MK_S_ME){
*ppmkRelPath=restOtherMk;
IMoniker_AddRef(restOtherMk);
}
/* the relative path is the inverse for the remainder of this moniker and the remainder of the other */
/* moniker on the right of it. */
else if (res==S_OK){
IMoniker_Inverse(restThisMk,&invRestThisMk);
IMoniker_Release(restThisMk);
CreateGenericComposite(invRestThisMk,restOtherMk,ppmkRelPath);
IMoniker_Release(invRestThisMk);
IMoniker_Release(restOtherMk);
}
return S_OK;
}
/******************************************************************************
* CompositeMoniker_GetDisplayName
******************************************************************************/
static HRESULT WINAPI
CompositeMonikerImpl_GetDisplayName(IMoniker* iface, IBindCtx* pbc,
IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName)
{
ULONG lengthStr=1;
IEnumMoniker *enumMoniker;
IMoniker* tempMk;
LPOLESTR tempStr;
TRACE("(%p,%p,%p,%p)\n",iface,pbc,pmkToLeft,ppszDisplayName);
if (ppszDisplayName==NULL)
return E_POINTER;
*ppszDisplayName=CoTaskMemAlloc(sizeof(WCHAR));
if (*ppszDisplayName==NULL)
return E_OUTOFMEMORY;
/* This method returns the concatenation of the display names returned by each component moniker of */
/* the composite */
**ppszDisplayName=0;
IMoniker_Enum(iface,TRUE,&enumMoniker);
while(IEnumMoniker_Next(enumMoniker,1,&tempMk,NULL)==S_OK){
IMoniker_GetDisplayName(tempMk,pbc,NULL,&tempStr);
lengthStr+=lstrlenW(tempStr);
*ppszDisplayName=CoTaskMemRealloc(*ppszDisplayName,lengthStr * sizeof(WCHAR));
if (*ppszDisplayName==NULL)
return E_OUTOFMEMORY;
strcatW(*ppszDisplayName,tempStr);
CoTaskMemFree(tempStr);
IMoniker_Release(tempMk);
}
IEnumMoniker_Release(enumMoniker);
return S_OK;
}
/******************************************************************************
* CompositeMoniker_ParseDisplayName
******************************************************************************/
static HRESULT WINAPI
CompositeMonikerImpl_ParseDisplayName(IMoniker* iface, IBindCtx* pbc,
IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten,
IMoniker** ppmkOut)
{
IEnumMoniker *enumMoniker;
IMoniker *tempMk,*mostRigthMk,*antiMk;
/* This method recursively calls IMoniker::ParseDisplayName on the rightmost component of the composite,*/
/* passing everything else as the pmkToLeft parameter for that call. */
/* get the most right moniker */
IMoniker_Enum(iface,FALSE,&enumMoniker);
IEnumMoniker_Next(enumMoniker,1,&mostRigthMk,NULL);
IEnumMoniker_Release(enumMoniker);
/* get the left moniker */
CreateAntiMoniker(&antiMk);
IMoniker_ComposeWith(iface,antiMk,0,&tempMk);
IMoniker_Release(antiMk);
return IMoniker_ParseDisplayName(mostRigthMk,pbc,tempMk,pszDisplayName,pchEaten,ppmkOut);
}
/******************************************************************************
* CompositeMoniker_IsSystemMoniker
******************************************************************************/
static HRESULT WINAPI
CompositeMonikerImpl_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys)
{
TRACE("(%p,%p)\n",iface,pwdMksys);
if (!pwdMksys)
return E_POINTER;
(*pwdMksys)=MKSYS_GENERICCOMPOSITE;
return S_OK;
}
/*******************************************************************************
* CompositeMonikerIROTData_QueryInterface
*******************************************************************************/
static HRESULT WINAPI
CompositeMonikerROTDataImpl_QueryInterface(IROTData *iface,REFIID riid,
VOID** ppvObject)
{
IMoniker *This = impl_from_IROTData(iface);
TRACE("(%p,%p,%p)\n",iface,riid,ppvObject);
return CompositeMonikerImpl_QueryInterface(This, riid, ppvObject);
}
/***********************************************************************
* CompositeMonikerIROTData_AddRef
*/
static ULONG WINAPI
CompositeMonikerROTDataImpl_AddRef(IROTData *iface)
{
IMoniker *This = impl_from_IROTData(iface);
TRACE("(%p)\n",iface);
return IMoniker_AddRef(This);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -