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