browse_ctx.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Implementation of hyperlinking (hlink.dll)
 *
 * Copyright 2005 Aric Stewart 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
 */

21
#include "hlink_private.h"
22 23

#include "wine/debug.h"
24
#include "wine/list.h"
25 26 27

WINE_DEFAULT_DEBUG_CHANNEL(hlink);

28 29 30 31 32 33
struct link_entry
{
    struct list entry;
    IHlink *link;
};

34 35
typedef struct
{
36
    IHlinkBrowseContext IHlinkBrowseContext_iface;
37 38
    LONG        ref;
    HLBWINFO*   BrowseWindowInfo;
39 40
    struct link_entry *current;
    struct list links;
41 42
} HlinkBCImpl;

43 44 45 46 47
static inline HlinkBCImpl *impl_from_IHlinkBrowseContext(IHlinkBrowseContext *iface)
{
    return CONTAINING_RECORD(iface, HlinkBCImpl, IHlinkBrowseContext_iface);
}

48 49 50
static HRESULT WINAPI IHlinkBC_fnQueryInterface( IHlinkBrowseContext *iface,
        REFIID riid, LPVOID* ppvObj)
{
51
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
    TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);

    if (IsEqualIID(riid, &IID_IUnknown) ||
        IsEqualIID(riid, &IID_IHlinkBrowseContext))
        *ppvObj = This;

    if (*ppvObj)
    {
        IUnknown_AddRef((IUnknown*)(*ppvObj));
        return S_OK;
    }
    return E_NOINTERFACE;
}

static ULONG WINAPI IHlinkBC_fnAddRef (IHlinkBrowseContext* iface)
{
68
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
69 70
    ULONG refCount = InterlockedIncrement(&This->ref);

71
    TRACE("(%p)->(count=%u)\n", This, refCount - 1);
72 73 74 75 76 77

    return refCount;
}

static ULONG WINAPI IHlinkBC_fnRelease (IHlinkBrowseContext* iface)
{
78
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
79
    ULONG ref = InterlockedDecrement(&This->ref);
80

81
    TRACE("(%p)->(count=%u)\n", This, ref + 1);
82

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    if (!ref)
    {
        struct link_entry *link, *link2;

        LIST_FOR_EACH_ENTRY_SAFE(link, link2, &This->links, struct link_entry, entry)
        {
            list_remove(&link->entry);
            IHlink_Release(link->link);
            heap_free(link);
        }

        heap_free(This->BrowseWindowInfo);
        heap_free(This);
    }

    return ref;
99 100 101 102 103
}

static HRESULT WINAPI IHlinkBC_Register(IHlinkBrowseContext* iface,
        DWORD dwReserved, IUnknown *piunk, IMoniker *pimk, DWORD *pdwRegister)
{
104
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
105 106 107
    IMoniker *mon;
    IMoniker *composite;
    IRunningObjectTable *ROT;
108
    HRESULT hr;
109

110
    FIXME("(%p)->(%i %p %p %p)\n", This, dwReserved, piunk, pimk, pdwRegister);
111

112
    hr = CreateItemMoniker(NULL, L"WINEHLINK", &mon);
113 114
    if (FAILED(hr))
        return hr;
115 116 117 118 119 120 121 122 123 124 125 126
    CreateGenericComposite(mon, pimk, &composite);

    GetRunningObjectTable(0, &ROT);
    IRunningObjectTable_Register(ROT, 0, piunk, composite, pdwRegister);

    IRunningObjectTable_Release(ROT);
    IMoniker_Release(composite);
    IMoniker_Release(mon);

    return S_OK;
}

127
static HRESULT WINAPI IHlinkBC_GetObject(IHlinkBrowseContext* iface,
128 129
        IMoniker *pimk, BOOL fBindifRootRegistered, IUnknown **ppiunk)
{
130 131 132 133 134 135 136 137
    HlinkBCImpl *This = impl_from_IHlinkBrowseContext(iface);
    IMoniker *mon;
    IMoniker *composite;
    IRunningObjectTable *ROT;
    HRESULT hr;

    TRACE("(%p)->(%p, %d, %p)\n", This, pimk, fBindifRootRegistered, ppiunk);

138
    hr = CreateItemMoniker(NULL, L"WINEHLINK", &mon);
139 140 141 142 143 144 145 146 147 148 149
    if (FAILED(hr)) return hr;
    CreateGenericComposite(mon, pimk, &composite);

    GetRunningObjectTable(0, &ROT);
    hr = IRunningObjectTable_GetObject(ROT, composite, ppiunk);

    IRunningObjectTable_Release(ROT);
    IMoniker_Release(composite);
    IMoniker_Release(mon);

    return hr;
150 151 152 153 154
}

