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
19 #include "mshtml_private.h"
21 static HRESULT
get_url(HTMLLocation
*This
, const WCHAR
**ret
)
23 if(!This
->window
|| !This
->window
->base
.outer_window
|| !This
->window
->base
.outer_window
->url
) {
24 FIXME("No current URL\n");
28 *ret
= This
->window
->base
.outer_window
->url
;
32 static IUri
*get_uri(HTMLLocation
*This
)
34 if(!This
->window
|| !This
->window
->base
.outer_window
)
36 return This
->window
->base
.outer_window
->uri
;
39 static HRESULT
get_url_components(HTMLLocation
*This
, URL_COMPONENTSW
*url
)
44 hres
= get_url(This
, &doc_url
);
48 if(!InternetCrackUrlW(doc_url
, 0, 0, url
)) {
49 FIXME("InternetCrackUrlW failed: 0x%08x\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
);
66 TRACE("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
68 if(IsEqualGUID(&IID_IUnknown
, riid
)) {
69 *ppv
= &This
->IHTMLLocation_iface
;
70 }else if(IsEqualGUID(&IID_IHTMLLocation
, riid
)) {
71 *ppv
= &This
->IHTMLLocation_iface
;
72 }else if(dispex_query_interface(&This
->dispex
, riid
, ppv
)) {
73 return *ppv
? S_OK
: E_NOINTERFACE
;
76 WARN("(%p)->(%s %p)\n", This
, debugstr_mshtml_guid(riid
), ppv
);
80 IUnknown_AddRef((IUnknown
*)*ppv
);
84 static ULONG WINAPI
HTMLLocation_AddRef(IHTMLLocation
*iface
)
86 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
87 LONG ref
= InterlockedIncrement(&This
->ref
);
89 TRACE("(%p) ref=%d\n", This
, ref
);
94 static ULONG WINAPI
HTMLLocation_Release(IHTMLLocation
*iface
)
96 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
97 LONG ref
= InterlockedDecrement(&This
->ref
);
99 TRACE("(%p) ref=%d\n", This
, ref
);
103 This
->window
->location
= NULL
;
104 release_dispex(&This
->dispex
);
111 static HRESULT WINAPI
HTMLLocation_GetTypeInfoCount(IHTMLLocation
*iface
, UINT
*pctinfo
)
113 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
114 return IDispatchEx_GetTypeInfoCount(&This
->dispex
.IDispatchEx_iface
, pctinfo
);
117 static HRESULT WINAPI
HTMLLocation_GetTypeInfo(IHTMLLocation
*iface
, UINT iTInfo
,
118 LCID lcid
, ITypeInfo
**ppTInfo
)
120 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
121 return IDispatchEx_GetTypeInfo(&This
->dispex
.IDispatchEx_iface
, iTInfo
, lcid
, ppTInfo
);
124 static HRESULT WINAPI
HTMLLocation_GetIDsOfNames(IHTMLLocation
*iface
, REFIID riid
,
125 LPOLESTR
*rgszNames
, UINT cNames
,
126 LCID lcid
, DISPID
*rgDispId
)
128 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
129 return IDispatchEx_GetIDsOfNames(&This
->dispex
.IDispatchEx_iface
, riid
, rgszNames
, cNames
,
133 static HRESULT WINAPI
HTMLLocation_Invoke(IHTMLLocation
*iface
, DISPID dispIdMember
,
134 REFIID riid
, LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
,
135 VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
, UINT
*puArgErr
)
137 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
138 return IDispatchEx_Invoke(&This
->dispex
.IDispatchEx_iface
, dispIdMember
, riid
, lcid
,
139 wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
142 static HRESULT WINAPI
HTMLLocation_put_href(IHTMLLocation
*iface
, BSTR v
)
144 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
146 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
148 if(!This
->window
|| !This
->window
->base
.outer_window
) {
149 FIXME("No window available\n");
153 return navigate_url(This
->window
->base
.outer_window
, v
, This
->window
->base
.outer_window
->uri
, BINDING_NAVIGATED
);
156 static HRESULT WINAPI
HTMLLocation_get_href(IHTMLLocation
*iface
, BSTR
*p
)
158 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
159 URL_COMPONENTSW url
= {sizeof(URL_COMPONENTSW
)};
160 WCHAR
*buf
= NULL
, *url_path
= NULL
;
165 TRACE("(%p)->(%p)\n", This
, p
);
170 url
.dwSchemeLength
= 1;
171 url
.dwHostNameLength
= 1;
172 url
.dwUrlPathLength
= 1;
173 url
.dwExtraInfoLength
= 1;
174 hres
= get_url_components(This
, &url
);
178 switch(url
.nScheme
) {
179 case INTERNET_SCHEME_FILE
:
181 /* prepend a slash */
182 url_path
= HeapAlloc(GetProcessHeap(), 0, (url
.dwUrlPathLength
+ 1) * sizeof(WCHAR
));
184 return E_OUTOFMEMORY
;
186 memcpy(url_path
+ 1, url
.lpszUrlPath
, url
.dwUrlPathLength
* sizeof(WCHAR
));
187 url
.lpszUrlPath
= url_path
;
188 url
.dwUrlPathLength
= url
.dwUrlPathLength
+ 1;
192 case INTERNET_SCHEME_HTTP
:
193 case INTERNET_SCHEME_HTTPS
:
194 case INTERNET_SCHEME_FTP
:
195 if(!url
.dwUrlPathLength
) {
196 /* add a slash if it's blank */
197 url_path
= url
.lpszUrlPath
= HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR
));
199 return E_OUTOFMEMORY
;
200 url
.lpszUrlPath
[0] = '/';
201 url
.dwUrlPathLength
= 1;
209 /* replace \ with / */
210 for(i
= 0; i
< url
.dwUrlPathLength
; ++i
)
211 if(url
.lpszUrlPath
[i
] == '\\')
212 url
.lpszUrlPath
[i
] = '/';
214 if(InternetCreateUrlW(&url
, ICU_ESCAPE
, NULL
, &len
)) {
215 FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
220 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER
) {
221 FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
228 buf
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
234 if(!InternetCreateUrlW(&url
, ICU_ESCAPE
, buf
, &len
)) {
235 FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
241 *p
= SysAllocStringLen(buf
, len
);
250 HeapFree(GetProcessHeap(), 0, buf
);
251 HeapFree(GetProcessHeap(), 0, url_path
);
256 static HRESULT WINAPI
HTMLLocation_put_protocol(IHTMLLocation
*iface
, BSTR v
)
258 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
259 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
263 static HRESULT WINAPI
HTMLLocation_get_protocol(IHTMLLocation
*iface
, BSTR
*p
)
265 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
271 TRACE("(%p)->(%p)\n", This
, p
);
276 if(!(uri
= get_uri(This
))) {
277 FIXME("No current URI\n");
281 hres
= IUri_GetSchemeName(uri
, &protocol
);
284 if(hres
== S_FALSE
) {
285 SysFreeString(protocol
);
290 len
= SysStringLen(protocol
);
291 ret
= SysAllocStringLen(protocol
, len
+1);
292 SysFreeString(protocol
);
294 return E_OUTOFMEMORY
;
301 static HRESULT WINAPI
HTMLLocation_put_host(IHTMLLocation
*iface
, BSTR v
)
303 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
304 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
308 static HRESULT WINAPI
HTMLLocation_get_host(IHTMLLocation
*iface
, BSTR
*p
)
310 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
311 URL_COMPONENTSW url
= {sizeof(URL_COMPONENTSW
)};
314 TRACE("(%p)->(%p)\n", This
, p
);
319 url
.dwHostNameLength
= 1;
320 hres
= get_url_components(This
, &url
);
324 if(!url
.dwHostNameLength
){
330 /* <hostname>:<port> */
331 const WCHAR format
[] = {'%','u',0};
332 DWORD len
= url
.dwHostNameLength
+ 1 + 5;
335 buf
= *p
= SysAllocStringLen(NULL
, len
);
336 memcpy(buf
, url
.lpszHostName
, url
.dwHostNameLength
* sizeof(WCHAR
));
337 buf
[url
.dwHostNameLength
] = ':';
338 snprintfW(buf
+ url
.dwHostNameLength
+ 1, 6, format
, url
.nPort
);
340 *p
= SysAllocStringLen(url
.lpszHostName
, url
.dwHostNameLength
);
343 return E_OUTOFMEMORY
;
347 static HRESULT WINAPI
HTMLLocation_put_hostname(IHTMLLocation
*iface
, BSTR v
)
349 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
350 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
354 static HRESULT WINAPI
HTMLLocation_get_hostname(IHTMLLocation
*iface
, BSTR
*p
)
356 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
361 TRACE("(%p)->(%p)\n", This
, p
);
366 if(!(uri
= get_uri(This
))) {
367 FIXME("No current URI\n");
371 hres
= IUri_GetHost(uri
, &hostname
);
374 }else if(hres
== S_FALSE
) {
375 SysFreeString(hostname
);
384 static HRESULT WINAPI
HTMLLocation_put_port(IHTMLLocation
*iface
, BSTR v
)
386 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
387 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
391 static HRESULT WINAPI
HTMLLocation_get_port(IHTMLLocation
*iface
, BSTR
*p
)
393 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
398 TRACE("(%p)->(%p)\n", This
, p
);
403 if(!(uri
= get_uri(This
))) {
404 FIXME("No current URI\n");
408 hres
= IUri_GetPort(uri
, &port
);
413 static const WCHAR formatW
[] = {'%','u',0};
416 sprintfW(buf
, formatW
, port
);
417 *p
= SysAllocString(buf
);
419 *p
= SysAllocStringLen(NULL
, 0);
423 return E_OUTOFMEMORY
;
427 static HRESULT WINAPI
HTMLLocation_put_pathname(IHTMLLocation
*iface
, BSTR v
)
429 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
430 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
434 static HRESULT WINAPI
HTMLLocation_get_pathname(IHTMLLocation
*iface
, BSTR
*p
)
436 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
437 URL_COMPONENTSW url
= {sizeof(URL_COMPONENTSW
)};
440 TRACE("(%p)->(%p)\n", This
, p
);
445 url
.dwUrlPathLength
= 1;
446 url
.dwExtraInfoLength
= 1;
447 hres
= get_url_components(This
, &url
);
451 if(url
.dwUrlPathLength
&& url
.lpszUrlPath
[0] == '/')
452 *p
= SysAllocStringLen(url
.lpszUrlPath
+ 1, url
.dwUrlPathLength
- 1);
454 *p
= SysAllocStringLen(url
.lpszUrlPath
, url
.dwUrlPathLength
);
457 return E_OUTOFMEMORY
;
461 static HRESULT WINAPI
HTMLLocation_put_search(IHTMLLocation
*iface
, BSTR v
)
463 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
464 FIXME("(%p)->(%s)\n", This
, debugstr_w(v
));
468 static HRESULT WINAPI
HTMLLocation_get_search(IHTMLLocation
*iface
, BSTR
*p
)
470 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
475 TRACE("(%p)->(%p)\n", This
, p
);
480 if(!(uri
= get_uri(This
))) {
481 FIXME("No current URI\n");
485 hres
= IUri_GetQuery(uri
, &query
);
488 }else if(hres
== S_FALSE
) {
489 SysFreeString(query
);
498 static HRESULT WINAPI
HTMLLocation_put_hash(IHTMLLocation
*iface
, BSTR v
)
500 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
502 TRACE("(%p)->(%s)\n", This
, debugstr_w(v
));
504 if(!This
->window
|| !This
->window
->base
.outer_window
) {
505 FIXME("No window available\n");
509 return navigate_url(This
->window
->base
.outer_window
, v
, This
->window
->base
.outer_window
->uri
, 0);
512 static HRESULT WINAPI
HTMLLocation_get_hash(IHTMLLocation
*iface
, BSTR
*p
)
514 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
519 TRACE("(%p)->(%p)\n", This
, p
);
524 if(!(uri
= get_uri(This
))) {
525 FIXME("No current URI\n");
529 hres
= IUri_GetFragment(uri
, &hash
);
532 }else if(hres
== S_FALSE
) {
542 static HRESULT WINAPI
HTMLLocation_reload(IHTMLLocation
*iface
, VARIANT_BOOL flag
)
544 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
545 FIXME("(%p)->(%x)\n", This
, flag
);
549 static HRESULT WINAPI
HTMLLocation_replace(IHTMLLocation
*iface
, BSTR bstr
)
551 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
553 TRACE("(%p)->(%s)\n", This
, debugstr_w(bstr
));
555 if(!This
->window
|| !This
->window
->base
.outer_window
) {
556 FIXME("No window available\n");
560 return navigate_url(This
->window
->base
.outer_window
, bstr
, This
->window
->base
.outer_window
->uri
,
561 BINDING_NAVIGATED
|BINDING_REPLACE
);
564 static HRESULT WINAPI
HTMLLocation_assign(IHTMLLocation
*iface
, BSTR bstr
)
566 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
567 TRACE("(%p)->(%s)\n", This
, debugstr_w(bstr
));
568 return IHTMLLocation_put_href(iface
, bstr
);
571 static HRESULT WINAPI
HTMLLocation_toString(IHTMLLocation
*iface
, BSTR
*String
)
573 HTMLLocation
*This
= impl_from_IHTMLLocation(iface
);
575 TRACE("(%p)->(%p)\n", This
, String
);
577 return IHTMLLocation_get_href(&This
->IHTMLLocation_iface
, String
);
580 static const IHTMLLocationVtbl HTMLLocationVtbl
= {
581 HTMLLocation_QueryInterface
,
583 HTMLLocation_Release
,
584 HTMLLocation_GetTypeInfoCount
,
585 HTMLLocation_GetTypeInfo
,
586 HTMLLocation_GetIDsOfNames
,
588 HTMLLocation_put_href
,
589 HTMLLocation_get_href
,
590 HTMLLocation_put_protocol
,
591 HTMLLocation_get_protocol
,
592 HTMLLocation_put_host
,
593 HTMLLocation_get_host
,
594 HTMLLocation_put_hostname
,
595 HTMLLocation_get_hostname
,
596 HTMLLocation_put_port
,
597 HTMLLocation_get_port
,
598 HTMLLocation_put_pathname
,
599 HTMLLocation_get_pathname
,
600 HTMLLocation_put_search
,
601 HTMLLocation_get_search
,
602 HTMLLocation_put_hash
,
603 HTMLLocation_get_hash
,
605 HTMLLocation_replace
,
607 HTMLLocation_toString
610 static const tid_t HTMLLocation_iface_tids
[] = {
614 static dispex_static_data_t HTMLLocation_dispex
= {
616 DispHTMLLocation_tid
,
618 HTMLLocation_iface_tids
622 HRESULT
HTMLLocation_Create(HTMLInnerWindow
*window
, HTMLLocation
**ret
)
624 HTMLLocation
*location
;
626 location
= heap_alloc(sizeof(*location
));
628 return E_OUTOFMEMORY
;
630 location
->IHTMLLocation_iface
.lpVtbl
= &HTMLLocationVtbl
;
632 location
->window
= window
;
634 init_dispex(&location
->dispex
, (IUnknown
*)&location
->IHTMLLocation_iface
, &HTMLLocation_dispex
);