wbemprox: Fix corner cases in IEnumWbemClassObject::Skip.
[wine] / dlls / wbemprox / class.c
1 /*
2  * Copyright 2012 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "wbemcli.h"
28
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
33
34 struct enum_class_object
35 {
36     IEnumWbemClassObject IEnumWbemClassObject_iface;
37     LONG refs;
38     struct query *query;
39     UINT index;
40 };
41
42 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
43     IEnumWbemClassObject *iface )
44 {
45     return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
46 }
47
48 static ULONG WINAPI enum_class_object_AddRef(
49     IEnumWbemClassObject *iface )
50 {
51     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
52     return InterlockedIncrement( &ec->refs );
53 }
54
55 static ULONG WINAPI enum_class_object_Release(
56     IEnumWbemClassObject *iface )
57 {
58     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
59     LONG refs = InterlockedDecrement( &ec->refs );
60     if (!refs)
61     {
62         TRACE("destroying %p\n", ec);
63         release_query( ec->query );
64         heap_free( ec );
65     }
66     return refs;
67 }
68
69 static HRESULT WINAPI enum_class_object_QueryInterface(
70     IEnumWbemClassObject *iface,
71     REFIID riid,
72     void **ppvObject )
73 {
74     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
75
76     TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
77
78     if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
79          IsEqualGUID( riid, &IID_IUnknown ) )
80     {
81         *ppvObject = ec;
82     }
83     else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
84     {
85         *ppvObject = &client_security;
86         return S_OK;
87     }
88     else
89     {
90         FIXME("interface %s not implemented\n", debugstr_guid(riid));
91         return E_NOINTERFACE;
92     }
93     IEnumWbemClassObject_AddRef( iface );
94     return S_OK;
95 }
96
97 static HRESULT WINAPI enum_class_object_Reset(
98     IEnumWbemClassObject *iface )
99 {
100     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
101
102     TRACE("%p\n", iface);
103
104     ec->index = 0;
105     return WBEM_S_NO_ERROR;
106 }
107
108 static HRESULT WINAPI enum_class_object_Next(
109     IEnumWbemClassObject *iface,
110     LONG lTimeout,
111     ULONG uCount,
112     IWbemClassObject **apObjects,
113     ULONG *puReturned )
114 {
115     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
116     struct view *view = ec->query->view;
117     HRESULT hr;
118
119     TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
120
121     if (!uCount) return WBEM_S_FALSE;
122     if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
123     if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
124
125     *puReturned = 0;
126     if (ec->index + uCount > view->count) return WBEM_S_FALSE;
127
128     hr = WbemClassObject_create( NULL, iface, ec->index, (void **)apObjects );
129     if (hr != S_OK) return hr;
130
131     ec->index++;
132     *puReturned = 1;
133     if (ec->index == view->count) return WBEM_S_FALSE;
134     if (uCount > 1) return WBEM_S_TIMEDOUT;
135     return WBEM_S_NO_ERROR;
136 }
137
138 static HRESULT WINAPI enum_class_object_NextAsync(
139     IEnumWbemClassObject *iface,
140     ULONG uCount,
141     IWbemObjectSink *pSink )
142 {
143     FIXME("%p, %u, %p\n", iface, uCount, pSink);
144     return E_NOTIMPL;
145 }
146
147 static HRESULT WINAPI enum_class_object_Clone(
148     IEnumWbemClassObject *iface,
149     IEnumWbemClassObject **ppEnum )
150 {
151     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
152
153     TRACE("%p, %p\n", iface, ppEnum);
154
155     return EnumWbemClassObject_create( NULL, ec->query, (void **)ppEnum );
156 }
157
158 static HRESULT WINAPI enum_class_object_Skip(
159     IEnumWbemClassObject *iface,
160     LONG lTimeout,
161     ULONG nCount )
162 {
163     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
164     struct view *view = ec->query->view;
165
166     TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
167
168     if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
169
170     if (!view->count) return WBEM_S_FALSE;
171
172     if (nCount > view->count - ec->index)
173     {
174         ec->index = view->count - 1;
175         return WBEM_S_FALSE;
176     }
177     ec->index += nCount;
178     return WBEM_S_NO_ERROR;
179 }
180
181 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
182 {
183     enum_class_object_QueryInterface,
184     enum_class_object_AddRef,
185     enum_class_object_Release,
186     enum_class_object_Reset,
187     enum_class_object_Next,
188     enum_class_object_NextAsync,
189     enum_class_object_Clone,
190     enum_class_object_Skip
191 };
192
193 HRESULT EnumWbemClassObject_create(
194     IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj )
195 {
196     struct enum_class_object *ec;
197
198     TRACE("%p, %p\n", pUnkOuter, ppObj);
199
200     ec = heap_alloc( sizeof(*ec) );
201     if (!ec) return E_OUTOFMEMORY;
202
203     ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
204     ec->refs  = 1;
205     ec->query = query;
206     addref_query( query );
207     ec->index = 0;
208
209     *ppObj = &ec->IEnumWbemClassObject_iface;
210
211     TRACE("returning iface %p\n", *ppObj);
212     return S_OK;
213 }
214
215 struct class_object
216 {
217     IWbemClassObject IWbemClassObject_iface;
218     LONG refs;
219     IEnumWbemClassObject *iter;
220     UINT index;
221 };
222
223 static inline struct class_object *impl_from_IWbemClassObject(
224     IWbemClassObject *iface )
225 {
226     return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
227 }
228
229 static ULONG WINAPI class_object_AddRef(
230     IWbemClassObject *iface )
231 {
232     struct class_object *co = impl_from_IWbemClassObject( iface );
233     return InterlockedIncrement( &co->refs );
234 }
235
236 static ULONG WINAPI class_object_Release(
237     IWbemClassObject *iface )
238 {
239     struct class_object *co = impl_from_IWbemClassObject( iface );
240     LONG refs = InterlockedDecrement( &co->refs );
241     if (!refs)
242     {
243         TRACE("destroying %p\n", co);
244         if (co->iter) IEnumWbemClassObject_Release( co->iter );
245         heap_free( co );
246     }
247     return refs;
248 }
249
250 static HRESULT WINAPI class_object_QueryInterface(
251     IWbemClassObject *iface,
252     REFIID riid,
253     void **ppvObject )
254 {
255     struct class_object *co = impl_from_IWbemClassObject( iface );
256
257     TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
258
259     if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
260          IsEqualGUID( riid, &IID_IUnknown ) )
261     {
262         *ppvObject = co;
263     }
264     else
265     {
266         FIXME("interface %s not implemented\n", debugstr_guid(riid));
267         return E_NOINTERFACE;
268     }
269     IWbemClassObject_AddRef( iface );
270     return S_OK;
271 }
272
273 static HRESULT WINAPI class_object_GetQualifierSet(
274     IWbemClassObject *iface,
275     IWbemQualifierSet **ppQualSet )
276 {
277     FIXME("%p, %p\n", iface, ppQualSet);
278     return E_NOTIMPL;
279 }
280
281 static HRESULT WINAPI class_object_Get(
282     IWbemClassObject *iface,
283     LPCWSTR wszName,
284     LONG lFlags,
285     VARIANT *pVal,
286     CIMTYPE *pType,
287     LONG *plFlavor )
288 {
289     struct class_object *co = impl_from_IWbemClassObject( iface );
290     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
291     struct view *view = ec->query->view;
292
293     TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
294
295     return get_propval( view, co->index, wszName, pVal, pType, plFlavor );
296 }
297
298 static HRESULT WINAPI class_object_Put(
299     IWbemClassObject *iface,
300     LPCWSTR wszName,
301     LONG lFlags,
302     VARIANT *pVal,
303     CIMTYPE Type )
304 {
305     struct class_object *co = impl_from_IWbemClassObject( iface );
306     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
307     struct view *view = ec->query->view;
308
309     TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
310
311     return put_propval( view, co->index, wszName, pVal, Type );
312 }
313
314 static HRESULT WINAPI class_object_Delete(
315     IWbemClassObject *iface,
316     LPCWSTR wszName )
317 {
318     FIXME("%p, %s\n", iface, debugstr_w(wszName));
319     return E_NOTIMPL;
320 }
321
322 static HRESULT WINAPI class_object_GetNames(
323     IWbemClassObject *iface,
324     LPCWSTR wszQualifierName,
325     LONG lFlags,
326     VARIANT *pQualifierVal,
327     SAFEARRAY **pNames )
328 {
329     struct class_object *co = impl_from_IWbemClassObject( iface );
330     struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
331
332     TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames);
333
334     if (wszQualifierName || pQualifierVal)
335     {
336         FIXME("qualifier not supported\n");
337         return E_NOTIMPL;
338     }
339     if (lFlags != WBEM_FLAG_ALWAYS)
340     {
341         FIXME("flags %08x not supported\n", lFlags);
342         return E_NOTIMPL;
343     }
344     return get_properties( ec->query->view, pNames );
345 }
346
347 static HRESULT WINAPI class_object_BeginEnumeration(
348     IWbemClassObject *iface,
349     LONG lEnumFlags )
350 {
351     FIXME("%p, %08x\n", iface, lEnumFlags);
352     return E_NOTIMPL;
353 }
354
355 static HRESULT WINAPI class_object_Next(
356     IWbemClassObject *iface,
357     LONG lFlags,
358     BSTR *strName,
359     VARIANT *pVal,
360     CIMTYPE *pType,
361     LONG *plFlavor )
362 {
363     FIXME("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
364     return E_NOTIMPL;
365 }
366
367 static HRESULT WINAPI class_object_EndEnumeration(
368     IWbemClassObject *iface )
369 {
370     FIXME("%p\n", iface);
371     return E_NOTIMPL;
372 }
373
374 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
375     IWbemClassObject *iface,
376     LPCWSTR wszProperty,
377     IWbemQualifierSet **ppQualSet )
378 {
379     FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
380     return E_NOTIMPL;
381 }
382
383 static HRESULT WINAPI class_object_Clone(
384     IWbemClassObject *iface,
385     IWbemClassObject **ppCopy )
386 {
387     FIXME("%p, %p\n", iface, ppCopy);
388     return E_NOTIMPL;
389 }
390
391 static HRESULT WINAPI class_object_GetObjectText(
392     IWbemClassObject *iface,
393     LONG lFlags,
394     BSTR *pstrObjectText )
395 {
396     FIXME("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
397     return E_NOTIMPL;
398 }
399
400 static HRESULT WINAPI class_object_SpawnDerivedClass(
401     IWbemClassObject *iface,
402     LONG lFlags,
403     IWbemClassObject **ppNewClass )
404 {
405     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
406     return E_NOTIMPL;
407 }
408
409 static HRESULT WINAPI class_object_SpawnInstance(
410     IWbemClassObject *iface,
411     LONG lFlags,
412     IWbemClassObject **ppNewInstance )
413 {
414     FIXME("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
415     return E_NOTIMPL;
416 }
417
418 static HRESULT WINAPI class_object_CompareTo(
419     IWbemClassObject *iface,
420     LONG lFlags,
421     IWbemClassObject *pCompareTo )
422 {
423     FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
424     return E_NOTIMPL;
425 }
426
427 static HRESULT WINAPI class_object_GetPropertyOrigin(
428     IWbemClassObject *iface,
429     LPCWSTR wszName,
430     BSTR *pstrClassName )
431 {
432     FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
433     return E_NOTIMPL;
434 }
435
436 static HRESULT WINAPI class_object_InheritsFrom(
437     IWbemClassObject *iface,
438     LPCWSTR strAncestor )
439 {
440     FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
441     return E_NOTIMPL;
442 }
443
444 static HRESULT WINAPI class_object_GetMethod(
445     IWbemClassObject *iface,
446     LPCWSTR wszName,
447     LONG lFlags,
448     IWbemClassObject **ppInSignature,
449     IWbemClassObject **ppOutSignature )
450 {
451     FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
452     return E_NOTIMPL;
453 }
454
455 static HRESULT WINAPI class_object_PutMethod(
456     IWbemClassObject *iface,
457     LPCWSTR wszName,
458     LONG lFlags,
459     IWbemClassObject *pInSignature,
460     IWbemClassObject *pOutSignature )
461 {
462     FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
463     return E_NOTIMPL;
464 }
465
466 static HRESULT WINAPI class_object_DeleteMethod(
467     IWbemClassObject *iface,
468     LPCWSTR wszName )
469 {
470     FIXME("%p, %s\n", iface, debugstr_w(wszName));
471     return E_NOTIMPL;
472 }
473
474 static HRESULT WINAPI class_object_BeginMethodEnumeration(
475     IWbemClassObject *iface,
476     LONG lEnumFlags)
477 {
478     FIXME("%p, %08x\n", iface, lEnumFlags);
479     return E_NOTIMPL;
480 }
481
482 static HRESULT WINAPI class_object_NextMethod(
483     IWbemClassObject *iface,
484     LONG lFlags,
485     BSTR *pstrName,
486     IWbemClassObject **ppInSignature,
487     IWbemClassObject **ppOutSignature)
488 {
489     FIXME("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
490     return E_NOTIMPL;
491 }
492
493 static HRESULT WINAPI class_object_EndMethodEnumeration(
494     IWbemClassObject *iface )
495 {
496     FIXME("%p\n", iface);
497     return E_NOTIMPL;
498 }
499
500 static HRESULT WINAPI class_object_GetMethodQualifierSet(
501     IWbemClassObject *iface,
502     LPCWSTR wszMethod,
503     IWbemQualifierSet **ppQualSet)
504 {
505     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
506     return E_NOTIMPL;
507 }
508
509 static HRESULT WINAPI class_object_GetMethodOrigin(
510     IWbemClassObject *iface,
511     LPCWSTR wszMethodName,
512     BSTR *pstrClassName)
513 {
514     FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
515     return E_NOTIMPL;
516 }
517
518 static const IWbemClassObjectVtbl class_object_vtbl =
519 {
520     class_object_QueryInterface,
521     class_object_AddRef,
522     class_object_Release,
523     class_object_GetQualifierSet,
524     class_object_Get,
525     class_object_Put,
526     class_object_Delete,
527     class_object_GetNames,
528     class_object_BeginEnumeration,
529     class_object_Next,
530     class_object_EndEnumeration,
531     class_object_GetPropertyQualifierSet,
532     class_object_Clone,
533     class_object_GetObjectText,
534     class_object_SpawnDerivedClass,
535     class_object_SpawnInstance,
536     class_object_CompareTo,
537     class_object_GetPropertyOrigin,
538     class_object_InheritsFrom,
539     class_object_GetMethod,
540     class_object_PutMethod,
541     class_object_DeleteMethod,
542     class_object_BeginMethodEnumeration,
543     class_object_NextMethod,
544     class_object_EndMethodEnumeration,
545     class_object_GetMethodQualifierSet,
546     class_object_GetMethodOrigin
547 };
548
549 HRESULT WbemClassObject_create(
550     IUnknown *pUnkOuter, IEnumWbemClassObject *iter, UINT index, LPVOID *ppObj )
551 {
552     struct class_object *co;
553
554     TRACE("%p, %p\n", pUnkOuter, ppObj);
555
556     co = heap_alloc( sizeof(*co) );
557     if (!co) return E_OUTOFMEMORY;
558
559     co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
560     co->refs  = 1;
561     co->iter  = iter;
562     co->index = index;
563     if (iter) IEnumWbemClassObject_AddRef( iter );
564
565     *ppObj = &co->IWbemClassObject_iface;
566
567     TRACE("returning iface %p\n", *ppObj);
568     return S_OK;
569 }