[WBEMPROX]
[reactos.git] / reactos / dll / win32 / 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 WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #define COBJMACROS
24
25 #include "config.h"
26 #include <stdarg.h>
27
28 #include "windef.h"
29 #include "winbase.h"
30 #include "ole2.h"
31 #include "wbemcli.h"
32
33 #include "wine/debug.h"
34 #include "wbemprox_private.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
37
38 struct enum_class_object
39 {
40 IEnumWbemClassObject IEnumWbemClassObject_iface;
41 LONG refs;
42 struct query *query;
43 UINT index;
44 };
45
46 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
47 IEnumWbemClassObject *iface )
48 {
49 return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
50 }
51
52 static ULONG WINAPI enum_class_object_AddRef(
53 IEnumWbemClassObject *iface )
54 {
55 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
56 return InterlockedIncrement( &ec->refs );
57 }
58
59 static ULONG WINAPI enum_class_object_Release(
60 IEnumWbemClassObject *iface )
61 {
62 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
63 LONG refs = InterlockedDecrement( &ec->refs );
64 if (!refs)
65 {
66 TRACE("destroying %p\n", ec);
67 release_query( ec->query );
68 heap_free( ec );
69 }
70 return refs;
71 }
72
73 static HRESULT WINAPI enum_class_object_QueryInterface(
74 IEnumWbemClassObject *iface,
75 REFIID riid,
76 void **ppvObject )
77 {
78 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
79
80 TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
81
82 if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
83 IsEqualGUID( riid, &IID_IUnknown ) )
84 {
85 *ppvObject = ec;
86 }
87 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
88 {
89 *ppvObject = &client_security;
90 return S_OK;
91 }
92 else
93 {
94 FIXME("interface %s not implemented\n", debugstr_guid(riid));
95 return E_NOINTERFACE;
96 }
97 IEnumWbemClassObject_AddRef( iface );
98 return S_OK;
99 }
100
101 static HRESULT WINAPI enum_class_object_Reset(
102 IEnumWbemClassObject *iface )
103 {
104 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
105
106 TRACE("%p\n", iface);
107
108 ec->index = 0;
109 return WBEM_S_NO_ERROR;
110 }
111
112 static HRESULT WINAPI enum_class_object_Next(
113 IEnumWbemClassObject *iface,
114 LONG lTimeout,
115 ULONG uCount,
116 IWbemClassObject **apObjects,
117 ULONG *puReturned )
118 {
119 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
120 struct view *view = ec->query->view;
121 HRESULT hr;
122
123 TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
124
125 if (!uCount) return WBEM_S_FALSE;
126 if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
127 if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
128
129 *puReturned = 0;
130 if (ec->index >= view->count) return WBEM_S_FALSE;
131
132 hr = create_class_object( view->table->name, iface, ec->index, NULL, apObjects );
133 if (hr != S_OK) return hr;
134
135 ec->index++;
136 *puReturned = 1;
137 if (ec->index == view->count) return WBEM_S_FALSE;
138 if (uCount > 1) return WBEM_S_TIMEDOUT;
139 return WBEM_S_NO_ERROR;
140 }
141
142 static HRESULT WINAPI enum_class_object_NextAsync(
143 IEnumWbemClassObject *iface,
144 ULONG uCount,
145 IWbemObjectSink *pSink )
146 {
147 FIXME("%p, %u, %p\n", iface, uCount, pSink);
148 return E_NOTIMPL;
149 }
150
151 static HRESULT WINAPI enum_class_object_Clone(
152 IEnumWbemClassObject *iface,
153 IEnumWbemClassObject **ppEnum )
154 {
155 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
156
157 TRACE("%p, %p\n", iface, ppEnum);
158
159 return EnumWbemClassObject_create( NULL, ec->query, (void **)ppEnum );
160 }
161
162 static HRESULT WINAPI enum_class_object_Skip(
163 IEnumWbemClassObject *iface,
164 LONG lTimeout,
165 ULONG nCount )
166 {
167 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
168 struct view *view = ec->query->view;
169
170 TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
171
172 if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
173
174 if (!view->count) return WBEM_S_FALSE;
175
176 if (nCount > view->count - ec->index)
177 {
178 ec->index = view->count - 1;
179 return WBEM_S_FALSE;
180 }
181 ec->index += nCount;
182 return WBEM_S_NO_ERROR;
183 }
184
185 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
186 {
187 enum_class_object_QueryInterface,
188 enum_class_object_AddRef,
189 enum_class_object_Release,
190 enum_class_object_Reset,
191 enum_class_object_Next,
192 enum_class_object_NextAsync,
193 enum_class_object_Clone,
194 enum_class_object_Skip
195 };
196
197 HRESULT EnumWbemClassObject_create(
198 IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj )
199 {
200 struct enum_class_object *ec;
201
202 TRACE("%p, %p\n", pUnkOuter, ppObj);
203
204 ec = heap_alloc( sizeof(*ec) );
205 if (!ec) return E_OUTOFMEMORY;
206
207 ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
208 ec->refs = 1;
209 ec->query = addref_query( query );
210 ec->index = 0;
211
212 *ppObj = &ec->IEnumWbemClassObject_iface;
213
214 TRACE("returning iface %p\n", *ppObj);
215 return S_OK;
216 }
217
218 static struct record *create_record( struct table *table )
219 {
220 UINT i;
221 struct record *record;
222
223 if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
224 if (!(record->fields = heap_alloc( table->num_cols * sizeof(struct field) )))
225 {
226 heap_free( record );
227 return NULL;
228 }
229 for (i = 0; i < table->num_cols; i++)
230 {
231 record->fields[i].type = table->columns[i].type;
232 record->fields[i].vartype = table->columns[i].vartype;
233 record->fields[i].u.ival = 0;
234 }
235 record->count = table->num_cols;
236 record->table = addref_table( table );
237 return record;
238 }
239
240 void destroy_array( struct array *array, CIMTYPE type )
241 {
242 UINT i, size;
243
244 if (!array) return;
245 if (type == CIM_STRING || type == CIM_DATETIME)
246 {
247 size = get_type_size( type );
248 for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * size) );
249 }
250 heap_free( array->ptr );
251 heap_free( array );
252 }
253
254 static void destroy_record( struct record *record )
255 {
256 UINT i;
257
258 if (!record) return;
259 release_table( record->table );
260 for (i = 0; i < record->count; i++)
261 {
262 if (record->fields[i].type == CIM_STRING || record->fields[i].type == CIM_DATETIME)
263 heap_free( record->fields[i].u.sval );
264 else if (record->fields[i].type & CIM_FLAG_ARRAY)
265 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
266 }
267 heap_free( record->fields );
268 heap_free( record );
269 }
270
271 struct class_object
272 {
273 IWbemClassObject IWbemClassObject_iface;
274 LONG refs;
275 WCHAR *name;
276 IEnumWbemClassObject *iter;
277 UINT index;
278 UINT index_method;
279 UINT index_property;
280 struct record *record; /* uncommitted instance */
281 };
282
283 static inline struct class_object *impl_from_IWbemClassObject(
284 IWbemClassObject *iface )
285 {
286 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
287 }
288
289 static ULONG WINAPI class_object_AddRef(
290 IWbemClassObject *iface )
291 {
292 struct class_object *co = impl_from_IWbemClassObject( iface );
293 return InterlockedIncrement( &co->refs );
294 }
295
296 static ULONG WINAPI class_object_Release(
297 IWbemClassObject *iface )
298 {
299 struct class_object *co = impl_from_IWbemClassObject( iface );
300 LONG refs = InterlockedDecrement( &co->refs );
301 if (!refs)
302 {
303 TRACE("destroying %p\n", co);
304 if (co->iter) IEnumWbemClassObject_Release( co->iter );
305 destroy_record( co->record );
306 heap_free( co->name );
307 heap_free( co );
308 }
309 return refs;
310 }
311
312 static HRESULT WINAPI class_object_QueryInterface(
313 IWbemClassObject *iface,
314 REFIID riid,
315 void **ppvObject )
316 {
317 struct class_object *co = impl_from_IWbemClassObject( iface );
318
319 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
320
321 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
322 IsEqualGUID( riid, &IID_IUnknown ) )
323 {
324 *ppvObject = co;
325 }
326 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
327 {
328 *ppvObject = &client_security;
329 return S_OK;
330 }
331 else
332 {
333 FIXME("interface %s not implemented\n", debugstr_guid(riid));
334 return E_NOINTERFACE;
335 }
336 IWbemClassObject_AddRef( iface );
337 return S_OK;
338 }
339
340 static HRESULT WINAPI class_object_GetQualifierSet(
341 IWbemClassObject *iface,
342 IWbemQualifierSet **ppQualSet )
343 {
344 FIXME("%p, %p\n", iface, ppQualSet);
345 return E_NOTIMPL;
346 }
347
348 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
349 {
350 VARTYPE vartype = record->fields[index].vartype;
351
352 if (type) *type = record->fields[index].type;
353
354 if (record->fields[index].type & CIM_FLAG_ARRAY)
355 {
356 V_VT( var ) = vartype ? vartype : to_vartype( record->fields[index].type & CIM_TYPE_MASK ) | VT_ARRAY;
357 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & CIM_TYPE_MASK );
358 return S_OK;
359 }
360 switch (record->fields[index].type)
361 {
362 case CIM_STRING:
363 case CIM_DATETIME:
364 if (!vartype) vartype = VT_BSTR;
365 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
366 break;
367 case CIM_SINT32:
368 if (!vartype) vartype = VT_I4;
369 V_I4( var ) = record->fields[index].u.ival;
370 break;
371 case CIM_UINT32:
372 if (!vartype) vartype = VT_UI4;
373 V_UI4( var ) = record->fields[index].u.ival;
374 break;
375 default:
376 FIXME("unhandled type %u\n", record->fields[index].type);
377 return WBEM_E_INVALID_PARAMETER;
378 }
379 V_VT( var ) = vartype;
380 return S_OK;
381 }
382
383 static HRESULT WINAPI class_object_Get(
384 IWbemClassObject *iface,
385 LPCWSTR wszName,
386 LONG lFlags,
387 VARIANT *pVal,
388 CIMTYPE *pType,
389 LONG *plFlavor )
390 {
391 struct class_object *co = impl_from_IWbemClassObject( iface );
392 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
393
394 TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
395
396 if (co->record)
397 {
398 UINT index;
399 HRESULT hr;
400
401 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
402 return record_get_value( co->record, index, pVal, pType );
403 }
404 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
405 }
406
407 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
408 {
409 LONGLONG val;
410 CIMTYPE type;
411 HRESULT hr;
412
413 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
414 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
415
416 if (type & CIM_FLAG_ARRAY)
417 {
418 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
419 return S_OK;
420 }
421 switch (type)
422 {
423 case CIM_STRING:
424 case CIM_DATETIME:
425 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
426 return S_OK;
427 case CIM_SINT16:
428 case CIM_UINT16:
429 case CIM_SINT32:
430 case CIM_UINT32:
431 record->fields[index].u.ival = val;
432 return S_OK;
433 default:
434 FIXME("unhandled type %u\n", type);
435 break;
436 }
437 return WBEM_E_INVALID_PARAMETER;
438 }
439
440 static HRESULT WINAPI class_object_Put(
441 IWbemClassObject *iface,
442 LPCWSTR wszName,
443 LONG lFlags,
444 VARIANT *pVal,
445 CIMTYPE Type )
446 {
447 struct class_object *co = impl_from_IWbemClassObject( iface );
448 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
449
450 TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
451
452 if (co->record)
453 {
454 UINT index;
455 HRESULT hr;
456
457 if ((hr = get_column_index( co->record->table, wszName, &index )) != S_OK) return hr;
458 return record_set_value( co->record, index, pVal );
459 }
460 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
461 }
462
463 static HRESULT WINAPI class_object_Delete(
464 IWbemClassObject *iface,
465 LPCWSTR wszName )
466 {
467 FIXME("%p, %s\n", iface, debugstr_w(wszName));
468 return E_NOTIMPL;
469 }
470
471 static HRESULT WINAPI class_object_GetNames(
472 IWbemClassObject *iface,
473 LPCWSTR wszQualifierName,
474 LONG lFlags,
475 VARIANT *pQualifierVal,
476 SAFEARRAY **pNames )
477 {
478 struct class_object *co = impl_from_IWbemClassObject( iface );
479 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
480
481 TRACE("%p, %s, %08x, %s, %p\n", iface, debugstr_w(wszQualifierName), lFlags,
482 debugstr_variant(pQualifierVal), pNames);
483
484 if (wszQualifierName || pQualifierVal)
485 {
486 FIXME("qualifier not supported\n");
487 return E_NOTIMPL;
488 }
489 if (lFlags != WBEM_FLAG_ALWAYS)
490 {
491 FIXME("flags %08x not supported\n", lFlags);
492 return E_NOTIMPL;
493 }
494 return get_properties( ec->query->view, pNames );
495 }
496
497 static HRESULT WINAPI class_object_BeginEnumeration(
498 IWbemClassObject *iface,
499 LONG lEnumFlags )
500 {
501 struct class_object *co = impl_from_IWbemClassObject( iface );
502
503 TRACE("%p, %08x\n", iface, lEnumFlags);
504
505 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
506
507 co->index_property = 0;
508 return S_OK;
509 }
510
511 static HRESULT WINAPI class_object_Next(
512 IWbemClassObject *iface,
513 LONG lFlags,
514 BSTR *strName,
515 VARIANT *pVal,
516 CIMTYPE *pType,
517 LONG *plFlavor )
518 {
519 struct class_object *co = impl_from_IWbemClassObject( iface );
520 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
521 struct view *view = ec->query->view;
522 BSTR property;
523 HRESULT hr;
524
525 TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
526
527 if (!(property = get_property_name( co->name, co->index_property ))) return WBEM_S_NO_MORE_DATA;
528 if ((hr = get_propval( view, co->index, property, pVal, pType, plFlavor ) != S_OK))
529 {
530 SysFreeString( property );
531 return hr;
532 }
533 *strName = property;
534 co->index_property++;
535 return S_OK;
536 }
537
538 static HRESULT WINAPI class_object_EndEnumeration(
539 IWbemClassObject *iface )
540 {
541 struct class_object *co = impl_from_IWbemClassObject( iface );
542
543 TRACE("%p\n", iface);
544
545 co->index_property = 0;
546 return S_OK;
547 }
548
549 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
550 IWbemClassObject *iface,
551 LPCWSTR wszProperty,
552 IWbemQualifierSet **ppQualSet )
553 {
554 struct class_object *co = impl_from_IWbemClassObject( iface );
555
556 TRACE("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
557
558 return WbemQualifierSet_create( NULL, co->name, wszProperty, (void **)ppQualSet );
559 }
560
561 static HRESULT WINAPI class_object_Clone(
562 IWbemClassObject *iface,
563 IWbemClassObject **ppCopy )
564 {
565 FIXME("%p, %p\n", iface, ppCopy);
566 return E_NOTIMPL;
567 }
568
569 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
570 {
571 static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
572 BSTR value, ret;
573 WCHAR *p;
574 UINT i;
575
576 *len = 0;
577 for (i = 0; i < table->num_cols; i++)
578 {
579 if ((value = get_value_bstr( table, row, i )))
580 {
581 *len += sizeof(fmtW) / sizeof(fmtW[0]);
582 *len += strlenW( table->columns[i].name );
583 *len += SysStringLen( value );
584 SysFreeString( value );
585 }
586 }
587 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
588 p = ret;
589 for (i = 0; i < table->num_cols; i++)
590 {
591 if ((value = get_value_bstr( table, row, i )))
592 {
593 p += sprintfW( p, fmtW, table->columns[i].name, value );
594 SysFreeString( value );
595 }
596 }
597 return ret;
598 }
599
600 static BSTR get_object_text( const struct view *view, UINT index )
601 {
602 static const WCHAR fmtW[] =
603 {'\n','i','n','s','t','a','n','c','e',' ','o','f',' ','%','s','\n','{','%','s','\n','}',';',0};
604 UINT len, len_body, row = view->result[index];
605 BSTR ret, body;
606
607 len = sizeof(fmtW) / sizeof(fmtW[0]);
608 len += strlenW( view->table->name );
609 if (!(body = get_body_text( view->table, row, &len_body ))) return NULL;
610 len += len_body;
611
612 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
613 sprintfW( ret, fmtW, view->table->name, body );
614 SysFreeString( body );
615 return ret;
616 }
617
618 static HRESULT WINAPI class_object_GetObjectText(
619 IWbemClassObject *iface,
620 LONG lFlags,
621 BSTR *pstrObjectText )
622 {
623 struct class_object *co = impl_from_IWbemClassObject( iface );
624 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
625 struct view *view = ec->query->view;
626 BSTR text;
627
628 TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
629
630 if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
631
632 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
633 *pstrObjectText = text;
634 return S_OK;
635 }
636
637 static HRESULT WINAPI class_object_SpawnDerivedClass(
638 IWbemClassObject *iface,
639 LONG lFlags,
640 IWbemClassObject **ppNewClass )
641 {
642 FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
643 return E_NOTIMPL;
644 }
645
646 static HRESULT WINAPI class_object_SpawnInstance(
647 IWbemClassObject *iface,
648 LONG lFlags,
649 IWbemClassObject **ppNewInstance )
650 {
651 struct class_object *co = impl_from_IWbemClassObject( iface );
652 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
653 struct view *view = ec->query->view;
654 struct record *record;
655
656 TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
657
658 if (!(record = create_record( view->table ))) return E_OUTOFMEMORY;
659
660 return create_class_object( co->name, NULL, 0, record, ppNewInstance );
661 }
662
663 static HRESULT WINAPI class_object_CompareTo(
664 IWbemClassObject *iface,
665 LONG lFlags,
666 IWbemClassObject *pCompareTo )
667 {
668 FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
669 return E_NOTIMPL;
670 }
671
672 static HRESULT WINAPI class_object_GetPropertyOrigin(
673 IWbemClassObject *iface,
674 LPCWSTR wszName,
675 BSTR *pstrClassName )
676 {
677 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
678 return E_NOTIMPL;
679 }
680
681 static HRESULT WINAPI class_object_InheritsFrom(
682 IWbemClassObject *iface,
683 LPCWSTR strAncestor )
684 {
685 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
686 return E_NOTIMPL;
687 }
688
689 static UINT count_instances( IEnumWbemClassObject *iter )
690 {
691 UINT count = 0;
692 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
693 IEnumWbemClassObject_Reset( iter );
694 return count;
695 }
696
697 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
698 {
699 switch (type)
700 {
701 case CIM_SINT16:
702 *(INT16 *)ptr = val;
703 break;
704 case CIM_UINT16:
705 *(UINT16 *)ptr = val;
706 break;
707 case CIM_SINT32:
708 *(INT32 *)ptr = val;
709 break;
710 case CIM_UINT32:
711 *(UINT32 *)ptr = val;
712 break;
713 default:
714 FIXME("unhandled type %u\n", type);
715 break;
716 }
717 }
718
719 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
720 struct column **cols, BYTE **data )
721 {
722 static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
723 static const WCHAR typeW[] = {'T','y','p','e',0};
724 static const WCHAR varianttypeW[] = {'V','a','r','i','a','n','t','T','y','p','e',0};
725 static const WCHAR defaultvalueW[] = {'D','e','f','a','u','l','t','V','a','l','u','e',0};
726 struct column *columns;
727 BYTE *row;
728 IWbemClassObject *param;
729 VARIANT val;
730 HRESULT hr = E_OUTOFMEMORY;
731 UINT offset = 0;
732 ULONG count;
733 int i = 0;
734
735 count = count_instances( iter );
736 if (!(columns = heap_alloc( count * sizeof(struct column) ))) return E_OUTOFMEMORY;
737 if (!(row = heap_alloc_zero( count * sizeof(LONGLONG) ))) goto error;
738
739 for (;;)
740 {
741 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
742 if (!count) break;
743
744 hr = IWbemClassObject_Get( param, parameterW, 0, &val, NULL, NULL );
745 if (hr != S_OK) goto error;
746 columns[i].name = heap_strdupW( V_BSTR( &val ) );
747 VariantClear( &val );
748
749 hr = IWbemClassObject_Get( param, typeW, 0, &val, NULL, NULL );
750 if (hr != S_OK) goto error;
751 columns[i].type = V_UI4( &val );
752
753 hr = IWbemClassObject_Get( param, varianttypeW, 0, &val, NULL, NULL );
754 if (hr != S_OK) goto error;
755 columns[i].vartype = V_UI4( &val );
756
757 hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
758 if (hr != S_OK) goto error;
759 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
760 offset += get_type_size( columns[i].type );
761
762 IWbemClassObject_Release( param );
763 i++;
764 }
765 *num_cols = i;
766 *cols = columns;
767 *data = row;
768 return S_OK;
769
770 error:
771 for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
772 heap_free( columns );
773 heap_free( row );
774 return hr;
775 }
776
777 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
778 {
779 HRESULT hr;
780 struct table *table;
781 struct column *columns;
782 UINT num_cols;
783 BYTE *row;
784
785 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
786 if (hr != S_OK) return hr;
787
788 if (!(table = create_table( name, num_cols, columns, 1, row, NULL )))
789 {
790 free_columns( columns, num_cols );
791 heap_free( row );
792 return E_OUTOFMEMORY;
793 }
794 if (!add_table( table )) free_table( table ); /* already exists */
795 return S_OK;
796 }
797
798 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
799 {
800 static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
801 static const WCHAR outW[] = {'O','U','T',0};
802 static const WCHAR inW[] = {'I','N',0};
803 UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
804 WCHAR *ret;
805
806 if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
807 sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
808 return struprW( ret );
809 }
810
811 HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
812 IWbemClassObject **sig )
813 {
814 static const WCHAR selectW[] =
815 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
816 '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
817 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
818 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
819 'D','i','r','e','c','t','i','o','n','%','s',0};
820 static const WCHAR geW[] = {'>','=','0',0};
821 static const WCHAR leW[] = {'<','=','0',0};
822 UINT len = SIZEOF(selectW) + SIZEOF(geW);
823 IEnumWbemClassObject *iter;
824 WCHAR *query, *name;
825 HRESULT hr;
826
827 len += strlenW( class ) + strlenW( method );
828 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
829 sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
830
831 hr = exec_query( query, &iter );
832 heap_free( query );
833 if (hr != S_OK) return hr;
834
835 if (!(name = build_signature_table_name( class, method, dir )))
836 {
837 IEnumWbemClassObject_Release( iter );
838 return E_OUTOFMEMORY;
839 }
840 hr = create_signature_table( iter, name );
841 IEnumWbemClassObject_Release( iter );
842 if (hr == S_OK)
843 hr = get_object( name, sig );
844
845 heap_free( name );
846 return hr;
847 }
848
849 static HRESULT WINAPI class_object_GetMethod(
850 IWbemClassObject *iface,
851 LPCWSTR wszName,
852 LONG lFlags,
853 IWbemClassObject **ppInSignature,
854 IWbemClassObject **ppOutSignature )
855 {
856 struct class_object *co = impl_from_IWbemClassObject( iface );
857 IWbemClassObject *in, *out;
858 HRESULT hr;
859
860 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
861
862 hr = create_signature( co->name, wszName, PARAM_IN, &in );
863 if (hr != S_OK) return hr;
864
865 hr = create_signature( co->name, wszName, PARAM_OUT, &out );
866 if (hr == S_OK)
867 {
868 if (ppInSignature) *ppInSignature = in;
869 else IWbemClassObject_Release( in );
870 if (ppOutSignature) *ppOutSignature = out;
871 else IWbemClassObject_Release( out );
872 }
873 else IWbemClassObject_Release( in );
874 return hr;
875 }
876
877 static HRESULT WINAPI class_object_PutMethod(
878 IWbemClassObject *iface,
879 LPCWSTR wszName,
880 LONG lFlags,
881 IWbemClassObject *pInSignature,
882 IWbemClassObject *pOutSignature )
883 {
884 FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
885 return E_NOTIMPL;
886 }
887
888 static HRESULT WINAPI class_object_DeleteMethod(
889 IWbemClassObject *iface,
890 LPCWSTR wszName )
891 {
892 FIXME("%p, %s\n", iface, debugstr_w(wszName));
893 return E_NOTIMPL;
894 }
895
896 static HRESULT WINAPI class_object_BeginMethodEnumeration(
897 IWbemClassObject *iface,
898 LONG lEnumFlags)
899 {
900 struct class_object *co = impl_from_IWbemClassObject( iface );
901
902 TRACE("%p, %08x\n", iface, lEnumFlags);
903
904 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
905
906 if (co->iter)
907 {
908 WARN("not allowed on instance\n");
909 return WBEM_E_ILLEGAL_OPERATION;
910 }
911 co->index_method = 0;
912 return S_OK;
913 }
914
915 static HRESULT WINAPI class_object_NextMethod(
916 IWbemClassObject *iface,
917 LONG lFlags,
918 BSTR *pstrName,
919 IWbemClassObject **ppInSignature,
920 IWbemClassObject **ppOutSignature)
921 {
922 struct class_object *co = impl_from_IWbemClassObject( iface );
923 BSTR method;
924 HRESULT hr;
925
926 TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
927
928 if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
929
930 hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
931 if (hr != S_OK)
932 {
933 SysFreeString( method );
934 return hr;
935 }
936 hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
937 if (hr != S_OK)
938 {
939 SysFreeString( method );
940 IWbemClassObject_Release( *ppInSignature );
941 }
942 else
943 {
944 *pstrName = method;
945 co->index_method++;
946 }
947 return hr;
948 }
949
950 static HRESULT WINAPI class_object_EndMethodEnumeration(
951 IWbemClassObject *iface )
952 {
953 struct class_object *co = impl_from_IWbemClassObject( iface );
954
955 TRACE("%p\n", iface);
956
957 co->index_method = 0;
958 return S_OK;
959 }
960
961 static HRESULT WINAPI class_object_GetMethodQualifierSet(
962 IWbemClassObject *iface,
963 LPCWSTR wszMethod,
964 IWbemQualifierSet **ppQualSet)
965 {
966 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
967 return E_NOTIMPL;
968 }
969
970 static HRESULT WINAPI class_object_GetMethodOrigin(
971 IWbemClassObject *iface,
972 LPCWSTR wszMethodName,
973 BSTR *pstrClassName)
974 {
975 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
976 return E_NOTIMPL;
977 }
978
979 static const IWbemClassObjectVtbl class_object_vtbl =
980 {
981 class_object_QueryInterface,
982 class_object_AddRef,
983 class_object_Release,
984 class_object_GetQualifierSet,
985 class_object_Get,
986 class_object_Put,
987 class_object_Delete,
988 class_object_GetNames,
989 class_object_BeginEnumeration,
990 class_object_Next,
991 class_object_EndEnumeration,
992 class_object_GetPropertyQualifierSet,
993 class_object_Clone,
994 class_object_GetObjectText,
995 class_object_SpawnDerivedClass,
996 class_object_SpawnInstance,
997 class_object_CompareTo,
998 class_object_GetPropertyOrigin,
999 class_object_InheritsFrom,
1000 class_object_GetMethod,
1001 class_object_PutMethod,
1002 class_object_DeleteMethod,
1003 class_object_BeginMethodEnumeration,
1004 class_object_NextMethod,
1005 class_object_EndMethodEnumeration,
1006 class_object_GetMethodQualifierSet,
1007 class_object_GetMethodOrigin
1008 };
1009
1010 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
1011 struct record *record, IWbemClassObject **obj )
1012 {
1013 struct class_object *co;
1014
1015 TRACE("%s, %p\n", debugstr_w(name), obj);
1016
1017 co = heap_alloc( sizeof(*co) );
1018 if (!co) return E_OUTOFMEMORY;
1019
1020 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1021 co->refs = 1;
1022 if (!name) co->name = NULL;
1023 else if (!(co->name = heap_strdupW( name )))
1024 {
1025 heap_free( co );
1026 return E_OUTOFMEMORY;
1027 }
1028 co->iter = iter;
1029 co->index = index;
1030 co->index_method = 0;
1031 co->index_property = 0;
1032 co->record = record;
1033 if (iter) IEnumWbemClassObject_AddRef( iter );
1034
1035 *obj = &co->IWbemClassObject_iface;
1036
1037 TRACE("returning iface %p\n", *obj);
1038 return S_OK;
1039 }