wbemprox: Always convert from BSTR.
[wine.git] / dlls / wbemprox / class.c
blobc17e1b30f04270bd8bfc9db8d444517ab1f99cbf
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
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.
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.
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
19 #define COBJMACROS
21 #include "config.h"
22 #include <stdarg.h>
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "wbemcli.h"
29 #include "wine/debug.h"
30 #include "wbemprox_private.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34 struct enum_class_object
36 IEnumWbemClassObject IEnumWbemClassObject_iface;
37 LONG refs;
38 struct query *query;
39 UINT index;
42 static inline struct enum_class_object *impl_from_IEnumWbemClassObject(
43 IEnumWbemClassObject *iface )
45 return CONTAINING_RECORD(iface, struct enum_class_object, IEnumWbemClassObject_iface);
48 static ULONG WINAPI enum_class_object_AddRef(
49 IEnumWbemClassObject *iface )
51 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
52 return InterlockedIncrement( &ec->refs );
55 static ULONG WINAPI enum_class_object_Release(
56 IEnumWbemClassObject *iface )
58 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
59 LONG refs = InterlockedDecrement( &ec->refs );
60 if (!refs)
62 TRACE("destroying %p\n", ec);
63 release_query( ec->query );
64 heap_free( ec );
66 return refs;
69 static HRESULT WINAPI enum_class_object_QueryInterface(
70 IEnumWbemClassObject *iface,
71 REFIID riid,
72 void **ppvObject )
74 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
76 TRACE("%p, %s, %p\n", ec, debugstr_guid( riid ), ppvObject );
78 if ( IsEqualGUID( riid, &IID_IEnumWbemClassObject ) ||
79 IsEqualGUID( riid, &IID_IUnknown ) )
81 *ppvObject = ec;
83 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
85 *ppvObject = &client_security;
86 return S_OK;
88 else
90 FIXME("interface %s not implemented\n", debugstr_guid(riid));
91 return E_NOINTERFACE;
93 IEnumWbemClassObject_AddRef( iface );
94 return S_OK;
97 static HRESULT WINAPI enum_class_object_Reset(
98 IEnumWbemClassObject *iface )
100 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
102 TRACE("%p\n", iface);
104 ec->index = 0;
105 return WBEM_S_NO_ERROR;
108 static HRESULT WINAPI enum_class_object_Next(
109 IEnumWbemClassObject *iface,
110 LONG lTimeout,
111 ULONG uCount,
112 IWbemClassObject **apObjects,
113 ULONG *puReturned )
115 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
116 struct view *view = ec->query->view;
117 HRESULT hr;
119 TRACE("%p, %d, %u, %p, %p\n", iface, lTimeout, uCount, apObjects, puReturned);
121 if (!uCount) return WBEM_S_FALSE;
122 if (!apObjects || !puReturned) return WBEM_E_INVALID_PARAMETER;
123 if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
125 *puReturned = 0;
126 if (ec->index + uCount > view->count) return WBEM_S_FALSE;
128 hr = create_class_object( view->table->name, iface, ec->index, NULL, apObjects );
129 if (hr != S_OK) return hr;
131 ec->index++;
132 *puReturned = 1;
133 if (ec->index == view->count) return WBEM_S_FALSE;
134 if (uCount > 1) return WBEM_S_TIMEDOUT;
135 return WBEM_S_NO_ERROR;
138 static HRESULT WINAPI enum_class_object_NextAsync(
139 IEnumWbemClassObject *iface,
140 ULONG uCount,
141 IWbemObjectSink *pSink )
143 FIXME("%p, %u, %p\n", iface, uCount, pSink);
144 return E_NOTIMPL;
147 static HRESULT WINAPI enum_class_object_Clone(
148 IEnumWbemClassObject *iface,
149 IEnumWbemClassObject **ppEnum )
151 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
153 TRACE("%p, %p\n", iface, ppEnum);
155 return EnumWbemClassObject_create( NULL, ec->query, (void **)ppEnum );
158 static HRESULT WINAPI enum_class_object_Skip(
159 IEnumWbemClassObject *iface,
160 LONG lTimeout,
161 ULONG nCount )
163 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( iface );
164 struct view *view = ec->query->view;
166 TRACE("%p, %d, %u\n", iface, lTimeout, nCount);
168 if (lTimeout != WBEM_INFINITE) FIXME("timeout not supported\n");
170 if (!view->count) return WBEM_S_FALSE;
172 if (nCount > view->count - ec->index)
174 ec->index = view->count - 1;
175 return WBEM_S_FALSE;
177 ec->index += nCount;
178 return WBEM_S_NO_ERROR;
181 static const IEnumWbemClassObjectVtbl enum_class_object_vtbl =
183 enum_class_object_QueryInterface,
184 enum_class_object_AddRef,
185 enum_class_object_Release,
186 enum_class_object_Reset,
187 enum_class_object_Next,
188 enum_class_object_NextAsync,
189 enum_class_object_Clone,
190 enum_class_object_Skip
193 HRESULT EnumWbemClassObject_create(
194 IUnknown *pUnkOuter, struct query *query, LPVOID *ppObj )
196 struct enum_class_object *ec;
198 TRACE("%p, %p\n", pUnkOuter, ppObj);
200 ec = heap_alloc( sizeof(*ec) );
201 if (!ec) return E_OUTOFMEMORY;
203 ec->IEnumWbemClassObject_iface.lpVtbl = &enum_class_object_vtbl;
204 ec->refs = 1;
205 ec->query = query;
206 addref_query( query );
207 ec->index = 0;
209 *ppObj = &ec->IEnumWbemClassObject_iface;
211 TRACE("returning iface %p\n", *ppObj);
212 return S_OK;
215 static struct record *create_record( const struct column *columns, UINT num_cols )
217 UINT i;
218 struct record *record;
220 if (!(record = heap_alloc( sizeof(struct record) ))) return NULL;
221 if (!(record->fields = heap_alloc( num_cols * sizeof(struct field) )))
223 heap_free( record );
224 return NULL;
226 for (i = 0; i < num_cols; i++)
228 record->fields[i].type = columns[i].type;
229 record->fields[i].u.ival = 0;
231 record->count = num_cols;
232 return record;
235 void destroy_array( struct array *array, CIMTYPE type )
237 UINT i, size;
239 if (!array) return;
240 if (type == CIM_STRING || type == CIM_DATETIME)
242 size = get_type_size( type );
243 for (i = 0; i < array->count; i++) heap_free( *(WCHAR **)((char *)array->ptr + i * size) );
245 heap_free( array->ptr );
246 heap_free( array );
249 static void destroy_record( struct record *record )
251 UINT i;
253 if (!record) return;
254 for (i = 0; i < record->count; i++)
256 if (record->fields[i].type == CIM_STRING || record->fields[i].type == CIM_DATETIME)
257 heap_free( record->fields[i].u.sval );
258 else if (record->fields[i].type & CIM_FLAG_ARRAY)
259 destroy_array( record->fields[i].u.aval, record->fields[i].type & CIM_TYPE_MASK );
261 heap_free( record->fields );
262 heap_free( record );
265 struct class_object
267 IWbemClassObject IWbemClassObject_iface;
268 LONG refs;
269 WCHAR *name;
270 IEnumWbemClassObject *iter;
271 UINT index;
272 UINT index_method;
273 UINT index_property;
274 struct record *record; /* uncommitted instance */
277 static inline struct class_object *impl_from_IWbemClassObject(
278 IWbemClassObject *iface )
280 return CONTAINING_RECORD(iface, struct class_object, IWbemClassObject_iface);
283 static ULONG WINAPI class_object_AddRef(
284 IWbemClassObject *iface )
286 struct class_object *co = impl_from_IWbemClassObject( iface );
287 return InterlockedIncrement( &co->refs );
290 static ULONG WINAPI class_object_Release(
291 IWbemClassObject *iface )
293 struct class_object *co = impl_from_IWbemClassObject( iface );
294 LONG refs = InterlockedDecrement( &co->refs );
295 if (!refs)
297 TRACE("destroying %p\n", co);
298 if (co->iter) IEnumWbemClassObject_Release( co->iter );
299 destroy_record( co->record );
300 heap_free( co->name );
301 heap_free( co );
303 return refs;
306 static HRESULT WINAPI class_object_QueryInterface(
307 IWbemClassObject *iface,
308 REFIID riid,
309 void **ppvObject )
311 struct class_object *co = impl_from_IWbemClassObject( iface );
313 TRACE("%p, %s, %p\n", co, debugstr_guid( riid ), ppvObject );
315 if ( IsEqualGUID( riid, &IID_IWbemClassObject ) ||
316 IsEqualGUID( riid, &IID_IUnknown ) )
318 *ppvObject = co;
320 else if (IsEqualGUID( riid, &IID_IClientSecurity ))
322 *ppvObject = &client_security;
323 return S_OK;
325 else
327 FIXME("interface %s not implemented\n", debugstr_guid(riid));
328 return E_NOINTERFACE;
330 IWbemClassObject_AddRef( iface );
331 return S_OK;
334 static HRESULT WINAPI class_object_GetQualifierSet(
335 IWbemClassObject *iface,
336 IWbemQualifierSet **ppQualSet )
338 FIXME("%p, %p\n", iface, ppQualSet);
339 return E_NOTIMPL;
342 static HRESULT record_get_value( const struct record *record, UINT index, VARIANT *var, CIMTYPE *type )
344 if (type) *type = record->fields[index].type;
346 if (record->fields[index].type & CIM_FLAG_ARRAY)
348 V_VT( var ) = VT_ARRAY;
349 V_ARRAY( var ) = to_safearray( record->fields[index].u.aval, record->fields[index].type & COL_TYPE_MASK );
350 return S_OK;
352 switch (record->fields[index].type)
354 case CIM_STRING:
355 case CIM_DATETIME:
356 V_VT( var ) = VT_BSTR;
357 V_BSTR( var ) = SysAllocString( record->fields[index].u.sval );
358 return S_OK;
359 case CIM_SINT32:
360 V_VT( var ) = VT_I4;
361 V_I4( var ) = record->fields[index].u.ival;
362 return S_OK;
363 case CIM_UINT32:
364 V_VT( var ) = VT_UI4;
365 V_UI4( var ) = record->fields[index].u.ival;
366 return S_OK;
367 default:
368 FIXME("unhandled type %u\n", record->fields[index].type);
369 break;
371 return WBEM_E_INVALID_PARAMETER;
374 static HRESULT WINAPI class_object_Get(
375 IWbemClassObject *iface,
376 LPCWSTR wszName,
377 LONG lFlags,
378 VARIANT *pVal,
379 CIMTYPE *pType,
380 LONG *plFlavor )
382 struct class_object *co = impl_from_IWbemClassObject( iface );
383 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
385 TRACE("%p, %s, %08x, %p, %p, %p\n", iface, debugstr_w(wszName), lFlags, pVal, pType, plFlavor);
387 if (co->record)
389 struct table *table = grab_table( co->name );
390 UINT index;
391 HRESULT hr;
393 if (!table) return WBEM_E_FAILED;
394 hr = get_column_index( table, wszName, &index );
395 release_table( table );
396 if (hr != S_OK) return hr;
397 return record_get_value( co->record, index, pVal, pType );
399 return get_propval( ec->query->view, co->index, wszName, pVal, pType, plFlavor );
402 static HRESULT record_set_value( struct record *record, UINT index, VARIANT *var )
404 LONGLONG val;
405 CIMTYPE type;
406 HRESULT hr;
408 if ((hr = to_longlong( var, &val, &type )) != S_OK) return hr;
409 if (type != record->fields[index].type) return WBEM_E_TYPE_MISMATCH;
411 if (type & CIM_FLAG_ARRAY)
413 record->fields[index].u.aval = (struct array *)(INT_PTR)val;
414 return S_OK;
416 switch (type)
418 case CIM_STRING:
419 case CIM_DATETIME:
420 record->fields[index].u.sval = (WCHAR *)(INT_PTR)val;
421 return S_OK;
422 case CIM_SINT16:
423 case CIM_UINT16:
424 case CIM_SINT32:
425 case CIM_UINT32:
426 record->fields[index].u.ival = val;
427 return S_OK;
428 default:
429 FIXME("unhandled type %u\n", type);
430 break;
432 return WBEM_E_INVALID_PARAMETER;
435 static HRESULT WINAPI class_object_Put(
436 IWbemClassObject *iface,
437 LPCWSTR wszName,
438 LONG lFlags,
439 VARIANT *pVal,
440 CIMTYPE Type )
442 struct class_object *co = impl_from_IWbemClassObject( iface );
443 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
445 TRACE("%p, %s, %08x, %p, %u\n", iface, debugstr_w(wszName), lFlags, pVal, Type);
447 if (co->record)
449 struct table *table = grab_table( co->name );
450 UINT index;
451 HRESULT hr;
453 if (!table) return WBEM_E_FAILED;
454 hr = get_column_index( table, wszName, &index );
455 release_table( table );
456 if (hr != S_OK) return hr;
457 return record_set_value( co->record, index, pVal );
459 return put_propval( ec->query->view, co->index, wszName, pVal, Type );
462 static HRESULT WINAPI class_object_Delete(
463 IWbemClassObject *iface,
464 LPCWSTR wszName )
466 FIXME("%p, %s\n", iface, debugstr_w(wszName));
467 return E_NOTIMPL;
470 static HRESULT WINAPI class_object_GetNames(
471 IWbemClassObject *iface,
472 LPCWSTR wszQualifierName,
473 LONG lFlags,
474 VARIANT *pQualifierVal,
475 SAFEARRAY **pNames )
477 struct class_object *co = impl_from_IWbemClassObject( iface );
478 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
480 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszQualifierName), lFlags, pQualifierVal, pNames);
482 if (wszQualifierName || pQualifierVal)
484 FIXME("qualifier not supported\n");
485 return E_NOTIMPL;
487 if (lFlags != WBEM_FLAG_ALWAYS)
489 FIXME("flags %08x not supported\n", lFlags);
490 return E_NOTIMPL;
492 return get_properties( ec->query->view, pNames );
495 static HRESULT WINAPI class_object_BeginEnumeration(
496 IWbemClassObject *iface,
497 LONG lEnumFlags )
499 struct class_object *co = impl_from_IWbemClassObject( iface );
501 TRACE("%p, %08x\n", iface, lEnumFlags);
503 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
505 co->index_property = 0;
506 return S_OK;
509 static HRESULT WINAPI class_object_Next(
510 IWbemClassObject *iface,
511 LONG lFlags,
512 BSTR *strName,
513 VARIANT *pVal,
514 CIMTYPE *pType,
515 LONG *plFlavor )
517 struct class_object *co = impl_from_IWbemClassObject( iface );
518 struct enum_class_object *ec = impl_from_IEnumWbemClassObject( co->iter );
519 struct view *view = ec->query->view;
520 BSTR property;
521 HRESULT hr;
523 TRACE("%p, %08x, %p, %p, %p, %p\n", iface, lFlags, strName, pVal, pType, plFlavor);
525 if (!(property = get_property_name( co->name, co->index_property ))) return WBEM_S_NO_MORE_DATA;
526 if ((hr = get_propval( view, co->index, property, pVal, pType, plFlavor ) != S_OK))
528 SysFreeString( property );
529 return hr;
531 *strName = property;
532 co->index_property++;
533 return S_OK;
536 static HRESULT WINAPI class_object_EndEnumeration(
537 IWbemClassObject *iface )
539 struct class_object *co = impl_from_IWbemClassObject( iface );
541 TRACE("%p\n", iface);
543 co->index_property = 0;
544 return S_OK;
547 static HRESULT WINAPI class_object_GetPropertyQualifierSet(
548 IWbemClassObject *iface,
549 LPCWSTR wszProperty,
550 IWbemQualifierSet **ppQualSet )
552 FIXME("%p, %s, %p\n", iface, debugstr_w(wszProperty), ppQualSet);
553 return E_NOTIMPL;
556 static HRESULT WINAPI class_object_Clone(
557 IWbemClassObject *iface,
558 IWbemClassObject **ppCopy )
560 FIXME("%p, %p\n", iface, ppCopy);
561 return E_NOTIMPL;
564 static BSTR get_body_text( const struct table *table, UINT row, UINT *len )
566 static const WCHAR fmtW[] = {'\n','\t','%','s',' ','=',' ','%','s',';',0};
567 BSTR value, ret;
568 WCHAR *p;
569 UINT i;
571 *len = 0;
572 for (i = 0; i < table->num_cols; i++)
574 *len += sizeof(fmtW) / sizeof(fmtW[0]);
575 *len += strlenW( table->columns[i].name );
576 value = get_value_bstr( table, row, i );
577 *len += SysStringLen( value );
578 SysFreeString( value );
580 if (!(ret = SysAllocStringLen( NULL, *len ))) return NULL;
581 p = ret;
582 for (i = 0; i < table->num_cols; i++)
584 value = get_value_bstr( table, row, i );
585 p += sprintfW( p, fmtW, table->columns[i].name, value );
586 SysFreeString( value );
588 return ret;
591 static BSTR get_object_text( const struct view *view, UINT index )
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;
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;
603 if (!(ret = SysAllocStringLen( NULL, len ))) return NULL;
604 sprintfW( ret, fmtW, view->table->name, body );
605 SysFreeString( body );
606 return ret;
609 static HRESULT WINAPI class_object_GetObjectText(
610 IWbemClassObject *iface,
611 LONG lFlags,
612 BSTR *pstrObjectText )
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;
619 TRACE("%p, %08x, %p\n", iface, lFlags, pstrObjectText);
621 if (lFlags) FIXME("flags %08x not implemented\n", lFlags);
623 if (!(text = get_object_text( view, co->index ))) return E_OUTOFMEMORY;
624 *pstrObjectText = text;
625 return S_OK;
628 static HRESULT WINAPI class_object_SpawnDerivedClass(
629 IWbemClassObject *iface,
630 LONG lFlags,
631 IWbemClassObject **ppNewClass )
633 FIXME("%p, %08x, %p\n", iface, lFlags, ppNewClass);
634 return E_NOTIMPL;
637 static HRESULT WINAPI class_object_SpawnInstance(
638 IWbemClassObject *iface,
639 LONG lFlags,
640 IWbemClassObject **ppNewInstance )
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;
647 TRACE("%p, %08x, %p\n", iface, lFlags, ppNewInstance);
649 if (!(record = create_record( view->table->columns, view->table->num_cols )))
650 return E_OUTOFMEMORY;
652 return create_class_object( co->name, NULL, 0, record, ppNewInstance );
655 static HRESULT WINAPI class_object_CompareTo(
656 IWbemClassObject *iface,
657 LONG lFlags,
658 IWbemClassObject *pCompareTo )
660 FIXME("%p, %08x, %p\n", iface, lFlags, pCompareTo);
661 return E_NOTIMPL;
664 static HRESULT WINAPI class_object_GetPropertyOrigin(
665 IWbemClassObject *iface,
666 LPCWSTR wszName,
667 BSTR *pstrClassName )
669 FIXME("%p, %s, %p\n", iface, debugstr_w(wszName), pstrClassName);
670 return E_NOTIMPL;
673 static HRESULT WINAPI class_object_InheritsFrom(
674 IWbemClassObject *iface,
675 LPCWSTR strAncestor )
677 FIXME("%p, %s\n", iface, debugstr_w(strAncestor));
678 return E_NOTIMPL;
681 static UINT count_instances( IEnumWbemClassObject *iter )
683 UINT count = 0;
684 while (!IEnumWbemClassObject_Skip( iter, WBEM_INFINITE, 1 )) count++;
685 IEnumWbemClassObject_Reset( iter );
686 return count;
689 static void set_default_value( CIMTYPE type, UINT val, BYTE *ptr )
691 switch (type)
693 case CIM_SINT16:
694 *(INT16 *)ptr = val;
695 break;
696 case CIM_UINT16:
697 *(UINT16 *)ptr = val;
698 break;
699 case CIM_SINT32:
700 *(INT32 *)ptr = val;
701 break;
702 case CIM_UINT32:
703 *(UINT32 *)ptr = val;
704 break;
705 default:
706 FIXME("unhandled type %u\n", type);
707 break;
711 static HRESULT create_signature_columns_and_data( IEnumWbemClassObject *iter, UINT *num_cols,
712 struct column **cols, BYTE **data )
714 static const WCHAR parameterW[] = {'P','a','r','a','m','e','t','e','r',0};
715 static const WCHAR typeW[] = {'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;
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;
730 for (;;)
732 IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, &param, &count );
733 if (!count) break;
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 );
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 columns[i].vartype = 0;
745 hr = IWbemClassObject_Get( param, defaultvalueW, 0, &val, NULL, NULL );
746 if (hr != S_OK) goto error;
747 if (V_UI4( &val )) set_default_value( columns[i].type, V_UI4( &val ), row + offset );
748 offset += get_type_size( columns[i].type );
750 IWbemClassObject_Release( param );
751 i++;
753 *num_cols = i;
754 *cols = columns;
755 *data = row;
756 return S_OK;
758 error:
759 for (; i >= 0; i--) heap_free( (WCHAR *)columns[i].name );
760 heap_free( columns );
761 heap_free( row );
762 return hr;
765 static HRESULT create_signature_table( IEnumWbemClassObject *iter, WCHAR *name )
767 HRESULT hr;
768 struct table *table;
769 struct column *columns;
770 UINT num_cols;
771 BYTE *row;
773 hr = create_signature_columns_and_data( iter, &num_cols, &columns, &row );
774 if (hr != S_OK) return hr;
776 if (!(table = create_table( name, num_cols, columns, 1, row, NULL )))
778 free_columns( columns, num_cols );
779 heap_free( row );
780 return E_OUTOFMEMORY;
782 if (!add_table( table )) free_table( table ); /* already exists */
783 return S_OK;
786 static WCHAR *build_signature_table_name( const WCHAR *class, const WCHAR *method, enum param_direction dir )
788 static const WCHAR fmtW[] = {'_','_','%','s','_','%','s','_','%','s',0};
789 static const WCHAR outW[] = {'O','U','T',0};
790 static const WCHAR inW[] = {'I','N',0};
791 UINT len = SIZEOF(fmtW) + SIZEOF(outW) + strlenW( class ) + strlenW( method );
792 WCHAR *ret;
794 if (!(ret = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
795 sprintfW( ret, fmtW, class, method, dir == PARAM_IN ? inW : outW );
796 return struprW( ret );
799 static HRESULT create_signature( const WCHAR *class, const WCHAR *method, enum param_direction dir,
800 IWbemClassObject **sig )
802 static const WCHAR selectW[] =
803 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',
804 '_','_','P','A','R','A','M','E','T','E','R','S',' ','W','H','E','R','E',' ',
805 'C','l','a','s','s','=','\'','%','s','\'',' ','A','N','D',' ',
806 'M','e','t','h','o','d','=','\'','%','s','\'',' ','A','N','D',' ',
807 'D','i','r','e','c','t','i','o','n','%','s',0};
808 static const WCHAR geW[] = {'>','=','0',0};
809 static const WCHAR leW[] = {'<','=','0',0};
810 UINT len = SIZEOF(selectW) + SIZEOF(geW);
811 IEnumWbemClassObject *iter;
812 WCHAR *query, *name;
813 HRESULT hr;
815 len += strlenW( class ) + strlenW( method );
816 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
817 sprintfW( query, selectW, class, method, dir >= 0 ? geW : leW );
819 hr = exec_query( query, &iter );
820 heap_free( query );
821 if (hr != S_OK) return hr;
823 if (!(name = build_signature_table_name( class, method, dir )))
825 IEnumWbemClassObject_Release( iter );
826 return E_OUTOFMEMORY;
828 hr = create_signature_table( iter, name );
829 IEnumWbemClassObject_Release( iter );
830 if (hr != S_OK)
832 heap_free( name );
833 return hr;
835 return get_object( name, sig );
838 static HRESULT WINAPI class_object_GetMethod(
839 IWbemClassObject *iface,
840 LPCWSTR wszName,
841 LONG lFlags,
842 IWbemClassObject **ppInSignature,
843 IWbemClassObject **ppOutSignature )
845 struct class_object *co = impl_from_IWbemClassObject( iface );
846 HRESULT hr;
848 TRACE("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, ppInSignature, ppOutSignature);
850 hr = create_signature( co->name, wszName, PARAM_IN, ppInSignature );
851 if (hr != S_OK) return hr;
853 hr = create_signature( co->name, wszName, PARAM_OUT, ppOutSignature );
854 if (hr != S_OK) IWbemClassObject_Release( *ppInSignature );
855 return hr;
858 static HRESULT WINAPI class_object_PutMethod(
859 IWbemClassObject *iface,
860 LPCWSTR wszName,
861 LONG lFlags,
862 IWbemClassObject *pInSignature,
863 IWbemClassObject *pOutSignature )
865 FIXME("%p, %s, %08x, %p, %p\n", iface, debugstr_w(wszName), lFlags, pInSignature, pOutSignature);
866 return E_NOTIMPL;
869 static HRESULT WINAPI class_object_DeleteMethod(
870 IWbemClassObject *iface,
871 LPCWSTR wszName )
873 FIXME("%p, %s\n", iface, debugstr_w(wszName));
874 return E_NOTIMPL;
877 static HRESULT WINAPI class_object_BeginMethodEnumeration(
878 IWbemClassObject *iface,
879 LONG lEnumFlags)
881 struct class_object *co = impl_from_IWbemClassObject( iface );
883 TRACE("%p, %08x\n", iface, lEnumFlags);
885 if (lEnumFlags) FIXME("flags 0x%08x not supported\n", lEnumFlags);
887 if (co->iter)
889 WARN("not allowed on instance\n");
890 return WBEM_E_ILLEGAL_OPERATION;
892 co->index_method = 0;
893 return S_OK;
896 static HRESULT WINAPI class_object_NextMethod(
897 IWbemClassObject *iface,
898 LONG lFlags,
899 BSTR *pstrName,
900 IWbemClassObject **ppInSignature,
901 IWbemClassObject **ppOutSignature)
903 struct class_object *co = impl_from_IWbemClassObject( iface );
904 BSTR method;
905 HRESULT hr;
907 TRACE("%p, %08x, %p, %p, %p\n", iface, lFlags, pstrName, ppInSignature, ppOutSignature);
909 if (!(method = get_method_name( co->name, co->index_method ))) return WBEM_S_NO_MORE_DATA;
911 hr = create_signature( co->name, method, PARAM_IN, ppInSignature );
912 if (hr != S_OK)
914 SysFreeString( method );
915 return hr;
917 hr = create_signature( co->name, method, PARAM_OUT, ppOutSignature );
918 if (hr != S_OK)
920 SysFreeString( method );
921 IWbemClassObject_Release( *ppInSignature );
923 else
925 *pstrName = method;
926 co->index_method++;
928 return hr;
931 static HRESULT WINAPI class_object_EndMethodEnumeration(
932 IWbemClassObject *iface )
934 struct class_object *co = impl_from_IWbemClassObject( iface );
936 TRACE("%p\n", iface);
938 co->index_method = 0;
939 return S_OK;
942 static HRESULT WINAPI class_object_GetMethodQualifierSet(
943 IWbemClassObject *iface,
944 LPCWSTR wszMethod,
945 IWbemQualifierSet **ppQualSet)
947 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethod), ppQualSet);
948 return E_NOTIMPL;
951 static HRESULT WINAPI class_object_GetMethodOrigin(
952 IWbemClassObject *iface,
953 LPCWSTR wszMethodName,
954 BSTR *pstrClassName)
956 FIXME("%p, %s, %p\n", iface, debugstr_w(wszMethodName), pstrClassName);
957 return E_NOTIMPL;
960 static const IWbemClassObjectVtbl class_object_vtbl =
962 class_object_QueryInterface,
963 class_object_AddRef,
964 class_object_Release,
965 class_object_GetQualifierSet,
966 class_object_Get,
967 class_object_Put,
968 class_object_Delete,
969 class_object_GetNames,
970 class_object_BeginEnumeration,
971 class_object_Next,
972 class_object_EndEnumeration,
973 class_object_GetPropertyQualifierSet,
974 class_object_Clone,
975 class_object_GetObjectText,
976 class_object_SpawnDerivedClass,
977 class_object_SpawnInstance,
978 class_object_CompareTo,
979 class_object_GetPropertyOrigin,
980 class_object_InheritsFrom,
981 class_object_GetMethod,
982 class_object_PutMethod,
983 class_object_DeleteMethod,
984 class_object_BeginMethodEnumeration,
985 class_object_NextMethod,
986 class_object_EndMethodEnumeration,
987 class_object_GetMethodQualifierSet,
988 class_object_GetMethodOrigin
991 HRESULT create_class_object( const WCHAR *name, IEnumWbemClassObject *iter, UINT index,
992 struct record *record, IWbemClassObject **obj )
994 struct class_object *co;
996 TRACE("%s, %p\n", debugstr_w(name), obj);
998 co = heap_alloc( sizeof(*co) );
999 if (!co) return E_OUTOFMEMORY;
1001 co->IWbemClassObject_iface.lpVtbl = &class_object_vtbl;
1002 co->refs = 1;
1003 co->name = heap_strdupW( name );
1004 if (!co->name)
1006 heap_free( co );
1007 return E_OUTOFMEMORY;
1009 co->iter = iter;
1010 co->index = index;
1011 co->index_method = 0;
1012 co->index_property = 0;
1013 co->record = record;
1014 if (iter) IEnumWbemClassObject_AddRef( iter );
1016 *obj = &co->IWbemClassObject_iface;
1018 TRACE("returning iface %p\n", *obj);
1019 return S_OK;