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