⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 compositemoniker.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -