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