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