d3dcompiler_34: Stub dll.
[wine] / dlls / mshtml / nsio.c
1 /*
2  * Copyright 2006-2010 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 NS_IOSERVICE_CLASSNAME "nsIOService"
42 #define NS_IOSERVICE_CONTRACTID "@mozilla.org/network/io-service;1"
43
44 static const IID NS_IOSERVICE_CID =
45     {0x9ac9e770, 0x18bc, 0x11d3, {0x93, 0x37, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40}};
46 static const IID IID_nsWineURI =
47     {0x5088272e, 0x900b, 0x11da, {0xc6,0x87, 0x00,0x0f,0xea,0x57,0xf2,0x1a}};
48
49 static nsIIOService *nsio = NULL;
50 static nsINetUtil *net_util;
51
52 static const WCHAR about_blankW[] = {'a','b','o','u','t',':','b','l','a','n','k',0};
53
54 static const char *request_method_strings[] = {"GET", "PUT", "POST"};
55
56 struct  nsWineURI {
57     const nsIURLVtbl *lpIURLVtbl;
58
59     LONG ref;
60
61     nsIURI *uri;
62     nsIURL *nsurl;
63     NSContainer *container;
64     windowref_t *window_ref;
65     nsChannelBSC *channel_bsc;
66     LPWSTR wine_url;
67     BOOL is_doc_uri;
68     BOOL use_wine_url;
69 };
70
71 #define NSURI(x)  ((nsIURI*)  &(x)->lpIURLVtbl)
72 #define NSURL(x)  ((nsIURL*)  &(x)->lpIURLVtbl)
73
74 static nsresult create_uri(nsIURI*,HTMLWindow*,NSContainer*,nsWineURI**);
75
76 static const char *debugstr_nsacstr(const nsACString *nsstr)
77 {
78     const char *data;
79
80     nsACString_GetData(nsstr, &data);
81     return debugstr_a(data);
82 }
83
84 HRESULT nsuri_to_url(LPCWSTR nsuri, BOOL ret_empty, BSTR *ret)
85 {
86     const WCHAR *ptr = nsuri;
87
88     static const WCHAR wine_prefixW[] = {'w','i','n','e',':'};
89
90     if(!strncmpW(nsuri, wine_prefixW, sizeof(wine_prefixW)/sizeof(WCHAR)))
91         ptr += sizeof(wine_prefixW)/sizeof(WCHAR);
92
93     if(*ptr || ret_empty) {
94         *ret = SysAllocString(ptr);
95         if(!*ret)
96             return E_OUTOFMEMORY;
97     }else {
98         *ret = NULL;
99     }
100
101     TRACE("%s -> %s\n", debugstr_w(nsuri), debugstr_w(*ret));
102     return S_OK;
103 }
104
105 static BOOL exec_shldocvw_67(HTMLDocumentObj *doc, LPCWSTR url)
106 {
107     IOleCommandTarget *cmdtrg = NULL;
108     HRESULT hres;
109
110     hres = IOleClientSite_QueryInterface(doc->client, &IID_IOleCommandTarget, (void**)&cmdtrg);
111     if(SUCCEEDED(hres)) {
112         VARIANT varUrl, varRes;
113
114         V_VT(&varUrl) = VT_BSTR;
115         V_BSTR(&varUrl) = SysAllocString(url);
116         V_VT(&varRes) = VT_BOOL;
117
118         hres = IOleCommandTarget_Exec(cmdtrg, &CGID_ShellDocView, 67, 0, &varUrl, &varRes);
119
120         IOleCommandTarget_Release(cmdtrg);
121         SysFreeString(V_BSTR(&varUrl));
122
123         if(SUCCEEDED(hres) && !V_BOOL(&varRes)) {
124             TRACE("got VARIANT_FALSE, do not load\n");
125             return FALSE;
126         }
127     }
128
129     return TRUE;
130 }
131
132 static BOOL before_async_open(nsChannel *channel, NSContainer *container)
133 {
134     HTMLDocumentObj *doc = container->doc;
135     DWORD hlnf = 0;
136     BOOL cancel;
137     HRESULT hres;
138
139     if(!doc) {
140         NSContainer *container_iter = container;
141
142         hlnf = HLNF_OPENINNEWWINDOW;
143         while(!container_iter->doc)
144             container_iter = container_iter->parent;
145         doc = container_iter->doc;
146     }
147
148     if(!doc->client)
149         return TRUE;
150
151     if(!hlnf && !exec_shldocvw_67(doc, channel->uri->wine_url))
152         return FALSE;
153
154     hres = hlink_frame_navigate(&doc->basedoc, channel->uri->wine_url, channel->post_data_stream, hlnf, &cancel);
155     return FAILED(hres) || cancel;
156 }
157
158 HRESULT load_nsuri(HTMLWindow *window, nsWineURI *uri, nsChannelBSC *channelbsc, DWORD flags)
159 {
160     nsIWebNavigation *web_navigation;
161     nsIDocShell *doc_shell;
162     nsresult nsres;
163
164     nsres = get_nsinterface((nsISupports*)window->nswindow, &IID_nsIWebNavigation, (void**)&web_navigation);
165     if(NS_FAILED(nsres)) {
166         ERR("Could not get nsIWebNavigation interface: %08x\n", nsres);
167         return E_FAIL;
168     }
169
170     nsres = nsIWebNavigation_QueryInterface(web_navigation, &IID_nsIDocShell, (void**)&doc_shell);
171     nsIWebNavigation_Release(web_navigation);
172     if(NS_FAILED(nsres)) {
173         ERR("Could not get nsIDocShell: %08x\n", nsres);
174         return E_FAIL;
175     }
176
177
178     uri->channel_bsc = channelbsc;
179     nsres = nsIDocShell_LoadURI(doc_shell, NSURI(uri), NULL, flags, FALSE);
180     uri->channel_bsc = NULL;
181     nsIDocShell_Release(doc_shell);
182     if(NS_FAILED(nsres)) {
183         WARN("LoadURI failed: %08x\n", nsres);
184         return E_FAIL;
185     }
186
187     return S_OK;
188 }
189
190 static BOOL translate_url(HTMLDocumentObj *doc, nsWineURI *uri)
191 {
192     OLECHAR *new_url = NULL, *url;
193     BOOL ret = FALSE;
194     HRESULT hres;
195
196     if(!doc->hostui)
197         return FALSE;
198
199     url = heap_strdupW(uri->wine_url);
200     hres = IDocHostUIHandler_TranslateUrl(doc->hostui, 0, url, &new_url);
201     if(hres == S_OK && new_url) {
202         if(strcmpW(url, new_url)) {
203             FIXME("TranslateUrl returned new URL %s -> %s\n", debugstr_w(url), debugstr_w(new_url));
204             ret = TRUE;
205         }
206         CoTaskMemFree(new_url);
207     }
208
209     heap_free(url);
210     return ret;
211 }
212
213 nsresult on_start_uri_open(NSContainer *nscontainer, nsIURI *uri, PRBool *_retval)
214 {
215     nsWineURI *wine_uri;
216     nsresult nsres;
217
218     *_retval = FALSE;
219
220     nsres = nsIURI_QueryInterface(uri, &IID_nsWineURI, (void**)&wine_uri);
221     if(NS_FAILED(nsres)) {
222         WARN("Could not get nsWineURI: %08x\n", nsres);
223         return NS_ERROR_NOT_IMPLEMENTED;
224     }
225
226     if(!wine_uri->is_doc_uri) {
227         wine_uri->is_doc_uri = TRUE;
228
229         if(!wine_uri->container) {
230             nsIWebBrowserChrome_AddRef(NSWBCHROME(nscontainer));
231             wine_uri->container = nscontainer;
232         }
233
234         if(nscontainer->doc)
235             *_retval = translate_url(nscontainer->doc, wine_uri);
236     }
237
238     nsIURI_Release(NSURI(wine_uri));
239     return NS_OK;
240 }
241
242 HRESULT set_wine_url(nsWineURI *This, LPCWSTR url)
243 {
244     static const WCHAR wszFtp[]   = {'f','t','p',':'};
245     static const WCHAR wszHttp[]  = {'h','t','t','p',':'};
246     static const WCHAR wszHttps[] = {'h','t','t','p','s',':'};
247
248     TRACE("(%p)->(%s)\n", This, debugstr_w(url));
249
250     if(url) {
251         WCHAR *new_url;
252
253         new_url = heap_strdupW(url);
254         if(!new_url)
255             return E_OUTOFMEMORY;
256         heap_free(This->wine_url);
257         This->wine_url = new_url;
258
259         if(This->uri) {
260             /* FIXME: Always use wine url */
261             This->use_wine_url =
262                    strncmpW(url, wszFtp,   sizeof(wszFtp)/sizeof(WCHAR))
263                 && strncmpW(url, wszHttp,  sizeof(wszHttp)/sizeof(WCHAR))
264                 && strncmpW(url, wszHttps, sizeof(wszHttps)/sizeof(WCHAR));
265         }else {
266             This->use_wine_url = TRUE;
267         }
268     }else {
269         heap_free(This->wine_url);
270         This->wine_url = NULL;
271         This->use_wine_url = FALSE;
272     }
273
274     return S_OK;
275 }
276
277 static void set_uri_nscontainer(nsWineURI *This, NSContainer *nscontainer)
278 {
279     if(This->container) {
280         if(This->container == nscontainer)
281             return;
282         TRACE("Changing %p -> %p\n", This->container, nscontainer);
283         nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
284     }
285
286     if(nscontainer)
287         nsIWebBrowserChrome_AddRef(NSWBCHROME(nscontainer));
288     This->container = nscontainer;
289 }
290
291 static void set_uri_window(nsWineURI *This, HTMLWindow *window)
292 {
293     if(This->window_ref) {
294         if(This->window_ref->window == window)
295             return;
296         TRACE("Changing %p -> %p\n", This->window_ref->window, window);
297         windowref_release(This->window_ref);
298     }
299
300     if(window) {
301         windowref_addref(window->window_ref);
302         This->window_ref = window->window_ref;
303
304         if(window->doc_obj)
305             set_uri_nscontainer(This, window->doc_obj->nscontainer);
306     }else {
307         This->window_ref = NULL;
308     }
309 }
310
311 static inline BOOL is_http_channel(nsChannel *This)
312 {
313     return This->url_scheme == URL_SCHEME_HTTP || This->url_scheme == URL_SCHEME_HTTPS;
314 }
315
316 static http_header_t *find_http_header(struct list *headers, const WCHAR *name, int len)
317 {
318     http_header_t *iter;
319
320     LIST_FOR_EACH_ENTRY(iter, headers, http_header_t, entry) {
321         if(!strcmpiW(iter->header, name))
322             return iter;
323     }
324
325     return NULL;
326 }
327
328 static nsresult get_channel_http_header(struct list *headers, const nsACString *header_name_str,
329         nsACString *_retval)
330 {
331     const char *header_namea;
332     http_header_t *header;
333     WCHAR *header_name;
334     char *data;
335
336     nsACString_GetData(header_name_str, &header_namea);
337     header_name = heap_strdupAtoW(header_namea);
338     if(!header_name)
339         return NS_ERROR_UNEXPECTED;
340
341     header = find_http_header(headers, header_name, strlenW(header_name));
342     heap_free(header_name);
343     if(!header)
344         return NS_ERROR_NOT_AVAILABLE;
345
346     data = heap_strdupWtoA(header->data);
347     if(!data)
348         return NS_ERROR_UNEXPECTED;
349
350     nsACString_SetData(_retval, data);
351     heap_free(data);
352     return NS_OK;
353 }
354
355 HRESULT set_http_header(struct list *headers, const WCHAR *name, int name_len,
356         const WCHAR *value, int value_len)
357 {
358     http_header_t *header;
359
360     TRACE("%s: %s\n", debugstr_wn(name, name_len), debugstr_wn(value, value_len));
361
362     header = find_http_header(headers, name, name_len);
363     if(header) {
364         WCHAR *new_data;
365
366         new_data = heap_strndupW(value, value_len);
367         if(!new_data)
368             return E_OUTOFMEMORY;
369
370         heap_free(header->data);
371         header->data = new_data;
372     }else {
373         header = heap_alloc(sizeof(http_header_t));
374         if(!header)
375             return E_OUTOFMEMORY;
376
377         header->header = heap_strndupW(name, name_len);
378         header->data = heap_strndupW(value, value_len);
379         if(!header->header || !header->data) {
380             heap_free(header->header);
381             heap_free(header->data);
382             heap_free(header);
383             return E_OUTOFMEMORY;
384         }
385
386         list_add_tail(headers, &header->entry);
387     }
388
389     return S_OK;
390 }
391
392 static nsresult set_channel_http_header(struct list *headers, const nsACString *name_str,
393         const nsACString *value_str)
394 {
395     const char *namea, *valuea;
396     WCHAR *name, *value;
397     HRESULT hres;
398
399     nsACString_GetData(name_str, &namea);
400     name = heap_strdupAtoW(namea);
401     if(!name)
402         return NS_ERROR_UNEXPECTED;
403
404     nsACString_GetData(value_str, &valuea);
405     value = heap_strdupAtoW(valuea);
406     if(!value) {
407         heap_free(name);
408         return NS_ERROR_UNEXPECTED;
409     }
410
411     hres = set_http_header(headers, name, strlenW(name), value, strlenW(value));
412
413     heap_free(name);
414     heap_free(value);
415     return SUCCEEDED(hres) ? NS_OK : NS_ERROR_UNEXPECTED;
416 }
417
418 static void free_http_headers(struct list *list)
419 {
420     http_header_t *iter, *iter_next;
421
422     LIST_FOR_EACH_ENTRY_SAFE(iter, iter_next, list, http_header_t, entry) {
423         list_remove(&iter->entry);
424         heap_free(iter->header);
425         heap_free(iter->data);
426         heap_free(iter);
427     }
428 }
429
430 #define NSCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, HttpChannel, iface)
431
432 static nsresult NSAPI nsChannel_QueryInterface(nsIHttpChannel *iface, nsIIDRef riid, void **result)
433 {
434     nsChannel *This = NSCHANNEL_THIS(iface);
435
436     if(IsEqualGUID(&IID_nsISupports, riid)) {
437         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
438         *result = NSCHANNEL(This);
439     }else if(IsEqualGUID(&IID_nsIRequest, riid)) {
440         TRACE("(%p)->(IID_nsIRequest %p)\n", This, result);
441         *result = NSCHANNEL(This);
442     }else if(IsEqualGUID(&IID_nsIChannel, riid)) {
443         TRACE("(%p)->(IID_nsIChannel %p)\n", This, result);
444         *result = NSCHANNEL(This);
445     }else if(IsEqualGUID(&IID_nsIHttpChannel, riid)) {
446         TRACE("(%p)->(IID_nsIHttpChannel %p)\n", This, result);
447         *result = is_http_channel(This) ? NSHTTPCHANNEL(This) : NULL;
448     }else if(IsEqualGUID(&IID_nsIUploadChannel, riid)) {
449         TRACE("(%p)->(IID_nsIUploadChannel %p)\n", This, result);
450         *result = NSUPCHANNEL(This);
451     }else if(IsEqualGUID(&IID_nsIHttpChannelInternal, riid)) {
452         TRACE("(%p)->(IID_nsIHttpChannelInternal %p)\n", This, result);
453         *result = is_http_channel(This) ? NSHTTPINTERNAL(This) : NULL;
454     }else {
455         TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
456         *result = NULL;
457     }
458
459     if(*result) {
460         nsIChannel_AddRef(NSCHANNEL(This));
461         return NS_OK;
462     }
463
464     return NS_NOINTERFACE;
465 }
466
467 static nsrefcnt NSAPI nsChannel_AddRef(nsIHttpChannel *iface)
468 {
469     nsChannel *This = NSCHANNEL_THIS(iface);
470     nsrefcnt ref = InterlockedIncrement(&This->ref);
471
472     TRACE("(%p) ref=%d\n", This, ref);
473
474     return ref;
475 }
476
477 static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface)
478 {
479     nsChannel *This = NSCHANNEL_THIS(iface);
480     LONG ref = InterlockedDecrement(&This->ref);
481
482     if(!ref) {
483         nsIURI_Release(NSURI(This->uri));
484         if(This->owner)
485             nsISupports_Release(This->owner);
486         if(This->post_data_stream)
487             nsIInputStream_Release(This->post_data_stream);
488         if(This->load_group)
489             nsILoadGroup_Release(This->load_group);
490         if(This->notif_callback)
491             nsIInterfaceRequestor_Release(This->notif_callback);
492         if(This->original_uri)
493             nsIURI_Release(This->original_uri);
494
495         free_http_headers(&This->response_headers);
496         free_http_headers(&This->request_headers);
497
498         heap_free(This->content_type);
499         heap_free(This->charset);
500         heap_free(This);
501     }
502
503     return ref;
504 }
505
506 static nsresult NSAPI nsChannel_GetName(nsIHttpChannel *iface, nsACString *aName)
507 {
508     nsChannel *This = NSCHANNEL_THIS(iface);
509
510     FIXME("(%p)->(%p)\n", This, aName);
511
512     return NS_ERROR_NOT_IMPLEMENTED;
513 }
514
515 static nsresult NSAPI nsChannel_IsPending(nsIHttpChannel *iface, PRBool *_retval)
516 {
517     nsChannel *This = NSCHANNEL_THIS(iface);
518
519     FIXME("(%p)->(%p)\n", This, _retval);
520
521     return NS_ERROR_NOT_IMPLEMENTED;
522 }
523
524 static nsresult NSAPI nsChannel_GetStatus(nsIHttpChannel *iface, nsresult *aStatus)
525 {
526     nsChannel *This = NSCHANNEL_THIS(iface);
527
528     WARN("(%p)->(%p) returning NS_OK\n", This, aStatus);
529
530     return *aStatus = NS_OK;
531 }
532
533 static nsresult NSAPI nsChannel_Cancel(nsIHttpChannel *iface, nsresult aStatus)
534 {
535     nsChannel *This = NSCHANNEL_THIS(iface);
536
537     FIXME("(%p)->(%08x)\n", This, aStatus);
538
539     return NS_ERROR_NOT_IMPLEMENTED;
540 }
541
542 static nsresult NSAPI nsChannel_Suspend(nsIHttpChannel *iface)
543 {
544     nsChannel *This = NSCHANNEL_THIS(iface);
545
546     FIXME("(%p)\n", This);
547
548     return NS_ERROR_NOT_IMPLEMENTED;
549 }
550
551 static nsresult NSAPI nsChannel_Resume(nsIHttpChannel *iface)
552 {
553     nsChannel *This = NSCHANNEL_THIS(iface);
554
555     FIXME("(%p)\n", This);
556
557     return NS_ERROR_NOT_IMPLEMENTED;
558 }
559
560 static nsresult NSAPI nsChannel_GetLoadGroup(nsIHttpChannel *iface, nsILoadGroup **aLoadGroup)
561 {
562     nsChannel *This = NSCHANNEL_THIS(iface);
563
564     TRACE("(%p)->(%p)\n", This, aLoadGroup);
565
566     if(This->load_group)
567         nsILoadGroup_AddRef(This->load_group);
568
569     *aLoadGroup = This->load_group;
570     return NS_OK;
571 }
572
573 static nsresult NSAPI nsChannel_SetLoadGroup(nsIHttpChannel *iface, nsILoadGroup *aLoadGroup)
574 {
575     nsChannel *This = NSCHANNEL_THIS(iface);
576
577     TRACE("(%p)->(%p)\n", This, aLoadGroup);
578
579     if(This->load_group)
580         nsILoadGroup_Release(This->load_group);
581     if(aLoadGroup)
582         nsILoadGroup_AddRef(aLoadGroup);
583     This->load_group = aLoadGroup;
584
585     return NS_OK;
586 }
587
588 static nsresult NSAPI nsChannel_GetLoadFlags(nsIHttpChannel *iface, nsLoadFlags *aLoadFlags)
589 {
590     nsChannel *This = NSCHANNEL_THIS(iface);
591
592     TRACE("(%p)->(%p)\n", This, aLoadFlags);
593
594     *aLoadFlags = This->load_flags;
595     return NS_OK;
596 }
597
598 static nsresult NSAPI nsChannel_SetLoadFlags(nsIHttpChannel *iface, nsLoadFlags aLoadFlags)
599 {
600     nsChannel *This = NSCHANNEL_THIS(iface);
601
602     TRACE("(%p)->(%08x)\n", This, aLoadFlags);
603
604     This->load_flags = aLoadFlags;
605     return NS_OK;
606 }
607
608 static nsresult NSAPI nsChannel_GetOriginalURI(nsIHttpChannel *iface, nsIURI **aOriginalURI)
609 {
610     nsChannel *This = NSCHANNEL_THIS(iface);
611
612     TRACE("(%p)->(%p)\n", This, aOriginalURI);
613
614     if(This->original_uri)
615         nsIURI_AddRef(This->original_uri);
616
617     *aOriginalURI = This->original_uri;
618     return NS_OK;
619 }
620
621 static nsresult NSAPI nsChannel_SetOriginalURI(nsIHttpChannel *iface, nsIURI *aOriginalURI)
622 {
623     nsChannel *This = NSCHANNEL_THIS(iface);
624
625     TRACE("(%p)->(%p)\n", This, aOriginalURI);
626
627     if(This->original_uri)
628         nsIURI_Release(This->original_uri);
629
630     nsIURI_AddRef(aOriginalURI);
631     This->original_uri = aOriginalURI;
632     return NS_OK;
633 }
634
635 static nsresult NSAPI nsChannel_GetURI(nsIHttpChannel *iface, nsIURI **aURI)
636 {
637     nsChannel *This = NSCHANNEL_THIS(iface);
638
639     TRACE("(%p)->(%p)\n", This, aURI);
640
641     nsIURI_AddRef(NSURI(This->uri));
642     *aURI = (nsIURI*)This->uri;
643
644     return NS_OK;
645 }
646
647 static nsresult NSAPI nsChannel_GetOwner(nsIHttpChannel *iface, nsISupports **aOwner)
648 {
649     nsChannel *This = NSCHANNEL_THIS(iface);
650
651     TRACE("(%p)->(%p)\n", This, aOwner);
652
653     if(This->owner)
654         nsISupports_AddRef(This->owner);
655     *aOwner = This->owner;
656
657     return NS_OK;
658 }
659
660 static nsresult NSAPI nsChannel_SetOwner(nsIHttpChannel *iface, nsISupports *aOwner)
661 {
662     nsChannel *This = NSCHANNEL_THIS(iface);
663
664     TRACE("(%p)->(%p)\n", This, aOwner);
665
666     if(aOwner)
667         nsISupports_AddRef(aOwner);
668     if(This->owner)
669         nsISupports_Release(This->owner);
670     This->owner = aOwner;
671
672     return NS_OK;
673 }
674
675 static nsresult NSAPI nsChannel_GetNotificationCallbacks(nsIHttpChannel *iface,
676         nsIInterfaceRequestor **aNotificationCallbacks)
677 {
678     nsChannel *This = NSCHANNEL_THIS(iface);
679
680     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
681
682     if(This->notif_callback)
683         nsIInterfaceRequestor_AddRef(This->notif_callback);
684     *aNotificationCallbacks = This->notif_callback;
685
686     return NS_OK;
687 }
688
689 static nsresult NSAPI nsChannel_SetNotificationCallbacks(nsIHttpChannel *iface,
690         nsIInterfaceRequestor *aNotificationCallbacks)
691 {
692     nsChannel *This = NSCHANNEL_THIS(iface);
693
694     TRACE("(%p)->(%p)\n", This, aNotificationCallbacks);
695
696     if(This->notif_callback)
697         nsIInterfaceRequestor_Release(This->notif_callback);
698     if(aNotificationCallbacks)
699         nsIInterfaceRequestor_AddRef(aNotificationCallbacks);
700
701     This->notif_callback = aNotificationCallbacks;
702
703     return NS_OK;
704 }
705
706 static nsresult NSAPI nsChannel_GetSecurityInfo(nsIHttpChannel *iface, nsISupports **aSecurityInfo)
707 {
708     nsChannel *This = NSCHANNEL_THIS(iface);
709
710     TRACE("(%p)->(%p)\n", This, aSecurityInfo);
711
712     return NS_ERROR_NOT_IMPLEMENTED;
713 }
714
715 static nsresult NSAPI nsChannel_GetContentType(nsIHttpChannel *iface, nsACString *aContentType)
716 {
717     nsChannel *This = NSCHANNEL_THIS(iface);
718
719     TRACE("(%p)->(%p)\n", This, aContentType);
720
721     if(This->content_type) {
722         nsACString_SetData(aContentType, This->content_type);
723         return S_OK;
724     }
725
726     WARN("unknown type\n");
727     return NS_ERROR_FAILURE;
728 }
729
730 static nsresult NSAPI nsChannel_SetContentType(nsIHttpChannel *iface,
731                                                const nsACString *aContentType)
732 {
733     nsChannel *This = NSCHANNEL_THIS(iface);
734     const char *content_type;
735
736     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aContentType));
737
738     nsACString_GetData(aContentType, &content_type);
739     heap_free(This->content_type);
740     This->content_type = heap_strdupA(content_type);
741
742     return NS_OK;
743 }
744
745 static nsresult NSAPI nsChannel_GetContentCharset(nsIHttpChannel *iface,
746                                                   nsACString *aContentCharset)
747 {
748     nsChannel *This = NSCHANNEL_THIS(iface);
749
750     TRACE("(%p)->(%p)\n", This, aContentCharset);
751
752     if(This->charset) {
753         nsACString_SetData(aContentCharset, This->charset);
754         return NS_OK;
755     }
756
757     nsACString_SetData(aContentCharset, "");
758     return NS_OK;
759 }
760
761 static nsresult NSAPI nsChannel_SetContentCharset(nsIHttpChannel *iface,
762                                                   const nsACString *aContentCharset)
763 {
764     nsChannel *This = NSCHANNEL_THIS(iface);
765
766     FIXME("(%p)->(%s)\n", This, debugstr_nsacstr(aContentCharset));
767
768     return NS_ERROR_NOT_IMPLEMENTED;
769 }
770
771 static nsresult NSAPI nsChannel_GetContentLength(nsIHttpChannel *iface, PRInt32 *aContentLength)
772 {
773     nsChannel *This = NSCHANNEL_THIS(iface);
774
775     FIXME("(%p)->(%p)\n", This, aContentLength);
776
777     return NS_ERROR_NOT_IMPLEMENTED;
778 }
779
780 static nsresult NSAPI nsChannel_SetContentLength(nsIHttpChannel *iface, PRInt32 aContentLength)
781 {
782     nsChannel *This = NSCHANNEL_THIS(iface);
783
784     FIXME("(%p)->(%d)\n", This, aContentLength);
785
786     return NS_ERROR_NOT_IMPLEMENTED;
787 }
788
789 static nsresult NSAPI nsChannel_Open(nsIHttpChannel *iface, nsIInputStream **_retval)
790 {
791     nsChannel *This = NSCHANNEL_THIS(iface);
792
793     FIXME("(%p)->(%p)\n", This, _retval);
794
795     return NS_ERROR_NOT_IMPLEMENTED;
796 }
797
798 static HRESULT create_mon_for_nschannel(nsChannel *channel, IMoniker **mon)
799 {
800     nsWineURI *wine_uri;
801     nsresult nsres;
802     HRESULT hres;
803
804     if(!channel->original_uri) {
805         ERR("original_uri == NULL\n");
806         return E_FAIL;
807     }
808
809     nsres = nsIURI_QueryInterface(channel->original_uri, &IID_nsWineURI, (void**)&wine_uri);
810     if(NS_FAILED(nsres)) {
811         ERR("Could not get nsWineURI: %08x\n", nsres);
812         return E_FAIL;
813     }
814
815     if(wine_uri->wine_url) {
816         hres = CreateURLMoniker(NULL, wine_uri->wine_url, mon);
817         if(FAILED(hres))
818             WARN("CreateURLMoniker failed: %08x\n", hres);
819     }else {
820         TRACE("wine_url == NULL\n");
821         hres = E_FAIL;
822     }
823
824     nsIURI_Release(NSURI(wine_uri));
825
826     return hres;
827 }
828
829 static HTMLWindow *get_window_from_load_group(nsChannel *This)
830 {
831     HTMLWindow *window;
832     nsIChannel *channel;
833     nsIRequest *req;
834     nsWineURI *wine_uri;
835     nsIURI *uri;
836     nsresult nsres;
837
838     nsres = nsILoadGroup_GetDefaultLoadRequest(This->load_group, &req);
839     if(NS_FAILED(nsres)) {
840         ERR("GetDefaultLoadRequest failed: %08x\n", nsres);
841         return NULL;
842     }
843
844     if(!req)
845         return NULL;
846
847     nsres = nsIRequest_QueryInterface(req, &IID_nsIChannel, (void**)&channel);
848     nsIRequest_Release(req);
849     if(NS_FAILED(nsres)) {
850         WARN("Could not get nsIChannel interface: %08x\n", nsres);
851         return NULL;
852     }
853
854     nsres = nsIChannel_GetURI(channel, &uri);
855     nsIChannel_Release(channel);
856     if(NS_FAILED(nsres)) {
857         ERR("GetURI failed: %08x\n", nsres);
858         return NULL;
859     }
860
861     nsres = nsIURI_QueryInterface(uri, &IID_nsWineURI, (void**)&wine_uri);
862     nsIURI_Release(uri);
863     if(NS_FAILED(nsres)) {
864         TRACE("Could not get nsWineURI: %08x\n", nsres);
865         return NULL;
866     }
867
868     window = wine_uri->window_ref ? wine_uri->window_ref->window : NULL;
869     if(window)
870         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
871     nsIURI_Release(NSURI(wine_uri));
872
873     return window;
874 }
875
876 static HTMLWindow *get_channel_window(nsChannel *This)
877 {
878     nsIRequestObserver *req_observer;
879     nsIWebProgress *web_progress;
880     nsIDOMWindow *nswindow;
881     HTMLWindow *window;
882     nsresult nsres;
883
884     if(!This->load_group) {
885         ERR("NULL load_group\n");
886         return NULL;
887     }
888
889     nsres = nsILoadGroup_GetGroupObserver(This->load_group, &req_observer);
890     if(NS_FAILED(nsres) || !req_observer) {
891         ERR("GetGroupObserver failed: %08x\n", nsres);
892         return NULL;
893     }
894
895     nsres = nsIRequestObserver_QueryInterface(req_observer, &IID_nsIWebProgress, (void**)&web_progress);
896     nsIRequestObserver_Release(req_observer);
897     if(NS_FAILED(nsres)) {
898         ERR("Could not get nsIWebProgress iface: %08x\n", nsres);
899         return NULL;
900     }
901
902     nsres = nsIWebProgress_GetDOMWindow(web_progress, &nswindow);
903     nsIWebProgress_Release(web_progress);
904     if(NS_FAILED(nsres) || !nswindow) {
905         ERR("GetDOMWindow failed: %08x\n", nsres);
906         return NULL;
907     }
908
909     window = nswindow_to_window(nswindow);
910     nsIDOMWindow_Release(nswindow);
911
912     if(window)
913         IHTMLWindow2_AddRef(HTMLWINDOW2(window));
914     else
915         FIXME("NULL window for %p\n", nswindow);
916     return window;
917 }
918
919 typedef struct {
920     task_t header;
921     HTMLDocumentNode *doc;
922     nsChannelBSC *bscallback;
923 } start_binding_task_t;
924
925 static void start_binding_proc(task_t *_task)
926 {
927     start_binding_task_t *task = (start_binding_task_t*)_task;
928
929     start_binding(NULL, task->doc, (BSCallback*)task->bscallback, NULL);
930
931     IUnknown_Release((IUnknown*)task->bscallback);
932 }
933
934 static nsresult async_open(nsChannel *This, HTMLWindow *window, BOOL is_doc_channel, nsIStreamListener *listener,
935         nsISupports *context)
936 {
937     nsChannelBSC *bscallback;
938     IMoniker *mon = NULL;
939     HRESULT hres;
940
941     hres = create_mon_for_nschannel(This, &mon);
942     if(FAILED(hres))
943         return NS_ERROR_UNEXPECTED;
944
945     if(is_doc_channel)
946         set_current_mon(window, mon);
947
948     hres = create_channelbsc(mon, NULL, NULL, 0, &bscallback);
949     IMoniker_Release(mon);
950     if(FAILED(hres))
951         return NS_ERROR_UNEXPECTED;
952
953     channelbsc_set_channel(bscallback, This, listener, context);
954
955     if(is_doc_channel) {
956         set_window_bscallback(window, bscallback);
957         async_start_doc_binding(window, bscallback);
958         IUnknown_Release((IUnknown*)bscallback);
959     }else {
960         start_binding_task_t *task = heap_alloc(sizeof(start_binding_task_t));
961
962         task->doc = window->doc;
963         task->bscallback = bscallback;
964         push_task(&task->header, start_binding_proc, window->doc->basedoc.task_magic);
965     }
966
967     return NS_OK;
968 }
969
970 static nsresult NSAPI nsChannel_AsyncOpen(nsIHttpChannel *iface, nsIStreamListener *aListener,
971                                           nsISupports *aContext)
972 {
973     nsChannel *This = NSCHANNEL_THIS(iface);
974     HTMLWindow *window = NULL;
975     BOOL open = TRUE;
976     nsresult nsres = NS_OK;
977
978     TRACE("(%p)->(%p %p) opening %s\n", This, aListener, aContext, debugstr_w(This->uri->wine_url));
979
980     if(This->uri->is_doc_uri) {
981         window = get_channel_window(This);
982         if(window) {
983             set_uri_window(This->uri, window);
984         }else if(This->uri->container) {
985             BOOL b;
986
987             /* nscontainer->doc should be NULL which means navigation to a new window */
988             if(This->uri->container->doc)
989                 FIXME("nscontainer->doc = %p\n", This->uri->container->doc);
990
991             b = before_async_open(This, This->uri->container);
992             if(b)
993                 FIXME("Navigation not cancelled\n");
994             return NS_ERROR_UNEXPECTED;
995         }
996     }
997
998     if(!window) {
999         if(This->uri->window_ref && This->uri->window_ref->window) {
1000             window = This->uri->window_ref->window;
1001             IHTMLWindow2_AddRef(HTMLWINDOW2(window));
1002         }else if(This->load_group) {
1003             window = get_window_from_load_group(This);
1004             if(window)
1005                 set_uri_window(This->uri, window);
1006         }
1007     }
1008
1009     if(!window) {
1010         ERR("window = NULL\n");
1011         return NS_ERROR_UNEXPECTED;
1012     }
1013
1014     if(This->uri->is_doc_uri && window == window->doc_obj->basedoc.window) {
1015         if(This->uri->channel_bsc) {
1016             channelbsc_set_channel(This->uri->channel_bsc, This, aListener, aContext);
1017
1018             if(window->doc_obj->mime) {
1019                 heap_free(This->content_type);
1020                 This->content_type = heap_strdupWtoA(window->doc_obj->mime);
1021             }
1022
1023             open = FALSE;
1024         }else {
1025             open = !before_async_open(This, window->doc_obj->nscontainer);
1026             if(!open) {
1027                 TRACE("canceled\n");
1028                 nsres = NS_ERROR_UNEXPECTED;
1029             }
1030         }
1031     }
1032
1033     if(open)
1034         nsres = async_open(This, window, This->uri->is_doc_uri, aListener, aContext);
1035
1036     IHTMLWindow2_Release(HTMLWINDOW2(window));
1037     return nsres;
1038 }
1039
1040 static nsresult NSAPI nsChannel_GetRequestMethod(nsIHttpChannel *iface, nsACString *aRequestMethod)
1041 {
1042     nsChannel *This = NSCHANNEL_THIS(iface);
1043
1044     TRACE("(%p)->(%p)\n", This, aRequestMethod);
1045
1046     nsACString_SetData(aRequestMethod, request_method_strings[This->request_method]);
1047     return NS_OK;
1048 }
1049
1050 static nsresult NSAPI nsChannel_SetRequestMethod(nsIHttpChannel *iface,
1051                                                  const nsACString *aRequestMethod)
1052 {
1053     nsChannel *This = NSCHANNEL_THIS(iface);
1054     const char *method;
1055     unsigned i;
1056
1057     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRequestMethod));
1058
1059     nsACString_GetData(aRequestMethod, &method);
1060     for(i=0; i < sizeof(request_method_strings)/sizeof(*request_method_strings); i++) {
1061         if(!strcasecmp(method, request_method_strings[i])) {
1062             This->request_method = i;
1063             return NS_OK;
1064         }
1065     }
1066
1067     ERR("Invalid method %s\n", debugstr_a(method));
1068     return NS_ERROR_UNEXPECTED;
1069 }
1070
1071 static nsresult NSAPI nsChannel_GetReferrer(nsIHttpChannel *iface, nsIURI **aReferrer)
1072 {
1073     nsChannel *This = NSCHANNEL_THIS(iface);
1074
1075     FIXME("(%p)->(%p)\n", This, aReferrer);
1076
1077     return NS_ERROR_NOT_IMPLEMENTED;
1078 }
1079
1080 static nsresult NSAPI nsChannel_SetReferrer(nsIHttpChannel *iface, nsIURI *aReferrer)
1081 {
1082     nsChannel *This = NSCHANNEL_THIS(iface);
1083
1084     FIXME("(%p)->(%p)\n", This, aReferrer);
1085
1086     return NS_OK;
1087 }
1088
1089 static nsresult NSAPI nsChannel_GetRequestHeader(nsIHttpChannel *iface,
1090          const nsACString *aHeader, nsACString *_retval)
1091 {
1092     nsChannel *This = NSCHANNEL_THIS(iface);
1093
1094     TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(aHeader), _retval);
1095
1096     return get_channel_http_header(&This->request_headers, aHeader, _retval);
1097 }
1098
1099 static nsresult NSAPI nsChannel_SetRequestHeader(nsIHttpChannel *iface,
1100          const nsACString *aHeader, const nsACString *aValue, PRBool aMerge)
1101 {
1102     nsChannel *This = NSCHANNEL_THIS(iface);
1103
1104     TRACE("(%p)->(%s %s %x)\n", This, debugstr_nsacstr(aHeader), debugstr_nsacstr(aValue), aMerge);
1105
1106     if(aMerge)
1107         FIXME("aMerge not supported\n");
1108
1109     return set_channel_http_header(&This->request_headers, aHeader, aValue);
1110 }
1111
1112 static nsresult NSAPI nsChannel_VisitRequestHeaders(nsIHttpChannel *iface,
1113                                                     nsIHttpHeaderVisitor *aVisitor)
1114 {
1115     nsChannel *This = NSCHANNEL_THIS(iface);
1116
1117     FIXME("(%p)->(%p)\n", This, aVisitor);
1118
1119     return NS_ERROR_NOT_IMPLEMENTED;
1120 }
1121
1122 static nsresult NSAPI nsChannel_GetAllowPipelining(nsIHttpChannel *iface, PRBool *aAllowPipelining)
1123 {
1124     nsChannel *This = NSCHANNEL_THIS(iface);
1125
1126     FIXME("(%p)->(%p)\n", This, aAllowPipelining);
1127
1128     return NS_ERROR_NOT_IMPLEMENTED;
1129 }
1130
1131 static nsresult NSAPI nsChannel_SetAllowPipelining(nsIHttpChannel *iface, PRBool aAllowPipelining)
1132 {
1133     nsChannel *This = NSCHANNEL_THIS(iface);
1134
1135     FIXME("(%p)->(%x)\n", This, aAllowPipelining);
1136
1137     return NS_ERROR_NOT_IMPLEMENTED;
1138 }
1139
1140 static nsresult NSAPI nsChannel_GetRedirectionLimit(nsIHttpChannel *iface, PRUint32 *aRedirectionLimit)
1141 {
1142     nsChannel *This = NSCHANNEL_THIS(iface);
1143
1144     FIXME("(%p)->(%p)\n", This, aRedirectionLimit);
1145
1146     return NS_ERROR_NOT_IMPLEMENTED;
1147 }
1148
1149 static nsresult NSAPI nsChannel_SetRedirectionLimit(nsIHttpChannel *iface, PRUint32 aRedirectionLimit)
1150 {
1151     nsChannel *This = NSCHANNEL_THIS(iface);
1152
1153     FIXME("(%p)->(%u)\n", This, aRedirectionLimit);
1154
1155     return NS_ERROR_NOT_IMPLEMENTED;
1156 }
1157
1158 static nsresult NSAPI nsChannel_GetResponseStatus(nsIHttpChannel *iface, PRUint32 *aResponseStatus)
1159 {
1160     nsChannel *This = NSCHANNEL_THIS(iface);
1161
1162     TRACE("(%p)->(%p)\n", This, aResponseStatus);
1163
1164     if(This->response_status) {
1165         *aResponseStatus = This->response_status;
1166         return NS_OK;
1167     }
1168
1169     WARN("No response status\n");
1170     return NS_ERROR_UNEXPECTED;
1171 }
1172
1173 static nsresult NSAPI nsChannel_GetResponseStatusText(nsIHttpChannel *iface,
1174                                                       nsACString *aResponseStatusText)
1175 {
1176     nsChannel *This = NSCHANNEL_THIS(iface);
1177
1178     FIXME("(%p)->(%p)\n", This, aResponseStatusText);
1179
1180     return NS_ERROR_NOT_IMPLEMENTED;
1181 }
1182
1183 static nsresult NSAPI nsChannel_GetRequestSucceeded(nsIHttpChannel *iface,
1184                                                     PRBool *aRequestSucceeded)
1185 {
1186     nsChannel *This = NSCHANNEL_THIS(iface);
1187
1188     TRACE("(%p)->(%p)\n", This, aRequestSucceeded);
1189
1190     if(!This->response_status)
1191         return NS_ERROR_NOT_AVAILABLE;
1192
1193     *aRequestSucceeded = This->response_status/100 == 2;
1194
1195     return NS_OK;
1196 }
1197
1198 static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface,
1199          const nsACString *header, nsACString *_retval)
1200 {
1201     nsChannel *This = NSCHANNEL_THIS(iface);
1202
1203     TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(header), _retval);
1204
1205     return get_channel_http_header(&This->response_headers, header, _retval);
1206 }
1207
1208 static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface,
1209         const nsACString *header, const nsACString *value, PRBool merge)
1210 {
1211     nsChannel *This = NSCHANNEL_THIS(iface);
1212
1213     FIXME("(%p)->(%s %s %x)\n", This, debugstr_nsacstr(header), debugstr_nsacstr(value), merge);
1214
1215     return NS_ERROR_NOT_IMPLEMENTED;
1216 }
1217
1218 static nsresult NSAPI nsChannel_VisitResponseHeaders(nsIHttpChannel *iface,
1219         nsIHttpHeaderVisitor *aVisitor)
1220 {
1221     nsChannel *This = NSCHANNEL_THIS(iface);
1222
1223     FIXME("(%p)->(%p)\n", This, aVisitor);
1224
1225     return NS_ERROR_NOT_IMPLEMENTED;
1226 }
1227
1228 static nsresult NSAPI nsChannel_IsNoStoreResponse(nsIHttpChannel *iface, PRBool *_retval)
1229 {
1230     nsChannel *This = NSCHANNEL_THIS(iface);
1231
1232     FIXME("(%p)->(%p)\n", This, _retval);
1233
1234     return NS_ERROR_NOT_IMPLEMENTED;
1235 }
1236
1237 static nsresult NSAPI nsChannel_IsNoCacheResponse(nsIHttpChannel *iface, PRBool *_retval)
1238 {
1239     nsChannel *This = NSCHANNEL_THIS(iface);
1240
1241     FIXME("(%p)->(%p)\n", This, _retval);
1242
1243     return NS_ERROR_NOT_IMPLEMENTED;
1244 }
1245
1246 #undef NSCHANNEL_THIS
1247
1248 static const nsIHttpChannelVtbl nsChannelVtbl = {
1249     nsChannel_QueryInterface,
1250     nsChannel_AddRef,
1251     nsChannel_Release,
1252     nsChannel_GetName,
1253     nsChannel_IsPending,
1254     nsChannel_GetStatus,
1255     nsChannel_Cancel,
1256     nsChannel_Suspend,
1257     nsChannel_Resume,
1258     nsChannel_GetLoadGroup,
1259     nsChannel_SetLoadGroup,
1260     nsChannel_GetLoadFlags,
1261     nsChannel_SetLoadFlags,
1262     nsChannel_GetOriginalURI,
1263     nsChannel_SetOriginalURI,
1264     nsChannel_GetURI,
1265     nsChannel_GetOwner,
1266     nsChannel_SetOwner,
1267     nsChannel_GetNotificationCallbacks,
1268     nsChannel_SetNotificationCallbacks,
1269     nsChannel_GetSecurityInfo,
1270     nsChannel_GetContentType,
1271     nsChannel_SetContentType,
1272     nsChannel_GetContentCharset,
1273     nsChannel_SetContentCharset,
1274     nsChannel_GetContentLength,
1275     nsChannel_SetContentLength,
1276     nsChannel_Open,
1277     nsChannel_AsyncOpen,
1278     nsChannel_GetRequestMethod,
1279     nsChannel_SetRequestMethod,
1280     nsChannel_GetReferrer,
1281     nsChannel_SetReferrer,
1282     nsChannel_GetRequestHeader,
1283     nsChannel_SetRequestHeader,
1284     nsChannel_VisitRequestHeaders,
1285     nsChannel_GetAllowPipelining,
1286     nsChannel_SetAllowPipelining,
1287     nsChannel_GetRedirectionLimit,
1288     nsChannel_SetRedirectionLimit,
1289     nsChannel_GetResponseStatus,
1290     nsChannel_GetResponseStatusText,
1291     nsChannel_GetRequestSucceeded,
1292     nsChannel_GetResponseHeader,
1293     nsChannel_SetResponseHeader,
1294     nsChannel_VisitResponseHeaders,
1295     nsChannel_IsNoStoreResponse,
1296     nsChannel_IsNoCacheResponse
1297 };
1298
1299 #define NSUPCHANNEL_THIS(iface) DEFINE_THIS(nsChannel, UploadChannel, iface)
1300
1301 static nsresult NSAPI nsUploadChannel_QueryInterface(nsIUploadChannel *iface, nsIIDRef riid,
1302         void **result)
1303 {
1304     nsChannel *This = NSUPCHANNEL_THIS(iface);
1305     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1306 }
1307
1308 static nsrefcnt NSAPI nsUploadChannel_AddRef(nsIUploadChannel *iface)
1309 {
1310     nsChannel *This = NSUPCHANNEL_THIS(iface);
1311     return nsIChannel_AddRef(NSCHANNEL(This));
1312 }
1313
1314 static nsrefcnt NSAPI nsUploadChannel_Release(nsIUploadChannel *iface)
1315 {
1316     nsChannel *This = NSUPCHANNEL_THIS(iface);
1317     return nsIChannel_Release(NSCHANNEL(This));
1318 }
1319
1320 static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
1321         nsIInputStream *aStream, const nsACString *aContentType, PRInt32 aContentLength)
1322 {
1323     nsChannel *This = NSUPCHANNEL_THIS(iface);
1324     const char *content_type;
1325
1326     static const WCHAR content_typeW[] =
1327         {'C','o','n','t','e','n','t','-','T','y','p','e',0};
1328
1329     TRACE("(%p)->(%p %s %d)\n", This, aStream, debugstr_nsacstr(aContentType), aContentLength);
1330
1331     This->parse_stream = TRUE;
1332     if(aContentType) {
1333         nsACString_GetData(aContentType, &content_type);
1334         if(*content_type) {
1335             WCHAR *ct;
1336
1337             ct = heap_strdupAtoW(content_type);
1338             if(!ct)
1339                 return NS_ERROR_UNEXPECTED;
1340
1341             set_http_header(&This->request_headers, content_typeW,
1342                     sizeof(content_typeW)/sizeof(WCHAR), ct, strlenW(ct));
1343             heap_free(ct);
1344             This->parse_stream = FALSE;
1345         }
1346     }
1347
1348     if(This->post_data_stream)
1349         nsIInputStream_Release(This->post_data_stream);
1350
1351     if(aContentLength != -1)
1352         FIXME("Unsupported acontentLength = %d\n", aContentLength);
1353
1354     if(This->post_data_stream)
1355         nsIInputStream_Release(This->post_data_stream);
1356     This->post_data_stream = aStream;
1357     if(aStream)
1358         nsIInputStream_AddRef(aStream);
1359
1360     This->request_method = METHOD_POST;
1361     return NS_OK;
1362 }
1363
1364 static nsresult NSAPI nsUploadChannel_GetUploadStream(nsIUploadChannel *iface,
1365         nsIInputStream **aUploadStream)
1366 {
1367     nsChannel *This = NSUPCHANNEL_THIS(iface);
1368
1369     TRACE("(%p)->(%p)\n", This, aUploadStream);
1370
1371     if(This->post_data_stream)
1372         nsIInputStream_AddRef(This->post_data_stream);
1373
1374     *aUploadStream = This->post_data_stream;
1375     return NS_OK;
1376 }
1377
1378 #undef NSUPCHANNEL_THIS
1379
1380 static const nsIUploadChannelVtbl nsUploadChannelVtbl = {
1381     nsUploadChannel_QueryInterface,
1382     nsUploadChannel_AddRef,
1383     nsUploadChannel_Release,
1384     nsUploadChannel_SetUploadStream,
1385     nsUploadChannel_GetUploadStream
1386 };
1387
1388 #define NSHTTPINTERNAL_THIS(iface) DEFINE_THIS(nsChannel, IHttpChannelInternal, iface)
1389
1390 static nsresult NSAPI nsHttpChannelInternal_QueryInterface(nsIHttpChannelInternal *iface, nsIIDRef riid,
1391         void **result)
1392 {
1393     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1394     return nsIChannel_QueryInterface(NSCHANNEL(This), riid, result);
1395 }
1396
1397 static nsrefcnt NSAPI nsHttpChannelInternal_AddRef(nsIHttpChannelInternal *iface)
1398 {
1399     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1400     return nsIChannel_AddRef(NSCHANNEL(This));
1401 }
1402
1403 static nsrefcnt NSAPI nsHttpChannelInternal_Release(nsIHttpChannelInternal *iface)
1404 {
1405     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1406     return nsIChannel_Release(NSCHANNEL(This));
1407 }
1408
1409 static nsresult NSAPI nsHttpChannelInternal_GetDocumentURI(nsIHttpChannelInternal *iface, nsIURI **aDocumentURI)
1410 {
1411     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1412
1413     FIXME("(%p)->()\n", This);
1414
1415     return NS_ERROR_NOT_IMPLEMENTED;
1416 }
1417
1418 static nsresult NSAPI nsHttpChannelInternal_SetDocumentURI(nsIHttpChannelInternal *iface, nsIURI *aDocumentURI)
1419 {
1420     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1421
1422     FIXME("(%p)->()\n", This);
1423
1424     return NS_ERROR_NOT_IMPLEMENTED;
1425 }
1426
1427 static nsresult NSAPI nsHttpChannelInternal_GetRequestVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1428 {
1429     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1430
1431     FIXME("(%p)->()\n", This);
1432
1433     return NS_ERROR_NOT_IMPLEMENTED;
1434 }
1435
1436 static nsresult NSAPI nsHttpChannelInternal_GetResponseVersion(nsIHttpChannelInternal *iface, PRUint32 *major, PRUint32 *minor)
1437 {
1438     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1439
1440     FIXME("(%p)->()\n", This);
1441
1442     return NS_ERROR_NOT_IMPLEMENTED;
1443 }
1444
1445 static nsresult NSAPI nsHttpChannelInternal_SetCookie(nsIHttpChannelInternal *iface, const char *aCookieHeader)
1446 {
1447     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1448
1449     FIXME("(%p)->()\n", This);
1450
1451     return NS_ERROR_NOT_IMPLEMENTED;
1452 }
1453
1454 static nsresult NSAPI nsHttpChannelInternal_SetupFallbackChannel(nsIHttpChannelInternal *iface, const char *aFallbackKey)
1455 {
1456     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1457
1458     FIXME("(%p)->()\n", This);
1459
1460     return NS_ERROR_NOT_IMPLEMENTED;
1461 }
1462
1463 static nsresult NSAPI nsHttpChannelInternal_GetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool *aForceThirdPartyCookie)
1464 {
1465     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1466
1467     FIXME("(%p)->()\n", This);
1468
1469     return NS_ERROR_NOT_IMPLEMENTED;
1470 }
1471
1472 static nsresult NSAPI nsHttpChannelInternal_SetForceAllowThirdPartyCookie(nsIHttpChannelInternal *iface, PRBool aForceThirdPartyCookie)
1473 {
1474     nsChannel *This = NSHTTPINTERNAL_THIS(iface);
1475
1476     FIXME("(%p)->()\n", This);
1477
1478     return NS_ERROR_NOT_IMPLEMENTED;
1479 }
1480
1481 #undef NSHTTPINTERNAL_THIS
1482
1483 static const nsIHttpChannelInternalVtbl nsHttpChannelInternalVtbl = {
1484     nsHttpChannelInternal_QueryInterface,
1485     nsHttpChannelInternal_AddRef,
1486     nsHttpChannelInternal_Release,
1487     nsHttpChannelInternal_GetDocumentURI,
1488     nsHttpChannelInternal_SetDocumentURI,
1489     nsHttpChannelInternal_GetRequestVersion,
1490     nsHttpChannelInternal_GetResponseVersion,
1491     nsHttpChannelInternal_SetCookie,
1492     nsHttpChannelInternal_SetupFallbackChannel,
1493     nsHttpChannelInternal_GetForceAllowThirdPartyCookie,
1494     nsHttpChannelInternal_SetForceAllowThirdPartyCookie
1495 };
1496
1497 #define NSURI_THIS(iface) DEFINE_THIS(nsWineURI, IURL, iface)
1498
1499 static nsresult NSAPI nsURI_QueryInterface(nsIURL *iface, nsIIDRef riid, void **result)
1500 {
1501     nsWineURI *This = NSURI_THIS(iface);
1502
1503     *result = NULL;
1504
1505     if(IsEqualGUID(&IID_nsISupports, riid)) {
1506         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
1507         *result = NSURI(This);
1508     }else if(IsEqualGUID(&IID_nsIURI, riid)) {
1509         TRACE("(%p)->(IID_nsIURI %p)\n", This, result);
1510         *result = NSURI(This);
1511     }else if(IsEqualGUID(&IID_nsIURL, riid)) {
1512         TRACE("(%p)->(IID_nsIURL %p)\n", This, result);
1513         *result = NSURL(This);
1514     }else if(IsEqualGUID(&IID_nsWineURI, riid)) {
1515         TRACE("(%p)->(IID_nsWineURI %p)\n", This, result);
1516         *result = This;
1517     }
1518
1519     if(*result) {
1520         nsIURI_AddRef(NSURI(This));
1521         return NS_OK;
1522     }
1523
1524     TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), result);
1525     return This->uri ? nsIURI_QueryInterface(This->uri, riid, result) : NS_NOINTERFACE;
1526 }
1527
1528 static nsrefcnt NSAPI nsURI_AddRef(nsIURL *iface)
1529 {
1530     nsWineURI *This = NSURI_THIS(iface);
1531     LONG ref = InterlockedIncrement(&This->ref);
1532
1533     TRACE("(%p) ref=%d\n", This, ref);
1534
1535     return ref;
1536 }
1537
1538 static nsrefcnt NSAPI nsURI_Release(nsIURL *iface)
1539 {
1540     nsWineURI *This = NSURI_THIS(iface);
1541     LONG ref = InterlockedDecrement(&This->ref);
1542
1543     TRACE("(%p) ref=%d\n", This, ref);
1544
1545     if(!ref) {
1546         if(This->window_ref)
1547             windowref_release(This->window_ref);
1548         if(This->container)
1549             nsIWebBrowserChrome_Release(NSWBCHROME(This->container));
1550         if(This->nsurl)
1551             nsIURL_Release(This->nsurl);
1552         if(This->uri)
1553             nsIURI_Release(This->uri);
1554         heap_free(This->wine_url);
1555         heap_free(This);
1556     }
1557
1558     return ref;
1559 }
1560
1561 static nsresult NSAPI nsURI_GetSpec(nsIURL *iface, nsACString *aSpec)
1562 {
1563     nsWineURI *This = NSURI_THIS(iface);
1564
1565     TRACE("(%p)->(%p)\n", This, aSpec);
1566
1567     if(This->use_wine_url) {
1568         char speca[INTERNET_MAX_URL_LENGTH] = "wine:";
1569         WideCharToMultiByte(CP_ACP, 0, This->wine_url, -1, speca+5, sizeof(speca)-5, NULL, NULL);
1570         nsACString_SetData(aSpec, speca);
1571
1572         return NS_OK;
1573     }
1574
1575     if(This->uri)
1576         return nsIURI_GetSpec(This->uri, aSpec);
1577
1578     TRACE("returning error\n");
1579     return NS_ERROR_NOT_IMPLEMENTED;
1580
1581 }
1582
1583 static nsresult NSAPI nsURI_SetSpec(nsIURL *iface, const nsACString *aSpec)
1584 {
1585     nsWineURI *This = NSURI_THIS(iface);
1586
1587     TRACE("(%p)->(%p)\n", This, debugstr_nsacstr(aSpec));
1588
1589     if(This->uri)
1590         return nsIURI_SetSpec(This->uri, aSpec);
1591
1592     FIXME("default action not implemented\n");
1593     return NS_ERROR_NOT_IMPLEMENTED;
1594 }
1595
1596 static nsresult NSAPI nsURI_GetPrePath(nsIURL *iface, nsACString *aPrePath)
1597 {
1598     nsWineURI *This = NSURI_THIS(iface);
1599
1600     TRACE("(%p)->(%p)\n", This, aPrePath);
1601
1602     if(This->uri)
1603         return nsIURI_GetPrePath(This->uri, aPrePath);
1604
1605     FIXME("default action not implemented\n");
1606     return NS_ERROR_NOT_IMPLEMENTED;
1607 }
1608
1609 static nsresult NSAPI nsURI_GetScheme(nsIURL *iface, nsACString *aScheme)
1610 {
1611     nsWineURI *This = NSURI_THIS(iface);
1612
1613     TRACE("(%p)->(%p)\n", This, aScheme);
1614
1615     if(This->use_wine_url) {
1616         /*
1617          * For Gecko we set scheme to unknown so it won't be handled
1618          * as any special case.
1619          */
1620         nsACString_SetData(aScheme, "wine");
1621         return NS_OK;
1622     }
1623
1624     if(This->uri)
1625         return nsIURI_GetScheme(This->uri, aScheme);
1626
1627     TRACE("returning error\n");
1628     return NS_ERROR_NOT_IMPLEMENTED;
1629 }
1630
1631 static nsresult NSAPI nsURI_SetScheme(nsIURL *iface, const nsACString *aScheme)
1632 {
1633     nsWineURI *This = NSURI_THIS(iface);
1634
1635     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aScheme));
1636
1637     if(This->uri)
1638         return nsIURI_SetScheme(This->uri, aScheme);
1639
1640     FIXME("default action not implemented\n");
1641     return NS_ERROR_NOT_IMPLEMENTED;
1642 }
1643
1644 static nsresult NSAPI nsURI_GetUserPass(nsIURL *iface, nsACString *aUserPass)
1645 {
1646     nsWineURI *This = NSURI_THIS(iface);
1647
1648     TRACE("(%p)->(%p)\n", This, aUserPass);
1649
1650     if(This->uri)
1651         return nsIURI_GetUserPass(This->uri, aUserPass);
1652
1653     FIXME("default action not implemented\n");
1654     return NS_ERROR_NOT_IMPLEMENTED;
1655 }
1656
1657 static nsresult NSAPI nsURI_SetUserPass(nsIURL *iface, const nsACString *aUserPass)
1658 {
1659     nsWineURI *This = NSURI_THIS(iface);
1660
1661     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aUserPass));
1662
1663     if(This->uri)
1664         return nsIURI_SetUserPass(This->uri, aUserPass);
1665
1666     FIXME("default action not implemented\n");
1667     return NS_ERROR_NOT_IMPLEMENTED;
1668 }
1669
1670 static nsresult NSAPI nsURI_GetUsername(nsIURL *iface, nsACString *aUsername)
1671 {
1672     nsWineURI *This = NSURI_THIS(iface);
1673
1674     TRACE("(%p)->(%p)\n", This, aUsername);
1675
1676     if(This->uri)
1677         return nsIURI_GetUsername(This->uri, aUsername);
1678
1679     FIXME("default action not implemented\n");
1680     return NS_ERROR_NOT_IMPLEMENTED;
1681 }
1682
1683 static nsresult NSAPI nsURI_SetUsername(nsIURL *iface, const nsACString *aUsername)
1684 {
1685     nsWineURI *This = NSURI_THIS(iface);
1686
1687     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aUsername));
1688
1689     if(This->uri)
1690         return nsIURI_SetUsername(This->uri, aUsername);
1691
1692     FIXME("default action not implemented\n");
1693     return NS_ERROR_NOT_IMPLEMENTED;
1694 }
1695
1696 static nsresult NSAPI nsURI_GetPassword(nsIURL *iface, nsACString *aPassword)
1697 {
1698     nsWineURI *This = NSURI_THIS(iface);
1699
1700     TRACE("(%p)->(%p)\n", This, aPassword);
1701
1702     if(This->uri)
1703         return nsIURI_GetPassword(This->uri, aPassword);
1704
1705     FIXME("default action not implemented\n");
1706     return NS_ERROR_NOT_IMPLEMENTED;
1707 }
1708
1709 static nsresult NSAPI nsURI_SetPassword(nsIURL *iface, const nsACString *aPassword)
1710 {
1711     nsWineURI *This = NSURI_THIS(iface);
1712
1713     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aPassword));
1714
1715     if(This->uri)
1716         return nsIURI_SetPassword(This->uri, aPassword);
1717
1718     FIXME("default action not implemented\n");
1719     return NS_ERROR_NOT_IMPLEMENTED;
1720 }
1721
1722 static nsresult NSAPI nsURI_GetHostPort(nsIURL *iface, nsACString *aHostPort)
1723 {
1724     nsWineURI *This = NSURI_THIS(iface);
1725
1726     TRACE("(%p)->(%p)\n", This, aHostPort);
1727
1728     if(This->uri)
1729         return nsIURI_GetHostPort(This->uri, aHostPort);
1730
1731     FIXME("default action not implemented\n");
1732     return NS_ERROR_NOT_IMPLEMENTED;
1733 }
1734
1735 static nsresult NSAPI nsURI_SetHostPort(nsIURL *iface, const nsACString *aHostPort)
1736 {
1737     nsWineURI *This = NSURI_THIS(iface);
1738
1739     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aHostPort));
1740
1741     if(This->uri)
1742         return nsIURI_SetHostPort(This->uri, aHostPort);
1743
1744     FIXME("default action not implemented\n");
1745     return NS_ERROR_NOT_IMPLEMENTED;
1746 }
1747
1748 static nsresult NSAPI nsURI_GetHost(nsIURL *iface, nsACString *aHost)
1749 {
1750     nsWineURI *This = NSURI_THIS(iface);
1751
1752     TRACE("(%p)->(%p)\n", This, aHost);
1753
1754     if(This->uri)
1755         return nsIURI_GetHost(This->uri, aHost);
1756
1757     FIXME("default action not implemented\n");
1758     return NS_ERROR_NOT_IMPLEMENTED;
1759 }
1760
1761 static nsresult NSAPI nsURI_SetHost(nsIURL *iface, const nsACString *aHost)
1762 {
1763     nsWineURI *This = NSURI_THIS(iface);
1764
1765     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aHost));
1766
1767     if(This->uri)
1768         return nsIURI_SetHost(This->uri, aHost);
1769
1770     FIXME("default action not implemented\n");
1771     return NS_ERROR_NOT_IMPLEMENTED;
1772 }
1773
1774 static nsresult NSAPI nsURI_GetPort(nsIURL *iface, PRInt32 *aPort)
1775 {
1776     nsWineURI *This = NSURI_THIS(iface);
1777
1778     TRACE("(%p)->(%p)\n", This, aPort);
1779
1780     if(This->uri)
1781         return nsIURI_GetPort(This->uri, aPort);
1782
1783     FIXME("default action not implemented\n");
1784     return NS_ERROR_NOT_IMPLEMENTED;
1785 }
1786
1787 static nsresult NSAPI nsURI_SetPort(nsIURL *iface, PRInt32 aPort)
1788 {
1789     nsWineURI *This = NSURI_THIS(iface);
1790
1791     TRACE("(%p)->(%d)\n", This, aPort);
1792
1793     if(This->uri)
1794         return nsIURI_SetPort(This->uri, aPort);
1795
1796     FIXME("default action not implemented\n");
1797     return NS_ERROR_NOT_IMPLEMENTED;
1798 }
1799
1800 static nsresult NSAPI nsURI_GetPath(nsIURL *iface, nsACString *aPath)
1801 {
1802     nsWineURI *This = NSURI_THIS(iface);
1803
1804     TRACE("(%p)->(%p)\n", This, aPath);
1805
1806     if(This->uri)
1807         return nsIURI_GetPath(This->uri, aPath);
1808
1809     FIXME("default action not implemented\n");
1810     return NS_ERROR_NOT_IMPLEMENTED;
1811 }
1812
1813 static nsresult NSAPI nsURI_SetPath(nsIURL *iface, const nsACString *aPath)
1814 {
1815     nsWineURI *This = NSURI_THIS(iface);
1816     const char *path;
1817
1818     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aPath));
1819
1820     nsACString_GetData(aPath, &path);
1821     if(This->wine_url) {
1822         WCHAR new_url[INTERNET_MAX_URL_LENGTH];
1823         DWORD size = sizeof(new_url)/sizeof(WCHAR);
1824         LPWSTR pathw;
1825         HRESULT hres;
1826
1827         pathw = heap_strdupAtoW(path);
1828         hres = UrlCombineW(This->wine_url, pathw, new_url, &size, 0);
1829         heap_free(pathw);
1830         if(SUCCEEDED(hres))
1831             set_wine_url(This, new_url);
1832         else
1833             WARN("UrlCombine failed: %08x\n", hres);
1834     }
1835
1836     if(!This->uri)
1837         return NS_OK;
1838
1839     return nsIURI_SetPath(This->uri, aPath);
1840 }
1841
1842 static nsresult NSAPI nsURI_Equals(nsIURL *iface, nsIURI *other, PRBool *_retval)
1843 {
1844     nsWineURI *This = NSURI_THIS(iface);
1845     nsWineURI *wine_uri;
1846     nsresult nsres;
1847
1848     TRACE("(%p)->(%p %p)\n", This, other, _retval);
1849
1850     if(This->uri)
1851         return nsIURI_Equals(This->uri, other, _retval);
1852
1853     nsres = nsIURI_QueryInterface(other, &IID_nsWineURI, (void**)&wine_uri);
1854     if(NS_FAILED(nsres)) {
1855         TRACE("Could not get nsWineURI interface\n");
1856         *_retval = FALSE;
1857         return NS_OK;
1858     }
1859
1860     *_retval = wine_uri->wine_url && !UrlCompareW(This->wine_url, wine_uri->wine_url, TRUE);
1861     nsIURI_Release(NSURI(wine_uri));
1862
1863     return NS_OK;
1864 }
1865
1866 static nsresult NSAPI nsURI_SchemeIs(nsIURL *iface, const char *scheme, PRBool *_retval)
1867 {
1868     nsWineURI *This = NSURI_THIS(iface);
1869
1870     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
1871
1872     if(This->use_wine_url) {
1873         WCHAR buf[INTERNET_MAX_SCHEME_LENGTH];
1874         int len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
1875
1876         *_retval = lstrlenW(This->wine_url) > len
1877             && This->wine_url[len] == ':'
1878             && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
1879         return NS_OK;
1880     }
1881
1882     if(This->uri)
1883         return nsIURI_SchemeIs(This->uri, scheme, _retval);
1884
1885     TRACE("returning error\n");
1886     return NS_ERROR_NOT_IMPLEMENTED;
1887 }
1888
1889 static nsresult NSAPI nsURI_Clone(nsIURL *iface, nsIURI **_retval)
1890 {
1891     nsWineURI *This = NSURI_THIS(iface);
1892     nsIURI *nsuri = NULL;
1893     nsWineURI *wine_uri;
1894     nsresult nsres;
1895
1896     TRACE("(%p)->(%p)\n", This, _retval);
1897
1898     if(This->uri) {
1899         nsres = nsIURI_Clone(This->uri, &nsuri);
1900         if(NS_FAILED(nsres)) {
1901             WARN("Clone failed: %08x\n", nsres);
1902             return nsres;
1903         }
1904     }
1905
1906     nsres = create_uri(nsuri, This->window_ref ? This->window_ref->window : NULL, This->container, &wine_uri);
1907     if(NS_FAILED(nsres)) {
1908         WARN("create_uri failed: %08x\n", nsres);
1909         return nsres;
1910     }
1911
1912     set_wine_url(wine_uri, This->wine_url);
1913
1914     *_retval = NSURI(wine_uri);
1915     return NS_OK;
1916 }
1917
1918 static nsresult NSAPI nsURI_Resolve(nsIURL *iface, const nsACString *arelativePath,
1919         nsACString *_retval)
1920 {
1921     nsWineURI *This = NSURI_THIS(iface);
1922
1923     TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(arelativePath), _retval);
1924
1925     if(This->uri)
1926         return nsIURI_Resolve(This->uri, arelativePath, _retval);
1927
1928     FIXME("default action not implemented\n");
1929     return NS_ERROR_NOT_IMPLEMENTED;
1930 }
1931
1932 static nsresult NSAPI nsURI_GetAsciiSpec(nsIURL *iface, nsACString *aAsciiSpec)
1933 {
1934     nsWineURI *This = NSURI_THIS(iface);
1935
1936     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
1937
1938     if(This->use_wine_url)
1939         return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
1940
1941     if(This->uri)
1942         return nsIURI_GetAsciiSpec(This->uri, aAsciiSpec);
1943
1944     TRACE("returning error\n");
1945     return NS_ERROR_NOT_IMPLEMENTED;
1946 }
1947
1948 static nsresult NSAPI nsURI_GetAsciiHost(nsIURL *iface, nsACString *aAsciiHost)
1949 {
1950     nsWineURI *This = NSURI_THIS(iface);
1951
1952     TRACE("(%p)->(%p)\n", This, aAsciiHost);
1953
1954     if(This->uri)
1955         return nsIURI_GetAsciiHost(This->uri, aAsciiHost);
1956
1957     FIXME("default action not implemented\n");
1958     return NS_ERROR_NOT_IMPLEMENTED;
1959 }
1960
1961 static nsresult NSAPI nsURI_GetOriginCharset(nsIURL *iface, nsACString *aOriginCharset)
1962 {
1963     nsWineURI *This = NSURI_THIS(iface);
1964
1965     TRACE("(%p)->(%p)\n", This, aOriginCharset);
1966
1967     if(This->uri)
1968         return nsIURI_GetOriginCharset(This->uri, aOriginCharset);
1969
1970     FIXME("default action not implemented\n");
1971     return NS_ERROR_NOT_IMPLEMENTED;
1972 }
1973
1974 static nsresult NSAPI nsURL_GetFilePath(nsIURL *iface, nsACString *aFilePath)
1975 {
1976     nsWineURI *This = NSURI_THIS(iface);
1977
1978     TRACE("(%p)->(%p)\n", This, aFilePath);
1979
1980     if(This->nsurl)
1981         return nsIURL_GetFilePath(This->nsurl, aFilePath);
1982
1983     FIXME("default action not implemented\n");
1984     return NS_ERROR_NOT_IMPLEMENTED;
1985 }
1986
1987 static nsresult NSAPI nsURL_SetFilePath(nsIURL *iface, const nsACString *aFilePath)
1988 {
1989     nsWineURI *This = NSURI_THIS(iface);
1990
1991     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath));
1992
1993     if(This->nsurl)
1994         return nsIURL_SetFilePath(This->nsurl, aFilePath);
1995
1996     FIXME("default action not implemented\n");
1997     return NS_ERROR_NOT_IMPLEMENTED;
1998 }
1999
2000 static nsresult NSAPI nsURL_GetParam(nsIURL *iface, nsACString *aParam)
2001 {
2002     nsWineURI *This = NSURI_THIS(iface);
2003
2004     TRACE("(%p)->(%p)\n", This, aParam);
2005
2006     if(This->nsurl)
2007         return nsIURL_GetParam(This->nsurl, aParam);
2008
2009     FIXME("default action not implemented\n");
2010     return NS_ERROR_NOT_IMPLEMENTED;
2011 }
2012
2013 static nsresult NSAPI nsURL_SetParam(nsIURL *iface, const nsACString *aParam)
2014 {
2015     nsWineURI *This = NSURI_THIS(iface);
2016
2017     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aParam));
2018
2019     if(This->nsurl)
2020         return nsIURL_SetParam(This->nsurl, aParam);
2021
2022     FIXME("default action not implemented\n");
2023     return NS_ERROR_NOT_IMPLEMENTED;
2024 }
2025
2026 static nsresult NSAPI nsURL_GetQuery(nsIURL *iface, nsACString *aQuery)
2027 {
2028     nsWineURI *This = NSURI_THIS(iface);
2029
2030     TRACE("(%p)->(%p)\n", This, aQuery);
2031
2032     if(This->nsurl)
2033         return nsIURL_GetQuery(This->nsurl, aQuery);
2034
2035     FIXME("default action not implemented\n");
2036     return NS_ERROR_NOT_IMPLEMENTED;
2037 }
2038
2039 static nsresult NSAPI nsURL_SetQuery(nsIURL *iface, const nsACString *aQuery)
2040 {
2041     nsWineURI *This = NSURI_THIS(iface);
2042     const WCHAR *ptr1, *ptr2;
2043     const char *query;
2044     WCHAR *new_url, *ptr;
2045     DWORD len, size;
2046
2047     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery));
2048
2049     if(This->nsurl)
2050         nsIURL_SetQuery(This->nsurl, aQuery);
2051
2052     if(!This->wine_url)
2053         return NS_OK;
2054
2055     nsACString_GetData(aQuery, &query);
2056     size = len = MultiByteToWideChar(CP_ACP, 0, query, -1, NULL, 0);
2057     ptr1 = strchrW(This->wine_url, '?');
2058     if(ptr1) {
2059         size += ptr1-This->wine_url;
2060         ptr2 = strchrW(ptr1, '#');
2061         if(ptr2)
2062             size += strlenW(ptr2);
2063     }else {
2064         ptr1 = This->wine_url + strlenW(This->wine_url);
2065         ptr2 = NULL;
2066         size += strlenW(This->wine_url);
2067     }
2068
2069     if(*query)
2070         size++;
2071
2072     new_url = heap_alloc(size*sizeof(WCHAR));
2073     memcpy(new_url, This->wine_url, (ptr1-This->wine_url)*sizeof(WCHAR));
2074     ptr = new_url + (ptr1-This->wine_url);
2075     if(*query) {
2076         *ptr++ = '?';
2077         MultiByteToWideChar(CP_ACP, 0, query, -1, ptr, len);
2078         ptr += len-1;
2079     }
2080     if(ptr2)
2081         strcpyW(ptr, ptr2);
2082     else
2083         *ptr = 0;
2084
2085     TRACE("setting %s\n", debugstr_w(new_url));
2086
2087     heap_free(This->wine_url);
2088     This->wine_url = new_url;
2089     return NS_OK;
2090 }
2091
2092 static nsresult NSAPI nsURL_GetRef(nsIURL *iface, nsACString *aRef)
2093 {
2094     nsWineURI *This = NSURI_THIS(iface);
2095
2096     TRACE("(%p)->(%p)\n", This, aRef);
2097
2098     if(This->nsurl)
2099         return nsIURL_GetRef(This->nsurl, aRef);
2100
2101     FIXME("default action not implemented\n");
2102     return NS_ERROR_NOT_IMPLEMENTED;
2103 }
2104
2105 static nsresult NSAPI nsURL_SetRef(nsIURL *iface, const nsACString *aRef)
2106 {
2107     nsWineURI *This = NSURI_THIS(iface);
2108     const char *refa;
2109
2110     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
2111
2112     if(This->nsurl)
2113         return nsIURL_SetRef(This->nsurl, aRef);
2114
2115     nsACString_GetData(aRef, &refa);
2116     if(!*refa)
2117         return NS_OK;
2118
2119     FIXME("default action not implemented\n");
2120     return NS_ERROR_NOT_IMPLEMENTED;
2121 }
2122
2123 static nsresult NSAPI nsURL_GetDirectory(nsIURL *iface, nsACString *aDirectory)
2124 {
2125     nsWineURI *This = NSURI_THIS(iface);
2126
2127     TRACE("(%p)->(%p)\n", This, aDirectory);
2128
2129     if(This->nsurl)
2130         return nsIURL_GetDirectory(This->nsurl, aDirectory);
2131
2132     FIXME("default action not implemented\n");
2133     return NS_ERROR_NOT_IMPLEMENTED;
2134 }
2135
2136 static nsresult NSAPI nsURL_SetDirectory(nsIURL *iface, const nsACString *aDirectory)
2137 {
2138     nsWineURI *This = NSURI_THIS(iface);
2139
2140     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
2141
2142     if(This->nsurl)
2143         return nsIURL_SetDirectory(This->nsurl, aDirectory);
2144
2145     FIXME("default action not implemented\n");
2146     return NS_ERROR_NOT_IMPLEMENTED;
2147 }
2148
2149 static nsresult NSAPI nsURL_GetFileName(nsIURL *iface, nsACString *aFileName)
2150 {
2151     nsWineURI *This = NSURI_THIS(iface);
2152
2153     TRACE("(%p)->(%p)\n", This, aFileName);
2154
2155     if(This->nsurl)
2156         return nsIURL_GetFileName(This->nsurl, aFileName);
2157
2158     FIXME("default action not implemented\n");
2159     return NS_ERROR_NOT_IMPLEMENTED;
2160 }
2161
2162 static nsresult NSAPI nsURL_SetFileName(nsIURL *iface, const nsACString *aFileName)
2163 {
2164     nsWineURI *This = NSURI_THIS(iface);
2165
2166     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
2167
2168     if(This->nsurl)
2169         return nsIURL_SetFileName(This->nsurl, aFileName);
2170
2171     FIXME("default action not implemented\n");
2172     return NS_ERROR_NOT_IMPLEMENTED;
2173 }
2174
2175 static nsresult NSAPI nsURL_GetFileBaseName(nsIURL *iface, nsACString *aFileBaseName)
2176 {
2177     nsWineURI *This = NSURI_THIS(iface);
2178
2179     TRACE("(%p)->(%p)\n", This, aFileBaseName);
2180
2181     if(This->nsurl)
2182         return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
2183
2184     FIXME("default action not implemented\n");
2185     return NS_ERROR_NOT_IMPLEMENTED;
2186 }
2187
2188 static nsresult NSAPI nsURL_SetFileBaseName(nsIURL *iface, const nsACString *aFileBaseName)
2189 {
2190     nsWineURI *This = NSURI_THIS(iface);
2191
2192     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
2193
2194     if(This->nsurl)
2195         return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
2196
2197     FIXME("default action not implemented\n");
2198     return NS_ERROR_NOT_IMPLEMENTED;
2199 }
2200
2201 static nsresult NSAPI nsURL_GetFileExtension(nsIURL *iface, nsACString *aFileExtension)
2202 {
2203     nsWineURI *This = NSURI_THIS(iface);
2204
2205     TRACE("(%p)->(%p)\n", This, aFileExtension);
2206
2207     if(This->nsurl)
2208         return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
2209
2210     FIXME("default action not implemented\n");
2211     return NS_ERROR_NOT_IMPLEMENTED;
2212 }
2213
2214 static nsresult NSAPI nsURL_SetFileExtension(nsIURL *iface, const nsACString *aFileExtension)
2215 {
2216     nsWineURI *This = NSURI_THIS(iface);
2217
2218     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
2219
2220     if(This->nsurl)
2221         return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
2222
2223     FIXME("default action not implemented\n");
2224     return NS_ERROR_NOT_IMPLEMENTED;
2225 }
2226
2227 static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval)
2228 {
2229     nsWineURI *This = NSURI_THIS(iface);
2230
2231     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2232
2233     if(This->nsurl)
2234         return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
2235
2236     FIXME("default action not implemented\n");
2237     return NS_ERROR_NOT_IMPLEMENTED;
2238 }
2239
2240 static nsresult NSAPI nsURL_GetRelativeSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval)
2241 {
2242     nsWineURI *This = NSURI_THIS(iface);
2243
2244     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2245
2246     if(This->nsurl)
2247         return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
2248
2249     FIXME("default action not implemented\n");
2250     return NS_ERROR_NOT_IMPLEMENTED;
2251 }
2252
2253 #undef NSURI_THIS
2254
2255 static const nsIURLVtbl nsURLVtbl = {
2256     nsURI_QueryInterface,
2257     nsURI_AddRef,
2258     nsURI_Release,
2259     nsURI_GetSpec,
2260     nsURI_SetSpec,
2261     nsURI_GetPrePath,
2262     nsURI_GetScheme,
2263     nsURI_SetScheme,
2264     nsURI_GetUserPass,
2265     nsURI_SetUserPass,
2266     nsURI_GetUsername,
2267     nsURI_SetUsername,
2268     nsURI_GetPassword,
2269     nsURI_SetPassword,
2270     nsURI_GetHostPort,
2271     nsURI_SetHostPort,
2272     nsURI_GetHost,
2273     nsURI_SetHost,
2274     nsURI_GetPort,
2275     nsURI_SetPort,
2276     nsURI_GetPath,
2277     nsURI_SetPath,
2278     nsURI_Equals,
2279     nsURI_SchemeIs,
2280     nsURI_Clone,
2281     nsURI_Resolve,
2282     nsURI_GetAsciiSpec,
2283     nsURI_GetAsciiHost,
2284     nsURI_GetOriginCharset,
2285     nsURL_GetFilePath,
2286     nsURL_SetFilePath,
2287     nsURL_GetParam,
2288     nsURL_SetParam,
2289     nsURL_GetQuery,
2290     nsURL_SetQuery,
2291     nsURL_GetRef,
2292     nsURL_SetRef,
2293     nsURL_GetDirectory,
2294     nsURL_SetDirectory,
2295     nsURL_GetFileName,
2296     nsURL_SetFileName,
2297     nsURL_GetFileBaseName,
2298     nsURL_SetFileBaseName,
2299     nsURL_GetFileExtension,
2300     nsURL_SetFileExtension,
2301     nsURL_GetCommonBaseSpec,
2302     nsURL_GetRelativeSpec
2303 };
2304
2305 static nsresult create_uri(nsIURI *uri, HTMLWindow *window, NSContainer *container, nsWineURI **_retval)
2306 {
2307     nsWineURI *ret = heap_alloc_zero(sizeof(nsWineURI));
2308
2309     ret->lpIURLVtbl = &nsURLVtbl;
2310     ret->ref = 1;
2311     ret->uri = uri;
2312
2313     set_uri_nscontainer(ret, container);
2314     set_uri_window(ret, window);
2315
2316     if(uri)
2317         nsIURI_QueryInterface(uri, &IID_nsIURL, (void**)&ret->nsurl);
2318
2319     TRACE("retval=%p\n", ret);
2320     *_retval = ret;
2321     return NS_OK;
2322 }
2323
2324 HRESULT create_doc_uri(HTMLWindow *window, WCHAR *url, nsWineURI **ret)
2325 {
2326     nsWineURI *uri;
2327     nsresult nsres;
2328
2329     nsres = create_uri(NULL, window, window->doc_obj->nscontainer, &uri);
2330     if(NS_FAILED(nsres))
2331         return E_FAIL;
2332
2333     set_wine_url(uri, url);
2334     uri->is_doc_uri = TRUE;
2335
2336     *ret = uri;
2337     return S_OK;
2338 }
2339
2340 typedef struct {
2341     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
2342
2343     LONG ref;
2344
2345     nsIProtocolHandler *nshandler;
2346 } nsProtocolHandler;
2347
2348 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
2349
2350 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
2351
2352 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
2353         void **result)
2354 {
2355     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2356
2357     *result = NULL;
2358
2359     if(IsEqualGUID(&IID_nsISupports, riid)) {
2360         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
2361         *result = NSPROTHANDLER(This);
2362     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
2363         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
2364         *result = NSPROTHANDLER(This);
2365     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
2366         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
2367         return NS_NOINTERFACE;
2368     }
2369
2370     if(*result) {
2371         nsISupports_AddRef((nsISupports*)*result);
2372         return NS_OK;
2373     }
2374
2375     WARN("(%s %p)\n", debugstr_guid(riid), result);
2376     return NS_NOINTERFACE;
2377 }
2378
2379 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
2380 {
2381     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2382     LONG ref = InterlockedIncrement(&This->ref);
2383
2384     TRACE("(%p) ref=%d\n", This, ref);
2385
2386     return ref;
2387 }
2388
2389 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
2390 {
2391     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2392     LONG ref = InterlockedDecrement(&This->ref);
2393
2394     TRACE("(%p) ref=%d\n", This, ref);
2395
2396     if(!ref) {
2397         if(This->nshandler)
2398             nsIProtocolHandler_Release(This->nshandler);
2399         heap_free(This);
2400     }
2401
2402     return ref;
2403 }
2404
2405 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
2406 {
2407     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2408
2409     TRACE("(%p)->(%p)\n", This, aScheme);
2410
2411     if(This->nshandler)
2412         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
2413     return NS_ERROR_NOT_IMPLEMENTED;
2414 }
2415
2416 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
2417         PRInt32 *aDefaultPort)
2418 {
2419     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2420
2421     TRACE("(%p)->(%p)\n", This, aDefaultPort);
2422
2423     if(This->nshandler)
2424         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
2425     return NS_ERROR_NOT_IMPLEMENTED;
2426 }
2427
2428 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
2429                                                          PRUint32 *aProtocolFlags)
2430 {
2431     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2432
2433     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
2434
2435     if(This->nshandler)
2436         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
2437     return NS_ERROR_NOT_IMPLEMENTED;
2438 }
2439
2440 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
2441         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2442 {
2443     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2444
2445     TRACE("((%p)->%s %s %p %p)\n", This, debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset),
2446           aBaseURI, _retval);
2447
2448     if(This->nshandler)
2449         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
2450     return NS_ERROR_NOT_IMPLEMENTED;
2451 }
2452
2453 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
2454         nsIURI *aURI, nsIChannel **_retval)
2455 {
2456     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2457
2458     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
2459
2460     if(This->nshandler)
2461         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
2462     return NS_ERROR_NOT_IMPLEMENTED;
2463 }
2464
2465 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
2466         PRInt32 port, const char *scheme, PRBool *_retval)
2467 {
2468     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2469
2470     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
2471
2472     if(This->nshandler)
2473         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
2474     return NS_ERROR_NOT_IMPLEMENTED;
2475 }
2476
2477 #undef NSPROTHANDLER_THIS
2478
2479 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
2480     nsProtocolHandler_QueryInterface,
2481     nsProtocolHandler_AddRef,
2482     nsProtocolHandler_Release,
2483     nsProtocolHandler_GetScheme,
2484     nsProtocolHandler_GetDefaultPort,
2485     nsProtocolHandler_GetProtocolFlags,
2486     nsProtocolHandler_NewURI,
2487     nsProtocolHandler_NewChannel,
2488     nsProtocolHandler_AllowPort
2489 };
2490
2491 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
2492 {
2493     nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler));
2494
2495     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
2496     ret->ref = 1;
2497     ret->nshandler = nshandler;
2498
2499     return NSPROTHANDLER(ret);
2500 }
2501
2502 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,void**);
2503
2504 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
2505 {
2506     return 2;
2507 }
2508
2509 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
2510 {
2511     return 1;
2512 }
2513
2514 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
2515                                                      nsIProtocolHandler **_retval)
2516 {
2517     nsIExternalProtocolHandler *nsexthandler;
2518     nsIProtocolHandler *nshandler;
2519     nsresult nsres;
2520
2521     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2522
2523     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
2524     if(NS_FAILED(nsres)) {
2525         WARN("GetProtocolHandler failed: %08x\n", nsres);
2526         return nsres;
2527     }
2528
2529     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
2530                                               (void**)&nsexthandler);
2531     if(NS_FAILED(nsres)) {
2532         *_retval = nshandler;
2533         return NS_OK;
2534     }
2535
2536     nsIExternalProtocolHandler_Release(nsexthandler);
2537     *_retval = create_protocol_handler(nshandler);
2538     TRACE("return %p\n", *_retval);
2539     return NS_OK;
2540 }
2541
2542 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
2543                                                     PRUint32 *_retval)
2544 {
2545     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2546     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
2547 }
2548
2549 static BOOL is_gecko_special_uri(const char *spec)
2550 {
2551     static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
2552     int i;
2553
2554     for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
2555         if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
2556             return TRUE;
2557     }
2558
2559     return FALSE;
2560 }
2561
2562 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
2563         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2564 {
2565     nsWineURI *wine_uri, *base_wine_uri = NULL;
2566     const char *spec = NULL;
2567     HTMLWindow *window = NULL;
2568     nsIURI *uri = NULL;
2569     LPCWSTR base_wine_url = NULL;
2570     nsACString spec_str;
2571     nsresult nsres;
2572
2573
2574     TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset),
2575           aBaseURI, _retval);
2576
2577     nsACString_GetData(aSpec, &spec);
2578     if(is_gecko_special_uri(spec))
2579         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2580
2581     if(!strncmp(spec, "wine:", 5))
2582         spec += 5;
2583
2584     if(aBaseURI) {
2585         PARSEDURLA parsed_url = {sizeof(PARSEDURLA)};
2586
2587         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsWineURI, (void**)&base_wine_uri);
2588         if(NS_SUCCEEDED(nsres)) {
2589             base_wine_url = base_wine_uri->wine_url;
2590             if(base_wine_uri->window_ref && base_wine_uri->window_ref->window) {
2591                 window = base_wine_uri->window_ref->window;
2592                 IHTMLWindow2_AddRef(HTMLWINDOW2(window));
2593             }
2594             TRACE("base url: %s window: %p\n", debugstr_w(base_wine_url), window);
2595         }else if(FAILED(ParseURLA(spec, &parsed_url))) {
2596             TRACE("not wraping\n");
2597             return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2598         }else {
2599             WARN("Could not get base nsWineURI: %08x\n", nsres);
2600         }
2601     }
2602
2603     nsACString_InitDepend(&spec_str, spec);
2604     nsres = nsIIOService_NewURI(nsio, &spec_str, aOriginCharset, aBaseURI, &uri);
2605     nsACString_Finish(&spec_str);
2606     if(NS_FAILED(nsres))
2607         TRACE("NewURI failed: %08x\n", nsres);
2608
2609     nsres = create_uri(uri, window, NULL, &wine_uri);
2610     *_retval = (nsIURI*)wine_uri;
2611
2612     if(window)
2613         IHTMLWindow2_Release(HTMLWINDOW2(window));
2614
2615     if(base_wine_url) {
2616         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2617         DWORD len;
2618         HRESULT hres;
2619
2620         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2621
2622         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2623                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2624                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2625         if(SUCCEEDED(hres))
2626             set_wine_url(wine_uri, url);
2627         else
2628              WARN("CoCombineUrl failed: %08x\n", hres);
2629     }else {
2630         WCHAR url[INTERNET_MAX_URL_LENGTH];
2631
2632         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2633         set_wine_url(wine_uri, url);
2634     }
2635
2636     if(base_wine_uri)
2637         nsIURI_Release(NSURI(base_wine_uri));
2638
2639     return nsres;
2640 }
2641
2642 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2643                                              nsIURI **_retval)
2644 {
2645     TRACE("(%p %p)\n", aFile, _retval);
2646     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2647 }
2648
2649 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2650                                                      nsIChannel **_retval)
2651 {
2652     PARSEDURLW parsed_url = {sizeof(PARSEDURLW)};
2653     nsChannel *ret;
2654     nsWineURI *wine_uri;
2655     nsresult nsres;
2656
2657     TRACE("(%p %p)\n", aURI, _retval);
2658
2659     nsres = nsIURI_QueryInterface(aURI, &IID_nsWineURI, (void**)&wine_uri);
2660     if(NS_FAILED(nsres)) {
2661         TRACE("Could not get nsWineURI: %08x\n", nsres);
2662         return nsIIOService_NewChannelFromURI(nsio, aURI, _retval);
2663     }
2664
2665     ret = heap_alloc_zero(sizeof(nsChannel));
2666
2667     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2668     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2669     ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
2670     ret->ref = 1;
2671     ret->uri = wine_uri;
2672     ret->request_method = METHOD_GET;
2673     list_init(&ret->response_headers);
2674     list_init(&ret->request_headers);
2675
2676     nsIURI_AddRef(aURI);
2677     ret->original_uri = aURI;
2678     ret->url_scheme = wine_uri->wine_url && SUCCEEDED(ParseURLW(wine_uri->wine_url, &parsed_url))
2679         ? parsed_url.nScheme : URL_SCHEME_UNKNOWN;
2680
2681     *_retval = NSCHANNEL(ret);
2682     return NS_OK;
2683 }
2684
2685 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2686         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2687 {
2688     TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), aBaseURI, _retval);
2689     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2690 }
2691
2692 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2693 {
2694     TRACE("(%p)\n", aOffline);
2695     return nsIIOService_GetOffline(nsio, aOffline);
2696 }
2697
2698 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2699 {
2700     TRACE("(%x)\n", aOffline);
2701     return nsIIOService_SetOffline(nsio, aOffline);
2702 }
2703
2704 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2705                                              const char *aScheme, PRBool *_retval)
2706 {
2707     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2708     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2709 }
2710
2711 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2712                                                  nsACString * _retval)
2713 {
2714     TRACE("(%s %p)\n", debugstr_nsacstr(urlString), _retval);
2715     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2716 }
2717
2718 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2719     nsIOService_QueryInterface,
2720     nsIOService_AddRef,
2721     nsIOService_Release,
2722     nsIOService_GetProtocolHandler,
2723     nsIOService_GetProtocolFlags,
2724     nsIOService_NewURI,
2725     nsIOService_NewFileURI,
2726     nsIOService_NewChannelFromURI,
2727     nsIOService_NewChannel,
2728     nsIOService_GetOffline,
2729     nsIOService_SetOffline,
2730     nsIOService_AllowPort,
2731     nsIOService_ExtractScheme
2732 };
2733
2734 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2735
2736 static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid,
2737         void **result)
2738 {
2739     return nsIIOService_QueryInterface(&nsIOService, riid, result);
2740 }
2741
2742 static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface)
2743 {
2744     return 2;
2745 }
2746
2747 static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface)
2748 {
2749     return 1;
2750 }
2751
2752 static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2753         nsACString *aCharset, PRBool *aHadCharset, nsACString *aContentType)
2754 {
2755     TRACE("(%s %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aHadCharset, aContentType);
2756
2757     return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType);
2758 }
2759
2760 static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2761 {
2762     TRACE("()\n");
2763
2764     return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval);
2765 }
2766
2767 static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2768 {
2769     TRACE("(%p %08x %p)\n", aURI, aFlags, _retval);
2770
2771     if(aFlags == (1<<11)) {
2772         *_retval = FALSE;
2773         return NS_OK;
2774     }
2775
2776     return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval);
2777 }
2778
2779 static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2780 {
2781     TRACE("(%p %p)\n", aURI, _retval);
2782
2783     return nsINetUtil_ToImmutableURI(net_util, aURI, _retval);
2784 }
2785
2786 static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString,
2787                                              PRUint32 aEscapeType, nsACString *_retval)
2788 {
2789     TRACE("(%s %x %p)\n", debugstr_nsacstr(aString), aEscapeType, _retval);
2790
2791     return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval);
2792 }
2793
2794 static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags,
2795                                           nsACString *_retval)
2796 {
2797     TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval);
2798
2799     return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval);
2800 }
2801
2802 static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr,
2803                                                PRUint32 aFlags, nsACString *_retval)
2804 {
2805     TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval);
2806
2807     return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval);
2808 }
2809
2810 static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2811         nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, PRBool *_retval)
2812 {
2813     TRACE("(%s %p %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aCharsetStart,
2814           aCharsetEnd, _retval);
2815
2816     return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
2817 }
2818
2819 static const nsINetUtilVtbl nsNetUtilVtbl = {
2820     nsNetUtil_QueryInterface,
2821     nsNetUtil_AddRef,
2822     nsNetUtil_Release,
2823     nsNetUtil_ParseContentType,
2824     nsNetUtil_ProtocolHasFlags,
2825     nsNetUtil_URIChainHasFlags,
2826     nsNetUtil_ToImmutableURI,
2827     nsNetUtil_EscapeString,
2828     nsNetUtil_EscapeURL,
2829     nsNetUtil_UnescapeString,
2830     nsNetUtil_ExtractCharsetFromContentType
2831 };
2832
2833 static nsINetUtil nsNetUtil = { &nsNetUtilVtbl };
2834
2835 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
2836         void **result)
2837 {
2838     *result = NULL;
2839
2840     if(IsEqualGUID(&IID_nsISupports, riid))
2841         *result = &nsIOService;
2842     else if(IsEqualGUID(&IID_nsIIOService, riid))
2843         *result = &nsIOService;
2844     else if(IsEqualGUID(&IID_nsINetUtil, riid))
2845         *result = &nsNetUtil;
2846
2847     if(*result) {
2848         nsISupports_AddRef((nsISupports*)*result);
2849         return NS_OK;
2850     }
2851
2852     FIXME("(%s %p)\n", debugstr_guid(riid), result);
2853     return NS_NOINTERFACE;
2854 }
2855
2856 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
2857         void **result)
2858 {
2859     *result = NULL;
2860
2861     if(IsEqualGUID(&IID_nsISupports, riid)) {
2862         TRACE("(IID_nsISupports %p)\n", result);
2863         *result = iface;
2864     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
2865         TRACE("(IID_nsIFactory %p)\n", result);
2866         *result = iface;
2867     }
2868
2869     if(*result) {
2870         nsIFactory_AddRef(iface);
2871         return NS_OK;
2872     }
2873
2874     WARN("(%s %p)\n", debugstr_guid(riid), result);
2875     return NS_NOINTERFACE;
2876 }
2877
2878 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
2879 {
2880     return 2;
2881 }
2882
2883 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
2884 {
2885     return 1;
2886 }
2887
2888 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
2889         nsISupports *aOuter, const nsIID *iid, void **result)
2890 {
2891     return nsIIOService_QueryInterface(&nsIOService, iid, result);
2892 }
2893
2894 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
2895 {
2896     WARN("(%x)\n", lock);
2897     return NS_OK;
2898 }
2899
2900 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
2901     nsIOServiceFactory_QueryInterface,
2902     nsIOServiceFactory_AddRef,
2903     nsIOServiceFactory_Release,
2904     nsIOServiceFactory_CreateInstance,
2905     nsIOServiceFactory_LockFactory
2906 };
2907
2908 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
2909
2910 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
2911 {
2912     nsIFactory *old_factory = NULL;
2913     nsresult nsres;
2914
2915     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
2916                                                &IID_nsIFactory, (void**)&old_factory);
2917     if(NS_FAILED(nsres)) {
2918         ERR("Could not get factory: %08x\n", nsres);
2919         return;
2920     }
2921
2922     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
2923     if(NS_FAILED(nsres)) {
2924         ERR("Couldn not create nsIOService instance %08x\n", nsres);
2925         nsIFactory_Release(old_factory);
2926         return;
2927     }
2928
2929     nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util);
2930     if(NS_FAILED(nsres)) {
2931         WARN("Could not get nsINetUtil interface: %08x\n", nsres);
2932         nsIIOService_Release(nsio);
2933         return;
2934     }
2935
2936     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
2937     nsIFactory_Release(old_factory);
2938     if(NS_FAILED(nsres))
2939         ERR("UnregisterFactory failed: %08x\n", nsres);
2940
2941     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
2942             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
2943     if(NS_FAILED(nsres))
2944         ERR("RegisterFactory failed: %08x\n", nsres);
2945 }
2946
2947 void release_nsio(void)
2948 {
2949     if(net_util) {
2950         nsINetUtil_Release(net_util);
2951         net_util = NULL;
2952     }
2953
2954     if(nsio) {
2955         nsIIOService_Release(nsio);
2956         nsio = NULL;
2957     }
2958 }