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