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