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