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