Jacek Caban : mshtml: Try to install ActiveX if it's not registered.
Alexandre Julliard
julliard at winehq.org
Fri Nov 2 15:52:03 CDT 2012
Module: wine
Branch: master
Commit: d1f2b8a8093dd7a3917c2aa5e84fd8f72fe30e12
URL: http://source.winehq.org/git/wine.git/?a=commit;h=d1f2b8a8093dd7a3917c2aa5e84fd8f72fe30e12
Author: Jacek Caban <jacek at codeweavers.com>
Date: Fri Nov 2 13:50:09 2012 +0100
mshtml: Try to install ActiveX if it's not registered.
---
dlls/mshtml/npplugin.c | 288 ++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 288 insertions(+), 0 deletions(-)
diff --git a/dlls/mshtml/npplugin.c b/dlls/mshtml/npplugin.c
index 192b8dc..aa74961 100644
--- a/dlls/mshtml/npplugin.c
+++ b/dlls/mshtml/npplugin.c
@@ -313,6 +313,292 @@ static BOOL get_elem_clsid(nsIDOMElement *elem, CLSID *clsid)
return ret;
}
+typedef struct {
+ IBindStatusCallback IBindStatusCallback_iface;
+ IWindowForBindingUI IWindowForBindingUI_iface;
+ LONG ref;
+} InstallCallback;
+
+static inline InstallCallback *impl_from_IBindStatusCallback(IBindStatusCallback *iface)
+{
+ return CONTAINING_RECORD(iface, InstallCallback, IBindStatusCallback_iface);
+}
+
+static HRESULT WINAPI InstallCallback_QueryInterface(IBindStatusCallback *iface,
+ REFIID riid, void **ppv)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = &This->IBindStatusCallback_iface;
+ }else if(IsEqualGUID(&IID_IBindStatusCallback, riid)) {
+ TRACE("(%p)->(IID_IBindStatusCallback %p)\n", This, ppv);
+ *ppv = &This->IBindStatusCallback_iface;
+ }else if(IsEqualGUID(&IID_IWindowForBindingUI, riid)) {
+ TRACE("(%p)->(IID_IWindowForBindingUI %p)\n", This, ppv);
+ *ppv = &This->IWindowForBindingUI_iface;
+ }else {
+ TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+ *ppv = NULL;
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI InstallCallback_AddRef(IBindStatusCallback *iface)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI InstallCallback_Release(IBindStatusCallback *iface)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref)
+ heap_free(This);
+
+ return ref;
+}
+
+static HRESULT WINAPI InstallCallback_OnStartBinding(IBindStatusCallback *iface,
+ DWORD dwReserved, IBinding *pib)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%x %p)\n", This, dwReserved, pib);
+ return S_OK;
+}
+
+static HRESULT WINAPI InstallCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%p)\n", This, pnPriority);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InstallCallback_OnLowResource(IBindStatusCallback *iface, DWORD dwReserved)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%x)\n", This, dwReserved);
+ return S_OK;
+}
+
+static HRESULT WINAPI InstallCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
+ ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%u %u %u %s)\n", This, ulProgress, ulProgressMax, ulStatusCode, debugstr_w(szStatusText));
+ return S_OK;
+}
+
+static HRESULT WINAPI InstallCallback_OnStopBinding(IBindStatusCallback *iface,
+ HRESULT hresult, LPCWSTR szError)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ TRACE("(%p)->(%08x %s)\n", This, hresult, debugstr_w(szError));
+ return S_OK;
+}
+
+static HRESULT WINAPI InstallCallback_GetBindInfo(IBindStatusCallback *iface,
+ DWORD* grfBINDF, BINDINFO* pbindinfo)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+
+ TRACE("(%p)->(%p %p)\n", This, grfBINDF, pbindinfo);
+
+ *grfBINDF = BINDF_ASYNCHRONOUS;
+ return S_OK;
+}
+
+static HRESULT WINAPI InstallCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
+ DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ ERR("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI InstallCallback_OnObjectAvailable(IBindStatusCallback *iface,
+ REFIID riid, IUnknown* punk)
+{
+ InstallCallback *This = impl_from_IBindStatusCallback(iface);
+ ERR("(%p)\n", This);
+ return E_NOTIMPL;
+}
+
+static IBindStatusCallbackVtbl InstallCallbackVtbl = {
+ InstallCallback_QueryInterface,
+ InstallCallback_AddRef,
+ InstallCallback_Release,
+ InstallCallback_OnStartBinding,
+ InstallCallback_GetPriority,
+ InstallCallback_OnLowResource,
+ InstallCallback_OnProgress,
+ InstallCallback_OnStopBinding,
+ InstallCallback_GetBindInfo,
+ InstallCallback_OnDataAvailable,
+ InstallCallback_OnObjectAvailable
+};
+
+static inline InstallCallback *impl_from_IWindowForBindingUI(IWindowForBindingUI *iface)
+{
+ return CONTAINING_RECORD(iface, InstallCallback, IWindowForBindingUI_iface);
+}
+
+static HRESULT WINAPI WindowForBindingUI_QueryInterface(IWindowForBindingUI *iface, REFIID riid, void **ppv)
+{
+ InstallCallback *This = impl_from_IWindowForBindingUI(iface);
+ return IBindStatusCallback_QueryInterface(&This->IBindStatusCallback_iface, riid, ppv);
+}
+
+static ULONG WINAPI WindowForBindingUI_AddRef(IWindowForBindingUI *iface)
+{
+ InstallCallback *This = impl_from_IWindowForBindingUI(iface);
+ return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
+}
+
+static ULONG WINAPI WindowForBindingUI_Release(IWindowForBindingUI *iface)
+{
+ InstallCallback *This = impl_from_IWindowForBindingUI(iface);
+ return IBindStatusCallback_AddRef(&This->IBindStatusCallback_iface);
+}
+
+static HRESULT WINAPI WindowForBindingUI_GetWindow(IWindowForBindingUI *iface, REFGUID rguidReason, HWND *phwnd)
+{
+ InstallCallback *This = impl_from_IWindowForBindingUI(iface);
+ FIXME("(%p)->(%s %p)\n", This, debugstr_guid(rguidReason), phwnd);
+ *phwnd = NULL;
+ return S_OK;
+}
+
+static const IWindowForBindingUIVtbl WindowForBindingUIVtbl = {
+ WindowForBindingUI_QueryInterface,
+ WindowForBindingUI_AddRef,
+ WindowForBindingUI_Release,
+ WindowForBindingUI_GetWindow
+};
+
+typedef struct {
+ struct list entry;
+ IUri *uri;
+} install_entry_t;
+
+static struct list install_list = LIST_INIT(install_list);
+
+static CRITICAL_SECTION cs_install_list;
+static CRITICAL_SECTION_DEBUG cs_install_list_dbg =
+{
+ 0, 0, &cs_install_list,
+ { &cs_install_list_dbg.ProcessLocksList, &cs_install_list_dbg.ProcessLocksList },
+ 0, 0, { (DWORD_PTR)(__FILE__ ": install_list") }
+};
+static CRITICAL_SECTION cs_install_list = { &cs_install_list_dbg, -1, 0, 0, 0, 0 };
+
+static void install_codebase(const WCHAR *url)
+{
+ InstallCallback *callback;
+ IBindCtx *bctx;
+ HRESULT hres;
+
+ callback = heap_alloc(sizeof(*callback));
+ if(!callback)
+ return;
+
+ callback->IBindStatusCallback_iface.lpVtbl = &InstallCallbackVtbl;
+ callback->IWindowForBindingUI_iface.lpVtbl = &WindowForBindingUIVtbl;
+ callback->ref = 1;
+
+ hres = CreateAsyncBindCtx(0, &callback->IBindStatusCallback_iface, NULL, &bctx);
+ IBindStatusCallback_Release(&callback->IBindStatusCallback_iface);
+ if(FAILED(hres))
+ return;
+
+ hres = AsyncInstallDistributionUnit(NULL, NULL, NULL, 0, 0, url, bctx, NULL, 0);
+ IBindCtx_Release(bctx);
+ if(FAILED(hres))
+ WARN("FAILED: %08x\n", hres);
+}
+
+static void check_codebase(HTMLInnerWindow *window, nsIDOMElement *nselem)
+{
+ nsAString attr_str, val_str;
+ BOOL is_on_list = FALSE;
+ install_entry_t *iter;
+ IUri *uri = NULL;
+ nsresult nsres;
+ HRESULT hres;
+
+ static const PRUnichar codebaseW[] = {'c','o','d','e','b','a','s','e',0};
+
+ nsAString_InitDepend(&attr_str, codebaseW);
+ nsAString_Init(&val_str, NULL);
+ nsres = nsIDOMElement_GetAttribute(nselem, &attr_str, &val_str);
+ nsAString_Finish(&attr_str);
+ if(NS_SUCCEEDED(nsres)) {
+ const PRUnichar *val;
+
+ nsAString_GetData(&val_str, &val);
+ if(*val) {
+ hres = CoInternetCombineUrlEx(window->base.outer_window->uri, val, 0, &uri, 0);
+ if(FAILED(hres))
+ uri = NULL;
+ }
+ }else {
+ ERR("GetAttribute failed: %08x\n", nsres);
+ }
+
+ nsAString_Finish(&attr_str);
+ if(!uri)
+ return;
+
+ EnterCriticalSection(&cs_install_list);
+
+ LIST_FOR_EACH_ENTRY(iter, &install_list, install_entry_t, entry) {
+ BOOL eq;
+
+ hres = IUri_IsEqual(uri, iter->uri, &eq);
+ if(SUCCEEDED(hres) && eq) {
+ TRACE("already proceeded\n");
+ is_on_list = TRUE;
+ break;
+ }
+ }
+
+ if(!is_on_list) {
+ iter = heap_alloc(sizeof(*iter));
+ if(iter) {
+ IUri_AddRef(uri);
+ iter->uri = uri;
+
+ list_add_tail(&install_list, &iter->entry);
+ }
+ }
+
+ LeaveCriticalSection(&cs_install_list);
+
+ if(!is_on_list) {
+ BSTR display_uri;
+
+ hres = IUri_GetDisplayUri(uri, &display_uri);
+ if(SUCCEEDED(hres)) {
+ install_codebase(display_uri);
+ SysFreeString(display_uri);
+ }
+ }
+
+ IUri_Release(uri);
+}
+
static IUnknown *create_activex_object(HTMLInnerWindow *window, nsIDOMElement *nselem, CLSID *clsid)
{
IClassFactoryEx *cfex;
@@ -337,6 +623,8 @@ static IUnknown *create_activex_object(HTMLInnerWindow *window, nsIDOMElement *n
}
hres = CoGetClassObject(clsid, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, NULL, &IID_IClassFactory, (void**)&cf);
+ if(hres == REGDB_E_CLASSNOTREG)
+ check_codebase(window, nselem);
if(FAILED(hres))
return NULL;
More information about the wine-cvs
mailing list