windowscodecs: Remove unneeded address-of operator from array name.
[wine] / dlls / mshtml / htmllocation.c
1 /*
2  * Copyright 2008 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 <stdarg.h>
20
21 #define COBJMACROS
22
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"
30
31 #include "wine/debug.h"
32
33 #include "mshtml_private.h"
34 #include "binding.h"
35 #include "resource.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
38
39 static HRESULT get_url(HTMLLocation *This, const WCHAR **ret)
40 {
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;
44     }
45
46     *ret = This->window->base.outer_window->url;
47     return S_OK;
48 }
49
50 static IUri *get_uri(HTMLLocation *This)
51 {
52     if(!This->window || !This->window->base.outer_window)
53         return NULL;
54     return This->window->base.outer_window->uri;
55 }
56
57 static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url)
58 {
59     const WCHAR *doc_url;
60     HRESULT hres;
61
62     hres = get_url(This, &doc_url);
63     if(FAILED(hres))
64         return hres;
65
66     if(!InternetCrackUrlW(doc_url, 0, 0, url)) {
67         FIXME("InternetCrackUrlW failed: 0x%08x\n", GetLastError());
68         SetLastError(0);
69         return E_FAIL;
70     }
71
72     return S_OK;
73 }
74
75 static inline HTMLLocation *impl_from_IHTMLLocation(IHTMLLocation *iface)
76 {
77     return CONTAINING_RECORD(iface, HTMLLocation, IHTMLLocation_iface);
78 }
79
80 static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID riid, void **ppv)
81 {
82     HTMLLocation *This = impl_from_IHTMLLocation(iface);
83
84     *ppv = NULL;
85
86     if(IsEqualGUID(&IID_IUnknown, riid)) {
87         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
88         *ppv = &This->IHTMLLocation_iface;
89     }else if(IsEqualGUID(&IID_IHTMLLocation, riid)) {
90         TRACE("(%p)->(IID_IHTMLLocation %p)\n", This, ppv);
91         *ppv = &This->IHTMLLocation_iface;
92     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
93         return *ppv ? S_OK : E_NOINTERFACE;
94     }
95
96     if(*ppv) {
97         IUnknown_AddRef((IUnknown*)*ppv);
98         return S_OK;
99     }
100
101     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
102     return E_NOINTERFACE;
103 }
104
105 static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface)
106 {
107     HTMLLocation *This = impl_from_IHTMLLocation(iface);
108     LONG ref = InterlockedIncrement(&This->ref);
109
110     TRACE("(%p) ref=%d\n", This, ref);
111
112     return ref;
113 }
114
115 static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface)
116 {
117     HTMLLocation *This = impl_from_IHTMLLocation(iface);
118     LONG ref = InterlockedDecrement(&This->ref);
119
120     TRACE("(%p) ref=%d\n", This, ref);
121
122     if(!ref) {
123         if(This->window)
124             This->window->location = NULL;
125         release_dispex(&This->dispex);
126         heap_free(This);
127     }
128
129     return ref;
130 }
131
132 static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo)
133 {
134     HTMLLocation *This = impl_from_IHTMLLocation(iface);
135     return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
136 }
137
138 static HRESULT WINAPI HTMLLocation_GetTypeInfo(IHTMLLocation *iface, UINT iTInfo,
139                                               LCID lcid, ITypeInfo **ppTInfo)
140 {
141     HTMLLocation *This = impl_from_IHTMLLocation(iface);
142     return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
143 }
144
145 static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID riid,
146                                                 LPOLESTR *rgszNames, UINT cNames,
147                                                 LCID lcid, DISPID *rgDispId)
148 {
149     HTMLLocation *This = impl_from_IHTMLLocation(iface);
150     return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
151             lcid, rgDispId);
152 }
153
154 static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMember,
155                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
156                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
157 {
158     HTMLLocation *This = impl_from_IHTMLLocation(iface);
159     return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
160             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
161 }
162
163 static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
164 {
165     HTMLLocation *This = impl_from_IHTMLLocation(iface);
166
167     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
168
169     if(!This->window || !This->window->base.outer_window) {
170         FIXME("No window available\n");
171         return E_FAIL;
172     }
173
174     return navigate_url(This->window->base.outer_window, v, This->window->base.outer_window->uri, BINDING_NAVIGATED);
175 }
176
177 static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
178 {
179     HTMLLocation *This = impl_from_IHTMLLocation(iface);
180     URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
181     WCHAR *buf = NULL, *url_path = NULL;
182     HRESULT hres, ret;
183     DWORD len = 0;
184     int i;
185
186     TRACE("(%p)->(%p)\n", This, p);
187
188     if(!p)
189         return E_POINTER;
190
191     url.dwSchemeLength = 1;
192     url.dwHostNameLength = 1;
193     url.dwUrlPathLength = 1;
194     url.dwExtraInfoLength = 1;
195     hres = get_url_components(This, &url);
196     if(FAILED(hres))
197         return hres;
198
199     switch(url.nScheme) {
200     case INTERNET_SCHEME_FILE:
201         {
202             /* prepend a slash */
203             url_path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
204             if(!url_path)
205                 return E_OUTOFMEMORY;
206             url_path[0] = '/';
207             memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
208             url.lpszUrlPath = url_path;
209             url.dwUrlPathLength = url.dwUrlPathLength + 1;
210         }
211         break;
212
213     case INTERNET_SCHEME_HTTP:
214     case INTERNET_SCHEME_HTTPS:
215     case INTERNET_SCHEME_FTP:
216         if(!url.dwUrlPathLength) {
217             /* add a slash if it's blank */
218             url_path = url.lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR));
219             if(!url.lpszUrlPath)
220                 return E_OUTOFMEMORY;
221             url.lpszUrlPath[0] = '/';
222             url.dwUrlPathLength = 1;
223         }
224         break;
225
226     default:
227         break;
228     }
229
230     /* replace \ with / */
231     for(i = 0; i < url.dwUrlPathLength; ++i)
232         if(url.lpszUrlPath[i] == '\\')
233             url.lpszUrlPath[i] = '/';
234
235     if(InternetCreateUrlW(&url, ICU_ESCAPE, NULL, &len)) {
236         FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
237         ret = E_FAIL;
238         goto cleanup;
239     }
240
241     if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
242         FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
243         SetLastError(0);
244         ret = E_FAIL;
245         goto cleanup;
246     }
247     SetLastError(0);
248
249     buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
250     if(!buf) {
251         ret = E_OUTOFMEMORY;
252         goto cleanup;
253     }
254
255     if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
256         FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
257         SetLastError(0);
258         ret = E_FAIL;
259         goto cleanup;
260     }
261
262     *p = SysAllocStringLen(buf, len);
263     if(!*p) {
264         ret = E_OUTOFMEMORY;
265         goto cleanup;
266     }
267
268     ret = S_OK;
269
270 cleanup:
271     HeapFree(GetProcessHeap(), 0, buf);
272     HeapFree(GetProcessHeap(), 0, url_path);
273
274     return ret;
275 }
276
277 static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
278 {
279     HTMLLocation *This = impl_from_IHTMLLocation(iface);
280     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
281     return E_NOTIMPL;
282 }
283
284 static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p)
285 {
286     HTMLLocation *This = impl_from_IHTMLLocation(iface);
287     BSTR protocol, ret;
288     unsigned len;
289     IUri *uri;
290     HRESULT hres;
291
292     TRACE("(%p)->(%p)\n", This, p);
293
294     if(!p)
295         return E_POINTER;
296
297     if(!(uri = get_uri(This))) {
298         FIXME("No current URI\n");
299         return E_NOTIMPL;
300     }
301
302     hres = IUri_GetSchemeName(uri, &protocol);
303     if(FAILED(hres))
304         return hres;
305     if(hres == S_FALSE) {
306         SysFreeString(protocol);
307         *p = NULL;
308         return S_OK;
309     }
310
311     len = SysStringLen(protocol);
312     ret = SysAllocStringLen(protocol, len+1);
313     SysFreeString(protocol);
314     if(!ret)
315         return E_OUTOFMEMORY;
316
317     ret[len] = ':';
318     *p = ret;
319     return S_OK;
320 }
321
322 static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
323 {
324     HTMLLocation *This = impl_from_IHTMLLocation(iface);
325     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
326     return E_NOTIMPL;
327 }
328
329 static HRESULT WINAPI HTMLLocation_get_host(IHTMLLocation *iface, BSTR *p)
330 {
331     HTMLLocation *This = impl_from_IHTMLLocation(iface);
332     URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
333     HRESULT hres;
334
335     TRACE("(%p)->(%p)\n", This, p);
336
337     if(!p)
338         return E_POINTER;
339
340     url.dwHostNameLength = 1;
341     hres = get_url_components(This, &url);
342     if(FAILED(hres))
343         return hres;
344
345     if(!url.dwHostNameLength){
346         *p = NULL;
347         return S_OK;
348     }
349
350     if(url.nPort) {
351         /* <hostname>:<port> */
352         const WCHAR format[] = {'%','u',0};
353         DWORD len = url.dwHostNameLength + 1 + 5;
354         WCHAR *buf;
355
356         buf = *p = SysAllocStringLen(NULL, len);
357         memcpy(buf, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
358         buf[url.dwHostNameLength] = ':';
359         snprintfW(buf + url.dwHostNameLength + 1, 6, format, url.nPort);
360     }else
361         *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);
362
363     if(!*p)
364         return E_OUTOFMEMORY;
365     return S_OK;
366 }
367
368 static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
369 {
370     HTMLLocation *This = impl_from_IHTMLLocation(iface);
371     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
372     return E_NOTIMPL;
373 }
374
375 static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p)
376 {
377     HTMLLocation *This = impl_from_IHTMLLocation(iface);
378     BSTR hostname;
379     IUri *uri;
380     HRESULT hres;
381
382     TRACE("(%p)->(%p)\n", This, p);
383
384     if(!p)
385         return E_POINTER;
386
387     if(!(uri = get_uri(This))) {
388         FIXME("No current URI\n");
389         return E_NOTIMPL;
390     }
391
392     hres = IUri_GetHost(uri, &hostname);
393     if(hres == S_OK) {
394         *p = hostname;
395     }else if(hres == S_FALSE) {
396         SysFreeString(hostname);
397         *p = NULL;
398     }else {
399         return hres;
400     }
401
402     return S_OK;
403 }
404
405 static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
406 {
407     HTMLLocation *This = impl_from_IHTMLLocation(iface);
408     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
409     return E_NOTIMPL;
410 }
411
412 static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p)
413 {
414     HTMLLocation *This = impl_from_IHTMLLocation(iface);
415     DWORD port;
416     IUri *uri;
417     HRESULT hres;
418
419     TRACE("(%p)->(%p)\n", This, p);
420
421     if(!p)
422         return E_POINTER;
423
424     if(!(uri = get_uri(This))) {
425         FIXME("No current URI\n");
426         return E_NOTIMPL;
427     }
428
429     hres = IUri_GetPort(uri, &port);
430     if(FAILED(hres))
431         return hres;
432
433     if(hres == S_OK) {
434         static const WCHAR formatW[] = {'%','u',0};
435         WCHAR buf[12];
436
437         sprintfW(buf, formatW, port);
438         *p = SysAllocString(buf);
439     }else {
440         *p = SysAllocStringLen(NULL, 0);
441     }
442
443     if(!*p)
444         return E_OUTOFMEMORY;
445     return S_OK;
446 }
447
448 static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
449 {
450     HTMLLocation *This = impl_from_IHTMLLocation(iface);
451     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
452     return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
456 {
457     HTMLLocation *This = impl_from_IHTMLLocation(iface);
458     URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
459     HRESULT hres;
460
461     TRACE("(%p)->(%p)\n", This, p);
462
463     if(!p)
464         return E_POINTER;
465
466     url.dwUrlPathLength = 1;
467     url.dwExtraInfoLength = 1;
468     hres = get_url_components(This, &url);
469     if(FAILED(hres))
470         return hres;
471
472     if(url.dwUrlPathLength && url.lpszUrlPath[0] == '/')
473         *p = SysAllocStringLen(url.lpszUrlPath + 1, url.dwUrlPathLength - 1);
474     else
475         *p = SysAllocStringLen(url.lpszUrlPath, url.dwUrlPathLength);
476
477     if(!*p)
478         return E_OUTOFMEMORY;
479     return S_OK;
480 }
481
482 static HRESULT WINAPI HTMLLocation_put_search(IHTMLLocation *iface, BSTR v)
483 {
484     HTMLLocation *This = impl_from_IHTMLLocation(iface);
485     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
486     return E_NOTIMPL;
487 }
488
489 static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p)
490 {
491     HTMLLocation *This = impl_from_IHTMLLocation(iface);
492     BSTR query;
493     IUri *uri;
494     HRESULT hres;
495
496     TRACE("(%p)->(%p)\n", This, p);
497
498     if(!p)
499         return E_POINTER;
500
501     if(!(uri = get_uri(This))) {
502         FIXME("No current URI\n");
503         return E_NOTIMPL;
504     }
505
506     hres = IUri_GetQuery(uri, &query);
507     if(hres == S_OK) {
508         *p = query;
509     }else if(hres == S_FALSE) {
510         SysFreeString(query);
511         *p = NULL;
512     }else {
513         return hres;
514     }
515
516     return S_OK;
517 }
518
519 static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
520 {
521     HTMLLocation *This = impl_from_IHTMLLocation(iface);
522     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
523     return E_NOTIMPL;
524 }
525
526 static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p)
527 {
528     HTMLLocation *This = impl_from_IHTMLLocation(iface);
529     BSTR hash;
530     IUri *uri;
531     HRESULT hres;
532
533     TRACE("(%p)->(%p)\n", This, p);
534
535     if(!p)
536         return E_POINTER;
537
538     if(!(uri = get_uri(This))) {
539         FIXME("No current URI\n");
540         return E_NOTIMPL;
541     }
542
543     hres = IUri_GetFragment(uri, &hash);
544     if(hres == S_OK) {
545         *p = hash;
546     }else if(hres == S_FALSE) {
547         SysFreeString(hash);
548         *p = NULL;
549     }else {
550         return hres;
551     }
552
553     return S_OK;
554 }
555
556 static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
557 {
558     HTMLLocation *This = impl_from_IHTMLLocation(iface);
559     FIXME("(%p)->(%x)\n", This, flag);
560     return E_NOTIMPL;
561 }
562
563 static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
564 {
565     HTMLLocation *This = impl_from_IHTMLLocation(iface);
566
567     TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));
568
569     if(!This->window || !This->window->base.outer_window) {
570         FIXME("No window available\n");
571         return E_FAIL;
572     }
573
574     return navigate_url(This->window->base.outer_window, bstr, This->window->base.outer_window->uri,
575             BINDING_NAVIGATED|BINDING_REPLACE);
576 }
577
578 static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr)
579 {
580     HTMLLocation *This = impl_from_IHTMLLocation(iface);
581     FIXME("(%p)->(%s)\n", This, debugstr_w(bstr));
582     return E_NOTIMPL;
583 }
584
585 static HRESULT WINAPI HTMLLocation_toString(IHTMLLocation *iface, BSTR *String)
586 {
587     HTMLLocation *This = impl_from_IHTMLLocation(iface);
588
589     TRACE("(%p)->(%p)\n", This, String);
590
591     return IHTMLLocation_get_href(&This->IHTMLLocation_iface, String);
592 }
593
594 static const IHTMLLocationVtbl HTMLLocationVtbl = {
595     HTMLLocation_QueryInterface,
596     HTMLLocation_AddRef,
597     HTMLLocation_Release,
598     HTMLLocation_GetTypeInfoCount,
599     HTMLLocation_GetTypeInfo,
600     HTMLLocation_GetIDsOfNames,
601     HTMLLocation_Invoke,
602     HTMLLocation_put_href,
603     HTMLLocation_get_href,
604     HTMLLocation_put_protocol,
605     HTMLLocation_get_protocol,
606     HTMLLocation_put_host,
607     HTMLLocation_get_host,
608     HTMLLocation_put_hostname,
609     HTMLLocation_get_hostname,
610     HTMLLocation_put_port,
611     HTMLLocation_get_port,
612     HTMLLocation_put_pathname,
613     HTMLLocation_get_pathname,
614     HTMLLocation_put_search,
615     HTMLLocation_get_search,
616     HTMLLocation_put_hash,
617     HTMLLocation_get_hash,
618     HTMLLocation_reload,
619     HTMLLocation_replace,
620     HTMLLocation_assign,
621     HTMLLocation_toString
622 };
623
624 static const tid_t HTMLLocation_iface_tids[] = {
625     IHTMLLocation_tid,
626     0
627 };
628 static dispex_static_data_t HTMLLocation_dispex = {
629     NULL,
630     DispHTMLLocation_tid,
631     NULL,
632     HTMLLocation_iface_tids
633 };
634
635
636 HRESULT HTMLLocation_Create(HTMLInnerWindow *window, HTMLLocation **ret)
637 {
638     HTMLLocation *location;
639
640     location = heap_alloc(sizeof(*location));
641     if(!location)
642         return E_OUTOFMEMORY;
643
644     location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl;
645     location->ref = 1;
646     location->window = window;
647
648     init_dispex(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex);
649
650     *ret = location;
651     return S_OK;
652 }