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