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