htmllocation.c 16.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Copyright 2008 Jacek Caban for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include <stdarg.h>

#define COBJMACROS

#include "windef.h"
#include "winbase.h"
#include "winuser.h"
26
#include "winreg.h"
27
#include "ole2.h"
28 29
#include "wininet.h"
#include "shlwapi.h"
30 31 32 33 34 35 36 37

#include "wine/debug.h"

#include "mshtml_private.h"
#include "resource.h"

WINE_DEFAULT_DEBUG_CHANNEL(mshtml);

38 39
static HRESULT get_url(HTMLLocation *This, const WCHAR **ret)
{
40
    if(!This->window || !This->window->url) {
41 42 43 44
        FIXME("No current URL\n");
        return E_NOTIMPL;
    }

45
    *ret = This->window->url;
46 47 48
    return S_OK;
}

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
static HRESULT get_url_components(HTMLLocation *This, URL_COMPONENTSW *url)
{
    const WCHAR *doc_url;
    HRESULT hres;

    hres = get_url(This, &doc_url);
    if(FAILED(hres))
        return hres;

    if(!InternetCrackUrlW(doc_url, 0, 0, url)) {
        FIXME("InternetCrackUrlW failed: 0x%08x\n", GetLastError());
        SetLastError(0);
        return E_FAIL;
    }

    return S_OK;
}
66

67 68 69 70
static inline HTMLLocation *impl_from_IHTMLLocation(IHTMLLocation *iface)
{
    return CONTAINING_RECORD(iface, HTMLLocation, IHTMLLocation_iface);
}
71 72 73

static HRESULT WINAPI HTMLLocation_QueryInterface(IHTMLLocation *iface, REFIID riid, void **ppv)
{
74
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
75 76 77 78 79

    *ppv = NULL;

    if(IsEqualGUID(&IID_IUnknown, riid)) {
        TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
80
        *ppv = &This->IHTMLLocation_iface;
81 82
    }else if(IsEqualGUID(&IID_IHTMLLocation, riid)) {
        TRACE("(%p)->(IID_IHTMLLocation %p)\n", This, ppv);
83
        *ppv = &This->IHTMLLocation_iface;
84 85
    }else if(dispex_query_interface(&This->dispex, riid, ppv)) {
        return *ppv ? S_OK : E_NOINTERFACE;
86 87 88 89 90 91 92 93 94 95 96 97 98
    }

    if(*ppv) {
        IUnknown_AddRef((IUnknown*)*ppv);
        return S_OK;
    }

    WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
    return E_NOINTERFACE;
}

static ULONG WINAPI HTMLLocation_AddRef(IHTMLLocation *iface)
{
99
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
100 101 102 103 104 105 106 107 108
    LONG ref = InterlockedIncrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    return ref;
}

static ULONG WINAPI HTMLLocation_Release(IHTMLLocation *iface)
{
109
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
110 111 112 113 114
    LONG ref = InterlockedDecrement(&This->ref);

    TRACE("(%p) ref=%d\n", This, ref);

    if(!ref) {
115 116
        if(This->window)
            This->window->location = NULL;
117
        release_dispex(&This->dispex);
118 119 120 121 122 123 124 125
        heap_free(This);
    }

    return ref;
}

static HRESULT WINAPI HTMLLocation_GetTypeInfoCount(IHTMLLocation *iface, UINT *pctinfo)
{
126
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
127
    return IDispatchEx_GetTypeInfoCount(&This->dispex.IDispatchEx_iface, pctinfo);
128 129 130 131 132
}

static HRESULT WINAPI HTMLLocation_GetTypeInfo(IHTMLLocation *iface, UINT iTInfo,
                                              LCID lcid, ITypeInfo **ppTInfo)
{
133
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
134
    return IDispatchEx_GetTypeInfo(&This->dispex.IDispatchEx_iface, iTInfo, lcid, ppTInfo);
135 136 137 138 139 140
}

static HRESULT WINAPI HTMLLocation_GetIDsOfNames(IHTMLLocation *iface, REFIID riid,
                                                LPOLESTR *rgszNames, UINT cNames,
                                                LCID lcid, DISPID *rgDispId)
{
141
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
142 143
    return IDispatchEx_GetIDsOfNames(&This->dispex.IDispatchEx_iface, riid, rgszNames, cNames,
            lcid, rgDispId);
144 145 146 147 148 149
}

