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