【发布时间】:2010-06-16 15:26:37
【问题描述】:
我在嵌入式 IE7/8 HTML 页面中有一个 ActiveX 控件,它具有以下事件 [id(1)] HRESULT MessageReceived([in] BSTR id, [in] BSTR json)。在 Windows 上,该事件使用 OCX.attachEvent("MessageReceived", onMessageReceivedFunc) 注册。
以下代码触发 HTML 页面中的事件。
HRESULT Fire_MessageReceived(BSTR id, BSTR json)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
CComVariant* pvars = new CComVariant[2];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[1] = id;
pvars[0] = json;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
delete[] pvars; // -> Memory Corruption here!
return varResult.scode;
}
使用应用程序验证程序启用 gflags.exe 后,出现以下奇怪行为: 在执行 JavaScript 回调的 Invoke() 之后,出于某种未知原因,来自 pvars[1] 的 BSTR 被复制到 pvars[0] ! pvars 的 delete[] 导致双重释放相同的字符串,然后以堆损坏结束。
有人知道这里发生了什么吗?这是一个 IE 错误,还是在 OCX 实现中我遗漏了一个技巧?
如果我使用这样的标签:
<script for="OCX" event="MessageReceived(id, json)" language="JavaScript" type="text/javascript">
window.onMessageReceivedFunc(windowId, json);
</script>
...奇怪的复制操作没有发生。
以下代码似乎也可以,因为 Fire_MessageReceived() 的调用者负责释放 BSTR。
HRESULT Fire_MessageReceived(BSTR srcWindowId, BSTR json)
{
CComVariant varResult;
T* pT = static_cast<T*>(this);
int nConnectionIndex;
VARIANT pvars[2];
int nConnections = m_vec.GetSize();
for (nConnectionIndex = 0; nConnectionIndex < nConnections; nConnectionIndex++)
{
pT->Lock();
CComPtr<IUnknown> sp = m_vec.GetAt(nConnectionIndex);
pT->Unlock();
IDispatch* pDispatch = reinterpret_cast<IDispatch*>(sp.p);
if (pDispatch != NULL)
{
VariantClear(&varResult);
pvars[1].vt = VT_BSTR;
pvars[1].bstrVal = srcWindowId;
pvars[0].vt = VT_BSTR;
pvars[0].bstrVal = json;
DISPPARAMS disp = { pvars, NULL, 2, 0 };
pDispatch->Invoke(0x1, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &disp, &varResult, NULL, NULL);
}
}
delete[] pvars;
return varResult.scode;
}
谢谢!
【问题讨论】:
标签: internet-explorer activex idispatch object-tag connection-points