框架上的权限被拒绝 [英] Permission denied on frame

查看:193
本文介绍了框架上的权限被拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于CAxWindow的窗口。在这个窗口中我创建WebBrowser控件。当DISPID_DOCUMENTCOMPLETE发生时,我做:

I have a window based on the CAxWindow. In this window I create WebBrowser control. When the DISPID_DOCUMENTCOMPLETE happens I do:

void __stdcall document_complete( LPDISPATCH pBrowser, VARIANT* )
{
    CComQIPtr< IWebBrowser2 > wb( pBrowser );

    CComPtr< IDispatch > doc;

    if( SUCCEEDED( wb->get_Document( &doc ) ) )
    {
        _docs.push_back( doc );
    }

    ...
}

当页面加载时,我调用_docs中的每个文档的脚本(IActiveScript和IActiveScriptSite):

When the page is loaded I call for each document in _docs the script (IActiveScript and IActiveScriptSite):

function main( doc )
{
    try
    {
        return doc.URL;
    }
    catch( e )
    {
        return "Error: " + e.description;
    }
}



在某些文档上,我收到错误:Permission denied 。
使用本地代码我没有任何问题:

On some documents I get error: "Permission denied". With native code I haven't any problems:

for( auto disp : _docs )
{
    CComQIPtr< IHTMLDocument2 > doc( disp );

    _bstr_t url;

    ATLVERIFY( SUCCEEDED( doc->get_URL( url.GetAddress() ) ) );
}

如何避免此错误?

原来,脚本不是原因:

for( auto disp : _docs )
{
    CComQIPtr< IDispatchEx > doc( disp );

    DISPID id = 0;
    auto hr = doc->GetDispID( _bstr_t( L"URL" ), 0, &id );

    // hr == E_ACCESSDENIED
}


推荐答案

据我所知,你有一个自定义脚本宿主通过活动脚本接口托管JavaScript。 JavaScript引擎使用 IDispatchEx :: Invoke 调用COM对象(每当 IDispatchEx 可用,与MSHTML doc 对象一样),并传递自己的 IServiceProvider 。我想,这是 doc 实现意识到它是从与自己的脚本不同的脚本环境中调用,并且出于安全原因(与本机代码调用不同)限制其方法。

As far as I understand, you have a custom scripting host hosting JavaScript through Active Scripting interfaces. JavaScript engine uses IDispatchEx::Invoke to call COM objects (whenever IDispatchEx is available, as with MSHTML doc object) and passes its own IServiceProvider to the call. I suppose, that's how doc implementation is aware it's being called from a scripting environment different from its own scripts, and restrict its methods for security reasons (unlike with native code calls).

我不知道有一个文件化的方法来关闭这个行为,但你可以尝试这些选项:

I'm not aware of a documented way to turn this behavior off, but you could try these options:


  • 在您的 IActiveScriptSite 对象上实现 IServiceProvider ,并将所有服务请求转发到对象( doc )可以从 IHTMLDocument2 对象获取 IServiceProvider c> c c c $ code>并将其所有调用转发到 IHTMLDocument2 。将包装器对象传递给您的脚本,而不是原始的 doc

  • Implement IServiceProvider on your IActiveScriptSite object and forward all service requests to the IServiceProvider you would get from the IHTMLDocument2 object (doc). This may or may not work.
  • Wrap doc with a native C++ object which implements only IDispatch and forward all its calls to IHTMLDocument2. Pass the wrapper object to your script instead of the original doc. Chances are high this should work.

让我们知道您是否有上述任何运气。

Let us know if you have any luck with the above.

请尝试:

