gdi32: Fix leak in GdiDeleteSpoolFileHandle.
[wine.git] / dlls / mshtml / htmllocation.c
blob92701cb42bc24323318ed1f8c42df99a561dd675
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 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());
50 SetLastError(0);
51 return E_FAIL;
54 return S_OK;
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,
99 lcid, rgDispId);
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;
125 HRESULT hres, ret;
126 DWORD len = 0;
127 int i;
129 TRACE("(%p)->(%p)\n", This, p);
131 if(!p)
132 return E_POINTER;
134 url.dwSchemeLength = 1;
135 url.dwHostNameLength = 1;
136 url.dwUrlPathLength = 1;
137 url.dwExtraInfoLength = 1;
138 hres = get_url_components(This, &url);
139 if(FAILED(hres))
140 return hres;
142 switch(url.nScheme) {
143 case INTERNET_SCHEME_FILE:
145 /* prepend a slash */
146 url_path = malloc((url.dwUrlPathLength + 1) * sizeof(WCHAR));
147 if(!url_path)
148 return E_OUTOFMEMORY;
149 url_path[0] = '/';
150 memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
151 url.lpszUrlPath = url_path;
152 url.dwUrlPathLength = url.dwUrlPathLength + 1;
154 break;
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));
162 if(!url.lpszUrlPath)
163 return E_OUTOFMEMORY;
164 url.lpszUrlPath[0] = '/';
165 url.dwUrlPathLength = 1;
167 break;
169 default:
170 break;
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");
180 ret = E_FAIL;
181 goto cleanup;
184 if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
185 FIXME("InternetCreateUrl failed with error: %08lx\n", GetLastError());
186 SetLastError(0);
187 ret = E_FAIL;
188 goto cleanup;
190 SetLastError(0);
192 buf = malloc(len * sizeof(WCHAR));
193 if(!buf) {
194 ret = E_OUTOFMEMORY;
195 goto cleanup;
198 if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
199 FIXME("InternetCreateUrl failed with error: %08lx\n", GetLastError());
200 SetLastError(0);
201 ret = E_FAIL;
202 goto cleanup;
205 *p = SysAllocStringLen(buf, len);
206 if(!*p) {
207 ret = E_OUTOFMEMORY;
208 goto cleanup;
211 ret = S_OK;
213 cleanup:
214 free(buf);
215 free(url_path);
217 return ret;
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));
224 return E_NOTIMPL;
227 static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p)
229 HTMLLocation *This = impl_from_IHTMLLocation(iface);
230 BSTR protocol, ret;
231 unsigned len;
232 IUri *uri;
233 HRESULT hres;
235 TRACE("(%p)->(%p)\n", This, p);
237 if(!p)
238 return E_POINTER;
240 if(!(uri = get_uri(This)))
241 return (*p = SysAllocString(L"about:")) ? S_OK : E_OUTOFMEMORY;
243 hres = IUri_GetSchemeName(uri, &protocol);
244 if(FAILED(hres))
245 return hres;
246 if(hres == S_FALSE) {
247 SysFreeString(protocol);
248 *p = NULL;
249 return S_OK;
252 len = SysStringLen(protocol);
253 ret = SysAllocStringLen(protocol, len+1);
254 SysFreeString(protocol);
255 if(!ret)
256 return E_OUTOFMEMORY;
258 ret[len] = ':';
259 *p = ret;
260 return S_OK;
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));
267 return E_NOTIMPL;
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)};
274 HRESULT hres;
276 TRACE("(%p)->(%p)\n", This, p);
278 if(!p)
279 return E_POINTER;
281 url.dwHostNameLength = 1;
282 hres = get_url_components(This, &url);
283 if(FAILED(hres))
284 return hres;
286 if(!url.dwHostNameLength){
287 *p = NULL;
288 return S_OK;
291 if(url.nPort) {
292 /* <hostname>:<port> */
293 DWORD len, port_len;
294 WCHAR portW[6];
295 WCHAR *buf;
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));
303 }else
304 *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
306 if(!*p)
307 return E_OUTOFMEMORY;
308 return S_OK;
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));
315 return E_NOTIMPL;
318 static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p)
320 HTMLLocation *This = impl_from_IHTMLLocation(iface);
321 BSTR hostname;
322 IUri *uri;
323 HRESULT hres;
325 TRACE("(%p)->(%p)\n", This, p);
327 if(!p)
328 return E_POINTER;
330 if(!(uri = get_uri(This))) {
331 *p = NULL;
332 return S_OK;
335 hres = IUri_GetHost(uri, &hostname);
336 if(hres == S_OK) {
337 *p = hostname;
338 }else if(hres == S_FALSE) {
339 SysFreeString(hostname);
340 *p = NULL;
341 }else {
342 return hres;
345 return S_OK;
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));
352 return E_NOTIMPL;
355 static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p)
357 HTMLLocation *This = impl_from_IHTMLLocation(iface);
358 DWORD port;
359 IUri *uri;
360 HRESULT hres;
362 TRACE("(%p)->(%p)\n", This, p);
364 if(!p)
365 return E_POINTER;
367 if(!(uri = get_uri(This))) {
368 *p = NULL;
369 return S_OK;
372 hres = IUri_GetPort(uri, &port);
373 if(FAILED(hres))
374 return hres;
376 if(hres == S_OK) {
377 WCHAR buf[12];
379 swprintf(buf, ARRAY_SIZE(buf), L"%u", port);
380 *p = SysAllocString(buf);
381 }else {
382 *p = SysAllocStringLen(NULL, 0);
385 if(!*p)
386 return E_OUTOFMEMORY;
387 return S_OK;
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));
394 return E_NOTIMPL;
397 static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
399 HTMLLocation *This = impl_from_IHTMLLocation(iface);
400 BSTR path;
401 IUri *uri;
402 HRESULT hres;
404 TRACE("(%p)->(%p)\n", This, p);
406 if(!p)
407 return E_POINTER;
409 if(!(uri = get_uri(This)))
410 return (*p = SysAllocString(L"blank")) ? S_OK : E_OUTOFMEMORY;
412 hres = IUri_GetPath(uri, &path);
413 if(FAILED(hres))
414 return hres;
416 if(hres == S_FALSE) {
417 SysFreeString(path);
418 path = NULL;
421 *p = path;
422 return S_OK;
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));
429 return E_NOTIMPL;
432 static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p)
434 HTMLLocation *This = impl_from_IHTMLLocation(iface);
435 BSTR query;
436 IUri *uri;
437 HRESULT hres;
439 TRACE("(%p)->(%p)\n", This, p);
441 if(!p)
442 return E_POINTER;
444 if(!(uri = get_uri(This))) {
445 *p = NULL;
446 return S_OK;
449 hres = IUri_GetQuery(uri, &query);
450 if(hres == S_OK) {
451 *p = query;
452 }else if(hres == S_FALSE) {
453 SysFreeString(query);
454 *p = NULL;
455 }else {
456 return hres;
459 return S_OK;
462 static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
464 HTMLLocation *This = impl_from_IHTMLLocation(iface);
465 WCHAR *hash = v;
466 HRESULT hres;
468 TRACE("(%p)->(%s)\n", This, debugstr_w(v));
470 if(hash[0] != '#') {
471 unsigned size = (1 /* # */ + wcslen(v) + 1) * sizeof(WCHAR);
472 if(!(hash = malloc(size)))
473 return E_OUTOFMEMORY;
474 hash[0] = '#';
475 memcpy(hash + 1, v, size - sizeof(WCHAR));
478 hres = navigate_url(This->window, hash, get_uri(This), BINDING_NAVIGATED);
480 if(hash != v)
481 free(hash);
482 return hres;
485 static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p)
487 HTMLLocation *This = impl_from_IHTMLLocation(iface);
488 BSTR hash;
489 IUri *uri;
490 HRESULT hres;
492 TRACE("(%p)->(%p)\n", This, p);
494 if(!p)
495 return E_POINTER;
497 if(!(uri = get_uri(This))) {
498 *p = NULL;
499 return S_OK;
502 hres = IUri_GetFragment(uri, &hash);
503 if(hres == S_OK) {
504 *p = hash;
505 }else if(hres == S_FALSE) {
506 SysFreeString(hash);
507 *p = NULL;
508 }else {
509 return hres;
512 return S_OK;
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");
524 return E_NOTIMPL;
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,
557 HTMLLocation_AddRef,
558 HTMLLocation_Release,
559 HTMLLocation_GetTypeInfoCount,
560 HTMLLocation_GetTypeInfo,
561 HTMLLocation_GetIDsOfNames,
562 HTMLLocation_Invoke,
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,
579 HTMLLocation_reload,
580 HTMLLocation_replace,
581 HTMLLocation_assign,
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);
598 return NULL;
601 return NULL;
604 static void HTMLLocation_traverse(DispatchEx *dispex, nsCycleCollectionTraversalCallback *cb)
606 HTMLLocation *This = impl_from_DispatchEx(dispex);
607 if(This->window)
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);
614 if(This->window) {
615 HTMLOuterWindow *window = This->window;
616 This->window = NULL;
617 IHTMLWindow2_Release(&window->base.IHTMLWindow2_iface);
621 static void HTMLLocation_destructor(DispatchEx *dispex)
623 HTMLLocation *This = impl_from_DispatchEx(dispex);
624 free(This);
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[] = {
635 IHTMLLocation_tid,
638 static dispex_static_data_t HTMLLocation_dispex = {
639 "Location",
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);
658 *ret = location;
659 return S_OK;