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