dbghelp: Check for NULL return from process_find_by_handle (Coverity).
[wine] / dlls / mshtml / nsio.c
1 /*
2  * Copyright 2006-2007 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 #include "shlguid.h"
31 #include "wininet.h"
32 #include "shlwapi.h"
33
34 #include "wine/debug.h"
35 #include "wine/unicode.h"
36
37 #include "mshtml_private.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
40
41 #define LOAD_INITIAL_DOCUMENT_URI 0x80000
42
43 #define NS_IOSERVICE_CLASSNAME "nsIOService"
44 #define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1"
45
46 static const IID NS_IOSERVICE_CID =
47     {0x9ac9e770, 0x18bc, 0x11d3, {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40}};
48
49 static nsIIOService *nsio = NULL;
50 static nsINetUtil *net_util;
51
52 static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
53
54 typedef struct {
55     const nsIWineURIVtbl *lpWineURIVtbl;
56
57     LONG ref;
58
59     nsIURI *uri;
60     nsIURL *nsurl;
61     NSContainer *container;
62     windowref_t *window_ref;
63     LPWSTR wine_url;
64     PRBool is_doc_uri;
65     BOOL use_wine_url;
66 } nsURI;
67
68 #define NSURI(x)         ((nsIURI*)            &(x)->lpWineURIVtbl)
69 #define NSWINEURI(x)     ((nsIWineURI*)        &(x)->lpWineURIVtbl)
70
71 static nsresult create_uri(nsIURI*,HTMLWindow*,NSContainer*,nsIWineURI**);
72
73 static const char *debugstr_nsacstr(const nsACString *nsstr)
74 {
75     const char *data;
76
77     nsACString_GetData(nsstr, &data);
78     return debugstr_a(data);
79 }
80
81 HRESULT nsuri_to_url(LPCWSTR nsuri, BOOL ret_empty, BSTR *ret)
82 {
83     const WCHAR *ptr = nsuri;
84
85     static const WCHAR wine_prefixW[] = {'w','i','n','e',':'};
86
87     if(!strncmpW(nsuri, wine_prefixW, sizeof(wine_prefixW)/sizeof(WCHAR)))
88         ptr += sizeof(wine_prefixW)/sizeof(WCHAR);
89
90     if(*ptr || ret_empty) {
91         *ret = SysAllocString(ptr);
92         if(!*ret)
93             return E_OUTOFMEMORY;
94     }else {
95         *ret = NULL;
96     }
97
98     TRACE("%s -> %s\n", debugstr_w(nsuri), debugstr_w(*ret));
99     return S_OK;
100 }
101
102 static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, LPCWSTR url)
103 {
104     IOleCommandTarget *cmdtrg = NULL;
105     HRESULT hres;
106
107     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
108     if(SUCCEEDED(hres)) {
109         VARIANT varUrl, varRes;
110
111         V_VT(&varUrl) = VT_BSTR;
112         V_BSTR(&varUrl) = SysAllocString(url);
113         V_VT(&varRes) = VT_BOOL;
114
115         hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes);
116
117         IOleCommandTarget_Release(cmdtrg);
118         SysFreeString(V_BSTR(&varUrl));
119
120         if(SUCCEEDED(hres) && !V_BOOL(&varRes)) {
121             TRACE("got VARIANT_FALSE, do not load\n");
122             return FALSE;
123         }
124     }
125
126     return TRUE;
127 }
128
129 static BOOL before_async_open(nsChannel *channel, NSContainer *container)
130 {
131     HTMLDocumentObj *doc = container->doc;
132     DWORD hlnf = 0;
133     LPCWSTR uri;
134     HRESULT hres;
135
136     nsIWineURI_GetWineURL(channel->uri, &uri);
137     if(!uri) {
138         ERR("GetWineURL returned NULL\n");
139         return TRUE;
140     }
141
142     if(!doc) {
143         NSContainer *container_iter = container;
144
145         hlnf = HLNF_OPENINNEWWINDOW;
146         while(!container_iter->doc)
147             container_iter = container_iter->parent;
148         doc = container_iter->doc;
149     }
150
151     if(!doc->client)
152         return TRUE;
153
154     if(!hlnf && !exec_shldocvw_67(doc, uri))
155         return FALSE;
156
157     hres = hlink_frame_navigate(&doc->basedoc, uri, channel->post_data_stream, hlnf);
158     return hres != S_OK;
159 }
160
161 static inline BOOL is_http_channel(nsChannel *This)
162 {
163     return This->url_scheme == URL_SCHEME_HTTP || This->url_scheme == URL_SCHEME_HTTP;
164 }
165
166 #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
167
168 static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, nsQIResult result)
169 {
170     nsChannel *This = NSCHANNEL_THIS(iface);
171
172     if(IsEqualGUID(&IID_nsISupports, riid)) {
173         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
174         *result = NSCHANNEL(This);
175     }else if(IsEqualGUID(&IID_nsIRequest, riid)) {
176         TRACE("(%p)->(IID_nsIRequest %p)\n", This, result);
177         *result = NSCHANNEL(This);
178     }else if(IsEqualGUID(&IID_nsIChannel, riid)) {
179         TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
180         *result = NSCHANNEL(This);
181     }else if(IsEqualGUID(&IID_nsIHttpChannel, riid)) {
182         TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
183         *result = is_http_channel(This) ? NSHTTPCHANNEL(This) : NULL;
184     }else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) {
185         TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result);
186         *result = NSUPCHANNEL(This);
187     }else if(IsEqualGUID(&IID_nsIHttpChannelInternal, riid)) {
188         TRACE("(%p)->(IID_nsIHttpChannelInternal %p)\n", This, result);
189         *result = is_http_channel(This) ? NSHTTPINTERNAL(This) : NULL;
190     }else {
191         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
192         *result = NULL;
193     }
194
195     if(*result) {
196         nsIChannel_AddRef(NSCHANNEL(This));
197         return NS_OK;
198     }
199
200     return NS_NOINTERFACE;
201 }
202
203 static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
204 {
205     nsChannel *This = NSCHANNEL_THIS(iface);
206     nsrefcnt ref = InterlockedIncrement(&This->ref);
207
208     TRACE("(%p) ref=%d\n", This, ref);
209
210     return ref;
211 }
212
213 static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
214 {
215     nsChannel *This = NSCHANNEL_THIS(iface);
216     LONG ref = InterlockedDecrement(&This->ref);
217
218     if(!ref) {
219         nsIWineURI_Release(This->uri);
220         if(This->channel)
221             nsIChannel_Release(This->channel);
222         if(This->http_channel)
223             nsIHttpChannel_Release(This->http_channel);
224         if(This->http_channel_internal)
225             nsIHttpChannel_Release(This->http_channel_internal);
226         if(This->owner)
227             nsISupports_Release(This->owner);
228         if(This->post_data_stream)
229             nsIInputStream_Release(This->post_data_stream);
230         if(This->load_group)
231             nsILoadGroup_Release(This->load_group);
232         if(This->notif_callback)
233             nsIInterfaceRequestor_Release(This->notif_callback);
234         if(This->original_uri)
235             nsIURI_Release(This->original_uri);
236         heap_free(This->content_type);
237         heap_free(This->charset);
238         heap_free(This);
239     }
240
241     return ref;
242 }
243
244 static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName)
245 {
246     nsChannel *This = NSCHANNEL_THIS(iface);
247
248     TRACE("(%p)->(%p)\n", This, aName);
249
250     if(This->channel)
251         return nsIChannel_GetName(This->channel, aName);
252
253     return NS_ERROR_NOT_IMPLEMENTED;
254 }
255
256 static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, PRBool *_retval)
257 {
258     nsChannel *This = NSCHANNEL_THIS(iface);
259
260     TRACE("(%p)->(%p)\n", This, _retval);
261
262     if(This->channel)
263         return nsIChannel_IsPending(This->channel, _retval);
264
265     FIXME("default action not implemented\n");
266     return NS_ERROR_NOT_IMPLEMENTED;
267 }
268
269 static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus)
270 {
271     nsChannel *This = NSCHANNEL_THIS(iface);
272
273     TRACE("(%p)->(%p)\n", This, aStatus);
274
275     if(This->channel)
276         return nsIChannel_GetStatus(This->channel, aStatus);
277
278     TRACE("returning NS_OK\n");
279     return *aStatus = NS_OK;
280 }
281
282 static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus)
283 {
284     nsChannel *This = NSCHANNEL_THIS(iface);
285
286     TRACE("(%p)->(%08x)\n", This, aStatus);
287
288     if(This->channel)
289         return nsIChannel_Cancel(This->channel, aStatus);
290
291     FIXME("default action not implemented\n");
292     return NS_ERROR_NOT_IMPLEMENTED;
293 }
294
295 static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface)
296 {
297     nsChannel *This = NSCHANNEL_THIS(iface);
298
299     TRACE("(%p)\n", This);
300
301     if(This->channel)
302         return nsIChannel_Suspend(This->channel);
303
304     FIXME("default action not implemented\n");
305     return NS_ERROR_NOT_IMPLEMENTED;
306 }
307
308 static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface)
309 {
310     nsChannel *This = NSCHANNEL_THIS(iface);
311
312     TRACE("(%p)\n", This);
313
314     if(This->channel)
315         return nsIChannel_Resume(This->channel);
316
317     FIXME("default action not implemented\n");
318     return NS_ERROR_NOT_IMPLEMENTED;
319 }
320
321 static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup)
322 {
323     nsChannel *This = NSCHANNEL_THIS(iface);
324
325     TRACE("(%p)->(%p)\n", This, aLoadGroup);
326
327     if(This->load_group)
328         nsILoadGroup_AddRef(This->load_group);
329
330     *aLoadGroup = This->load_group;
331     return NS_OK;
332 }
333
334 static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup)
335 {
336     nsChannel *This = NSCHANNEL_THIS(iface);
337
338     TRACE("(%p)->(%p)\n", This, aLoadGroup);
339
340     if(This->load_group)
341         nsILoadGroup_Release(This->load_group);
342     if(aLoadGroup)
343         nsILoadGroup_AddRef(aLoadGroup);
344
345     This->load_group = aLoadGroup;
346
347     if(This->channel)
348         return nsIChannel_SetLoadGroup(This->channel, aLoadGroup);
349     return NS_OK;
350 }
351
352 static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags)
353 {
354     nsChannel *This = NSCHANNEL_THIS(iface);
355
356     TRACE("(%p)->(%p)\n", This, aLoadFlags);
357
358     *aLoadFlags = This->load_flags;
359     return NS_OK;
360 }
361
362 static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags)
363 {
364     nsChannel *This = NSCHANNEL_THIS(iface);
365
366     TRACE("(%p)->(%08x)\n", This, aLoadFlags);
367
368     This->load_flags = aLoadFlags;
369
370     if(This->channel)
371         return nsIChannel_SetLoadFlags(This->channel, aLoadFlags);
372     return NS_OK;
373 }
374
375 static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI)
376 {
377     nsChannel *This = NSCHANNEL_THIS(iface);
378
379     TRACE("(%p)->(%p)\n", This, aOriginalURI);
380
381     if(This->original_uri)
382         nsIURI_AddRef(This->original_uri);
383
384     *aOriginalURI = This->original_uri;
385     return NS_OK;
386 }
387
388 static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI)
389 {
390     nsChannel *This = NSCHANNEL_THIS(iface);
391
392     TRACE("(%p)->(%p)\n", This, aOriginalURI);
393
394     if(This->original_uri)
395         nsIURI_Release(This->original_uri);
396
397     nsIURI_AddRef(aOriginalURI);
398     This->original_uri = aOriginalURI;
399
400     if(This->channel)
401         return nsIChannel_SetOriginalURI(This->channel, aOriginalURI);
402     return NS_OK;
403 }
404
405 static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI)
406 {
407     nsChannel *This = NSCHANNEL_THIS(iface);
408
409     TRACE("(%p)->(%p)\n", This, aURI);
410
411     nsIWineURI_AddRef(This->uri);
412     *aURI = (nsIURI*)This->uri;
413
414     return NS_OK;
415 }
416
417 static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner)
418 {
419     nsChannel *This = NSCHANNEL_THIS(iface);
420
421     TRACE("(%p)->(%p)\n", This, aOwner);
422
423     if(This->channel)
424         return nsIChannel_GetOwner(This->channel, aOwner);
425
426     if(This->owner)
427         nsISupports_AddRef(This->owner);
428     *aOwner = This->owner;
429
430     return NS_OK;
431 }
432
433 static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner)
434 {
435     nsChannel *This = NSCHANNEL_THIS(iface);
436
437     TRACE("(%p)->(%p)\n", This, aOwner);
438
439     if(This->channel)
440         return nsIChannel_SetOwner(This->channel, aOwner);
441
442     if(aOwner)
443         nsISupports_AddRef(aOwner);
444     if(This->owner)
445         nsISupports_Release(This->owner);
446     This->owner = aOwner;
447
448     return NS_OK;
449 }
450
451 static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface,
452         nsIInterfaceRequestor **aNotificationCallbacks)
453 {
454     nsChannel *This = NSCHANNEL_THIS(iface);
455
456     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
457
458     if(This->notif_callback)
459         nsIInterfaceRequestor_AddRef(This->notif_callback);
460     *aNotificationCallbacks = This->notif_callback;
461
462     return NS_OK;
463 }
464
465 static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface,
466         nsIInterfaceRequestor *aNotificationCallbacks)
467 {
468     nsChannel *This = NSCHANNEL_THIS(iface);
469
470     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
471
472     if(This->notif_callback)
473         nsIInterfaceRequestor_Release(This->notif_callback);
474     if(aNotificationCallbacks)
475         nsIInterfaceRequestor_AddRef(aNotificationCallbacks);
476
477     This->notif_callback = aNotificationCallbacks;
478
479     if(This->channel)
480         return nsIChannel_SetNotificationCallbacks(This->channel, aNotificationCallbacks);
481     return NS_OK;
482 }
483
484 static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo)
485 {
486     nsChannel *This = NSCHANNEL_THIS(iface);
487
488     TRACE("(%p)->(%p)\n", This, aSecurityInfo);
489
490     if(This->channel)
491         return nsIChannel_GetSecurityInfo(This->channel, aSecurityInfo);
492
493     FIXME("default action not implemented\n");
494     return NS_ERROR_NOT_IMPLEMENTED;
495 }
496
497 static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType)
498 {
499     nsChannel *This = NSCHANNEL_THIS(iface);
500
501     TRACE("(%p)->(%p)\n", This, aContentType);
502
503     if(This->content_type) {
504         nsACString_SetData(aContentType, This->content_type);
505         return S_OK;
506     }
507
508     if(This->channel)
509         return nsIChannel_GetContentType(This->channel, aContentType);
510
511     WARN("unknown type\n");
512     return NS_ERROR_FAILURE;
513 }
514
515 static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface,
516                                                const nsACString *aContentType)
517 {
518     nsChannel *This = NSCHANNEL_THIS(iface);
519     const char *content_type;
520
521     TRACE("(%p)->(%p)\n", This, aContentType);
522
523     nsACString_GetData(aContentType, &content_type);
524
525     TRACE("content_type %s\n", content_type);
526
527     heap_free(This->content_type);
528     This->content_type = heap_strdupA(content_type);
529
530     if(This->channel)
531         return nsIChannel_SetContentType(This->channel, aContentType);
532
533     return NS_OK;
534 }
535
536 static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface,
537                                                   nsACString *aContentCharset)
538 {
539     nsChannel *This = NSCHANNEL_THIS(iface);
540
541     TRACE("(%p)->(%p)\n", This, aContentCharset);
542
543     if(This->charset) {
544         nsACString_SetData(aContentCharset, This->charset);
545         return NS_OK;
546     }
547
548     if(This->channel) {
549         nsresult nsres = nsIChannel_GetContentCharset(This->channel, aContentCharset);
550         const char *ch;
551         nsACString_GetData(aContentCharset, &ch);
552         return nsres;
553     }
554
555     nsACString_SetData(aContentCharset, "");
556     return NS_OK;
557 }
558
559 static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface,
560                                                   const nsACString *aContentCharset)
561 {
562     nsChannel *This = NSCHANNEL_THIS(iface);
563
564     TRACE("(%p)->(%p)\n", This, aContentCharset);
565
566     if(This->channel)
567         return nsIChannel_SetContentCharset(This->channel, aContentCharset);
568
569     FIXME("default action not implemented\n");
570     return NS_ERROR_NOT_IMPLEMENTED;
571 }
572
573 static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength)
574 {
575     nsChannel *This = NSCHANNEL_THIS(iface);
576
577     TRACE("(%p)->(%p)\n", This, aContentLength);
578
579     if(This->channel)
580         return nsIChannel_GetContentLength(This->channel, aContentLength);
581
582     FIXME("default action not implemented\n");
583     return NS_ERROR_NOT_IMPLEMENTED;
584 }
585
586 static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength)
587 {
588     nsChannel *This = NSCHANNEL_THIS(iface);
589
590     TRACE("(%p)->(%d)\n", This, aContentLength);
591
592     if(This->channel)
593         return nsIChannel_SetContentLength(This->channel, aContentLength);
594
595     FIXME("default action not implemented\n");
596     return NS_ERROR_NOT_IMPLEMENTED;
597 }
598
599 static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval)
600 {
601     nsChannel *This = NSCHANNEL_THIS(iface);
602
603     TRACE("(%p)->(%p)\n", This, _retval);
604
605     if(This->channel)
606         return nsIChannel_Open(This->channel, _retval);
607
608     FIXME("default action not implemented\n");
609     return NS_ERROR_NOT_IMPLEMENTED;
610 }
611
612 static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
613 {
614     nsIWineURI *wine_uri;
615     LPCWSTR wine_url;
616     nsresult nsres;
617     HRESULT hres;
618
619     if(!channel->original_uri) {
620         ERR("original_uri == NULL\n");
621         return E_FAIL;
622     }
623
624     nsres = nsIURI_QueryInterface(channel->original_uri, &IID_nsIWineURI, (void**)&wine_uri);
625     if(NS_FAILED(nsres)) {
626         ERR("Could not get nsIWineURI: %08x\n", nsres);
627         return E_FAIL;
628     }
629
630     nsIWineURI_GetWineURL(wine_uri, &wine_url);
631     nsIWineURI_Release(wine_uri);
632     if(!wine_url) {
633         TRACE("wine_url == NULL\n");
634         return E_FAIL;
635     }
636
637     hres = CreateURLMoniker(NULL, wine_url, mon);
638     if(FAILED(hres))
639         WARN("CreateURLMoniker failed: %08x\n", hres);
640
641     return hres;
642 }
643
644 static HTMLWindow *get_window_from_load_group(nsChannel *This)
645 {
646     HTMLWindow *window;
647     nsIChannel *channel;
648     nsIRequest *req;
649     nsIWineURI *wine_uri;
650     nsIURI *uri;
651     nsresult nsres;
652
653     nsres = nsILoadGroup_GetDefaultLoadRequest(This->load_group, &req);
654     if(NS_FAILED(nsres)) {
655         ERR("GetDefaultLoadRequest failed: %08x\n", nsres);
656         return NULL;
657     }
658
659     if(!req)
660         return NULL;
661
662     nsres = nsIRequest_QueryInterface(req, &IID_nsIChannel, (void**)&channel);
663     nsIRequest_Release(req);
664     if(NS_FAILED(nsres)) {
665         WARN("Could not get nsIChannel interface: %08x\n", nsres);
666         return NULL;
667     }
668
669     nsres = nsIChannel_GetURI(channel, &uri);
670     nsIChannel_Release(channel);
671     if(NS_FAILED(nsres)) {
672         ERR("GetURI failed: %08x\n", nsres);
673         return NULL;
674     }
675
676     nsres = nsIURI_QueryInterface(uri, &IID_nsIWineURI, (void**)&wine_uri);
677     nsIURI_Release(uri);
678     if(NS_FAILED(nsres)) {
679         TRACE("Could not get nsIWineURI: %08x\n", nsres);
680         return NULL;
681     }
682
683     nsIWineURI_GetWindow(wine_uri, &window);
684     nsIWineURI_Release(wine_uri);
685
686     return window;
687 }
688
689 static HTMLWindow *get_channel_window(nsChannel *This)
690 {
691     nsIRequestObserver *req_observer;
692     nsIWebProgress *web_progress;
693     nsIDOMWindow *nswindow;
694     HTMLWindow *window;
695     nsresult nsres;
696
697     if(!This->load_group) {
698         ERR("NULL load_group\n");
699         return NULL;
700     }
701
702     nsres = nsILoadGroup_GetGroupObserver(This->load_group, &req_observer);
703     if(NS_FAILED(nsres) || !req_observer) {
704         ERR("GetGroupObserver failed: %08x\n", nsres);
705         return NULL;
706     }
707
708     nsres = nsIRequestObserver_QueryInterface(req_observer, &IID_nsIWebProgress, (void**)&web_progress);
709     nsIRequestObserver_Release(req_observer);
710     if(NS_FAILED(nsres)) {
711         ERR("Could not get nsIWebProgress iface: %08x\n", nsres);
712         return NULL;
713     }
714
715     nsres = nsIWebProgress_GetDOMWindow(web_progress, &nswindow);
716     nsIWebProgress_Release(web_progress);
717     if(NS_FAILED(nsres) || !nswindow) {
718         ERR("GetDOMWindow failed: %08x\n", nsres);
719         return NULL;
720     }
721
722     window = nswindow_to_window(nswindow);
723     nsIDOMWindow_Release(nswindow);
724
725     if(window)
726         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
727     else
728         FIXME("NULL window for %p\n", nswindow);
729     return window;
730 }
731
732 typedef struct {
733     task_t header;
734     HTMLDocumentNode *doc;
735     nsChannelBSC *bscallback;
736 } start_binding_task_t;
737
738 static void start_binding_proc(task_t *_task)
739 {
740     start_binding_task_t *task = (start_binding_task_t*)_task;
741
742     start_binding(NULL, task->doc, (BSCallback*)task->bscallback, NULL);
743 }
744
745 typedef struct {
746     task_t header;
747     HTMLWindow *window;
748     nsChannelBSC *bscallback;
749 } start_doc_binding_task_t;
750
751 static void start_doc_binding_proc(task_t *_task)
752 {
753     start_doc_binding_task_t *task = (start_doc_binding_task_t*)_task;
754
755     start_binding(task->window, NULL, (BSCallback*)task->bscallback, NULL);
756     IUnknown_Release((IUnknown*)task->bscallback);
757 }
758
759 static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_channel, nsIStreamListener *listener,
760         nsISupports *context)
761 {
762     nsChannelBSC *bscallback;
763     IMoniker *mon = NULL;
764     HRESULT hres;
765
766     hres = create_mon_for_nschannel(This, &mon);
767     if(FAILED(hres))
768         return NS_ERROR_UNEXPECTED;
769
770     if(is_doc_channel)
771         set_current_mon(window, mon);
772
773     bscallback = create_channelbsc(mon);
774     IMoniker_Release(mon);
775
776     channelbsc_set_channel(bscallback, This, listener, context);
777
778     if(is_doc_channel) {
779         start_doc_binding_task_t *task;
780
781         set_window_bscallback(window, bscallback);
782
783         task = heap_alloc(sizeof(start_doc_binding_task_t));
784         task->window = window;
785         task->bscallback = bscallback;
786         push_task(&task->header, start_doc_binding_proc, window->task_magic);
787     }else {
788         start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t));
789
790         task->doc = window->doc;
791         task->bscallback = bscallback;
792         push_task(&task->header, start_binding_proc, window->doc->basedoc.task_magic);
793     }
794
795     return NS_OK;
796 }
797
798 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
799                                           nsISupports *aContext)
800 {
801     nsChannel *This = NSCHANNEL_THIS(iface);
802     HTMLWindow *window = NULL;
803     PRBool is_doc_uri;
804     BOOL open = TRUE;
805     nsresult nsres = NS_OK;
806
807     TRACE("(%p)->(%p %p)\n", This, aListener, aContext);
808
809     if(TRACE_ON(mshtml)) {
810         LPCWSTR url;
811
812         nsIWineURI_GetWineURL(This->uri, &url);
813         TRACE("opening %s\n", debugstr_w(url));
814     }
815
816     nsIWineURI_GetIsDocumentURI(This->uri, &is_doc_uri);
817     if(is_doc_uri) {
818         window = get_channel_window(This);
819         if(window) {
820             nsIWineURI_SetWindow(This->uri, window);
821         }else {
822             NSContainer *nscontainer;
823
824             nsIWineURI_GetNSContainer(This->uri, &nscontainer);
825             if(nscontainer) {
826                 BOOL b;
827
828                 /* nscontainer->doc should be NULL which means navigation to a new window */
829                 if(nscontainer->doc)
830                     FIXME("nscontainer->doc = %p\n", nscontainer->doc);
831
832                 b = before_async_open(This, nscontainer);
833                 nsIWebBrowserChrome_Release(NSWBCHROME(nscontainer));
834                 if(b)
835                     FIXME("Navigation not cancelled\n");
836                 return NS_ERROR_UNEXPECTED;
837             }
838         }
839     }
840
841     if(!window) {
842         nsIWineURI_GetWindow(This->uri, &window);
843
844         if(!window && This->load_group) {
845             window = get_window_from_load_group(This);
846             if(window)
847                 nsIWineURI_SetWindow(This->uri, window);
848         }
849     }
850
851     if(!window) {
852         ERR("window = NULL\n");
853         return This->channel
854             ? nsIChannel_AsyncOpen(This->channel, aListener, aContext)
855             : NS_ERROR_UNEXPECTED;
856     }
857
858     if(is_doc_uri && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI) && window == window->doc_obj->basedoc.window) {
859         if(window->doc_obj->nscontainer->bscallback) {
860             NSContainer *nscontainer = window->doc_obj->nscontainer;
861
862             channelbsc_set_channel(nscontainer->bscallback, This, aListener, aContext);
863
864             if(nscontainer->doc->mime) {
865                 heap_free(This->content_type);
866                 This->content_type = heap_strdupWtoA(nscontainer->doc->mime);
867             }
868
869             open = FALSE;
870         }else {
871             open = before_async_open(This, window->doc_obj->nscontainer);
872             if(!open) {
873                 TRACE("canceled\n");
874                 nsres = NS_ERROR_UNEXPECTED;
875             }
876         }
877     }
878
879     if(open)
880         nsres = async_open(This, window, is_doc_uri, aListener, aContext);
881
882     if(window)
883         IHTMLWindow2_Release(HTMLWINDOW2(window));
884     return nsres;
885 }
886
887 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
888 {
889     nsChannel *This = NSCHANNEL_THIS(iface);
890
891     TRACE("(%p)->(%p)\n", This, aRequestMethod);
892
893     if(This->http_channel)
894         return nsIHttpChannel_GetRequestMethod(This->http_channel, aRequestMethod);
895
896     return NS_ERROR_NOT_IMPLEMENTED;
897 }
898
899 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
900                                                  const nsACString *aRequestMethod)
901 {
902     nsChannel *This = NSCHANNEL_THIS(iface);
903
904     TRACE("(%p)->(%p)\n", This, aRequestMethod);
905
906     if(This->http_channel)
907         return nsIHttpChannel_SetRequestMethod(This->http_channel, aRequestMethod);
908
909     return NS_ERROR_NOT_IMPLEMENTED;
910 }
911
912 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
913 {
914     nsChannel *This = NSCHANNEL_THIS(iface);
915
916     TRACE("(%p)->(%p)\n", This, aReferrer);
917
918     if(This->http_channel)
919         return nsIHttpChannel_GetReferrer(This->http_channel, aReferrer);
920
921     return NS_ERROR_NOT_IMPLEMENTED;
922 }
923
924 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
925 {
926     nsChannel *This = NSCHANNEL_THIS(iface);
927
928     TRACE("(%p)->(%p)\n", This, aReferrer);
929
930     if(This->http_channel)
931         return nsIHttpChannel_SetReferrer(This->http_channel, aReferrer);
932
933     return NS_ERROR_NOT_IMPLEMENTED;
934 }
935
936 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
937          const nsACString *aHeader, nsACString *_retval)
938 {
939     nsChannel *This = NSCHANNEL_THIS(iface);
940
941     TRACE("(%p)->(%p %p)\n", This, aHeader, _retval);
942
943     if(This->http_channel)
944         return nsIHttpChannel_GetRequestHeader(This->http_channel, aHeader, _retval);
945
946     return NS_ERROR_NOT_IMPLEMENTED;
947 }
948
949 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
950          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
951 {
952     nsChannel *This = NSCHANNEL_THIS(iface);
953
954     TRACE("(%p)->(%p %p %x)\n", This, aHeader, aValue, aMerge);
955
956     if(This->http_channel)
957         return nsIHttpChannel_SetRequestHeader(This->http_channel, aHeader, aValue, aMerge);
958
959     return NS_ERROR_NOT_IMPLEMENTED;
960 }
961
962 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
963                                                     nsIHttpHeaderVisitor *aVisitor)
964 {
965     nsChannel *This = NSCHANNEL_THIS(iface);
966
967     TRACE("(%p)->(%p)\n", This, aVisitor);
968
969     if(This->http_channel)
970         return nsIHttpChannel_VisitRequestHeaders(This->http_channel, aVisitor);
971
972     return NS_ERROR_NOT_IMPLEMENTED;
973 }
974
975 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
976 {
977     nsChannel *This = NSCHANNEL_THIS(iface);
978
979     TRACE("(%p)->(%p)\n", This, aAllowPipelining);
980
981     if(This->http_channel)
982         return nsIHttpChannel_GetAllowPipelining(This->http_channel, aAllowPipelining);
983
984     return NS_ERROR_NOT_IMPLEMENTED;
985 }
986
987 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
988 {
989     nsChannel *This = NSCHANNEL_THIS(iface);
990
991     TRACE("(%p)->(%x)\n", This, aAllowPipelining);
992
993     if(This->http_channel)
994         return nsIHttpChannel_SetAllowPipelining(This->http_channel, aAllowPipelining);
995
996     return NS_ERROR_NOT_IMPLEMENTED;
997 }
998
999 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
1000 {
1001     nsChannel *This = NSCHANNEL_THIS(iface);
1002
1003     TRACE("(%p)->(%p)\n", This, aRedirectionLimit);
1004
1005     if(This->http_channel)
1006         return nsIHttpChannel_GetRedirectionLimit(This->http_channel, aRedirectionLimit);
1007
1008     return NS_ERROR_NOT_IMPLEMENTED;
1009 }
1010
1011 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
1012 {
1013     nsChannel *This = NSCHANNEL_THIS(iface);
1014
1015     TRACE("(%p)->(%u)\n", This, aRedirectionLimit);
1016
1017     if(This->http_channel)
1018         return nsIHttpChannel_SetRedirectionLimit(This->http_channel, aRedirectionLimit);
1019
1020     return NS_ERROR_NOT_IMPLEMENTED;
1021 }
1022
1023 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
1024 {
1025     nsChannel *This = NSCHANNEL_THIS(iface);
1026
1027     TRACE("(%p)->(%p)\n", This, aResponseStatus);
1028
1029     if(This->response_status) {
1030         *aResponseStatus = This->response_status;
1031         return NS_OK;
1032     }
1033
1034     if(This->http_channel)
1035         return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
1036
1037     return NS_ERROR_UNEXPECTED;
1038 }
1039
1040 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
1041                                                       nsACString *aResponseStatusText)
1042 {
1043     nsChannel *This = NSCHANNEL_THIS(iface);
1044
1045     TRACE("(%p)->(%p)\n", This, aResponseStatusText);
1046
1047     if(This->http_channel)
1048         return nsIHttpChannel_GetResponseStatusText(This->http_channel, aResponseStatusText);
1049
1050     return NS_ERROR_NOT_IMPLEMENTED;
1051 }
1052
1053 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
1054                                                     PRBool *aRequestSucceeded)
1055 {
1056     nsChannel *This = NSCHANNEL_THIS(iface);
1057
1058     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
1059
1060     if(This->http_channel)
1061         return nsIHttpChannel_GetRequestSucceeded(This->http_channel, aRequestSucceeded);
1062
1063     return NS_ERROR_NOT_IMPLEMENTED;
1064 }
1065
1066 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
1067          const nsACString *header, nsACString *_retval)
1068 {
1069     nsChannel *This = NSCHANNEL_THIS(iface);
1070
1071     TRACE("(%p)->(%p %p)\n", This, header, _retval);
1072
1073     if(This->http_channel)
1074         return nsIHttpChannel_GetResponseHeader(This->http_channel, header, _retval);
1075
1076     return NS_ERROR_NOT_IMPLEMENTED;
1077 }
1078
1079 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
1080         const nsACString *header, const nsACString *value, PRBool merge)
1081 {
1082     nsChannel *This = NSCHANNEL_THIS(iface);
1083
1084     TRACE("(%p)->(%p %p %x)\n", This, header, value, merge);
1085
1086     if(This->http_channel)
1087         return nsIHttpChannel_SetResponseHeader(This->http_channel, header, value, merge);
1088
1089     return NS_ERROR_NOT_IMPLEMENTED;
1090 }
1091
1092 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
1093         nsIHttpHeaderVisitor *aVisitor)
1094 {
1095     nsChannel *This = NSCHANNEL_THIS(iface);
1096
1097     TRACE("(%p)->(%p)\n", This, aVisitor);
1098
1099     if(This->http_channel)
1100         return nsIHttpChannel_VisitResponseHeaders(This->http_channel, aVisitor);
1101
1102     return NS_ERROR_NOT_IMPLEMENTED;
1103 }
1104
1105 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
1106 {
1107     nsChannel *This = NSCHANNEL_THIS(iface);
1108
1109     TRACE("(%p)->(%p)\n", This, _retval);
1110
1111     if(This->http_channel)
1112         return nsIHttpChannel_IsNoStoreResponse(This->http_channel, _retval);
1113
1114     return NS_ERROR_NOT_IMPLEMENTED;
1115 }
1116
1117 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
1118 {
1119     nsChannel *This = NSCHANNEL_THIS(iface);
1120
1121     TRACE("(%p)->(%p)\n", This, _retval);
1122
1123     if(This->http_channel)
1124         return nsIHttpChannel_IsNoCacheResponse(This->http_channel, _retval);
1125
1126     return NS_ERROR_NOT_IMPLEMENTED;
1127 }
1128
1129 #undef NSCHANNEL_THIS
1130
1131 static const nsIHttpChannelVtbl nsChannelVtbl = {
1132     nsChannel_QueryInterface,
1133     nsChannel_AddRef,
1134     nsChannel_Release,
1135     nsChannel_GetName,
1136     nsChannel_IsPending,
1137     nsChannel_GetStatus,
1138     nsChannel_Cancel,
1139     nsChannel_Suspend,
1140     nsChannel_Resume,
1141     nsChannel_GetLoadGroup,
1142     nsChannel_SetLoadGroup,
1143     nsChannel_GetLoadFlags,
1144     nsChannel_SetLoadFlags,
1145     nsChannel_GetOriginalURI,
1146     nsChannel_SetOriginalURI,
1147     nsChannel_GetURI,
1148     nsChannel_GetOwner,
1149     nsChannel_SetOwner,
1150     nsChannel_GetNotificationCallbacks,
1151     nsChannel_SetNotificationCallbacks,
1152     nsChannel_GetSecurityInfo,
1153     nsChannel_GetContentType,
1154     nsChannel_SetContentType,
1155     nsChannel_GetContentCharset,
1156     nsChannel_SetContentCharset,
1157     nsChannel_GetContentLength,
1158     nsChannel_SetContentLength,
1159     nsChannel_Open,
1160     nsChannel_AsyncOpen,
1161     nsChannel_GetRequestMethod,
1162     nsChannel_SetRequestMethod,
1163     nsChannel_GetReferrer,
1164     nsChannel_SetReferrer,
1165     nsChannel_GetRequestHeader,
1166     nsChannel_SetRequestHeader,
1167     nsChannel_VisitRequestHeaders,
1168     nsChannel_GetAllowPipelining,
1169     nsChannel_SetAllowPipelining,
1170     nsChannel_GetRedirectionLimit,
1171     nsChannel_SetRedirectionLimit,
1172     nsChannel_GetResponseStatus,
1173     nsChannel_GetResponseStatusText,
1174     nsChannel_GetRequestSucceeded,
1175     nsChannel_GetResponseHeader,
1176     nsChannel_SetResponseHeader,
1177     nsChannel_VisitResponseHeaders,
1178     nsChannel_IsNoStoreResponse,
1179     nsChannel_IsNoCacheResponse
1180 };
1181
1182 #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface)
1183
1184 static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid,
1185                                                      nsQIResult result)
1186 {
1187     nsChannel *This = NSUPCHANNEL_THIS(iface);
1188     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1189 }
1190
1191 static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface)
1192 {
1193     nsChannel *This = NSUPCHANNEL_THIS(iface);
1194     return nsIChannel_AddRef(NSCHANNEL(This));
1195 }
1196
1197 static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface)
1198 {
1199     nsChannel *This = NSUPCHANNEL_THIS(iface);
1200     return nsIChannel_Release(NSCHANNEL(This));
1201 }
1202
1203 static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
1204         nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength)
1205 {
1206     nsChannel *This = NSUPCHANNEL_THIS(iface);
1207     const char *content_type;
1208     nsresult nsres;
1209
1210     TRACE("(%p)->(%p %p %d)\n", This, aStream, aContentType, aContentLength);
1211
1212     if(This->post_data_stream)
1213         nsIInputStream_Release(This->post_data_stream);
1214
1215     if(aContentType) {
1216         nsACString_GetData(aContentType, &content_type);
1217         if(*content_type)
1218             FIXME("Unsupported aContentType argument: %s\n", debugstr_a(content_type));
1219     }
1220
1221     if(aContentLength != -1)
1222         FIXME("Unsupported acontentLength = %d\n", aContentLength);
1223
1224     if(This->post_data_stream)
1225         nsIInputStream_Release(This->post_data_stream);
1226     This->post_data_stream = aStream;
1227     if(aStream)
1228         nsIInputStream_AddRef(aStream);
1229
1230     if(This->post_data_stream) {
1231         nsIUploadChannel *upload_channel;
1232
1233         nsres = nsIChannel_QueryInterface(This->channel, &IID_nsIUploadChannel,
1234                 (void**)&upload_channel);
1235         if(NS_SUCCEEDED(nsres)) {
1236             nsres = nsIUploadChannel_SetUploadStream(upload_channel, aStream, aContentType, aContentLength);
1237             nsIUploadChannel_Release(upload_channel);
1238             if(NS_FAILED(nsres))
1239                 WARN("SetUploadStream failed: %08x\n", nsres);
1240
1241         }
1242     }
1243
1244     return NS_OK;
1245 }
1246
1247 static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface,
1248         nsIInputStream **aUploadStream)
1249 {
1250     nsChannel *This = NSUPCHANNEL_THIS(iface);
1251
1252     TRACE("(%p)->(%p)\n", This, aUploadStream);
1253
1254     if(This->post_data_stream)
1255         nsIInputStream_AddRef(This->post_data_stream);
1256
1257     *aUploadStream = This->post_data_stream;
1258     return NS_OK;
1259 }
1260
1261 #undef NSUPCHANNEL_THIS
1262
1263 static const nsIUploadChannelVtbl nsUploadChannelVtbl = {
1264     nsUploadChannel_QueryInterface,
1265     nsUploadChannel_AddRef,
1266     nsUploadChannel_Release,
1267     nsUploadChannel_SetUploadStream,
1268     nsUploadChannel_GetUploadStream
1269 };
1270
1271 #define NSHTTPINTERNAL_THIS(iface) DEFINE_THIS(nsChannel, IHttpChannelInternal, iface)
1272
1273 static nsresult NSAPI nsHttpChannelInternal_QueryInterface(nsIHttpChannelInternal *iface, nsIIDRef riid,
1274         nsQIResult result)
1275 {
1276     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1277     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1278 }
1279
1280 static nsrefcnt NSAPI nsHttpChannelInternal_AddRef(nsIHttpChannelInternal *iface)
1281 {
1282     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1283     return nsIChannel_AddRef(NSCHANNEL(This));
1284 }
1285
1286 static nsrefcnt NSAPI nsHttpChannelInternal_Release(nsIHttpChannelInternal *iface)
1287 {
1288     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1289     return nsIChannel_Release(NSCHANNEL(This));
1290 }
1291
1292 static nsresult NSAPI nsHttpChannelInternal_GetDocumentURI(nsIHttpChannelInternal *iface, nsIURI **aDocumentURI)
1293 {
1294     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1295
1296     TRACE("(%p)->()\n", This);
1297
1298     if(This->http_channel_internal)
1299         return nsIHttpChannelInternal_GetDocumentURI(This->http_channel_internal, aDocumentURI);
1300     return NS_ERROR_NOT_IMPLEMENTED;
1301 }
1302
1303 static nsresult NSAPI nsHttpChannelInternal_SetDocumentURI(nsIHttpChannelInternal *iface, nsIURI *aDocumentURI)
1304 {
1305     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1306
1307     TRACE("(%p)->()\n", This);
1308
1309     if(This->http_channel_internal)
1310         return nsIHttpChannelInternal_SetDocumentURI(This->http_channel_internal, aDocumentURI);
1311     return NS_ERROR_NOT_IMPLEMENTED;
1312 }
1313
1314 static nsresult NSAPI nsHttpChannelInternal_GetRequestVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1315 {
1316     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1317
1318     TRACE("(%p)->()\n", This);
1319
1320     if(This->http_channel_internal)
1321         return nsIHttpChannelInternal_GetRequestVersion(This->http_channel_internal, major, minor);
1322     return NS_ERROR_NOT_IMPLEMENTED;
1323 }
1324
1325 static nsresult NSAPI nsHttpChannelInternal_GetResponseVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1326 {
1327     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1328
1329     TRACE("(%p)->()\n", This);
1330
1331     if(This->http_channel_internal)
1332         return nsIHttpChannelInternal_GetResponseVersion(This->http_channel_internal, major, minor);
1333     return NS_ERROR_NOT_IMPLEMENTED;
1334 }
1335
1336 static nsresult NSAPI nsHttpChannelInternal_SetCookie(nsIHttpChannelInternal *iface, const char *aCookieHeader)
1337 {
1338     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1339
1340     TRACE("(%p)->()\n", This);
1341
1342     if(This->http_channel_internal)
1343         return nsIHttpChannelInternal_SetCookie(This->http_channel_internal, aCookieHeader);
1344     return NS_ERROR_NOT_IMPLEMENTED;
1345 }
1346
1347 static nsresult NSAPI nsHttpChannelInternal_SetupFallbackChannel(nsIHttpChannelInternal *iface, const char *aFallbackKey)
1348 {
1349     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1350
1351     TRACE("(%p)->()\n", This);
1352
1353     if(This->http_channel_internal)
1354         return nsIHttpChannelInternal_SetupFallbackChannel(This->http_channel_internal, aFallbackKey);
1355     return NS_ERROR_NOT_IMPLEMENTED;
1356 }
1357
1358 static nsresult NSAPI nsHttpChannelInternal_GetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool *aForceThirdPartyCookie)
1359 {
1360     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1361
1362     TRACE("(%p)->()\n", This);
1363
1364     if(This->http_channel_internal)
1365         return nsIHttpChannelInternal_GetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
1366     return NS_ERROR_NOT_IMPLEMENTED;
1367 }
1368
1369 static nsresult NSAPI nsHttpChannelInternal_SetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool aForceThirdPartyCookie)
1370 {
1371     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1372
1373     TRACE("(%p)->()\n", This);
1374
1375     if(This->http_channel_internal)
1376         return nsIHttpChannelInternal_SetForceAllowThirdPartyCookie(This->http_channel_internal, aForceThirdPartyCookie);
1377     return NS_ERROR_NOT_IMPLEMENTED;
1378 }
1379
1380 #undef NSHTTPINTERNAL_THIS
1381
1382 static const nsIHttpChannelInternalVtbl nsHttpChannelInternalVtbl = {
1383     nsHttpChannelInternal_QueryInterface,
1384     nsHttpChannelInternal_AddRef,
1385     nsHttpChannelInternal_Release,
1386     nsHttpChannelInternal_GetDocumentURI,
1387     nsHttpChannelInternal_SetDocumentURI,
1388     nsHttpChannelInternal_GetRequestVersion,
1389     nsHttpChannelInternal_GetResponseVersion,
1390     nsHttpChannelInternal_SetCookie,
1391     nsHttpChannelInternal_SetupFallbackChannel,
1392     nsHttpChannelInternal_GetForceAllowThirdPartyCookie,
1393     nsHttpChannelInternal_SetForceAllowThirdPartyCookie
1394 };
1395
1396 #define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
1397
1398 static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
1399 {
1400     nsURI *This = NSURI_THIS(iface);
1401
1402     *result = NULL;
1403
1404     if(IsEqualGUID(&IID_nsISupports, riid)) {
1405         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1406         *result = NSURI(This);
1407     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
1408         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
1409         *result = NSURI(This);
1410     }else if(IsEqualGUID(&IID_nsIURL, riid)) {
1411         TRACE("(%p)->(IID_nsIURL %p)\n", This, result);
1412         *result = NSURI(This);
1413     }else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
1414         TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
1415         *result = NSURI(This);
1416     }
1417
1418     if(*result) {
1419         nsIURI_AddRef(NSURI(This));
1420         return NS_OK;
1421     }
1422
1423     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1424     return This->uri ? nsIURI_QueryInterface(This->uri, riid, result) : NS_NOINTERFACE;
1425 }
1426
1427 static nsrefcnt NSAPI nsURI_AddRef(nsIWineURI *iface)
1428 {
1429     nsURI *This = NSURI_THIS(iface);
1430     LONG ref = InterlockedIncrement(&This->ref);
1431
1432     TRACE("(%p) ref=%d\n", This, ref);
1433
1434     return ref;
1435 }
1436
1437 static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface)
1438 {
1439     nsURI *This = NSURI_THIS(iface);
1440     LONG ref = InterlockedDecrement(&This->ref);
1441
1442     TRACE("(%p) ref=%d\n", This, ref);
1443
1444     if(!ref) {
1445         if(This->window_ref)
1446             windowref_release(This->window_ref);
1447         if(This->container)
1448             nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1449         if(This->nsurl)
1450             nsIURL_Release(This->nsurl);
1451         if(This->uri)
1452             nsIURI_Release(This->uri);
1453         heap_free(This->wine_url);
1454         heap_free(This);
1455     }
1456
1457     return ref;
1458 }
1459
1460 static nsresult NSAPI nsURI_GetSpec(nsIWineURI *iface, nsACString *aSpec)
1461 {
1462     nsURI *This = NSURI_THIS(iface);
1463
1464     TRACE("(%p)->(%p)\n", This, aSpec);
1465
1466     if(This->use_wine_url) {
1467         char speca[INTERNET_MAX_URL_LENGTH] = "wine:";
1468         WideCharToMultiByte(CP_ACP, 0, This->wine_url, -1, speca+5, sizeof(speca)-5, NULL, NULL);
1469         nsACString_SetData(aSpec, speca);
1470
1471         return NS_OK;
1472     }
1473
1474     if(This->uri)
1475         return nsIURI_GetSpec(This->uri, aSpec);
1476
1477     TRACE("returning error\n");
1478     return NS_ERROR_NOT_IMPLEMENTED;
1479
1480 }
1481
1482 static nsresult NSAPI nsURI_SetSpec(nsIWineURI *iface, const nsACString *aSpec)
1483 {
1484     nsURI *This = NSURI_THIS(iface);
1485
1486     TRACE("(%p)->(%p)\n", This, aSpec);
1487
1488     if(This->uri)
1489         return nsIURI_SetSpec(This->uri, aSpec);
1490
1491     FIXME("default action not implemented\n");
1492     return NS_ERROR_NOT_IMPLEMENTED;
1493 }
1494
1495 static nsresult NSAPI nsURI_GetPrePath(nsIWineURI *iface, nsACString *aPrePath)
1496 {
1497     nsURI *This = NSURI_THIS(iface);
1498
1499     TRACE("(%p)->(%p)\n", This, aPrePath);
1500
1501     if(This->uri)
1502         return nsIURI_GetPrePath(This->uri, aPrePath);
1503
1504     FIXME("default action not implemented\n");
1505     return NS_ERROR_NOT_IMPLEMENTED;
1506 }
1507
1508 static nsresult NSAPI nsURI_GetScheme(nsIWineURI *iface, nsACString *aScheme)
1509 {
1510     nsURI *This = NSURI_THIS(iface);
1511
1512     TRACE("(%p)->(%p)\n", This, aScheme);
1513
1514     if(This->use_wine_url) {
1515         /*
1516          * For Gecko we set scheme to unknown so it won't be handled
1517          * as any special case.
1518          */
1519         nsACString_SetData(aScheme, "wine");
1520         return NS_OK;
1521     }
1522
1523     if(This->uri)
1524         return nsIURI_GetScheme(This->uri, aScheme);
1525
1526     TRACE("returning error\n");
1527     return NS_ERROR_NOT_IMPLEMENTED;
1528 }
1529
1530 static nsresult NSAPI nsURI_SetScheme(nsIWineURI *iface, const nsACString *aScheme)
1531 {
1532     nsURI *This = NSURI_THIS(iface);
1533
1534     TRACE("(%p)->(%p)\n", This, aScheme);
1535
1536     if(This->uri)
1537         return nsIURI_SetScheme(This->uri, aScheme);
1538
1539     FIXME("default action not implemented\n");
1540     return NS_ERROR_NOT_IMPLEMENTED;
1541 }
1542
1543 static nsresult NSAPI nsURI_GetUserPass(nsIWineURI *iface, nsACString *aUserPass)
1544 {
1545     nsURI *This = NSURI_THIS(iface);
1546
1547     TRACE("(%p)->(%p)\n", This, aUserPass);
1548
1549     if(This->uri)
1550         return nsIURI_GetUserPass(This->uri, aUserPass);
1551
1552     FIXME("default action not implemented\n");
1553     return NS_ERROR_NOT_IMPLEMENTED;
1554 }
1555
1556 static nsresult NSAPI nsURI_SetUserPass(nsIWineURI *iface, const nsACString *aUserPass)
1557 {
1558     nsURI *This = NSURI_THIS(iface);
1559
1560     TRACE("(%p)->(%p)\n", This, aUserPass);
1561
1562     if(This->uri)
1563         return nsIURI_SetUserPass(This->uri, aUserPass);
1564
1565     FIXME("default action not implemented\n");
1566     return NS_ERROR_NOT_IMPLEMENTED;
1567 }
1568
1569 static nsresult NSAPI nsURI_GetUsername(nsIWineURI *iface, nsACString *aUsername)
1570 {
1571     nsURI *This = NSURI_THIS(iface);
1572
1573     TRACE("(%p)->(%p)\n", This, aUsername);
1574
1575     if(This->uri)
1576         return nsIURI_GetUsername(This->uri, aUsername);
1577
1578     FIXME("default action not implemented\n");
1579     return NS_ERROR_NOT_IMPLEMENTED;
1580 }
1581
1582 static nsresult NSAPI nsURI_SetUsername(nsIWineURI *iface, const nsACString *aUsername)
1583 {
1584     nsURI *This = NSURI_THIS(iface);
1585
1586     TRACE("(%p)->(%p)\n", This, aUsername);
1587
1588     if(This->uri)
1589         return nsIURI_SetUsername(This->uri, aUsername);
1590
1591     FIXME("default action not implemented\n");
1592     return NS_ERROR_NOT_IMPLEMENTED;
1593 }
1594
1595 static nsresult NSAPI nsURI_GetPassword(nsIWineURI *iface, nsACString *aPassword)
1596 {
1597     nsURI *This = NSURI_THIS(iface);
1598
1599     TRACE("(%p)->(%p)\n", This, aPassword);
1600
1601     if(This->uri)
1602         return nsIURI_GetPassword(This->uri, aPassword);
1603
1604     FIXME("default action not implemented\n");
1605     return NS_ERROR_NOT_IMPLEMENTED;
1606 }
1607
1608 static nsresult NSAPI nsURI_SetPassword(nsIWineURI *iface, const nsACString *aPassword)
1609 {
1610     nsURI *This = NSURI_THIS(iface);
1611
1612     TRACE("(%p)->(%p)\n", This, aPassword);
1613
1614     if(This->uri)
1615         return nsIURI_SetPassword(This->uri, aPassword);
1616
1617     FIXME("default action not implemented\n");
1618     return NS_ERROR_NOT_IMPLEMENTED;
1619 }
1620
1621 static nsresult NSAPI nsURI_GetHostPort(nsIWineURI *iface, nsACString *aHostPort)
1622 {
1623     nsURI *This = NSURI_THIS(iface);
1624
1625     TRACE("(%p)->(%p)\n", This, aHostPort);
1626
1627     if(This->uri)
1628         return nsIURI_GetHostPort(This->uri, aHostPort);
1629
1630     FIXME("default action not implemented\n");
1631     return NS_ERROR_NOT_IMPLEMENTED;
1632 }
1633
1634 static nsresult NSAPI nsURI_SetHostPort(nsIWineURI *iface, const nsACString *aHostPort)
1635 {
1636     nsURI *This = NSURI_THIS(iface);
1637
1638     TRACE("(%p)->(%p)\n", This, aHostPort);
1639
1640     if(This->uri)
1641         return nsIURI_SetHostPort(This->uri, aHostPort);
1642
1643     FIXME("default action not implemented\n");
1644     return NS_ERROR_NOT_IMPLEMENTED;
1645 }
1646
1647 static nsresult NSAPI nsURI_GetHost(nsIWineURI *iface, nsACString *aHost)
1648 {
1649     nsURI *This = NSURI_THIS(iface);
1650
1651     TRACE("(%p)->(%p)\n", This, aHost);
1652
1653     if(This->uri)
1654         return nsIURI_GetHost(This->uri, aHost);
1655
1656     FIXME("default action not implemented\n");
1657     return NS_ERROR_NOT_IMPLEMENTED;
1658 }
1659
1660 static nsresult NSAPI nsURI_SetHost(nsIWineURI *iface, const nsACString *aHost)
1661 {
1662     nsURI *This = NSURI_THIS(iface);
1663
1664     TRACE("(%p)->(%p)\n", This, aHost);
1665
1666     if(This->uri)
1667         return nsIURI_SetHost(This->uri, aHost);
1668
1669     FIXME("default action not implemented\n");
1670     return NS_ERROR_NOT_IMPLEMENTED;
1671 }
1672
1673 static nsresult NSAPI nsURI_GetPort(nsIWineURI *iface, PRInt32 *aPort)
1674 {
1675     nsURI *This = NSURI_THIS(iface);
1676
1677     TRACE("(%p)->(%p)\n", This, aPort);
1678
1679     if(This->uri)
1680         return nsIURI_GetPort(This->uri, aPort);
1681
1682     FIXME("default action not implemented\n");
1683     return NS_ERROR_NOT_IMPLEMENTED;
1684 }
1685
1686 static nsresult NSAPI nsURI_SetPort(nsIWineURI *iface, PRInt32 aPort)
1687 {
1688     nsURI *This = NSURI_THIS(iface);
1689
1690     TRACE("(%p)->(%d)\n", This, aPort);
1691
1692     if(This->uri)
1693         return nsIURI_SetPort(This->uri, aPort);
1694
1695     FIXME("default action not implemented\n");
1696     return NS_ERROR_NOT_IMPLEMENTED;
1697 }
1698
1699 static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath)
1700 {
1701     nsURI *This = NSURI_THIS(iface);
1702
1703     TRACE("(%p)->(%p)\n", This, aPath);
1704
1705     if(This->uri)
1706         return nsIURI_GetPath(This->uri, aPath);
1707
1708     FIXME("default action not implemented\n");
1709     return NS_ERROR_NOT_IMPLEMENTED;
1710 }
1711
1712 static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath)
1713 {
1714     nsURI *This = NSURI_THIS(iface);
1715     const char *path;
1716
1717     nsACString_GetData(aPath, &path);
1718     TRACE("(%p)->(%p(%s))\n", This, aPath, debugstr_a(path));
1719
1720
1721     if(This->wine_url) {
1722         WCHAR new_url[INTERNET_MAX_URL_LENGTH];
1723         DWORD size = sizeof(new_url)/sizeof(WCHAR);
1724         LPWSTR pathw;
1725         HRESULT hres;
1726
1727         pathw = heap_strdupAtoW(path);
1728         hres = UrlCombineW(This->wine_url, pathw, new_url, &size, 0);
1729         heap_free(pathw);
1730         if(SUCCEEDED(hres))
1731             nsIWineURI_SetWineURL(NSWINEURI(This), new_url);
1732         else
1733             WARN("UrlCombine failed: %08x\n", hres);
1734     }
1735
1736     if(!This->uri)
1737         return NS_OK;
1738
1739     return nsIURI_SetPath(This->uri, aPath);
1740 }
1741
1742 static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval)
1743 {
1744     nsURI *This = NSURI_THIS(iface);
1745     nsIWineURI *wine_uri;
1746     LPCWSTR other_url = NULL;
1747     nsresult nsres;
1748
1749     TRACE("(%p)->(%p %p)\n", This, other, _retval);
1750
1751     if(This->uri)
1752         return nsIURI_Equals(This->uri, other, _retval);
1753
1754     nsres = nsIURI_QueryInterface(other, &IID_nsIWineURI, (void**)&wine_uri);
1755     if(NS_FAILED(nsres)) {
1756         TRACE("Could not get nsIWineURI interface\n");
1757         *_retval = FALSE;
1758         return NS_OK;
1759     }
1760
1761     nsIWineURI_GetWineURL(wine_uri, &other_url);
1762     *_retval = other_url && !UrlCompareW(This->wine_url, other_url, TRUE);
1763     nsIWineURI_Release(wine_uri);
1764
1765     return NS_OK;
1766 }
1767
1768 static nsresult NSAPI nsURI_SchemeIs(nsIWineURI *iface, const char *scheme, PRBool *_retval)
1769 {
1770     nsURI *This = NSURI_THIS(iface);
1771
1772     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
1773
1774     if(This->use_wine_url) {
1775         WCHAR buf[INTERNET_MAX_SCHEME_LENGTH];
1776         int len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
1777
1778         *_retval = lstrlenW(This->wine_url) > len
1779             && This->wine_url[len] == ':'
1780             && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
1781         return NS_OK;
1782     }
1783
1784     if(This->uri)
1785         return nsIURI_SchemeIs(This->uri, scheme, _retval);
1786
1787     TRACE("returning error\n");
1788     return NS_ERROR_NOT_IMPLEMENTED;
1789 }
1790
1791 static nsresult NSAPI nsURI_Clone(nsIWineURI *iface, nsIURI **_retval)
1792 {
1793     nsURI *This = NSURI_THIS(iface);
1794     nsIURI *nsuri = NULL;
1795     nsIWineURI *wine_uri;
1796     nsresult nsres;
1797
1798     TRACE("(%p)->(%p)\n", This, _retval);
1799
1800     if(This->uri) {
1801         nsres = nsIURI_Clone(This->uri, &nsuri);
1802         if(NS_FAILED(nsres)) {
1803             WARN("Clone failed: %08x\n", nsres);
1804             return nsres;
1805         }
1806     }
1807
1808     nsres = create_uri(nsuri, This->window_ref ? This->window_ref->window : NULL, This->container, &wine_uri);
1809     if(NS_FAILED(nsres)) {
1810         WARN("create_uri failed: %08x\n", nsres);
1811         return nsres;
1812     }
1813
1814     *_retval = (nsIURI*)wine_uri;
1815     return nsIWineURI_SetWineURL(wine_uri, This->wine_url);
1816 }
1817
1818 static nsresult NSAPI nsURI_Resolve(nsIWineURI *iface, const nsACString *arelativePath,
1819         nsACString *_retval)
1820 {
1821     nsURI *This = NSURI_THIS(iface);
1822
1823     TRACE("(%p)->(%p %p)\n", This, arelativePath, _retval);
1824
1825     if(This->uri)
1826         return nsIURI_Resolve(This->uri, arelativePath, _retval);
1827
1828     FIXME("default action not implemented\n");
1829     return NS_ERROR_NOT_IMPLEMENTED;
1830 }
1831
1832 static nsresult NSAPI nsURI_GetAsciiSpec(nsIWineURI *iface, nsACString *aAsciiSpec)
1833 {
1834     nsURI *This = NSURI_THIS(iface);
1835
1836     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
1837
1838     if(This->use_wine_url)
1839         return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
1840
1841     if(This->uri)
1842         return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
1843
1844     TRACE("returning error\n");
1845     return NS_ERROR_NOT_IMPLEMENTED;
1846 }
1847
1848 static nsresult NSAPI nsURI_GetAsciiHost(nsIWineURI *iface, nsACString *aAsciiHost)
1849 {
1850     nsURI *This = NSURI_THIS(iface);
1851
1852     TRACE("(%p)->(%p)\n", This, aAsciiHost);
1853
1854     if(This->uri)
1855         return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
1856
1857     FIXME("default action not implemented\n");
1858     return NS_ERROR_NOT_IMPLEMENTED;
1859 }
1860
1861 static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOriginCharset)
1862 {
1863     nsURI *This = NSURI_THIS(iface);
1864
1865     TRACE("(%p)->(%p)\n", This, aOriginCharset);
1866
1867     if(This->uri)
1868         return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
1869
1870     FIXME("default action not implemented\n");
1871     return NS_ERROR_NOT_IMPLEMENTED;
1872 }
1873
1874 static nsresult NSAPI nsURL_GetFilePath(nsIWineURI *iface, nsACString *aFilePath)
1875 {
1876     nsURI *This = NSURI_THIS(iface);
1877
1878     TRACE("(%p)->(%p)\n", This, aFilePath);
1879
1880     if(This->nsurl)
1881         return nsIURL_GetFilePath(This->nsurl, aFilePath);
1882
1883     FIXME("default action not implemented\n");
1884     return NS_ERROR_NOT_IMPLEMENTED;
1885 }
1886
1887 static nsresult NSAPI nsURL_SetFilePath(nsIWineURI *iface, const nsACString *aFilePath)
1888 {
1889     nsURI *This = NSURI_THIS(iface);
1890
1891     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath));
1892
1893     if(This->nsurl)
1894         return nsIURL_SetFilePath(This->nsurl, aFilePath);
1895
1896     FIXME("default action not implemented\n");
1897     return NS_ERROR_NOT_IMPLEMENTED;
1898 }
1899
1900 static nsresult NSAPI nsURL_GetParam(nsIWineURI *iface, nsACString *aParam)
1901 {
1902     nsURI *This = NSURI_THIS(iface);
1903
1904     TRACE("(%p)->(%p)\n", This, aParam);
1905
1906     if(This->nsurl)
1907         return nsIURL_GetParam(This->nsurl, aParam);
1908
1909     FIXME("default action not implemented\n");
1910     return NS_ERROR_NOT_IMPLEMENTED;
1911 }
1912
1913 static nsresult NSAPI nsURL_SetParam(nsIWineURI *iface, const nsACString *aParam)
1914 {
1915     nsURI *This = NSURI_THIS(iface);
1916
1917     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aParam));
1918
1919     if(This->nsurl)
1920         return nsIURL_SetParam(This->nsurl, aParam);
1921
1922     FIXME("default action not implemented\n");
1923     return NS_ERROR_NOT_IMPLEMENTED;
1924 }
1925
1926 static nsresult NSAPI nsURL_GetQuery(nsIWineURI *iface, nsACString *aQuery)
1927 {
1928     nsURI *This = NSURI_THIS(iface);
1929
1930     TRACE("(%p)->(%p)\n", This, aQuery);
1931
1932     if(This->nsurl)
1933         return nsIURL_GetQuery(This->nsurl, aQuery);
1934
1935     FIXME("default action not implemented\n");
1936     return NS_ERROR_NOT_IMPLEMENTED;
1937 }
1938
1939 static nsresult NSAPI nsURL_SetQuery(nsIWineURI *iface, const nsACString *aQuery)
1940 {
1941     nsURI *This = NSURI_THIS(iface);
1942     const WCHAR *ptr1, *ptr2;
1943     const char *query;
1944     WCHAR *new_url, *ptr;
1945     DWORD len, size;
1946
1947     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery));
1948
1949     if(This->nsurl)
1950         nsIURL_SetQuery(This->nsurl, aQuery);
1951
1952     if(!This->wine_url)
1953         return NS_OK;
1954
1955     nsACString_GetData(aQuery, &query);
1956     size = len = MultiByteToWideChar(CP_ACP, 0, query, -1, NULL, 0);
1957     ptr1 = strchrW(This->wine_url, '?');
1958     if(ptr1) {
1959         size += ptr1-This->wine_url;
1960         ptr2 = strchrW(ptr1, '#');
1961         if(ptr2)
1962             size += strlenW(ptr2);
1963     }else {
1964         ptr1 = This->wine_url + strlenW(This->wine_url);
1965         ptr2 = NULL;
1966         size += strlenW(This->wine_url);
1967     }
1968
1969     if(*query)
1970         size++;
1971
1972     new_url = heap_alloc(size*sizeof(WCHAR));
1973     memcpy(new_url, This->wine_url, (ptr1-This->wine_url)*sizeof(WCHAR));
1974     ptr = new_url + (ptr1-This->wine_url);
1975     if(*query) {
1976         *ptr++ = '?';
1977         MultiByteToWideChar(CP_ACP, 0, query, -1, ptr, len);
1978         ptr += len-1;
1979     }
1980     if(ptr2)
1981         strcpyW(ptr, ptr2);
1982     else
1983         *ptr = 0;
1984
1985     TRACE("setting %s\n", debugstr_w(new_url));
1986
1987     heap_free(This->wine_url);
1988     This->wine_url = new_url;
1989     return NS_OK;
1990 }
1991
1992 static nsresult NSAPI nsURL_GetRef(nsIWineURI *iface, nsACString *aRef)
1993 {
1994     nsURI *This = NSURI_THIS(iface);
1995
1996     TRACE("(%p)->(%p)\n", This, aRef);
1997
1998     if(This->nsurl)
1999         return nsIURL_GetRef(This->nsurl, aRef);
2000
2001     FIXME("default action not implemented\n");
2002     return NS_ERROR_NOT_IMPLEMENTED;
2003 }
2004
2005 static nsresult NSAPI nsURL_SetRef(nsIWineURI *iface, const nsACString *aRef)
2006 {
2007     nsURI *This = NSURI_THIS(iface);
2008     const char *refa;
2009
2010     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
2011
2012     if(This->nsurl)
2013         return nsIURL_SetRef(This->nsurl, aRef);
2014
2015     nsACString_GetData(aRef, &refa);
2016     if(!*refa)
2017         return NS_OK;
2018
2019     FIXME("default action not implemented\n");
2020     return NS_ERROR_NOT_IMPLEMENTED;
2021 }
2022
2023 static nsresult NSAPI nsURL_GetDirectory(nsIWineURI *iface, nsACString *aDirectory)
2024 {
2025     nsURI *This = NSURI_THIS(iface);
2026
2027     TRACE("(%p)->(%p)\n", This, aDirectory);
2028
2029     if(This->nsurl)
2030         return nsIURL_GetDirectory(This->nsurl, aDirectory);
2031
2032     FIXME("default action not implemented\n");
2033     return NS_ERROR_NOT_IMPLEMENTED;
2034 }
2035
2036 static nsresult NSAPI nsURL_SetDirectory(nsIWineURI *iface, const nsACString *aDirectory)
2037 {
2038     nsURI *This = NSURI_THIS(iface);
2039
2040     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
2041
2042     if(This->nsurl)
2043         return nsIURL_SetDirectory(This->nsurl, aDirectory);
2044
2045     FIXME("default action not implemented\n");
2046     return NS_ERROR_NOT_IMPLEMENTED;
2047 }
2048
2049 static nsresult NSAPI nsURL_GetFileName(nsIWineURI *iface, nsACString *aFileName)
2050 {
2051     nsURI *This = NSURI_THIS(iface);
2052
2053     TRACE("(%p)->(%p)\n", This, aFileName);
2054
2055     if(This->nsurl)
2056         return nsIURL_GetFileName(This->nsurl, aFileName);
2057
2058     FIXME("default action not implemented\n");
2059     return NS_ERROR_NOT_IMPLEMENTED;
2060 }
2061
2062 static nsresult NSAPI nsURL_SetFileName(nsIWineURI *iface, const nsACString *aFileName)
2063 {
2064     nsURI *This = NSURI_THIS(iface);
2065
2066     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
2067
2068     if(This->nsurl)
2069         return nsIURL_SetFileName(This->nsurl, aFileName);
2070
2071     FIXME("default action not implemented\n");
2072     return NS_ERROR_NOT_IMPLEMENTED;
2073 }
2074
2075 static nsresult NSAPI nsURL_GetFileBaseName(nsIWineURI *iface, nsACString *aFileBaseName)
2076 {
2077     nsURI *This = NSURI_THIS(iface);
2078
2079     TRACE("(%p)->(%p)\n", This, aFileBaseName);
2080
2081     if(This->nsurl)
2082         return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
2083
2084     FIXME("default action not implemented\n");
2085     return NS_ERROR_NOT_IMPLEMENTED;
2086 }
2087
2088 static nsresult NSAPI nsURL_SetFileBaseName(nsIWineURI *iface, const nsACString *aFileBaseName)
2089 {
2090     nsURI *This = NSURI_THIS(iface);
2091
2092     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
2093
2094     if(This->nsurl)
2095         return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
2096
2097     FIXME("default action not implemented\n");
2098     return NS_ERROR_NOT_IMPLEMENTED;
2099 }
2100
2101 static nsresult NSAPI nsURL_GetFileExtension(nsIWineURI *iface, nsACString *aFileExtension)
2102 {
2103     nsURI *This = NSURI_THIS(iface);
2104
2105     TRACE("(%p)->(%p)\n", This, aFileExtension);
2106
2107     if(This->nsurl)
2108         return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
2109
2110     FIXME("default action not implemented\n");
2111     return NS_ERROR_NOT_IMPLEMENTED;
2112 }
2113
2114 static nsresult NSAPI nsURL_SetFileExtension(nsIWineURI *iface, const nsACString *aFileExtension)
2115 {
2116     nsURI *This = NSURI_THIS(iface);
2117
2118     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
2119
2120     if(This->nsurl)
2121         return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
2122
2123     FIXME("default action not implemented\n");
2124     return NS_ERROR_NOT_IMPLEMENTED;
2125 }
2126
2127 static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2128 {
2129     nsURI *This = NSURI_THIS(iface);
2130
2131     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2132
2133     if(This->nsurl)
2134         return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
2135
2136     FIXME("default action not implemented\n");
2137     return NS_ERROR_NOT_IMPLEMENTED;
2138 }
2139
2140 static nsresult NSAPI nsURL_GetRelativeSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2141 {
2142     nsURI *This = NSURI_THIS(iface);
2143
2144     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2145
2146     if(This->nsurl)
2147         return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
2148
2149     FIXME("default action not implemented\n");
2150     return NS_ERROR_NOT_IMPLEMENTED;
2151 }
2152
2153 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
2154 {
2155     nsURI *This = NSURI_THIS(iface);
2156
2157     TRACE("(%p)->(%p)\n", This, aContainer);
2158
2159     if(This->container)
2160         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
2161     *aContainer = This->container;
2162
2163     return NS_OK;
2164 }
2165
2166 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
2167 {
2168     nsURI *This = NSURI_THIS(iface);
2169
2170     TRACE("(%p)->(%p)\n", This, aContainer);
2171
2172     if(This->container) {
2173         if(This->container == aContainer)
2174             return NS_OK;
2175         TRACE("Changing %p -> %p\n", This->container, aContainer);
2176         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
2177     }
2178
2179     if(aContainer)
2180         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
2181     This->container = aContainer;
2182
2183     return NS_OK;
2184 }
2185
2186 static nsresult NSAPI nsURI_GetWindow(nsIWineURI *iface, HTMLWindow **aHTMLWindow)
2187 {
2188     nsURI *This = NSURI_THIS(iface);
2189
2190     TRACE("(%p)->(%p)\n", This, aHTMLWindow);
2191
2192     if(This->window_ref && This->window_ref->window) {
2193         IHTMLWindow2_AddRef(HTMLWINDOW2(This->window_ref->window));
2194         *aHTMLWindow = This->window_ref->window;
2195     }else {
2196         *aHTMLWindow = NULL;
2197     }
2198
2199     return NS_OK;
2200 }
2201
2202 static nsresult NSAPI nsURI_SetWindow(nsIWineURI *iface, HTMLWindow *aHTMLWindow)
2203 {
2204     nsURI *This = NSURI_THIS(iface);
2205
2206     TRACE("(%p)->(%p)\n", This, aHTMLWindow);
2207
2208     if(This->window_ref) {
2209         if(This->window_ref->window == aHTMLWindow)
2210             return NS_OK;
2211         TRACE("Changing %p -> %p\n", This->window_ref->window, aHTMLWindow);
2212         windowref_release(This->window_ref);
2213     }
2214
2215     if(aHTMLWindow) {
2216         windowref_addref(aHTMLWindow->window_ref);
2217         This->window_ref = aHTMLWindow->window_ref;
2218
2219         if(aHTMLWindow->doc_obj)
2220             nsIWineURI_SetNSContainer(NSWINEURI(This), aHTMLWindow->doc_obj->nscontainer);
2221     }else {
2222         This->window_ref = NULL;
2223     }
2224
2225     return NS_OK;
2226 }
2227
2228 static nsresult NSAPI nsURI_GetIsDocumentURI(nsIWineURI *iface, PRBool *aIsDocumentURI)
2229 {
2230     nsURI *This = NSURI_THIS(iface);
2231
2232     TRACE("(%p)->(%p)\n", This, aIsDocumentURI);
2233
2234     *aIsDocumentURI = This->is_doc_uri;
2235     return NS_OK;
2236 }
2237
2238 static nsresult NSAPI nsURI_SetIsDocumentURI(nsIWineURI *iface, PRBool aIsDocumentURI)
2239 {
2240     nsURI *This = NSURI_THIS(iface);
2241
2242     TRACE("(%p)->(%x)\n", This, aIsDocumentURI);
2243
2244     This->is_doc_uri = aIsDocumentURI;
2245     return NS_OK;
2246 }
2247
2248 static nsresult NSAPI nsURI_GetWineURL(nsIWineURI *iface, LPCWSTR *aURL)
2249 {
2250     nsURI *This = NSURI_THIS(iface);
2251
2252     TRACE("(%p)->(%p)\n", This, aURL);
2253
2254     *aURL = This->wine_url;
2255     return NS_OK;
2256 }
2257
2258 static nsresult NSAPI nsURI_SetWineURL(nsIWineURI *iface, LPCWSTR aURL)
2259 {
2260     nsURI *This = NSURI_THIS(iface);
2261
2262     static const WCHAR wszFtp[]   = {'f','t','p',':'};
2263     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
2264     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
2265
2266     TRACE("(%p)->(%s)\n", This, debugstr_w(aURL));
2267
2268     heap_free(This->wine_url);
2269
2270     if(aURL) {
2271         int len = strlenW(aURL)+1;
2272         This->wine_url = heap_alloc(len*sizeof(WCHAR));
2273         memcpy(This->wine_url, aURL, len*sizeof(WCHAR));
2274
2275         if(This->uri) {
2276             /* FIXME: Always use wine url */
2277             This->use_wine_url =
2278                    strncmpW(aURL, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
2279                 && strncmpW(aURL, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
2280                 && strncmpW(aURL, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
2281         }else {
2282             This->use_wine_url = TRUE;
2283         }
2284     }else {
2285         This->wine_url = NULL;
2286         This->use_wine_url = FALSE;
2287     }
2288
2289     return NS_OK;
2290 }
2291
2292 #undef NSURI_THIS
2293
2294 static const nsIWineURIVtbl nsWineURIVtbl = {
2295     nsURI_QueryInterface,
2296     nsURI_AddRef,
2297     nsURI_Release,
2298     nsURI_GetSpec,
2299     nsURI_SetSpec,
2300     nsURI_GetPrePath,
2301     nsURI_GetScheme,
2302     nsURI_SetScheme,
2303     nsURI_GetUserPass,
2304     nsURI_SetUserPass,
2305     nsURI_GetUsername,
2306     nsURI_SetUsername,
2307     nsURI_GetPassword,
2308     nsURI_SetPassword,
2309     nsURI_GetHostPort,
2310     nsURI_SetHostPort,
2311     nsURI_GetHost,
2312     nsURI_SetHost,
2313     nsURI_GetPort,
2314     nsURI_SetPort,
2315     nsURI_GetPath,
2316     nsURI_SetPath,
2317     nsURI_Equals,
2318     nsURI_SchemeIs,
2319     nsURI_Clone,
2320     nsURI_Resolve,
2321     nsURI_GetAsciiSpec,
2322     nsURI_GetAsciiHost,
2323     nsURI_GetOriginCharset,
2324     nsURL_GetFilePath,
2325     nsURL_SetFilePath,
2326     nsURL_GetParam,
2327     nsURL_SetParam,
2328     nsURL_GetQuery,
2329     nsURL_SetQuery,
2330     nsURL_GetRef,
2331     nsURL_SetRef,
2332     nsURL_GetDirectory,
2333     nsURL_SetDirectory,
2334     nsURL_GetFileName,
2335     nsURL_SetFileName,
2336     nsURL_GetFileBaseName,
2337     nsURL_SetFileBaseName,
2338     nsURL_GetFileExtension,
2339     nsURL_SetFileExtension,
2340     nsURL_GetCommonBaseSpec,
2341     nsURL_GetRelativeSpec,
2342     nsURI_GetNSContainer,
2343     nsURI_SetNSContainer,
2344     nsURI_GetWindow,
2345     nsURI_SetWindow,
2346     nsURI_GetIsDocumentURI,
2347     nsURI_SetIsDocumentURI,
2348     nsURI_GetWineURL,
2349     nsURI_SetWineURL
2350 };
2351
2352 static nsresult create_uri(nsIURI *uri, HTMLWindow *window, NSContainer *container, nsIWineURI **_retval)
2353 {
2354     nsURI *ret = heap_alloc_zero(sizeof(nsURI));
2355
2356     ret->lpWineURIVtbl = &nsWineURIVtbl;
2357     ret->ref = 1;
2358     ret->uri = uri;
2359
2360     nsIWineURI_SetNSContainer(NSWINEURI(ret), container);
2361     nsIWineURI_SetWindow(NSWINEURI(ret), window);
2362
2363     if(uri)
2364         nsIURI_QueryInterface(uri, &IID_nsIURL, (void**)&ret->nsurl);
2365     else
2366         ret->nsurl = NULL;
2367
2368     TRACE("retval=%p\n", ret);
2369     *_retval = NSWINEURI(ret);
2370     return NS_OK;
2371 }
2372
2373 HRESULT create_doc_uri(HTMLWindow *window, WCHAR *url, nsIWineURI **ret)
2374 {
2375     nsIWineURI *uri;
2376     nsresult nsres;
2377
2378     nsres = create_uri(NULL, window, window->doc_obj->nscontainer, &uri);
2379     if(NS_FAILED(nsres))
2380         return E_FAIL;
2381
2382     nsIWineURI_SetWineURL(uri, url);
2383     nsIWineURI_SetIsDocumentURI(uri, TRUE);
2384
2385     *ret = uri;
2386     return S_OK;
2387 }
2388
2389 typedef struct {
2390     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
2391
2392     LONG ref;
2393
2394     nsIProtocolHandler *nshandler;
2395 } nsProtocolHandler;
2396
2397 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
2398
2399 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
2400
2401 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
2402         nsQIResult result)
2403 {
2404     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2405
2406     *result = NULL;
2407
2408     if(IsEqualGUID(&IID_nsISupports, riid)) {
2409         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
2410         *result = NSPROTHANDLER(This);
2411     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
2412         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
2413         *result = NSPROTHANDLER(This);
2414     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
2415         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
2416         return NS_NOINTERFACE;
2417     }
2418
2419     if(*result) {
2420         nsISupports_AddRef((nsISupports*)*result);
2421         return NS_OK;
2422     }
2423
2424     WARN("(%s %p)\n", debugstr_guid(riid), result);
2425     return NS_NOINTERFACE;
2426 }
2427
2428 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
2429 {
2430     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2431     LONG ref = InterlockedIncrement(&This->ref);
2432
2433     TRACE("(%p) ref=%d\n", This, ref);
2434
2435     return ref;
2436 }
2437
2438 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
2439 {
2440     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2441     LONG ref = InterlockedDecrement(&This->ref);
2442
2443     TRACE("(%p) ref=%d\n", This, ref);
2444
2445     if(!ref) {
2446         if(This->nshandler)
2447             nsIProtocolHandler_Release(This->nshandler);
2448         heap_free(This);
2449     }
2450
2451     return ref;
2452 }
2453
2454 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
2455 {
2456     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2457
2458     TRACE("(%p)->(%p)\n", This, aScheme);
2459
2460     if(This->nshandler)
2461         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
2462     return NS_ERROR_NOT_IMPLEMENTED;
2463 }
2464
2465 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
2466         PRInt32 *aDefaultPort)
2467 {
2468     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2469
2470     TRACE("(%p)->(%p)\n", This, aDefaultPort);
2471
2472     if(This->nshandler)
2473         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
2474     return NS_ERROR_NOT_IMPLEMENTED;
2475 }
2476
2477 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
2478                                                          PRUint32 *aProtocolFlags)
2479 {
2480     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2481
2482     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
2483
2484     if(This->nshandler)
2485         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
2486     return NS_ERROR_NOT_IMPLEMENTED;
2487 }
2488
2489 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
2490         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2491 {
2492     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2493
2494     TRACE("((%p)->%p %s %p %p)\n", This, aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2495
2496     if(This->nshandler)
2497         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
2498     return NS_ERROR_NOT_IMPLEMENTED;
2499 }
2500
2501 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
2502         nsIURI *aURI, nsIChannel **_retval)
2503 {
2504     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2505
2506     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
2507
2508     if(This->nshandler)
2509         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
2510     return NS_ERROR_NOT_IMPLEMENTED;
2511 }
2512
2513 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
2514         PRInt32 port, const char *scheme, PRBool *_retval)
2515 {
2516     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2517
2518     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
2519
2520     if(This->nshandler)
2521         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
2522     return NS_ERROR_NOT_IMPLEMENTED;
2523 }
2524
2525 #undef NSPROTHANDLER_THIS
2526
2527 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
2528     nsProtocolHandler_QueryInterface,
2529     nsProtocolHandler_AddRef,
2530     nsProtocolHandler_Release,
2531     nsProtocolHandler_GetScheme,
2532     nsProtocolHandler_GetDefaultPort,
2533     nsProtocolHandler_GetProtocolFlags,
2534     nsProtocolHandler_NewURI,
2535     nsProtocolHandler_NewChannel,
2536     nsProtocolHandler_AllowPort
2537 };
2538
2539 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
2540 {
2541     nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler));
2542
2543     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
2544     ret->ref = 1;
2545     ret->nshandler = nshandler;
2546
2547     return NSPROTHANDLER(ret);
2548 }
2549
2550 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,nsQIResult);
2551
2552 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
2553 {
2554     return 2;
2555 }
2556
2557 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
2558 {
2559     return 1;
2560 }
2561
2562 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
2563                                                      nsIProtocolHandler **_retval)
2564 {
2565     nsIExternalProtocolHandler *nsexthandler;
2566     nsIProtocolHandler *nshandler;
2567     nsresult nsres;
2568
2569     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2570
2571     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
2572     if(NS_FAILED(nsres)) {
2573         WARN("GetProtocolHandler failed: %08x\n", nsres);
2574         return nsres;
2575     }
2576
2577     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
2578                                               (void**)&nsexthandler);
2579     if(NS_FAILED(nsres)) {
2580         *_retval = nshandler;
2581         return NS_OK;
2582     }
2583
2584     nsIExternalProtocolHandler_Release(nsexthandler);
2585     *_retval = create_protocol_handler(nshandler);
2586     TRACE("return %p\n", *_retval);
2587     return NS_OK;
2588 }
2589
2590 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
2591                                                     PRUint32 *_retval)
2592 {
2593     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2594     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
2595 }
2596
2597 static BOOL is_gecko_special_uri(const char *spec)
2598 {
2599     static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
2600     int i;
2601
2602     for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
2603         if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
2604             return TRUE;
2605     }
2606
2607     return FALSE;
2608 }
2609
2610 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
2611         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2612 {
2613     const char *spec = NULL;
2614     HTMLWindow *window = NULL;
2615     nsIURI *uri = NULL;
2616     LPCWSTR base_wine_url = NULL;
2617     nsIWineURI *base_wine_uri = NULL, *wine_uri;
2618     BOOL is_wine_uri = FALSE;
2619     nsresult nsres;
2620
2621     nsACString_GetData(aSpec, &spec);
2622
2623     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
2624           aBaseURI, _retval);
2625
2626     if(is_gecko_special_uri(spec))
2627         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2628
2629     if(!strncmp(spec, "wine:", 5)) {
2630         spec += 5;
2631         is_wine_uri = TRUE;
2632     }
2633
2634     if(aBaseURI) {
2635         PARSEDURLA parsed_url = {sizeof(PARSEDURLA)};
2636
2637         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsIWineURI, (void**)&base_wine_uri);
2638         if(NS_SUCCEEDED(nsres)) {
2639             nsIWineURI_GetWineURL(base_wine_uri, &base_wine_url);
2640             nsIWineURI_GetWindow(base_wine_uri, &window);
2641             TRACE("base url: %s window: %p\n", debugstr_w(base_wine_url), window);
2642         }else if(FAILED(ParseURLA(spec, &parsed_url))) {
2643             TRACE("not wraping\n");
2644             return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2645         }else {
2646             WARN("Could not get base nsIWineURI: %08x\n", nsres);
2647         }
2648     }
2649
2650     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
2651     if(NS_FAILED(nsres))
2652         TRACE("NewURI failed: %08x\n", nsres);
2653
2654     nsres = create_uri(uri, window, NULL, &wine_uri);
2655     *_retval = (nsIURI*)wine_uri;
2656
2657     if(window)
2658         IHTMLWindow2_Release(HTMLWINDOW2(window));
2659
2660     if(base_wine_url) {
2661         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2662         DWORD len;
2663         HRESULT hres;
2664
2665         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2666
2667         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2668                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2669                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2670         if(SUCCEEDED(hres))
2671             nsIWineURI_SetWineURL(wine_uri, url);
2672         else
2673              WARN("CoCombineUrl failed: %08x\n", hres);
2674     }else if(is_wine_uri) {
2675         WCHAR url[INTERNET_MAX_URL_LENGTH];
2676
2677         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2678         nsIWineURI_SetWineURL(wine_uri, url);
2679     }
2680
2681     if(base_wine_uri)
2682         nsIWineURI_Release(base_wine_uri);
2683
2684     return nsres;
2685 }
2686
2687 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2688                                              nsIURI **_retval)
2689 {
2690     TRACE("(%p %p)\n", aFile, _retval);
2691     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2692 }
2693
2694 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2695                                                      nsIChannel **_retval)
2696 {
2697     PARSEDURLW parsed_url = {sizeof(PARSEDURLW)};
2698     nsIChannel *channel = NULL;
2699     nsChannel *ret;
2700     nsIWineURI *wine_uri;
2701     const WCHAR *url;
2702     nsresult nsres;
2703
2704     TRACE("(%p %p)\n", aURI, _retval);
2705
2706     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
2707     if(NS_FAILED(nsres)) {
2708         TRACE("Could not get nsIWineURI: %08x\n", nsres);
2709         return nsIIOService_NewChannelFromURI(nsio, aURI, _retval);
2710     }
2711
2712     nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
2713
2714     ret = heap_alloc_zero(sizeof(nsChannel));
2715
2716     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2717     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2718     ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
2719     ret->ref = 1;
2720     ret->channel = channel;
2721     ret->uri = wine_uri;
2722
2723     nsIURI_AddRef(aURI);
2724     ret->original_uri = aURI;
2725
2726     nsIWineURI_GetWineURL(wine_uri, &url);
2727     ret->url_scheme = url && SUCCEEDED(ParseURLW(url, &parsed_url)) ? parsed_url.nScheme : URL_SCHEME_UNKNOWN;
2728
2729     if(channel) {
2730         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
2731         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannelInternal, (void**)&ret->http_channel_internal);
2732     }
2733
2734     *_retval = NSCHANNEL(ret);
2735     return NS_OK;
2736 }
2737
2738 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2739         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2740 {
2741     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2742     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2743 }
2744
2745 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2746 {
2747     TRACE("(%p)\n", aOffline);
2748     return nsIIOService_GetOffline(nsio, aOffline);
2749 }
2750
2751 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2752 {
2753     TRACE("(%x)\n", aOffline);
2754     return nsIIOService_SetOffline(nsio, aOffline);
2755 }
2756
2757 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2758                                              const char *aScheme, PRBool *_retval)
2759 {
2760     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2761     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2762 }
2763
2764 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2765                                                  nsACString * _retval)
2766 {
2767     TRACE("(%p %p)\n", urlString, _retval);
2768     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2769 }
2770
2771 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2772     nsIOService_QueryInterface,
2773     nsIOService_AddRef,
2774     nsIOService_Release,
2775     nsIOService_GetProtocolHandler,
2776     nsIOService_GetProtocolFlags,
2777     nsIOService_NewURI,
2778     nsIOService_NewFileURI,
2779     nsIOService_NewChannelFromURI,
2780     nsIOService_NewChannel,
2781     nsIOService_GetOffline,
2782     nsIOService_SetOffline,
2783     nsIOService_AllowPort,
2784     nsIOService_ExtractScheme
2785 };
2786
2787 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2788
2789 static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid,
2790                                                nsQIResult result)
2791 {
2792     return nsIIOService_QueryInterface(&nsIOService, riid, result);
2793 }
2794
2795 static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface)
2796 {
2797     return 2;
2798 }
2799
2800 static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface)
2801 {
2802     return 1;
2803 }
2804
2805 static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2806         nsACString *aCharset, PRBool *aHadCharset, nsACString *aContentType)
2807 {
2808     TRACE("(%p %p %p %p)\n", aTypeHeader, aCharset, aHadCharset, aContentType);
2809
2810     return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType);
2811 }
2812
2813 static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2814 {
2815     TRACE("()\n");
2816
2817     return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval);
2818 }
2819
2820 static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2821 {
2822     TRACE("(%p %08x %p)\n", aURI, aFlags, _retval);
2823
2824     if(aFlags == (1<<11)) {
2825         *_retval = FALSE;
2826         return NS_OK;
2827     }
2828
2829     return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval);
2830 }
2831
2832 static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2833 {
2834     TRACE("(%p %p)\n", aURI, _retval);
2835
2836     return nsINetUtil_ToImmutableURI(net_util, aURI, _retval);
2837 }
2838
2839 static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString,
2840                                              PRUint32 aEscapeType, nsACString *_retval)
2841 {
2842     TRACE("(%p %x %p)\n", aString, aEscapeType, _retval);
2843
2844     return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval);
2845 }
2846
2847 static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags,
2848                                           nsACString *_retval)
2849 {
2850     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2851
2852     return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval);
2853 }
2854
2855 static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr,
2856                                                PRUint32 aFlags, nsACString *_retval)
2857 {
2858     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2859
2860     return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval);
2861 }
2862
2863 static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2864         nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, PRBool *_retval)
2865 {
2866     TRACE("(%p %p %p %p %p)\n", aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2867
2868     return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2869 }
2870
2871 static const nsINetUtilVtbl nsNetUtilVtbl = {
2872     nsNetUtil_QueryInterface,
2873     nsNetUtil_AddRef,
2874     nsNetUtil_Release,
2875     nsNetUtil_ParseContentType,
2876     nsNetUtil_ProtocolHasFlags,
2877     nsNetUtil_URIChainHasFlags,
2878     nsNetUtil_ToImmutableURI,
2879     nsNetUtil_EscapeString,
2880     nsNetUtil_EscapeURL,
2881     nsNetUtil_UnescapeString,
2882     nsNetUtil_ExtractCharsetFromContentType
2883 };
2884
2885 static nsINetUtil nsNetUtil = { &nsNetUtilVtbl };
2886
2887 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
2888                                                  nsQIResult result)
2889 {
2890     *result = NULL;
2891
2892     if(IsEqualGUID(&IID_nsISupports, riid))
2893         *result = &nsIOService;
2894     else if(IsEqualGUID(&IID_nsIIOService, riid))
2895         *result = &nsIOService;
2896     else if(IsEqualGUID(&IID_nsINetUtil, riid))
2897         *result = &nsNetUtil;
2898
2899     if(*result) {
2900         nsISupports_AddRef((nsISupports*)*result);
2901         return NS_OK;
2902     }
2903
2904     FIXME("(%s %p)\n", debugstr_guid(riid), result);
2905     return NS_NOINTERFACE;
2906 }
2907
2908 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2909                                                         nsQIResult result)
2910 {
2911     *result = NULL;
2912
2913     if(IsEqualGUID(&IID_nsISupports, riid)) {
2914         TRACE("(IID_nsISupports %p)\n", result);
2915         *result = iface;
2916     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2917         TRACE("(IID_nsIFactory %p)\n", result);
2918         *result = iface;
2919     }
2920
2921     if(*result) {
2922         nsIFactory_AddRef(iface);
2923         return NS_OK;
2924     }
2925
2926     WARN("(%s %p)\n", debugstr_guid(riid), result);
2927     return NS_NOINTERFACE;
2928 }
2929
2930 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2931 {
2932     return 2;
2933 }
2934
2935 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2936 {
2937     return 1;
2938 }
2939
2940 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2941         nsISupports *aOuter, const nsIID *iid, void **result)
2942 {
2943     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2944 }
2945
2946 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2947 {
2948     WARN("(%x)\n", lock);
2949     return NS_OK;
2950 }
2951
2952 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2953     nsIOServiceFactory_QueryInterface,
2954     nsIOServiceFactory_AddRef,
2955     nsIOServiceFactory_Release,
2956     nsIOServiceFactory_CreateInstance,
2957     nsIOServiceFactory_LockFactory
2958 };
2959
2960 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2961
2962 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2963 {
2964     nsIFactory *old_factory = NULL;
2965     nsresult nsres;
2966
2967     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2968                                                &IID_nsIFactory, (void**)&old_factory);
2969     if(NS_FAILED(nsres)) {
2970         ERR("Could not get factory: %08x\n", nsres);
2971         return;
2972     }
2973
2974     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2975     if(NS_FAILED(nsres)) {
2976         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2977         nsIFactory_Release(old_factory);
2978         return;
2979     }
2980
2981     nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util);
2982     if(NS_FAILED(nsres)) {
2983         WARN("Could not get nsINetUtil interface: %08x\n", nsres);
2984         nsIIOService_Release(nsio);
2985         return;
2986     }
2987
2988     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2989     nsIFactory_Release(old_factory);
2990     if(NS_FAILED(nsres))
2991         ERR("UnregisterFactory failed: %08x\n", nsres);
2992
2993     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2994             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2995     if(NS_FAILED(nsres))
2996         ERR("RegisterFactory failed: %08x\n", nsres);
2997 }
2998
2999 void release_nsio(void)
3000 {
3001     if(net_util) {
3002         nsINetUtil_Release(net_util);
3003         net_util = NULL;
3004     }
3005
3006     if(nsio) {
3007         nsIIOService_Release(nsio);
3008         nsio = NULL;
3009     }
3010 }