enummoniker.c 5.38 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * IEnumMoniker implementation
 *
 * Copyright 2003 Robert Shearman
 *
 * This file contains the (internal) driver registration functions,
 * driver enumeration APIs and DirectDraw creation functions.
 *
 * 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
21
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 23
 */

24 25
#define COBJMACROS

26
#include "quartz_private.h"
27 28 29 30 31 32 33

#include "wine/debug.h"

WINE_DEFAULT_DEBUG_CHANNEL(quartz);

typedef struct EnumMonikerImpl
{
34
    const IEnumMonikerVtbl *lpVtbl;
35
    LONG ref;
36 37 38 39 40
    IMoniker ** ppMoniker;
    ULONG nMonikerCount;
    ULONG index;
} EnumMonikerImpl;

41
static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl;
42 43 44 45 46 47 48 49 50 51

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));

52
    TRACE("(%p, %d, %p)\n", ppMoniker, nMonikerCount, ppEnum);
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

    *ppEnum = NULL;

    if (!pemi)
        return E_OUTOFMEMORY;

    pemi->lpVtbl = &EnumMonikerImpl_Vtbl;
    pemi->ref = 1;
    pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*));
    memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*));
    pemi->nMonikerCount = nMonikerCount;
    pemi->index = 0;

    *ppEnum = (IEnumMoniker *)pemi;

    return S_OK;
}

/**********************************************************************
 * IEnumMoniker_QueryInterface (also IUnknown)
 */
static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
    LPENUMMONIKER iface,
    REFIID riid,
    LPVOID *ppvObj)
{
79
    EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
80 81 82 83 84 85 86 87 88 89 90 91
    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))
    {
        *ppvObj = (LPVOID)iface;
        EnumMonikerImpl_AddRef(iface);
        return S_OK;
    }

92
    *ppvObj = NULL;
93 94 95 96 97 98 99 100 101
    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)
{
102
    EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
103
    ULONG ref;
104 105 106

    if (This == NULL) return E_POINTER;

107 108
    ref = InterlockedIncrement(&This->ref);

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

    return ref;
112 113 114 115 116 117 118
}

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

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

124
    if (!ref)
125
    {
126 127 128 129 130
        ULONG i;

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

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

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

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

    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;

154
    TRACE("-- fetched %d\n", fetched);
155

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

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

static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
{
167
    EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
168

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

    This->index += celt;

    return S_OK;
}

static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
{
178
    EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
179

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

    This->index = 0;

    return S_OK;
}

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

    return E_NOTIMPL;
}

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