ntdll: Fix race in NtRead/WriteFile.
[wine/testsucceed.git] / dlls / ole32 / enumx.c
blob26653014984088800003c11fda3fd931a9c3ae42
1 /*
2 * IEnum* implementation
4 * Copyright 2006 Mike McCormack
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.
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.
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
21 #define COBJMACROS
23 #include <stdarg.h>
25 #include "windef.h"
26 #include "winbase.h"
27 #include "objbase.h"
29 #include "enumx.h"
31 #include "wine/list.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(ole);
36 struct tagEnumSTATPROPSETSTG_impl
38 const void *vtbl;
39 LONG ref;
40 struct list elements;
41 struct list *current;
42 ULONG elem_size;
43 GUID riid;
46 /************************************************************************
47 * enumx_QueryInterface
49 HRESULT WINAPI enumx_QueryInterface(
50 enumx_impl *This,
51 REFIID riid,
52 void** ppvObject)
54 if ( (This==0) || (ppvObject==0) )
55 return E_INVALIDARG;
57 *ppvObject = 0;
59 if (IsEqualGUID(&IID_IUnknown, riid) ||
60 IsEqualGUID(&This->riid, riid))
62 IUnknown_AddRef(((IUnknown*)This));
63 *ppvObject = This;
64 return S_OK;
67 return E_NOINTERFACE;
70 /************************************************************************
71 * enumx_AddRef
73 ULONG WINAPI enumx_AddRef(enumx_impl *This)
75 return InterlockedIncrement(&This->ref);
78 /************************************************************************
79 * enumx_Release
81 ULONG WINAPI enumx_Release(enumx_impl *This)
83 ULONG ref;
85 ref = InterlockedDecrement(&This->ref);
86 if (ref == 0)
88 while (!list_empty(&This->elements))
90 struct list *x = list_head(&This->elements);
91 list_remove(x);
92 HeapFree(GetProcessHeap(), 0, x);
94 HeapFree(GetProcessHeap(), 0, This);
96 return ref;
99 /************************************************************************
100 * enumx_Next
102 HRESULT WINAPI enumx_Next(enumx_impl *This, ULONG celt,
103 void *rgelt, ULONG *pceltFetched)
105 unsigned char *p;
106 ULONG count = 0;
108 TRACE("%p %u %p\n", This, celt, pceltFetched);
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)
115 memcpy(p, &This->current[1], This->elem_size);
116 p += This->elem_size;
117 This->current = This->current->next;
118 count++;
120 if (pceltFetched)
121 *pceltFetched = count;
122 if (count < celt)
123 return S_FALSE;
124 return S_OK;
127 /************************************************************************
128 * enumx_Skip
130 HRESULT WINAPI enumx_Skip(enumx_impl *This, ULONG celt)
132 ULONG count = 0;
134 TRACE("%p %u\n", This, celt);
136 if (This->current == NULL)
137 This->current = list_head(&This->elements);
139 while (count < celt && This->current && This->current != &This->elements)
140 count++;
142 return S_OK;
145 /************************************************************************
146 * enumx_Reset
148 HRESULT WINAPI enumx_Reset(enumx_impl *This)
150 TRACE("\n");
152 This->current = NULL;
153 return S_OK;
156 /************************************************************************
157 * enumx_fnClone
159 HRESULT WINAPI enumx_Clone(
160 enumx_impl *iface,
161 enumx_impl **ppenum)
163 FIXME("\n");
164 return E_NOTIMPL;
167 /************************************************************************
168 * enumx_allocate
170 * Allocate a generic enumerator
172 enumx_impl *enumx_allocate(REFIID riid, const void *vtbl, ULONG elem_size)
174 enumx_impl *enumx;
176 enumx = HeapAlloc(GetProcessHeap(), 0, sizeof *enumx);
177 if (enumx)
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);
187 return enumx;
190 /************************************************************************
191 * enumx_add_element
193 * Add an element to the enumeration.
195 void *enumx_add_element(enumx_impl *enumx, const void *data)
197 struct list *element;
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];