static HRESULT WINAPI HTMLLocation_Invoke(IHTMLLocation *iface, DISPID dispIdMember,
                            REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
                            VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
150
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
151
    return IDispatchEx_Invoke(&This->dispex.IDispatchEx_iface, dispIdMember, riid, lcid,
152
            wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
153 154 155 156
}

static HRESULT WINAPI HTMLLocation_put_href(IHTMLLocation *iface, BSTR v)
{
157
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
158 159 160

    TRACE("(%p)->(%s)\n", This, debugstr_w(v));

161 162
    if(!This->window) {
        FIXME("No window available\n");
163 164 165
        return E_FAIL;
    }

166
    return navigate_url(This->window, v, This->window->url);
167 168 169 170
}

static HRESULT WINAPI HTMLLocation_get_href(IHTMLLocation *iface, BSTR *p)
{
171
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
172 173 174 175 176
    URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
    WCHAR *buf = NULL, *url_path = NULL;
    HRESULT hres, ret;
    DWORD len = 0;
    int i;
177 178 179 180 181 182

    TRACE("(%p)->(%p)\n", This, p);

    if(!p)
        return E_POINTER;

183 184 185 186 187
    url.dwSchemeLength = 1;
    url.dwHostNameLength = 1;
    url.dwUrlPathLength = 1;
    url.dwExtraInfoLength = 1;
    hres = get_url_components(This, &url);
188 189
    if(FAILED(hres))
        return hres;
190

191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
    switch(url.nScheme) {
    case INTERNET_SCHEME_FILE:
        {
            /* prepend a slash */
            url_path = HeapAlloc(GetProcessHeap(), 0, (url.dwUrlPathLength + 1) * sizeof(WCHAR));
            if(!url_path)
                return E_OUTOFMEMORY;
            url_path[0] = '/';
            memcpy(url_path + 1, url.lpszUrlPath, url.dwUrlPathLength * sizeof(WCHAR));
            url.lpszUrlPath = url_path;
            url.dwUrlPathLength = url.dwUrlPathLength + 1;
        }
        break;

    case INTERNET_SCHEME_HTTP:
    case INTERNET_SCHEME_HTTPS:
    case INTERNET_SCHEME_FTP:
        if(!url.dwUrlPathLength) {
            /* add a slash if it's blank */
            url_path = url.lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, 1 * sizeof(WCHAR));
            if(!url.lpszUrlPath)
                return E_OUTOFMEMORY;
            url.lpszUrlPath[0] = '/';
            url.dwUrlPathLength = 1;
        }
        break;

    default:
        break;
    }

    /* replace \ with / */
    for(i = 0; i < url.dwUrlPathLength; ++i)
        if(url.lpszUrlPath[i] == '\\')
            url.lpszUrlPath[i] = '/';

    if(InternetCreateUrlW(&url, ICU_ESCAPE, NULL, &len)) {
        FIXME("InternetCreateUrl succeeded with NULL buffer?\n");
        ret = E_FAIL;
        goto cleanup;
    }

    if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
        SetLastError(0);
        ret = E_FAIL;
        goto cleanup;
    }
    SetLastError(0);

    buf = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
    if(!buf) {
        ret = E_OUTOFMEMORY;
        goto cleanup;
    }

    if(!InternetCreateUrlW(&url, ICU_ESCAPE, buf, &len)) {
        FIXME("InternetCreateUrl failed with error: %08x\n", GetLastError());
        SetLastError(0);
        ret = E_FAIL;
        goto cleanup;
    }

    *p = SysAllocStringLen(buf, len);
    if(!*p) {
        ret = E_OUTOFMEMORY;
        goto cleanup;
    }

    ret = S_OK;

cleanup:
263 264
    HeapFree(GetProcessHeap(), 0, buf);
    HeapFree(GetProcessHeap(), 0, url_path);
265 266

    return ret;
267 268 269 270
}

