msvcp: Prevent overflows while operating on string sizes.
[wine] / dlls / quartz / enummoniker.c
1 /*
2  * IEnumMoniker implementation
3  *
4  * Copyright 2003 Robert Shearman
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 "quartz_private.h"
24
25 #include "wine/debug.h"
26
27 WINE_DEFAULT_DEBUG_CHANNEL(quartz);
28
29 typedef struct EnumMonikerImpl
30 {
31     IEnumMoniker IEnumMoniker_iface;
32     LONG ref;
33     IMoniker ** ppMoniker;
34     ULONG nMonikerCount;
35     ULONG index;
36 } EnumMonikerImpl;
37
38 static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl;
39
40 static inline EnumMonikerImpl *impl_from_IEnumMoniker(IEnumMoniker *iface)
41 {
42     return CONTAINING_RECORD(iface, EnumMonikerImpl, IEnumMoniker_iface);
43 }
44
45 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface);
46
47 HRESULT EnumMonikerImpl_Create(IMoniker ** ppMoniker, ULONG nMonikerCount, IEnumMoniker ** ppEnum)
48 {
49     /* NOTE: assumes that array of IMonikers has already been AddRef'd
50      * I.e. this function does not AddRef the array of incoming
51      * IMonikers */
52     EnumMonikerImpl * pemi = CoTaskMemAlloc(sizeof(EnumMonikerImpl));
53
54     TRACE("(%p, %d, %p)\n", ppMoniker, nMonikerCount, ppEnum);
55
56     *ppEnum = NULL;
57
58     if (!pemi)
59         return E_OUTOFMEMORY;
60
61     pemi->IEnumMoniker_iface.lpVtbl = &EnumMonikerImpl_Vtbl;
62     pemi->ref = 1;
63     pemi->ppMoniker = CoTaskMemAlloc(nMonikerCount * sizeof(IMoniker*));
64     memcpy(pemi->ppMoniker, ppMoniker, nMonikerCount*sizeof(IMoniker*));
65     pemi->nMonikerCount = nMonikerCount;
66     pemi->index = 0;
67
68     *ppEnum = &pemi->IEnumMoniker_iface;
69
70     return S_OK;
71 }
72
73 /**********************************************************************
74  * IEnumMoniker_QueryInterface (also IUnknown)
75  */
76 static HRESULT WINAPI EnumMonikerImpl_QueryInterface(
77     LPENUMMONIKER iface,
78     REFIID riid,
79     LPVOID *ppvObj)
80 {
81     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
82     TRACE("\n\tIID:\t%s\n",debugstr_guid(riid));
83
84     if (This == NULL || ppvObj == NULL) return E_POINTER;
85
86     if (IsEqualGUID(riid, &IID_IUnknown) ||
87         IsEqualGUID(riid, &IID_IEnumMoniker))
88     {
89         *ppvObj = iface;
90         EnumMonikerImpl_AddRef(iface);
91         return S_OK;
92     }
93
94     *ppvObj = NULL;
95     FIXME("- no interface\n\tIID:\t%s\n", debugstr_guid(riid));
96     return E_NOINTERFACE;
97 }
98
99 /**********************************************************************
100  * IEnumMoniker_AddRef (also IUnknown)
101  */
102 static ULONG WINAPI EnumMonikerImpl_AddRef(LPENUMMONIKER iface)
103 {
104     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
105     ULONG ref;
106
107     if (This == NULL) return E_POINTER;
108
109     ref = InterlockedIncrement(&This->ref);
110
111     TRACE("(%p)->() AddRef from %d\n", iface, ref - 1);
112
113     return ref;
114 }
115
116 /**********************************************************************
117  * IEnumMoniker_Release (also IUnknown)
118  */
119 static ULONG WINAPI EnumMonikerImpl_Release(LPENUMMONIKER iface)
120 {
121     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
122     ULONG ref = InterlockedDecrement(&This->ref);
123
124     TRACE("(%p)->() Release from %d\n", iface, ref + 1);
125
126     if (!ref)
127     {
128         ULONG i;
129
130         for (i = 0; i < This->nMonikerCount; i++)
131             IMoniker_Release(This->ppMoniker[i]);
132
133         CoTaskMemFree(This->ppMoniker);
134         This->ppMoniker = NULL;
135         CoTaskMemFree(This);
136         return 0;
137     }
138     return ref;
139 }
140
141 static HRESULT WINAPI EnumMonikerImpl_Next(LPENUMMONIKER iface, ULONG celt, IMoniker ** rgelt, ULONG * pceltFetched)
142 {
143     ULONG fetched;
144     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
145
146     TRACE("(%p)->(%d, %p, %p)\n", iface, celt, rgelt, pceltFetched);
147
148     for (fetched = 0; (This->index + fetched < This->nMonikerCount) && (fetched < celt); fetched++)
149     {
150         rgelt[fetched] = This->ppMoniker[This->index + fetched];
151         IMoniker_AddRef(rgelt[fetched]);
152     }
153
154     This->index += fetched;
155
156     TRACE("-- fetched %d\n", fetched);
157
158     if (pceltFetched)
159         *pceltFetched = fetched;
160
161     if (fetched != celt)
162         return S_FALSE;
163     else
164         return S_OK;
165 }
166
167 static HRESULT WINAPI EnumMonikerImpl_Skip(LPENUMMONIKER iface, ULONG celt)
168 {
169     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
170
171     TRACE("(%p)->(%d)\n", iface, celt);
172
173     This->index += celt;
174
175     return S_OK;
176 }
177
178 static HRESULT WINAPI EnumMonikerImpl_Reset(LPENUMMONIKER iface)
179 {
180     EnumMonikerImpl *This = impl_from_IEnumMoniker(iface);
181
182     TRACE("(%p)->()\n", iface);
183
184     This->index = 0;
185
186     return S_OK;
187 }
188
189 static HRESULT WINAPI EnumMonikerImpl_Clone(LPENUMMONIKER iface, IEnumMoniker ** ppenum)
190 {
191     FIXME("(%p)->(%p): stub\n", iface, ppenum);
192
193     return E_NOTIMPL;
194 }
195
196 /**********************************************************************
197  * IEnumMoniker_Vtbl
198  */
199 static const IEnumMonikerVtbl EnumMonikerImpl_Vtbl =
200 {
201     EnumMonikerImpl_QueryInterface,
202     EnumMonikerImpl_AddRef,
203     EnumMonikerImpl_Release,
204     EnumMonikerImpl_Next,
205     EnumMonikerImpl_Skip,
206     EnumMonikerImpl_Reset,
207     EnumMonikerImpl_Clone
208 };