class CDispatchWrapper: 
    public CComObjectRoot,
    public IDispatch
{
// http://stackoverflow.com/questions/18718366/permission-denied-on-frame/
protected:
    CDispatchWrapper() {}

    struct MEMBER
    {
        CComPtr<IUnknown> unk;
        CComPtr<ITypeInfo> ti;
    };

    CComPtr<ITypeLib> m_typeLib;
    CComPtr<IDispatch> m_dispatch;
    CSimpleMap<CComBSTR, DISPID> m_dispids;
    CSimpleMap<DISPID, MEMBER> m_members;

public:
    BEGIN_COM_MAP(CDispatchWrapper)
        COM_INTERFACE_ENTRY(IDispatch)
    END_COM_MAP()

    // create and initialize
    static HRESULT Create(IDispatch* dispatch, const GUID& libid, CDispatchWrapper** pp)
    {
        CComObject<CDispatchWrapper>* pThis = NULL;
        CComObject<CDispatchWrapper>::CreateInstance(&pThis);
        if (!pThis) 
            return E_OUTOFMEMORY;

        if ( FAILED(LoadRegTypeLib(libid, 0xFFFF, 0xFFFF, 0, &pThis->m_typeLib)) )
            return E_FAIL;

        pThis->m_dispatch = dispatch;

        (*pp = pThis)->AddRef();
        return S_OK;
    }

    // IDispatch
    STDMETHODIMP GetTypeInfoCount(UINT* pctinfo)
    {
        return E_NOTIMPL; 
    }

    STDMETHODIMP GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo)
    {
        return E_NOTIMPL; 
    }

    STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
    {
        if ( cNames != 1 || !rgszNames || !rgszNames[0] || !*rgszNames[0] || !rgdispid ) 
            return E_INVALIDARG;

        CComBSTR name(rgszNames[0]);
        if ( !name )
            return E_OUTOFMEMORY;

        int n = m_dispids.FindKey(name);
        if ( n >= 0 )
        {
            DISPID dispid = m_dispids.GetValueAt(n);
            if ( dispid == DISPID_UNKNOWN )
                return DISP_E_UNKNOWNNAME;
            rgdispid[0] = dispid;
            return S_OK;
        }

        // find the name(s) in the typelib
        UINT cMax = m_typeLib->GetTypeInfoCount();
        ITypeInfo** ppTypeInfo = (ITypeInfo**)_alloca(sizeof(ITypeInfo*) * cMax);
        MEMBERID* pMemberid = (MEMBERID*)_alloca(sizeof(MEMBERID*) * cMax);
        USHORT cTypes = cMax;
        if ( FAILED(m_typeLib->FindName(name, 0, ppTypeInfo, pMemberid, &cTypes)) || !cTypes )
            return DISP_E_UNKNOWNNAME;

        bool found = false;
        MEMBER member;
        DISPID dispid = DISPID_UNKNOWN;

        for ( int i = 0; i < cTypes && !found; i++ ) 
        {
            TYPEATTR* pTypeAttr = NULL;
            member.ti.Release();
            member.unk.Release();

            member.ti = ppTypeInfo[i];
            member.ti->GetTypeAttr(&pTypeAttr);
            if (pTypeAttr)
            {
                // check to see if m_dispatch object also implements pTypeAttr->guid interface
                m_dispatch->QueryInterface(pTypeAttr->guid, (void**)&member.unk);
                if (member.unk)
                {
                    // could use pMemberid[i], but let's make sure
                    dispid = DISPID_UNKNOWN;
                    if ( SUCCEEDED(member.ti->GetIDsOfNames(rgszNames, 1, &dispid)) )
                        found = true;
                }
                member.ti->ReleaseTypeAttr(pTypeAttr);
            }
        }

        for ( int i = 0; i < cTypes; i++ ) 
            ppTypeInfo[i]->Release();

        if (found)
        {
            if ( !m_dispids.Add(name, dispid) )
                return E_OUTOFMEMORY;
            if ( !m_members.Add(dispid, member) )
                return E_OUTOFMEMORY;

            rgdispid[0] = dispid;
            return S_OK;
        }

        if ( !m_dispids.Add(name, DISPID_UNKNOWN) )
            return E_OUTOFMEMORY;

        return DISP_E_UNKNOWNNAME;
    }

    STDMETHODIMP Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
    {
        int n = m_members.FindKey(dispidMember);
        if ( n >= 0 )
        {
            const MEMBER& member = m_members.GetValueAt(n);
            return member.ti->Invoke(member.unk, dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr); 
        }

        return DISP_E_MEMBERNOTFOUND;
    }
};

用法:

CComPtr<IHTMLDocument2> doc; 
// ...
// once doc != NULL, wrap it
CComPtr<CDispatchWrapper> wrapper;
CDispatchWrapper::Create(doc, LIBID_MSHTML, &wrapper);
// now pass the wrapper to the script, instead of doc

这篇关于框架上的权限被拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