xref: /reactos/dll/win32/ole32/enumx.c (revision c2c66aff)
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