dpnet/tests: Add a trailing '\n' to some ok() calls.
[wine.git] / dlls / mshtml / htmllocation.c
blob6411eb7b8d1cd481819390509857dbad87c0a385
1 /*
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 <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winreg.h"
27 #include "ole2.h"
28 #include "wininet.h"
29 #include "shlwapi.h"
31 #include "wine/debug.h"
33 #include "mshtml_private.h"
34 #include "binding.h"
35 #include "resource.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
39 static HRESULT get_url(HTMLLocation *This, const WCHAR **ret)
41 if(!This->window || !This->window->base.outer_window || !This->window->base.outer_window->url) {
42 FIXME("No current URL\n");
43 return E_NOTIMPL;
46 *ret = This->window->base.outer_window->url;
47 return S_OK;
50 static IUri *get_uri(HTMLLocation *This)
52 if(!This->window || !This->window->base.outer_window)
53 return NULL;
54 return This->window->base.outer_window->uri;
57 static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url)
59 const WCHAR *doc_url;
60 HRESULT hres;
62 hres = get_url(This, &doc_url);
63 if(FAILED(hres))
64 return hres;
66 if(!InternetCrackUrlW(doc_url, 0, 0, url)) {
67 FIXME("InternetCrackUrlW failed: 0x%08x\n", GetLastError());
68 SetLastError(0);
69 return E_FAIL;
72 return S_OK;
75 static inline HTMLLocation *impl_from_IHTMLLocation(IHTMLLocation *iface)
77 return CONTAINING_RECORD(iface, HTMLLocation, IHTMLLocation_iface);
80 static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID riid, void **ppv)
82 HTMLLocation *This = impl_from_IHTMLLocation(iface);
84 TRACE("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
86 if(IsEqualGUID(&IID_IUnknown, riid)) {
87 *ppv = &This->IHTMLLocation_iface;
88 }else if(IsEqualGUID(&IID_IHTMLLocation, riid)) {
89 *ppv = &This->IHTMLLocation_iface;
90 }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
91 return *ppv ? S_OK : E_NOINTERFACE;
92 }else {
93 *ppv = NULL;
94 WARN("(%p)->(%s %p)\n", This, debugstr_mshtml_guid(riid), ppv);
95 return E_NOINTERFACE;
98 IUnknown_AddRef((IUnknown*)*ppv);
99 return S_OK;
102 static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface)
104 HTMLLocation *This = impl_from_IHTMLLocation(iface);
105 LONG ref = InterlockedIncrement(&This->ref);
107 TRACE("(%p) ref=%d\n", This, ref);
109 return ref;
112 static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface)
114 HTMLLocation *This = impl_from_IHTMLLocation(iface);
115 LONG ref = InterlockedDecrement(&This->ref);
117 TRACE("(%p) ref=%d\n", This, ref);
119 if(!ref) {
120 if(This->window)
121 This->window->location = NULL;
122 release_dispex(&This->dispex);
123 heap_free(This);
126 return ref;
129 static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo)
131 HTMLLocation *This = impl_from_IHTMLLocation(iface);
132 return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
135 static HRESULT WINAPI HTMLLocation_GetTypeInfo(IHTMLLocation *iface, UINT iTInfo,
136 LCID lcid, ITypeInfo **ppTInfo)
138 HTMLLocation *This = impl_from_IHTMLLocation(iface);
139 return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
142 static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID riid,
143 LPOLESTR *rgszNames, UINT cNames,
144 LCID lcid, DISPID *rgDispId)
146 HTMLLocation *This = impl_from_IHTMLLocation(iface);
147 return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
148 lcid, rgDispId);
151 static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMember,
152 REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
153 VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
155 HTMLLocation *This = impl_from_IHTMLLocation(iface);
156 return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
157 wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
160 static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
162 HTMLLocation *This = impl_from_IHTMLLocation(iface);
164 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
166 if(!This->window || !This->window->base.outer_window) {
167 FIXME("No window available\n");
168 return E_FAIL;
171 return navigate_url(This->window->base.outer_window, v, This->window->base.outer_window->uri, BINDING_NAVIGATED);
174 static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
176 HTMLLocation *This = impl_from_IHTMLLocation(iface);
177 URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
178 WCHAR *buf = NULL, *url_path = NULL;
179 HRESULT hres, ret;
180 DWORD len = 0;
181 int i;
183 TRACE("(%p)->(%p)\n", This, p);
185 if(!p)
186 return E_POINTER;
188 url.dwSchemeLength = 1;
189 url.dwHostNameLength = 1;
190 url.dwUrlPathLength = 1;
191 url.dwExtraInfoLength = 1;
192 hres = get_url_components(This, &url);
193 if(FAILED(hres))
194 return hres;
196 switch(url.nScheme) {
197 case INTERNET_SCHEME_FILE:
199 /* prepend a slash */
200 url_path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
201 if(!url_path)
202 return E_OUTOFMEMORY;
203 url_path[0] = '/';
204 memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
205 url.lpszUrlPath = url_path;
206 url.dwUrlPathLength = url.dwUrlPathLength + 1;
208 break;
210 case INTERNET_SCHEME_HTTP:
211 case INTERNET_SCHEME_HTTPS:
212 case INTERNET_SCHEME_FTP:
213 if(!url.dwUrlPathLength) {
214 /* add a slash if it's blank */
215 url_path = url.lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR));
216 if(!url.lpszUrlPath)
217 return E_OUTOFMEMORY;
218 url.lpszUrlPath[0] = '/';
219 url.dwUrlPathLength = 1;
221 break;
223 default:
224 break;
227 /* replace \ with / */
228 for(i = 0; i < url.dwUrlPathLength; ++i)
229 if(url.lpszUrlPath[i] == '\\')
230 url.lpszUrlPath[i] = '/';
232 if(InternetCreateUrlW(&url, ICU_ESCAPE, NULL, &len)) {
233 FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
234 ret = E_FAIL;
235 goto cleanup;
238 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
239 FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
240 SetLastError(0);
241 ret = E_FAIL;
242 goto cleanup;
244 SetLastError(0);
246 buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
247 if(!buf) {
248 ret = E_OUTOFMEMORY;
249 goto cleanup;
252 if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
253 FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
254 SetLastError(0);
255 ret = E_FAIL;
256 goto cleanup;
259 *p = SysAllocStringLen(buf, len);
260 if(!*p) {
261 ret = E_OUTOFMEMORY;
262 goto cleanup;
265 ret = S_OK;
267 cleanup:
268 HeapFree(GetProcessHeap(), 0, buf);
269 HeapFree(GetProcessHeap(), 0, url_path);
271 return ret;
274 static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
276 HTMLLocation *This = impl_from_IHTMLLocation(iface);
277 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
278 return E_NOTIMPL;
281 static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p)
283 HTMLLocation *This = impl_from_IHTMLLocation(iface);
284 BSTR protocol, ret;
285 unsigned len;
286 IUri *uri;
287 HRESULT hres;
289 TRACE("(%p)->(%p)\n", This, p);
291 if(!p)
292 return E_POINTER;
294 if(!(uri = get_uri(This))) {
295 FIXME("No current URI\n");
296 return E_NOTIMPL;
299 hres = IUri_GetSchemeName(uri, &protocol);
300 if(FAILED(hres))
301 return hres;
302 if(hres == S_FALSE) {
303 SysFreeString(protocol);
304 *p = NULL;
305 return S_OK;
308 len = SysStringLen(protocol);
309 ret = SysAllocStringLen(protocol, len+1);
310 SysFreeString(protocol);
311 if(!ret)
312 return E_OUTOFMEMORY;
314 ret[len] = ':';
315 *p = ret;
316 return S_OK;
319 static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
321 HTMLLocation *This = impl_from_IHTMLLocation(iface);
322 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
323 return E_NOTIMPL;
326 static HRESULT WINAPI HTMLLocation_get_host(IHTMLLocation *iface, BSTR *p)
328 HTMLLocation *This = impl_from_IHTMLLocation(iface);
329 URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
330 HRESULT hres;
332 TRACE("(%p)->(%p)\n", This, p);
334 if(!p)
335 return E_POINTER;
337 url.dwHostNameLength = 1;
338 hres = get_url_components(This, &url);
339 if(FAILED(hres))
340 return hres;
342 if(!url.dwHostNameLength){
343 *p = NULL;
344 return S_OK;
347 if(url.nPort) {
348 /* <hostname>:<port> */
349 const WCHAR format[] = {'%','u',0};
350 DWORD len = url.dwHostNameLength + 1 + 5;
351 WCHAR *buf;
353 buf = *p = SysAllocStringLen(NULL, len);
354 memcpy(buf, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
355 buf[url.dwHostNameLength] = ':';
356 snprintfW(buf + url.dwHostNameLength + 1, 6, format, url.nPort);
357 }else
358 *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
360 if(!*p)
361 return E_OUTOFMEMORY;
362 return S_OK;
365 static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
367 HTMLLocation *This = impl_from_IHTMLLocation(iface);
368 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
369 return E_NOTIMPL;
372 static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p)
374 HTMLLocation *This = impl_from_IHTMLLocation(iface);
375 BSTR hostname;
376 IUri *uri;
377 HRESULT hres;
379 TRACE("(%p)->(%p)\n", This, p);
381 if(!p)
382 return E_POINTER;
384 if(!(uri = get_uri(This))) {
385 FIXME("No current URI\n");
386 return E_NOTIMPL;
389 hres = IUri_GetHost(uri, &hostname);
390 if(hres == S_OK) {
391 *p = hostname;
392 }else if(hres == S_FALSE) {
393 SysFreeString(hostname);
394 *p = NULL;
395 }else {
396 return hres;
399 return S_OK;
402 static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
404 HTMLLocation *This = impl_from_IHTMLLocation(iface);
405 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
406 return E_NOTIMPL;
409 static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p)
411 HTMLLocation *This = impl_from_IHTMLLocation(iface);
412 DWORD port;
413 IUri *uri;
414 HRESULT hres;
416 TRACE("(%p)->(%p)\n", This, p);
418 if(!p)
419 return E_POINTER;
421 if(!(uri = get_uri(This))) {
422 FIXME("No current URI\n");
423 return E_NOTIMPL;
426 hres = IUri_GetPort(uri, &port);
427 if(FAILED(hres))
428 return hres;
430 if(hres == S_OK) {
431 static const WCHAR formatW[] = {'%','u',0};
432 WCHAR buf[12];
434 sprintfW(buf, formatW, port);
435 *p = SysAllocString(buf);
436 }else {
437 *p = SysAllocStringLen(NULL, 0);
440 if(!*p)
441 return E_OUTOFMEMORY;
442 return S_OK;
445 static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
447 HTMLLocation *This = impl_from_IHTMLLocation(iface);
448 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
449 return E_NOTIMPL;
452 static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
454 HTMLLocation *This = impl_from_IHTMLLocation(iface);
455 URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
456 HRESULT hres;
458 TRACE("(%p)->(%p)\n", This, p);
460 if(!p)
461 return E_POINTER;
463 url.dwUrlPathLength = 1;
464 url.dwExtraInfoLength = 1;
465 hres = get_url_components(This, &url);
466 if(FAILED(hres))
467 return hres;
469 if(url.dwUrlPathLength && url.lpszUrlPath[0] == '/')
470 *p = SysAllocStringLen(url.lpszUrlPath + 1, url.dwUrlPathLength - 1);
471 else
472 *p = SysAllocStringLen(url.lpszUrlPath, url.dwUrlPathLength);
474 if(!*p)
475 return E_OUTOFMEMORY;
476 return S_OK;
479 static HRESULT WINAPI HTMLLocation_put_search(IHTMLLocation *iface, BSTR v)
481 HTMLLocation *This = impl_from_IHTMLLocation(iface);
482 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
483 return E_NOTIMPL;
486 static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p)
488 HTMLLocation *This = impl_from_IHTMLLocation(iface);
489 BSTR query;
490 IUri *uri;
491 HRESULT hres;
493 TRACE("(%p)->(%p)\n", This, p);
495 if(!p)
496 return E_POINTER;
498 if(!(uri = get_uri(This))) {
499 FIXME("No current URI\n");
500 return E_NOTIMPL;
503 hres = IUri_GetQuery(uri, &query);
504 if(hres == S_OK) {
505 *p = query;
506 }else if(hres == S_FALSE) {
507 SysFreeString(query);
508 *p = NULL;
509 }else {
510 return hres;
513 return S_OK;
516 static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
518 HTMLLocation *This = impl_from_IHTMLLocation(iface);
519 FIXME("(%p)->(%s)\n", This, debugstr_w(v));
520 return E_NOTIMPL;
523 static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p)
525 HTMLLocation *This = impl_from_IHTMLLocation(iface);
526 BSTR hash;
527 IUri *uri;
528 HRESULT hres;
530 TRACE("(%p)->(%p)\n", This, p);
532 if(!p)
533 return E_POINTER;
535 if(!(uri = get_uri(This))) {
536 FIXME("No current URI\n");
537 return E_NOTIMPL;
540 hres = IUri_GetFragment(uri, &hash);
541 if(hres == S_OK) {
542 *p = hash;
543 }else if(hres == S_FALSE) {
544 SysFreeString(hash);
545 *p = NULL;
546 }else {
547 return hres;
550 return S_OK;
553 static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
555 HTMLLocation *This = impl_from_IHTMLLocation(iface);
556 FIXME("(%p)->(%x)\n", This, flag);
557 return E_NOTIMPL;
560 static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
562 HTMLLocation *This = impl_from_IHTMLLocation(iface);
564 TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
566 if(!This->window || !This->window->base.outer_window) {
567 FIXME("No window available\n");
568 return E_FAIL;
571 return navigate_url(This->window->base.outer_window, bstr, This->window->base.outer_window->uri,
572 BINDING_NAVIGATED|BINDING_REPLACE);
575 static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr)
577 HTMLLocation *This = impl_from_IHTMLLocation(iface);
578 TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
579 return IHTMLLocation_put_href(iface, bstr);
582 static HRESULT WINAPI HTMLLocation_toString(IHTMLLocation *iface, BSTR *String)
584 HTMLLocation *This = impl_from_IHTMLLocation(iface);
586 TRACE("(%p)->(%p)\n", This, String);
588 return IHTMLLocation_get_href(&This->IHTMLLocation_iface, String);
591 static const IHTMLLocationVtbl HTMLLocationVtbl = {
592 HTMLLocation_QueryInterface,
593 HTMLLocation_AddRef,
594 HTMLLocation_Release,
595 HTMLLocation_GetTypeInfoCount,
596 HTMLLocation_GetTypeInfo,
597 HTMLLocation_GetIDsOfNames,
598 HTMLLocation_Invoke,
599 HTMLLocation_put_href,
600 HTMLLocation_get_href,
601 HTMLLocation_put_protocol,
602 HTMLLocation_get_protocol,
603 HTMLLocation_put_host,
604 HTMLLocation_get_host,
605 HTMLLocation_put_hostname,
606 HTMLLocation_get_hostname,
607 HTMLLocation_put_port,
608 HTMLLocation_get_port,
609 HTMLLocation_put_pathname,
610 HTMLLocation_get_pathname,
611 HTMLLocation_put_search,
612 HTMLLocation_get_search,
613 HTMLLocation_put_hash,
614 HTMLLocation_get_hash,
615 HTMLLocation_reload,
616 HTMLLocation_replace,
617 HTMLLocation_assign,
618 HTMLLocation_toString
621 static const tid_t HTMLLocation_iface_tids[] = {
622 IHTMLLocation_tid,
625 static dispex_static_data_t HTMLLocation_dispex = {
626 NULL,
627 DispHTMLLocation_tid,
628 NULL,
629 HTMLLocation_iface_tids
633 HRESULT HTMLLocation_Create(HTMLInnerWindow *window, HTMLLocation **ret)
635 HTMLLocation *location;
637 location = heap_alloc(sizeof(*location));
638 if(!location)
639 return E_OUTOFMEMORY;
641 location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl;
642 location->ref = 1;
643 location->window = window;
645 init_dispex(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex);
647 *ret = location;
648 return S_OK;