2 * Copyright 2008 Jacek Caban for CodeWeavers
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.
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.
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
31 #include "wine/debug.h"
33 #include "mshtml_private.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml
);
39 static IUri
*get_uri(HTMLLocation
*This
)
41 return This
->window
->uri
;
44 static HRESULT
get_url_components(HTMLLocation
*This
, URL_COMPONENTSW
*url
)
46 const WCHAR
*doc_url
= This
->window
->url
? This
->window
->url
: L
"about:blank";
48 if(!InternetCrackUrlW(doc_url
, 0, 0, url
)) {
49 FIXME("InternetCrackUrlW failed: 0x%08lx\n", GetLastError());
57 static inline HTMLLocation
*impl_from_IHTMLLocation(IHTMLLocation
*iface
)
59 return CONTAINING_RECORD(iface
, HTMLLocation
, IHTMLLocation_iface
);
62 static HRESULT WINAPI
HTMLLocation_QueryInterface(IHTMLLocation
*iface
, REFIID riid
, void **ppv
)
64 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
65 return IDispatchEx_QueryInterface(&This
->dispex
.IDispatchEx_iface
, riid
, ppv
);
68 static ULONG WINAPI
HTMLLocation_AddRef(IHTMLLocation
*iface
)
70 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
71 return IDispatchEx_AddRef(&This
->dispex
.IDispatchEx_iface
);
74 static ULONG WINAPI
HTMLLocation_Release(IHTMLLocation
*iface
)
76 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
77 return IDispatchEx_Release(&This
->dispex
.IDispatchEx_iface
);
80 static HRESULT WINAPI
HTMLLocation_GetTypeInfoCount(IHTMLLocation
*iface
, UINT
*pctinfo
)
82 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
83 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
86 static HRESULT WINAPI
HTMLLocation_GetTypeInfo(IHTMLLocation
*iface
, UINT iTInfo
,
87 LCID lcid
, ITypeInfo
**ppTInfo
)
89 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
90 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
93 static HRESULT WINAPI
HTMLLocation_GetIDsOfNames(IHTMLLocation
*iface
, REFIID riid
,
94 LPOLESTR
*rgszNames
, UINT cNames
,
95 LCID lcid
, DISPID
*rgDispId
)
97 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
98 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
102 static HRESULT WINAPI
HTMLLocation_Invoke(IHTMLLocation
*iface
, DISPID dispIdMember
,
103 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
104 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
106 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
107 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
108 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
111 static HRESULT WINAPI
HTMLLocation_put_href(IHTMLLocation
*iface
, BSTR v
)
113 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
115 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
117 return navigate_url(This
->window
, v
, get_uri(This
), BINDING_NAVIGATED
);
120 static HRESULT WINAPI
HTMLLocation_get_href(IHTMLLocation
*iface
, BSTR
*p
)
122 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
123 URL_COMPONENTSW url
= {sizeof(URL_COMPONENTSW
)};
124 WCHAR
*buf
= NULL
, *url_path
= NULL
;
129 TRACE("(%p)->(%p)\n", This
, p
);
134 url
.dwSchemeLength
= 1;
135 url
.dwHostNameLength
= 1;
136 url
.dwUrlPathLength
= 1;
137 url
.dwExtraInfoLength
= 1;
138 hres
= get_url_components(This
, &url
);
142 switch(url
.nScheme
) {
143 case INTERNET_SCHEME_FILE
:
145 /* prepend a slash */
146 url_path
= malloc((url
.dwUrlPathLength
+ 1) * sizeof(WCHAR
));
148 return E_OUTOFMEMORY
;
150 memcpy(url_path
+ 1, url
.lpszUrlPath
, url
.dwUrlPathLength
* sizeof(WCHAR
));
151 url
.lpszUrlPath
= url_path
;
152 url
.dwUrlPathLength
= url
.dwUrlPathLength
+ 1;
156 case INTERNET_SCHEME_HTTP
:
157 case INTERNET_SCHEME_HTTPS
:
158 case INTERNET_SCHEME_FTP
:
159 if(!url
.dwUrlPathLength
) {
160 /* add a slash if it's blank */
161 url_path
= url
.lpszUrlPath
= malloc(sizeof(WCHAR
));
163 return E_OUTOFMEMORY
;
164 url
.lpszUrlPath
[0] = '/';
165 url
.dwUrlPathLength
= 1;
173 /* replace \ with / */
174 for(i
= 0; i
< url
.dwUrlPathLength
; ++i
)
175 if(url
.lpszUrlPath
[i
] == '\\')
176 url
.lpszUrlPath
[i
] = '/';
178 if(InternetCreateUrlW(&url
, ICU_ESCAPE
, NULL
, &len
)) {
179 FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
184 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER
) {
185 FIXME("InternetCreateUrl failed with error: %08lx\n", GetLastError());
192 buf
= malloc(len
* sizeof(WCHAR
));
198 if(!InternetCreateUrlW(&url
, ICU_ESCAPE
, buf
, &len
)) {
199 FIXME("InternetCreateUrl failed with error: %08lx\n", GetLastError());
205 *p
= SysAllocStringLen(buf
, len
);
220 static HRESULT WINAPI
HTMLLocation_put_protocol(IHTMLLocation
*iface
, BSTR v
)
222 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
223 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
227 static HRESULT WINAPI
HTMLLocation_get_protocol(IHTMLLocation
*iface
, BSTR
*p
)
229 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
235 TRACE("(%p)->(%p)\n", This
, p
);
240 if(!(uri
= get_uri(This
)))
241 return (*p
= SysAllocString(L
"about:")) ? S_OK
: E_OUTOFMEMORY
;
243 hres
= IUri_GetSchemeName(uri
, &protocol
);
246 if(hres
== S_FALSE
) {
247 SysFreeString(protocol
);
252 len
= SysStringLen(protocol
);
253 ret
= SysAllocStringLen(protocol
, len
+1);
254 SysFreeString(protocol
);
256 return E_OUTOFMEMORY
;
263 static HRESULT WINAPI
HTMLLocation_put_host(IHTMLLocation
*iface
, BSTR v
)
265 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
266 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
270 static HRESULT WINAPI
HTMLLocation_get_host(IHTMLLocation
*iface
, BSTR
*p
)
272 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
273 URL_COMPONENTSW url
= {sizeof(URL_COMPONENTSW
)};
276 TRACE("(%p)->(%p)\n", This
, p
);
281 url
.dwHostNameLength
= 1;
282 hres
= get_url_components(This
, &url
);
286 if(!url
.dwHostNameLength
){
292 /* <hostname>:<port> */
297 port_len
= swprintf(portW
, ARRAY_SIZE(portW
), L
"%u", url
.nPort
);
298 len
= url
.dwHostNameLength
+ 1 /* ':' */ + port_len
;
299 buf
= *p
= SysAllocStringLen(NULL
, len
);
300 memcpy(buf
, url
.lpszHostName
, url
.dwHostNameLength
* sizeof(WCHAR
));
301 buf
[url
.dwHostNameLength
] = ':';
302 memcpy(buf
+ url
.dwHostNameLength
+ 1, portW
, port_len
* sizeof(WCHAR
));
304 *p
= SysAllocStringLen(url
.lpszHostName
, url
.dwHostNameLength
);
307 return E_OUTOFMEMORY
;
311 static HRESULT WINAPI
HTMLLocation_put_hostname(IHTMLLocation
*iface
, BSTR v
)
313 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
314 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
318 static HRESULT WINAPI
HTMLLocation_get_hostname(IHTMLLocation
*iface
, BSTR
*p
)
320 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
325 TRACE("(%p)->(%p)\n", This
, p
);
330 if(!(uri
= get_uri(This
))) {
335 hres
= IUri_GetHost(uri
, &hostname
);
338 }else if(hres
== S_FALSE
) {
339 SysFreeString(hostname
);
348 static HRESULT WINAPI
HTMLLocation_put_port(IHTMLLocation
*iface
, BSTR v
)
350 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
351 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
355 static HRESULT WINAPI
HTMLLocation_get_port(IHTMLLocation
*iface
, BSTR
*p
)
357 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
362 TRACE("(%p)->(%p)\n", This
, p
);
367 if(!(uri
= get_uri(This
))) {
372 hres
= IUri_GetPort(uri
, &port
);
379 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", port
);
380 *p
= SysAllocString(buf
);
382 *p
= SysAllocStringLen(NULL
, 0);
386 return E_OUTOFMEMORY
;
390 static HRESULT WINAPI
HTMLLocation_put_pathname(IHTMLLocation
*iface
, BSTR v
)
392 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
393 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
397 static HRESULT WINAPI
HTMLLocation_get_pathname(IHTMLLocation
*iface
, BSTR
*p
)
399 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
404 TRACE("(%p)->(%p)\n", This
, p
);
409 if(!(uri
= get_uri(This
)))
410 return (*p
= SysAllocString(L
"blank")) ? S_OK
: E_OUTOFMEMORY
;
412 hres
= IUri_GetPath(uri
, &path
);
416 if(hres
== S_FALSE
) {
425 static HRESULT WINAPI
HTMLLocation_put_search(IHTMLLocation
*iface
, BSTR v
)
427 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
428 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
432 static HRESULT WINAPI
HTMLLocation_get_search(IHTMLLocation
*iface
, BSTR
*p
)
434 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
439 TRACE("(%p)->(%p)\n", This
, p
);
444 if(!(uri
= get_uri(This
))) {
449 hres
= IUri_GetQuery(uri
, &query
);
452 }else if(hres
== S_FALSE
) {
453 SysFreeString(query
);
462 static HRESULT WINAPI
HTMLLocation_put_hash(IHTMLLocation
*iface
, BSTR v
)
464 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
468 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
471 unsigned size
= (1 /* # */ + wcslen(v
) + 1) * sizeof(WCHAR
);
472 if(!(hash
= malloc(size
)))
473 return E_OUTOFMEMORY
;
475 memcpy(hash
+ 1, v
, size
- sizeof(WCHAR
));
478 hres
= navigate_url(This
->window
, hash
, get_uri(This
), BINDING_NAVIGATED
);
485 static HRESULT WINAPI
HTMLLocation_get_hash(IHTMLLocation
*iface
, BSTR
*p
)
487 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
492 TRACE("(%p)->(%p)\n", This
, p
);
497 if(!(uri
= get_uri(This
))) {
502 hres
= IUri_GetFragment(uri
, &hash
);
505 }else if(hres
== S_FALSE
) {
515 static HRESULT WINAPI
HTMLLocation_reload(IHTMLLocation
*iface
, VARIANT_BOOL flag
)
517 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
519 TRACE("(%p)->(%x)\n", This
, flag
);
521 /* reload is supposed to fail if called from a script with different origin, but IE doesn't care */
522 if(!is_main_content_window(This
->window
)) {
523 FIXME("Unsupported on iframe\n");
527 return reload_page(This
->window
);
530 static HRESULT WINAPI
HTMLLocation_replace(IHTMLLocation
*iface
, BSTR bstr
)
532 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
534 TRACE("(%p)->(%s)\n", This
, debugstr_w(bstr
));
536 return navigate_url(This
->window
, bstr
, get_uri(This
), BINDING_NAVIGATED
| BINDING_REPLACE
);
539 static HRESULT WINAPI
HTMLLocation_assign(IHTMLLocation
*iface
, BSTR bstr
)
541 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
542 TRACE("(%p)->(%s)\n", This
, debugstr_w(bstr
));
543 return IHTMLLocation_put_href(iface
, bstr
);
546 static HRESULT WINAPI
HTMLLocation_toString(IHTMLLocation
*iface
, BSTR
*String
)
548 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
550 TRACE("(%p)->(%p)\n", This
, String
);
552 return IHTMLLocation_get_href(&This
->IHTMLLocation_iface
, String
);
555 static const IHTMLLocationVtbl HTMLLocationVtbl
= {
556 HTMLLocation_QueryInterface
,
558 HTMLLocation_Release
,
559 HTMLLocation_GetTypeInfoCount
,
560 HTMLLocation_GetTypeInfo
,
561 HTMLLocation_GetIDsOfNames
,
563 HTMLLocation_put_href
,
564 HTMLLocation_get_href
,
565 HTMLLocation_put_protocol
,
566 HTMLLocation_get_protocol
,
567 HTMLLocation_put_host
,
568 HTMLLocation_get_host
,
569 HTMLLocation_put_hostname
,
570 HTMLLocation_get_hostname
,
571 HTMLLocation_put_port
,
572 HTMLLocation_get_port
,
573 HTMLLocation_put_pathname
,
574 HTMLLocation_get_pathname
,
575 HTMLLocation_put_search
,
576 HTMLLocation_get_search
,
577 HTMLLocation_put_hash
,
578 HTMLLocation_get_hash
,
580 HTMLLocation_replace
,
582 HTMLLocation_toString
585 static inline HTMLLocation
*impl_from_DispatchEx(DispatchEx
*iface
)
587 return CONTAINING_RECORD(iface
, HTMLLocation
, dispex
);
590 static void *HTMLLocation_query_interface(DispatchEx
*dispex
, REFIID riid
)
592 HTMLLocation
*This
= impl_from_DispatchEx(dispex
);
594 if(IsEqualGUID(&IID_IHTMLLocation
, riid
))
595 return &This
->IHTMLLocation_iface
;
596 if(IsEqualGUID(&IID_IMarshal
, riid
)) {
597 FIXME("(%p)->(IID_IMarshal)\n", This
);
604 static void HTMLLocation_traverse(DispatchEx
*dispex
, nsCycleCollectionTraversalCallback
*cb
)
606 HTMLLocation
*This
= impl_from_DispatchEx(dispex
);
608 note_cc_edge((nsISupports
*)&This
->window
->base
.IHTMLWindow2_iface
, "window", cb
);
611 static void HTMLLocation_unlink(DispatchEx
*dispex
)
613 HTMLLocation
*This
= impl_from_DispatchEx(dispex
);
615 HTMLOuterWindow
*window
= This
->window
;
617 IHTMLWindow2_Release(&window
->base
.IHTMLWindow2_iface
);
621 static void HTMLLocation_destructor(DispatchEx
*dispex
)
623 HTMLLocation
*This
= impl_from_DispatchEx(dispex
);
627 static const dispex_static_data_vtbl_t HTMLLocation_dispex_vtbl
= {
628 .query_interface
= HTMLLocation_query_interface
,
629 .destructor
= HTMLLocation_destructor
,
630 .traverse
= HTMLLocation_traverse
,
631 .unlink
= HTMLLocation_unlink
634 static const tid_t HTMLLocation_iface_tids
[] = {
638 static dispex_static_data_t HTMLLocation_dispex
= {
640 &HTMLLocation_dispex_vtbl
,
641 DispHTMLLocation_tid
,
642 HTMLLocation_iface_tids
645 HRESULT
create_location(HTMLOuterWindow
*window
, HTMLLocation
**ret
)
647 HTMLLocation
*location
;
649 if(!(location
= calloc(1, sizeof(*location
))))
650 return E_OUTOFMEMORY
;
652 location
->IHTMLLocation_iface
.lpVtbl
= &HTMLLocationVtbl
;
653 location
->window
= window
;
654 IHTMLWindow2_AddRef(&window
->base
.IHTMLWindow2_iface
);
656 init_dispatch(&location
->dispex
, &HTMLLocation_dispex
, COMPAT_MODE_QUIRKS
);