diff --git a/dlls/mshtml/dispex.c b/dlls/mshtml/dispex.c
index 65e6edb..c63181f 100644
--- a/dlls/mshtml/dispex.c
+++ b/dlls/mshtml/dispex.c
@@ -85,6 +85,7 @@ static struct list dispex_data_list = LIST_INIT(dispex_data_list);
static REFIID tid_ids[] = {
&IID_NULL,
&DIID_DispCEventObj,
+ &DIID_DispCPlugins,
&DIID_DispDOMChildrenCollection,
&DIID_DispHTMLAnchorElement,
&DIID_DispHTMLBody,
@@ -150,6 +151,7 @@ static REFIID tid_ids[] = {
&IID_IHTMLLocation,
&IID_IHTMLObjectElement,
&IID_IHTMLOptionElement,
+ &IID_IHTMLPluginsCollection,
&IID_IHTMLRect,
&IID_IHTMLScreen,
&IID_IHTMLScriptElement,
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index ce71586..be11bd4 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -67,6 +67,7 @@ typedef struct event_target_t event_target_t;
typedef enum {
NULL_tid,
DispCEventObj_tid,
+ DispCPlugins_tid,
DispDOMChildrenCollection_tid,
DispHTMLAnchorElement_tid,
DispHTMLBody_tid,
@@ -132,6 +133,7 @@ typedef enum {
IHTMLLocation_tid,
IHTMLObjectElement_tid,
IHTMLOptionElement_tid,
+ IHTMLPluginsCollection_tid,
IHTMLRect_tid,
IHTMLScreen_tid,
IHTMLScriptElement_tid,
diff --git a/dlls/mshtml/omnavigator.c b/dlls/mshtml/omnavigator.c
index d127eef..de4489b 100644
--- a/dlls/mshtml/omnavigator.c
+++ b/dlls/mshtml/omnavigator.c
@@ -31,15 +31,168 @@
WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
+typedef struct HTMLPluginsCollection HTMLPluginsCollection;
+
typedef struct {
DispatchEx dispex;
const IOmNavigatorVtbl *lpIOmNavigatorVtbl;
LONG ref;
+
+ HTMLPluginsCollection *plugins;
} OmNavigator;
+
#define OMNAVIGATOR(x) ((IOmNavigator*) &(x)->lpIOmNavigatorVtbl)
+struct HTMLPluginsCollection {
+ DispatchEx dispex;
+ const IHTMLPluginsCollectionVtbl *lpIHTMLPluginsCollectionVtbl;
+
+ LONG ref;
+
+ OmNavigator *navigator;
+};
+
+#define HTMLPLUGINSCOL(x) ((IHTMLPluginsCollection*) &(x)->lpIHTMLPluginsCollectionVtbl)
+
+#define HTMLPLUGINCOL_THIS(iface) DEFINE_THIS(HTMLPluginsCollection, IHTMLPluginsCollection, iface)
+
+static HRESULT WINAPI HTMLPluginsCollection_QueryInterface(IHTMLPluginsCollection *iface, REFIID riid, void **ppv)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+
+ if(IsEqualGUID(&IID_IUnknown, riid)) {
+ TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
+ *ppv = HTMLPLUGINSCOL(This);
+ }else if(IsEqualGUID(&IID_IHTMLPluginsCollection, riid)) {
+ TRACE("(%p)->(IID_IHTMLPluginCollection %p)\n", This, ppv);
+ *ppv = HTMLPLUGINSCOL(This);
+ }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
+ return *ppv ? S_OK : E_NOINTERFACE;
+ }else {
+ *ppv = NULL;
+ WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
+ return E_NOINTERFACE;
+ }
+
+ IUnknown_AddRef((IUnknown*)*ppv);
+ return S_OK;
+}
+
+static ULONG WINAPI HTMLPluginsCollection_AddRef(IHTMLPluginsCollection *iface)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ LONG ref = InterlockedIncrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ return ref;
+}
+
+static ULONG WINAPI HTMLPluginsCollection_Release(IHTMLPluginsCollection *iface)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ LONG ref = InterlockedDecrement(&This->ref);
+
+ TRACE("(%p) ref=%d\n", This, ref);
+
+ if(!ref) {
+ if(This->navigator)
+ This->navigator->plugins = NULL;
+ release_dispex(&This->dispex);
+ heap_free(This);
+ }
+
+ return ref;
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_GetTypeInfoCount(IHTMLPluginsCollection *iface, UINT *pctinfo)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_GetTypeInfo(IHTMLPluginsCollection *iface, UINT iTInfo,
+ LCID lcid, ITypeInfo **ppTInfo)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_GetIDsOfNames(IHTMLPluginsCollection *iface, REFIID riid,
+ LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_Invoke(IHTMLPluginsCollection *iface, DISPID dispIdMember,
+ REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
+ EXCEPINFO *pExcepInfo, UINT *puArgErr)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
+ wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_get_length(IHTMLPluginsCollection *iface, LONG *p)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ FIXME("(%p)->(%p)\n", This, p);
+ return E_NOTIMPL;
+}
+
+static HRESULT WINAPI HTMLPluginsCollection_refresh(IHTMLPluginsCollection *iface, VARIANT_BOOL reload)
+{
+ HTMLPluginsCollection *This = HTMLPLUGINCOL_THIS(iface);
+ FIXME("(%p)->(%x)\n", This, reload);
+ return E_NOTIMPL;
+}
+
+#undef HTMLPLUGINSCOL_THIS
+
+static const IHTMLPluginsCollectionVtbl HTMLPluginsCollectionVtbl = {
+ HTMLPluginsCollection_QueryInterface,
+ HTMLPluginsCollection_AddRef,
+ HTMLPluginsCollection_Release,
+ HTMLPluginsCollection_GetTypeInfoCount,
+ HTMLPluginsCollection_GetTypeInfo,
+ HTMLPluginsCollection_GetIDsOfNames,
+ HTMLPluginsCollection_Invoke,
+ HTMLPluginsCollection_get_length,
+ HTMLPluginsCollection_refresh
+};
+
+static const tid_t HTMLPluginsCollection_iface_tids[] = {
+ IHTMLPluginsCollection_tid,
+ 0
+};
+static dispex_static_data_t HTMLPluginsCollection_dispex = {
+ NULL,
+ DispCPlugins_tid,
+ NULL,
+ HTMLPluginsCollection_iface_tids
+};
+
+static HRESULT create_plugins_collection(OmNavigator *navigator, HTMLPluginsCollection **ret)
+{
+ HTMLPluginsCollection *col;
+
+ col = heap_alloc_zero(sizeof(*col));
+ if(!col)
+ return E_OUTOFMEMORY;
+
+ col->lpIHTMLPluginsCollectionVtbl = &HTMLPluginsCollectionVtbl;
+ col->ref = 1;
+ col->navigator = navigator;
+
+ init_dispex(&col->dispex, (IUnknown*)HTMLPLUGINSCOL(col), &HTMLPluginsCollection_dispex);
+
+ *ret = col;
+ return S_OK;
+}
+
#define OMNAVIGATOR_THIS(iface) DEFINE_THIS(OmNavigator, IOmNavigator, iface)
static HRESULT WINAPI OmNavigator_QueryInterface(IOmNavigator *iface, REFIID riid, void **ppv)
@@ -85,6 +238,10 @@ static ULONG WINAPI OmNavigator_Release(IOmNavigator *iface)
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
+ if(This->plugins) {
+ This->plugins->navigator = NULL;
+ IHTMLPluginsCollection_Release(HTMLPLUGINSCOL(This->plugins));
+ }
release_dispex(&This->dispex);
heap_free(This);
}
@@ -232,8 +389,21 @@ static HRESULT WINAPI OmNavigator_get_mimeTypes(IOmNavigator *iface, IHTMLMimeTy
static HRESULT WINAPI OmNavigator_get_plugins(IOmNavigator *iface, IHTMLPluginsCollection **p)
{
OmNavigator *This = OMNAVIGATOR_THIS(iface);
- FIXME("(%p)->(%p)\n", This, p);
- return E_NOTIMPL;
+
+ TRACE("(%p)->(%p)\n", This, p);
+
+ if(!This->plugins) {
+ HRESULT hres;
+
+ hres = create_plugins_collection(This, &This->plugins);
+ if(FAILED(hres))
+ return hres;
+ }else {
+ IHTMLPluginsCollection_AddRef(HTMLPLUGINSCOL(This->plugins));
+ }
+
+ *p = HTMLPLUGINSCOL(This->plugins);
+ return S_OK;
}
static HRESULT WINAPI OmNavigator_get_cookieEnabled(IOmNavigator *iface, VARIANT_BOOL *p)
diff --git a/dlls/mshtml/tests/dom.c b/dlls/mshtml/tests/dom.c
index f472768..2134b31 100644
--- a/dlls/mshtml/tests/dom.c
+++ b/dlls/mshtml/tests/dom.c
@@ -3590,6 +3590,26 @@ static void test_location(IHTMLDocument2 *doc)
ok(!ref, "location chould be destroyed here\n");
}
+static void test_plugins_col(IOmNavigator *nav)
+{
+ IHTMLPluginsCollection *col, *col2;
+ ULONG ref;
+ HRESULT hres;
+
+ hres = IOmNavigator_get_plugins(nav, &col);
+ ok(hres == S_OK, "get_plugins failed: %08x\n", hres);
+
+ hres = IOmNavigator_get_plugins(nav, &col2);
+ ok(hres == S_OK, "get_plugins failed: %08x\n", hres);
+ ok(iface_cmp((IUnknown*)col, (IUnknown*)col2), "col != col2\n");
+ IHTMLPluginsCollection_Release(col2);
+
+ test_disp2((IUnknown*)col, &DIID_DispCPlugins, &IID_IHTMLPluginsCollection, "[object]");
+
+ ref = IHTMLPluginsCollection_Release(col);
+ ok(!ref, "ref=%d\n", ref);
+}
+
static void test_navigator(IHTMLDocument2 *doc)
{
IHTMLWindow2 *window;
@@ -3673,6 +3693,8 @@ static void test_navigator(IHTMLDocument2 *doc)
skip("nonstandard user agent\n");
}
+ test_plugins_col(navigator);
+
ref = IOmNavigator_Release(navigator);
ok(!ref, "navigator should be destroyed here\n");
}
diff --git a/include/mshtml.idl b/include/mshtml.idl
index d76f20c..55740a7 100644
--- a/include/mshtml.idl
+++ b/include/mshtml.idl
@@ -9146,12 +9146,32 @@ interface IHTMLPluginsCollection : IDispatch
}
[
+ hidden,
+ uuid(3050f54a-98b5-11cf-bb82-00aa00bdce0b)
+]
+dispinterface DispCPlugins
+{
+ properties:
+methods:
+ [propget, id(DISPID_IHTMLPLUGINSCOLLECTION_LENGTH)]
+ long length();
+
+ [id(DISPID_IHTMLPLUGINSCOLLECTION_REFRESH)]
+ void refresh([defaultvalue(0), in] VARIANT_BOOL reload);
+
+ [propget, id(DISPID_IHTMLDOMCONSTRUCTOR_CONSTRUCTOR), hidden]
+ IDispatch *constructor();
+}
+
+[
noncreatable,
uuid(3050f3ff-98b5-11cf-bb82-00aa00bdce0b)
]
coclass CPlugins
{
- [default] interface IHTMLPluginsCollection;
+ [default] dispinterface DispCPlugins;
+ interface IHTMLPluginsCollection;
+ interface IHTMLDOMConstructor;
}
/*****************************************************************************