xref: /reactos/dll/win32/mshtml/omnavigator.c (revision 40462c92)
1 /*
2  * Copyright 2008 Jacek Caban for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "mshtml_private.h"
20 
21 #ifdef __REACTOS__
22 /* HACK This is a Vista+ API */
23 static INT WINAPI LCIDToLocaleName( LCID lcid, LPWSTR name, INT count, DWORD flags )
24 {
25     if (flags) FIXME( "unsupported flags %x\n", flags );
26 
27     return GetLocaleInfoW( lcid, LOCALE_SNAME | LOCALE_NOUSEROVERRIDE, name, count );
28 }
29 #endif
30 
31 typedef struct HTMLPluginsCollection HTMLPluginsCollection;
32 typedef struct HTMLMimeTypesCollection HTMLMimeTypesCollection;
33 
34 typedef struct {
35     DispatchEx dispex;
36     IOmNavigator IOmNavigator_iface;
37 
38     LONG ref;
39 
40     HTMLPluginsCollection *plugins;
41     HTMLMimeTypesCollection *mime_types;
42 } OmNavigator;
43 
44 typedef struct {
45     DispatchEx dispex;
46     IHTMLDOMImplementation IHTMLDOMImplementation_iface;
47 
48     LONG ref;
49 } HTMLDOMImplementation;
50 
51 static inline HTMLDOMImplementation *impl_from_IHTMLDOMImplementation(IHTMLDOMImplementation *iface)
52 {
53     return CONTAINING_RECORD(iface, HTMLDOMImplementation, IHTMLDOMImplementation_iface);
54 }
55 
56 static HRESULT WINAPI HTMLDOMImplementation_QueryInterface(IHTMLDOMImplementation *iface, REFIID riid, void **ppv)
57 {
58     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
59 
60     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
61 
62     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IHTMLDOMImplementation, riid)) {
63         *ppv = &This->IHTMLDOMImplementation_iface;
64     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
65         return *ppv ? S_OK : E_NOINTERFACE;
66     }else {
67         WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
68         *ppv = NULL;
69         return E_NOINTERFACE;
70     }
71 
72     IUnknown_AddRef((IUnknown*)*ppv);
73     return S_OK;
74 }
75 
76 static ULONG WINAPI HTMLDOMImplementation_AddRef(IHTMLDOMImplementation *iface)
77 {
78     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
79     LONG ref = InterlockedIncrement(&This->ref);
80 
81     TRACE("(%p) ref=%d\n", This, ref);
82 
83     return ref;
84 }
85 
86 static ULONG WINAPI HTMLDOMImplementation_Release(IHTMLDOMImplementation *iface)
87 {
88     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
89     LONG ref = InterlockedDecrement(&This->ref);
90 
91     TRACE("(%p) ref=%d\n", This, ref);
92 
93     if(!ref) {
94         release_dispex(&This->dispex);
95         heap_free(This);
96     }
97 
98     return ref;
99 }
100 
101 static HRESULT WINAPI HTMLDOMImplementation_GetTypeInfoCount(IHTMLDOMImplementation *iface, UINT *pctinfo)
102 {
103     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
104 
105     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
106 }
107 
108 static HRESULT WINAPI HTMLDOMImplementation_GetTypeInfo(IHTMLDOMImplementation *iface, UINT iTInfo,
109         LCID lcid, ITypeInfo **ppTInfo)
110 {
111     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
112 
113     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
114 }
115 
116 static HRESULT WINAPI HTMLDOMImplementation_GetIDsOfNames(IHTMLDOMImplementation *iface, REFIID riid,
117         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
118 {
119     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
120 
121     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames,
122             cNames, lcid, rgDispId);
123 }
124 
125 static HRESULT WINAPI HTMLDOMImplementation_Invoke(IHTMLDOMImplementation *iface, DISPID dispIdMember,
126         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
127         EXCEPINFO *pExcepInfo, UINT *puArgErr)
128 {
129     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
130 
131     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid,
132             lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
133 }
134 
135 static HRESULT WINAPI HTMLDOMImplementation_hasFeature(IHTMLDOMImplementation *iface, BSTR feature,
136         VARIANT version, VARIANT_BOOL *pfHasFeature)
137 {
138     HTMLDOMImplementation *This = impl_from_IHTMLDOMImplementation(iface);
139 
140     FIXME("(%p)->(%s %s %p) returning false\n", This, debugstr_w(feature), debugstr_variant(&version), pfHasFeature);
141 
142     *pfHasFeature = VARIANT_FALSE;
143     return S_OK;
144 }
145 
146 static const IHTMLDOMImplementationVtbl HTMLDOMImplementationVtbl = {
147     HTMLDOMImplementation_QueryInterface,
148     HTMLDOMImplementation_AddRef,
149     HTMLDOMImplementation_Release,
150     HTMLDOMImplementation_GetTypeInfoCount,
151     HTMLDOMImplementation_GetTypeInfo,
152     HTMLDOMImplementation_GetIDsOfNames,
153     HTMLDOMImplementation_Invoke,
154     HTMLDOMImplementation_hasFeature
155 };
156 
157 static const tid_t HTMLDOMImplementation_iface_tids[] = {
158     IHTMLDOMImplementation_tid,
159     0
160 };
161 static dispex_static_data_t HTMLDOMImplementation_dispex = {
162     NULL,
163     IHTMLDOMImplementation_tid,
164     NULL,
165     HTMLDOMImplementation_iface_tids
166 };
167 
168 HRESULT create_dom_implementation(IHTMLDOMImplementation **ret)
169 {
170     HTMLDOMImplementation *dom_implementation;
171 
172     dom_implementation = heap_alloc_zero(sizeof(*dom_implementation));
173     if(!dom_implementation)
174         return E_OUTOFMEMORY;
175 
176     dom_implementation->IHTMLDOMImplementation_iface.lpVtbl = &HTMLDOMImplementationVtbl;
177     dom_implementation->ref = 1;
178 
179     init_dispex(&dom_implementation->dispex, (IUnknown*)&dom_implementation->IHTMLDOMImplementation_iface,
180             &HTMLDOMImplementation_dispex);
181 
182     *ret = &dom_implementation->IHTMLDOMImplementation_iface;
183     return S_OK;
184 }
185 
186 static inline OmHistory *impl_from_IOmHistory(IOmHistory *iface)
187 {
188     return CONTAINING_RECORD(iface, OmHistory, IOmHistory_iface);
189 }
190 
191 static HRESULT WINAPI OmHistory_QueryInterface(IOmHistory *iface, REFIID riid, void **ppv)
192 {
193     OmHistory *This = impl_from_IOmHistory(iface);
194 
195     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
196 
197     if(IsEqualGUID(&IID_IUnknown, riid)) {
198         *ppv = &This->IOmHistory_iface;
199     }else if(IsEqualGUID(&IID_IOmHistory, riid)) {
200         *ppv = &This->IOmHistory_iface;
201     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
202         return *ppv ? S_OK : E_NOINTERFACE;
203     }else {
204         WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
205         *ppv = NULL;
206         return E_NOINTERFACE;
207     }
208 
209     IUnknown_AddRef((IUnknown*)*ppv);
210     return S_OK;
211 }
212 
213 static ULONG WINAPI OmHistory_AddRef(IOmHistory *iface)
214 {
215     OmHistory *This = impl_from_IOmHistory(iface);
216     LONG ref = InterlockedIncrement(&This->ref);
217 
218     TRACE("(%p) ref=%d\n", This, ref);
219 
220     return ref;
221 }
222 
223 static ULONG WINAPI OmHistory_Release(IOmHistory *iface)
224 {
225     OmHistory *This = impl_from_IOmHistory(iface);
226     LONG ref = InterlockedDecrement(&This->ref);
227 
228     TRACE("(%p) ref=%d\n", This, ref);
229 
230     if(!ref) {
231         release_dispex(&This->dispex);
232         heap_free(This);
233     }
234 
235     return ref;
236 }
237 
238 static HRESULT WINAPI OmHistory_GetTypeInfoCount(IOmHistory *iface, UINT *pctinfo)
239 {
240     OmHistory *This = impl_from_IOmHistory(iface);
241     FIXME("(%p)->(%p)\n", This, pctinfo);
242     return E_NOTIMPL;
243 }
244 
245 static HRESULT WINAPI OmHistory_GetTypeInfo(IOmHistory *iface, UINT iTInfo,
246         LCID lcid, ITypeInfo **ppTInfo)
247 {
248     OmHistory *This = impl_from_IOmHistory(iface);
249 
250     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
251 }
252 
253 static HRESULT WINAPI OmHistory_GetIDsOfNames(IOmHistory *iface, REFIID riid, LPOLESTR *rgszNames, UINT cNames,
254         LCID lcid, DISPID *rgDispId)
255 {
256     OmHistory *This = impl_from_IOmHistory(iface);
257 
258     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
259             lcid, rgDispId);
260 }
261 
262 static HRESULT WINAPI OmHistory_Invoke(IOmHistory *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
263         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
264 {
265     OmHistory *This = impl_from_IOmHistory(iface);
266 
267     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
268             pDispParams, pVarResult, pExcepInfo, puArgErr);
269 }
270 
271 static HRESULT WINAPI OmHistory_get_length(IOmHistory *iface, short *p)
272 {
273     OmHistory *This = impl_from_IOmHistory(iface);
274 
275     TRACE("(%p)->(%p)\n", This, p);
276 
277     if(!This->window || !This->window->base.outer_window->doc_obj
278             || !This->window->base.outer_window->doc_obj->travel_log) {
279         *p = 0;
280     }else {
281         *p = ITravelLog_CountEntries(This->window->base.outer_window->doc_obj->travel_log,
282                 This->window->base.outer_window->doc_obj->browser_service);
283     }
284     return S_OK;
285 }
286 
287 static HRESULT WINAPI OmHistory_back(IOmHistory *iface, VARIANT *pvargdistance)
288 {
289     OmHistory *This = impl_from_IOmHistory(iface);
290     FIXME("(%p)->(%s)\n", This, debugstr_variant(pvargdistance));
291     return E_NOTIMPL;
292 }
293 
294 static HRESULT WINAPI OmHistory_forward(IOmHistory *iface, VARIANT *pvargdistance)
295 {
296     OmHistory *This = impl_from_IOmHistory(iface);
297     FIXME("(%p)->(%s)\n", This, debugstr_variant(pvargdistance));
298     return E_NOTIMPL;
299 }
300 
301 static HRESULT WINAPI OmHistory_go(IOmHistory *iface, VARIANT *pvargdistance)
302 {
303     OmHistory *This = impl_from_IOmHistory(iface);
304     FIXME("(%p)->(%s)\n", This, debugstr_variant(pvargdistance));
305     return E_NOTIMPL;
306 }
307 
308 static const IOmHistoryVtbl OmHistoryVtbl = {
309     OmHistory_QueryInterface,
310     OmHistory_AddRef,
311     OmHistory_Release,
312     OmHistory_GetTypeInfoCount,
313     OmHistory_GetTypeInfo,
314     OmHistory_GetIDsOfNames,
315     OmHistory_Invoke,
316     OmHistory_get_length,
317     OmHistory_back,
318     OmHistory_forward,
319     OmHistory_go
320 };
321 
322 static const tid_t OmHistory_iface_tids[] = {
323     IOmHistory_tid,
324     0
325 };
326 static dispex_static_data_t OmHistory_dispex = {
327     NULL,
328     DispHTMLHistory_tid,
329     NULL,
330     OmHistory_iface_tids
331 };
332 
333 
334 HRESULT create_history(HTMLInnerWindow *window, OmHistory **ret)
335 {
336     OmHistory *history;
337 
338     history = heap_alloc_zero(sizeof(*history));
339     if(!history)
340         return E_OUTOFMEMORY;
341 
342     init_dispex(&history->dispex, (IUnknown*)&history->IOmHistory_iface, &OmHistory_dispex);
343     history->IOmHistory_iface.lpVtbl = &OmHistoryVtbl;
344     history->ref = 1;
345 
346     history->window = window;
347 
348     *ret = history;
349     return S_OK;
350 }
351 
352 struct HTMLPluginsCollection {
353     DispatchEx dispex;
354     IHTMLPluginsCollection IHTMLPluginsCollection_iface;
355 
356     LONG ref;
357 
358     OmNavigator *navigator;
359 };
360 
361 static inline HTMLPluginsCollection *impl_from_IHTMLPluginsCollection(IHTMLPluginsCollection *iface)
362 {
363     return CONTAINING_RECORD(iface, HTMLPluginsCollection, IHTMLPluginsCollection_iface);
364 }
365 
366 static HRESULT WINAPI HTMLPluginsCollection_QueryInterface(IHTMLPluginsCollection *iface, REFIID riid, void **ppv)
367 {
368     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
369 
370     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
371 
372     if(IsEqualGUID(&IID_IUnknown, riid)) {
373         *ppv = &This->IHTMLPluginsCollection_iface;
374     }else if(IsEqualGUID(&IID_IHTMLPluginsCollection, riid)) {
375         *ppv = &This->IHTMLPluginsCollection_iface;
376     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
377         return *ppv ? S_OK : E_NOINTERFACE;
378     }else {
379         *ppv = NULL;
380         WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
381         return E_NOINTERFACE;
382     }
383 
384     IUnknown_AddRef((IUnknown*)*ppv);
385     return S_OK;
386 }
387 
388 static ULONG WINAPI HTMLPluginsCollection_AddRef(IHTMLPluginsCollection *iface)
389 {
390     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
391     LONG ref = InterlockedIncrement(&This->ref);
392 
393     TRACE("(%p) ref=%d\n", This, ref);
394 
395     return ref;
396 }
397 
398 static ULONG WINAPI HTMLPluginsCollection_Release(IHTMLPluginsCollection *iface)
399 {
400     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
401     LONG ref = InterlockedDecrement(&This->ref);
402 
403     TRACE("(%p) ref=%d\n", This, ref);
404 
405     if(!ref) {
406         if(This->navigator)
407             This->navigator->plugins = NULL;
408         release_dispex(&This->dispex);
409         heap_free(This);
410     }
411 
412     return ref;
413 }
414 
415 static HRESULT WINAPI HTMLPluginsCollection_GetTypeInfoCount(IHTMLPluginsCollection *iface, UINT *pctinfo)
416 {
417     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
418     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
419 }
420 
421 static HRESULT WINAPI HTMLPluginsCollection_GetTypeInfo(IHTMLPluginsCollection *iface, UINT iTInfo,
422                                               LCID lcid, ITypeInfo **ppTInfo)
423 {
424     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
425     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
426 }
427 
428 static HRESULT WINAPI HTMLPluginsCollection_GetIDsOfNames(IHTMLPluginsCollection *iface, REFIID riid,
429         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
430 {
431     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
432     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
433             lcid, rgDispId);
434 }
435 
436 static HRESULT WINAPI HTMLPluginsCollection_Invoke(IHTMLPluginsCollection *iface, DISPID dispIdMember,
437         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
438         EXCEPINFO *pExcepInfo, UINT *puArgErr)
439 {
440     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
441     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
442             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
443 }
444 
445 static HRESULT WINAPI HTMLPluginsCollection_get_length(IHTMLPluginsCollection *iface, LONG *p)
446 {
447     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
448 
449     TRACE("(%p)->(%p)\n", This, p);
450 
451     /* IE always returns 0 here */
452     *p = 0;
453     return S_OK;
454 }
455 
456 static HRESULT WINAPI HTMLPluginsCollection_refresh(IHTMLPluginsCollection *iface, VARIANT_BOOL reload)
457 {
458     HTMLPluginsCollection *This = impl_from_IHTMLPluginsCollection(iface);
459 
460     TRACE("(%p)->(%x)\n", This, reload);
461 
462     /* Nothing to do here. */
463     return S_OK;
464 }
465 
466 static const IHTMLPluginsCollectionVtbl HTMLPluginsCollectionVtbl = {
467     HTMLPluginsCollection_QueryInterface,
468     HTMLPluginsCollection_AddRef,
469     HTMLPluginsCollection_Release,
470     HTMLPluginsCollection_GetTypeInfoCount,
471     HTMLPluginsCollection_GetTypeInfo,
472     HTMLPluginsCollection_GetIDsOfNames,
473     HTMLPluginsCollection_Invoke,
474     HTMLPluginsCollection_get_length,
475     HTMLPluginsCollection_refresh
476 };
477 
478 static const tid_t HTMLPluginsCollection_iface_tids[] = {
479     IHTMLPluginsCollection_tid,
480     0
481 };
482 static dispex_static_data_t HTMLPluginsCollection_dispex = {
483     NULL,
484     DispCPlugins_tid,
485     NULL,
486     HTMLPluginsCollection_iface_tids
487 };
488 
489 static HRESULT create_plugins_collection(OmNavigator *navigator, HTMLPluginsCollection **ret)
490 {
491     HTMLPluginsCollection *col;
492 
493     col = heap_alloc_zero(sizeof(*col));
494     if(!col)
495         return E_OUTOFMEMORY;
496 
497     col->IHTMLPluginsCollection_iface.lpVtbl = &HTMLPluginsCollectionVtbl;
498     col->ref = 1;
499     col->navigator = navigator;
500 
501     init_dispex(&col->dispex, (IUnknown*)&col->IHTMLPluginsCollection_iface,
502                 &HTMLPluginsCollection_dispex);
503 
504     *ret = col;
505     return S_OK;
506 }
507 
508 struct HTMLMimeTypesCollection {
509     DispatchEx dispex;
510     IHTMLMimeTypesCollection IHTMLMimeTypesCollection_iface;
511 
512     LONG ref;
513 
514     OmNavigator *navigator;
515 };
516 
517 static inline HTMLMimeTypesCollection *impl_from_IHTMLMimeTypesCollection(IHTMLMimeTypesCollection *iface)
518 {
519     return CONTAINING_RECORD(iface, HTMLMimeTypesCollection, IHTMLMimeTypesCollection_iface);
520 }
521 
522 static HRESULT WINAPI HTMLMimeTypesCollection_QueryInterface(IHTMLMimeTypesCollection *iface, REFIID riid, void **ppv)
523 {
524     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
525 
526     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
527 
528     if(IsEqualGUID(&IID_IUnknown, riid)) {
529         *ppv = &This->IHTMLMimeTypesCollection_iface;
530     }else if(IsEqualGUID(&IID_IHTMLMimeTypesCollection, riid)) {
531         *ppv = &This->IHTMLMimeTypesCollection_iface;
532     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
533         return *ppv ? S_OK : E_NOINTERFACE;
534     }else {
535         WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
536         *ppv = NULL;
537         return E_NOINTERFACE;
538     }
539 
540     IUnknown_AddRef((IUnknown*)*ppv);
541     return S_OK;
542 }
543 
544 static ULONG WINAPI HTMLMimeTypesCollection_AddRef(IHTMLMimeTypesCollection *iface)
545 {
546     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
547     LONG ref = InterlockedIncrement(&This->ref);
548 
549     TRACE("(%p) ref=%d\n", This, ref);
550 
551     return ref;
552 }
553 
554 static ULONG WINAPI HTMLMimeTypesCollection_Release(IHTMLMimeTypesCollection *iface)
555 {
556     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
557     LONG ref = InterlockedDecrement(&This->ref);
558 
559     TRACE("(%p) ref=%d\n", This, ref);
560 
561     if(!ref) {
562         if(This->navigator)
563             This->navigator->mime_types = NULL;
564         release_dispex(&This->dispex);
565         heap_free(This);
566     }
567 
568     return ref;
569 }
570 
571 static HRESULT WINAPI HTMLMimeTypesCollection_GetTypeInfoCount(IHTMLMimeTypesCollection *iface, UINT *pctinfo)
572 {
573     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
574     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
575 }
576 
577 static HRESULT WINAPI HTMLMimeTypesCollection_GetTypeInfo(IHTMLMimeTypesCollection *iface, UINT iTInfo,
578                                               LCID lcid, ITypeInfo **ppTInfo)
579 {
580     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
581     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
582 }
583 
584 static HRESULT WINAPI HTMLMimeTypesCollection_GetIDsOfNames(IHTMLMimeTypesCollection *iface, REFIID riid,
585         LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
586 {
587     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
588     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
589             lcid, rgDispId);
590 }
591 
592 static HRESULT WINAPI HTMLMimeTypesCollection_Invoke(IHTMLMimeTypesCollection *iface, DISPID dispIdMember,
593         REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
594         EXCEPINFO *pExcepInfo, UINT *puArgErr)
595 {
596     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
597     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
598             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
599 }
600 
601 static HRESULT WINAPI HTMLMimeTypesCollection_get_length(IHTMLMimeTypesCollection *iface, LONG *p)
602 {
603     HTMLMimeTypesCollection *This = impl_from_IHTMLMimeTypesCollection(iface);
604 
605     TRACE("(%p)->(%p)\n", This, p);
606 
607     /* This is just a stub for compatibility with other browser in IE */
608     *p = 0;
609     return S_OK;
610 }
611 
612 static const IHTMLMimeTypesCollectionVtbl HTMLMimeTypesCollectionVtbl = {
613     HTMLMimeTypesCollection_QueryInterface,
614     HTMLMimeTypesCollection_AddRef,
615     HTMLMimeTypesCollection_Release,
616     HTMLMimeTypesCollection_GetTypeInfoCount,
617     HTMLMimeTypesCollection_GetTypeInfo,
618     HTMLMimeTypesCollection_GetIDsOfNames,
619     HTMLMimeTypesCollection_Invoke,
620     HTMLMimeTypesCollection_get_length
621 };
622 
623 static const tid_t HTMLMimeTypesCollection_iface_tids[] = {
624     IHTMLMimeTypesCollection_tid,
625     0
626 };
627 static dispex_static_data_t HTMLMimeTypesCollection_dispex = {
628     NULL,
629     IHTMLMimeTypesCollection_tid,
630     NULL,
631     HTMLMimeTypesCollection_iface_tids
632 };
633 
634 static HRESULT create_mime_types_collection(OmNavigator *navigator, HTMLMimeTypesCollection **ret)
635 {
636     HTMLMimeTypesCollection *col;
637 
638     col = heap_alloc_zero(sizeof(*col));
639     if(!col)
640         return E_OUTOFMEMORY;
641 
642     col->IHTMLMimeTypesCollection_iface.lpVtbl = &HTMLMimeTypesCollectionVtbl;
643     col->ref = 1;
644     col->navigator = navigator;
645 
646     init_dispex(&col->dispex, (IUnknown*)&col->IHTMLMimeTypesCollection_iface,
647                 &HTMLMimeTypesCollection_dispex);
648 
649     *ret = col;
650     return S_OK;
651 }
652 
653 static inline OmNavigator *impl_from_IOmNavigator(IOmNavigator *iface)
654 {
655     return CONTAINING_RECORD(iface, OmNavigator, IOmNavigator_iface);
656 }
657 
658 static HRESULT WINAPI OmNavigator_QueryInterface(IOmNavigator *iface, REFIID riid, void **ppv)
659 {
660     OmNavigator *This = impl_from_IOmNavigator(iface);
661 
662     TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
663 
664     if(IsEqualGUID(&IID_IUnknown, riid)) {
665         *ppv = &This->IOmNavigator_iface;
666     }else if(IsEqualGUID(&IID_IOmNavigator, riid)) {
667         *ppv = &This->IOmNavigator_iface;
668     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
669         return *ppv ? S_OK : E_NOINTERFACE;
670     }else {
671         WARN("Unsupported interface %s\n", debugstr_mshtml_guid(riid));
672         *ppv = NULL;
673         return E_NOINTERFACE;
674     }
675 
676     IUnknown_AddRef((IUnknown*)*ppv);
677     return S_OK;
678 }
679 
680 static ULONG WINAPI OmNavigator_AddRef(IOmNavigator *iface)
681 {
682     OmNavigator *This = impl_from_IOmNavigator(iface);
683     LONG ref = InterlockedIncrement(&This->ref);
684 
685     TRACE("(%p) ref=%d\n", This, ref);
686 
687     return ref;
688 }
689 
690 static ULONG WINAPI OmNavigator_Release(IOmNavigator *iface)
691 {
692     OmNavigator *This = impl_from_IOmNavigator(iface);
693     LONG ref = InterlockedDecrement(&This->ref);
694 
695     TRACE("(%p) ref=%d\n", This, ref);
696 
697     if(!ref) {
698         if(This->plugins)
699             This->plugins->navigator = NULL;
700         if(This->mime_types)
701             This->mime_types->navigator = NULL;
702         release_dispex(&This->dispex);
703         heap_free(This);
704     }
705 
706     return ref;
707 }
708 
709 static HRESULT WINAPI OmNavigator_GetTypeInfoCount(IOmNavigator *iface, UINT *pctinfo)
710 {
711     OmNavigator *This = impl_from_IOmNavigator(iface);
712     FIXME("(%p)->(%p)\n", This, pctinfo);
713     return E_NOTIMPL;
714 }
715 
716 static HRESULT WINAPI OmNavigator_GetTypeInfo(IOmNavigator *iface, UINT iTInfo,
717                                               LCID lcid, ITypeInfo **ppTInfo)
718 {
719     OmNavigator *This = impl_from_IOmNavigator(iface);
720 
721     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
722 }
723 
724 static HRESULT WINAPI OmNavigator_GetIDsOfNames(IOmNavigator *iface, REFIID riid,
725                                                 LPOLESTR *rgszNames, UINT cNames,
726                                                 LCID lcid, DISPID *rgDispId)
727 {
728     OmNavigator *This = impl_from_IOmNavigator(iface);
729 
730     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
731             lcid, rgDispId);
732 }
733 
734 static HRESULT WINAPI OmNavigator_Invoke(IOmNavigator *iface, DISPID dispIdMember,
735                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
736                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
737 {
738     OmNavigator *This = impl_from_IOmNavigator(iface);
739 
740     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid, wFlags,
741             pDispParams, pVarResult, pExcepInfo, puArgErr);
742 }
743 
744 static HRESULT WINAPI OmNavigator_get_appCodeName(IOmNavigator *iface, BSTR *p)
745 {
746     OmNavigator *This = impl_from_IOmNavigator(iface);
747 
748     static const WCHAR mozillaW[] = {'M','o','z','i','l','l','a',0};
749 
750     TRACE("(%p)->(%p)\n", This, p);
751 
752     *p = SysAllocString(mozillaW);
753     return S_OK;
754 }
755 
756 static HRESULT WINAPI OmNavigator_get_appName(IOmNavigator *iface, BSTR *p)
757 {
758     OmNavigator *This = impl_from_IOmNavigator(iface);
759 
760     static const WCHAR app_nameW[] =
761         {'M','i','c','r','o','s','o','f','t',' ',
762          'I','n','t','e','r','n','e','t',' ',
763          'E','x','p','l','o','r','e','r',0};
764 
765     TRACE("(%p)->(%p)\n", This, p);
766 
767     *p = SysAllocString(app_nameW);
768     if(!*p)
769         return E_OUTOFMEMORY;
770 
771     return S_OK;
772 }
773 
774 static HRESULT WINAPI OmNavigator_get_appVersion(IOmNavigator *iface, BSTR *p)
775 {
776     OmNavigator *This = impl_from_IOmNavigator(iface);
777 
778     char user_agent[512];
779     DWORD size;
780     HRESULT hres;
781 
782     TRACE("(%p)->(%p)\n", This, p);
783 
784     size = sizeof(user_agent);
785     hres = ObtainUserAgentString(0, user_agent, &size);
786     if(FAILED(hres))
787         return hres;
788 
789     if(strncmp(user_agent, "Mozilla/", 8)) {
790         FIXME("Unsupported user agent\n");
791         return E_FAIL;
792     }
793 
794     size = MultiByteToWideChar(CP_ACP, 0, user_agent+8, -1, NULL, 0);
795     *p = SysAllocStringLen(NULL, size-1);
796     if(!*p)
797         return E_OUTOFMEMORY;
798 
799     MultiByteToWideChar(CP_ACP, 0, user_agent+8, -1, *p, size);
800     return S_OK;
801 }
802 
803 static HRESULT WINAPI OmNavigator_get_userAgent(IOmNavigator *iface, BSTR *p)
804 {
805     OmNavigator *This = impl_from_IOmNavigator(iface);
806     char user_agent[512];
807     DWORD size;
808     HRESULT hres;
809 
810     TRACE("(%p)->(%p)\n", This, p);
811 
812     size = sizeof(user_agent);
813     hres = ObtainUserAgentString(0, user_agent, &size);
814     if(FAILED(hres))
815         return hres;
816 
817     size = MultiByteToWideChar(CP_ACP, 0, user_agent, -1, NULL, 0);
818     *p = SysAllocStringLen(NULL, size-1);
819     if(!*p)
820         return E_OUTOFMEMORY;
821 
822     MultiByteToWideChar(CP_ACP, 0, user_agent, -1, *p, size);
823     return S_OK;
824 }
825 
826 static HRESULT WINAPI OmNavigator_javaEnabled(IOmNavigator *iface, VARIANT_BOOL *enabled)
827 {
828     OmNavigator *This = impl_from_IOmNavigator(iface);
829 
830     FIXME("(%p)->(%p) semi-stub\n", This, enabled);
831 
832     *enabled = VARIANT_TRUE;
833     return S_OK;
834 }
835 
836 static HRESULT WINAPI OmNavigator_taintEnabled(IOmNavigator *iface, VARIANT_BOOL *enabled)
837 {
838     OmNavigator *This = impl_from_IOmNavigator(iface);
839     FIXME("(%p)->(%p)\n", This, enabled);
840     return E_NOTIMPL;
841 }
842 
843 static HRESULT WINAPI OmNavigator_get_mimeTypes(IOmNavigator *iface, IHTMLMimeTypesCollection **p)
844 {
845     OmNavigator *This = impl_from_IOmNavigator(iface);
846 
847     TRACE("(%p)->(%p)\n", This, p);
848 
849     if(!This->mime_types) {
850         HRESULT hres;
851 
852         hres = create_mime_types_collection(This, &This->mime_types);
853         if(FAILED(hres))
854             return hres;
855     }else {
856         IHTMLMimeTypesCollection_AddRef(&This->mime_types->IHTMLMimeTypesCollection_iface);
857     }
858 
859     *p = &This->mime_types->IHTMLMimeTypesCollection_iface;
860     return S_OK;
861 }
862 
863 static HRESULT WINAPI OmNavigator_get_plugins(IOmNavigator *iface, IHTMLPluginsCollection **p)
864 {
865     OmNavigator *This = impl_from_IOmNavigator(iface);
866 
867     TRACE("(%p)->(%p)\n", This, p);
868 
869     if(!This->plugins) {
870         HRESULT hres;
871 
872         hres = create_plugins_collection(This, &This->plugins);
873         if(FAILED(hres))
874             return hres;
875     }else {
876         IHTMLPluginsCollection_AddRef(&This->plugins->IHTMLPluginsCollection_iface);
877     }
878 
879     *p = &This->plugins->IHTMLPluginsCollection_iface;
880     return S_OK;
881 }
882 
883 static HRESULT WINAPI OmNavigator_get_cookieEnabled(IOmNavigator *iface, VARIANT_BOOL *p)
884 {
885     OmNavigator *This = impl_from_IOmNavigator(iface);
886 
887     WARN("(%p)->(%p) semi-stub\n", This, p);
888 
889     *p = VARIANT_TRUE;
890     return S_OK;
891 }
892 
893 static HRESULT WINAPI OmNavigator_get_opsProfile(IOmNavigator *iface, IHTMLOpsProfile **p)
894 {
895     OmNavigator *This = impl_from_IOmNavigator(iface);
896     FIXME("(%p)->(%p)\n", This, p);
897     return E_NOTIMPL;
898 }
899 
900 static HRESULT WINAPI OmNavigator_toString(IOmNavigator *iface, BSTR *String)
901 {
902     OmNavigator *This = impl_from_IOmNavigator(iface);
903 
904     static const WCHAR objectW[] = {'[','o','b','j','e','c','t',']',0};
905 
906     TRACE("(%p)->(%p)\n", This, String);
907 
908     if(!String)
909         return E_INVALIDARG;
910 
911     *String = SysAllocString(objectW);
912     return *String ? S_OK : E_OUTOFMEMORY;
913 }
914 
915 static HRESULT WINAPI OmNavigator_get_cpuClass(IOmNavigator *iface, BSTR *p)
916 {
917     OmNavigator *This = impl_from_IOmNavigator(iface);
918 
919     static const WCHAR cpu_classW[] =
920 #ifdef _WIN64
921         {'x','6','4',0};
922 #else
923         {'x','8','6',0};
924 #endif
925 
926     TRACE("(%p)->(%p)\n", This, p);
927 
928     *p = SysAllocString(cpu_classW);
929     return *p ? S_OK : E_OUTOFMEMORY;
930 }
931 
932 static HRESULT get_language_string(LCID lcid, BSTR *p)
933 {
934     BSTR ret;
935     int len;
936 
937     len = LCIDToLocaleName(lcid, NULL, 0, 0);
938     if(!len) {
939         WARN("LCIDToLocaleName failed: %u\n", GetLastError());
940         return E_FAIL;
941     }
942 
943     ret = SysAllocStringLen(NULL, len-1);
944     if(!ret)
945         return E_OUTOFMEMORY;
946 
947     len = LCIDToLocaleName(lcid, ret, len, 0);
948     if(!len) {
949         WARN("LCIDToLocaleName failed: %u\n", GetLastError());
950         SysFreeString(ret);
951         return E_FAIL;
952     }
953 
954     *p = ret;
955     return S_OK;
956 }
957 
958 static HRESULT WINAPI OmNavigator_get_systemLanguage(IOmNavigator *iface, BSTR *p)
959 {
960     OmNavigator *This = impl_from_IOmNavigator(iface);
961 
962     TRACE("(%p)->(%p)\n", This, p);
963 
964     return get_language_string(LOCALE_SYSTEM_DEFAULT, p);
965 }
966 
967 static HRESULT WINAPI OmNavigator_get_browserLanguage(IOmNavigator *iface, BSTR *p)
968 {
969     OmNavigator *This = impl_from_IOmNavigator(iface);
970 
971     TRACE("(%p)->(%p)\n", This, p);
972 
973     return get_language_string(GetUserDefaultUILanguage(), p);
974 }
975 
976 static HRESULT WINAPI OmNavigator_get_userLanguage(IOmNavigator *iface, BSTR *p)
977 {
978     OmNavigator *This = impl_from_IOmNavigator(iface);
979 
980     TRACE("(%p)->(%p)\n", This, p);
981 
982     return get_language_string(LOCALE_USER_DEFAULT, p);
983 }
984 
985 static HRESULT WINAPI OmNavigator_get_platform(IOmNavigator *iface, BSTR *p)
986 {
987     OmNavigator *This = impl_from_IOmNavigator(iface);
988 
989 #ifdef _WIN64
990     static const WCHAR platformW[] = {'W','i','n','6','4',0};
991 #else
992     static const WCHAR platformW[] = {'W','i','n','3','2',0};
993 #endif
994 
995     TRACE("(%p)->(%p)\n", This, p);
996 
997     *p = SysAllocString(platformW);
998     return S_OK;
999 }
1000 
1001 static HRESULT WINAPI OmNavigator_get_appMinorVersion(IOmNavigator *iface, BSTR *p)
1002 {
1003     OmNavigator *This = impl_from_IOmNavigator(iface);
1004 
1005     static const WCHAR zeroW[] = {'0',0};
1006 
1007     TRACE("(%p)->(%p)\n", This, p);
1008 
1009     /* NOTE: MSIE returns "0" or values like ";SP2;". Returning "0" should be enough. */
1010     *p = SysAllocString(zeroW);
1011     return S_OK;
1012 }
1013 
1014 static HRESULT WINAPI OmNavigator_get_connectionSpeed(IOmNavigator *iface, LONG *p)
1015 {
1016     OmNavigator *This = impl_from_IOmNavigator(iface);
1017     FIXME("(%p)->(%p)\n", This, p);
1018     return E_NOTIMPL;
1019 }
1020 
1021 static HRESULT WINAPI OmNavigator_get_onLine(IOmNavigator *iface, VARIANT_BOOL *p)
1022 {
1023     OmNavigator *This = impl_from_IOmNavigator(iface);
1024 
1025     WARN("(%p)->(%p) semi-stub, returning true\n", This, p);
1026 
1027     *p = VARIANT_TRUE;
1028     return S_OK;
1029 }
1030 
1031 static HRESULT WINAPI OmNavigator_get_userProfile(IOmNavigator *iface, IHTMLOpsProfile **p)
1032 {
1033     OmNavigator *This = impl_from_IOmNavigator(iface);
1034     FIXME("(%p)->(%p)\n", This, p);
1035     return E_NOTIMPL;
1036 }
1037 
1038 static const IOmNavigatorVtbl OmNavigatorVtbl = {
1039     OmNavigator_QueryInterface,
1040     OmNavigator_AddRef,
1041     OmNavigator_Release,
1042     OmNavigator_GetTypeInfoCount,
1043     OmNavigator_GetTypeInfo,
1044     OmNavigator_GetIDsOfNames,
1045     OmNavigator_Invoke,
1046     OmNavigator_get_appCodeName,
1047     OmNavigator_get_appName,
1048     OmNavigator_get_appVersion,
1049     OmNavigator_get_userAgent,
1050     OmNavigator_javaEnabled,
1051     OmNavigator_taintEnabled,
1052     OmNavigator_get_mimeTypes,
1053     OmNavigator_get_plugins,
1054     OmNavigator_get_cookieEnabled,
1055     OmNavigator_get_opsProfile,
1056     OmNavigator_toString,
1057     OmNavigator_get_cpuClass,
1058     OmNavigator_get_systemLanguage,
1059     OmNavigator_get_browserLanguage,
1060     OmNavigator_get_userLanguage,
1061     OmNavigator_get_platform,
1062     OmNavigator_get_appMinorVersion,
1063     OmNavigator_get_connectionSpeed,
1064     OmNavigator_get_onLine,
1065     OmNavigator_get_userProfile
1066 };
1067 
1068 static const tid_t OmNavigator_iface_tids[] = {
1069     IOmNavigator_tid,
1070     0
1071 };
1072 static dispex_static_data_t OmNavigator_dispex = {
1073     NULL,
1074     DispHTMLNavigator_tid,
1075     NULL,
1076     OmNavigator_iface_tids
1077 };
1078 
1079 IOmNavigator *OmNavigator_Create(void)
1080 {
1081     OmNavigator *ret;
1082 
1083     ret = heap_alloc_zero(sizeof(*ret));
1084     if(!ret)
1085         return NULL;
1086 
1087     ret->IOmNavigator_iface.lpVtbl = &OmNavigatorVtbl;
1088     ret->ref = 1;
1089 
1090     init_dispex(&ret->dispex, (IUnknown*)&ret->IOmNavigator_iface, &OmNavigator_dispex);
1091 
1092     return &ret->IOmNavigator_iface;
1093 }
1094