mshtml: Avoid crash in nsIURI:Equals if other_url is NULL.
[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
2004     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
2005
2006     if(This->nsurl)
2007         return nsIURL_SetRef(This->nsurl, aRef);
2008
2009     FIXME("default action not implemented\n");
2010     return NS_ERROR_NOT_IMPLEMENTED;
2011 }
2012
2013 static nsresult NSAPI nsURL_GetDirectory(nsIWineURI *iface, nsACString *aDirectory)
2014 {
2015     nsURI *This = NSURI_THIS(iface);
2016
2017     TRACE("(%p)->(%p)\n", This, aDirectory);
2018
2019     if(This->nsurl)
2020         return nsIURL_GetDirectory(This->nsurl, aDirectory);
2021
2022     FIXME("default action not implemented\n");
2023     return NS_ERROR_NOT_IMPLEMENTED;
2024 }
2025
2026 static nsresult NSAPI nsURL_SetDirectory(nsIWineURI *iface, const nsACString *aDirectory)
2027 {
2028     nsURI *This = NSURI_THIS(iface);
2029
2030     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
2031
2032     if(This->nsurl)
2033         return nsIURL_SetDirectory(This->nsurl, aDirectory);
2034
2035     FIXME("default action not implemented\n");
2036     return NS_ERROR_NOT_IMPLEMENTED;
2037 }
2038
2039 static nsresult NSAPI nsURL_GetFileName(nsIWineURI *iface, nsACString *aFileName)
2040 {
2041     nsURI *This = NSURI_THIS(iface);
2042
2043     TRACE("(%p)->(%p)\n", This, aFileName);
2044
2045     if(This->nsurl)
2046         return nsIURL_GetFileName(This->nsurl, aFileName);
2047
2048     FIXME("default action not implemented\n");
2049     return NS_ERROR_NOT_IMPLEMENTED;
2050 }
2051
2052 static nsresult NSAPI nsURL_SetFileName(nsIWineURI *iface, const nsACString *aFileName)
2053 {
2054     nsURI *This = NSURI_THIS(iface);
2055
2056     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
2057
2058     if(This->nsurl)
2059         return nsIURL_SetFileName(This->nsurl, aFileName);
2060
2061     FIXME("default action not implemented\n");
2062     return NS_ERROR_NOT_IMPLEMENTED;
2063 }
2064
2065 static nsresult NSAPI nsURL_GetFileBaseName(nsIWineURI *iface, nsACString *aFileBaseName)
2066 {
2067     nsURI *This = NSURI_THIS(iface);
2068
2069     TRACE("(%p)->(%p)\n", This, aFileBaseName);
2070
2071     if(This->nsurl)
2072         return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
2073
2074     FIXME("default action not implemented\n");
2075     return NS_ERROR_NOT_IMPLEMENTED;
2076 }
2077
2078 static nsresult NSAPI nsURL_SetFileBaseName(nsIWineURI *iface, const nsACString *aFileBaseName)
2079 {
2080     nsURI *This = NSURI_THIS(iface);
2081
2082     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
2083
2084     if(This->nsurl)
2085         return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
2086
2087     FIXME("default action not implemented\n");
2088     return NS_ERROR_NOT_IMPLEMENTED;
2089 }
2090
2091 static nsresult NSAPI nsURL_GetFileExtension(nsIWineURI *iface, nsACString *aFileExtension)
2092 {
2093     nsURI *This = NSURI_THIS(iface);
2094
2095     TRACE("(%p)->(%p)\n", This, aFileExtension);
2096
2097     if(This->nsurl)
2098         return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
2099
2100     FIXME("default action not implemented\n");
2101     return NS_ERROR_NOT_IMPLEMENTED;
2102 }
2103
2104 static nsresult NSAPI nsURL_SetFileExtension(nsIWineURI *iface, const nsACString *aFileExtension)
2105 {
2106     nsURI *This = NSURI_THIS(iface);
2107
2108     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
2109
2110     if(This->nsurl)
2111         return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
2112
2113     FIXME("default action not implemented\n");
2114     return NS_ERROR_NOT_IMPLEMENTED;
2115 }
2116
2117 static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2118 {
2119     nsURI *This = NSURI_THIS(iface);
2120
2121     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2122
2123     if(This->nsurl)
2124         return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
2125
2126     FIXME("default action not implemented\n");
2127     return NS_ERROR_NOT_IMPLEMENTED;
2128 }
2129
2130 static nsresult NSAPI nsURL_GetRelativeSpec(nsIWineURI *iface, nsIURI *aURIToCompare, nsACString *_retval)
2131 {
2132     nsURI *This = NSURI_THIS(iface);
2133
2134     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2135
2136     if(This->nsurl)
2137         return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
2138
2139     FIXME("default action not implemented\n");
2140     return NS_ERROR_NOT_IMPLEMENTED;
2141 }
2142
2143 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
2144 {
2145     nsURI *This = NSURI_THIS(iface);
2146
2147     TRACE("(%p)->(%p)\n", This, aContainer);
2148
2149     if(This->container)
2150         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
2151     *aContainer = This->container;
2152
2153     return NS_OK;
2154 }
2155
2156 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
2157 {
2158     nsURI *This = NSURI_THIS(iface);
2159
2160     TRACE("(%p)->(%p)\n", This, aContainer);
2161
2162     if(This->container) {
2163         if(This->container == aContainer)
2164             return NS_OK;
2165         TRACE("Changing %p -> %p\n", This->container, aContainer);
2166         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
2167     }
2168
2169     if(aContainer)
2170         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
2171     This->container = aContainer;
2172
2173     return NS_OK;
2174 }
2175
2176 static nsresult NSAPI nsURI_GetWindow(nsIWineURI *iface, HTMLWindow **aHTMLWindow)
2177 {
2178     nsURI *This = NSURI_THIS(iface);
2179
2180     TRACE("(%p)->(%p)\n", This, aHTMLWindow);
2181
2182     if(This->window_ref && This->window_ref->window) {
2183         IHTMLWindow2_AddRef(HTMLWINDOW2(This->window_ref->window));
2184         *aHTMLWindow = This->window_ref->window;
2185     }else {
2186         *aHTMLWindow = NULL;
2187     }
2188
2189     return NS_OK;
2190 }
2191
2192 static nsresult NSAPI nsURI_SetWindow(nsIWineURI *iface, HTMLWindow *aHTMLWindow)
2193 {
2194     nsURI *This = NSURI_THIS(iface);
2195
2196     TRACE("(%p)->(%p)\n", This, aHTMLWindow);
2197
2198     if(This->window_ref) {
2199         if(This->window_ref->window == aHTMLWindow)
2200             return NS_OK;
2201         TRACE("Changing %p -> %p\n", This->window_ref->window, aHTMLWindow);
2202         windowref_release(This->window_ref);
2203     }
2204
2205     if(aHTMLWindow) {
2206         windowref_addref(aHTMLWindow->window_ref);
2207         This->window_ref = aHTMLWindow->window_ref;
2208
2209         if(aHTMLWindow->doc_obj)
2210             nsIWineURI_SetNSContainer(NSWINEURI(This), aHTMLWindow->doc_obj->nscontainer);
2211     }else {
2212         This->window_ref = NULL;
2213     }
2214
2215     return NS_OK;
2216 }
2217
2218 static nsresult NSAPI nsURI_GetIsDocumentURI(nsIWineURI *iface, PRBool *aIsDocumentURI)
2219 {
2220     nsURI *This = NSURI_THIS(iface);
2221
2222     TRACE("(%p)->(%p)\n", This, aIsDocumentURI);
2223
2224     *aIsDocumentURI = This->is_doc_uri;
2225     return NS_OK;
2226 }
2227
2228 static nsresult NSAPI nsURI_SetIsDocumentURI(nsIWineURI *iface, PRBool aIsDocumentURI)
2229 {
2230     nsURI *This = NSURI_THIS(iface);
2231
2232     TRACE("(%p)->(%x)\n", This, aIsDocumentURI);
2233
2234     This->is_doc_uri = aIsDocumentURI;
2235     return NS_OK;
2236 }
2237
2238 static nsresult NSAPI nsURI_GetWineURL(nsIWineURI *iface, LPCWSTR *aURL)
2239 {
2240     nsURI *This = NSURI_THIS(iface);
2241
2242     TRACE("(%p)->(%p)\n", This, aURL);
2243
2244     *aURL = This->wine_url;
2245     return NS_OK;
2246 }
2247
2248 static nsresult NSAPI nsURI_SetWineURL(nsIWineURI *iface, LPCWSTR aURL)
2249 {
2250     nsURI *This = NSURI_THIS(iface);
2251
2252     static const WCHAR wszFtp[]   = {'f','t','p',':'};
2253     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
2254     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
2255
2256     TRACE("(%p)->(%s)\n", This, debugstr_w(aURL));
2257
2258     heap_free(This->wine_url);
2259
2260     if(aURL) {
2261         int len = strlenW(aURL)+1;
2262         This->wine_url = heap_alloc(len*sizeof(WCHAR));
2263         memcpy(This->wine_url, aURL, len*sizeof(WCHAR));
2264
2265         /* FIXME: Always use wine url */
2266         This->use_wine_url =
2267                strncmpW(aURL, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
2268             && strncmpW(aURL, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
2269             && strncmpW(aURL, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
2270     }else {
2271         This->wine_url = NULL;
2272         This->use_wine_url = FALSE;
2273     }
2274
2275     return NS_OK;
2276 }
2277
2278 #undef NSURI_THIS
2279
2280 static const nsIWineURIVtbl nsWineURIVtbl = {
2281     nsURI_QueryInterface,
2282     nsURI_AddRef,
2283     nsURI_Release,
2284     nsURI_GetSpec,
2285     nsURI_SetSpec,
2286     nsURI_GetPrePath,
2287     nsURI_GetScheme,
2288     nsURI_SetScheme,
2289     nsURI_GetUserPass,
2290     nsURI_SetUserPass,
2291     nsURI_GetUsername,
2292     nsURI_SetUsername,
2293     nsURI_GetPassword,
2294     nsURI_SetPassword,
2295     nsURI_GetHostPort,
2296     nsURI_SetHostPort,
2297     nsURI_GetHost,
2298     nsURI_SetHost,
2299     nsURI_GetPort,
2300     nsURI_SetPort,
2301     nsURI_GetPath,
2302     nsURI_SetPath,
2303     nsURI_Equals,
2304     nsURI_SchemeIs,
2305     nsURI_Clone,
2306     nsURI_Resolve,
2307     nsURI_GetAsciiSpec,
2308     nsURI_GetAsciiHost,
2309     nsURI_GetOriginCharset,
2310     nsURL_GetFilePath,
2311     nsURL_SetFilePath,
2312     nsURL_GetParam,
2313     nsURL_SetParam,
2314     nsURL_GetQuery,
2315     nsURL_SetQuery,
2316     nsURL_GetRef,
2317     nsURL_SetRef,
2318     nsURL_GetDirectory,
2319     nsURL_SetDirectory,
2320     nsURL_GetFileName,
2321     nsURL_SetFileName,
2322     nsURL_GetFileBaseName,
2323     nsURL_SetFileBaseName,
2324     nsURL_GetFileExtension,
2325     nsURL_SetFileExtension,
2326     nsURL_GetCommonBaseSpec,
2327     nsURL_GetRelativeSpec,
2328     nsURI_GetNSContainer,
2329     nsURI_SetNSContainer,
2330     nsURI_GetWindow,
2331     nsURI_SetWindow,
2332     nsURI_GetIsDocumentURI,
2333     nsURI_SetIsDocumentURI,
2334     nsURI_GetWineURL,
2335     nsURI_SetWineURL
2336 };
2337
2338 static nsresult create_uri(nsIURI *uri, HTMLWindow *window, NSContainer *container, nsIWineURI **_retval)
2339 {
2340     nsURI *ret = heap_alloc_zero(sizeof(nsURI));
2341
2342     ret->lpWineURIVtbl = &nsWineURIVtbl;
2343     ret->ref = 1;
2344     ret->uri = uri;
2345
2346     nsIWineURI_SetNSContainer(NSWINEURI(ret), container);
2347     nsIWineURI_SetWindow(NSWINEURI(ret), window);
2348
2349     if(uri)
2350         nsIURI_QueryInterface(uri, &IID_nsIURL, (void**)&ret->nsurl);
2351     else
2352         ret->nsurl = NULL;
2353
2354     TRACE("retval=%p\n", ret);
2355     *_retval = NSWINEURI(ret);
2356     return NS_OK;
2357 }
2358
2359 typedef struct {
2360     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
2361
2362     LONG ref;
2363
2364     nsIProtocolHandler *nshandler;
2365 } nsProtocolHandler;
2366
2367 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
2368
2369 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
2370
2371 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
2372         nsQIResult result)
2373 {
2374     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2375
2376     *result = NULL;
2377
2378     if(IsEqualGUID(&IID_nsISupports, riid)) {
2379         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
2380         *result = NSPROTHANDLER(This);
2381     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
2382         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
2383         *result = NSPROTHANDLER(This);
2384     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
2385         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
2386         return NS_NOINTERFACE;
2387     }
2388
2389     if(*result) {
2390         nsISupports_AddRef((nsISupports*)*result);
2391         return NS_OK;
2392     }
2393
2394     WARN("(%s %p)\n", debugstr_guid(riid), result);
2395     return NS_NOINTERFACE;
2396 }
2397
2398 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
2399 {
2400     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2401     LONG ref = InterlockedIncrement(&This->ref);
2402
2403     TRACE("(%p) ref=%d\n", This, ref);
2404
2405     return ref;
2406 }
2407
2408 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
2409 {
2410     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2411     LONG ref = InterlockedDecrement(&This->ref);
2412
2413     TRACE("(%p) ref=%d\n", This, ref);
2414
2415     if(!ref) {
2416         if(This->nshandler)
2417             nsIProtocolHandler_Release(This->nshandler);
2418         heap_free(This);
2419     }
2420
2421     return ref;
2422 }
2423
2424 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
2425 {
2426     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2427
2428     TRACE("(%p)->(%p)\n", This, aScheme);
2429
2430     if(This->nshandler)
2431         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
2432     return NS_ERROR_NOT_IMPLEMENTED;
2433 }
2434
2435 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
2436         PRInt32 *aDefaultPort)
2437 {
2438     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2439
2440     TRACE("(%p)->(%p)\n", This, aDefaultPort);
2441
2442     if(This->nshandler)
2443         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
2444     return NS_ERROR_NOT_IMPLEMENTED;
2445 }
2446
2447 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
2448                                                          PRUint32 *aProtocolFlags)
2449 {
2450     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2451
2452     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
2453
2454     if(This->nshandler)
2455         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
2456     return NS_ERROR_NOT_IMPLEMENTED;
2457 }
2458
2459 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
2460         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2461 {
2462     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2463
2464     TRACE("((%p)->%p %s %p %p)\n", This, aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2465
2466     if(This->nshandler)
2467         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
2468     return NS_ERROR_NOT_IMPLEMENTED;
2469 }
2470
2471 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
2472         nsIURI *aURI, nsIChannel **_retval)
2473 {
2474     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2475
2476     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
2477
2478     if(This->nshandler)
2479         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
2480     return NS_ERROR_NOT_IMPLEMENTED;
2481 }
2482
2483 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
2484         PRInt32 port, const char *scheme, PRBool *_retval)
2485 {
2486     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2487
2488     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
2489
2490     if(This->nshandler)
2491         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
2492     return NS_ERROR_NOT_IMPLEMENTED;
2493 }
2494
2495 #undef NSPROTHANDLER_THIS
2496
2497 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
2498     nsProtocolHandler_QueryInterface,
2499     nsProtocolHandler_AddRef,
2500     nsProtocolHandler_Release,
2501     nsProtocolHandler_GetScheme,
2502     nsProtocolHandler_GetDefaultPort,
2503     nsProtocolHandler_GetProtocolFlags,
2504     nsProtocolHandler_NewURI,
2505     nsProtocolHandler_NewChannel,
2506     nsProtocolHandler_AllowPort
2507 };
2508
2509 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
2510 {
2511     nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler));
2512
2513     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
2514     ret->ref = 1;
2515     ret->nshandler = nshandler;
2516
2517     return NSPROTHANDLER(ret);
2518 }
2519
2520 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,nsQIResult);
2521
2522 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
2523 {
2524     return 2;
2525 }
2526
2527 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
2528 {
2529     return 1;
2530 }
2531
2532 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
2533                                                      nsIProtocolHandler **_retval)
2534 {
2535     nsIExternalProtocolHandler *nsexthandler;
2536     nsIProtocolHandler *nshandler;
2537     nsresult nsres;
2538
2539     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2540
2541     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
2542     if(NS_FAILED(nsres)) {
2543         WARN("GetProtocolHandler failed: %08x\n", nsres);
2544         return nsres;
2545     }
2546
2547     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
2548                                               (void**)&nsexthandler);
2549     if(NS_FAILED(nsres)) {
2550         *_retval = nshandler;
2551         return NS_OK;
2552     }
2553
2554     nsIExternalProtocolHandler_Release(nsexthandler);
2555     *_retval = create_protocol_handler(nshandler);
2556     TRACE("return %p\n", *_retval);
2557     return NS_OK;
2558 }
2559
2560 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
2561                                                     PRUint32 *_retval)
2562 {
2563     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2564     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
2565 }
2566
2567 static BOOL is_gecko_special_uri(const char *spec)
2568 {
2569     static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
2570     int i;
2571
2572     for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
2573         if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
2574             return TRUE;
2575     }
2576
2577     return FALSE;
2578 }
2579
2580 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
2581         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2582 {
2583     const char *spec = NULL;
2584     HTMLWindow *window = NULL;
2585     nsIURI *uri = NULL;
2586     LPCWSTR base_wine_url = NULL;
2587     nsIWineURI *base_wine_uri = NULL, *wine_uri;
2588     BOOL is_wine_uri = FALSE;
2589     nsresult nsres;
2590
2591     nsACString_GetData(aSpec, &spec);
2592
2593     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
2594           aBaseURI, _retval);
2595
2596     if(is_gecko_special_uri(spec))
2597         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2598
2599     if(!strncmp(spec, "wine:", 5)) {
2600         spec += 5;
2601         is_wine_uri = TRUE;
2602     }
2603
2604     if(aBaseURI) {
2605         nsACString base_uri_str;
2606         const char *base_uri = NULL;
2607
2608         nsACString_Init(&base_uri_str, NULL);
2609
2610         nsres = nsIURI_GetSpec(aBaseURI, &base_uri_str);
2611         if(NS_SUCCEEDED(nsres)) {
2612             nsACString_GetData(&base_uri_str, &base_uri);
2613             TRACE("base_uri=%s\n", debugstr_a(base_uri));
2614         }else {
2615             ERR("GetSpec failed: %08x\n", nsres);
2616         }
2617
2618         nsACString_Finish(&base_uri_str);
2619     }
2620
2621     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
2622     if(NS_FAILED(nsres))
2623         TRACE("NewURI failed: %08x\n", nsres);
2624
2625     if(aBaseURI) {
2626         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsIWineURI, (void**)&base_wine_uri);
2627         if(NS_SUCCEEDED(nsres)) {
2628             nsIWineURI_GetWindow(base_wine_uri, &window);
2629             nsIWineURI_GetWineURL(base_wine_uri, &base_wine_url);
2630         }else {
2631             TRACE("Could not get base nsIWineURI: %08x\n", nsres);
2632         }
2633     }
2634
2635     TRACE("window = %p\n", window);
2636
2637     nsres = create_uri(uri, window, NULL, &wine_uri);
2638     *_retval = (nsIURI*)wine_uri;
2639
2640     if(window)
2641         IHTMLWindow2_Release(HTMLWINDOW2(window));
2642
2643     if(base_wine_url) {
2644         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2645         DWORD len;
2646         HRESULT hres;
2647
2648         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2649
2650         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2651                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2652                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2653         if(SUCCEEDED(hres))
2654             nsIWineURI_SetWineURL(wine_uri, url);
2655         else
2656              WARN("CoCombineUrl failed: %08x\n", hres);
2657     }else if(is_wine_uri) {
2658         WCHAR url[INTERNET_MAX_URL_LENGTH];
2659
2660         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2661         nsIWineURI_SetWineURL(wine_uri, url);
2662     }
2663
2664     if(base_wine_uri)
2665         nsIWineURI_Release(base_wine_uri);
2666
2667     return nsres;
2668 }
2669
2670 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2671                                              nsIURI **_retval)
2672 {
2673     TRACE("(%p %p)\n", aFile, _retval);
2674     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2675 }
2676
2677 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2678                                                      nsIChannel **_retval)
2679 {
2680     nsIChannel *channel = NULL;
2681     nsChannel *ret;
2682     nsIWineURI *wine_uri;
2683     nsresult nsres;
2684
2685     TRACE("(%p %p)\n", aURI, _retval);
2686
2687     nsres = nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
2688     if(NS_FAILED(nsres) && nsres != NS_ERROR_UNKNOWN_PROTOCOL) {
2689         WARN("NewChannelFromURI failed: %08x\n", nsres);
2690         *_retval = channel;
2691         return nsres;
2692     }
2693
2694     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
2695     if(NS_FAILED(nsres)) {
2696         WARN("Could not get nsIWineURI: %08x\n", nsres);
2697         *_retval = channel;
2698         return channel ? NS_OK : NS_ERROR_UNEXPECTED;
2699     }
2700
2701     ret = heap_alloc_zero(sizeof(nsChannel));
2702
2703     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2704     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2705     ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
2706     ret->ref = 1;
2707     ret->channel = channel;
2708     ret->uri = wine_uri;
2709
2710     nsIURI_AddRef(aURI);
2711     ret->original_uri = aURI;
2712
2713     if(channel) {
2714         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
2715         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannelInternal, (void**)&ret->http_channel_internal);
2716     }
2717
2718     *_retval = NSCHANNEL(ret);
2719     return NS_OK;
2720 }
2721
2722 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2723         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2724 {
2725     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2726     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2727 }
2728
2729 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2730 {
2731     TRACE("(%p)\n", aOffline);
2732     return nsIIOService_GetOffline(nsio, aOffline);
2733 }
2734
2735 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2736 {
2737     TRACE("(%x)\n", aOffline);
2738     return nsIIOService_SetOffline(nsio, aOffline);
2739 }
2740
2741 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2742                                              const char *aScheme, PRBool *_retval)
2743 {
2744     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2745     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2746 }
2747
2748 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2749                                                  nsACString * _retval)
2750 {
2751     TRACE("(%p %p)\n", urlString, _retval);
2752     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2753 }
2754
2755 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2756     nsIOService_QueryInterface,
2757     nsIOService_AddRef,
2758     nsIOService_Release,
2759     nsIOService_GetProtocolHandler,
2760     nsIOService_GetProtocolFlags,
2761     nsIOService_NewURI,
2762     nsIOService_NewFileURI,
2763     nsIOService_NewChannelFromURI,
2764     nsIOService_NewChannel,
2765     nsIOService_GetOffline,
2766     nsIOService_SetOffline,
2767     nsIOService_AllowPort,
2768     nsIOService_ExtractScheme
2769 };
2770
2771 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2772
2773 static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid,
2774                                                nsQIResult result)
2775 {
2776     return nsIIOService_QueryInterface(&nsIOService, riid, result);
2777 }
2778
2779 static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface)
2780 {
2781     return 2;
2782 }
2783
2784 static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface)
2785 {
2786     return 1;
2787 }
2788
2789 static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2790         nsACString *aCharset, PRBool *aHadCharset, nsACString *aContentType)
2791 {
2792     TRACE("(%p %p %p %p)\n", aTypeHeader, aCharset, aHadCharset, aContentType);
2793
2794     return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType);
2795 }
2796
2797 static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2798 {
2799     TRACE("()\n");
2800
2801     return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval);
2802 }
2803
2804 static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2805 {
2806     TRACE("(%p %08x %p)\n", aURI, aFlags, _retval);
2807
2808     if(aFlags == (1<<11)) {
2809         *_retval = FALSE;
2810         return NS_OK;
2811     }
2812
2813     return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval);
2814 }
2815
2816 static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2817 {
2818     TRACE("(%p %p)\n", aURI, _retval);
2819
2820     return nsINetUtil_ToImmutableURI(net_util, aURI, _retval);
2821 }
2822
2823 static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString,
2824                                              PRUint32 aEscapeType, nsACString *_retval)
2825 {
2826     TRACE("(%p %x %p)\n", aString, aEscapeType, _retval);
2827
2828     return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval);
2829 }
2830
2831 static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags,
2832                                           nsACString *_retval)
2833 {
2834     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2835
2836     return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval);
2837 }
2838
2839 static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr,
2840                                                PRUint32 aFlags, nsACString *_retval)
2841 {
2842     TRACE("(%p %08x %p)\n", aStr, aFlags, _retval);
2843
2844     return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval);
2845 }
2846
2847 static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2848         nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, PRBool *_retval)
2849 {
2850     TRACE("(%p %p %p %p %p)\n", aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2851
2852     return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2853 }
2854
2855 static const nsINetUtilVtbl nsNetUtilVtbl = {
2856     nsNetUtil_QueryInterface,
2857     nsNetUtil_AddRef,
2858     nsNetUtil_Release,
2859     nsNetUtil_ParseContentType,
2860     nsNetUtil_ProtocolHasFlags,
2861     nsNetUtil_URIChainHasFlags,
2862     nsNetUtil_ToImmutableURI,
2863     nsNetUtil_EscapeString,
2864     nsNetUtil_EscapeURL,
2865     nsNetUtil_UnescapeString,
2866     nsNetUtil_ExtractCharsetFromContentType
2867 };
2868
2869 static nsINetUtil nsNetUtil = { &nsNetUtilVtbl };
2870
2871 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
2872                                                  nsQIResult result)
2873 {
2874     *result = NULL;
2875
2876     if(IsEqualGUID(&IID_nsISupports, riid))
2877         *result = &nsIOService;
2878     else if(IsEqualGUID(&IID_nsIIOService, riid))
2879         *result = &nsIOService;
2880     else if(IsEqualGUID(&IID_nsINetUtil, riid))
2881         *result = &nsNetUtil;
2882
2883     if(*result) {
2884         nsISupports_AddRef((nsISupports*)*result);
2885         return NS_OK;
2886     }
2887
2888     FIXME("(%s %p)\n", debugstr_guid(riid), result);
2889     return NS_NOINTERFACE;
2890 }
2891
2892 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2893                                                         nsQIResult result)
2894 {
2895     *result = NULL;
2896
2897     if(IsEqualGUID(&IID_nsISupports, riid)) {
2898         TRACE("(IID_nsISupports %p)\n", result);
2899         *result = iface;
2900     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2901         TRACE("(IID_nsIFactory %p)\n", result);
2902         *result = iface;
2903     }
2904
2905     if(*result) {
2906         nsIFactory_AddRef(iface);
2907         return NS_OK;
2908     }
2909
2910     WARN("(%s %p)\n", debugstr_guid(riid), result);
2911     return NS_NOINTERFACE;
2912 }
2913
2914 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2915 {
2916     return 2;
2917 }
2918
2919 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2920 {
2921     return 1;
2922 }
2923
2924 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2925         nsISupports *aOuter, const nsIID *iid, void **result)
2926 {
2927     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2928 }
2929
2930 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2931 {
2932     WARN("(%x)\n", lock);
2933     return NS_OK;
2934 }
2935
2936 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2937     nsIOServiceFactory_QueryInterface,
2938     nsIOServiceFactory_AddRef,
2939     nsIOServiceFactory_Release,
2940     nsIOServiceFactory_CreateInstance,
2941     nsIOServiceFactory_LockFactory
2942 };
2943
2944 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2945
2946 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2947 {
2948     nsIFactory *old_factory = NULL;
2949     nsresult nsres;
2950
2951     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2952                                                &IID_nsIFactory, (void**)&old_factory);
2953     if(NS_FAILED(nsres)) {
2954         ERR("Could not get factory: %08x\n", nsres);
2955         return;
2956     }
2957
2958     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2959     if(NS_FAILED(nsres)) {
2960         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2961         nsIFactory_Release(old_factory);
2962         return;
2963     }
2964
2965     nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util);
2966     if(NS_FAILED(nsres)) {
2967         WARN("Could not get nsINetUtil interface: %08x\n", nsres);
2968         nsIIOService_Release(nsio);
2969         return;
2970     }
2971
2972     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2973     nsIFactory_Release(old_factory);
2974     if(NS_FAILED(nsres))
2975         ERR("UnregisterFactory failed: %08x\n", nsres);
2976
2977     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2978             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2979     if(NS_FAILED(nsres))
2980         ERR("RegisterFactory failed: %08x\n", nsres);
2981 }
2982
2983 void release_nsio(void)
2984 {
2985     if(net_util) {
2986         nsINetUtil_Release(net_util);
2987         net_util = NULL;
2988     }
2989
2990     if(nsio) {
2991         nsIIOService_Release(nsio);
2992         nsio = NULL;
2993     }
2994 }