iSelectedImage is allowed to be 0.
[wine] / dlls / quartz / enummoniker.c
1 /*
2  * IEnumMoniker implementation
3  *
4  * Copyright 2003 Robert Shearman
5  *
6  * This file contains the (internal) driver registration functions,
7  * driver enumeration APIs and DirectDraw creation functions.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23
24 #include <stdarg.h>
25
26 #define COBJMACROS
27 #define COM_NO_WINDOWS_H
28
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "ole2.h"
33 #include "strmif.h"
34
35 #include "wine/debug.h"
36
37 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
38
39 typedef struct EnumMonikerImpl
40 {
41     IEnumMonikerVtbl *lpVtbl;
42     ULONG ref;
43     IMoniker ** ppMoniker;
44     ULONG nMonikerCount;
45     ULONG index;
46 } EnumMonikerImpl;
47
48 static struct IEnumMonikerVtbl EnumMonikerImpl_Vtbl;
49
50 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface);
51
52 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum)
53 {
54     /* NOTE: assumes that array of IMonikers has already been AddRef'd
55      * I.e. this function does not AddRef the array of incoming
56      * IMonikers */
57     EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
58
59     TRACE("(%p, %ld, %p)\n", ppMoniker, nMonikerCount, ppEnum);
60
61     *ppEnum = NULL;
62
63     if (!pemi)
64         return E_OUTOFMEMORY;
65
66     pemi->lpVtbl = &EnumMonikerImpl_Vtbl;
67     pemi->ref = 1;
68     pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*));
69     memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*));
70     pemi->nMonikerCount = nMonikerCount;
71     pemi->index = 0;
72
73     *ppEnum = (IEnumMoniker *)pemi;
74
75     return S_OK;
76 }
77
78 /**********************************************************************
79  * IEnumMoniker_QueryInterface (also IUnknown)
80  */
81 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
82     LPENUMMONIKER iface,
83     REFIID riid,
84     LPVOID *ppvObj)
85 {
86     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
87     TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
88
89     if (This == NULL || ppvObj == NULL) return E_POINTER;
90
91     if (IsEqualGUID(riid, &IID_IUnknown) ||
92         IsEqualGUID(riid, &IID_IEnumMoniker))
93     {
94         *ppvObj = (LPVOID)iface;
95         EnumMonikerImpl_AddRef(iface);
96         return S_OK;
97     }
98
99     FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
100     return E_NOINTERFACE;
101 }
102
103 /**********************************************************************
104  * IEnumMoniker_AddRef (also IUnknown)
105  */
106 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface)
107 {
108     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
109     ULONG ref;
110
111     if (This == NULL) return E_POINTER;
112
113     ref = InterlockedIncrement(&This->ref);
114
115     TRACE("(%p)->() AddRef from %ld\n", iface, ref - 1);
116
117     return ref;
118 }
119
120 /**********************************************************************
121  * IEnumMoniker_Release (also IUnknown)
122  */
123 static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface)
124 {
125     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
126     ULONG ref = InterlockedDecrement(&This->ref);
127
128     TRACE("(%p)->() Release from %ld\n", iface, ref + 1);
129
130     if (!ref)
131     {
132         CoTaskMemFree(This->ppMoniker);
133         This->ppMoniker = NULL;
134         CoTaskMemFree(This);
135         return 0;
136     }
137     return ref;
138 }
139
140 static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
141 {
142     ULONG fetched;
143     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
144
145     TRACE("(%p)->(%ld, %p, %p)\n", iface, celt, rgelt, pceltFetched);
146
147     for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++)
148     {
149         rgelt[fetched] = This->ppMoniker[This->index + fetched];
150         IMoniker_AddRef(rgelt[fetched]);
151     }
152
153     This->index += fetched;
154
155     TRACE("-- fetched %ld\n", fetched);
156
157     if (pceltFetched)
158         *pceltFetched = fetched;
159
160     if (fetched != celt)
161         return S_FALSE;
162     else
163         return S_OK;
164 }
165
166 static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
167 {
168     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
169
170     TRACE("(%p)->(%ld)\n", iface, celt);
171
172     This->index += celt;
173
174     return S_OK;
175 }
176
177 static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
178 {
179     EnumMonikerImpl *This = (EnumMonikerImpl *)iface;
180
181     TRACE("(%p)->()\n", iface);
182
183     This->index = 0;
184
185     return S_OK;
186 }
187
188 static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
189 {
190     FIXME("(%p)->(%p): stub\n", iface, ppenum);
191
192     return E_NOTIMPL;
193 }
194
195 /**********************************************************************
196  * IEnumMoniker_Vtbl
197  */
198 static IEnumMonikerVtbl EnumMonikerImpl_Vtbl =
199 {
200     EnumMonikerImpl_QueryInterface,
201     EnumMonikerImpl_AddRef,
202     EnumMonikerImpl_Release,
203     EnumMonikerImpl_Next,
204     EnumMonikerImpl_Skip,
205     EnumMonikerImpl_Reset,
206     EnumMonikerImpl_Clone
207 };