IDispatchEx :: GetDispID返回S_OK但无法找到成员

时间:2016-08-23 09:24:56

标签: c++ internet-explorer bho

我有以下代码(其中windowDispIDispatchEx代表IE中的文档):

DISPID dispId = 0;
HRESULT res = windowDisp->GetDispID(objectNameStr, fdexNameEnsure, &dispId);
if (FAILED(res))
{
    LOG_ERROR("Failed creating " << AnsiConverter(objectName) << " object in "
        << AnsiConverter(url) << ", HResult: " << res);
    return false;
}
if (dispId == DISPID_UNKNOWN)
{
    LOG_ERROR("Creating " << AnsiConverter(objectName) << " object in "
        << AnsiConverter(url) << " resulted in DISPID_UNKNOWN");
}

// Validate creating property
DISPID testDispId = 0;
res = windowDisp->GetDispID(objectNameStr, 0, &testDispId);
if (FAILED(res) || dispId != testDispId)
{
    LOG_ERROR("Failed validating " << AnsiConverter(objectName) << " object in "
        << AnsiConverter(url) << ", HResult: " << res);
    if (res == DISP_E_UNKNOWNNAME)
    {
        std::string all = enumerateDispIds(windowDisp);
        LOG_ERROR("Available objects are" << all);
    }
    return false;
}

并且(从https://msdn.microsoft.com/en-us/library/tt99ahf2(v=vs.94).aspx修改):

static std::string enumerateDispIds(const CComQIPtr<IDispatchEx>& windowDisp)
{
    HRESULT hr;
    BSTR bstrName;
    DISPID dispid;

    std::stringstream ss;

    hr = windowDisp->GetNextDispID(fdexEnumAll, DISPID_STARTENUM, &dispid);
    while (hr == S_OK)
    {
        hr = windowDisp->GetMemberName(dispid, &bstrName);

        ss << "\t" << dispid << ": " << (hr == S_OK ? AnsiConverter(bstrName) : "COULD NOT GET NAME") << std::endl;

        SysFreeString(bstrName);
        hr = windowDisp->GetNextDispID(fdexEnumAll, dispid, &dispid);
    }

    return ss.str();
}

我的问题是第一次调用GetDispID会返回S_OK和一个有效的dispId,据我所知,这意味着该成员之前已经创建过,或者是在此期间创建的调用(感谢fdexNameEnsure参数),但第二次调用GetDispID应该验证成员确实存在,但DISP_E_UNKNOWNNAME失败。当我查看日志时,我会看到枚举中的所有成员,而这些成员都不是我试图创建的。因此,GetDispID似乎会返回S_OK,但并不会真正成功。

我在Windows 10 x64和IE 11上。

我问的原因是我们在测试环境(Windows 7版本7601 SP1 x64,IE 11.0.9600.18347)中使用以下调用堆栈在IE中获取访问冲突(底部3帧是我们然后我们进入IE代码):

jscript9!Js::SimpleDictionaryTypeHandlerBase<unsigned short,Js::PropertyRecord const * __ptr64,0>::HasProperty+0xb0
jscript9!Js::GlobalObject::SetExistingProperty+0x57
jscript9!Js::GlobalObject::SetProperty+0x4f
jscript9!Js::DefaultScriptOperations::DefaultOperationsWrapper<<lambda_0739649a84a512e5527a10b6eeb626fd> >+0x1b6
jscript9!Js::DefaultScriptOperations::SetProperty+0x7b
mshtml!CWindowTypeOperations::SetProperty+0x70
jscript9!Js::CustomExternalObject::SetPropertyImpl<0>+0x133
jscript9!Js::JavascriptExternalOperators::SetProperty+0xd10e6
jscript9!ScriptSite::ExternalSetProperty+0x6f
jscript9!JavascriptDispatch::InvokeOnMember+0x1fa
jscript9!JavascriptDispatch::InvokeEx+0x28e
mshtml!CBase::varInvokeEx+0xbd
Hook64!createHookObject+0x599
Hook64!InjectScript+0x402
Hook64!CHtmlInterceptor::Invoke+0x5bb

获得dispId后,我们致电InvokeEx

windowDisp->InvokeEx(dispId, 
    LOCALE_USER_DEFAULT, 
    DISPATCH_PROPERTYPUT, 
    &params, 
    NULL, NULL, NULL);

这会导致访问冲突。所以我们认为可能没有创建对象......

0 个答案:

没有答案