1 /* 2 * IEnum* implementation 3 * 4 * Copyright 2006 Mike McCormack 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 <stdarg.h> 24 25 #include "windef.h" 26 #include "winbase.h" 27 #include "objbase.h" 28 29 #include "enumx.h" 30 31 #include "wine/list.h" 32 #include "wine/debug.h" 33 34 WINE_DEFAULT_DEBUG_CHANNEL(ole); 35 36 struct tagEnumSTATPROPSETSTG_impl 37 { 38 const void *vtbl; 39 LONG ref; 40 struct list elements; 41 struct list *current; 42 ULONG elem_size; 43 GUID riid; 44 IUnknown *parent; 45 enumx_copy_cb copy_cb; 46 }; 47 48 /************************************************************************ 49 * enumx_QueryInterface 50 */ 51 HRESULT WINAPI enumx_QueryInterface( 52 enumx_impl *This, 53 REFIID riid, 54 void** ppvObject) 55 { 56 if ( ppvObject==0 ) 57 return E_INVALIDARG; 58 59 *ppvObject = 0; 60 61 if (IsEqualGUID(&IID_IUnknown, riid) || 62 IsEqualGUID(&This->riid, riid)) 63 { 64 IUnknown_AddRef(((IUnknown*)This)); 65 *ppvObject = This; 66 return S_OK; 67 } 68 69 return E_NOINTERFACE; 70 } 71 72 /************************************************************************ 73 * enumx_AddRef 74 */ 75 ULONG WINAPI enumx_AddRef(enumx_impl *This) 76 { 77 return InterlockedIncrement(&This->ref); 78 } 79 80 /************************************************************************ 81 * enumx_Release 82 */ 83 ULONG WINAPI enumx_Release(enumx_impl *This) 84 { 85 ULONG ref; 86 87 ref = InterlockedDecrement(&This->ref); 88 if (ref == 0) 89 { 90 while (!list_empty(&This->elements)) 91 { 92 struct list *x = list_head(&This->elements); 93 list_remove(x); 94 HeapFree(GetProcessHeap(), 0, x); 95 } 96 IUnknown_Release(This->parent); 97 HeapFree(GetProcessHeap(), 0, This); 98 } 99 return ref; 100 } 101 102 /************************************************************************ 103 * enumx_Next 104 */ 105 HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt, 106 void *rgelt, ULONG *pceltFetched) 107 { 108 unsigned char *p; 109 ULONG count = 0; 110 111 TRACE("%p %u %p\n", This, celt, pceltFetched); 112 113 if (This->current == NULL) 114 This->current = list_head(&This->elements); 115 p = rgelt; 116 while (count < celt && This->current && This->current != &This->elements) 117 { 118 if (This->copy_cb) 119 This->copy_cb(This->parent, &This->current[1], p); 120 else 121 memcpy(p, &This->current[1], This->elem_size); 122 p += This->elem_size; 123 This->current = This->current->next; 124 count++; 125 } 126 if (pceltFetched) 127 *pceltFetched = count; 128 if (count < celt) 129 return S_FALSE; 130 return S_OK; 131 } 132 133 /************************************************************************ 134 * enumx_Skip 135 */ 136 HRESULT WINAPI enumx_Skip(enumx_impl *This, ULONG celt) 137 { 138 ULONG count = 0; 139 140 TRACE("%p %u\n", This, celt); 141 142 if (This->current == NULL) 143 This->current = list_head(&This->elements); 144 145 while (count < celt && This->current && This->current != &This->elements) 146 count++; 147 148 return S_OK; 149 } 150 151 /************************************************************************ 152 * enumx_Reset 153 */ 154 HRESULT WINAPI enumx_Reset(enumx_impl *This) 155 { 156 TRACE("\n"); 157 158 This->current = NULL; 159 return S_OK; 160 } 161 162 /************************************************************************ 163 * enumx_fnClone 164 */ 165 HRESULT WINAPI enumx_Clone( 166 enumx_impl *iface, 167 enumx_impl **ppenum) 168 { 169 FIXME("\n"); 170 return E_NOTIMPL; 171 } 172 173 /************************************************************************ 174 * enumx_allocate 175 * 176 * Allocate a generic enumerator 177 */ 178 enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size, 179 IUnknown *parent, enumx_copy_cb copy_cb) 180 { 181 enumx_impl *enumx; 182 183 enumx = HeapAlloc(GetProcessHeap(), 0, sizeof *enumx); 184 if (enumx) 185 { 186 enumx->vtbl = vtbl; 187 enumx->ref = 1; 188 enumx->current = NULL; 189 enumx->elem_size = elem_size; 190 enumx->riid = *riid; 191 enumx->parent = parent; 192 enumx->copy_cb = copy_cb; 193 194 IUnknown_AddRef(parent); 195 196 list_init(&enumx->elements); 197 } 198 199 return enumx; 200 } 201 202 /************************************************************************ 203 * enumx_add_element 204 * 205 * Add an element to the enumeration. 206 */ 207 void *enumx_add_element(enumx_impl *enumx, const void *data) 208 { 209 struct list *element; 210 211 element = HeapAlloc(GetProcessHeap(), 0, sizeof *element + enumx->elem_size); 212 if (!element) 213 return NULL; 214 memcpy(&element[1], data, enumx->elem_size); 215 list_add_tail(&enumx->elements, element); 216 return &element[1]; 217 } 218