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