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