enummoniker.c 5.45 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * IEnumMoniker implementation
 *
 * Copyright 2003 Robert Shearman
 *
 * 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
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20
 */

21 22
#define COBJMACROS

23
#include "quartz_private.h"
24 25 26 27 28 29 30

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(quartz);

typedef struct EnumMonikerImpl
{
31
    IEnumMoniker IEnumMoniker_iface;
32
    LONG ref;
33 34 35 36 37
    IMoniker ** ppMoniker;
    ULONG nMonikerCount;
    ULONG index;
} EnumMonikerImpl;

38
static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl;
39

40 41 42 43 44
static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
{
    return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
}

45 46 47 48 49 50 51 52 53
static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface);

HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum)
{
    /* NOTE: assumes that array of IMonikers has already been AddRef'd
     * I.e. this function does not AddRef the array of incoming
     * IMonikers */
    EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl));

54
    TRACE("(%p, %d, %p)\n", ppMoniker, nMonikerCount, ppEnum);
55 56 57 58 59 60

    *ppEnum = NULL;

    if (!pemi)
        return E_OUTOFMEMORY;

61
    pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl;
62 63 64 65 66 67
    pemi->ref = 1;
    pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*));
    memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*));
    pemi->nMonikerCount = nMonikerCount;
    pemi->index = 0;

68
    *ppEnum = &pemi->IEnumMoniker_iface;
69 70 71 72 73 74 75 76 77 78 79 80

    return S_OK;
}

/**********************************************************************
 * IEnumMoniker_QueryInterface (also IUnknown)
 */
static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
    LPENUMMONIKER iface,
    REFIID riid,
    LPVOID *ppvObj)
{
81
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
82 83 84 85 86 87 88
    TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));

    if (This == NULL || ppvObj == NULL) return E_POINTER;

    if (IsEqualGUID(riid, &IID_IUnknown) ||
        IsEqualGUID(riid, &IID_IEnumMoniker))
    {
89
        *ppvObj = iface;
90 91 92 93
        EnumMonikerImpl_AddRef(iface);
        return S_OK;
    }

94
    *ppvObj = NULL;
95 96 97 98 99 100 101 102 103
    FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
    return E_NOINTERFACE;
}

/**********************************************************************
 * IEnumMoniker_AddRef (also IUnknown)
 */
static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface)
{
104
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
105
    ULONG ref;
106 107 108

    if (This == NULL) return E_POINTER;

109 110
    ref = InterlockedIncrement(&This->ref);

111
    TRACE("(%p)->() AddRef from %d\n", iface, ref - 1);
112 113

    return ref;
114 115 116 117 118 119 120
}

/**********************************************************************
 * IEnumMoniker_Release (also IUnknown)
 */
static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface)
{
121
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
122
    ULONG ref = InterlockedDecrement(&This->ref);
123

124
    TRACE("(%p)->() Release from %d\n", iface, ref + 1);
125

126
    if (!ref)
127
    {
128 129 130 131 132
        ULONG i;

        for (i = 0; i < This->nMonikerCount; i++)
            IMoniker_Release(This->ppMoniker[i]);

133 134 135 136 137
        CoTaskMemFree(This->ppMoniker);
        This->ppMoniker = NULL;
        CoTaskMemFree(This);
        return 0;
    }
138
    return ref;
139 140 141 142 143
}

static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
{
    ULONG fetched;
144
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
145

146
    TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
147 148 149 150 151 152 153 154 155

    for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++)
    {
        rgelt[fetched] = This->ppMoniker[This->index + fetched];
        IMoniker_AddRef(rgelt[fetched]);
    }

    This->index += fetched;

156
    TRACE("-- fetched %d\n", fetched);
157

158 159 160 161 162 163 164 165 166 167 168
    if (pceltFetched)
        *pceltFetched = fetched;

    if (fetched != celt)
        return S_FALSE;
    else
        return S_OK;
}

static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
{
169
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
170

171
    TRACE("(%p)->(%d)\n", iface, celt);
172 173 174 175 176 177 178 179

    This->index += celt;

    return S_OK;
}

static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
{
180
    EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
181

182
    TRACE("(%p)->()\n", iface);
183 184 185 186 187 188 189 190

    This->index = 0;

    return S_OK;
}

static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
{
191
    FIXME("(%p)->(%p): stub\n", iface, ppenum);
192 193 194 195 196 197 198

    return E_NOTIMPL;
}

/**********************************************************************
 * IEnumMoniker_Vtbl
 */
199
static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl =
200 201 202 203 204 205 206 207 208
{
    EnumMonikerImpl_QueryInterface,
    EnumMonikerImpl_AddRef,
    EnumMonikerImpl_Release,
    EnumMonikerImpl_Next,
    EnumMonikerImpl_Skip,
    EnumMonikerImpl_Reset,
    EnumMonikerImpl_Clone
};