mshtml: Implement IHTMLLocation::get_protocol.
[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 "resource.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(mshtml);
37
38 static HRESULT get_url(HTMLLocation *This, const WCHAR **ret)
39 {
40     if(!This->window || !This->window->doc_obj || !This->window->doc_obj->url) {
41         FIXME("No current URL\n");
42         return E_NOTIMPL;
43     }
44
45     *ret = This->window->doc_obj->url;
46     return S_OK;
47 }
48
49 static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url)
50 {
51     const WCHAR *doc_url;
52     HRESULT hres;
53
54     hres = get_url(This, &doc_url);
55     if(FAILED(hres))
56         return hres;
57
58     if(!InternetCrackUrlW(doc_url, 0, 0, url)) {
59         FIXME("InternetCrackUrlW failed: 0x%08x\n", GetLastError());
60         SetLastError(0);
61         return E_FAIL;
62     }
63
64     return S_OK;
65 }
66
67 #define HTMLLOCATION_THIS(iface) DEFINE_THIS(HTMLLocation, HTMLLocation, iface)
68
69 static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID riid, void **ppv)
70 {
71     HTMLLocation *This = HTMLLOCATION_THIS(iface);
72
73     *ppv = NULL;
74
75     if(IsEqualGUID(&IID_IUnknown, riid)) {
76         TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
77         *ppv = HTMLLOCATION(This);
78     }else if(IsEqualGUID(&IID_IHTMLLocation, riid)) {
79         TRACE("(%p)->(IID_IHTMLLocation %p)\n", This, ppv);
80         *ppv = HTMLLOCATION(This);
81     }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
82         return *ppv ? S_OK : E_NOINTERFACE;
83     }
84
85     if(*ppv) {
86         IUnknown_AddRef((IUnknown*)*ppv);
87         return S_OK;
88     }
89
90     WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
91     return E_NOINTERFACE;
92 }
93
94 static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface)
95 {
96     HTMLLocation *This = HTMLLOCATION_THIS(iface);
97     LONG ref = InterlockedIncrement(&This->ref);
98
99     TRACE("(%p) ref=%d\n", This, ref);
100
101     return ref;
102 }
103
104 static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface)
105 {
106     HTMLLocation *This = HTMLLOCATION_THIS(iface);
107     LONG ref = InterlockedDecrement(&This->ref);
108
109     TRACE("(%p) ref=%d\n", This, ref);
110
111     if(!ref) {
112         if(This->window)
113             This->window->location = NULL;
114         release_dispex(&This->dispex);
115         heap_free(This);
116     }
117
118     return ref;
119 }
120
121 static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo)
122 {
123     HTMLLocation *This = HTMLLOCATION_THIS(iface);
124     return IDispatchEx_GetTypeInfoCount(DISPATCHEX(&This->dispex), pctinfo);
125 }
126
127 static HRESULT WINAPI HTMLLocation_GetTypeInfo(IHTMLLocation *iface, UINT iTInfo,
128                                               LCID lcid, ITypeInfo **ppTInfo)
129 {
130     HTMLLocation *This = HTMLLOCATION_THIS(iface);
131     return IDispatchEx_GetTypeInfo(DISPATCHEX(&This->dispex), iTInfo, lcid, ppTInfo);
132 }
133
134 static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID riid,
135                                                 LPOLESTR *rgszNames, UINT cNames,
136                                                 LCID lcid, DISPID *rgDispId)
137 {
138     HTMLLocation *This = HTMLLOCATION_THIS(iface);
139     return IDispatchEx_GetIDsOfNames(DISPATCHEX(&This->dispex), riid, rgszNames, cNames, lcid, rgDispId);
140 }
141
142 static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMember,
143                             REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
144                             VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
145 {
146     HTMLLocation *This = HTMLLOCATION_THIS(iface);
147     return IDispatchEx_Invoke(DISPATCHEX(&This->dispex), dispIdMember, riid, lcid,
148             wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
149 }
150
151 static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
152 {
153     HTMLLocation *This = HTMLLOCATION_THIS(iface);
154
155     TRACE("(%p)->(%s)\n", This, debugstr_w(v));
156
157     if(!This->window || !This->window->doc) {
158         FIXME("No document available\n");
159         return E_FAIL;
160     }
161
162     return navigate_url(This->window->doc, v);
163 }
164
165 static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
166 {
167     HTMLLocation *This = HTMLLOCATION_THIS(iface);
168     const WCHAR *url;
169     HRESULT hres;
170
171     TRACE("(%p)->(%p)\n", This, p);
172
173     if(!p)
174         return E_POINTER;
175
176     hres = get_url(This, &url);
177     if(FAILED(hres))
178         return hres;
179
180     *p = SysAllocString(url);
181     return *p ? S_OK : E_OUTOFMEMORY;
182 }
183
184 static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
185 {
186     HTMLLocation *This = HTMLLOCATION_THIS(iface);
187     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
188     return E_NOTIMPL;
189 }
190
191 static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p)
192 {
193     HTMLLocation *This = HTMLLOCATION_THIS(iface);
194     URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
195     HRESULT hres;
196
197     TRACE("(%p)->(%p)\n", This, p);
198
199     if(!p)
200         return E_POINTER;
201
202     url.dwSchemeLength = 1;
203     hres = get_url_components(This, &url);
204     if(FAILED(hres))
205         return hres;
206
207     if(!url.dwSchemeLength) {
208         FIXME("Unexpected blank protocol\n");
209         return E_NOTIMPL;
210     }else {
211         WCHAR buf[url.dwSchemeLength + 1];
212         memcpy(buf, url.lpszScheme, url.dwSchemeLength * sizeof(WCHAR));
213         buf[url.dwSchemeLength] = ':';
214         *p = SysAllocStringLen(buf, url.dwSchemeLength + 1);
215     }
216     if(!*p)
217         return E_OUTOFMEMORY;
218     return S_OK;
219 }
220
221 static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
222 {
223     HTMLLocation *This = HTMLLOCATION_THIS(iface);
224     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
225     return E_NOTIMPL;
226 }
227
228 static HRESULT WINAPI HTMLLocation_get_host(IHTMLLocation *iface, BSTR *p)
229 {
230     HTMLLocation *This = HTMLLOCATION_THIS(iface);
231     FIXME("(%p)->(%p)\n", This, p);
232
233     if(!p)
234         return E_POINTER;
235
236     return E_NOTIMPL;
237 }
238
239 static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
240 {
241     HTMLLocation *This = HTMLLOCATION_THIS(iface);
242     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
243     return E_NOTIMPL;
244 }
245
246 static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p)
247 {
248     HTMLLocation *This = HTMLLOCATION_THIS(iface);
249     FIXME("(%p)->(%p)\n", This, p);
250
251     if(!p)
252         return E_POINTER;
253
254     return E_NOTIMPL;
255 }
256
257 static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
258 {
259     HTMLLocation *This = HTMLLOCATION_THIS(iface);
260     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
261     return E_NOTIMPL;
262 }
263
264 static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p)
265 {
266     HTMLLocation *This = HTMLLOCATION_THIS(iface);
267     URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
268     HRESULT hres;
269
270     TRACE("(%p)->(%p)\n", This, p);
271
272     if(!p)
273         return E_POINTER;
274
275     hres = get_url_components(This, &url);
276     if(FAILED(hres))
277         return hres;
278
279     if(url.nPort) {
280         const WCHAR format[] = {'%','d',0};
281         WCHAR buf[6];
282         snprintfW(buf, 6, format, url.nPort);
283         *p = SysAllocString(buf);
284     }else {
285         const WCHAR empty[] = {0};
286         *p = SysAllocString(empty);
287     }
288
289     if(!*p)
290         return E_OUTOFMEMORY;
291     return S_OK;
292 }
293
294 static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
295 {
296     HTMLLocation *This = HTMLLOCATION_THIS(iface);
297     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
298     return E_NOTIMPL;
299 }
300
301 static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
302 {
303     HTMLLocation *This = HTMLLOCATION_THIS(iface);
304     WCHAR buf[INTERNET_MAX_PATH_LENGTH];
305     URL_COMPONENTSW url = {sizeof(url)};
306     const WCHAR *doc_url;
307     DWORD size = 0;
308     HRESULT hres;
309
310     TRACE("(%p)->(%p)\n", This, p);
311
312     if(!p)
313         return E_POINTER;
314
315     hres = get_url(This, &doc_url);
316     if(FAILED(hres))
317         return hres;
318
319     hres = CoInternetParseUrl(doc_url, PARSE_PATH_FROM_URL, 0, buf, sizeof(buf), &size, 0);
320     if(SUCCEEDED(hres)) {
321         *p = SysAllocString(buf);
322         if(!*p)
323             return E_OUTOFMEMORY;
324         return S_OK;
325     }
326
327     url.dwUrlPathLength = 1;
328     hres = get_url_components(This, &url);
329     if(FAILED(hres))
330         return hres;
331
332     if(!url.dwUrlPathLength) {
333         *p = NULL;
334         return S_OK;
335     }
336
337     *p = SysAllocStringLen(url.lpszUrlPath, url.dwUrlPathLength);
338     if(!*p)
339         return E_OUTOFMEMORY;
340     return S_OK;
341 }
342
343 static HRESULT WINAPI HTMLLocation_put_search(IHTMLLocation *iface, BSTR v)
344 {
345     HTMLLocation *This = HTMLLOCATION_THIS(iface);
346     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
347     return E_NOTIMPL;
348 }
349
350 static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p)
351 {
352     HTMLLocation *This = HTMLLOCATION_THIS(iface);
353     FIXME("(%p)->(%p)\n", This, p);
354
355     if(!p)
356         return E_POINTER;
357
358     return E_NOTIMPL;
359 }
360
361 static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
362 {
363     HTMLLocation *This = HTMLLOCATION_THIS(iface);
364     FIXME("(%p)->(%s)\n", This, debugstr_w(v));
365     return E_NOTIMPL;
366 }
367
368 static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p)
369 {
370     HTMLLocation *This = HTMLLOCATION_THIS(iface);
371     FIXME("(%p)->(%p)\n", This, p);
372
373     if(!p)
374         return E_POINTER;
375
376     return E_NOTIMPL;
377 }
378
379 static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
380 {
381     HTMLLocation *This = HTMLLOCATION_THIS(iface);
382     FIXME("(%p)->(%x)\n", This, flag);
383     return E_NOTIMPL;
384 }
385
386 static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
387 {
388     HTMLLocation *This = HTMLLOCATION_THIS(iface);
389     FIXME("(%p)->(%s)\n", This, debugstr_w(bstr));
390     return E_NOTIMPL;
391 }
392
393 static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr)
394 {
395     HTMLLocation *This = HTMLLOCATION_THIS(iface);
396     FIXME("(%p)->(%s)\n", This, debugstr_w(bstr));
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI HTMLLocation_toString(IHTMLLocation *iface, BSTR *String)
401 {
402     HTMLLocation *This = HTMLLOCATION_THIS(iface);
403     FIXME("(%p)->(%p)\n", This, String);
404     return E_NOTIMPL;
405 }
406
407 #undef HTMLLOCATION_THIS
408
409 static const IHTMLLocationVtbl HTMLLocationVtbl = {
410     HTMLLocation_QueryInterface,
411     HTMLLocation_AddRef,
412     HTMLLocation_Release,
413     HTMLLocation_GetTypeInfoCount,
414     HTMLLocation_GetTypeInfo,
415     HTMLLocation_GetIDsOfNames,
416     HTMLLocation_Invoke,
417     HTMLLocation_put_href,
418     HTMLLocation_get_href,
419     HTMLLocation_put_protocol,
420     HTMLLocation_get_protocol,
421     HTMLLocation_put_host,
422     HTMLLocation_get_host,
423     HTMLLocation_put_hostname,
424     HTMLLocation_get_hostname,
425     HTMLLocation_put_port,
426     HTMLLocation_get_port,
427     HTMLLocation_put_pathname,
428     HTMLLocation_get_pathname,
429     HTMLLocation_put_search,
430     HTMLLocation_get_search,
431     HTMLLocation_put_hash,
432     HTMLLocation_get_hash,
433     HTMLLocation_reload,
434     HTMLLocation_replace,
435     HTMLLocation_assign,
436     HTMLLocation_toString
437 };
438
439 static const tid_t HTMLLocation_iface_tids[] = {
440     IHTMLLocation_tid,
441     0
442 };
443 static dispex_static_data_t HTMLLocation_dispex = {
444     NULL,
445     DispHTMLLocation_tid,
446     NULL,
447     HTMLLocation_iface_tids
448 };
449
450
451 HRESULT HTMLLocation_Create(HTMLWindow *window, HTMLLocation **ret)
452 {
453     HTMLLocation *location;
454
455     location = heap_alloc(sizeof(*location));
456     if(!location)
457         return E_OUTOFMEMORY;
458
459     location->lpHTMLLocationVtbl = &HTMLLocationVtbl;
460     location->ref = 1;
461     location->window = window;
462
463     init_dispex(&location->dispex, (IUnknown*)HTMLLOCATION(location),  &HTMLLocation_dispex);
464
465     *ret = location;
466     return S_OK;
467 }