static HRESULT WINAPI IHlinkBC_Revoke(IHlinkBrowseContext* iface,
        DWORD dwRegister)
{
155
    HRESULT r;
156
    IRunningObjectTable *ROT;
157
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
158

159
    FIXME("(%p)->(%i)\n", This, dwRegister);
160 161 162 163 164 165 166 167 168 169 170

    GetRunningObjectTable(0, &ROT);
    r = IRunningObjectTable_Revoke(ROT, dwRegister);
    IRunningObjectTable_Release(ROT);

    return r;
}

static HRESULT WINAPI IHlinkBC_SetBrowseWindowInfo(IHlinkBrowseContext* iface,
        HLBWINFO *phlbwi)
{
171
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
172 173
    TRACE("(%p)->(%p)\n", This, phlbwi);

174 175 176
    if(!phlbwi)
        return E_INVALIDARG;

177 178
    heap_free(This->BrowseWindowInfo);
    This->BrowseWindowInfo = heap_alloc(phlbwi->cbSize);
179 180 181 182 183 184 185 186
    memcpy(This->BrowseWindowInfo, phlbwi, phlbwi->cbSize);

    return S_OK;
}

static HRESULT WINAPI IHlinkBC_GetBrowseWindowInfo(IHlinkBrowseContext* iface,
        HLBWINFO *phlbwi)
{
187
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
188 189 190 191 192 193 194 195 196 197 198
    TRACE("(%p)->(%p)\n", This, phlbwi);

    if(!phlbwi)
        return E_INVALIDARG;

    if(!This->BrowseWindowInfo)
        phlbwi->cbSize = 0;
    else
        memcpy(phlbwi, This->BrowseWindowInfo, This->BrowseWindowInfo->cbSize);

    return S_OK;
199 200 201 202 203
}

static HRESULT WINAPI IHlinkBC_SetInitialHlink(IHlinkBrowseContext* iface,
        IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
{
204 205 206 207
    HlinkBCImpl *This = impl_from_IHlinkBrowseContext(iface);
    struct link_entry *link;

    TRACE("(%p)->(%p %s %s)\n", This, pimkTarget, debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName));
208

209 210
    if (!list_empty(&This->links))
        return CO_E_ALREADYINITIALIZED;
211

212 213
    link = heap_alloc(sizeof(struct link_entry));
    if (!link) return E_OUTOFMEMORY;
214 215

    HlinkCreateFromMoniker(pimkTarget, pwzLocation, pwzFriendlyName, NULL,
216
            0, NULL, &IID_IHlink, (void**)&link->link);
217

218 219
    list_add_head(&This->links, &link->entry);
    This->current = LIST_ENTRY(list_head(&This->links), struct link_entry, entry);
220 221 222 223 224 225 226
    return S_OK;
}

static HRESULT WINAPI IHlinkBC_OnNavigateHlink(IHlinkBrowseContext *iface,
        DWORD grfHLNF, IMoniker* pmkTarget, LPCWSTR pwzLocation, LPCWSTR
        pwzFriendlyName, ULONG *puHLID)
{
227
    HlinkBCImpl  *This = impl_from_IHlinkBrowseContext(iface);
228

229
    FIXME("(%p)->(%i %p %s %s %p)\n", This, grfHLNF, pmkTarget,
230 231 232 233 234
            debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), puHLID);

    return S_OK;
}

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 263
static struct link_entry *context_get_entry(HlinkBCImpl *ctxt, ULONG hlid)
{
    struct list *entry;

    switch (hlid)
    {
    case HLID_PREVIOUS:
        entry = list_prev(&ctxt->links, &ctxt->current->entry);
        break;
    case HLID_NEXT:
        entry = list_next(&ctxt->links, &ctxt->current->entry);
        break;
    case HLID_CURRENT:
        entry = &ctxt->current->entry;
        break;
    case HLID_STACKBOTTOM:
        entry = list_tail(&ctxt->links);
        break;
    case HLID_STACKTOP:
        entry = list_head(&ctxt->links);
        break;
    default:
        WARN("unknown id 0x%x\n", hlid);
        entry = NULL;
    }

    return entry ? LIST_ENTRY(entry, struct link_entry, entry) : NULL;
}

