credui: Updated French translation.
[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     nsACString scheme_str;
572     nsresult nsres;
573     BOOL ret = TRUE;
574
575     /* 
576      * We should always load the page from IMoniker, but Wine is not yet
577      * ready for this. This function is a heuristic, that decides which
578      * way of loading is better (Gecko implementation or IMoniker). The
579      * aim is to always return TRUE.
580      */
581
582     /* Load from moniker if there is no Gecko channel available */
583     if(!This->channel)
584         return TRUE;
585
586     nsACString_Init(&scheme_str, NULL);
587     nsres = nsIWineURI_GetScheme(This->uri, &scheme_str);
588
589     if(NS_SUCCEEDED(nsres)) {
590         const char *scheme;
591
592         nsACString_GetData(&scheme_str, &scheme, NULL);
593         ret = !strcmp(scheme, "wine");
594     }
595
596     nsACString_Finish(&scheme_str);
597     return ret;
598 }
599
600 static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
601 {
602     nsIWineURI *wine_uri;
603     LPCWSTR wine_url;
604     nsresult nsres;
605     HRESULT hres;
606
607     if(!channel->original_uri) {
608         ERR("original_uri == NULL\n");
609         return E_FAIL;
610     }
611
612     nsres = nsIURI_QueryInterface(channel->original_uri, &IID_nsIWineURI, (void**)&wine_uri);
613     if(NS_FAILED(nsres)) {
614         ERR("Could not get nsIWineURI: %08x\n", nsres);
615         return E_FAIL;
616     }
617
618     nsIWineURI_GetWineURL(wine_uri, &wine_url);
619     nsIWineURI_Release(wine_uri);
620     if(!wine_url) {
621         TRACE("wine_url == NULL\n");
622         return E_FAIL;
623     }
624
625     hres = CreateURLMoniker(NULL, wine_url, mon);
626     if(FAILED(hres))
627         WARN("CreateURLMonikrer failed: %08x\n", hres);
628
629     return hres;
630 }
631
632 static nsresult async_open_doc_uri(nsChannel *This, NSContainer *container,
633         nsIStreamListener *listener, nsISupports *context, BOOL *open)
634 {
635     IMoniker *mon;
636     HRESULT hres;
637
638     *open = FALSE;
639
640     if(container->bscallback) {
641         nsIChannel_AddRef(NSCHANNEL(This));
642         container->bscallback->nschannel = This;
643
644         nsIStreamListener_AddRef(listener);
645         container->bscallback->nslistener = listener;
646
647         if(context) {
648             nsISupports_AddRef(context);
649             container->bscallback->nscontext = context;
650         }
651
652         if(do_load_from_moniker_hack(This))
653             return WINE_NS_LOAD_FROM_MONIKER;
654     }else  {
655         BOOL cont = before_async_open(This, container);
656
657         if(!cont) {
658             TRACE("canceled\n");
659             return NS_ERROR_UNEXPECTED;
660         }
661
662         if(!container->doc) {
663             return This->channel
664                 ?  nsIChannel_AsyncOpen(This->channel, listener, context)
665                 : NS_ERROR_UNEXPECTED;
666         }
667
668         hres = create_mon_for_nschannel(This, &mon);
669         if(FAILED(hres)) {
670             return NS_ERROR_UNEXPECTED;
671         }
672         set_current_mon(container->doc, mon);
673     }
674
675     *open = TRUE;
676     return NS_OK;
677 }
678
679 static nsresult async_open(nsChannel *This, NSContainer *container, nsIStreamListener *listener,
680         nsISupports *context)
681 {
682     BSCallback *bscallback;
683     IMoniker *mon = NULL;
684     nsresult nsres;
685     task_t *task;
686     HRESULT hres;
687
688     if(This->channel) {
689         if(This->post_data_stream) {
690             nsIUploadChannel *upload_channel;
691
692             nsres = nsIChannel_QueryInterface(This->channel, &IID_nsIUploadChannel,
693                                           (void**)&upload_channel);
694             if(NS_SUCCEEDED(nsres)) {
695                 nsACString empty_string;
696                 nsACString_Init(&empty_string, "");
697
698                 nsres = nsIUploadChannel_SetUploadStream(upload_channel, This->post_data_stream,
699                                                          &empty_string, -1);
700                 nsIUploadChannel_Release(upload_channel);
701                 if(NS_FAILED(nsres))
702                     WARN("SetUploadStream failed: %08x\n", nsres);
703
704                 nsACString_Finish(&empty_string);
705             }
706         }
707
708         nsres = nsIChannel_AsyncOpen(This->channel, listener, context);
709
710         if(mon)
711             IMoniker_Release(mon);
712
713         if(NS_FAILED(nsres) && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI))
714             return WINE_NS_LOAD_FROM_MONIKER;
715         return nsres;
716     }
717
718     TRACE("channel == NULL\n");
719
720     hres = create_mon_for_nschannel(This, &mon);
721     if(FAILED(hres))
722         return NS_ERROR_UNEXPECTED;
723
724     bscallback = create_bscallback(mon);
725     IMoniker_Release(mon);
726
727     nsIChannel_AddRef(NSCHANNEL(This));
728     bscallback->nschannel = This;
729
730     nsIStreamListener_AddRef(listener);
731     bscallback->nslistener = listener;
732
733     if(context) {
734         nsISupports_AddRef(context);
735         bscallback->nscontext = context;
736     }
737
738     task = mshtml_alloc(sizeof(task_t));
739
740     task->doc = container->doc;
741     task->task_id = TASK_START_BINDING;
742     task->next = NULL;
743     task->bscallback = bscallback;
744
745     push_task(task);
746
747     return NS_OK;
748 }
749
750 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
751                                           nsISupports *aContext)
752 {
753     nsChannel *This = NSCHANNEL_THIS(iface);
754     NSContainer *container;
755     PRBool is_doc_uri;
756     BOOL open = TRUE;
757     nsresult nsres = NS_OK;
758
759     TRACE("(%p)->(%p %p)\n", This, aListener, aContext);
760
761     nsIWineURI_GetNSContainer(This->uri, &container);
762     if(!container) {
763         TRACE("container = NULL\n");
764         return This->channel
765             ? nsIChannel_AsyncOpen(This->channel, aListener, aContext)
766             : NS_ERROR_UNEXPECTED;
767     }
768
769     nsIWineURI_GetIsDocumentURI(This->uri, &is_doc_uri);
770
771     if(is_doc_uri && (This->load_flags & LOAD_INITIAL_DOCUMENT_URI))
772         nsres = async_open_doc_uri(This, container, aListener, aContext, &open);
773
774     if(open)
775         nsres = async_open(This, container, aListener, aContext);
776
777     nsIWebBrowserChrome_Release(NSWBCHROME(container));
778     return nsres;
779 }
780
781 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
782 {
783     nsChannel *This = NSCHANNEL_THIS(iface);
784
785     TRACE("(%p)->(%p)\n", This, aRequestMethod);
786
787     if(This->http_channel)
788         return nsIHttpChannel_GetRequestMethod(This->http_channel, aRequestMethod);
789
790     return NS_ERROR_NOT_IMPLEMENTED;
791 }
792
793 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
794                                                  const nsACString *aRequestMethod)
795 {
796     nsChannel *This = NSCHANNEL_THIS(iface);
797
798     TRACE("(%p)->(%p)\n", This, aRequestMethod);
799
800     if(This->http_channel)
801         return nsIHttpChannel_SetRequestMethod(This->http_channel, aRequestMethod);
802
803     return NS_ERROR_NOT_IMPLEMENTED;
804 }
805
806 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
807 {
808     nsChannel *This = NSCHANNEL_THIS(iface);
809
810     TRACE("(%p)->(%p)\n", This, aReferrer);
811
812     if(This->http_channel)
813         return nsIHttpChannel_GetReferrer(This->http_channel, aReferrer);
814
815     return NS_ERROR_NOT_IMPLEMENTED;
816 }
817
818 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
819 {
820     nsChannel *This = NSCHANNEL_THIS(iface);
821
822     TRACE("(%p)->(%p)\n", This, aReferrer);
823
824     if(This->http_channel)
825         return nsIHttpChannel_SetReferrer(This->http_channel, aReferrer);
826
827     return NS_ERROR_NOT_IMPLEMENTED;
828 }
829
830 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
831          const nsACString *aHeader, nsACString *_retval)
832 {
833     nsChannel *This = NSCHANNEL_THIS(iface);
834
835     TRACE("(%p)->(%p %p)\n", This, aHeader, _retval);
836
837     if(This->http_channel)
838         return nsIHttpChannel_GetRequestHeader(This->http_channel, aHeader, _retval);
839
840     return NS_ERROR_NOT_IMPLEMENTED;
841 }
842
843 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
844          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
845 {
846     nsChannel *This = NSCHANNEL_THIS(iface);
847
848     TRACE("(%p)->(%p %p %x)\n", This, aHeader, aValue, aMerge);
849
850     if(This->http_channel)
851         return nsIHttpChannel_SetRequestHeader(This->http_channel, aHeader, aValue, aMerge);
852
853     return NS_ERROR_NOT_IMPLEMENTED;
854 }
855
856 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
857                                                     nsIHttpHeaderVisitor *aVisitor)
858 {
859     nsChannel *This = NSCHANNEL_THIS(iface);
860
861     TRACE("(%p)->(%p)\n", This, aVisitor);
862
863     if(This->http_channel)
864         return nsIHttpChannel_VisitRequestHeaders(This->http_channel, aVisitor);
865
866     return NS_ERROR_NOT_IMPLEMENTED;
867 }
868
869 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
870 {
871     nsChannel *This = NSCHANNEL_THIS(iface);
872
873     TRACE("(%p)->(%p)\n", This, aAllowPipelining);
874
875     if(This->http_channel)
876         return nsIHttpChannel_GetAllowPipelining(This->http_channel, aAllowPipelining);
877
878     return NS_ERROR_NOT_IMPLEMENTED;
879 }
880
881 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
882 {
883     nsChannel *This = NSCHANNEL_THIS(iface);
884
885     TRACE("(%p)->(%x)\n", This, aAllowPipelining);
886
887     if(This->http_channel)
888         return nsIHttpChannel_SetAllowPipelining(This->http_channel, aAllowPipelining);
889
890     return NS_ERROR_NOT_IMPLEMENTED;
891 }
892
893 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
894 {
895     nsChannel *This = NSCHANNEL_THIS(iface);
896
897     TRACE("(%p)->(%p)\n", This, aRedirectionLimit);
898
899     if(This->http_channel)
900         return nsIHttpChannel_GetRedirectionLimit(This->http_channel, aRedirectionLimit);
901
902     return NS_ERROR_NOT_IMPLEMENTED;
903 }
904
905 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
906 {
907     nsChannel *This = NSCHANNEL_THIS(iface);
908
909     TRACE("(%p)->(%u)\n", This, aRedirectionLimit);
910
911     if(This->http_channel)
912         return nsIHttpChannel_SetRedirectionLimit(This->http_channel, aRedirectionLimit);
913
914     return NS_ERROR_NOT_IMPLEMENTED;
915 }
916
917 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
918 {
919     nsChannel *This = NSCHANNEL_THIS(iface);
920
921     TRACE("(%p)->(%p)\n", This, aResponseStatus);
922
923     if(This->http_channel)
924         return nsIHttpChannel_GetResponseStatus(This->http_channel, aResponseStatus);
925
926     return NS_ERROR_NOT_IMPLEMENTED;
927 }
928
929 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
930                                                       nsACString *aResponseStatusText)
931 {
932     nsChannel *This = NSCHANNEL_THIS(iface);
933
934     TRACE("(%p)->(%p)\n", This, aResponseStatusText);
935
936     if(This->http_channel)
937         return nsIHttpChannel_GetResponseStatusText(This->http_channel, aResponseStatusText);
938
939     return NS_ERROR_NOT_IMPLEMENTED;
940 }
941
942 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
943                                                     PRBool *aRequestSucceeded)
944 {
945     nsChannel *This = NSCHANNEL_THIS(iface);
946
947     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
948
949     if(This->http_channel)
950         return nsIHttpChannel_GetRequestSucceeded(This->http_channel, aRequestSucceeded);
951
952     return NS_ERROR_NOT_IMPLEMENTED;
953 }
954
955 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
956          const nsACString *header, nsACString *_retval)
957 {
958     nsChannel *This = NSCHANNEL_THIS(iface);
959
960     TRACE("(%p)->(%p %p)\n", This, header, _retval);
961
962     if(This->http_channel)
963         return nsIHttpChannel_GetResponseHeader(This->http_channel, header, _retval);
964
965     return NS_ERROR_NOT_IMPLEMENTED;
966 }
967
968 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
969         const nsACString *header, const nsACString *value, PRBool merge)
970 {
971     nsChannel *This = NSCHANNEL_THIS(iface);
972
973     TRACE("(%p)->(%p %p %x)\n", This, header, value, merge);
974
975     if(This->http_channel)
976         return nsIHttpChannel_SetResponseHeader(This->http_channel, header, value, merge);
977
978     return NS_ERROR_NOT_IMPLEMENTED;
979 }
980
981 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
982         nsIHttpHeaderVisitor *aVisitor)
983 {
984     nsChannel *This = NSCHANNEL_THIS(iface);
985
986     TRACE("(%p)->(%p)\n", This, aVisitor);
987
988     if(This->http_channel)
989         return nsIHttpChannel_VisitResponseHeaders(This->http_channel, aVisitor);
990
991     return NS_ERROR_NOT_IMPLEMENTED;
992 }
993
994 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
995 {
996     nsChannel *This = NSCHANNEL_THIS(iface);
997
998     TRACE("(%p)->(%p)\n", This, _retval);
999
1000     if(This->http_channel)
1001         return nsIHttpChannel_IsNoStoreResponse(This->http_channel, _retval);
1002
1003     return NS_ERROR_NOT_IMPLEMENTED;
1004 }
1005
1006 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
1007 {
1008     nsChannel *This = NSCHANNEL_THIS(iface);
1009
1010     TRACE("(%p)->(%p)\n", This, _retval);
1011
1012     if(This->http_channel)
1013         return nsIHttpChannel_IsNoCacheResponse(This->http_channel, _retval);
1014
1015     return NS_ERROR_NOT_IMPLEMENTED;
1016 }
1017
1018 #undef NSCHANNEL_THIS
1019
1020 static const nsIHttpChannelVtbl nsChannelVtbl = {
1021     nsChannel_QueryInterface,
1022     nsChannel_AddRef,
1023     nsChannel_Release,
1024     nsChannel_GetName,
1025     nsChannel_IsPending,
1026     nsChannel_GetStatus,
1027     nsChannel_Cancel,
1028     nsChannel_Suspend,
1029     nsChannel_Resume,
1030     nsChannel_GetLoadGroup,
1031     nsChannel_SetLoadGroup,
1032     nsChannel_GetLoadFlags,
1033     nsChannel_SetLoadFlags,
1034     nsChannel_GetOriginalURI,
1035     nsChannel_SetOriginalURI,
1036     nsChannel_GetURI,
1037     nsChannel_GetOwner,
1038     nsChannel_SetOwner,
1039     nsChannel_GetNotificationCallbacks,
1040     nsChannel_SetNotificationCallbacks,
1041     nsChannel_GetSecurityInfo,
1042     nsChannel_GetContentType,
1043     nsChannel_SetContentType,
1044     nsChannel_GetContentCharset,
1045     nsChannel_SetContentCharset,
1046     nsChannel_GetContentLength,
1047     nsChannel_SetContentLength,
1048     nsChannel_Open,
1049     nsChannel_AsyncOpen,
1050     nsChannel_GetRequestMethod,
1051     nsChannel_SetRequestMethod,
1052     nsChannel_GetReferrer,
1053     nsChannel_SetReferrer,
1054     nsChannel_GetRequestHeader,
1055     nsChannel_SetRequestHeader,
1056     nsChannel_VisitRequestHeaders,
1057     nsChannel_GetAllowPipelining,
1058     nsChannel_SetAllowPipelining,
1059     nsChannel_GetRedirectionLimit,
1060     nsChannel_SetRedirectionLimit,
1061     nsChannel_GetResponseStatus,
1062     nsChannel_GetResponseStatusText,
1063     nsChannel_GetRequestSucceeded,
1064     nsChannel_GetResponseHeader,
1065     nsChannel_SetResponseHeader,
1066     nsChannel_VisitResponseHeaders,
1067     nsChannel_IsNoStoreResponse,
1068     nsChannel_IsNoCacheResponse
1069 };
1070
1071 #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface)
1072
1073 static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid,
1074                                                      nsQIResult result)
1075 {
1076     nsChannel *This = NSUPCHANNEL_THIS(iface);
1077     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1078 }
1079
1080 static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface)
1081 {
1082     nsChannel *This = NSUPCHANNEL_THIS(iface);
1083     return nsIChannel_AddRef(NSCHANNEL(This));
1084 }
1085
1086 static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface)
1087 {
1088     nsChannel *This = NSUPCHANNEL_THIS(iface);
1089     return nsIChannel_Release(NSCHANNEL(This));
1090 }
1091
1092 static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
1093         nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength)
1094 {
1095     nsChannel *This = NSUPCHANNEL_THIS(iface);
1096     const char *content_type;
1097
1098     TRACE("(%p)->(%p %p %d)\n", This, aStream, aContentType, aContentLength);
1099
1100     if(This->post_data_stream)
1101         nsIInputStream_Release(This->post_data_stream);
1102
1103     if(aContentType) {
1104         nsACString_GetData(aContentType, &content_type, NULL);
1105         if(*content_type)
1106             FIXME("Unsupported aContentType argument: %s\n", debugstr_a(content_type));
1107     }
1108
1109     if(aContentLength != -1)
1110         FIXME("Unsupported acontentLength = %d\n", aContentLength);
1111
1112     if(aStream)
1113         nsIInputStream_AddRef(aStream);
1114     This->post_data_stream = aStream;
1115
1116     return NS_OK;
1117 }
1118
1119 static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface,
1120         nsIInputStream **aUploadStream)
1121 {
1122     nsChannel *This = NSUPCHANNEL_THIS(iface);
1123
1124     TRACE("(%p)->(%p)\n", This, aUploadStream);
1125
1126     if(This->post_data_stream)
1127         nsIInputStream_AddRef(This->post_data_stream);
1128
1129     *aUploadStream = This->post_data_stream;
1130     return NS_OK;
1131 }
1132
1133 #undef NSUPCHANNEL_THIS
1134
1135 static const nsIUploadChannelVtbl nsUploadChannelVtbl = {
1136     nsUploadChannel_QueryInterface,
1137     nsUploadChannel_AddRef,
1138     nsUploadChannel_Release,
1139     nsUploadChannel_SetUploadStream,
1140     nsUploadChannel_GetUploadStream
1141 };
1142
1143 #define NSURI_THIS(iface) DEFINE_THIS(nsURI, WineURI, iface)
1144
1145 static nsresult NSAPI nsURI_QueryInterface(nsIWineURI *iface, nsIIDRef riid, nsQIResult result)
1146 {
1147     nsURI *This = NSURI_THIS(iface);
1148
1149     *result = NULL;
1150
1151     if(IsEqualGUID(&IID_nsISupports, riid)) {
1152         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1153         *result = NSURI(This);
1154     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
1155         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
1156         *result = NSURI(This);
1157     }else if(IsEqualGUID(&IID_nsIWineURI, riid)) {
1158         TRACE("(%p)->(IID_nsIWineURI %p)\n", This, result);
1159         *result = NSURI(This);
1160     }
1161
1162     if(*result) {
1163         nsIURI_AddRef(NSURI(This));
1164         return NS_OK;
1165     }
1166
1167     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1168     return This->uri ? nsIURI_QueryInterface(This->uri, riid, result) : NS_NOINTERFACE;
1169 }
1170
1171 static nsrefcnt NSAPI nsURI_AddRef(nsIWineURI *iface)
1172 {
1173     nsURI *This = NSURI_THIS(iface);
1174     LONG ref = InterlockedIncrement(&This->ref);
1175
1176     TRACE("(%p) ref=%d\n", This, ref);
1177
1178     return ref;
1179 }
1180
1181 static nsrefcnt NSAPI nsURI_Release(nsIWineURI *iface)
1182 {
1183     nsURI *This = NSURI_THIS(iface);
1184     LONG ref = InterlockedDecrement(&This->ref);
1185
1186     TRACE("(%p) ref=%d\n", This, ref);
1187
1188     if(!ref) {
1189         if(This->container)
1190             nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1191         if(This->uri)
1192             nsIURI_Release(This->uri);
1193         mshtml_free(This->wine_url);
1194         mshtml_free(This);
1195     }
1196
1197     return ref;
1198 }
1199
1200 static nsresult NSAPI nsURI_GetSpec(nsIWineURI *iface, nsACString *aSpec)
1201 {
1202     nsURI *This = NSURI_THIS(iface);
1203
1204     TRACE("(%p)->(%p)\n", This, aSpec);
1205
1206     if(This->use_wine_url) {
1207         char speca[INTERNET_MAX_URL_LENGTH] = "wine:";
1208         WideCharToMultiByte(CP_ACP, 0, This->wine_url, -1, speca+5, sizeof(speca)-5, NULL, NULL);
1209         nsACString_SetData(aSpec, speca);
1210
1211         return NS_OK;
1212     }
1213
1214     if(This->uri)
1215         return nsIURI_GetSpec(This->uri, aSpec);
1216
1217     TRACE("returning error\n");
1218     return NS_ERROR_NOT_IMPLEMENTED;
1219
1220 }
1221
1222 static nsresult NSAPI nsURI_SetSpec(nsIWineURI *iface, const nsACString *aSpec)
1223 {
1224     nsURI *This = NSURI_THIS(iface);
1225
1226     TRACE("(%p)->(%p)\n", This, aSpec);
1227
1228     if(This->uri)
1229         return nsIURI_SetSpec(This->uri, aSpec);
1230
1231     FIXME("default action not implemented\n");
1232     return NS_ERROR_NOT_IMPLEMENTED;
1233 }
1234
1235 static nsresult NSAPI nsURI_GetPrePath(nsIWineURI *iface, nsACString *aPrePath)
1236 {
1237     nsURI *This = NSURI_THIS(iface);
1238
1239     TRACE("(%p)->(%p)\n", This, aPrePath);
1240
1241     if(This->uri)
1242         return nsIURI_GetPrePath(This->uri, aPrePath);
1243
1244     FIXME("default action not implemented\n");
1245     return NS_ERROR_NOT_IMPLEMENTED;
1246 }
1247
1248 static nsresult NSAPI nsURI_GetScheme(nsIWineURI *iface, nsACString *aScheme)
1249 {
1250     nsURI *This = NSURI_THIS(iface);
1251
1252     TRACE("(%p)->(%p)\n", This, aScheme);
1253
1254     if(This->use_wine_url) {
1255         /*
1256          * For Gecko we set scheme to unknown so it won't be handled
1257          * as any special case.
1258          */
1259         nsACString_SetData(aScheme, "wine");
1260         return NS_OK;
1261     }
1262
1263     if(This->uri)
1264         return nsIURI_GetScheme(This->uri, aScheme);
1265
1266     TRACE("returning error\n");
1267     return NS_ERROR_NOT_IMPLEMENTED;
1268 }
1269
1270 static nsresult NSAPI nsURI_SetScheme(nsIWineURI *iface, const nsACString *aScheme)
1271 {
1272     nsURI *This = NSURI_THIS(iface);
1273
1274     TRACE("(%p)->(%p)\n", This, aScheme);
1275
1276     if(This->uri)
1277         return nsIURI_SetScheme(This->uri, aScheme);
1278
1279     FIXME("default action not implemented\n");
1280     return NS_ERROR_NOT_IMPLEMENTED;
1281 }
1282
1283 static nsresult NSAPI nsURI_GetUserPass(nsIWineURI *iface, nsACString *aUserPass)
1284 {
1285     nsURI *This = NSURI_THIS(iface);
1286
1287     TRACE("(%p)->(%p)\n", This, aUserPass);
1288
1289     if(This->uri)
1290         return nsIURI_GetUserPass(This->uri, aUserPass);
1291
1292     FIXME("default action not implemented\n");
1293     return NS_ERROR_NOT_IMPLEMENTED;
1294 }
1295
1296 static nsresult NSAPI nsURI_SetUserPass(nsIWineURI *iface, const nsACString *aUserPass)
1297 {
1298     nsURI *This = NSURI_THIS(iface);
1299
1300     TRACE("(%p)->(%p)\n", This, aUserPass);
1301
1302     if(This->uri)
1303         return nsIURI_SetUserPass(This->uri, aUserPass);
1304
1305     FIXME("default action not implemented\n");
1306     return NS_ERROR_NOT_IMPLEMENTED;
1307 }
1308
1309 static nsresult NSAPI nsURI_GetUsername(nsIWineURI *iface, nsACString *aUsername)
1310 {
1311     nsURI *This = NSURI_THIS(iface);
1312
1313     TRACE("(%p)->(%p)\n", This, aUsername);
1314
1315     if(This->uri)
1316         return nsIURI_GetUsername(This->uri, aUsername);
1317
1318     FIXME("default action not implemented\n");
1319     return NS_ERROR_NOT_IMPLEMENTED;
1320 }
1321
1322 static nsresult NSAPI nsURI_SetUsername(nsIWineURI *iface, const nsACString *aUsername)
1323 {
1324     nsURI *This = NSURI_THIS(iface);
1325
1326     TRACE("(%p)->(%p)\n", This, aUsername);
1327
1328     if(This->uri)
1329         return nsIURI_SetUsername(This->uri, aUsername);
1330
1331     FIXME("default action not implemented\n");
1332     return NS_ERROR_NOT_IMPLEMENTED;
1333 }
1334
1335 static nsresult NSAPI nsURI_GetPassword(nsIWineURI *iface, nsACString *aPassword)
1336 {
1337     nsURI *This = NSURI_THIS(iface);
1338
1339     TRACE("(%p)->(%p)\n", This, aPassword);
1340
1341     if(This->uri)
1342         return nsIURI_GetPassword(This->uri, aPassword);
1343
1344     FIXME("default action not implemented\n");
1345     return NS_ERROR_NOT_IMPLEMENTED;
1346 }
1347
1348 static nsresult NSAPI nsURI_SetPassword(nsIWineURI *iface, const nsACString *aPassword)
1349 {
1350     nsURI *This = NSURI_THIS(iface);
1351
1352     TRACE("(%p)->(%p)\n", This, aPassword);
1353
1354     if(This->uri)
1355         return nsIURI_SetPassword(This->uri, aPassword);
1356
1357     FIXME("default action not implemented\n");
1358     return NS_ERROR_NOT_IMPLEMENTED;
1359 }
1360
1361 static nsresult NSAPI nsURI_GetHostPort(nsIWineURI *iface, nsACString *aHostPort)
1362 {
1363     nsURI *This = NSURI_THIS(iface);
1364
1365     TRACE("(%p)->(%p)\n", This, aHostPort);
1366
1367     if(This->uri)
1368         return nsIURI_GetHostPort(This->uri, aHostPort);
1369
1370     FIXME("default action not implemented\n");
1371     return NS_ERROR_NOT_IMPLEMENTED;
1372 }
1373
1374 static nsresult NSAPI nsURI_SetHostPort(nsIWineURI *iface, const nsACString *aHostPort)
1375 {
1376     nsURI *This = NSURI_THIS(iface);
1377
1378     TRACE("(%p)->(%p)\n", This, aHostPort);
1379
1380     if(This->uri)
1381         return nsIURI_SetHostPort(This->uri, aHostPort);
1382
1383     FIXME("default action not implemented\n");
1384     return NS_ERROR_NOT_IMPLEMENTED;
1385 }
1386
1387 static nsresult NSAPI nsURI_GetHost(nsIWineURI *iface, nsACString *aHost)
1388 {
1389     nsURI *This = NSURI_THIS(iface);
1390
1391     TRACE("(%p)->(%p)\n", This, aHost);
1392
1393     if(This->uri)
1394         return nsIURI_GetHost(This->uri, aHost);
1395
1396     FIXME("default action not implemented\n");
1397     return NS_ERROR_NOT_IMPLEMENTED;
1398 }
1399
1400 static nsresult NSAPI nsURI_SetHost(nsIWineURI *iface, const nsACString *aHost)
1401 {
1402     nsURI *This = NSURI_THIS(iface);
1403
1404     TRACE("(%p)->(%p)\n", This, aHost);
1405
1406     if(This->uri)
1407         return nsIURI_SetHost(This->uri, aHost);
1408
1409     FIXME("default action not implemented\n");
1410     return NS_ERROR_NOT_IMPLEMENTED;
1411 }
1412
1413 static nsresult NSAPI nsURI_GetPort(nsIWineURI *iface, PRInt32 *aPort)
1414 {
1415     nsURI *This = NSURI_THIS(iface);
1416
1417     TRACE("(%p)->(%p)\n", This, aPort);
1418
1419     if(This->uri)
1420         return nsIURI_GetPort(This->uri, aPort);
1421
1422     FIXME("default action not implemented\n");
1423     return NS_ERROR_NOT_IMPLEMENTED;
1424 }
1425
1426 static nsresult NSAPI nsURI_SetPort(nsIWineURI *iface, PRInt32 aPort)
1427 {
1428     nsURI *This = NSURI_THIS(iface);
1429
1430     TRACE("(%p)->(%d)\n", This, aPort);
1431
1432     if(This->uri)
1433         return nsIURI_SetPort(This->uri, aPort);
1434
1435     FIXME("default action not implemented\n");
1436     return NS_ERROR_NOT_IMPLEMENTED;
1437 }
1438
1439 static nsresult NSAPI nsURI_GetPath(nsIWineURI *iface, nsACString *aPath)
1440 {
1441     nsURI *This = NSURI_THIS(iface);
1442
1443     TRACE("(%p)->(%p)\n", This, aPath);
1444
1445     if(This->uri)
1446         return nsIURI_GetPath(This->uri, aPath);
1447
1448     FIXME("default action not implemented\n");
1449     return NS_ERROR_NOT_IMPLEMENTED;
1450 }
1451
1452 static nsresult NSAPI nsURI_SetPath(nsIWineURI *iface, const nsACString *aPath)
1453 {
1454     nsURI *This = NSURI_THIS(iface);
1455
1456     TRACE("(%p)->(%p)\n", This, aPath);
1457
1458     if(This->uri)
1459         return nsIURI_SetPath(This->uri, aPath);
1460
1461     FIXME("default action not implemented\n");
1462     return NS_ERROR_NOT_IMPLEMENTED;
1463 }
1464
1465 static nsresult NSAPI nsURI_Equals(nsIWineURI *iface, nsIURI *other, PRBool *_retval)
1466 {
1467     nsURI *This = NSURI_THIS(iface);
1468
1469     TRACE("(%p)->(%p %p)\n", This, other, _retval);
1470
1471     if(This->uri)
1472         return nsIURI_Equals(This->uri, other, _retval);
1473
1474     FIXME("default action not implemented\n");
1475     return NS_ERROR_NOT_IMPLEMENTED;
1476 }
1477
1478 static nsresult NSAPI nsURI_SchemeIs(nsIWineURI *iface, const char *scheme, PRBool *_retval)
1479 {
1480     nsURI *This = NSURI_THIS(iface);
1481
1482     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
1483
1484     if(This->use_wine_url) {
1485         WCHAR buf[INTERNET_MAX_SCHEME_LENGTH];
1486         int len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
1487
1488         *_retval = strlenW(This->wine_url) > len
1489             && This->wine_url[len] == ':'
1490             && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
1491         return NS_OK;
1492     }
1493
1494     if(This->uri)
1495         return nsIURI_SchemeIs(This->uri, scheme, _retval);
1496
1497     TRACE("returning error\n");
1498     return NS_ERROR_NOT_IMPLEMENTED;
1499 }
1500
1501 static nsresult NSAPI nsURI_Clone(nsIWineURI *iface, nsIURI **_retval)
1502 {
1503     nsURI *This = NSURI_THIS(iface);
1504
1505     TRACE("(%p)->(%p)\n", This, _retval);
1506
1507     if(This->uri) {
1508         nsIURI *uri;
1509         nsIWineURI *wine_uri;
1510         nsresult nsres;
1511
1512         nsres = nsIURI_Clone(This->uri, &uri);
1513         if(NS_FAILED(nsres)) {
1514             WARN("Clone failed: %08x\n", nsres);
1515             return nsres;
1516         }
1517
1518         nsres = create_uri(uri, This->container, &wine_uri);
1519         *_retval = (nsIURI*)wine_uri;
1520         if(NS_SUCCEEDED(nsres))
1521             return nsIWineURI_SetWineURL(wine_uri, This->wine_url);
1522         return nsres;
1523     }
1524
1525     FIXME("default action not implemented\n");
1526     return NS_ERROR_NOT_IMPLEMENTED;
1527 }
1528
1529 static nsresult NSAPI nsURI_Resolve(nsIWineURI *iface, const nsACString *arelativePath,
1530         nsACString *_retval)
1531 {
1532     nsURI *This = NSURI_THIS(iface);
1533
1534     TRACE("(%p)->(%p %p)\n", This, arelativePath, _retval);
1535
1536     if(This->uri)
1537         return nsIURI_Resolve(This->uri, arelativePath, _retval);
1538
1539     FIXME("default action not implemented\n");
1540     return NS_ERROR_NOT_IMPLEMENTED;
1541 }
1542
1543 static nsresult NSAPI nsURI_GetAsciiSpec(nsIWineURI *iface, nsACString *aAsciiSpec)
1544 {
1545     nsURI *This = NSURI_THIS(iface);
1546
1547     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
1548
1549     if(This->use_wine_url)
1550         return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
1551
1552     if(This->uri)
1553         return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
1554
1555     TRACE("returning error\n");
1556     return NS_ERROR_NOT_IMPLEMENTED;
1557 }
1558
1559 static nsresult NSAPI nsURI_GetAsciiHost(nsIWineURI *iface, nsACString *aAsciiHost)
1560 {
1561     nsURI *This = NSURI_THIS(iface);
1562
1563     TRACE("(%p)->(%p)\n", This, aAsciiHost);
1564
1565     if(This->uri)
1566         return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
1567
1568     FIXME("default action not implemented\n");
1569     return NS_ERROR_NOT_IMPLEMENTED;
1570 }
1571
1572 static nsresult NSAPI nsURI_GetOriginCharset(nsIWineURI *iface, nsACString *aOriginCharset)
1573 {
1574     nsURI *This = NSURI_THIS(iface);
1575
1576     TRACE("(%p)->(%p)\n", This, aOriginCharset);
1577
1578     if(This->uri)
1579         return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
1580
1581     FIXME("default action not implemented\n");
1582     return NS_ERROR_NOT_IMPLEMENTED;
1583 }
1584
1585 static nsresult NSAPI nsURI_GetNSContainer(nsIWineURI *iface, NSContainer **aContainer)
1586 {
1587     nsURI *This = NSURI_THIS(iface);
1588
1589     TRACE("(%p)->(%p)\n", This, aContainer);
1590
1591     if(This->container)
1592         nsIWebBrowserChrome_AddRef(NSWBCHROME(This->container));
1593     *aContainer = This->container;
1594
1595     return NS_OK;
1596 }
1597
1598 static nsresult NSAPI nsURI_SetNSContainer(nsIWineURI *iface, NSContainer *aContainer)
1599 {
1600     nsURI *This = NSURI_THIS(iface);
1601
1602     TRACE("(%p)->(%p)\n", This, aContainer);
1603
1604     if(This->container) {
1605         if(This->container == aContainer)
1606             return NS_OK;
1607         TRACE("Changing %p -> %p\n", This->container, aContainer);
1608         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1609     }
1610
1611     if(aContainer)
1612         nsIWebBrowserChrome_AddRef(NSWBCHROME(aContainer));
1613     This->container = aContainer;
1614
1615     return NS_OK;
1616 }
1617
1618 static nsresult NSAPI nsURI_GetIsDocumentURI(nsIWineURI *iface, PRBool *aIsDocumentURI)
1619 {
1620     nsURI *This = NSURI_THIS(iface);
1621
1622     TRACE("(%p)->(%p)\n", This, aIsDocumentURI);
1623
1624     *aIsDocumentURI = This->is_doc_uri;
1625     return NS_OK;
1626 }
1627
1628 static nsresult NSAPI nsURI_SetIsDocumentURI(nsIWineURI *iface, PRBool aIsDocumentURI)
1629 {
1630     nsURI *This = NSURI_THIS(iface);
1631
1632     TRACE("(%p)->(%x)\n", This, aIsDocumentURI);
1633
1634     This->is_doc_uri = aIsDocumentURI;
1635     return NS_OK;
1636 }
1637
1638 static nsresult NSAPI nsURI_GetWineURL(nsIWineURI *iface, LPCWSTR *aURL)
1639 {
1640     nsURI *This = NSURI_THIS(iface);
1641
1642     TRACE("(%p)->(%p)\n", This, aURL);
1643
1644     *aURL = This->wine_url;
1645     return NS_OK;
1646 }
1647
1648 static nsresult NSAPI nsURI_SetWineURL(nsIWineURI *iface, LPCWSTR aURL)
1649 {
1650     nsURI *This = NSURI_THIS(iface);
1651
1652     static const WCHAR wszFtp[]   = {'f','t','p',':'};
1653     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
1654     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
1655
1656     TRACE("(%p)->(%s)\n", This, debugstr_w(aURL));
1657
1658     mshtml_free(This->wine_url);
1659
1660     if(aURL) {
1661         int len = strlenW(aURL)+1;
1662         This->wine_url = mshtml_alloc(len*sizeof(WCHAR));
1663         memcpy(This->wine_url, aURL, len*sizeof(WCHAR));
1664
1665         /* FIXME: Always use wine url */
1666         This->use_wine_url =
1667                strncmpW(aURL, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
1668             && strncmpW(aURL, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
1669             && strncmpW(aURL, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
1670     }else {
1671         This->wine_url = NULL;
1672         This->use_wine_url = FALSE;
1673     }
1674
1675     return NS_OK;
1676 }
1677
1678 #undef NSURI_THIS
1679
1680 static const nsIWineURIVtbl nsWineURIVtbl = {
1681     nsURI_QueryInterface,
1682     nsURI_AddRef,
1683     nsURI_Release,
1684     nsURI_GetSpec,
1685     nsURI_SetSpec,
1686     nsURI_GetPrePath,
1687     nsURI_GetScheme,
1688     nsURI_SetScheme,
1689     nsURI_GetUserPass,
1690     nsURI_SetUserPass,
1691     nsURI_GetUsername,
1692     nsURI_SetUsername,
1693     nsURI_GetPassword,
1694     nsURI_SetPassword,
1695     nsURI_GetHostPort,
1696     nsURI_SetHostPort,
1697     nsURI_GetHost,
1698     nsURI_SetHost,
1699     nsURI_GetPort,
1700     nsURI_SetPort,
1701     nsURI_GetPath,
1702     nsURI_SetPath,
1703     nsURI_Equals,
1704     nsURI_SchemeIs,
1705     nsURI_Clone,
1706     nsURI_Resolve,
1707     nsURI_GetAsciiSpec,
1708     nsURI_GetAsciiHost,
1709     nsURI_GetOriginCharset,
1710     nsURI_GetNSContainer,
1711     nsURI_SetNSContainer,
1712     nsURI_GetIsDocumentURI,
1713     nsURI_SetIsDocumentURI,
1714     nsURI_GetWineURL,
1715     nsURI_SetWineURL
1716 };
1717
1718 static nsresult create_uri(nsIURI *uri, NSContainer *container, nsIWineURI **_retval)
1719 {
1720     nsURI *ret = mshtml_alloc(sizeof(nsURI));
1721
1722     ret->lpWineURIVtbl = &nsWineURIVtbl;
1723     ret->ref = 1;
1724     ret->uri = uri;
1725     ret->container = container;
1726     ret->wine_url = NULL;
1727     ret->is_doc_uri = FALSE;
1728     ret->use_wine_url = FALSE;
1729
1730     if(container)
1731         nsIWebBrowserChrome_AddRef(NSWBCHROME(container));
1732
1733     TRACE("retval=%p\n", ret);
1734     *_retval = NSWINEURI(ret);
1735     return NS_OK;
1736 }
1737
1738 typedef struct {
1739     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
1740
1741     LONG ref;
1742
1743     nsIProtocolHandler *nshandler;
1744 } nsProtocolHandler;
1745
1746 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
1747
1748 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
1749
1750 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
1751         nsQIResult result)
1752 {
1753     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1754
1755     *result = NULL;
1756
1757     if(IsEqualGUID(&IID_nsISupports, riid)) {
1758         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1759         *result = NSPROTHANDLER(This);
1760     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
1761         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
1762         *result = NSPROTHANDLER(This);
1763     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
1764         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
1765         return NS_NOINTERFACE;
1766     }
1767
1768     if(*result) {
1769         nsISupports_AddRef((nsISupports*)*result);
1770         return NS_OK;
1771     }
1772
1773     WARN("(%s %p)\n", debugstr_guid(riid), result);
1774     return NS_NOINTERFACE;
1775 }
1776
1777 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
1778 {
1779     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1780     LONG ref = InterlockedIncrement(&This->ref);
1781
1782     TRACE("(%p) ref=%d\n", This, ref);
1783
1784     return ref;
1785 }
1786
1787 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
1788 {
1789     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1790     LONG ref = InterlockedDecrement(&This->ref);
1791
1792     TRACE("(%p) ref=%d\n", This, ref);
1793
1794     if(!ref) {
1795         if(This->nshandler)
1796             nsIProtocolHandler_Release(This->nshandler);
1797         mshtml_free(This);
1798     }
1799
1800     return ref;
1801 }
1802
1803 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
1804 {
1805     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1806
1807     TRACE("(%p)->(%p)\n", This, aScheme);
1808
1809     if(This->nshandler)
1810         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
1811     return NS_ERROR_NOT_IMPLEMENTED;
1812 }
1813
1814 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
1815         PRInt32 *aDefaultPort)
1816 {
1817     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1818
1819     TRACE("(%p)->(%p)\n", This, aDefaultPort);
1820
1821     if(This->nshandler)
1822         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
1823     return NS_ERROR_NOT_IMPLEMENTED;
1824 }
1825
1826 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
1827                                                          PRUint32 *aProtocolFlags)
1828 {
1829     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1830
1831     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
1832
1833     if(This->nshandler)
1834         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
1835     return NS_ERROR_NOT_IMPLEMENTED;
1836 }
1837
1838 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
1839         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
1840 {
1841     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1842
1843     TRACE("((%p)->%p %s %p %p)\n", This, aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
1844
1845     if(This->nshandler)
1846         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
1847     return NS_ERROR_NOT_IMPLEMENTED;
1848 }
1849
1850 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
1851         nsIURI *aURI, nsIChannel **_retval)
1852 {
1853     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1854
1855     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
1856
1857     if(This->nshandler)
1858         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
1859     return NS_ERROR_NOT_IMPLEMENTED;
1860 }
1861
1862 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
1863         PRInt32 port, const char *scheme, PRBool *_retval)
1864 {
1865     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
1866
1867     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
1868
1869     if(This->nshandler)
1870         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
1871     return NS_ERROR_NOT_IMPLEMENTED;
1872 }
1873
1874 #undef NSPROTHANDLER_THIS
1875
1876 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
1877     nsProtocolHandler_QueryInterface,
1878     nsProtocolHandler_AddRef,
1879     nsProtocolHandler_Release,
1880     nsProtocolHandler_GetScheme,
1881     nsProtocolHandler_GetDefaultPort,
1882     nsProtocolHandler_GetProtocolFlags,
1883     nsProtocolHandler_NewURI,
1884     nsProtocolHandler_NewChannel,
1885     nsProtocolHandler_AllowPort
1886 };
1887
1888 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
1889 {
1890     nsProtocolHandler *ret = mshtml_alloc(sizeof(nsProtocolHandler));
1891
1892     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
1893     ret->ref = 1;
1894     ret->nshandler = nshandler;
1895
1896     return NSPROTHANDLER(ret);
1897 }
1898
1899 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
1900                                                  nsQIResult result)
1901 {
1902     *result = NULL;
1903
1904     if(IsEqualGUID(&IID_nsISupports, riid)
1905        || IsEqualGUID(&IID_nsIIOService, riid)) {
1906         *result = iface;
1907         nsIIOService_AddRef(iface);
1908         return S_OK;
1909     }
1910
1911     WARN("(%s %p)\n", debugstr_guid(riid), result);
1912     return NS_NOINTERFACE;
1913 }
1914
1915 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
1916 {
1917     return 2;
1918 }
1919
1920 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
1921 {
1922     return 1;
1923 }
1924
1925 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
1926                                                      nsIProtocolHandler **_retval)
1927 {
1928     nsIExternalProtocolHandler *nsexthandler;
1929     nsIProtocolHandler *nshandler;
1930     nsresult nsres;
1931
1932     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1933
1934     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
1935     if(NS_FAILED(nsres)) {
1936         WARN("GetProtocolHandler failed: %08x\n", nsres);
1937         return nsres;
1938     }
1939
1940     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
1941                                               (void**)&nsexthandler);
1942     if(NS_FAILED(nsres)) {
1943         *_retval = nshandler;
1944         return NS_OK;
1945     }
1946
1947     nsIExternalProtocolHandler_Release(nsexthandler);
1948     *_retval = create_protocol_handler(nshandler);
1949     TRACE("return %p\n", *_retval);
1950     return NS_OK;
1951 }
1952
1953 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
1954                                                     PRUint32 *_retval)
1955 {
1956     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
1957     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
1958 }
1959
1960 static BOOL is_gecko_special_uri(const char *spec)
1961 {
1962     static const char chromeW[] = "chrome:";
1963     static const char jarW[] = "jar:";
1964     static const char resourceW[] = "resource:";
1965     static const char javascriptW[] = "javascript:";
1966
1967     return !strncasecmp(spec, chromeW,     sizeof(chromeW)-1)
1968         || !strncasecmp(spec, resourceW,   sizeof(resourceW)-1)
1969         || !strncasecmp(spec, jarW,        sizeof(jarW)-1)
1970         || !strncasecmp(spec, javascriptW, sizeof(javascriptW)-1);
1971 }
1972
1973 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
1974         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
1975 {
1976     const char *spec = NULL;
1977     nsACString spec_str;
1978     NSContainer *nscontainer = NULL;
1979     nsIURI *uri = NULL;
1980     LPCWSTR base_wine_url = NULL;
1981     nsIWineURI *base_wine_uri = NULL, *wine_uri;
1982     BOOL is_wine_uri = FALSE;
1983     nsresult nsres;
1984
1985     nsACString_GetData(aSpec, &spec, NULL);
1986
1987     TRACE("(%p(%s) %s %p %p)\n", aSpec, debugstr_a(spec), debugstr_a(aOriginCharset),
1988           aBaseURI, _retval);
1989
1990     if(is_gecko_special_uri(spec))
1991         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
1992
1993     if(!strncmp(spec, "wine:", 5)) {
1994         spec += 5;
1995         is_wine_uri = TRUE;
1996     }
1997
1998     if(aBaseURI) {
1999         nsACString base_uri_str;
2000         const char *base_uri = NULL;
2001
2002         nsACString_Init(&base_uri_str, NULL);
2003
2004         nsres = nsIURI_GetSpec(aBaseURI, &base_uri_str);
2005         if(NS_SUCCEEDED(nsres)) {
2006             nsACString_GetData(&base_uri_str, &base_uri, NULL);
2007             TRACE("base_uri=%s\n", debugstr_a(base_uri));
2008         }else {
2009             ERR("GetSpec failed: %08x\n", nsres);
2010         }
2011
2012         nsACString_Finish(&base_uri_str);
2013     }
2014
2015     nsACString_Init(&spec_str, spec);
2016     nsres = nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, &uri);
2017     nsACString_Finish(&spec_str);
2018     if(NS_FAILED(nsres))
2019         TRACE("NewURI failed: %08x\n", nsres);
2020
2021     if(aBaseURI) {
2022         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsIWineURI, (void**)&base_wine_uri);
2023         if(NS_SUCCEEDED(nsres)) {
2024             nsIWineURI_GetNSContainer(base_wine_uri, &nscontainer);
2025             nsIWineURI_GetWineURL(base_wine_uri, &base_wine_url);
2026         }else {
2027             TRACE("Could not get base nsIWineURI: %08x\n", nsres);
2028         }
2029     }
2030
2031     nsres = create_uri(uri, nscontainer, &wine_uri);
2032     *_retval = (nsIURI*)wine_uri;
2033
2034     if(nscontainer)
2035         nsIWebBrowserChrome_Release(NSWBCHROME(nscontainer));
2036
2037     if(base_wine_url) {
2038         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2039         DWORD len;
2040         HRESULT hres;
2041
2042         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2043
2044         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2045                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2046                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2047         if(SUCCEEDED(hres))
2048             nsIWineURI_SetWineURL(wine_uri, url);
2049         else
2050              WARN("CoCombineUrl failed: %08x\n", hres);
2051     }else if(is_wine_uri) {
2052         WCHAR url[INTERNET_MAX_URL_LENGTH];
2053
2054         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2055         nsIWineURI_SetWineURL(wine_uri, url);
2056     }
2057
2058     if(base_wine_uri)
2059         nsIWineURI_Release(base_wine_uri);
2060
2061     return nsres;
2062 }
2063
2064 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2065                                              nsIURI **_retval)
2066 {
2067     TRACE("(%p %p)\n", aFile, _retval);
2068     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2069 }
2070
2071 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2072                                                      nsIChannel **_retval)
2073 {
2074     nsIChannel *channel = NULL;
2075     nsChannel *ret;
2076     nsIWineURI *wine_uri;
2077     nsresult nsres;
2078
2079     TRACE("(%p %p)\n", aURI, _retval);
2080
2081     nsres = nsIIOService_NewChannelFromURI(nsio, aURI, &channel);
2082     if(NS_FAILED(nsres) && nsres != NS_ERROR_UNKNOWN_PROTOCOL) {
2083         WARN("NewChannelFromURI failed: %08x\n", nsres);
2084         *_retval = channel;
2085         return nsres;
2086     }
2087
2088     nsres = nsIURI_QueryInterface(aURI, &IID_nsIWineURI, (void**)&wine_uri);
2089     if(NS_FAILED(nsres)) {
2090         WARN("Could not get nsIWineURI: %08x\n", nsres);
2091         *_retval = channel;
2092         return channel ? NS_OK : NS_ERROR_UNEXPECTED;
2093     }
2094
2095     ret = mshtml_alloc(sizeof(nsChannel));
2096
2097     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2098     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2099     ret->ref = 1;
2100     ret->channel = channel;
2101     ret->http_channel = NULL;
2102     ret->uri = wine_uri;
2103     ret->post_data_stream = NULL;
2104     ret->load_group = NULL;
2105     ret->notif_callback = NULL;
2106     ret->load_flags = 0;
2107     ret->content = NULL;
2108     ret->charset = NULL;
2109
2110     nsIURI_AddRef(aURI);
2111     ret->original_uri = aURI;
2112
2113     if(channel)
2114         nsIChannel_QueryInterface(channel, &IID_nsIHttpChannel, (void**)&ret->http_channel);
2115
2116     *_retval = NSCHANNEL(ret);
2117     return NS_OK;
2118 }
2119
2120 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2121         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2122 {
2123     TRACE("(%p %s %p %p)\n", aSpec, debugstr_a(aOriginCharset), aBaseURI, _retval);
2124     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2125 }
2126
2127 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2128 {
2129     TRACE("(%p)\n", aOffline);
2130     return nsIIOService_GetOffline(nsio, aOffline);
2131 }
2132
2133 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2134 {
2135     TRACE("(%x)\n", aOffline);
2136     return nsIIOService_SetOffline(nsio, aOffline);
2137 }
2138
2139 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2140                                              const char *aScheme, PRBool *_retval)
2141 {
2142     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2143     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2144 }
2145
2146 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2147                                                  nsACString * _retval)
2148 {
2149     TRACE("(%p %p)\n", urlString, _retval);
2150     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2151 }
2152
2153 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2154     nsIOService_QueryInterface,
2155     nsIOService_AddRef,
2156     nsIOService_Release,
2157     nsIOService_GetProtocolHandler,
2158     nsIOService_GetProtocolFlags,
2159     nsIOService_NewURI,
2160     nsIOService_NewFileURI,
2161     nsIOService_NewChannelFromURI,
2162     nsIOService_NewChannel,
2163     nsIOService_GetOffline,
2164     nsIOService_SetOffline,
2165     nsIOService_AllowPort,
2166     nsIOService_ExtractScheme
2167 };
2168
2169 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2170
2171 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2172                                                         nsQIResult result)
2173 {
2174     *result = NULL;
2175
2176     if(IsEqualGUID(&IID_nsISupports, riid)) {
2177         TRACE("(IID_nsISupoprts %p)\n", result);
2178         *result = iface;
2179     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2180         TRACE("(IID_nsIFactory %p)\n", result);
2181         *result = iface;
2182     }
2183
2184     if(*result) {
2185         nsIFactory_AddRef(iface);
2186         return NS_OK;
2187     }
2188
2189     WARN("(%s %p)\n", debugstr_guid(riid), result);
2190     return NS_NOINTERFACE;
2191 }
2192
2193 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2194 {
2195     return 2;
2196 }
2197
2198 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2199 {
2200     return 1;
2201 }
2202
2203 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2204         nsISupports *aOuter, const nsIID *iid, void **result)
2205 {
2206     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2207 }
2208
2209 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2210 {
2211     WARN("(%x)\n", lock);
2212     return NS_OK;
2213 }
2214
2215 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2216     nsIOServiceFactory_QueryInterface,
2217     nsIOServiceFactory_AddRef,
2218     nsIOServiceFactory_Release,
2219     nsIOServiceFactory_CreateInstance,
2220     nsIOServiceFactory_LockFactory
2221 };
2222
2223 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2224
2225 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2226 {
2227     nsIFactory *old_factory = NULL;
2228     nsresult nsres;
2229
2230     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2231                                                &IID_nsIFactory, (void**)&old_factory);
2232     if(NS_FAILED(nsres)) {
2233         ERR("Could not get factory: %08x\n", nsres);
2234         return;
2235     }
2236
2237     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2238     if(NS_FAILED(nsres)) {
2239         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2240         nsIFactory_Release(old_factory);
2241         return;
2242     }
2243
2244     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2245     nsIFactory_Release(old_factory);
2246     if(NS_FAILED(nsres))
2247         ERR("UnregisterFactory failed: %08x\n", nsres);
2248
2249     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2250             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2251     if(NS_FAILED(nsres))
2252         ERR("RegisterFactory failed: %08x\n", nsres);
2253 }