1 /* 2 * IEnumMoniker implementation 3 * 4 * Copyright 2003 Robert Shearman 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * 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 #define COBJMACROS 22 23 #include "quartz_private.h" 24 25 #include "wine/debug.h" 26 27 WINE_DEFAULT_DEBUG_CHANNEL(quartz); 28 29 typedef struct EnumMonikerImpl 30 { 31 IEnumMoniker IEnumMoniker_iface; 32 LONG ref; 33 IMoniker ** ppMoniker; 34 ULONG nMonikerCount; 35 ULONG index; 36 } EnumMonikerImpl; 37 38 static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl; 39 40 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface) 41 { 42 return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface); 43 } 44 45 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface); 46 47 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum) 48 { 49 /* NOTE: assumes that array of IMonikers has already been AddRef'd 50 * I.e. this function does not AddRef the array of incoming 51 * IMonikers */ 52 EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl)); 53 54 TRACE("(%p, %d, %p)\n", ppMoniker, nMonikerCount, ppEnum); 55 56 *ppEnum = NULL; 57 58 if (!pemi) 59 return E_OUTOFMEMORY; 60 61 pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl; 62 pemi->ref = 1; 63 pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*)); 64 memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*)); 65 pemi->nMonikerCount = nMonikerCount; 66 pemi->index = 0; 67 68 *ppEnum = &pemi->IEnumMoniker_iface; 69 70 return S_OK; 71 } 72 73 /********************************************************************** 74 * IEnumMoniker_QueryInterface (also IUnknown) 75 */ 76 static HRESULT WINAPI EnumMonikerImpl_QueryInterface( 77 LPENUMMONIKER iface, 78 REFIID riid, 79 LPVOID *ppvObj) 80 { 81 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 82 TRACE("\n\tIID:\t%s\n",debugstr_guid(riid)); 83 84 if (This == NULL || ppvObj == NULL) return E_POINTER; 85 86 if (IsEqualGUID(riid, &IID_IUnknown) || 87 IsEqualGUID(riid, &IID_IEnumMoniker)) 88 { 89 *ppvObj = iface; 90 EnumMonikerImpl_AddRef(iface); 91 return S_OK; 92 } 93 94 *ppvObj = NULL; 95 FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid)); 96 return E_NOINTERFACE; 97 } 98 99 /********************************************************************** 100 * IEnumMoniker_AddRef (also IUnknown) 101 */ 102 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface) 103 { 104 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 105 ULONG ref; 106 107 if (This == NULL) return E_POINTER; 108 109 ref = InterlockedIncrement(&This->ref); 110 111 TRACE("(%p)->() AddRef from %d\n", iface, ref - 1); 112 113 return ref; 114 } 115 116 /********************************************************************** 117 * IEnumMoniker_Release (also IUnknown) 118 */ 119 static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface) 120 { 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 ULONG i; 129 130 for (i = 0; i < This->nMonikerCount; i++) 131 IMoniker_Release(This->ppMoniker[i]); 132 133 CoTaskMemFree(This->ppMoniker); 134 This->ppMoniker = NULL; 135 CoTaskMemFree(This); 136 return 0; 137 } 138 return ref; 139 } 140 141 static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched) 142 { 143 ULONG fetched; 144 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 145 146 TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched); 147 148 for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++) 149 { 150 rgelt[fetched] = This->ppMoniker[This->index + fetched]; 151 IMoniker_AddRef(rgelt[fetched]); 152 } 153 154 This->index += fetched; 155 156 TRACE("-- fetched %d\n", fetched); 157 158 if (pceltFetched) 159 *pceltFetched = fetched; 160 161 if (fetched != celt) 162 return S_FALSE; 163 else 164 return S_OK; 165 } 166 167 static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt) 168 { 169 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 170 171 TRACE("(%p)->(%d)\n", iface, celt); 172 173 This->index += celt; 174 175 return S_OK; 176 } 177 178 static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface) 179 { 180 EnumMonikerImpl *This = impl_from_IEnumMoniker(iface); 181 182 TRACE("(%p)->()\n", iface); 183 184 This->index = 0; 185 186 return S_OK; 187 } 188 189 static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum) 190 { 191 FIXME("(%p)->(%p): stub\n", iface, ppenum); 192 193 return E_NOTIMPL; 194 } 195 196 /********************************************************************** 197 * IEnumMoniker_Vtbl 198 */ 199 static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl = 200 { 201 EnumMonikerImpl_QueryInterface, 202 EnumMonikerImpl_AddRef, 203 EnumMonikerImpl_Release, 204 EnumMonikerImpl_Next, 205 EnumMonikerImpl_Skip, 206 EnumMonikerImpl_Reset, 207 EnumMonikerImpl_Clone 208 }; 209