wintrust: Add a helper function to initialize chain creation parameters.
[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
51 typedef struct {
52     const nsIWineURIVtbl *lpWineURIVtbl;
53
54     LONG ref;
55
56     nsIURI *uri;
57     NSContainer *container;
58     LPWSTR wine_url;
59     PRBool is_doc_uri;
60     BOOL use_wine_url;
61 } nsURI;
62
63 #define NSURI(x)         ((nsIURI*)            &(x)->lpWineURIVtbl)
64 #define NSWINEURI(x)     ((nsIWineURI*)        &(x)->lpWineURIVtbl)
65
66 static nsresult create_uri(nsIURI*,NSContainer*,nsIWineURI**);
67
68 static BOOL exec_shldocvw_67(HTMLDocument *doc, LPCWSTR url)
69 {
70     IOleCommandTarget *cmdtrg = NULL;
71     HRESULT hres;
72
73     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget,
74                                          (void**)&cmdtrg);
75     if(SUCCEEDED(hres)) {
76         VARIANT varUrl, varRes;
77
78         V_VT(&varUrl) = VT_BSTR;
79         V_BSTR(&varUrl) = SysAllocString(url);
80         V_VT(&varRes) = VT_BOOL;
81
82         hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes);
83
84         IOleCommandTarget_Release(cmdtrg);
85         SysFreeString(V_BSTR(&varUrl));
86
87         if(SUCCEEDED(hres) && !V_BOOL(&varRes)) {
88             TRACE("got VARIANT_FALSE, do not load\n");
89             return FALSE;
90         }
91     }
92
93     return TRUE;
94 }
95
96 static BOOL before_async_open(nsChannel *channel, NSContainer *container)
97 {
98     IServiceProvider *service_provider;
99     HTMLDocument *doc = container->doc;
100     DWORD hlnf = 0;
101     LPCWSTR uri;
102     HRESULT hres;
103
104     nsIWineURI_GetWineURL(channel->uri, &uri);
105     if(!uri) {
106         ERR("GetWineURL returned NULL\n");
107         return TRUE;
108     }
109
110     if(!doc) {
111         NSContainer *container_iter = container;
112
113         hlnf = HLNF_OPENINNEWWINDOW;
114         while(!container_iter->doc)
115             container_iter = container_iter->parent;
116         doc = container_iter->doc;
117     }
118
119     if(!hlnf && !exec_shldocvw_67(doc, uri))
120         return FALSE;
121
122     hres = IOleClientSite_QueryInterface(doc->client, &IID_IServiceProvider,
123                                          (void**)&service_provider);
124     if(SUCCEEDED(hres)) {
125         IHlinkFrame *hlink_frame;
126
127         hres = IServiceProvider_QueryService(service_provider, &IID_IHlinkFrame,
128                                              &IID_IHlinkFrame, (void**)&hlink_frame);
129         IServiceProvider_Release(service_provider);
130         if(SUCCEEDED(hres)) {
131             hlink_frame_navigate(doc, hlink_frame, uri, channel->post_data_stream, hlnf);
132             IHlinkFrame_Release(hlink_frame);
133
134             return FALSE;
135         }
136     }
137
138     return TRUE;
139 }
140
141 #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
142
143 static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, nsQIResult result)
144 {
145     nsChannel *This = NSCHANNEL_THIS(iface);
146
147     *result = NULL;
148
149     if(IsEqualGUID(&IID_nsISupports, riid)) {
150         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
151         *result = NSCHANNEL(This);
152     }else if(IsEqualGUID(&IID_nsIRequest, riid)) {
153         TRACE("(%p)->(IID_nsIRequest %p)\n", This, result);
154         *result = NSCHANNEL(This);
155     }else if(IsEqualGUID(&IID_nsIChannel, riid)) {
156         TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
157         *result = NSCHANNEL(This);
158     }else if(This->http_channel && IsEqualGUID(&IID_nsIHttpChannel, riid)) {
159         TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
160         *result = NSHTTPCHANNEL(This);
161     }else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) {
162         TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result);
163         *result = NSUPCHANNEL(This);
164     }
165
166     if(*result) {
167         nsIChannel_AddRef(NSCHANNEL(This));
168         return NS_OK;
169     }
170
171     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
172
173     if(This->channel)
174         return nsIChannel_QueryInterface(This->channel, riid, result);
175     return NS_NOINTERFACE;
176 }
177
178 static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
179 {
180     nsChannel *This = NSCHANNEL_THIS(iface);
181     nsrefcnt ref = InterlockedIncrement(&This->ref);
182
183     TRACE("(%p) ref=%d\n", This, ref);
184
185     return ref;
186 }
187
188 static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
189 {
190     nsChannel *This = NSCHANNEL_THIS(iface);
191     LONG ref = InterlockedDecrement(&This->ref);
192
193     if(!ref) {
194         nsIWineURI_Release(This->uri);
195         if(This->channel)
196             nsIChannel_Release(This->channel);
197         if(This->http_channel)
198             nsIHttpChannel_Release(This->http_channel);
199         if(This->post_data_stream)
200             nsIInputStream_Release(This->post_data_stream);
201         if(This->load_group)
202             nsILoadGroup_Release(This->load_group);
203         if(This->notif_callback)
204             nsIInterfaceRequestor_Release(This->notif_callback);
205         if(This->original_uri)
206             nsIURI_Release(This->original_uri);
207         mshtml_free(This->content);
208         mshtml_free(This->charset);
209         mshtml_free(This);
210     }
211
212     return ref;
213 }
214
215 static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName)
216 {
217     nsChannel *This = NSCHANNEL_THIS(iface);
218
219     TRACE("(%p)->(%p)\n", This, aName);
220
221     if(This->channel)
222         return nsIChannel_GetName(This->channel, aName);
223
224     return NS_ERROR_NOT_IMPLEMENTED;
225 }
226
227 static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, PRBool *_retval)
228 {
229     nsChannel *This = NSCHANNEL_THIS(iface);
230
231     TRACE("(%p)->(%p)\n", This, _retval);
232
233     if(This->channel)
234         return nsIChannel_IsPending(This->channel, _retval);
235
236     FIXME("default action not implemented\n");
237     return NS_ERROR_NOT_IMPLEMENTED;
238 }
239
240 static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus)
241 {
242     nsChannel *This = NSCHANNEL_THIS(iface);
243
244     TRACE("(%p)->(%p)\n", This, aStatus);
245
246     if(This->channel)
247         return nsIChannel_GetStatus(This->channel, aStatus);
248
249     TRACE("returning NS_OK\n");
250     return *aStatus = NS_OK;
251 }
252
253 static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus)
254 {
255     nsChannel *This = NSCHANNEL_THIS(iface);
256
257     TRACE("(%p)->(%08x)\n", This, aStatus);
258
259     if(This->channel)
260         return nsIChannel_Cancel(This->channel, aStatus);
261
262     FIXME("default action not implemented\n");
263     return NS_ERROR_NOT_IMPLEMENTED;
264 }
265
266 static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface)
267 {
268     nsChannel *This = NSCHANNEL_THIS(iface);
269
270     TRACE("(%p)\n", This);
271
272     if(This->channel)
273         return nsIChannel_Suspend(This->channel);
274
275     FIXME("default action not implemented\n");
276     return NS_ERROR_NOT_IMPLEMENTED;
277 }
278
279 static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface)
280 {
281     nsChannel *This = NSCHANNEL_THIS(iface);
282
283     TRACE("(%p)\n", This);
284
285     if(This->channel)
286         return nsIChannel_Resume(This->channel);
287
288     FIXME("default action not implemented\n");
289     return NS_ERROR_NOT_IMPLEMENTED;
290 }
291
292 static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup)
293 {
294     nsChannel *This = NSCHANNEL_THIS(iface);
295
296     TRACE("(%p)->(%p)\n", This, aLoadGroup);
297
298     if(This->load_group)
299         nsILoadGroup_AddRef(This->load_group);
300
301     *aLoadGroup = This->load_group;
302     return NS_OK;
303 }
304
305 static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup)
306 {
307     nsChannel *This = NSCHANNEL_THIS(iface);
308
309     TRACE("(%p)->(%p)\n", This, aLoadGroup);
310
311     if(This->load_group)
312         nsILoadGroup_Release(This->load_group);
313     if(aLoadGroup)
314         nsILoadGroup_AddRef(aLoadGroup);
315
316     This->load_group = aLoadGroup;
317
318     if(This->channel)
319         return nsIChannel_SetLoadGroup(This->channel, aLoadGroup);
320     return NS_OK;
321 }
322
323 static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags)
324 {
325     nsChannel *This = NSCHANNEL_THIS(iface);
326
327     TRACE("(%p)->(%p)\n", This, aLoadFlags);
328
329     *aLoadFlags = This->load_flags;
330     return NS_OK;
331 }
332
333 static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags)
334 {
335     nsChannel *This = NSCHANNEL_THIS(iface);
336
337     TRACE("(%p)->(%08x)\n", This, aLoadFlags);
338
339     This->load_flags = aLoadFlags;
340
341     if(This->channel)
342         return nsIChannel_SetLoadFlags(This->channel, aLoadFlags);
343     return NS_OK;
344 }
345
346 static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI)
347 {
348     nsChannel *This = NSCHANNEL_THIS(iface);
349
350     TRACE("(%p)->(%p)\n", This, aOriginalURI);
351
352     if(This->original_uri)
353         nsIURI_AddRef(This->original_uri);
354
355     *aOriginalURI = This->original_uri;
356     return NS_OK;
357 }
358
359 static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI)
360 {
361     nsChannel *This = NSCHANNEL_THIS(iface);
362
363     TRACE("(%p)->(%p)\n", This, aOriginalURI);
364
365     if(This->original_uri)
366         nsIURI_Release(This->original_uri);
367
368     nsIURI_AddRef(aOriginalURI);
369     This->original_uri = aOriginalURI;
370
371     if(This->channel)
372         return nsIChannel_SetOriginalURI(This->channel, aOriginalURI);
373     return NS_OK;
374 }
375
376 static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI)
377 {
378     nsChannel *This = NSCHANNEL_THIS(iface);
379
380     TRACE("(%p)->(%p)\n", This, aURI);
381
382     nsIWineURI_AddRef(This->uri);
383     *aURI = (nsIURI*)This->uri;
384
385     return NS_OK;
386 }
387
388 static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner)
389 {
390     nsChannel *This = NSCHANNEL_THIS(iface);
391
392     TRACE("(%p)->(%p)\n", This, aOwner);
393
394     if(This->channel)
395         return nsIChannel_GetOwner(This->channel, aOwner);
396
397     FIXME("default action not implemented\n");
398     return NS_ERROR_NOT_IMPLEMENTED;
399 }
400
401 static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner)
402 {
403     nsChannel *This = NSCHANNEL_THIS(iface);
404
405     TRACE("(%p)->(%p)\n", This, aOwner);
406
407     if(This->channel)
408         return nsIChannel_SetOwner(This->channel, aOwner);
409
410     FIXME("default action not implemented\n");
411     return NS_ERROR_NOT_IMPLEMENTED;
412 }
413
414 static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface,
415         nsIInterfaceRequestor **aNotificationCallbacks)
416 {
417     nsChannel *This = NSCHANNEL_THIS(iface);
418
419     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
420
421     if(This->notif_callback)
422         nsIInterfaceRequestor_AddRef(This->notif_callback);
423     *aNotificationCallbacks = This->notif_callback;
424
425     return NS_OK;
426 }
427
428 static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface,
429         nsIInterfaceRequestor *aNotificationCallbacks)
430 {
431     nsChannel *This = NSCHANNEL_THIS(iface);
432
433     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
434
435     if(This->notif_callback)
436         nsIInterfaceRequestor_Release(This->notif_callback);
437     if(aNotificationCallbacks)
438         nsIInterfaceRequestor_AddRef(aNotificationCallbacks);
439
440     This->notif_callback = aNotificationCallbacks;
441
442     if(This->channel)
443         return nsIChannel_SetNotificationCallbacks(This->channel, aNotificationCallbacks);
444     return NS_OK;
445 }
446
447 static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo)
448 {
449     nsChannel *This = NSCHANNEL_THIS(iface);
450
451     TRACE("(%p)->(%p)\n", This, aSecurityInfo);
452
453     if(This->channel)
454         return nsIChannel_GetSecurityInfo(This->channel, aSecurityInfo);
455
456     FIXME("default action not implemented\n");
457     return NS_ERROR_NOT_IMPLEMENTED;
458 }
459
460 static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType)
461 {
462     nsChannel *This = NSCHANNEL_THIS(iface);
463
464     TRACE("(%p)->(%p)\n", This, aContentType);
465
466     if(This->content) {
467         nsACString_SetData(aContentType, This->content);
468         return S_OK;
469     }
470
471     if(This->channel)
472         return nsIChannel_GetContentType(This->channel, aContentType);
473
474     TRACE("returning default text/html\n");
475     nsACString_SetData(aContentType, "text/html");
476     return NS_OK;
477 }
478
479 static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface,
480                                                const nsACString *aContentType)
481 {
482     nsChannel *This = NSCHANNEL_THIS(iface);
483
484     TRACE("(%p)->(%p)\n", This, aContentType);
485
486     if(This->channel)
487         return nsIChannel_SetContentType(This->channel, aContentType);
488
489     FIXME("default action not implemented\n");
490     return NS_ERROR_NOT_IMPLEMENTED;
491 }
492
493 static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface,
494                                                   nsACString *aContentCharset)
495 {
496     nsChannel *This = NSCHANNEL_THIS(iface);
497
498     TRACE("(%p)->(%p)\n", This, aContentCharset);
499
500     if(This->charset) {
501         nsACString_SetData(aContentCharset, This->charset);
502         return NS_OK;
503     }
504
505     if(This->channel) {
506         nsresult nsres = nsIChannel_GetContentCharset(This->channel, aContentCharset);
507         const char *ch;
508         nsACString_GetData(aContentCharset, &ch, NULL);
509         return nsres;
510     }
511
512     nsACString_SetData(aContentCharset, "");
513     return NS_OK;
514 }
515
516 static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface,
517                                                   const nsACString *aContentCharset)
518 {
519     nsChannel *This = NSCHANNEL_THIS(iface);
520
521     TRACE("(%p)->(%p)\n", This, aContentCharset);
522
523     if(This->channel)
524         return nsIChannel_SetContentCharset(This->channel, aContentCharset);
525
526     FIXME("default action not implemented\n");
527     return NS_ERROR_NOT_IMPLEMENTED;
528 }
529
530 static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength)
531 {
532     nsChannel *This = NSCHANNEL_THIS(iface);
533
534     TRACE("(%p)->(%p)\n", This, aContentLength);
535
536     if(This->channel)
537         return nsIChannel_GetContentLength(This->channel, aContentLength);
538
539     FIXME("default action not implemented\n");
540     return NS_ERROR_NOT_IMPLEMENTED;
541 }
542
543 static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength)
544 {
545     nsChannel *This = NSCHANNEL_THIS(iface);
546
547     TRACE("(%p)->(%d)\n", This, aContentLength);
548
549     if(This->channel)
550         return nsIChannel_SetContentLength(This->channel, aContentLength);
551
552     FIXME("default action not implemented\n");
553     return NS_ERROR_NOT_IMPLEMENTED;
554 }
555
556 static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval)
557 {
558     nsChannel *This = NSCHANNEL_THIS(iface);
559
560     TRACE("(%p)->(%p)\n", This, _retval);
561
562     if(This->channel)
563         return nsIChannel_Open(This->channel, _retval);
564
565     FIXME("default action not implemented\n");
566     return NS_ERROR_NOT_IMPLEMENTED;
567 }
568
569 static BOOL do_load_from_moniker_hack(nsChannel *This)
570 {
571     PRBool b = FALSE;
572
573     /* 
574      * We should always load the page from IMoniker, but Wine is not yet
575      * ready for this. This function is a heuristic, that decides which
576      * way of loading is better (Gecko implementation or IMoniker). The
577      * aim is to always return TRUE.
578      */
579
580     /* Load from moniker if there is no Gecko channel available */
581     if(!This->channel)
582         return TRUE;
583
584     /* Load about protocol from moniker */
585     nsIWineURI_SchemeIs(This->uri, "about", &b);
586     if(b)
587         return TRUE;
588
589     return FALSE;
590 }
591
592 static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
593 {
594     nsIWineURI *wine_uri;
595     LPCWSTR wine_url;
596     nsresult nsres;
597     HRESULT hres;
598
599     if(!channel->original_uri) {
600         ERR("original_uri == NULL\n");
601         return E_FAIL;
602     }
603
604     nsres = nsIURI_QueryInterface(channel->original_uri, &IID_nsIWineURI, (void**)&wine_uri);
605     if(NS_FAILED(nsres)) {
606         ERR("Could not get nsIWineURI: %08x\n", nsres);
607         return E_FAIL;
608     }
609
610     nsIWineURI_GetWineURL(wine_uri, &wine_url);
611     nsIWineURI_Release(wine_uri);
612     if(!wine_url) {
613         TRACE("wine_url == NULL\n");
614         return E_FAIL;
615     }
616
617     hres = CreateURLMoniker(NULL, wine_url, mon);
618     if(FAILED(hres))
619         WARN("CreateURLMonikrer failed: %08x\n", hres);
620
621     return hres;
622 }
623
624 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
625                                           nsISupports *aContext)
626 {
627     nsChannel *This = NSCHANNEL_THIS(iface);
628     BSCallback *bscallback;
629     IMoniker *mon = NULL;
630     PRBool is_doc_uri;
631     nsresult nsres;
632     task_t *task;
633     HRESULT hres;
634
635     TRACE("(%p)->(%p %p)\n", This, aListener, aContext);
636
637     nsIWineURI_GetIsDocumentURI(This->uri, &is_doc_uri);
638
639     if(is_doc_uri && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI)) {
640         NSContainer *container;
641
642         nsIWineURI_GetNSContainer(This->uri, &container);
643         if(!container) {
644             TRACE("container = NULL\n");
645             return nsIChannel_AsyncOpen(This->channel, aListener, aContext);
646         }
647
648         if(container->bscallback) {
649             nsIChannel_AddRef(NSCHANNEL(This));
650             container->bscallback->nschannel = This;
651
652             nsIStreamListener_AddRef(aListener);
653             container->bscallback->nslistener = aListener;
654
655             if(aContext) {
656                 nsISupports_AddRef(aContext);
657                 container->bscallback->nscontext = aContext;
658             }
659
660             nsIWebBrowserChrome_Release(NSWBCHROME(container));
661
662             if(do_load_from_moniker_hack(This))
663                 return WINE_NS_LOAD_FROM_MONIKER;
664         }else  {
665             BOOL cont = before_async_open(This, container);
666             nsIWebBrowserChrome_Release(NSWBCHROME(container));
667
668             if(!cont) {
669                 TRACE("canceled\n");
670                 return NS_ERROR_UNEXPECTED;
671             }
672
673             if(!container->doc)
674                 return This->channel
675                     ?  nsIChannel_AsyncOpen(This->channel, aListener, aContext)
676                     : NS_ERROR_UNEXPECTED;
677
678             hres = create_mon_for_nschannel(This, &mon);
679             if(FAILED(hres))
680                 return NS_ERROR_UNEXPECTED;
681             set_current_mon(container->doc, mon);
682         }
683     }
684
685     if(This->channel) {
686         if(This->post_data_stream) {
687             nsIUploadChannel *upload_channel;
688
689             nsres = nsIChannel_QueryInterface(This->channel, &IID_nsIUploadChannel,
690                                           (void**)&upload_channel);
691             if(NS_SUCCEEDED(nsres)) {
692                 nsACString empty_string;
693                 nsACString_Init(&empty_string, "");
694
695                 nsres = nsIUploadChannel_SetUploadStream(upload_channel, This->post_data_stream,
696                                                          &empty_string, -1);
697                 nsIUploadChannel_Release(upload_channel);
698                 if(NS_FAILED(nsres))
699                     WARN("SetUploadStream failed: %08x\n", nsres);
700
701                 nsACString_Finish(&empty_string);
702             }
703         }
704
705         nsres = nsIChannel_AsyncOpen(This->channel, aListener, aContext);
706
707         if(mon)
708             IMoniker_Release(mon);
709
710         if(NS_FAILED(nsres) && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI))
711             return WINE_NS_LOAD_FROM_MONIKER;
712         return nsres;
713     }
714
715     TRACE("channel == NULL\n");
716
717     hres = create_mon_for_nschannel(This, &mon);
718     if(FAILED(hres))
719         return NS_ERROR_UNEXPECTED;
720
721     bscallback = create_bscallback(mon);
722     IMoniker_Release(mon);
723
724     nsIChannel_AddRef(NSCHANNEL(This));
725     bscallback->nschannel = This;
726
727     nsIStreamListener_AddRef(aListener);
728     bscallback->nslistener = aListener;
729
730     if(aContext) {
731         nsISupports_AddRef(aContext);
732         bscallback->nscontext = aContext;
733     }
734
735     task = mshtml_alloc(sizeof(task_t));
736
737     task->doc = bscallback->doc;
738     task->task_id = TASK_START_BINDING;
739     task->next = NULL;
740     task->bscallback = bscallback;
741
742     push_task(task);
743
744     return NS_OK;
745 }
746
747 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
748 {
749     nsChannel *This = NSCHANNEL_THIS(iface);
750
751     TRACE("(%p)->(%p)\n", This, aRequestMethod);
752
753     if(This->http_channel)
754         return nsIHttpChannel_GetRequestMethod(This->http_channel, aRequestMethod);
755
756     return NS_ERROR_NOT_IMPLEMENTED;
757 }
758
759 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
760                                                  const nsACString *aRequestMethod)
761 {
762     nsChannel *This = NSCHANNEL_THIS(iface);
763
764     TRACE("(%p)->(%p)\n", This, aRequestMethod);
765
766     if(This->http_channel)
767         return nsIHttpChannel_SetRequestMethod(This->http_channel, aRequestMethod);
768
769     return NS_ERROR_NOT_IMPLEMENTED;
770 }
771
772 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
773 {
774     nsChannel *This = NSCHANNEL_THIS(iface);
775
776     TRACE("(%p)->(%p)\n", This, aReferrer);
777
778     if(This->http_channel)
779         return nsIHttpChannel_GetReferrer(This->http_channel, aReferrer);
780
781     return NS_ERROR_NOT_IMPLEMENTED;
782 }
783
784 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
785 {
786     nsChannel *This = NSCHANNEL_THIS(iface);
787
788     TRACE("(%p)->(%p)\n", This, aReferrer);
789
790     if(This->http_channel)
791         return nsIHttpChannel_SetReferrer(This->http_channel, aReferrer);
792
793     return NS_ERROR_NOT_IMPLEMENTED;
794 }
795
796 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
797          const nsACString *aHeader, nsACString *_retval)
798 {
799     nsChannel *This = NSCHANNEL_THIS(iface);
800
801     TRACE("(%p)->(%p %p)\n", This, aHeader, _retval);
802
803     if(This->http_channel)
804         return nsIHttpChannel_GetRequestHeader(This->http_channel, aHeader, _retval);
805
806     return NS_ERROR_NOT_IMPLEMENTED;
807 }
808
809 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
810          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
811 {
812     nsChannel *This = NSCHANNEL_THIS(iface);
813
814     TRACE("(%p)->(%p %p %x)\n", This, aHeader, aValue, aMerge);
815
816     if(This->http_channel)
817         return nsIHttpChannel_SetRequestHeader(This->http_channel, aHeader, aValue, aMerge);
818
819     return NS_ERROR_NOT_IMPLEMENTED;
820 }
821
822 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
823                                                     nsIHttpHeaderVisitor *aVisitor)
824 {
825     nsChannel *This = NSCHANNEL_THIS(iface);
826
827     TRACE("(%p)->(%p)\n", This, aVisitor);
828
829     if(This->http_channel)
830         return nsIHttpChannel_VisitRequestHeaders(This->http_channel, aVisitor);
831
832     return NS_ERROR_NOT_IMPLEMENTED;
833 }
834
835 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
836 {
837     nsChannel *This = NSCHANNEL_THIS(iface);
838
839     TRACE("(%p)->(%p)\n", This, aAllowPipelining);
840
841     if(This->http_channel)
842         return nsIHttpChannel_GetAllowPipelining(This->http_channel, aAllowPipelining);
843
844     return NS_ERROR_NOT_IMPLEMENTED;
845 }
846
847 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
848 {
849     nsChannel *This = NSCHANNEL_THIS(iface);
850
851     TRACE("(%p)->(%x)\n", This, aAllowPipelining);
852
853     if(This->http_channel)
854         return nsIHttpChannel_SetAllowPipelining(This->http_channel, aAllowPipelining);
855
856     return NS_ERROR_NOT_IMPLEMENTED;
857 }
858
859 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
860 {
861     nsChannel *This = NSCHANNEL_THIS(iface);
862
863     TRACE("(%p)->(%p)\n", This, aRedirectionLimit);
864
865     if(This->http_channel)
866         return nsIHttpChannel_GetRedirectionLimit(This->http_channel, aRedirectionLimit);
867
868     return NS_ERROR_NOT_IMPLEMENTED;
869 }
870
871 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
872 {
873     nsChannel *This = NSCHANNEL_THIS(iface);
874
875     TRACE("(%p)->(%u)\n", This, aRedirectionLimit);
876
877     if(This->http_channel)
878         return nsIHttpChannel_SetRedirectionLimit(This->http_channel, aRedirectionLimit);
879
880     return NS_ERROR_NOT_IMPLEMENTED;
881 }
882
883 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
884 {
885     nsChannel *This = NSCHANNEL_THIS(iface);
886
887     TRACE("(%p)->(%p)\n", This, aResponseStatus);
888
889     if(This->http_channel)
890         return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
891
892     return NS_ERROR_NOT_IMPLEMENTED;
893 }
894
895 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
896                                                       nsACString *aResponseStatusText)
897 {
898     nsChannel *This = NSCHANNEL_THIS(iface);
899
900     TRACE("(%p)->(%p)\n", This, aResponseStatusText);
901
902     if(This->http_channel)
903         return nsIHttpChannel_GetResponseStatusText(This->http_channel, aResponseStatusText);
904
905     return NS_ERROR_NOT_IMPLEMENTED;
906 }
907
908 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
909                                                     PRBool *aRequestSucceeded)
910 {
911     nsChannel *This = NSCHANNEL_THIS(iface);
912
913     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
914
915     if(This->http_channel)
916         return nsIHttpChannel_GetRequestSucceeded(This->http_channel, aRequestSucceeded);
917
918     return NS_ERROR_NOT_IMPLEMENTED;
919 }
920
921 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
922          const nsACString *header, nsACString *_retval)
923 {
924     nsChannel *This = NSCHANNEL_THIS(iface);
925
926     TRACE("(%p)->(%p %p)\n", This, header, _retval);
927
928     if(This->http_channel)
929         return nsIHttpChannel_GetResponseHeader(This->http_channel, header, _retval);
930
931     return NS_ERROR_NOT_IMPLEMENTED;
932 }
933
934 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
935         const nsACString *header, const nsACString *value, PRBool merge)
936 {
937     nsChannel *This = NSCHANNEL_THIS(iface);
938
939     TRACE("(%p)->(%p %p %x)\n", This, header, value, merge);
940
941     if(This->http_channel)
942         return nsIHttpChannel_SetResponseHeader(This->http_channel, header, value, merge);
943
944     return NS_ERROR_NOT_IMPLEMENTED;
945 }
946
947 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
948         nsIHttpHeaderVisitor *aVisitor)
949 {
950     nsChannel *This = NSCHANNEL_THIS(iface);
951
952     TRACE("(%p)->(%p)\n", This, aVisitor);
953
954     if(This->http_channel)
955         return nsIHttpChannel_VisitResponseHeaders(This->http_channel, aVisitor);
956
957     return NS_ERROR_NOT_IMPLEMENTED;
958 }
959
960 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
961 {
962     nsChannel *This = NSCHANNEL_THIS(iface);
963
964     TRACE("(%p)->(%p)\n", This, _retval);
965
966     if(This->http_channel)
967         return nsIHttpChannel_IsNoStoreResponse(This->http_channel, _retval);
968
969     return NS_ERROR_NOT_IMPLEMENTED;
970 }
971
972 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
973 {
974     nsChannel *This = NSCHANNEL_THIS(iface);
975
976     TRACE("(%p)->(%p)\n", This, _retval);
977
978     if(This->http_channel)
979         return nsIHttpChannel_IsNoCacheResponse(This->http_channel, _retval);
980
981     return NS_ERROR_NOT_IMPLEMENTED;
982 }
983
984 #undef NSCHANNEL_THIS
985
986 static const nsIHttpChannelVtbl nsChannelVtbl = {
987     nsChannel_QueryInterface,
988     nsChannel_AddRef,
989     nsChannel_Release,
990     nsChannel_GetName,
991     nsChannel_IsPending,
992     nsChannel_GetStatus,
993     nsChannel_Cancel,
994     nsChannel_Suspend,
995     nsChannel_Resume,
996     nsChannel_GetLoadGroup,
997     nsChannel_SetLoadGroup,
998     nsChannel_GetLoadFlags,
999     nsChannel_SetLoadFlags,
1000     nsChannel_GetOriginalURI,
1001     nsChannel_SetOriginalURI,
1002     nsChannel_GetURI,
1003     nsChannel_GetOwner,
1004     nsChannel_SetOwner,
1005     nsChannel_GetNotificationCallbacks,
1006     nsChannel_SetNotificationCallbacks,
1007     nsChannel_GetSecurityInfo,
1008     nsChannel_GetContentType,
1009     nsChannel_SetContentType,
1010     nsChannel_GetContentCharset,
1011     nsChannel_SetContentCharset,
1012     nsChannel_GetContentLength,
1013     nsChannel_SetContentLength,
1014     nsChannel_Open,
1015     nsChannel_AsyncOpen,
1016     nsChannel_GetRequestMethod,
1017     nsChannel_SetRequestMethod,
1018     nsChannel_GetReferrer,
1019     nsChannel_SetReferrer,
1020     nsChannel_GetRequestHeader,
1021     nsChannel_SetRequestHeader,
1022     nsChannel_VisitRequestHeaders,
1023     nsChannel_GetAllowPipelining,
1024     nsChannel_SetAllowPipelining,
1025     nsChannel_GetRedirectionLimit,
1026     nsChannel_SetRedirectionLimit,
1027     nsChannel_GetResponseStatus,
1028     nsChannel_GetResponseStatusText,
1029     nsChannel_GetRequestSucceeded,
1030     nsChannel_GetResponseHeader,
1031     nsChannel_SetResponseHeader,
1032     nsChannel_VisitResponseHeaders,
1033     nsChannel_IsNoStoreResponse,
1034     nsChannel_IsNoCacheResponse
1035 };
1036
1037 #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface)
1038
1039 static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid,
1040                                                      nsQIResult result)
1041 {
1042     nsChannel *This = NSUPCHANNEL_THIS(iface);
1043     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1044 }
1045
1046 static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface)
1047 {
1048     nsChannel *This = NSUPCHANNEL_THIS(iface);
1049     return nsIChannel_AddRef(NSCHANNEL(This));
1050 }
1051
1052 static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface)
1053 {
1054     nsChannel *This = NSUPCHANNEL_THIS(iface);
1055     return nsIChannel_Release(NSCHANNEL(This));
1056 }
1057
1058 static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
1059         nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength)
1060 {
1061     nsChannel *This = NSUPCHANNEL_THIS(iface);
1062     const char *content_type;
1063
1064     TRACE("(%p)->(%p %p %d)\n", This, aStream, aContentType, aContentLength);
1065
1066     if(This->post_data_stream)
1067         nsIInputStream_Release(This->post_data_stream);
1068
1069     if(aContentType) {
1070         nsACString_GetData(aContentType, &content_type, NULL);
1071         if(*content_type)
1072             FIXME("Unsupported aContentType argument: %s\n", debugstr_a(content_type));
1073     }
1074
1075     if(aContentLength != -1)
1076         FIXME("Unsupported acontentLength = %d\n", aContentLength);
1077
1078     if(aStream)
1079         nsIInputStream_AddRef(aStream);
1080     This->post_data_stream = aStream;
1081
1082     return NS_OK;
1083 }
1084
1085 static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface,
1086         nsIInputStream **aUploadStream)
1087 {
1088     nsChannel *This = NSUPCHANNEL_THIS(iface);
1089
1090     TRACE("(%p)->(%p)\n", This, aUploadStream);
1091
1092     if(This->post_data_stream)
1093         nsIInputStream_AddRef(This->post_data_stream);
1094
1095     *aUploadStream = This->post_data_stream;
1096     return NS_OK;
1097 }
1098
1099 #undef NSUPCHANNEL_THIS
1100
1101 static const nsIUploadChannelVtbl nsUploadChannelVtbl = {
1102     nsUploadChannel_QueryInterface,
1103     nsUploadChannel_AddRef,
1104     nsUploadChannel_Release,
1105     nsUploadChannel_SetUploadStream,
1106     nsUploadChannel_GetUploadStream
1107 };
1108
1109 #define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
1110
1111 static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
1112 {
1113     nsURI *This = NSURI_THIS(iface);
1114
1115     *result = NULL;
1116
1117     if(IsEqualGUID(&IID_nsISupports, riid)) {
1118         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1119         *result = NSURI(This);
1120     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
1121         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
1122         *result = NSURI(This);
1123     }else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
1124         TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
1125         *result = NSURI(This);
1126     }
1127
1128     if(*result) {
1129         nsIURI_AddRef(NSURI(This));
1130         return NS_OK;
1131     }
1132
1133     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1134     return This->uri ? nsIURI_QueryInterface(This->uri, riid, result) : NS_NOINTERFACE;
1135 }
1136
1137 static nsrefcnt NSAPI nsURI_AddRef(nsIWineURI *iface)
1138 {
1139     nsURI *This = NSURI_THIS(iface);
1140     LONG ref = InterlockedIncrement(&This->ref);
1141
1142     TRACE("(%p) ref=%d\n", This, ref);
1143
1144     return ref;
1145 }
1146
1147 static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface)
1148 {
1149     nsURI *This = NSURI_THIS(iface);
1150     LONG ref = InterlockedDecrement(&This->ref);
1151
1152     TRACE("(%p) ref=%d\n", This, ref);
1153
1154     if(!ref) {
1155         if(This->container)
1156             nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1157         if(This->uri)
1158             nsIURI_Release(This->uri);
1159         mshtml_free(This->wine_url);
1160         mshtml_free(This);
1161     }
1162
1163     return ref;
1164 }
1165
1166 static nsresult NSAPI nsURI_GetSpec(nsIWineURI *iface, nsACString *aSpec)
1167 {
1168     nsURI *This = NSURI_THIS(iface);
1169
1170     TRACE("(%p)->(%p)\n", This, aSpec);
1171
1172     if(This->use_wine_url) {
1173         char speca[INTERNET_MAX_URL_LENGTH] = "wine:";
1174         WideCharToMultiByte(CP_ACP, 0, This->wine_url, -1, speca+5, sizeof(speca)-5, NULL, NULL);
1175         nsACString_SetData(aSpec, speca);
1176
1177         return NS_OK;
1178     }
1179
1180     if(This->uri)
1181         return nsIURI_GetSpec(This->uri, aSpec);
1182
1183     TRACE("returning error\n");
1184     return NS_ERROR_NOT_IMPLEMENTED;
1185
1186 }
1187
1188 static nsresult NSAPI nsURI_SetSpec(nsIWineURI *iface, const nsACString *aSpec)
1189 {
1190     nsURI *This = NSURI_THIS(iface);
1191
1192     TRACE("(%p)->(%p)\n", This, aSpec);
1193
1194     if(This->uri)
1195         return nsIURI_SetSpec(This->uri, aSpec);
1196
1197     FIXME("default action not implemented\n");
1198     return NS_ERROR_NOT_IMPLEMENTED;
1199 }
1200
1201 static nsresult NSAPI nsURI_GetPrePath(nsIWineURI *iface, nsACString *aPrePath)
1202 {
1203     nsURI *This = NSURI_THIS(iface);
1204
1205     TRACE("(%p)->(%p)\n", This, aPrePath);
1206
1207     if(This->uri)
1208         return nsIURI_GetPrePath(This->uri, aPrePath);
1209
1210     FIXME("default action not implemented\n");
1211     return NS_ERROR_NOT_IMPLEMENTED;
1212 }
1213
1214 static nsresult NSAPI nsURI_GetScheme(nsIWineURI *iface, nsACString *aScheme)
1215 {
1216     nsURI *This = NSURI_THIS(iface);
1217
1218     TRACE("(%p)->(%p)\n", This, aScheme);
1219
1220     if(This->use_wine_url) {
1221         /*
1222          * For Gecko we set scheme to unknown so it won't be handled
1223          * as any special case.
1224          */
1225         nsACString_SetData(aScheme, "wine");
1226         return NS_OK;
1227     }
1228
1229     if(This->uri)
1230         return nsIURI_GetScheme(This->uri, aScheme);
1231
1232     TRACE("returning error\n");
1233     return NS_ERROR_NOT_IMPLEMENTED;
1234 }
1235
1236 static nsresult NSAPI nsURI_SetScheme(nsIWineURI *iface, const nsACString *aScheme)
1237 {
1238     nsURI *This = NSURI_THIS(iface);
1239
1240     TRACE("(%p)->(%p)\n", This, aScheme);
1241
1242     if(This->uri)
1243         return nsIURI_SetScheme(This->uri, aScheme);
1244
1245     FIXME("default action not implemented\n");
1246     return NS_ERROR_NOT_IMPLEMENTED;
1247 }
1248
1249 static nsresult NSAPI nsURI_GetUserPass(nsIWineURI *iface, nsACString *aUserPass)
1250 {
1251     nsURI *This = NSURI_THIS(iface);
1252
1253     TRACE("(%p)->(%p)\n", This, aUserPass);
1254
1255     if(This->uri)
1256         return nsIURI_GetUserPass(This->uri, aUserPass);
1257
1258     FIXME("default action not implemented\n");
1259     return NS_ERROR_NOT_IMPLEMENTED;
1260 }
1261
1262 static nsresult NSAPI nsURI_SetUserPass(nsIWineURI *iface, const nsACString *aUserPass)
1263 {
1264     nsURI *This = NSURI_THIS(iface);
1265
1266     TRACE("(%p)->(%p)\n", This, aUserPass);
1267
1268     if(This->uri)
1269         return nsIURI_SetUserPass(This->uri, aUserPass);
1270
1271     FIXME("default action not implemented\n");
1272     return NS_ERROR_NOT_IMPLEMENTED;
1273 }
1274
1275 static nsresult NSAPI nsURI_GetUsername(nsIWineURI *iface, nsACString *aUsername)
1276 {
1277     nsURI *This = NSURI_THIS(iface);
1278
1279     TRACE("(%p)->(%p)\n", This, aUsername);
1280
1281     if(This->uri)
1282         return nsIURI_GetUsername(This->uri, aUsername);
1283
1284     FIXME("default action not implemented\n");
1285     return NS_ERROR_NOT_IMPLEMENTED;
1286 }
1287
1288 static nsresult NSAPI nsURI_SetUsername(nsIWineURI *iface, const nsACString *aUsername)
1289 {
1290     nsURI *This = NSURI_THIS(iface);
1291
1292     TRACE("(%p)->(%p)\n", This, aUsername);
1293
1294     if(This->uri)
1295         return nsIURI_SetUsername(This->uri, aUsername);
1296
1297     FIXME("default action not implemented\n");
1298     return NS_ERROR_NOT_IMPLEMENTED;
1299 }
1300
1301 static nsresult NSAPI nsURI_GetPassword(nsIWineURI *iface, nsACString *aPassword)
1302 {
1303     nsURI *This = NSURI_THIS(iface);
1304
1305     TRACE("(%p)->(%p)\n", This, aPassword);
1306
1307     if(This->uri)
1308         return nsIURI_GetPassword(This->uri, aPassword);
1309
1310     FIXME("default action not implemented\n");
1311     return NS_ERROR_NOT_IMPLEMENTED;
1312 }
1313
1314 static nsresult NSAPI nsURI_SetPassword(nsIWineURI *iface, const nsACString *aPassword)
1315 {
1316     nsURI *This = NSURI_THIS(iface);
1317
1318     TRACE("(%p)->(%p)\n", This, aPassword);
1319
1320     if(This->uri)
1321         return nsIURI_SetPassword(This->uri, aPassword);
1322
1323     FIXME("default action not implemented\n");
1324     return NS_ERROR_NOT_IMPLEMENTED;
1325 }
1326
1327 static nsresult NSAPI nsURI_GetHostPort(nsIWineURI *iface, nsACString *aHostPort)
1328 {
1329     nsURI *This = NSURI_THIS(iface);
1330
1331     TRACE("(%p)->(%p)\n", This, aHostPort);
1332
1333     if(This->uri)
1334         return nsIURI_GetHostPort(This->uri, aHostPort);
1335
1336     FIXME("default action not implemented\n");
1337     return NS_ERROR_NOT_IMPLEMENTED;
1338 }
1339
1340 static nsresult NSAPI nsURI_SetHostPort(nsIWineURI *iface, const nsACString *aHostPort)
1341 {
1342     nsURI *This = NSURI_THIS(iface);
1343
1344     TRACE("(%p)->(%p)\n", This, aHostPort);
1345
1346     if(This->uri)
1347         return nsIURI_SetHostPort(This->uri, aHostPort);
1348
1349     FIXME("default action not implemented\n");
1350     return NS_ERROR_NOT_IMPLEMENTED;
1351 }
1352
1353 static nsresult NSAPI nsURI_GetHost(nsIWineURI *iface, nsACString *aHost)
1354 {
1355     nsURI *This = NSURI_THIS(iface);
1356
1357     TRACE("(%p)->(%p)\n", This, aHost);
1358
1359     if(This->uri)
1360         return nsIURI_GetHost(This->uri, aHost);
1361
1362     FIXME("default action not implemented\n");
1363     return NS_ERROR_NOT_IMPLEMENTED;
1364 }
1365
1366 static nsresult NSAPI nsURI_SetHost(nsIWineURI *iface, const nsACString *aHost)
1367 {
1368     nsURI *This = NSURI_THIS(iface);
1369
1370     TRACE("(%p)->(%p)\n", This, aHost);
1371
1372     if(This->uri)
1373         return nsIURI_SetHost(This->uri, aHost);
1374
1375     FIXME("default action not implemented\n");
1376     return NS_ERROR_NOT_IMPLEMENTED;
1377 }
1378
1379 static nsresult NSAPI nsURI_GetPort(nsIWineURI *iface, PRInt32 *aPort)
1380 {
1381     nsURI *This = NSURI_THIS(iface);
1382
1383     TRACE("(%p)->(%p)\n", This, aPort);
1384
1385     if(This->uri)
1386         return nsIURI_GetPort(This->uri, aPort);
1387
1388     FIXME("default action not implemented\n");
1389     return NS_ERROR_NOT_IMPLEMENTED;
1390 }
1391
1392 static nsresult NSAPI nsURI_SetPort(nsIWineURI *iface, PRInt32 aPort)
1393 {
1394     nsURI *This = NSURI_THIS(iface);
1395
1396     TRACE("(%p)->(%d)\n", This, aPort);
1397
1398     if(This->uri)
1399         return nsIURI_SetPort(This->uri, aPort);
1400
1401     FIXME("default action not implemented\n");
1402     return NS_ERROR_NOT_IMPLEMENTED;
1403 }
1404
1405 static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath)
1406 {
1407     nsURI *This = NSURI_THIS(iface);
1408
1409     TRACE("(%p)->(%p)\n", This, aPath);
1410
1411     if(This->uri)
1412         return nsIURI_GetPath(This->uri, aPath);
1413
1414     FIXME("default action not implemented\n");
1415     return NS_ERROR_NOT_IMPLEMENTED;
1416 }
1417
1418 static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath)
1419 {
1420     nsURI *This = NSURI_THIS(iface);
1421
1422     TRACE("(%p)->(%p)\n", This, aPath);
1423
1424     if(This->uri)
1425         return nsIURI_SetPath(This->uri, aPath);
1426
1427     FIXME("default action not implemented\n");
1428     return NS_ERROR_NOT_IMPLEMENTED;
1429 }
1430
1431 static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval)
1432 {
1433     nsURI *This = NSURI_THIS(iface);
1434
1435     TRACE("(%p)->(%p %p)\n", This, other, _retval);
1436
1437     if(This->uri)
1438         return nsIURI_Equals(This->uri, other, _retval);
1439
1440     FIXME("default action not implemented\n");
1441     return NS_ERROR_NOT_IMPLEMENTED;
1442 }
1443
1444 static nsresult NSAPI nsURI_SchemeIs(nsIWineURI *iface, const char *scheme, PRBool *_retval)
1445 {
1446     nsURI *This = NSURI_THIS(iface);
1447
1448     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
1449
1450     if(This->use_wine_url) {
1451         WCHAR buf[INTERNET_MAX_SCHEME_LENGTH];
1452         int len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
1453
1454         *_retval = strlenW(This->wine_url) > len
1455             && This->wine_url[len] == ':'
1456             && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
1457         return NS_OK;
1458     }
1459
1460     if(This->uri)
1461         return nsIURI_SchemeIs(This->uri, scheme, _retval);
1462
1463     TRACE("returning error\n");
1464     return NS_ERROR_NOT_IMPLEMENTED;
1465 }
1466
1467 static nsresult NSAPI nsURI_Clone(nsIWineURI *iface, nsIURI **_retval)
1468 {
1469     nsURI *This = NSURI_THIS(iface);
1470
1471     TRACE("(%p)->(%p)\n", This, _retval);
1472
1473     if(This->uri) {
1474         nsIURI *uri;
1475         nsIWineURI *wine_uri;
1476         nsresult nsres;
1477
1478         nsres = nsIURI_Clone(This->uri, &uri);
1479         if(NS_FAILED(nsres)) {
1480             WARN("Clone failed: %08x\n", nsres);
1481             return nsres;
1482         }
1483
1484         nsres = create_uri(uri, This->container, &wine_uri);
1485         *_retval = (nsIURI*)wine_uri;
1486         if(NS_SUCCEEDED(nsres))
1487             return nsIWineURI_SetWineURL(wine_uri, This->wine_url);
1488         return nsres;
1489     }
1490
1491     FIXME("default action not implemented\n");
1492     return NS_ERROR_NOT_IMPLEMENTED;
1493 }
1494
1495 static nsresult NSAPI nsURI_Resolve(nsIWineURI *iface, const nsACString *arelativePath,
1496         nsACString *_retval)
1497 {
1498     nsURI *This = NSURI_THIS(iface);
1499
1500     TRACE("(%p)->(%p %p)\n", This, arelativePath, _retval);
1501
1502     if(This->uri)
1503         return nsIURI_Resolve(This->uri, arelativePath, _retval);
1504
1505     FIXME("default action not implemented\n");
1506     return NS_ERROR_NOT_IMPLEMENTED;
1507 }
1508
1509 static nsresult NSAPI nsURI_GetAsciiSpec(nsIWineURI *iface, nsACString *aAsciiSpec)
1510 {
1511     nsURI *This = NSURI_THIS(iface);
1512
1513     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
1514
1515     if(This->use_wine_url)
1516         return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
1517
1518     if(This->uri)
1519         return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
1520
1521     TRACE("returning error\n");
1522     return NS_ERROR_NOT_IMPLEMENTED;
1523 }
1524
1525 static nsresult NSAPI nsURI_GetAsciiHost(nsIWineURI *iface, nsACString *aAsciiHost)
1526 {
1527     nsURI *This = NSURI_THIS(iface);
1528
1529     TRACE("(%p)->(%p)\n", This, aAsciiHost);
1530
1531     if(This->uri)
1532         return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
1533
1534     FIXME("default action not implemented\n");
1535     return NS_ERROR_NOT_IMPLEMENTED;
1536 }
1537
1538 static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOriginCharset)
1539 {
1540     nsURI *This = NSURI_THIS(iface);
1541
1542     TRACE("(%p)->(%p)\n", This, aOriginCharset);
1543
1544     if(This->uri)
1545         return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
1546
1547     FIXME("default action not implemented\n");
1548     return NS_ERROR_NOT_IMPLEMENTED;
1549 }
1550
1551 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
1552 {
1553     nsURI *This = NSURI_THIS(iface);
1554
1555     TRACE("(%p)->(%p)\n", This, aContainer);
1556
1557     if(This->container)
1558         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
1559     *aContainer = This->container;
1560
1561     return NS_OK;
1562 }
1563
1564 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
1565 {
1566     nsURI *This = NSURI_THIS(iface);
1567
1568     TRACE("(%p)->(%p)\n", This, aContainer);
1569
1570     if(This->container) {
1571         if(This->container == aContainer)
1572             return NS_OK;
1573         TRACE("Changing %p -> %p\n", This->container, aContainer);
1574         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1575     }
1576
1577     if(aContainer)
1578         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
1579     This->container = aContainer;
1580
1581     return NS_OK;
1582 }
1583
1584 static nsresult NSAPI nsURI_GetIsDocumentURI(nsIWineURI *iface, PRBool *aIsDocumentURI)
1585 {
1586     nsURI *This = NSURI_THIS(iface);
1587
1588     TRACE("(%p)->(%p)\n", This, aIsDocumentURI);
1589
1590     *aIsDocumentURI = This->is_doc_uri;
1591     return NS_OK;
1592 }
1593
1594 static nsresult NSAPI nsURI_SetIsDocumentURI(nsIWineURI *iface, PRBool aIsDocumentURI)
1595 {
1596     nsURI *This = NSURI_THIS(iface);
1597
1598     TRACE("(%p)->(%x)\n", This, aIsDocumentURI);
1599
1600     This->is_doc_uri = aIsDocumentURI;
1601     return NS_OK;
1602 }
1603
1604 static nsresult NSAPI nsURI_GetWineURL(nsIWineURI *iface, LPCWSTR *aURL)
1605 {
1606     nsURI *This = NSURI_THIS(iface);
1607
1608     TRACE("(%p)->(%p)\n", This, aURL);
1609
1610     *aURL = This->wine_url;
1611     return NS_OK;
1612 }
1613
1614 static nsresult NSAPI nsURI_SetWineURL(nsIWineURI *iface, LPCWSTR aURL)
1615 {
1616     nsURI *This = NSURI_THIS(iface);
1617
1618     static const WCHAR wszFtp[]   = {'f','t','p',':'};
1619     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
1620     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
1621
1622     TRACE("(%p)->(%s)\n", This, debugstr_w(aURL));
1623
1624     mshtml_free(This->wine_url);
1625
1626     if(aURL) {
1627         int len = strlenW(aURL)+1;
1628         This->wine_url = mshtml_alloc(len*sizeof(WCHAR));
1629         memcpy(This->wine_url, aURL, len*sizeof(WCHAR));
1630
1631         /* FIXME: Always use wine url */
1632         This->use_wine_url =
1633                strncmpW(aURL, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
1634             && strncmpW(aURL, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
1635             && strncmpW(aURL, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
1636     }else {
1637         This->wine_url = NULL;
1638         This->use_wine_url = FALSE;
1639     }
1640
1641     return NS_OK;
1642 }
1643
1644 #undef NSURI_THIS
1645
1646 static const nsIWineURIVtbl nsWineURIVtbl = {
1647     nsURI_QueryInterface,
1648     nsURI_AddRef,
1649     nsURI_Release,
1650     nsURI_GetSpec,
1651     nsURI_SetSpec,
1652     nsURI_GetPrePath,
1653     nsURI_GetScheme,
1654     nsURI_SetScheme,
1655     nsURI_GetUserPass,
1656     nsURI_SetUserPass,
1657     nsURI_GetUsername,
1658     nsURI_SetUsername,
1659     nsURI_GetPassword,
1660     nsURI_SetPassword,
1661     nsURI_GetHostPort,
1662     nsURI_SetHostPort,
1663     nsURI_GetHost,
1664     nsURI_SetHost,
1665     nsURI_GetPort,
1666     nsURI_SetPort,
1667     nsURI_GetPath,
1668     nsURI_SetPath,
1669     nsURI_Equals,
1670     nsURI_SchemeIs,
1671     nsURI_Clone,
1672     nsURI_Resolve,
1673     nsURI_GetAsciiSpec,
1674     nsURI_GetAsciiHost,
1675     nsURI_GetOriginCharset,
1676     nsURI_GetNSContainer,
1677     nsURI_SetNSContainer,
1678     nsURI_GetIsDocumentURI,
1679     nsURI_SetIsDocumentURI,
1680     nsURI_GetWineURL,
1681     nsURI_SetWineURL
1682 };
1683
1684 static nsresult create_uri(nsIURI *uri, NSContainer *container, nsIWineURI **_retval)
1685 {
1686     nsURI *ret = mshtml_alloc(sizeof(nsURI));
1687
1688     ret->lpWineURIVtbl = &nsWineURIVtbl;
1689     ret->ref = 1;
1690     ret->uri = uri;
1691     ret->container = container;
1692     ret->wine_url = NULL;
1693     ret->is_doc_uri = FALSE;
1694     ret->use_wine_url = FALSE;
1695
1696     if(container)
1697         nsIWebBrowserChrome_AddRef(NSWBCHROME(container));
1698
1699     TRACE("retval=%p\n", ret);
1700     *_retval = NSWINEURI(ret);
1701     return NS_OK;
1702 }
1703
1704 typedef struct {
1705     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
1706
1707     LONG ref;
1708
1709     nsIProtocolHandler *nshandler;
1710 } nsProtocolHandler;
1711
1712 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
1713
1714 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
1715
1716 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
1717         nsQIResult result)
1718 {
1719     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1720
1721     *result = NULL;
1722
1723     if(IsEqualGUID(&IID_nsISupports, riid)) {
1724         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1725         *result = NSPROTHANDLER(This);
1726     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
1727         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
1728         *result = NSPROTHANDLER(This);
1729     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
1730         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
1731         return NS_NOINTERFACE;
1732     }
1733
1734     if(*result) {
1735         nsISupports_AddRef((nsISupports*)*result);
1736         return NS_OK;
1737     }
1738
1739     WARN("(%s %p)\n", debugstr_guid(riid), result);
1740     return NS_NOINTERFACE;
1741 }
1742
1743 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
1744 {
1745     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1746     LONG ref = InterlockedIncrement(&This->ref);
1747
1748     TRACE("(%p) ref=%d\n", This, ref);
1749
1750     return ref;
1751 }
1752
1753 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
1754 {
1755     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1756     LONG ref = InterlockedDecrement(&This->ref);
1757
1758     TRACE("(%p) ref=%d\n", This, ref);
1759
1760     if(!ref) {
1761         if(This->nshandler)
1762             nsIProtocolHandler_Release(This->nshandler);
1763         mshtml_free(This);
1764     }
1765
1766     return ref;
1767 }
1768
1769 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
1770 {
1771     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1772
1773     TRACE("(%p)->(%p)\n", This, aScheme);
1774
1775     if(This->nshandler)
1776         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
1777     return NS_ERROR_NOT_IMPLEMENTED;
1778 }
1779
1780 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
1781         PRInt32 *aDefaultPort)
1782 {
1783     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1784
1785     TRACE("(%p)->(%p)\n", This, aDefaultPort);
1786
1787     if(This->nshandler)
1788         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
1789     return NS_ERROR_NOT_IMPLEMENTED;
1790 }
1791
1792 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
1793                                                          PRUint32 *aProtocolFlags)
1794 {
1795     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1796
1797     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
1798
1799     if(This->nshandler)
1800         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
1801     return NS_ERROR_NOT_IMPLEMENTED;
1802 }
1803
1804 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
1805         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
1806 {
1807     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1808
1809     TRACE("((%p)->%p %s %p %p)\n", This, aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
1810
1811     if(This->nshandler)
1812         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
1813     return NS_ERROR_NOT_IMPLEMENTED;
1814 }
1815
1816 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
1817         nsIURI *aURI, nsIChannel **_retval)
1818 {
1819     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1820
1821     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
1822
1823     if(This->nshandler)
1824         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
1825     return NS_ERROR_NOT_IMPLEMENTED;
1826 }
1827
1828 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
1829         PRInt32 port, const char *scheme, PRBool *_retval)
1830 {
1831     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1832
1833     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
1834
1835     if(This->nshandler)
1836         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
1837     return NS_ERROR_NOT_IMPLEMENTED;
1838 }
1839
1840 #undef NSPROTHANDLER_THIS
1841
1842 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
1843     nsProtocolHandler_QueryInterface,
1844     nsProtocolHandler_AddRef,
1845     nsProtocolHandler_Release,
1846     nsProtocolHandler_GetScheme,
1847     nsProtocolHandler_GetDefaultPort,
1848     nsProtocolHandler_GetProtocolFlags,
1849     nsProtocolHandler_NewURI,
1850     nsProtocolHandler_NewChannel,
1851     nsProtocolHandler_AllowPort
1852 };
1853
1854 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
1855 {
1856     nsProtocolHandler *ret = mshtml_alloc(sizeof(nsProtocolHandler));
1857
1858     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
1859     ret->ref = 1;
1860     ret->nshandler = nshandler;
1861
1862     return NSPROTHANDLER(ret);
1863 }
1864
1865 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
1866                                                  nsQIResult result)
1867 {
1868     *result = NULL;
1869
1870     if(IsEqualGUID(&IID_nsISupports, riid)
1871        || IsEqualGUID(&IID_nsIIOService, riid)) {
1872         *result = iface;
1873         nsIIOService_AddRef(iface);
1874         return S_OK;
1875     }
1876
1877     WARN("(%s %p)\n", debugstr_guid(riid), result);
1878     return NS_NOINTERFACE;
1879 }
1880
1881 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
1882 {
1883     return 2;
1884 }
1885
1886 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
1887 {
1888     return 1;
1889 }
1890
1891 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
1892                                                      nsIProtocolHandler **_retval)
1893 {
1894     nsIExternalProtocolHandler *nsexthandler;
1895     nsIProtocolHandler *nshandler;
1896     nsresult nsres;
1897
1898     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1899
1900     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
1901     if(NS_FAILED(nsres)) {
1902         WARN("GetProtocolHandler failed: %08x\n", nsres);
1903         return nsres;
1904     }
1905
1906     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
1907                                               (void**)&nsexthandler);
1908     if(NS_FAILED(nsres)) {
1909         *_retval = nshandler;
1910         return NS_OK;
1911     }
1912
1913     nsIExternalProtocolHandler_Release(nsexthandler);
1914     *_retval = create_protocol_handler(nshandler);
1915     TRACE("return %p\n", *_retval);
1916     return NS_OK;
1917 }
1918
1919 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
1920                                                     PRUint32 *_retval)
1921 {
1922     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1923     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
1924 }
1925
1926 static BOOL is_gecko_special_uri(const char *spec)
1927 {
1928     static const char chromeW[] = "chrome:";
1929     static const char jarW[] = "jar:";
1930     static const char resourceW[] = "resource:";
1931     static const char javascriptW[] = "javascript:";
1932
1933     return !strncasecmp(spec, chromeW,     sizeof(chromeW)-1)
1934         || !strncasecmp(spec, resourceW,   sizeof(resourceW)-1)
1935         || !strncasecmp(spec, jarW,        sizeof(jarW)-1)
1936         || !strncasecmp(spec, javascriptW, sizeof(javascriptW)-1);
1937 }
1938
1939 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
1940         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
1941 {
1942     const char *spec = NULL;
1943     nsACString spec_str;
1944     NSContainer *nscontainer = NULL;
1945     nsIURI *uri = NULL;
1946     LPCWSTR base_wine_url = NULL;
1947     nsIWineURI *base_wine_uri = NULL, *wine_uri;
1948     BOOL is_wine_uri = FALSE;
1949     nsresult nsres;
1950
1951     nsACString_GetData(aSpec, &spec, NULL);
1952
1953     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
1954           aBaseURI, _retval);
1955
1956     if(is_gecko_special_uri(spec))
1957         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
1958
1959     if(!strncmp(spec, "wine:", 5)) {
1960         spec += 5;
1961         is_wine_uri = TRUE;
1962     }
1963
1964     if(aBaseURI) {
1965         nsACString base_uri_str;
1966         const char *base_uri = NULL;
1967
1968         nsACString_Init(&base_uri_str, NULL);
1969
1970         nsres = nsIURI_GetSpec(aBaseURI, &base_uri_str);
1971         if(NS_SUCCEEDED(nsres)) {
1972             nsACString_GetData(&base_uri_str, &base_uri, NULL);
1973             TRACE("base_uri=%s\n", debugstr_a(base_uri));
1974         }else {
1975             ERR("GetSpec failed: %08x\n", nsres);
1976         }
1977
1978         nsACString_Finish(&base_uri_str);
1979     }
1980
1981     nsACString_Init(&spec_str, spec);
1982     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
1983     nsACString_Finish(&spec_str);
1984     if(NS_FAILED(nsres))
1985         TRACE("NewURI failed: %08x\n", nsres);
1986
1987     if(aBaseURI) {
1988         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsIWineURI, (void**)&base_wine_uri);
1989         if(NS_SUCCEEDED(nsres)) {
1990             nsIWineURI_GetNSContainer(base_wine_uri, &nscontainer);
1991             nsIWineURI_GetWineURL(base_wine_uri, &base_wine_url);
1992         }else {
1993             TRACE("Could not get base nsIWineURI: %08x\n", nsres);
1994         }
1995     }
1996
1997     nsres = create_uri(uri, nscontainer, &wine_uri);
1998     *_retval = (nsIURI*)wine_uri;
1999
2000     if(nscontainer)
2001         nsIWebBrowserChrome_Release(NSWBCHROME(nscontainer));
2002
2003     if(base_wine_url) {
2004         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2005         DWORD len;
2006         HRESULT hres;
2007
2008         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2009
2010         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2011                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2012                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2013         if(SUCCEEDED(hres))
2014             nsIWineURI_SetWineURL(wine_uri, url);
2015         else
2016              WARN("CoCombineUrl failed: %08x\n", hres);
2017     }else if(is_wine_uri) {
2018         WCHAR url[INTERNET_MAX_URL_LENGTH];
2019
2020         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2021         nsIWineURI_SetWineURL(wine_uri, url);
2022     }
2023
2024     if(base_wine_uri)
2025         nsIWineURI_Release(base_wine_uri);
2026
2027     return nsres;
2028 }
2029
2030 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2031                                              nsIURI **_retval)
2032 {
2033     TRACE("(%p %p)\n", aFile, _retval);
2034     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2035 }
2036
2037 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2038                                                      nsIChannel **_retval)
2039 {
2040     nsIChannel *channel = NULL;
2041     nsChannel *ret;
2042     nsIWineURI *wine_uri;
2043     nsresult nsres;
2044
2045     TRACE("(%p %p)\n", aURI, _retval);
2046
2047     nsres = nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
2048     if(NS_FAILED(nsres) && nsres != NS_ERROR_UNKNOWN_PROTOCOL) {
2049         WARN("NewChannelFromURI failed: %08x\n", nsres);
2050         *_retval = channel;
2051         return nsres;
2052     }
2053
2054     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
2055     if(NS_FAILED(nsres)) {
2056         WARN("Could not get nsIWineURI: %08x\n", nsres);
2057         *_retval = channel;
2058         return channel ? NS_OK : NS_ERROR_UNEXPECTED;
2059     }
2060
2061     ret = mshtml_alloc(sizeof(nsChannel));
2062
2063     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2064     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2065     ret->ref = 1;
2066     ret->channel = channel;
2067     ret->http_channel = NULL;
2068     ret->uri = wine_uri;
2069     ret->post_data_stream = NULL;
2070     ret->load_group = NULL;
2071     ret->notif_callback = NULL;
2072     ret->load_flags = 0;
2073     ret->content = NULL;
2074     ret->charset = NULL;
2075
2076     nsIURI_AddRef(aURI);
2077     ret->original_uri = aURI;
2078
2079     if(channel)
2080         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
2081
2082     *_retval = NSCHANNEL(ret);
2083     return NS_OK;
2084 }
2085
2086 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2087         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2088 {
2089     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2090     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2091 }
2092
2093 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2094 {
2095     TRACE("(%p)\n", aOffline);
2096     return nsIIOService_GetOffline(nsio, aOffline);
2097 }
2098
2099 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2100 {
2101     TRACE("(%x)\n", aOffline);
2102     return nsIIOService_SetOffline(nsio, aOffline);
2103 }
2104
2105 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2106                                              const char *aScheme, PRBool *_retval)
2107 {
2108     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2109     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2110 }
2111
2112 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2113                                                  nsACString * _retval)
2114 {
2115     TRACE("(%p %p)\n", urlString, _retval);
2116     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2117 }
2118
2119 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2120     nsIOService_QueryInterface,
2121     nsIOService_AddRef,
2122     nsIOService_Release,
2123     nsIOService_GetProtocolHandler,
2124     nsIOService_GetProtocolFlags,
2125     nsIOService_NewURI,
2126     nsIOService_NewFileURI,
2127     nsIOService_NewChannelFromURI,
2128     nsIOService_NewChannel,
2129     nsIOService_GetOffline,
2130     nsIOService_SetOffline,
2131     nsIOService_AllowPort,
2132     nsIOService_ExtractScheme
2133 };
2134
2135 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2136
2137 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2138                                                         nsQIResult result)
2139 {
2140     *result = NULL;
2141
2142     if(IsEqualGUID(&IID_nsISupports, riid)) {
2143         TRACE("(IID_nsISupoprts %p)\n", result);
2144         *result = iface;
2145     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2146         TRACE("(IID_nsIFactory %p)\n", result);
2147         *result = iface;
2148     }
2149
2150     if(*result) {
2151         nsIFactory_AddRef(iface);
2152         return NS_OK;
2153     }
2154
2155     WARN("(%s %p)\n", debugstr_guid(riid), result);
2156     return NS_NOINTERFACE;
2157 }
2158
2159 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2160 {
2161     return 2;
2162 }
2163
2164 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2165 {
2166     return 1;
2167 }
2168
2169 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2170         nsISupports *aOuter, const nsIID *iid, void **result)
2171 {
2172     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2173 }
2174
2175 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2176 {
2177     WARN("(%x)\n", lock);
2178     return NS_OK;
2179 }
2180
2181 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2182     nsIOServiceFactory_QueryInterface,
2183     nsIOServiceFactory_AddRef,
2184     nsIOServiceFactory_Release,
2185     nsIOServiceFactory_CreateInstance,
2186     nsIOServiceFactory_LockFactory
2187 };
2188
2189 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2190
2191 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2192 {
2193     nsIFactory *old_factory = NULL;
2194     nsresult nsres;
2195
2196     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2197                                                &IID_nsIFactory, (void**)&old_factory);
2198     if(NS_FAILED(nsres)) {
2199         ERR("Could not get factory: %08x\n", nsres);
2200         return;
2201     }
2202
2203     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2204     if(NS_FAILED(nsres)) {
2205         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2206         nsIFactory_Release(old_factory);
2207         return;
2208     }
2209
2210     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2211     nsIFactory_Release(old_factory);
2212     if(NS_FAILED(nsres))
2213         ERR("UnregisterFactory failed: %08x\n", nsres);
2214
2215     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2216             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2217     if(NS_FAILED(nsres))
2218         ERR("RegisterFactory failed: %08x\n", nsres);
2219 }