wined3d: Fix matching WINED3DDECLUSAGE_POSITION against WINED3DDECLUSAGE_POSITIONT.
[wine] / dlls / mshtml / nsembed.c
1 /*
2  * Copyright 2005-2006 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 "config.h"
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winuser.h"
28 #include "winreg.h"
29 #include "ole2.h"
30
31 #include "wine/debug.h"
32 #include "wine/unicode.h"
33
34 #include "mshtml_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 #define NS_APPSTARTUPNOTIFIER_CONTRACTID "@mozilla.org/embedcomp/appstartup-notifier;1"
39 #define NS_WEBBROWSER_CONTRACTID "@mozilla.org/embedding/browser/nsWebBrowser;1"
40 #define NS_PROFILE_CONTRACTID "@mozilla.org/profile/manager;1"
41 #define NS_MEMORY_CONTRACTID "@mozilla.org/xpcom/memory-service;1"
42 #define NS_STRINGSTREAM_CONTRACTID "@mozilla.org/io/string-input-stream;1"
43 #define NS_COMMANDPARAMS_CONTRACTID "@mozilla.org/embedcomp/command-params;1"
44 #define NS_HTMLSERIALIZER_CONTRACTID "@mozilla.org/layout/contentserializer;1?mimetype=text/html"
45
46 #define APPSTARTUP_TOPIC "app-startup"
47
48 #define PR_UINT32_MAX 0xffffffff
49
50 struct nsCStringContainer {
51     void *v;
52     void *d1;
53     PRUint32 d2;
54     void *d3;
55 };
56
57 static nsresult (*NS_InitXPCOM2)(nsIServiceManager**,void*,void*);
58 static nsresult (*NS_ShutdownXPCOM)(nsIServiceManager*);
59 static nsresult (*NS_GetComponentRegistrar)(nsIComponentRegistrar**);
60 static nsresult (*NS_StringContainerInit)(nsStringContainer*);
61 static nsresult (*NS_CStringContainerInit)(nsCStringContainer*);
62 static nsresult (*NS_StringContainerFinish)(nsStringContainer*);
63 static nsresult (*NS_CStringContainerFinish)(nsCStringContainer*);
64 static nsresult (*NS_StringSetData)(nsAString*,const PRUnichar*,PRUint32);
65 static nsresult (*NS_CStringSetData)(nsACString*,const char*,PRUint32);
66 static nsresult (*NS_NewLocalFile)(const nsAString*,PRBool,nsIFile**);
67 static PRUint32 (*NS_StringGetData)(const nsAString*,const PRUnichar **,PRBool*);
68 static PRUint32 (*NS_CStringGetData)(const nsACString*,const char**,PRBool*);
69
70 static HINSTANCE hXPCOM = NULL;
71
72 static nsIServiceManager *pServMgr = NULL;
73 static nsIComponentManager *pCompMgr = NULL;
74 static nsIMemory *nsmem = NULL;
75
76 static const WCHAR wszNsContainer[] = {'N','s','C','o','n','t','a','i','n','e','r',0};
77
78 static ATOM nscontainer_class;
79
80 static LRESULT WINAPI nsembed_proc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
81 {
82     NSContainer *This;
83     nsresult nsres;
84
85     static const WCHAR wszTHIS[] = {'T','H','I','S',0};
86
87     if(msg == WM_CREATE) {
88         This = *(NSContainer**)lParam;
89         SetPropW(hwnd, wszTHIS, This);
90     }else {
91         This = (NSContainer*)GetPropW(hwnd, wszTHIS);
92     }
93
94     switch(msg) {
95         case WM_SIZE:
96             TRACE("(%p)->(WM_SIZE)\n", This);
97
98             nsres = nsIBaseWindow_SetSize(This->window,
99                     LOWORD(lParam), HIWORD(lParam), TRUE);
100             if(NS_FAILED(nsres))
101                 WARN("SetSize failed: %08x\n", nsres);
102     }
103
104     return DefWindowProcW(hwnd, msg, wParam, lParam);
105 }
106
107
108 static void register_nscontainer_class(void)
109 {
110     static WNDCLASSEXW wndclass = {
111         sizeof(WNDCLASSEXW),
112         CS_DBLCLKS,
113         nsembed_proc,
114         0, 0, NULL, NULL, NULL, NULL, NULL,
115         wszNsContainer,
116         NULL,
117     };
118     wndclass.hInstance = hInst;
119     nscontainer_class = RegisterClassExW(&wndclass);
120 }
121
122 static BOOL load_xpcom(PRUnichar *gre_path)
123 {
124     WCHAR path_env[MAX_PATH];
125     int len;
126
127     static const WCHAR wszPATH[] = {'P','A','T','H',0};
128     static const WCHAR strXPCOM[] = {'x','p','c','o','m','.','d','l','l',0};
129
130     TRACE("(%s)\n", debugstr_w(gre_path));
131
132     /* We have to modify PATH as XPCOM loads other DLLs from this directory. */
133     GetEnvironmentVariableW(wszPATH, path_env, sizeof(path_env)/sizeof(WCHAR));
134     len = strlenW(path_env);
135     path_env[len++] = ';';
136     strcpyW(path_env+len, gre_path);
137     SetEnvironmentVariableW(wszPATH, path_env);
138
139     hXPCOM = LoadLibraryW(strXPCOM);
140     if(!hXPCOM) {
141         WARN("Could not load XPCOM: %d\n", GetLastError());
142         return FALSE;
143     }
144
145 #define NS_DLSYM(func) \
146     func = (typeof(func))GetProcAddress(hXPCOM, #func); \
147     if(!func) \
148         ERR("Could not GetProcAddress(" #func ") failed\n")
149
150     NS_DLSYM(NS_InitXPCOM2);
151     NS_DLSYM(NS_ShutdownXPCOM);
152     NS_DLSYM(NS_GetComponentRegistrar);
153     NS_DLSYM(NS_StringContainerInit);
154     NS_DLSYM(NS_CStringContainerInit);
155     NS_DLSYM(NS_StringContainerFinish);
156     NS_DLSYM(NS_CStringContainerFinish);
157     NS_DLSYM(NS_StringSetData);
158     NS_DLSYM(NS_CStringSetData);
159     NS_DLSYM(NS_NewLocalFile);
160     NS_DLSYM(NS_StringGetData);
161     NS_DLSYM(NS_CStringGetData);
162
163 #undef NS_DLSYM
164
165     return TRUE;
166 }
167
168 static BOOL load_mozilla(PRUnichar *gre_path)
169 {
170     DWORD res, type, i, size = MAX_PATH;
171     HKEY mozilla_key, hkey;
172     WCHAR key_name[100];
173     BOOL ret = FALSE;
174
175     static const WCHAR wszGreKey[] =
176         {'S','o','f','t','w','a','r','e','\\',
177             'm','o','z','i','l','l','a','.','o','r','g','\\',
178                 'G','R','E',0};
179
180     static const WCHAR wszGreHome[] = {'G','r','e','H','o','m','e',0};
181
182     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszGreKey, &mozilla_key);
183     if(res != ERROR_SUCCESS) {
184         TRACE("Could not open key %s\n", debugstr_w(wszGreKey));
185         return FALSE;
186     }
187
188     for(i=0; !ret && RegEnumKeyW(mozilla_key, i, key_name, sizeof(key_name)/sizeof(WCHAR)) == ERROR_SUCCESS; i++) {
189         RegOpenKeyW(mozilla_key, key_name, &hkey);
190         res = RegQueryValueExW(hkey, wszGreHome, NULL, &type, (LPBYTE)gre_path, &size);
191         if(res == ERROR_SUCCESS)
192             ret = TRUE;
193         RegCloseKey(hkey);
194     }
195
196     RegCloseKey(mozilla_key);
197     return ret ? load_xpcom(gre_path) : FALSE;
198 }
199
200 static BOOL load_mozctl(PRUnichar *gre_path)
201 {
202     HKEY hkey;
203     DWORD res, type, size = MAX_PATH;
204
205     static const WCHAR wszMozCtlKey[] =
206         {'S','o','f','t','w','a','r','e','\\','M','o','z','i','l','l','a',0};
207     static const WCHAR wszBinDirectoryPath[] =
208         {'B','i','n','D','i','r','e','c','t','o','r','y','P','a','t','h',0};
209     static const WCHAR wszMozCtlClsidKey[] =
210         {'C','L','S','I','D','\\',
211          '{','1','3','3','9','B','5','4','C','-','3','4','5','3','-','1','1','D','2',
212          '-','9','3','B','9','-','0','0','0','0','0','0','0','0','0','0','0','0','}','\\',
213          'I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
214
215     res = RegOpenKeyW(HKEY_LOCAL_MACHINE, wszMozCtlKey, &hkey);
216     if(res == ERROR_SUCCESS) {
217         res = RegQueryValueExW(hkey, wszBinDirectoryPath, NULL, &type, (LPBYTE)gre_path, &size);
218         if(res == ERROR_SUCCESS)
219             return load_xpcom(gre_path);
220         else
221             ERR("Could not get value %s\n", debugstr_w(wszBinDirectoryPath));
222     }
223
224     res = RegOpenKeyW(HKEY_CLASSES_ROOT, wszMozCtlClsidKey, &hkey);
225     if(res == ERROR_SUCCESS) {
226         res = RegQueryValueExW(hkey, NULL, NULL, &type, (LPBYTE)gre_path, &size);
227         if(res == ERROR_SUCCESS) {
228             WCHAR *ptr;
229             if((ptr = strrchrW(gre_path, '\\')))
230                 ptr[1] = 0;
231             return load_xpcom(gre_path);
232         }else {
233             ERR("Could not get value of %s\n", debugstr_w(wszMozCtlClsidKey));
234         }
235     }
236
237     TRACE("Could not find Mozilla ActiveX Control\n");
238
239     return FALSE;
240 }
241
242 static void check_version(LPCWSTR gre_path)
243 {
244     WCHAR file_name[MAX_PATH];
245     char version[128];
246     DWORD read=0;
247     HANDLE hfile;
248
249     static const WCHAR wszVersion[] = {'\\','V','E','R','S','I','O','N',0};
250
251     strcpyW(file_name, gre_path);
252     strcatW(file_name, wszVersion);
253
254     hfile = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
255                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
256     if(hfile == INVALID_HANDLE_VALUE) {
257         TRACE("unknown version\n");
258         return;
259     }
260
261     ReadFile(hfile, version, sizeof(version), &read, NULL);
262     version[read] = 0;
263
264     TRACE("%s\n", debugstr_a(version));
265
266     CloseHandle(hfile);
267 }
268
269 static BOOL load_wine_gecko(PRUnichar *gre_path)
270 {
271     HKEY hkey;
272     DWORD res, type, size = MAX_PATH;
273
274     static const WCHAR wszMshtmlKey[] = {
275         'S','o','f','t','w','a','r','e','\\','W','i','n','e',
276         '\\','M','S','H','T','M','L',0};
277     static const WCHAR wszGeckoPath[] =
278         {'G','e','c','k','o','P','a','t','h',0};
279
280     /* @@ Wine registry key: HKCU\Software\Wine\MSHTML */
281     res = RegOpenKeyW(HKEY_CURRENT_USER, wszMshtmlKey, &hkey);
282     if(res != ERROR_SUCCESS)
283         return FALSE;
284
285     res = RegQueryValueExW(hkey, wszGeckoPath, NULL, &type, (LPBYTE)gre_path, &size);
286     if(res != ERROR_SUCCESS || type != REG_SZ)
287         return FALSE;
288
289     if(TRACE_ON(mshtml))
290         check_version(gre_path);
291
292     return load_xpcom(gre_path);
293 }
294
295 static void set_profile(void)
296 {
297     nsIProfile *profile;
298     PRBool exists = FALSE;
299     nsresult nsres;
300
301     static const WCHAR wszMSHTML[] = {'M','S','H','T','M','L',0};
302
303     nsres = nsIServiceManager_GetServiceByContactID(pServMgr, NS_PROFILE_CONTRACTID,
304                                          &IID_nsIProfile, (void**)&profile);
305     if(NS_FAILED(nsres)) {
306         ERR("Could not get profile service: %08x\n", nsres);
307         return;
308     }
309
310     nsres = nsIProfile_ProfileExists(profile, wszMSHTML, &exists);
311     if(!exists) {
312         nsres = nsIProfile_CreateNewProfile(profile, wszMSHTML, NULL, NULL, FALSE);
313         if(NS_FAILED(nsres))
314             ERR("CreateNewProfile failed: %08x\n", nsres);
315     }
316
317     nsres = nsIProfile_SetCurrentProfile(profile, wszMSHTML);
318     if(NS_FAILED(nsres))
319         ERR("SetCurrentProfile failed: %08x\n", nsres);
320
321     nsIProfile_Release(profile);
322 }
323
324 static BOOL init_xpcom(PRUnichar *gre_path)
325 {
326     nsresult nsres;
327     nsIObserver *pStartNotif;
328     nsIComponentRegistrar *registrar = NULL;
329     nsAString path;
330     nsIFile *gre_dir;
331
332     nsAString_Init(&path, gre_path);
333     nsres = NS_NewLocalFile(&path, FALSE, &gre_dir);
334     nsAString_Finish(&path);
335     if(NS_FAILED(nsres)) {
336         ERR("NS_NewLocalFile failed: %08x\n", nsres);
337         FreeLibrary(hXPCOM);
338         return FALSE;
339     }
340
341     nsres = NS_InitXPCOM2(&pServMgr, gre_dir, NULL);
342     if(NS_FAILED(nsres)) {
343         ERR("NS_InitXPCOM2 failed: %08x\n", nsres);
344         FreeLibrary(hXPCOM);
345         return FALSE;
346     }
347
348     nsres = nsIServiceManager_QueryInterface(pServMgr, &IID_nsIComponentManager, (void**)&pCompMgr);
349     if(NS_FAILED(nsres))
350         ERR("Could not get nsIComponentManager: %08x\n", nsres);
351
352     nsres = NS_GetComponentRegistrar(&registrar);
353     if(NS_SUCCEEDED(nsres)) {
354         nsres = nsIComponentRegistrar_AutoRegister(registrar, NULL);
355         if(NS_FAILED(nsres))
356             ERR("AutoRegister(NULL) failed: %08x\n", nsres);
357
358         nsres = nsIComponentRegistrar_AutoRegister(registrar, gre_dir);
359         if(NS_FAILED(nsres))
360             ERR("AutoRegister(gre_dir) failed: %08x\n", nsres);
361
362         init_nsio(pCompMgr, registrar);
363     }else {
364         ERR("NS_GetComponentRegistrar failed: %08x\n", nsres);
365     }
366
367     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_APPSTARTUPNOTIFIER_CONTRACTID,
368             NULL, &IID_nsIObserver, (void**)&pStartNotif);
369     if(NS_SUCCEEDED(nsres)) {
370         nsres = nsIObserver_Observe(pStartNotif, NULL, APPSTARTUP_TOPIC, NULL);
371         if(NS_FAILED(nsres))
372             ERR("Observe failed: %08x\n", nsres);
373
374         nsIObserver_Release(pStartNotif);
375     }else {
376         ERR("could not get appstartup-notifier: %08x\n", nsres);
377     }
378
379     set_profile();
380
381     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_MEMORY_CONTRACTID,
382             NULL, &IID_nsIMemory, (void**)&nsmem);
383     if(NS_FAILED(nsres))
384         ERR("Could not get nsIMemory: %08x\n", nsres);
385
386     if(registrar) {
387         register_nsservice(registrar, pServMgr);
388         nsIComponentRegistrar_Release(registrar);
389     }
390
391     return TRUE;
392 }
393
394 static CRITICAL_SECTION cs_load_gecko;
395 static CRITICAL_SECTION_DEBUG cs_load_gecko_dbg =
396 {
397     0, 0, &cs_load_gecko,
398     { &cs_load_gecko_dbg.ProcessLocksList, &cs_load_gecko_dbg.ProcessLocksList },
399       0, 0, { (DWORD_PTR)(__FILE__ ": load_gecko") }
400 };
401 static CRITICAL_SECTION cs_load_gecko = { &cs_load_gecko_dbg, -1, 0, 0, 0, 0 };
402
403 static BOOL load_gecko(void)
404 {
405     PRUnichar gre_path[MAX_PATH];
406     BOOL ret = FALSE;
407
408     static LONG loading_thread;
409
410     TRACE("()\n");
411
412     /* load_gecko may be called recursively */
413     if(loading_thread == GetCurrentThreadId())
414         return pCompMgr != NULL;
415
416     EnterCriticalSection(&cs_load_gecko);
417
418     if(!loading_thread) {
419         loading_thread = GetCurrentThreadId();
420
421         if(load_wine_gecko(gre_path)
422            || load_mozctl(gre_path)
423            || load_mozilla(gre_path)
424            || (install_wine_gecko() && load_wine_gecko(gre_path)))
425             ret = init_xpcom(gre_path);
426         else
427            MESSAGE("Could not load Mozilla. HTML rendering will be disabled.\n");
428     }else {
429         ret = pCompMgr != NULL;
430     }
431
432     LeaveCriticalSection(&cs_load_gecko);
433
434     return ret;
435 }
436
437 void *nsalloc(size_t size)
438 {
439     return nsIMemory_Alloc(nsmem, size);
440 }
441
442 void nsfree(void *mem)
443 {
444     nsIMemory_Free(nsmem, mem);
445 }
446
447 void nsACString_Init(nsACString *str, const char *data)
448 {
449     NS_CStringContainerInit(str);
450     if(data)
451         nsACString_SetData(str, data);
452 }
453
454 void nsACString_SetData(nsACString *str, const char *data)
455 {
456     NS_CStringSetData(str, data, PR_UINT32_MAX);
457 }
458
459 PRUint32 nsACString_GetData(const nsACString *str, const char **data, PRBool *termited)
460 {
461     return NS_CStringGetData(str, data, termited);
462 }
463
464 void nsACString_Finish(nsACString *str)
465 {
466     NS_CStringContainerFinish(str);
467 }
468
469 void nsAString_Init(nsAString *str, const PRUnichar *data)
470 {
471     NS_StringContainerInit(str);
472     if(data)
473         NS_StringSetData(str, data, PR_UINT32_MAX);
474 }
475
476 PRUint32 nsAString_GetData(const nsAString *str, const PRUnichar **data, PRBool *termited)
477 {
478     return NS_StringGetData(str, data, termited);
479 }
480
481 void nsAString_Finish(nsAString *str)
482 {
483     NS_StringContainerFinish(str);
484 }
485
486 nsIInputStream *create_nsstream(const char *data, PRInt32 data_len)
487 {
488     nsIStringInputStream *ret;
489     nsresult nsres;
490
491     if(!pCompMgr)
492         return NULL;
493
494     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
495             NS_STRINGSTREAM_CONTRACTID, NULL, &IID_nsIStringInputStream,
496             (void**)&ret);
497     if(NS_FAILED(nsres)) {
498         ERR("Could not get nsIStringInputStream\n");
499         return NULL;
500     }
501
502     nsres = nsIStringInputStream_SetData(ret, data, data_len);
503     if(NS_FAILED(nsres)) {
504         ERR("AdoptData failed: %08x\n", nsres);
505         nsIStringInputStream_Release(ret);
506         return NULL;
507     }
508
509     return (nsIInputStream*)ret;
510 }
511
512 nsICommandParams *create_nscommand_params(void)
513 {
514     nsICommandParams *ret = NULL;
515     nsresult nsres;
516
517     if(!pCompMgr)
518         return NULL;
519
520     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
521             NS_COMMANDPARAMS_CONTRACTID, NULL, &IID_nsICommandParams,
522             (void**)&ret);
523     if(NS_FAILED(nsres))
524         ERR("Could not get nsICommandParams\n");
525
526     return ret;
527 }
528
529 static void nsnode_to_nsstring_rec(nsIContentSerializer *serializer, nsIDOMNode *nsnode, nsAString *str)
530 {
531     nsIDOMNodeList *node_list = NULL;
532     PRBool has_children = FALSE;
533     PRUint16 type;
534     nsresult nsres;
535
536     nsIDOMNode_HasChildNodes(nsnode, &has_children);
537
538     nsres = nsIDOMNode_GetNodeType(nsnode, &type);
539     if(NS_FAILED(nsres)) {
540         ERR("GetType failed: %08x\n", nsres);
541         return;
542     }
543
544     switch(type) {
545     case ELEMENT_NODE: {
546         nsIDOMElement *nselem;
547         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem);
548         nsIContentSerializer_AppendElementStart(serializer, nselem, has_children, str);
549         nsIDOMElement_Release(nselem);
550         break;
551     }
552     case TEXT_NODE: {
553         nsIDOMText *nstext;
554         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMText, (void**)&nstext);
555         nsIContentSerializer_AppendText(serializer, nstext, 0, -1, str);
556         nsIDOMText_Release(nstext);
557         break;
558     }
559     case DOCUMENT_NODE: {
560         nsIDOMDocument *nsdoc;
561         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMDocument, (void**)&nsdoc);
562         nsIContentSerializer_AppendDocumentStart(serializer, nsdoc, str);
563         nsIDOMDocument_Release(nsdoc);
564         break;
565     }
566     default:
567         FIXME("Unhandled type %u\n", type);
568     }
569
570     if(has_children) {
571         PRUint32 child_cnt, i;
572         nsIDOMNode *child_node;
573
574         nsIDOMNode_GetChildNodes(nsnode, &node_list);
575         nsIDOMNodeList_GetLength(node_list, &child_cnt);
576
577         for(i=0; i<child_cnt; i++) {
578             nsres = nsIDOMNodeList_Item(node_list, i, &child_node);
579             if(NS_SUCCEEDED(nsres)) {
580                 nsnode_to_nsstring_rec(serializer, child_node, str);
581                 nsIDOMNode_Release(child_node);
582             }else {
583                 ERR("Item failed: %08x\n", nsres);
584             }
585         }
586
587         nsIDOMNodeList_Release(node_list);
588     }
589
590     if(type == ELEMENT_NODE) {
591         nsIDOMElement *nselem;
592         nsIDOMNode_QueryInterface(nsnode, &IID_nsIDOMElement, (void**)&nselem);
593         nsIContentSerializer_AppendElementEnd(serializer, nselem, str);
594         nsIDOMElement_Release(nselem);
595     }
596 }
597
598 void nsnode_to_nsstring(nsIDOMNode *nsdoc, nsAString *str)
599 {
600     nsIContentSerializer *serializer;
601     nsIDOMNode *nsnode;
602     nsresult nsres;
603
604     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr,
605             NS_HTMLSERIALIZER_CONTRACTID, NULL, &IID_nsIContentSerializer,
606             (void**)&serializer);
607     if(NS_FAILED(nsres)) {
608         ERR("Could not get nsIContentSerializer: %08x\n", nsres);
609         return;
610     }
611
612     nsres = nsIContentSerializer_Init(serializer, 0, 100, NULL, FALSE);
613     if(NS_FAILED(nsres))
614         ERR("Init failed: %08x\n", nsres);
615
616     nsIDOMDocument_QueryInterface(nsdoc, &IID_nsIDOMNode, (void**)&nsnode);
617     nsnode_to_nsstring_rec(serializer, nsnode, str);
618     nsIDOMNode_Release(nsnode);
619
620     nsres = nsIContentSerializer_Flush(serializer, str);
621     if(NS_FAILED(nsres))
622         ERR("Flush failed: %08x\n", nsres);
623
624     nsIContentSerializer_Release(serializer);
625 }
626
627 void close_gecko()
628 {
629     TRACE("()\n");
630
631     if(pCompMgr)
632         nsIComponentManager_Release(pCompMgr);
633
634     if(pServMgr)
635         nsIServiceManager_Release(pServMgr);
636
637     if(nsmem)
638         nsIMemory_Release(nsmem);
639
640     if(hXPCOM)
641         FreeLibrary(hXPCOM);
642 }
643
644 /**********************************************************
645  *      nsIWebBrowserChrome interface
646  */
647
648 #define NSWBCHROME_THIS(iface) DEFINE_THIS(NSContainer, WebBrowserChrome, iface)
649
650 static nsresult NSAPI nsWebBrowserChrome_QueryInterface(nsIWebBrowserChrome *iface,
651         nsIIDRef riid, nsQIResult result)
652 {
653     NSContainer *This = NSWBCHROME_THIS(iface);
654
655     *result = NULL;
656     if(IsEqualGUID(&IID_nsISupports, riid)) {
657         TRACE("(%p)->(IID_nsISupports, %p)\n", This, result);
658         *result = NSWBCHROME(This);
659     }else if(IsEqualGUID(&IID_nsIWebBrowserChrome, riid)) {
660         TRACE("(%p)->(IID_nsIWebBrowserChrome, %p)\n", This, result);
661         *result = NSWBCHROME(This);
662     }else if(IsEqualGUID(&IID_nsIContextMenuListener, riid)) {
663         TRACE("(%p)->(IID_nsIContextMenuListener, %p)\n", This, result);
664         *result = NSCML(This);
665     }else if(IsEqualGUID(&IID_nsIURIContentListener, riid)) {
666         TRACE("(%p)->(IID_nsIURIContentListener %p)\n", This, result);
667         *result = NSURICL(This);
668     }else if(IsEqualGUID(&IID_nsIEmbeddingSiteWindow, riid)) {
669         TRACE("(%p)->(IID_nsIEmbeddingSiteWindow %p)\n", This, result);
670         *result = NSEMBWNDS(This);
671     }else if(IsEqualGUID(&IID_nsITooltipListener, riid)) {
672         TRACE("(%p)->(IID_nsITooltipListener %p)\n", This, result);
673         *result = NSTOOLTIP(This);
674     }else if(IsEqualGUID(&IID_nsIDOMEventListener, riid)) {
675         TRACE("(%p)->(IID_nsIDOMEventListener %p)\n", This, result);
676         *result = NSEVENTLIST(This);
677     }else if(IsEqualGUID(&IID_nsIInterfaceRequestor, riid)) {
678         TRACE("(%p)->(IID_nsIInterfaceRequestor %p)\n", This, result);
679         *result = NSIFACEREQ(This);
680     }else if(IsEqualGUID(&IID_nsIWeakReference, riid)) {
681         TRACE("(%p)->(IID_nsIWeakReference %p)\n", This, result);
682         *result = NSWEAKREF(This);
683     }else if(IsEqualGUID(&IID_nsISupportsWeakReference, riid)) {
684         TRACE("(%p)->(IID_nsISupportsWeakReference %p)\n", This, result);
685         *result = NSSUPWEAKREF(This);
686     }
687
688     if(*result) {
689         nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
690         return NS_OK;
691     }
692
693     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
694     return NS_NOINTERFACE;
695 }
696
697 static nsrefcnt NSAPI nsWebBrowserChrome_AddRef(nsIWebBrowserChrome *iface)
698 {
699     NSContainer *This = NSWBCHROME_THIS(iface);
700     LONG ref = InterlockedIncrement(&This->ref);
701
702     TRACE("(%p) ref=%d\n", This, ref);
703
704     return ref;
705 }
706
707 static nsrefcnt NSAPI nsWebBrowserChrome_Release(nsIWebBrowserChrome *iface)
708 {
709     NSContainer *This = NSWBCHROME_THIS(iface);
710     LONG ref = InterlockedDecrement(&This->ref);
711
712     TRACE("(%p) ref=%d\n", This, ref);
713
714     if(!ref) {
715         if(This->parent)
716             nsIWebBrowserChrome_Release(NSWBCHROME(This->parent));
717         mshtml_free(This);
718     }
719
720     return ref;
721 }
722
723 static nsresult NSAPI nsWebBrowserChrome_SetStatus(nsIWebBrowserChrome *iface,
724         PRUint32 statusType, const PRUnichar *status)
725 {
726     NSContainer *This = NSWBCHROME_THIS(iface);
727     TRACE("(%p)->(%d %s)\n", This, statusType, debugstr_w(status));
728     return NS_ERROR_NOT_IMPLEMENTED;
729 }
730
731 static nsresult NSAPI nsWebBrowserChrome_GetWebBrowser(nsIWebBrowserChrome *iface,
732         nsIWebBrowser **aWebBrowser)
733 {
734     NSContainer *This = NSWBCHROME_THIS(iface);
735
736     TRACE("(%p)->(%p)\n", This, aWebBrowser);
737
738     if(!aWebBrowser)
739         return NS_ERROR_INVALID_ARG;
740
741     if(This->webbrowser)
742         nsIWebBrowser_AddRef(This->webbrowser);
743     *aWebBrowser = This->webbrowser;
744     return S_OK;
745 }
746
747 static nsresult NSAPI nsWebBrowserChrome_SetWebBrowser(nsIWebBrowserChrome *iface,
748         nsIWebBrowser *aWebBrowser)
749 {
750     NSContainer *This = NSWBCHROME_THIS(iface);
751
752     TRACE("(%p)->(%p)\n", This, aWebBrowser);
753
754     if(aWebBrowser != This->webbrowser)
755         ERR("Wrong nsWebBrowser!\n");
756
757     return NS_OK;
758 }
759
760 static nsresult NSAPI nsWebBrowserChrome_GetChromeFlags(nsIWebBrowserChrome *iface,
761         PRUint32 *aChromeFlags)
762 {
763     NSContainer *This = NSWBCHROME_THIS(iface);
764     WARN("(%p)->(%p)\n", This, aChromeFlags);
765     return NS_ERROR_NOT_IMPLEMENTED;
766 }
767
768 static nsresult NSAPI nsWebBrowserChrome_SetChromeFlags(nsIWebBrowserChrome *iface,
769         PRUint32 aChromeFlags)
770 {
771     NSContainer *This = NSWBCHROME_THIS(iface);
772     WARN("(%p)->(%08x)\n", This, aChromeFlags);
773     return NS_ERROR_NOT_IMPLEMENTED;
774 }
775
776 static nsresult NSAPI nsWebBrowserChrome_DestroyBrowserWindow(nsIWebBrowserChrome *iface)
777 {
778     NSContainer *This = NSWBCHROME_THIS(iface);
779     TRACE("(%p)\n", This);
780     return NS_ERROR_NOT_IMPLEMENTED;
781 }
782
783 static nsresult NSAPI nsWebBrowserChrome_SizeBrowserTo(nsIWebBrowserChrome *iface,
784         PRInt32 aCX, PRInt32 aCY)
785 {
786     NSContainer *This = NSWBCHROME_THIS(iface);
787     WARN("(%p)->(%d %d)\n", This, aCX, aCY);
788     return NS_ERROR_NOT_IMPLEMENTED;
789 }
790
791 static nsresult NSAPI nsWebBrowserChrome_ShowAsModal(nsIWebBrowserChrome *iface)
792 {
793     NSContainer *This = NSWBCHROME_THIS(iface);
794     WARN("(%p)\n", This);
795     return NS_ERROR_NOT_IMPLEMENTED;
796 }
797
798 static nsresult NSAPI nsWebBrowserChrome_IsWindowModal(nsIWebBrowserChrome *iface, PRBool *_retval)
799 {
800     NSContainer *This = NSWBCHROME_THIS(iface);
801     WARN("(%p)->(%p)\n", This, _retval);
802     return NS_ERROR_NOT_IMPLEMENTED;
803 }
804
805 static nsresult NSAPI nsWebBrowserChrome_ExitModalEventLoop(nsIWebBrowserChrome *iface,
806         nsresult aStatus)
807 {
808     NSContainer *This = NSWBCHROME_THIS(iface);
809     WARN("(%p)->(%08x)\n", This, aStatus);
810     return NS_ERROR_NOT_IMPLEMENTED;
811 }
812
813 #undef NSWBCHROME_THIS
814
815 static const nsIWebBrowserChromeVtbl nsWebBrowserChromeVtbl = {
816     nsWebBrowserChrome_QueryInterface,
817     nsWebBrowserChrome_AddRef,
818     nsWebBrowserChrome_Release,
819     nsWebBrowserChrome_SetStatus,
820     nsWebBrowserChrome_GetWebBrowser,
821     nsWebBrowserChrome_SetWebBrowser,
822     nsWebBrowserChrome_GetChromeFlags,
823     nsWebBrowserChrome_SetChromeFlags,
824     nsWebBrowserChrome_DestroyBrowserWindow,
825     nsWebBrowserChrome_SizeBrowserTo,
826     nsWebBrowserChrome_ShowAsModal,
827     nsWebBrowserChrome_IsWindowModal,
828     nsWebBrowserChrome_ExitModalEventLoop
829 };
830
831 /**********************************************************
832  *      nsIContextMenuListener interface
833  */
834
835 #define NSCML_THIS(iface) DEFINE_THIS(NSContainer, ContextMenuListener, iface)
836
837 static nsresult NSAPI nsContextMenuListener_QueryInterface(nsIContextMenuListener *iface,
838         nsIIDRef riid, nsQIResult result)
839 {
840     NSContainer *This = NSCML_THIS(iface);
841     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
842 }
843
844 static nsrefcnt NSAPI nsContextMenuListener_AddRef(nsIContextMenuListener *iface)
845 {
846     NSContainer *This = NSCML_THIS(iface);
847     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
848 }
849
850 static nsrefcnt NSAPI nsContextMenuListener_Release(nsIContextMenuListener *iface)
851 {
852     NSContainer *This = NSCML_THIS(iface);
853     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
854 }
855
856 static nsresult NSAPI nsContextMenuListener_OnShowContextMenu(nsIContextMenuListener *iface,
857         PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
858 {
859     NSContainer *This = NSCML_THIS(iface);
860     nsIDOMMouseEvent *event;
861     POINT pt;
862     DWORD dwID = CONTEXT_MENU_DEFAULT;
863     nsresult nsres;
864
865     TRACE("(%p)->(%08x %p %p)\n", This, aContextFlags, aEvent, aNode);
866
867     nsres = nsIDOMEvent_QueryInterface(aEvent, &IID_nsIDOMMouseEvent, (void**)&event);
868     if(NS_FAILED(nsres)) {
869         ERR("Could not get nsIDOMMouseEvent interface: %08x\n", nsres);
870         return nsres;
871     }
872
873     nsIDOMMouseEvent_GetScreenX(event, &pt.x);
874     nsIDOMMouseEvent_GetScreenY(event, &pt.y);
875     nsIDOMMouseEvent_Release(event);
876
877     switch(aContextFlags) {
878     case CONTEXT_NONE:
879     case CONTEXT_DOCUMENT:
880     case CONTEXT_TEXT:
881         dwID = CONTEXT_MENU_DEFAULT;
882         break;
883     case CONTEXT_IMAGE:
884     case CONTEXT_IMAGE|CONTEXT_LINK:
885         dwID = CONTEXT_MENU_IMAGE;
886         break;
887     case CONTEXT_LINK:
888         dwID = CONTEXT_MENU_ANCHOR;
889         break;
890     case CONTEXT_INPUT:
891         dwID = CONTEXT_MENU_CONTROL;
892         break;
893     default:
894         FIXME("aContextFlags=%08x\n", aContextFlags);
895     };
896
897     HTMLDocument_ShowContextMenu(This->doc, dwID, &pt);
898
899     return NS_OK;
900 }
901
902 #undef NSCML_THIS
903
904 static const nsIContextMenuListenerVtbl nsContextMenuListenerVtbl = {
905     nsContextMenuListener_QueryInterface,
906     nsContextMenuListener_AddRef,
907     nsContextMenuListener_Release,
908     nsContextMenuListener_OnShowContextMenu
909 };
910
911 /**********************************************************
912  *      nsIURIContentListener interface
913  */
914
915 #define NSURICL_THIS(iface) DEFINE_THIS(NSContainer, URIContentListener, iface)
916
917 static nsresult NSAPI nsURIContentListener_QueryInterface(nsIURIContentListener *iface,
918         nsIIDRef riid, nsQIResult result)
919 {
920     NSContainer *This = NSURICL_THIS(iface);
921     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
922 }
923
924 static nsrefcnt NSAPI nsURIContentListener_AddRef(nsIURIContentListener *iface)
925 {
926     NSContainer *This = NSURICL_THIS(iface);
927     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
928 }
929
930 static nsrefcnt NSAPI nsURIContentListener_Release(nsIURIContentListener *iface)
931 {
932     NSContainer *This = NSURICL_THIS(iface);
933     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
934 }
935
936 static nsresult NSAPI nsURIContentListener_OnStartURIOpen(nsIURIContentListener *iface,
937                                                           nsIURI *aURI, PRBool *_retval)
938 {
939     NSContainer *This = NSURICL_THIS(iface);
940     nsIWineURI *wine_uri;
941     nsACString spec_str;
942     const char *spec;
943     nsresult nsres;
944
945     nsACString_Init(&spec_str, NULL);
946     nsIURI_GetSpec(aURI, &spec_str);
947     nsACString_GetData(&spec_str, &spec, NULL);
948
949     TRACE("(%p)->(%p(%s) %p)\n", This, aURI, debugstr_a(spec), _retval);
950
951     nsACString_Finish(&spec_str);
952
953     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
954     if(NS_FAILED(nsres)) {
955         WARN("Could not get nsIWineURI interface: %08x\n", nsres);
956         return NS_ERROR_NOT_IMPLEMENTED;
957     }
958
959     nsIWineURI_SetNSContainer(wine_uri, This);
960     nsIWineURI_SetIsDocumentURI(wine_uri, TRUE);
961
962     if(This->bscallback && This->bscallback->mon) {
963         LPWSTR wine_url;
964         HRESULT hres;
965
966         hres = IMoniker_GetDisplayName(This->bscallback->mon, NULL, 0, &wine_url);
967         if(SUCCEEDED(hres)) {
968             nsIWineURI_SetWineURL(wine_uri, wine_url);
969             CoTaskMemFree(wine_url);
970         }else {
971             WARN("GetDisplayName failed: %08x\n", hres);
972         }
973     }
974
975     nsIWineURI_Release(wine_uri);
976
977     *_retval = FALSE;
978     return This->content_listener
979         ? nsIURIContentListener_OnStartURIOpen(This->content_listener, aURI, _retval)
980         : NS_OK;
981 }
982
983 static nsresult NSAPI nsURIContentListener_DoContent(nsIURIContentListener *iface,
984         const char *aContentType, PRBool aIsContentPreferred, nsIRequest *aRequest,
985         nsIStreamListener **aContentHandler, PRBool *_retval)
986 {
987     NSContainer *This = NSURICL_THIS(iface);
988
989     TRACE("(%p)->(%s %x %p %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
990             aRequest, aContentHandler, _retval);
991
992     return This->content_listener
993         ? nsIURIContentListener_DoContent(This->content_listener, aContentType,
994                   aIsContentPreferred, aRequest, aContentHandler, _retval)
995         : NS_ERROR_NOT_IMPLEMENTED;
996 }
997
998 static nsresult NSAPI nsURIContentListener_IsPreferred(nsIURIContentListener *iface,
999         const char *aContentType, char **aDesiredContentType, PRBool *_retval)
1000 {
1001     NSContainer *This = NSURICL_THIS(iface);
1002
1003     TRACE("(%p)->(%s %p %p)\n", This, debugstr_a(aContentType), aDesiredContentType, _retval);
1004
1005     /* FIXME: Should we do something here? */
1006     *_retval = TRUE; 
1007
1008     return This->content_listener
1009         ? nsIURIContentListener_IsPreferred(This->content_listener, aContentType,
1010                   aDesiredContentType, _retval)
1011         : NS_OK;
1012 }
1013
1014 static nsresult NSAPI nsURIContentListener_CanHandleContent(nsIURIContentListener *iface,
1015         const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType,
1016         PRBool *_retval)
1017 {
1018     NSContainer *This = NSURICL_THIS(iface);
1019
1020     TRACE("(%p)->(%s %x %p %p)\n", This, debugstr_a(aContentType), aIsContentPreferred,
1021             aDesiredContentType, _retval);
1022
1023     return This->content_listener
1024         ? nsIURIContentListener_CanHandleContent(This->content_listener, aContentType,
1025                 aIsContentPreferred, aDesiredContentType, _retval)
1026         : NS_ERROR_NOT_IMPLEMENTED;
1027 }
1028
1029 static nsresult NSAPI nsURIContentListener_GetLoadCookie(nsIURIContentListener *iface,
1030         nsISupports **aLoadCookie)
1031 {
1032     NSContainer *This = NSURICL_THIS(iface);
1033
1034     WARN("(%p)->(%p)\n", This, aLoadCookie);
1035
1036     return This->content_listener
1037         ? nsIURIContentListener_GetLoadCookie(This->content_listener, aLoadCookie)
1038         : NS_ERROR_NOT_IMPLEMENTED;
1039 }
1040
1041 static nsresult NSAPI nsURIContentListener_SetLoadCookie(nsIURIContentListener *iface,
1042         nsISupports *aLoadCookie)
1043 {
1044     NSContainer *This = NSURICL_THIS(iface);
1045
1046     WARN("(%p)->(%p)\n", This, aLoadCookie);
1047
1048     return This->content_listener
1049         ? nsIURIContentListener_SetLoadCookie(This->content_listener, aLoadCookie)
1050         : NS_ERROR_NOT_IMPLEMENTED;
1051 }
1052
1053 static nsresult NSAPI nsURIContentListener_GetParentContentListener(nsIURIContentListener *iface,
1054         nsIURIContentListener **aParentContentListener)
1055 {
1056     NSContainer *This = NSURICL_THIS(iface);
1057
1058     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1059
1060     if(This->content_listener)
1061         nsIURIContentListener_AddRef(This->content_listener);
1062
1063     *aParentContentListener = This->content_listener;
1064     return NS_OK;
1065 }
1066
1067 static nsresult NSAPI nsURIContentListener_SetParentContentListener(nsIURIContentListener *iface,
1068         nsIURIContentListener *aParentContentListener)
1069 {
1070     NSContainer *This = NSURICL_THIS(iface);
1071
1072     TRACE("(%p)->(%p)\n", This, aParentContentListener);
1073
1074     if(aParentContentListener == NSURICL(This))
1075         return NS_OK;
1076
1077     if(This->content_listener)
1078         nsIURIContentListener_Release(This->content_listener);
1079
1080     This->content_listener = aParentContentListener;
1081     if(This->content_listener)
1082         nsIURIContentListener_AddRef(This->content_listener);
1083
1084     return NS_OK;
1085 }
1086
1087 #undef NSURICL_THIS
1088
1089 static const nsIURIContentListenerVtbl nsURIContentListenerVtbl = {
1090     nsURIContentListener_QueryInterface,
1091     nsURIContentListener_AddRef,
1092     nsURIContentListener_Release,
1093     nsURIContentListener_OnStartURIOpen,
1094     nsURIContentListener_DoContent,
1095     nsURIContentListener_IsPreferred,
1096     nsURIContentListener_CanHandleContent,
1097     nsURIContentListener_GetLoadCookie,
1098     nsURIContentListener_SetLoadCookie,
1099     nsURIContentListener_GetParentContentListener,
1100     nsURIContentListener_SetParentContentListener
1101 };
1102
1103 /**********************************************************
1104  *      nsIEmbeddinSiteWindow interface
1105  */
1106
1107 #define NSEMBWNDS_THIS(iface) DEFINE_THIS(NSContainer, EmbeddingSiteWindow, iface)
1108
1109 static nsresult NSAPI nsEmbeddingSiteWindow_QueryInterface(nsIEmbeddingSiteWindow *iface,
1110         nsIIDRef riid, nsQIResult result)
1111 {
1112     NSContainer *This = NSEMBWNDS_THIS(iface);
1113     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1114 }
1115
1116 static nsrefcnt NSAPI nsEmbeddingSiteWindow_AddRef(nsIEmbeddingSiteWindow *iface)
1117 {
1118     NSContainer *This = NSEMBWNDS_THIS(iface);
1119     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1120 }
1121
1122 static nsrefcnt NSAPI nsEmbeddingSiteWindow_Release(nsIEmbeddingSiteWindow *iface)
1123 {
1124     NSContainer *This = NSEMBWNDS_THIS(iface);
1125     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1126 }
1127
1128 static nsresult NSAPI nsEmbeddingSiteWindow_SetDimensions(nsIEmbeddingSiteWindow *iface,
1129         PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
1130 {
1131     NSContainer *This = NSEMBWNDS_THIS(iface);
1132     WARN("(%p)->(%08x %d %d %d %d)\n", This, flags, x, y, cx, cy);
1133     return NS_ERROR_NOT_IMPLEMENTED;
1134 }
1135
1136 static nsresult NSAPI nsEmbeddingSiteWindow_GetDimensions(nsIEmbeddingSiteWindow *iface,
1137         PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
1138 {
1139     NSContainer *This = NSEMBWNDS_THIS(iface);
1140     WARN("(%p)->(%08x %p %p %p %p)\n", This, flags, x, y, cx, cy);
1141     return NS_ERROR_NOT_IMPLEMENTED;
1142 }
1143
1144 static nsresult NSAPI nsEmbeddingSiteWindow_SetFocus(nsIEmbeddingSiteWindow *iface)
1145 {
1146     NSContainer *This = NSEMBWNDS_THIS(iface);
1147     WARN("(%p)\n", This);
1148     return NS_ERROR_NOT_IMPLEMENTED;
1149 }
1150
1151 static nsresult NSAPI nsEmbeddingSiteWindow_GetVisibility(nsIEmbeddingSiteWindow *iface,
1152         PRBool *aVisibility)
1153 {
1154     NSContainer *This = NSEMBWNDS_THIS(iface);
1155     WARN("(%p)->(%p)\n", This, aVisibility);
1156     return NS_ERROR_NOT_IMPLEMENTED;
1157 }
1158
1159 static nsresult NSAPI nsEmbeddingSiteWindow_SetVisibility(nsIEmbeddingSiteWindow *iface,
1160         PRBool aVisibility)
1161 {
1162     NSContainer *This = NSEMBWNDS_THIS(iface);
1163     WARN("(%p)->(%x)\n", This, aVisibility);
1164     return NS_ERROR_NOT_IMPLEMENTED;
1165 }
1166
1167 static nsresult NSAPI nsEmbeddingSiteWindow_GetTitle(nsIEmbeddingSiteWindow *iface,
1168         PRUnichar **aTitle)
1169 {
1170     NSContainer *This = NSEMBWNDS_THIS(iface);
1171     WARN("(%p)->(%p)\n", This, aTitle);
1172     return NS_ERROR_NOT_IMPLEMENTED;
1173 }
1174
1175 static nsresult NSAPI nsEmbeddingSiteWindow_SetTitle(nsIEmbeddingSiteWindow *iface,
1176         const PRUnichar *aTitle)
1177 {
1178     NSContainer *This = NSEMBWNDS_THIS(iface);
1179     WARN("(%p)->(%s)\n", This, debugstr_w(aTitle));
1180     return NS_ERROR_NOT_IMPLEMENTED;
1181 }
1182
1183 static nsresult NSAPI nsEmbeddingSiteWindow_GetSiteWindow(nsIEmbeddingSiteWindow *iface,
1184         void **aSiteWindow)
1185 {
1186     NSContainer *This = NSEMBWNDS_THIS(iface);
1187
1188     TRACE("(%p)->(%p)\n", This, aSiteWindow);
1189
1190     *aSiteWindow = This->hwnd;
1191     return NS_OK;
1192 }
1193
1194 static const nsIEmbeddingSiteWindowVtbl nsEmbeddingSiteWindowVtbl = {
1195     nsEmbeddingSiteWindow_QueryInterface,
1196     nsEmbeddingSiteWindow_AddRef,
1197     nsEmbeddingSiteWindow_Release,
1198     nsEmbeddingSiteWindow_SetDimensions,
1199     nsEmbeddingSiteWindow_GetDimensions,
1200     nsEmbeddingSiteWindow_SetFocus,
1201     nsEmbeddingSiteWindow_GetVisibility,
1202     nsEmbeddingSiteWindow_SetVisibility,
1203     nsEmbeddingSiteWindow_GetTitle,
1204     nsEmbeddingSiteWindow_SetTitle,
1205     nsEmbeddingSiteWindow_GetSiteWindow
1206 };
1207
1208 #define NSTOOLTIP_THIS(iface) DEFINE_THIS(NSContainer, TooltipListener, iface)
1209
1210 static nsresult NSAPI nsTooltipListener_QueryInterface(nsITooltipListener *iface, nsIIDRef riid,
1211                                                        nsQIResult result)
1212 {
1213     NSContainer *This = NSTOOLTIP_THIS(iface);
1214     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1215 }
1216
1217 static nsrefcnt NSAPI nsTooltipListener_AddRef(nsITooltipListener *iface)
1218 {
1219     NSContainer *This = NSTOOLTIP_THIS(iface);
1220     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1221 }
1222
1223 static nsrefcnt NSAPI nsTooltipListener_Release(nsITooltipListener *iface)
1224 {
1225     NSContainer *This = NSTOOLTIP_THIS(iface);
1226     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1227 }
1228
1229 static nsresult NSAPI nsTooltipListener_OnShowTooltip(nsITooltipListener *iface,
1230         PRInt32 aXCoord, PRInt32 aYCoord, const PRUnichar *aTipText)
1231 {
1232     NSContainer *This = NSTOOLTIP_THIS(iface);
1233
1234     show_tooltip(This->doc, aXCoord, aYCoord, aTipText);
1235
1236     return NS_OK;
1237 }
1238
1239 static nsresult NSAPI nsTooltipListener_OnHideTooltip(nsITooltipListener *iface)
1240 {
1241     NSContainer *This = NSTOOLTIP_THIS(iface);
1242
1243     hide_tooltip(This->doc);
1244
1245     return NS_OK;
1246 }
1247
1248 #undef NSTOOLTIM_THIS
1249
1250 static const nsITooltipListenerVtbl nsTooltipListenerVtbl = {
1251     nsTooltipListener_QueryInterface,
1252     nsTooltipListener_AddRef,
1253     nsTooltipListener_Release,
1254     nsTooltipListener_OnShowTooltip,
1255     nsTooltipListener_OnHideTooltip
1256 };
1257
1258 #define NSEVENTLIST_THIS(iface) DEFINE_THIS(NSContainer, DOMEventListener, iface)
1259
1260 static nsresult NSAPI nsDOMEventListener_QueryInterface(nsIDOMEventListener *iface,
1261                                                         nsIIDRef riid, nsQIResult result)
1262 {
1263     NSContainer *This = NSEVENTLIST_THIS(iface);
1264     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1265 }
1266
1267 static nsrefcnt NSAPI nsDOMEventListener_AddRef(nsIDOMEventListener *iface)
1268 {
1269     NSContainer *This = NSEVENTLIST_THIS(iface);
1270     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1271 }
1272
1273 static nsrefcnt NSAPI nsDOMEventListener_Release(nsIDOMEventListener *iface)
1274 {
1275     NSContainer *This = NSEVENTLIST_THIS(iface);
1276     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1277 }
1278
1279 static nsresult NSAPI nsDOMEventListener_HandleEvent(nsIDOMEventListener *iface, nsIDOMEvent *event)
1280 {
1281     NSContainer *This = NSEVENTLIST_THIS(iface);
1282
1283     TRACE("(%p)->(%p)\n", This, event);
1284
1285     if(This->doc->usermode == EDITMODE)
1286         handle_edit_event(This->doc, event);
1287
1288     return NS_OK;
1289 }
1290
1291 #undef NSEVENTLIST_THIS
1292
1293 static const nsIDOMEventListenerVtbl nsDOMEventListenerVtbl = {
1294     nsDOMEventListener_QueryInterface,
1295     nsDOMEventListener_AddRef,
1296     nsDOMEventListener_Release,
1297     nsDOMEventListener_HandleEvent
1298 };
1299
1300 #define NSIFACEREQ_THIS(iface) DEFINE_THIS(NSContainer, InterfaceRequestor, iface)
1301
1302 static nsresult NSAPI nsInterfaceRequestor_QueryInterface(nsIInterfaceRequestor *iface,
1303                                                           nsIIDRef riid, nsQIResult result)
1304 {
1305     NSContainer *This = NSIFACEREQ_THIS(iface);
1306     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1307 }
1308
1309 static nsrefcnt NSAPI nsInterfaceRequestor_AddRef(nsIInterfaceRequestor *iface)
1310 {
1311     NSContainer *This = NSIFACEREQ_THIS(iface);
1312     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1313 }
1314
1315 static nsrefcnt NSAPI nsInterfaceRequestor_Release(nsIInterfaceRequestor *iface)
1316 {
1317     NSContainer *This = NSIFACEREQ_THIS(iface);
1318     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1319 }
1320
1321 static nsresult NSAPI nsInterfaceRequestor_GetInterface(nsIInterfaceRequestor *iface,
1322                                                         nsIIDRef riid, nsQIResult result)
1323 {
1324     NSContainer *This = NSIFACEREQ_THIS(iface);
1325
1326     if(IsEqualGUID(&IID_nsIDOMWindow, riid)) {
1327         TRACE("(%p)->(IID_nsIDOMWindow %p)\n", This, result);
1328         return nsIWebBrowser_GetContentDOMWindow(This->webbrowser, (nsIDOMWindow**)result);
1329     }
1330
1331     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1332 }
1333
1334 #undef NSIFACEREQ_THIS
1335
1336 static const nsIInterfaceRequestorVtbl nsInterfaceRequestorVtbl = {
1337     nsInterfaceRequestor_QueryInterface,
1338     nsInterfaceRequestor_AddRef,
1339     nsInterfaceRequestor_Release,
1340     nsInterfaceRequestor_GetInterface
1341 };
1342
1343 #define NSWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, WeakReference, iface)
1344
1345 static nsresult NSAPI nsWeakReference_QueryInterface(nsIWeakReference *iface,
1346         nsIIDRef riid, nsQIResult result)
1347 {
1348     NSContainer *This = NSWEAKREF_THIS(iface);
1349     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1350 }
1351
1352 static nsrefcnt NSAPI nsWeakReference_AddRef(nsIWeakReference *iface)
1353 {
1354     NSContainer *This = NSWEAKREF_THIS(iface);
1355     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1356 }
1357
1358 static nsrefcnt NSAPI nsWeakReference_Release(nsIWeakReference *iface)
1359 {
1360     NSContainer *This = NSWEAKREF_THIS(iface);
1361     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1362 }
1363
1364 static nsresult NSAPI nsWeakReference_QueryReferent(nsIWeakReference *iface,
1365         const nsIID *riid, void **result)
1366 {
1367     NSContainer *This = NSWEAKREF_THIS(iface);
1368     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1369 }
1370
1371 #undef NSWEAKREF_THIS
1372
1373 static const nsIWeakReferenceVtbl nsWeakReferenceVtbl = {
1374     nsWeakReference_QueryInterface,
1375     nsWeakReference_AddRef,
1376     nsWeakReference_Release,
1377     nsWeakReference_QueryReferent
1378 };
1379
1380 #define NSSUPWEAKREF_THIS(iface) DEFINE_THIS(NSContainer, SupportsWeakReference, iface)
1381
1382 static nsresult NSAPI nsSupportsWeakReference_QueryInterface(nsISupportsWeakReference *iface,
1383         nsIIDRef riid, nsQIResult result)
1384 {
1385     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1386     return nsIWebBrowserChrome_QueryInterface(NSWBCHROME(This), riid, result);
1387 }
1388
1389 static nsrefcnt NSAPI nsSupportsWeakReference_AddRef(nsISupportsWeakReference *iface)
1390 {
1391     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1392     return nsIWebBrowserChrome_AddRef(NSWBCHROME(This));
1393 }
1394
1395 static nsrefcnt NSAPI nsSupportsWeakReference_Release(nsISupportsWeakReference *iface)
1396 {
1397     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1398     return nsIWebBrowserChrome_Release(NSWBCHROME(This));
1399 }
1400
1401 static nsresult NSAPI nsSupportsWeakReference_GetWeakReference(nsISupportsWeakReference *iface,
1402         nsIWeakReference **_retval)
1403 {
1404     NSContainer *This = NSSUPWEAKREF_THIS(iface);
1405
1406     TRACE("(%p)->(%p)\n", This, _retval);
1407
1408     nsIWeakReference_AddRef(NSWEAKREF(This));
1409     *_retval = NSWEAKREF(This);
1410     return NS_OK;
1411 }
1412
1413 #undef NSWEAKREF_THIS
1414
1415 static const nsISupportsWeakReferenceVtbl nsSupportsWeakReferenceVtbl = {
1416     nsSupportsWeakReference_QueryInterface,
1417     nsSupportsWeakReference_AddRef,
1418     nsSupportsWeakReference_Release,
1419     nsSupportsWeakReference_GetWeakReference
1420 };
1421
1422
1423 NSContainer *NSContainer_Create(HTMLDocument *doc, NSContainer *parent)
1424 {
1425     nsIDOMWindow *dom_window;
1426     nsIWebBrowserSetup *wbsetup;
1427     NSContainer *ret;
1428     nsresult nsres;
1429
1430     if(!load_gecko())
1431         return NULL;
1432
1433     ret = mshtml_alloc(sizeof(NSContainer));
1434
1435     ret->lpWebBrowserChromeVtbl      = &nsWebBrowserChromeVtbl;
1436     ret->lpContextMenuListenerVtbl   = &nsContextMenuListenerVtbl;
1437     ret->lpURIContentListenerVtbl    = &nsURIContentListenerVtbl;
1438     ret->lpEmbeddingSiteWindowVtbl   = &nsEmbeddingSiteWindowVtbl;
1439     ret->lpTooltipListenerVtbl       = &nsTooltipListenerVtbl;
1440     ret->lpInterfaceRequestorVtbl    = &nsInterfaceRequestorVtbl;
1441     ret->lpWeakReferenceVtbl         = &nsWeakReferenceVtbl;
1442     ret->lpSupportsWeakReferenceVtbl = &nsSupportsWeakReferenceVtbl;
1443     ret->lpDOMEventListenerVtbl      = &nsDOMEventListenerVtbl;
1444
1445     ret->doc = doc;
1446     ret->ref = 1;
1447     ret->bscallback = NULL;
1448     ret->content_listener = NULL;
1449
1450     if(parent)
1451         nsIWebBrowserChrome_AddRef(NSWBCHROME(parent));
1452     ret->parent = parent;
1453
1454     nsres = nsIComponentManager_CreateInstanceByContractID(pCompMgr, NS_WEBBROWSER_CONTRACTID,
1455             NULL, &IID_nsIWebBrowser, (void**)&ret->webbrowser);
1456     if(NS_FAILED(nsres))
1457         ERR("Creating WebBrowser failed: %08x\n", nsres);
1458
1459     nsres = nsIWebBrowser_SetContainerWindow(ret->webbrowser, NSWBCHROME(ret));
1460     if(NS_FAILED(nsres))
1461         ERR("SetContainerWindow failed: %08x\n", nsres);
1462
1463     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIBaseWindow,
1464             (void**)&ret->window);
1465     if(NS_FAILED(nsres))
1466         ERR("Could not get nsIBaseWindow interface: %08x\n", nsres);
1467
1468     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserSetup,
1469                                          (void**)&wbsetup);
1470     if(NS_SUCCEEDED(nsres)) {
1471         nsres = nsIWebBrowserSetup_SetProperty(wbsetup, SETUP_IS_CHROME_WRAPPER, TRUE);
1472         nsIWebBrowserSetup_Release(wbsetup);
1473         if(NS_FAILED(nsres))
1474             ERR("SetProperty(SETUP_IS_CHROME_WRAPPER) failed: %08x\n", nsres);
1475     }else {
1476         ERR("Could not get nsIWebBrowserSetup interface\n");
1477     }
1478
1479     nsres = nsIWebBrowser_QueryInterface(ret->webbrowser, &IID_nsIWebNavigation,
1480             (void**)&ret->navigation);
1481     if(NS_FAILED(nsres))
1482         ERR("Could not get nsIWebNavigation interface: %08x\n", nsres);
1483
1484     nsres = nsIWebBrowserFocus_QueryInterface(ret->webbrowser, &IID_nsIWebBrowserFocus,
1485             (void**)&ret->focus);
1486     if(NS_FAILED(nsres))
1487         ERR("Could not get nsIWebBrowserFocus interface: %08x\n", nsres);
1488
1489     if(!nscontainer_class)
1490         register_nscontainer_class();
1491
1492     ret->hwnd = CreateWindowExW(0, wszNsContainer, NULL,
1493             WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, 0, 0, 100, 100,
1494             GetDesktopWindow(), NULL, hInst, ret);
1495
1496     nsres = nsIBaseWindow_InitWindow(ret->window, ret->hwnd, NULL, 0, 0, 100, 100);
1497     if(NS_SUCCEEDED(nsres)) {
1498         nsres = nsIBaseWindow_Create(ret->window);
1499         if(NS_FAILED(nsres))
1500             WARN("Creating window failed: %08x\n", nsres);
1501
1502         nsIBaseWindow_SetVisibility(ret->window, FALSE);
1503         nsIBaseWindow_SetEnabled(ret->window, FALSE);
1504     }else {
1505         ERR("InitWindow failed: %08x\n", nsres);
1506     }
1507
1508     nsres = nsIWebBrowser_SetParentURIContentListener(ret->webbrowser, NSURICL(ret));
1509     if(NS_FAILED(nsres))
1510         ERR("SetParentURIContentListener failed: %08x\n", nsres);
1511
1512     nsres = nsIWebBrowser_GetContentDOMWindow(ret->webbrowser, &dom_window);
1513     if(NS_SUCCEEDED(nsres)) {
1514         nsIDOMEventTarget *target;
1515         nsres = nsIDOMWindow_QueryInterface(dom_window, &IID_nsIDOMEventTarget, (void**)&target);
1516         nsIDOMWindow_Release(dom_window);
1517         if(NS_SUCCEEDED(nsres)) {
1518             nsAString keypress_str;
1519             static const PRUnichar wsz_keypress[] = {'k','e','y','p','r','e','s','s',0};
1520             nsAString_Init(&keypress_str, wsz_keypress);
1521             nsres = nsIDOMEventTarget_AddEventListener(target, &keypress_str, NSEVENTLIST(ret), TRUE);
1522             nsAString_Finish(&keypress_str);
1523             nsIDOMEventTarget_Release(target);
1524             if(NS_FAILED(nsres))
1525                 ERR("AddEventTarget failed: %08x\n", nsres);
1526         }else {
1527             ERR("Could not get nsIDOMEventTarget interface: %08x\n", nsres);
1528         }
1529     }else {
1530         ERR("GetContentDOMWindow failed: %08x\n", nsres);
1531     }
1532
1533     return ret;
1534 }
1535
1536 void NSContainer_Release(NSContainer *This)
1537 {
1538     TRACE("(%p)\n", This);
1539
1540     ShowWindow(This->hwnd, SW_HIDE);
1541     SetParent(This->hwnd, NULL);
1542
1543     nsIBaseWindow_SetVisibility(This->window, FALSE);
1544     nsIBaseWindow_Destroy(This->window);
1545
1546     nsIWebBrowser_SetContainerWindow(This->webbrowser, NULL);
1547
1548     nsIWebBrowser_Release(This->webbrowser);
1549     This->webbrowser = NULL;
1550
1551     nsIWebNavigation_Release(This->navigation);
1552     This->navigation = NULL;
1553
1554     nsIBaseWindow_Release(This->window);
1555     This->window = NULL;
1556
1557     nsIWebBrowserFocus_Release(This->focus);
1558     This->focus = NULL;
1559
1560     if(This->content_listener) {
1561         nsIURIContentListener_Release(This->content_listener);
1562         This->content_listener = NULL;
1563     }
1564
1565     if(This->hwnd) {
1566         DestroyWindow(This->hwnd);
1567         This->hwnd = NULL;
1568     }
1569
1570     nsIWebBrowserChrome_Release(NSWBCHROME(This));
1571 }