mshtml: Use IUri for nsIURI::GetSpec implementation.
[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     int len;
2041
2042     TRACE("(%p)->(%s %p)\n", This, debugstr_a(scheme), _retval);
2043
2044     len = MultiByteToWideChar(CP_ACP, 0, scheme, -1, buf, sizeof(buf)/sizeof(WCHAR))-1;
2045
2046     *_retval = lstrlenW(This->wine_url) > len
2047         && This->wine_url[len] == ':'
2048         && !memcmp(buf, This->wine_url, len*sizeof(WCHAR));
2049     return NS_OK;
2050 }
2051
2052 static nsresult NSAPI nsURI_Clone(nsIURL *iface, nsIURI **_retval)
2053 {
2054     nsWineURI *This = NSURI_THIS(iface);
2055     nsIURI *nsuri = NULL;
2056     nsWineURI *wine_uri;
2057     nsresult nsres;
2058
2059     TRACE("(%p)->(%p)\n", This, _retval);
2060
2061     if(This->nsuri) {
2062         nsres = nsIURI_Clone(This->nsuri, &nsuri);
2063         if(NS_FAILED(nsres)) {
2064             WARN("Clone failed: %08x\n", nsres);
2065             return nsres;
2066         }
2067     }
2068
2069     nsres = create_uri(nsuri, This->window_ref ? This->window_ref->window : NULL, This->container, &wine_uri);
2070     if(NS_FAILED(nsres)) {
2071         WARN("create_uri failed: %08x\n", nsres);
2072         return nsres;
2073     }
2074
2075     set_wine_url(wine_uri, This->wine_url);
2076
2077     if(This->uri) {
2078         IUri_AddRef(This->uri);
2079         wine_uri->uri = This->uri;
2080     }
2081
2082     *_retval = NSURI(wine_uri);
2083     return NS_OK;
2084 }
2085
2086 static nsresult NSAPI nsURI_Resolve(nsIURL *iface, const nsACString *aRelativePath,
2087         nsACString *_retval)
2088 {
2089     nsWineURI *This = NSURI_THIS(iface);
2090     WCHAR url[INTERNET_MAX_URL_LENGTH];
2091     const char *patha;
2092     WCHAR *path;
2093     char *urla;
2094     DWORD len;
2095     HRESULT hres;
2096
2097     TRACE("(%p)->(%s %p)\n", This, debugstr_nsacstr(aRelativePath), _retval);
2098
2099     if(This->nsuri)
2100         return nsIURI_Resolve(This->nsuri, aRelativePath, _retval);
2101
2102     nsACString_GetData(aRelativePath, &patha);
2103     path = heap_strdupAtoW(patha);
2104     if(!path)
2105         return NS_ERROR_OUT_OF_MEMORY;
2106
2107     hres = CoInternetCombineUrl(This->wine_url, path,
2108                                 URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2109                                 url, sizeof(url)/sizeof(WCHAR), &len, 0);
2110     heap_free(path);
2111     if(FAILED(hres)) {
2112         ERR("CoIntenetCombineUrl failed: %08x\n", hres);
2113         return NS_ERROR_FAILURE;
2114     }
2115
2116     urla = heap_strdupWtoA(url);
2117     if(!urla)
2118         return NS_ERROR_OUT_OF_MEMORY;
2119
2120     TRACE("returning %s\n", debugstr_a(urla));
2121     nsACString_SetData(_retval, urla);
2122     heap_free(urla);
2123     return NS_OK;
2124 }
2125
2126 static nsresult NSAPI nsURI_GetAsciiSpec(nsIURL *iface, nsACString *aAsciiSpec)
2127 {
2128     nsWineURI *This = NSURI_THIS(iface);
2129
2130     TRACE("(%p)->(%p)\n", This, aAsciiSpec);
2131
2132     return nsIURI_GetSpec(NSURI(This), aAsciiSpec);
2133 }
2134
2135 static nsresult NSAPI nsURI_GetAsciiHost(nsIURL *iface, nsACString *aAsciiHost)
2136 {
2137     nsWineURI *This = NSURI_THIS(iface);
2138
2139     TRACE("(%p)->(%p)\n", This, aAsciiHost);
2140
2141     if(This->nsuri)
2142         return nsIURI_GetAsciiHost(This->nsuri, aAsciiHost);
2143
2144     FIXME("Use Uri_PUNYCODE_IDN_HOST flag\n");
2145     return get_uri_string(This, Uri_PROPERTY_HOST, aAsciiHost);
2146 }
2147
2148 static nsresult NSAPI nsURI_GetOriginCharset(nsIURL *iface, nsACString *aOriginCharset)
2149 {
2150     nsWineURI *This = NSURI_THIS(iface);
2151
2152     TRACE("(%p)->(%p)\n", This, aOriginCharset);
2153
2154     if(This->nsuri)
2155         return nsIURI_GetOriginCharset(This->nsuri, aOriginCharset);
2156
2157     FIXME("default action not implemented\n");
2158     return NS_ERROR_NOT_IMPLEMENTED;
2159 }
2160
2161 static nsresult NSAPI nsURL_GetFilePath(nsIURL *iface, nsACString *aFilePath)
2162 {
2163     nsWineURI *This = NSURI_THIS(iface);
2164
2165     TRACE("(%p)->(%p)\n", This, aFilePath);
2166
2167     if(This->nsurl)
2168         return nsIURL_GetFilePath(This->nsurl, aFilePath);
2169
2170     FIXME("default action not implemented\n");
2171     return NS_ERROR_NOT_IMPLEMENTED;
2172 }
2173
2174 static nsresult NSAPI nsURL_SetFilePath(nsIURL *iface, const nsACString *aFilePath)
2175 {
2176     nsWineURI *This = NSURI_THIS(iface);
2177
2178     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFilePath));
2179
2180     if(This->nsurl) {
2181         invalidate_uri(This);
2182         return nsIURL_SetFilePath(This->nsurl, aFilePath);
2183     }
2184
2185     FIXME("default action not implemented\n");
2186     return NS_ERROR_NOT_IMPLEMENTED;
2187 }
2188
2189 static nsresult NSAPI nsURL_GetParam(nsIURL *iface, nsACString *aParam)
2190 {
2191     nsWineURI *This = NSURI_THIS(iface);
2192
2193     TRACE("(%p)->(%p)\n", This, aParam);
2194
2195     if(This->nsurl)
2196         return nsIURL_GetParam(This->nsurl, aParam);
2197
2198     FIXME("default action not implemented\n");
2199     return NS_ERROR_NOT_IMPLEMENTED;
2200 }
2201
2202 static nsresult NSAPI nsURL_SetParam(nsIURL *iface, const nsACString *aParam)
2203 {
2204     nsWineURI *This = NSURI_THIS(iface);
2205
2206     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aParam));
2207
2208     if(This->nsurl) {
2209         invalidate_uri(This);
2210         return nsIURL_SetParam(This->nsurl, aParam);
2211     }
2212
2213     FIXME("default action not implemented\n");
2214     return NS_ERROR_NOT_IMPLEMENTED;
2215 }
2216
2217 static nsresult NSAPI nsURL_GetQuery(nsIURL *iface, nsACString *aQuery)
2218 {
2219     nsWineURI *This = NSURI_THIS(iface);
2220
2221     TRACE("(%p)->(%p)\n", This, aQuery);
2222
2223     if(This->nsurl)
2224         return nsIURL_GetQuery(This->nsurl, aQuery);
2225
2226     return get_uri_string(This, Uri_PROPERTY_QUERY, aQuery);
2227 }
2228
2229 static nsresult NSAPI nsURL_SetQuery(nsIURL *iface, const nsACString *aQuery)
2230 {
2231     nsWineURI *This = NSURI_THIS(iface);
2232     const char *querya;
2233     WCHAR *query;
2234     HRESULT hres;
2235
2236     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aQuery));
2237
2238     if(!ensure_uri_builder(This))
2239         return NS_ERROR_UNEXPECTED;
2240
2241     nsACString_GetData(aQuery, &querya);
2242     query = heap_strdupAtoW(querya);
2243     if(!query)
2244         return NS_ERROR_OUT_OF_MEMORY;
2245
2246     hres = IUriBuilder_SetQuery(This->uri_builder, query);
2247     heap_free(query);
2248     if(FAILED(hres))
2249         return NS_ERROR_UNEXPECTED;
2250
2251     sync_wine_url(This);
2252     return NS_OK;
2253 }
2254
2255 static nsresult NSAPI nsURL_GetRef(nsIURL *iface, nsACString *aRef)
2256 {
2257     nsWineURI *This = NSURI_THIS(iface);
2258
2259     TRACE("(%p)->(%p)\n", This, aRef);
2260
2261     if(This->nsurl)
2262         return nsIURL_GetRef(This->nsurl, aRef);
2263
2264     FIXME("default action not implemented\n");
2265     return NS_ERROR_NOT_IMPLEMENTED;
2266 }
2267
2268 static nsresult NSAPI nsURL_SetRef(nsIURL *iface, const nsACString *aRef)
2269 {
2270     nsWineURI *This = NSURI_THIS(iface);
2271     const char *refa;
2272
2273     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aRef));
2274
2275     if(This->nsurl) {
2276         invalidate_uri(This);
2277         return nsIURL_SetRef(This->nsurl, aRef);
2278     }
2279
2280     nsACString_GetData(aRef, &refa);
2281     if(!*refa)
2282         return NS_OK;
2283
2284     FIXME("default action not implemented\n");
2285     return NS_ERROR_NOT_IMPLEMENTED;
2286 }
2287
2288 static nsresult NSAPI nsURL_GetDirectory(nsIURL *iface, nsACString *aDirectory)
2289 {
2290     nsWineURI *This = NSURI_THIS(iface);
2291
2292     TRACE("(%p)->(%p)\n", This, aDirectory);
2293
2294     if(This->nsurl)
2295         return nsIURL_GetDirectory(This->nsurl, aDirectory);
2296
2297     FIXME("default action not implemented\n");
2298     return NS_ERROR_NOT_IMPLEMENTED;
2299 }
2300
2301 static nsresult NSAPI nsURL_SetDirectory(nsIURL *iface, const nsACString *aDirectory)
2302 {
2303     nsWineURI *This = NSURI_THIS(iface);
2304
2305     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aDirectory));
2306
2307     if(This->nsurl) {
2308         invalidate_uri(This);
2309         return nsIURL_SetDirectory(This->nsurl, aDirectory);
2310     }
2311
2312     FIXME("default action not implemented\n");
2313     return NS_ERROR_NOT_IMPLEMENTED;
2314 }
2315
2316 static nsresult NSAPI nsURL_GetFileName(nsIURL *iface, nsACString *aFileName)
2317 {
2318     nsWineURI *This = NSURI_THIS(iface);
2319
2320     TRACE("(%p)->(%p)\n", This, aFileName);
2321
2322     if(This->nsurl)
2323         return nsIURL_GetFileName(This->nsurl, aFileName);
2324
2325     FIXME("default action not implemented\n");
2326     return NS_ERROR_NOT_IMPLEMENTED;
2327 }
2328
2329 static nsresult NSAPI nsURL_SetFileName(nsIURL *iface, const nsACString *aFileName)
2330 {
2331     nsWineURI *This = NSURI_THIS(iface);
2332
2333     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileName));
2334
2335     if(This->nsurl) {
2336         invalidate_uri(This);
2337         return nsIURL_SetFileName(This->nsurl, aFileName);
2338     }
2339
2340     FIXME("default action not implemented\n");
2341     return NS_ERROR_NOT_IMPLEMENTED;
2342 }
2343
2344 static nsresult NSAPI nsURL_GetFileBaseName(nsIURL *iface, nsACString *aFileBaseName)
2345 {
2346     nsWineURI *This = NSURI_THIS(iface);
2347
2348     TRACE("(%p)->(%p)\n", This, aFileBaseName);
2349
2350     if(This->nsurl)
2351         return nsIURL_GetFileBaseName(This->nsurl, aFileBaseName);
2352
2353     FIXME("default action not implemented\n");
2354     return NS_ERROR_NOT_IMPLEMENTED;
2355 }
2356
2357 static nsresult NSAPI nsURL_SetFileBaseName(nsIURL *iface, const nsACString *aFileBaseName)
2358 {
2359     nsWineURI *This = NSURI_THIS(iface);
2360
2361     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileBaseName));
2362
2363     if(This->nsurl) {
2364         invalidate_uri(This);
2365         return nsIURL_SetFileBaseName(This->nsurl, aFileBaseName);
2366     }
2367
2368     FIXME("default action not implemented\n");
2369     return NS_ERROR_NOT_IMPLEMENTED;
2370 }
2371
2372 static nsresult NSAPI nsURL_GetFileExtension(nsIURL *iface, nsACString *aFileExtension)
2373 {
2374     nsWineURI *This = NSURI_THIS(iface);
2375
2376     TRACE("(%p)->(%p)\n", This, aFileExtension);
2377
2378     if(This->nsurl)
2379         return nsIURL_GetFileExtension(This->nsurl, aFileExtension);
2380
2381     FIXME("default action not implemented\n");
2382     return NS_ERROR_NOT_IMPLEMENTED;
2383 }
2384
2385 static nsresult NSAPI nsURL_SetFileExtension(nsIURL *iface, const nsACString *aFileExtension)
2386 {
2387     nsWineURI *This = NSURI_THIS(iface);
2388
2389     TRACE("(%p)->(%s)\n", This, debugstr_nsacstr(aFileExtension));
2390
2391     if(This->nsurl) {
2392         invalidate_uri(This);
2393         return nsIURL_SetFileExtension(This->nsurl, aFileExtension);
2394     }
2395
2396     FIXME("default action not implemented\n");
2397     return NS_ERROR_NOT_IMPLEMENTED;
2398 }
2399
2400 static nsresult NSAPI nsURL_GetCommonBaseSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval)
2401 {
2402     nsWineURI *This = NSURI_THIS(iface);
2403
2404     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2405
2406     if(This->nsurl)
2407         return nsIURL_GetCommonBaseSpec(This->nsurl, aURIToCompare, _retval);
2408
2409     FIXME("default action not implemented\n");
2410     return NS_ERROR_NOT_IMPLEMENTED;
2411 }
2412
2413 static nsresult NSAPI nsURL_GetRelativeSpec(nsIURL *iface, nsIURI *aURIToCompare, nsACString *_retval)
2414 {
2415     nsWineURI *This = NSURI_THIS(iface);
2416
2417     TRACE("(%p)->(%p %p)\n", This, aURIToCompare, _retval);
2418
2419     if(This->nsurl)
2420         return nsIURL_GetRelativeSpec(This->nsurl, aURIToCompare, _retval);
2421
2422     FIXME("default action not implemented\n");
2423     return NS_ERROR_NOT_IMPLEMENTED;
2424 }
2425
2426 #undef NSURI_THIS
2427
2428 static const nsIURLVtbl nsURLVtbl = {
2429     nsURI_QueryInterface,
2430     nsURI_AddRef,
2431     nsURI_Release,
2432     nsURI_GetSpec,
2433     nsURI_SetSpec,
2434     nsURI_GetPrePath,
2435     nsURI_GetScheme,
2436     nsURI_SetScheme,
2437     nsURI_GetUserPass,
2438     nsURI_SetUserPass,
2439     nsURI_GetUsername,
2440     nsURI_SetUsername,
2441     nsURI_GetPassword,
2442     nsURI_SetPassword,
2443     nsURI_GetHostPort,
2444     nsURI_SetHostPort,
2445     nsURI_GetHost,
2446     nsURI_SetHost,
2447     nsURI_GetPort,
2448     nsURI_SetPort,
2449     nsURI_GetPath,
2450     nsURI_SetPath,
2451     nsURI_Equals,
2452     nsURI_SchemeIs,
2453     nsURI_Clone,
2454     nsURI_Resolve,
2455     nsURI_GetAsciiSpec,
2456     nsURI_GetAsciiHost,
2457     nsURI_GetOriginCharset,
2458     nsURL_GetFilePath,
2459     nsURL_SetFilePath,
2460     nsURL_GetParam,
2461     nsURL_SetParam,
2462     nsURL_GetQuery,
2463     nsURL_SetQuery,
2464     nsURL_GetRef,
2465     nsURL_SetRef,
2466     nsURL_GetDirectory,
2467     nsURL_SetDirectory,
2468     nsURL_GetFileName,
2469     nsURL_SetFileName,
2470     nsURL_GetFileBaseName,
2471     nsURL_SetFileBaseName,
2472     nsURL_GetFileExtension,
2473     nsURL_SetFileExtension,
2474     nsURL_GetCommonBaseSpec,
2475     nsURL_GetRelativeSpec
2476 };
2477
2478 static nsresult create_uri(nsIURI *nsuri, HTMLWindow *window, NSContainer *container, nsWineURI **_retval)
2479 {
2480     nsWineURI *ret = heap_alloc_zero(sizeof(nsWineURI));
2481
2482     ret->lpIURLVtbl = &nsURLVtbl;
2483     ret->ref = 1;
2484     ret->nsuri = nsuri;
2485
2486     set_uri_nscontainer(ret, container);
2487     set_uri_window(ret, window);
2488
2489     if(nsuri)
2490         nsIURI_QueryInterface(nsuri, &IID_nsIURL, (void**)&ret->nsurl);
2491
2492     TRACE("retval=%p\n", ret);
2493     *_retval = ret;
2494     return NS_OK;
2495 }
2496
2497 HRESULT create_doc_uri(HTMLWindow *window, WCHAR *url, nsWineURI **ret)
2498 {
2499     nsWineURI *uri;
2500     nsresult nsres;
2501
2502     nsres = create_uri(NULL, window, window->doc_obj->nscontainer, &uri);
2503     if(NS_FAILED(nsres))
2504         return E_FAIL;
2505
2506     set_wine_url(uri, url);
2507     uri->is_doc_uri = TRUE;
2508
2509     *ret = uri;
2510     return S_OK;
2511 }
2512
2513 typedef struct {
2514     const nsIProtocolHandlerVtbl  *lpProtocolHandlerVtbl;
2515
2516     LONG ref;
2517
2518     nsIProtocolHandler *nshandler;
2519 } nsProtocolHandler;
2520
2521 #define NSPROTHANDLER(x)  ((nsIProtocolHandler*)  &(x)->lpProtocolHandlerVtbl)
2522
2523 #define NSPROTHANDLER_THIS(iface) DEFINE_THIS(nsProtocolHandler, ProtocolHandler, iface)
2524
2525 static nsresult NSAPI nsProtocolHandler_QueryInterface(nsIProtocolHandler *iface, nsIIDRef riid,
2526         void **result)
2527 {
2528     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2529
2530     *result = NULL;
2531
2532     if(IsEqualGUID(&IID_nsISupports, riid)) {
2533         TRACE("(%p)->(IID_nsISupports %p)\n", This, result);
2534         *result = NSPROTHANDLER(This);
2535     }else if(IsEqualGUID(&IID_nsIProtocolHandler, riid)) {
2536         TRACE("(%p)->(IID_nsIProtocolHandler %p)\n", This, result);
2537         *result = NSPROTHANDLER(This);
2538     }else if(IsEqualGUID(&IID_nsIExternalProtocolHandler, riid)) {
2539         TRACE("(%p)->(IID_nsIExternalProtocolHandler %p), returning NULL\n", This, result);
2540         return NS_NOINTERFACE;
2541     }
2542
2543     if(*result) {
2544         nsISupports_AddRef((nsISupports*)*result);
2545         return NS_OK;
2546     }
2547
2548     WARN("(%s %p)\n", debugstr_guid(riid), result);
2549     return NS_NOINTERFACE;
2550 }
2551
2552 static nsrefcnt NSAPI nsProtocolHandler_AddRef(nsIProtocolHandler *iface)
2553 {
2554     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2555     LONG ref = InterlockedIncrement(&This->ref);
2556
2557     TRACE("(%p) ref=%d\n", This, ref);
2558
2559     return ref;
2560 }
2561
2562 static nsrefcnt NSAPI nsProtocolHandler_Release(nsIProtocolHandler *iface)
2563 {
2564     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2565     LONG ref = InterlockedDecrement(&This->ref);
2566
2567     TRACE("(%p) ref=%d\n", This, ref);
2568
2569     if(!ref) {
2570         if(This->nshandler)
2571             nsIProtocolHandler_Release(This->nshandler);
2572         heap_free(This);
2573     }
2574
2575     return ref;
2576 }
2577
2578 static nsresult NSAPI nsProtocolHandler_GetScheme(nsIProtocolHandler *iface, nsACString *aScheme)
2579 {
2580     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2581
2582     TRACE("(%p)->(%p)\n", This, aScheme);
2583
2584     if(This->nshandler)
2585         return nsIProtocolHandler_GetScheme(This->nshandler, aScheme);
2586     return NS_ERROR_NOT_IMPLEMENTED;
2587 }
2588
2589 static nsresult NSAPI nsProtocolHandler_GetDefaultPort(nsIProtocolHandler *iface,
2590         PRInt32 *aDefaultPort)
2591 {
2592     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2593
2594     TRACE("(%p)->(%p)\n", This, aDefaultPort);
2595
2596     if(This->nshandler)
2597         return nsIProtocolHandler_GetDefaultPort(This->nshandler, aDefaultPort);
2598     return NS_ERROR_NOT_IMPLEMENTED;
2599 }
2600
2601 static nsresult NSAPI nsProtocolHandler_GetProtocolFlags(nsIProtocolHandler *iface,
2602                                                          PRUint32 *aProtocolFlags)
2603 {
2604     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2605
2606     TRACE("(%p)->(%p)\n", This, aProtocolFlags);
2607
2608     if(This->nshandler)
2609         return nsIProtocolHandler_GetProtocolFlags(This->nshandler, aProtocolFlags);
2610     return NS_ERROR_NOT_IMPLEMENTED;
2611 }
2612
2613 static nsresult NSAPI nsProtocolHandler_NewURI(nsIProtocolHandler *iface,
2614         const nsACString *aSpec, const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2615 {
2616     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2617
2618     TRACE("((%p)->%s %s %p %p)\n", This, debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset),
2619           aBaseURI, _retval);
2620
2621     if(This->nshandler)
2622         return nsIProtocolHandler_NewURI(This->nshandler, aSpec, aOriginCharset, aBaseURI, _retval);
2623     return NS_ERROR_NOT_IMPLEMENTED;
2624 }
2625
2626 static nsresult NSAPI nsProtocolHandler_NewChannel(nsIProtocolHandler *iface,
2627         nsIURI *aURI, nsIChannel **_retval)
2628 {
2629     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2630
2631     TRACE("(%p)->(%p %p)\n", This, aURI, _retval);
2632
2633     if(This->nshandler)
2634         return nsIProtocolHandler_NewChannel(This->nshandler, aURI, _retval);
2635     return NS_ERROR_NOT_IMPLEMENTED;
2636 }
2637
2638 static nsresult NSAPI nsProtocolHandler_AllowPort(nsIProtocolHandler *iface,
2639         PRInt32 port, const char *scheme, PRBool *_retval)
2640 {
2641     nsProtocolHandler *This = NSPROTHANDLER_THIS(iface);
2642
2643     TRACE("(%p)->(%d %s %p)\n", This, port, debugstr_a(scheme), _retval);
2644
2645     if(This->nshandler)
2646         return nsIProtocolHandler_AllowPort(This->nshandler, port, scheme, _retval);
2647     return NS_ERROR_NOT_IMPLEMENTED;
2648 }
2649
2650 #undef NSPROTHANDLER_THIS
2651
2652 static const nsIProtocolHandlerVtbl nsProtocolHandlerVtbl = {
2653     nsProtocolHandler_QueryInterface,
2654     nsProtocolHandler_AddRef,
2655     nsProtocolHandler_Release,
2656     nsProtocolHandler_GetScheme,
2657     nsProtocolHandler_GetDefaultPort,
2658     nsProtocolHandler_GetProtocolFlags,
2659     nsProtocolHandler_NewURI,
2660     nsProtocolHandler_NewChannel,
2661     nsProtocolHandler_AllowPort
2662 };
2663
2664 static nsIProtocolHandler *create_protocol_handler(nsIProtocolHandler *nshandler)
2665 {
2666     nsProtocolHandler *ret = heap_alloc(sizeof(nsProtocolHandler));
2667
2668     ret->lpProtocolHandlerVtbl = &nsProtocolHandlerVtbl;
2669     ret->ref = 1;
2670     ret->nshandler = nshandler;
2671
2672     return NSPROTHANDLER(ret);
2673 }
2674
2675 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService*,nsIIDRef,void**);
2676
2677 static nsrefcnt NSAPI nsIOService_AddRef(nsIIOService *iface)
2678 {
2679     return 2;
2680 }
2681
2682 static nsrefcnt NSAPI nsIOService_Release(nsIIOService *iface)
2683 {
2684     return 1;
2685 }
2686
2687 static nsresult NSAPI nsIOService_GetProtocolHandler(nsIIOService *iface, const char *aScheme,
2688                                                      nsIProtocolHandler **_retval)
2689 {
2690     nsIExternalProtocolHandler *nsexthandler;
2691     nsIProtocolHandler *nshandler;
2692     nsresult nsres;
2693
2694     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2695
2696     nsres = nsIIOService_GetProtocolHandler(nsio, aScheme, &nshandler);
2697     if(NS_FAILED(nsres)) {
2698         WARN("GetProtocolHandler failed: %08x\n", nsres);
2699         return nsres;
2700     }
2701
2702     nsres = nsIProtocolHandler_QueryInterface(nshandler, &IID_nsIExternalProtocolHandler,
2703                                               (void**)&nsexthandler);
2704     if(NS_FAILED(nsres)) {
2705         *_retval = nshandler;
2706         return NS_OK;
2707     }
2708
2709     nsIExternalProtocolHandler_Release(nsexthandler);
2710     *_retval = create_protocol_handler(nshandler);
2711     TRACE("return %p\n", *_retval);
2712     return NS_OK;
2713 }
2714
2715 static nsresult NSAPI nsIOService_GetProtocolFlags(nsIIOService *iface, const char *aScheme,
2716                                                     PRUint32 *_retval)
2717 {
2718     TRACE("(%s %p)\n", debugstr_a(aScheme), _retval);
2719     return nsIIOService_GetProtocolFlags(nsio, aScheme, _retval);
2720 }
2721
2722 static BOOL is_gecko_special_uri(const char *spec)
2723 {
2724     static const char *special_schemes[] = {"chrome:", "jar:", "resource:", "javascript:", "wyciwyg:"};
2725     int i;
2726
2727     for(i=0; i < sizeof(special_schemes)/sizeof(*special_schemes); i++) {
2728         if(!strncasecmp(spec, special_schemes[i], strlen(special_schemes[i])))
2729             return TRUE;
2730     }
2731
2732     if(!strncasecmp(spec, "file:", 5)) {
2733         const char *ptr = spec+5;
2734         while(*ptr == '/')
2735             ptr++;
2736         return is_gecko_path(ptr);
2737     }
2738
2739     return FALSE;
2740 }
2741
2742 static nsresult NSAPI nsIOService_NewURI(nsIIOService *iface, const nsACString *aSpec,
2743         const char *aOriginCharset, nsIURI *aBaseURI, nsIURI **_retval)
2744 {
2745     nsWineURI *wine_uri, *base_wine_uri = NULL;
2746     const char *spec = NULL;
2747     HTMLWindow *window = NULL;
2748     nsIURI *uri = NULL;
2749     LPCWSTR base_wine_url = NULL;
2750     nsACString spec_str;
2751     nsresult nsres;
2752
2753
2754     TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset),
2755           aBaseURI, _retval);
2756
2757     nsACString_GetData(aSpec, &spec);
2758     if(is_gecko_special_uri(spec))
2759         return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2760
2761     if(!strncmp(spec, "wine:", 5))
2762         spec += 5;
2763
2764     if(aBaseURI) {
2765         PARSEDURLA parsed_url = {sizeof(PARSEDURLA)};
2766
2767         nsres = nsIURI_QueryInterface(aBaseURI, &IID_nsWineURI, (void**)&base_wine_uri);
2768         if(NS_SUCCEEDED(nsres)) {
2769             base_wine_url = base_wine_uri->wine_url;
2770             if(base_wine_uri->window_ref && base_wine_uri->window_ref->window) {
2771                 window = base_wine_uri->window_ref->window;
2772                 IHTMLWindow2_AddRef(HTMLWINDOW2(window));
2773             }
2774             TRACE("base url: %s window: %p\n", debugstr_w(base_wine_url), window);
2775         }else if(FAILED(ParseURLA(spec, &parsed_url))) {
2776             TRACE("not wraping\n");
2777             return nsIIOService_NewURI(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2778         }else {
2779             WARN("Could not get base nsWineURI: %08x\n", nsres);
2780         }
2781     }
2782
2783     nsACString_InitDepend(&spec_str, spec);
2784     nsres = nsIIOService_NewURI(nsio, &spec_str, aOriginCharset, aBaseURI, &uri);
2785     nsACString_Finish(&spec_str);
2786     if(NS_FAILED(nsres))
2787         TRACE("NewURI failed: %08x\n", nsres);
2788
2789     nsres = create_uri(uri, window, NULL, &wine_uri);
2790     *_retval = (nsIURI*)wine_uri;
2791
2792     if(window)
2793         IHTMLWindow2_Release(HTMLWINDOW2(window));
2794
2795     if(base_wine_url) {
2796         WCHAR url[INTERNET_MAX_URL_LENGTH], rel_url[INTERNET_MAX_URL_LENGTH];
2797         DWORD len;
2798         HRESULT hres;
2799
2800         MultiByteToWideChar(CP_ACP, 0, spec, -1, rel_url, sizeof(rel_url)/sizeof(WCHAR));
2801
2802         hres = CoInternetCombineUrl(base_wine_url, rel_url,
2803                                     URL_ESCAPE_SPACES_ONLY|URL_DONT_ESCAPE_EXTRA_INFO,
2804                                     url, sizeof(url)/sizeof(WCHAR), &len, 0);
2805         if(SUCCEEDED(hres))
2806             set_wine_url(wine_uri, url);
2807         else
2808              WARN("CoCombineUrl failed: %08x\n", hres);
2809     }else {
2810         WCHAR url[INTERNET_MAX_URL_LENGTH];
2811
2812         MultiByteToWideChar(CP_ACP, 0, spec, -1, url, sizeof(url)/sizeof(WCHAR));
2813         set_wine_url(wine_uri, url);
2814     }
2815
2816     if(base_wine_uri)
2817         nsIURI_Release(NSURI(base_wine_uri));
2818
2819     return nsres;
2820 }
2821
2822 static nsresult NSAPI nsIOService_NewFileURI(nsIIOService *iface, nsIFile *aFile,
2823                                              nsIURI **_retval)
2824 {
2825     TRACE("(%p %p)\n", aFile, _retval);
2826     return nsIIOService_NewFileURI(nsio, aFile, _retval);
2827 }
2828
2829 static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI *aURI,
2830                                                      nsIChannel **_retval)
2831 {
2832     PARSEDURLW parsed_url = {sizeof(PARSEDURLW)};
2833     nsChannel *ret;
2834     nsWineURI *wine_uri;
2835     nsresult nsres;
2836
2837     TRACE("(%p %p)\n", aURI, _retval);
2838
2839     nsres = nsIURI_QueryInterface(aURI, &IID_nsWineURI, (void**)&wine_uri);
2840     if(NS_FAILED(nsres)) {
2841         TRACE("Could not get nsWineURI: %08x\n", nsres);
2842         return nsIIOService_NewChannelFromURI(nsio, aURI, _retval);
2843     }
2844
2845     ret = heap_alloc_zero(sizeof(nsChannel));
2846
2847     ret->lpHttpChannelVtbl = &nsChannelVtbl;
2848     ret->lpUploadChannelVtbl = &nsUploadChannelVtbl;
2849     ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl;
2850     ret->ref = 1;
2851     ret->uri = wine_uri;
2852     ret->request_method = METHOD_GET;
2853     list_init(&ret->response_headers);
2854     list_init(&ret->request_headers);
2855
2856     nsIURI_AddRef(aURI);
2857     ret->original_uri = aURI;
2858     ret->url_scheme = wine_uri->wine_url && SUCCEEDED(ParseURLW(wine_uri->wine_url, &parsed_url))
2859         ? parsed_url.nScheme : URL_SCHEME_UNKNOWN;
2860
2861     *_retval = NSCHANNEL(ret);
2862     return NS_OK;
2863 }
2864
2865 static nsresult NSAPI nsIOService_NewChannel(nsIIOService *iface, const nsACString *aSpec,
2866         const char *aOriginCharset, nsIURI *aBaseURI, nsIChannel **_retval)
2867 {
2868     TRACE("(%s %s %p %p)\n", debugstr_nsacstr(aSpec), debugstr_a(aOriginCharset), aBaseURI, _retval);
2869     return nsIIOService_NewChannel(nsio, aSpec, aOriginCharset, aBaseURI, _retval);
2870 }
2871
2872 static nsresult NSAPI nsIOService_GetOffline(nsIIOService *iface, PRBool *aOffline)
2873 {
2874     TRACE("(%p)\n", aOffline);
2875     return nsIIOService_GetOffline(nsio, aOffline);
2876 }
2877
2878 static nsresult NSAPI nsIOService_SetOffline(nsIIOService *iface, PRBool aOffline)
2879 {
2880     TRACE("(%x)\n", aOffline);
2881     return nsIIOService_SetOffline(nsio, aOffline);
2882 }
2883
2884 static nsresult NSAPI nsIOService_AllowPort(nsIIOService *iface, PRInt32 aPort,
2885                                              const char *aScheme, PRBool *_retval)
2886 {
2887     TRACE("(%d %s %p)\n", aPort, debugstr_a(aScheme), _retval);
2888     return nsIIOService_AllowPort(nsio, aPort, debugstr_a(aScheme), _retval);
2889 }
2890
2891 static nsresult NSAPI nsIOService_ExtractScheme(nsIIOService *iface, const nsACString *urlString,
2892                                                  nsACString * _retval)
2893 {
2894     TRACE("(%s %p)\n", debugstr_nsacstr(urlString), _retval);
2895     return nsIIOService_ExtractScheme(nsio, urlString, _retval);
2896 }
2897
2898 static const nsIIOServiceVtbl nsIOServiceVtbl = {
2899     nsIOService_QueryInterface,
2900     nsIOService_AddRef,
2901     nsIOService_Release,
2902     nsIOService_GetProtocolHandler,
2903     nsIOService_GetProtocolFlags,
2904     nsIOService_NewURI,
2905     nsIOService_NewFileURI,
2906     nsIOService_NewChannelFromURI,
2907     nsIOService_NewChannel,
2908     nsIOService_GetOffline,
2909     nsIOService_SetOffline,
2910     nsIOService_AllowPort,
2911     nsIOService_ExtractScheme
2912 };
2913
2914 static nsIIOService nsIOService = { &nsIOServiceVtbl };
2915
2916 static nsresult NSAPI nsNetUtil_QueryInterface(nsINetUtil *iface, nsIIDRef riid,
2917         void **result)
2918 {
2919     return nsIIOService_QueryInterface(&nsIOService, riid, result);
2920 }
2921
2922 static nsrefcnt NSAPI nsNetUtil_AddRef(nsINetUtil *iface)
2923 {
2924     return 2;
2925 }
2926
2927 static nsrefcnt NSAPI nsNetUtil_Release(nsINetUtil *iface)
2928 {
2929     return 1;
2930 }
2931
2932 static nsresult NSAPI nsNetUtil_ParseContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2933         nsACString *aCharset, PRBool *aHadCharset, nsACString *aContentType)
2934 {
2935     TRACE("(%s %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aHadCharset, aContentType);
2936
2937     return nsINetUtil_ParseContentType(net_util, aTypeHeader, aCharset, aHadCharset, aContentType);
2938 }
2939
2940 static nsresult NSAPI nsNetUtil_ProtocolHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2941 {
2942     TRACE("()\n");
2943
2944     return nsINetUtil_ProtocolHasFlags(net_util, aURI, aFlags, _retval);
2945 }
2946
2947 static nsresult NSAPI nsNetUtil_URIChainHasFlags(nsINetUtil *iface, nsIURI *aURI, PRUint32 aFlags, PRBool *_retval)
2948 {
2949     TRACE("(%p %08x %p)\n", aURI, aFlags, _retval);
2950
2951     if(aFlags == (1<<11)) {
2952         *_retval = FALSE;
2953         return NS_OK;
2954     }
2955
2956     return nsINetUtil_URIChainHasFlags(net_util, aURI, aFlags, _retval);
2957 }
2958
2959 static nsresult NSAPI nsNetUtil_ToImmutableURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2960 {
2961     TRACE("(%p %p)\n", aURI, _retval);
2962
2963     return nsINetUtil_ToImmutableURI(net_util, aURI, _retval);
2964 }
2965
2966 static nsresult NSAPI nsNetUtil_NewSimpleNestedURI(nsINetUtil *iface, nsIURI *aURI, nsIURI **_retval)
2967 {
2968     TRACE("(%p %p)\n", aURI, _retval);
2969
2970     return nsINetUtil_NewSimpleNestedURI(net_util, aURI, _retval);
2971 }
2972
2973 static nsresult NSAPI nsNetUtil_EscapeString(nsINetUtil *iface, const nsACString *aString,
2974                                              PRUint32 aEscapeType, nsACString *_retval)
2975 {
2976     TRACE("(%s %x %p)\n", debugstr_nsacstr(aString), aEscapeType, _retval);
2977
2978     return nsINetUtil_EscapeString(net_util, aString, aEscapeType, _retval);
2979 }
2980
2981 static nsresult NSAPI nsNetUtil_EscapeURL(nsINetUtil *iface, const nsACString *aStr, PRUint32 aFlags,
2982                                           nsACString *_retval)
2983 {
2984     TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval);
2985
2986     return nsINetUtil_EscapeURL(net_util, aStr, aFlags, _retval);
2987 }
2988
2989 static nsresult NSAPI nsNetUtil_UnescapeString(nsINetUtil *iface, const nsACString *aStr,
2990                                                PRUint32 aFlags, nsACString *_retval)
2991 {
2992     TRACE("(%s %08x %p)\n", debugstr_nsacstr(aStr), aFlags, _retval);
2993
2994     return nsINetUtil_UnescapeString(net_util, aStr, aFlags, _retval);
2995 }
2996
2997 static nsresult NSAPI nsNetUtil_ExtractCharsetFromContentType(nsINetUtil *iface, const nsACString *aTypeHeader,
2998         nsACString *aCharset, PRInt32 *aCharsetStart, PRInt32 *aCharsetEnd, PRBool *_retval)
2999 {
3000     TRACE("(%s %p %p %p %p)\n", debugstr_nsacstr(aTypeHeader), aCharset, aCharsetStart,
3001           aCharsetEnd, _retval);
3002
3003     return nsINetUtil_ExtractCharsetFromContentType(net_util, aTypeHeader, aCharset, aCharsetStart, aCharsetEnd, _retval);
3004 }
3005
3006 static const nsINetUtilVtbl nsNetUtilVtbl = {
3007     nsNetUtil_QueryInterface,
3008     nsNetUtil_AddRef,
3009     nsNetUtil_Release,
3010     nsNetUtil_ParseContentType,
3011     nsNetUtil_ProtocolHasFlags,
3012     nsNetUtil_URIChainHasFlags,
3013     nsNetUtil_ToImmutableURI,
3014     nsNetUtil_NewSimpleNestedURI,
3015     nsNetUtil_EscapeString,
3016     nsNetUtil_EscapeURL,
3017     nsNetUtil_UnescapeString,
3018     nsNetUtil_ExtractCharsetFromContentType
3019 };
3020
3021 static nsINetUtil nsNetUtil = { &nsNetUtilVtbl };
3022
3023 static nsresult NSAPI nsIOService_QueryInterface(nsIIOService *iface, nsIIDRef riid,
3024         void **result)
3025 {
3026     *result = NULL;
3027
3028     if(IsEqualGUID(&IID_nsISupports, riid))
3029         *result = &nsIOService;
3030     else if(IsEqualGUID(&IID_nsIIOService, riid))
3031         *result = &nsIOService;
3032     else if(IsEqualGUID(&IID_nsINetUtil, riid))
3033         *result = &nsNetUtil;
3034
3035     if(*result) {
3036         nsISupports_AddRef((nsISupports*)*result);
3037         return NS_OK;
3038     }
3039
3040     FIXME("(%s %p)\n", debugstr_guid(riid), result);
3041     return NS_NOINTERFACE;
3042 }
3043
3044 static nsresult NSAPI nsIOServiceFactory_QueryInterface(nsIFactory *iface, nsIIDRef riid,
3045         void **result)
3046 {
3047     *result = NULL;
3048
3049     if(IsEqualGUID(&IID_nsISupports, riid)) {
3050         TRACE("(IID_nsISupports %p)\n", result);
3051         *result = iface;
3052     }else if(IsEqualGUID(&IID_nsIFactory, riid)) {
3053         TRACE("(IID_nsIFactory %p)\n", result);
3054         *result = iface;
3055     }
3056
3057     if(*result) {
3058         nsIFactory_AddRef(iface);
3059         return NS_OK;
3060     }
3061
3062     WARN("(%s %p)\n", debugstr_guid(riid), result);
3063     return NS_NOINTERFACE;
3064 }
3065
3066 static nsrefcnt NSAPI nsIOServiceFactory_AddRef(nsIFactory *iface)
3067 {
3068     return 2;
3069 }
3070
3071 static nsrefcnt NSAPI nsIOServiceFactory_Release(nsIFactory *iface)
3072 {
3073     return 1;
3074 }
3075
3076 static nsresult NSAPI nsIOServiceFactory_CreateInstance(nsIFactory *iface,
3077         nsISupports *aOuter, const nsIID *iid, void **result)
3078 {
3079     return nsIIOService_QueryInterface(&nsIOService, iid, result);
3080 }
3081
3082 static nsresult NSAPI nsIOServiceFactory_LockFactory(nsIFactory *iface, PRBool lock)
3083 {
3084     WARN("(%x)\n", lock);
3085     return NS_OK;
3086 }
3087
3088 static const nsIFactoryVtbl nsIOServiceFactoryVtbl = {
3089     nsIOServiceFactory_QueryInterface,
3090     nsIOServiceFactory_AddRef,
3091     nsIOServiceFactory_Release,
3092     nsIOServiceFactory_CreateInstance,
3093     nsIOServiceFactory_LockFactory
3094 };
3095
3096 static nsIFactory nsIOServiceFactory = { &nsIOServiceFactoryVtbl };
3097
3098 void init_nsio(nsIComponentManager *component_manager, nsIComponentRegistrar *registrar)
3099 {
3100     nsIFactory *old_factory = NULL;
3101     nsresult nsres;
3102
3103     nsres = nsIComponentManager_GetClassObject(component_manager, &NS_IOSERVICE_CID,
3104                                                &IID_nsIFactory, (void**)&old_factory);
3105     if(NS_FAILED(nsres)) {
3106         ERR("Could not get factory: %08x\n", nsres);
3107         return;
3108     }
3109
3110     nsres = nsIFactory_CreateInstance(old_factory, NULL, &IID_nsIIOService, (void**)&nsio);
3111     if(NS_FAILED(nsres)) {
3112         ERR("Couldn not create nsIOService instance %08x\n", nsres);
3113         nsIFactory_Release(old_factory);
3114         return;
3115     }
3116
3117     nsres = nsIIOService_QueryInterface(nsio, &IID_nsINetUtil, (void**)&net_util);
3118     if(NS_FAILED(nsres)) {
3119         WARN("Could not get nsINetUtil interface: %08x\n", nsres);
3120         nsIIOService_Release(nsio);
3121         return;
3122     }
3123
3124     nsres = nsIComponentRegistrar_UnregisterFactory(registrar, &NS_IOSERVICE_CID, old_factory);
3125     nsIFactory_Release(old_factory);
3126     if(NS_FAILED(nsres))
3127         ERR("UnregisterFactory failed: %08x\n", nsres);
3128
3129     nsres = nsIComponentRegistrar_RegisterFactory(registrar, &NS_IOSERVICE_CID,
3130             NS_IOSERVICE_CLASSNAME, NS_IOSERVICE_CONTRACTID, &nsIOServiceFactory);
3131     if(NS_FAILED(nsres))
3132         ERR("RegisterFactory failed: %08x\n", nsres);
3133 }
3134
3135 void release_nsio(void)
3136 {
3137     if(net_util) {
3138         nsINetUtil_Release(net_util);
3139         net_util = NULL;
3140     }
3141
3142     if(nsio) {
3143         nsIIOService_Release(nsio);
3144         nsio = NULL;
3145     }
3146 }