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