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