264
static HRESULT WINAPI IHlinkBC_UpdateHlink(IHlinkBrowseContext* iface,
265
        ULONG hlid, IMoniker *target, LPCWSTR location, LPCWSTR friendly_name)
266
{
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    HlinkBCImpl *This = impl_from_IHlinkBrowseContext(iface);
    struct link_entry *entry = context_get_entry(This, hlid);
    IHlink *link;
    HRESULT hr;

    TRACE("(%p)->(0x%x %p %s %s)\n", This, hlid, target, debugstr_w(location), debugstr_w(friendly_name));

    if (!entry)
        return E_INVALIDARG;

    hr = HlinkCreateFromMoniker(target, location, friendly_name, NULL, 0, NULL, &IID_IHlink, (void**)&link);
    if (FAILED(hr))
        return hr;

    IHlink_Release(entry->link);
    entry->link = link;

    return S_OK;
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300
}

static HRESULT WINAPI IHlinkBC_EnumNavigationStack( IHlinkBrowseContext *iface,
        DWORD dwReserved, DWORD grfHLFNAMEF, IEnumHLITEM** ppienumhlitem)
{
    FIXME("\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IHlinkBC_QueryHlink( IHlinkBrowseContext* iface,
        DWORD grfHLONG, ULONG uHLID)
{
    FIXME("\n");
    return E_NOTIMPL;
}

301
static HRESULT WINAPI IHlinkBC_GetHlink(IHlinkBrowseContext* iface, ULONG hlid, IHlink **ret)
302
{
303 304
    HlinkBCImpl *This = impl_from_IHlinkBrowseContext(iface);
    struct link_entry *link;
305

306
    TRACE("(%p)->(0x%x %p)\n", This, hlid, ret);
307

308 309
    link = context_get_entry(This, hlid);
    if (!link)
310 311 312 313
        return E_FAIL;

    *ret = link->link;
    IHlink_AddRef(*ret);
314 315

    return S_OK;
316 317
}

318
static HRESULT WINAPI IHlinkBC_SetCurrentHlink(IHlinkBrowseContext* iface, ULONG hlid)
319
{
320 321 322 323 324 325 326 327 328 329 330
    HlinkBCImpl *This = impl_from_IHlinkBrowseContext(iface);
    struct link_entry *link;

    TRACE("(%p)->(0x%08x)\n", This, hlid);

    link = context_get_entry(This, hlid);
    if (!link)
        return E_FAIL;

    This->current = link;
    return S_OK;
331 332 333 334 335 336 337 338 339 340
}

static HRESULT WINAPI IHlinkBC_Clone( IHlinkBrowseContext* iface,
        IUnknown* piunkOuter, REFIID riid, IUnknown** ppiunkOjb)
{
    FIXME("\n");
    return E_NOTIMPL;
}

static HRESULT WINAPI IHlinkBC_Close(IHlinkBrowseContext* iface,
341
        DWORD reserved)
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366
{
    FIXME("\n");
    return E_NOTIMPL;
}

static const IHlinkBrowseContextVtbl hlvt =
{
    IHlinkBC_fnQueryInterface,
    IHlinkBC_fnAddRef,
    IHlinkBC_fnRelease,
    IHlinkBC_Register,
    IHlinkBC_GetObject,
    IHlinkBC_Revoke,
    IHlinkBC_SetBrowseWindowInfo,
    IHlinkBC_GetBrowseWindowInfo,
    IHlinkBC_SetInitialHlink,
    IHlinkBC_OnNavigateHlink,
    IHlinkBC_UpdateHlink,
    IHlinkBC_EnumNavigationStack,
    IHlinkBC_QueryHlink,
    IHlinkBC_GetHlink,
    IHlinkBC_SetCurrentHlink,
    IHlinkBC_Clone,
    IHlinkBC_Close
};
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383

HRESULT HLinkBrowseContext_Constructor(IUnknown *pUnkOuter, REFIID riid, void **ppv)
{
    HlinkBCImpl * hl;

    TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
    *ppv = NULL;

    if (pUnkOuter)
        return CLASS_E_NOAGGREGATION;

    hl = heap_alloc_zero(sizeof(HlinkBCImpl));
    if (!hl)
        return E_OUTOFMEMORY;

    hl->ref = 1;
    hl->IHlinkBrowseContext_iface.lpVtbl = &hlvt;
384 385
    list_init(&hl->links);
    hl->current = NULL;
386 387 388 389

    *ppv = hl;
    return S_OK;
}