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