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