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