static HRESULT WINAPI HTMLLocation_put_protocol(IHTMLLocation *iface, BSTR v)
{
271
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
272 273 274 275 276 277
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_protocol(IHTMLLocation *iface, BSTR *p)
{
278
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
279 280
    BSTR protocol, ret;
    unsigned len;
281 282 283
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
284 285 286 287

    if(!p)
        return E_POINTER;

288 289 290 291 292 293
    if(!This->window || !This->window->uri) {
        FIXME("No current URI\n");
        return E_NOTIMPL;
    }

    hres = IUri_GetSchemeName(This->window->uri, &protocol);
294 295
    if(FAILED(hres))
        return hres;
296 297 298 299
    if(hres == S_FALSE) {
        SysFreeString(protocol);
        *p = NULL;
        return S_OK;
300
    }
301 302 303 304 305

    len = SysStringLen(protocol);
    ret = SysAllocStringLen(protocol, len+1);
    SysFreeString(protocol);
    if(!ret)
306
        return E_OUTOFMEMORY;
307 308 309

    ret[len] = ':';
    *p = ret;
310
    return S_OK;
311 312 313 314
}

static HRESULT WINAPI HTMLLocation_put_host(IHTMLLocation *iface, BSTR v)
{
315
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
316 317 318 319 320 321
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_host(IHTMLLocation *iface, BSTR *p)
{
322
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
323 324 325 326
    URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
327 328 329 330

    if(!p)
        return E_POINTER;

331 332 333 334 335 336 337 338 339 340 341 342
    url.dwHostNameLength = 1;
    hres = get_url_components(This, &url);
    if(FAILED(hres))
        return hres;

    if(!url.dwHostNameLength){
        *p = NULL;
        return S_OK;
    }

    if(url.nPort) {
        /* <hostname>:<port> */
343
        const WCHAR format[] = {'%','u',0};
344 345
        DWORD len = url.dwHostNameLength + 1 + 5;
        WCHAR *buf;
346

347
        buf = *p = SysAllocStringLen(NULL, len);
348 349 350 351 352 353 354 355 356
        memcpy(buf, url.lpszHostName, url.dwHostNameLength * sizeof(WCHAR));
        buf[url.dwHostNameLength] = ':';
        snprintfW(buf + url.dwHostNameLength + 1, 6, format, url.nPort);
    }else
        *p = SysAllocStringLen(url.lpszHostName, url.dwHostNameLength);

    if(!*p)
        return E_OUTOFMEMORY;
    return S_OK;
357 358 359 360
}

static HRESULT WINAPI HTMLLocation_put_hostname(IHTMLLocation *iface, BSTR v)
{
361
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
362 363 364 365 366 367
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_hostname(IHTMLLocation *iface, BSTR *p)
{
368
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
369
    BSTR hostname;
370 371 372
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
373 374 375 376

    if(!p)
        return E_POINTER;

377 378 379 380
    if(!This->window || !This->window->uri) {
        FIXME("No current URI\n");
        return E_NOTIMPL;
    }
381

382 383 384 385 386
    hres = IUri_GetHost(This->window->uri, &hostname);
    if(hres == S_OK) {
        *p = hostname;
    }else if(hres == S_FALSE) {
        SysFreeString(hostname);
387
        *p = NULL;
388 389
    }else {
        return hres;
390 391 392
    }

    return S_OK;
393 394 395 396
}

static HRESULT WINAPI HTMLLocation_put_port(IHTMLLocation *iface, BSTR v)
{
397
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
398 399 400 401 402 403
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_port(IHTMLLocation *iface, BSTR *p)
{
404
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
405
    DWORD port;
406 407 408
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
409 410 411 412

    if(!p)
        return E_POINTER;

413 414 415 416 417 418
    if(!This->window || !This->window->uri) {
        FIXME("No current URI\n");
        return E_NOTIMPL;
    }

    hres = IUri_GetPort(This->window->uri, &port);
419 420 421
    if(FAILED(hres))
        return hres;

422 423 424 425 426
    if(hres == S_OK) {
        static const WCHAR formatW[] = {'%','u',0};
        WCHAR buf[12];

        sprintfW(buf, formatW, port);
427 428
        *p = SysAllocString(buf);
    }else {
429
        *p = SysAllocStringLen(NULL, 0);
430 431 432 433 434
    }

    if(!*p)
        return E_OUTOFMEMORY;
    return S_OK;
435 436 437 438
}

static HRESULT WINAPI HTMLLocation_put_pathname(IHTMLLocation *iface, BSTR v)
{
439
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
440 441 442 443 444 445
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_pathname(IHTMLLocation *iface, BSTR *p)
{
446
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
447
    URL_COMPONENTSW url = {sizeof(URL_COMPONENTSW)};
448 449 450 451
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);

452 453 454
    if(!p)
        return E_POINTER;

455
    url.dwUrlPathLength = 1;
456
    url.dwExtraInfoLength = 1;
457 458 459
    hres = get_url_components(This, &url);
    if(FAILED(hres))
        return hres;
460

461 462 463 464
    if(url.dwUrlPathLength && url.lpszUrlPath[0] == '/')
        *p = SysAllocStringLen(url.lpszUrlPath + 1, url.dwUrlPathLength - 1);
    else
        *p = SysAllocStringLen(url.lpszUrlPath, url.dwUrlPathLength);
465 466 467 468

    if(!*p)
        return E_OUTOFMEMORY;
    return S_OK;
469 470 471 472
}

static HRESULT WINAPI HTMLLocation_put_search(IHTMLLocation *iface, BSTR v)
{
473
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
474 475 476 477 478 479
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_search(IHTMLLocation *iface, BSTR *p)
{
480
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
481
    BSTR query;
482 483 484
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
485 486 487 488

    if(!p)
        return E_POINTER;

489 490 491 492
    if(!This->window || !This->window->uri) {
        FIXME("No current URI\n");
        return E_NOTIMPL;
    }
493

494 495 496 497 498
    hres = IUri_GetQuery(This->window->uri, &query);
    if(hres == S_OK) {
        *p = query;
    }else if(hres == S_FALSE) {
        SysFreeString(query);
499
        *p = NULL;
500 501
    }else {
        return hres;
502 503 504
    }

    return S_OK;
505 506 507 508
}

static HRESULT WINAPI HTMLLocation_put_hash(IHTMLLocation *iface, BSTR v)
{
509
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
510 511 512 513 514 515
    FIXME("(%p)->(%s)\n", This, debugstr_w(v));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_get_hash(IHTMLLocation *iface, BSTR *p)
{
516
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
517
    BSTR hash;
518 519 520
    HRESULT hres;

    TRACE("(%p)->(%p)\n", This, p);
521 522 523 524

    if(!p)
        return E_POINTER;

525 526 527 528
    if(!This->window || !This->window->uri) {
        FIXME("No current URI\n");
        return E_NOTIMPL;
    }
529

530 531 532 533 534
    hres = IUri_GetFragment(This->window->uri, &hash);
    if(hres == S_OK) {
        *p = hash;
    }else if(hres == S_FALSE) {
        SysFreeString(hash);
535
        *p = NULL;
536 537
    }else {
        return hres;
538 539 540
    }

    return S_OK;
541 542 543 544
}

static HRESULT WINAPI HTMLLocation_reload(IHTMLLocation *iface, VARIANT_BOOL flag)
{
545
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
546 547 548 549 550 551
    FIXME("(%p)->(%x)\n", This, flag);
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_replace(IHTMLLocation *iface, BSTR bstr)
{
552
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
553 554 555 556 557 558 559 560 561

    TRACE("(%p)->(%s)\n", This, debugstr_w(bstr));

    if(!This->window) {
        FIXME("No window available\n");
        return E_FAIL;
    }

    return navigate_url(This->window, bstr, This->window->url);
562 563 564 565
}

static HRESULT WINAPI HTMLLocation_assign(IHTMLLocation *iface, BSTR bstr)
{
566
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
567 568 569 570 571 572
    FIXME("(%p)->(%s)\n", This, debugstr_w(bstr));
    return E_NOTIMPL;
}

static HRESULT WINAPI HTMLLocation_toString(IHTMLLocation *iface, BSTR *String)
{
573
    HTMLLocation *This = impl_from_IHTMLLocation(iface);
574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
    FIXME("(%p)->(%p)\n", This, String);
    return E_NOTIMPL;
}

static const IHTMLLocationVtbl HTMLLocationVtbl = {
    HTMLLocation_QueryInterface,
    HTMLLocation_AddRef,
    HTMLLocation_Release,
    HTMLLocation_GetTypeInfoCount,
    HTMLLocation_GetTypeInfo,
    HTMLLocation_GetIDsOfNames,
    HTMLLocation_Invoke,
    HTMLLocation_put_href,
    HTMLLocation_get_href,
    HTMLLocation_put_protocol,
    HTMLLocation_get_protocol,
    HTMLLocation_put_host,
    HTMLLocation_get_host,
    HTMLLocation_put_hostname,
    HTMLLocation_get_hostname,
    HTMLLocation_put_port,
    HTMLLocation_get_port,
    HTMLLocation_put_pathname,
    HTMLLocation_get_pathname,
    HTMLLocation_put_search,
    HTMLLocation_get_search,
    HTMLLocation_put_hash,
    HTMLLocation_get_hash,
    HTMLLocation_reload,
    HTMLLocation_replace,
    HTMLLocation_assign,
    HTMLLocation_toString
};

608 609 610 611 612
static const tid_t HTMLLocation_iface_tids[] = {
    IHTMLLocation_tid,
    0
};
static dispex_static_data_t HTMLLocation_dispex = {
613
    NULL,
614
    DispHTMLLocation_tid,
615 616 617 618 619
    NULL,
    HTMLLocation_iface_tids
};


620
HRESULT HTMLLocation_Create(HTMLWindow *window, HTMLLocation **ret)
621
{
622
    HTMLLocation *location;
623

624 625 626
    location = heap_alloc(sizeof(*location));
    if(!location)
        return E_OUTOFMEMORY;
627

628
    location->IHTMLLocation_iface.lpVtbl = &HTMLLocationVtbl;
629 630
    location->ref = 1;
    location->window = window;
631

632
    init_dispex(&location->dispex, (IUnknown*)&location->IHTMLLocation_iface, &HTMLLocation_dispex);
633 634 635

    *ret = location;
    return S_OK;
636
}