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