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 client_security 37 { 38 IClientSecurity IClientSecurity_iface; 39 }; 40 41 static inline struct client_security *impl_from_IClientSecurity( IClientSecurity *iface ) 42 { 43 return CONTAINING_RECORD( iface, struct client_security, IClientSecurity_iface ); 44 } 45 46 static HRESULT WINAPI client_security_QueryInterface( 47 IClientSecurity *iface, 48 REFIID riid, 49 void **ppvObject ) 50 { 51 struct client_security *cs = impl_from_IClientSecurity( iface ); 52 53 TRACE("%p %s %p\n", cs, debugstr_guid( riid ), ppvObject ); 54 55 if ( IsEqualGUID( riid, &IID_IClientSecurity ) || 56 IsEqualGUID( riid, &IID_IUnknown ) ) 57 { 58 *ppvObject = cs; 59 } 60 else 61 { 62 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 63 return E_NOINTERFACE; 64 } 65 IClientSecurity_AddRef( iface ); 66 return S_OK; 67 } 68 69 static ULONG WINAPI client_security_AddRef( 70 IClientSecurity *iface ) 71 { 72 FIXME("%p\n", iface); 73 return 2; 74 } 75 76 static ULONG WINAPI client_security_Release( 77 IClientSecurity *iface ) 78 { 79 FIXME("%p\n", iface); 80 return 1; 81 } 82 83 static HRESULT WINAPI client_security_QueryBlanket( 84 IClientSecurity *iface, 85 IUnknown *pProxy, 86 DWORD *pAuthnSvc, 87 DWORD *pAuthzSvc, 88 OLECHAR **pServerPrincName, 89 DWORD *pAuthnLevel, 90 DWORD *pImpLevel, 91 void **pAuthInfo, 92 DWORD *pCapabilities ) 93 { 94 FIXME("\n"); 95 return WBEM_E_FAILED; 96 } 97 98 static HRESULT WINAPI client_security_SetBlanket( 99 IClientSecurity *iface, 100 IUnknown *pProxy, 101 DWORD AuthnSvc, 102 DWORD AuthzSvc, 103 OLECHAR *pServerPrincName, 104 DWORD AuthnLevel, 105 DWORD ImpLevel, 106 void *pAuthInfo, 107 DWORD Capabilities ) 108 { 109 static const OLECHAR defaultW[] = 110 {'<','C','O','L','E','_','D','E','F','A','U','L','T','_','P','R','I','N','C','I','P','A','L','>',0}; 111 const OLECHAR *princname = (pServerPrincName == COLE_DEFAULT_PRINCIPAL) ? defaultW : pServerPrincName; 112 113 FIXME("%p, %p, %u, %u, %s, %u, %u, %p, 0x%08x\n", iface, pProxy, AuthnSvc, AuthzSvc, 114 debugstr_w(princname), AuthnLevel, ImpLevel, pAuthInfo, Capabilities); 115 return WBEM_NO_ERROR; 116 } 117 118 static HRESULT WINAPI client_security_CopyProxy( 119 IClientSecurity *iface, 120 IUnknown *pProxy, 121 IUnknown **ppCopy ) 122 { 123 FIXME("\n"); 124 return WBEM_E_FAILED; 125 } 126 127 static const IClientSecurityVtbl client_security_vtbl = 128 { 129 client_security_QueryInterface, 130 client_security_AddRef, 131 client_security_Release, 132 client_security_QueryBlanket, 133 client_security_SetBlanket, 134 client_security_CopyProxy 135 }; 136 137 IClientSecurity client_security = { &client_security_vtbl }; 138 139 struct async_header 140 { 141 IWbemObjectSink *sink; 142 void (*proc)( struct async_header * ); 143 HANDLE cancel; 144 HANDLE wait; 145 }; 146 147 struct async_query 148 { 149 struct async_header hdr; 150 WCHAR *str; 151 }; 152 153 static void free_async( struct async_header *async ) 154 { 155 if (async->sink) IWbemObjectSink_Release( async->sink ); 156 CloseHandle( async->cancel ); 157 CloseHandle( async->wait ); 158 heap_free( async ); 159 } 160 161 static BOOL init_async( struct async_header *async, IWbemObjectSink *sink, 162 void (*proc)(struct async_header *) ) 163 { 164 if (!(async->wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE; 165 if (!(async->cancel = CreateEventW( NULL, FALSE, FALSE, NULL ))) 166 { 167 CloseHandle( async->wait ); 168 return FALSE; 169 } 170 async->proc = proc; 171 async->sink = sink; 172 IWbemObjectSink_AddRef( sink ); 173 return TRUE; 174 } 175 176 static DWORD CALLBACK async_proc( LPVOID param ) 177 { 178 struct async_header *async = param; 179 HANDLE wait = async->wait; 180 181 async->proc( async ); 182 183 WaitForSingleObject( async->cancel, INFINITE ); 184 SetEvent( wait ); 185 return ERROR_SUCCESS; 186 } 187 188 static HRESULT queue_async( struct async_header *async ) 189 { 190 if (QueueUserWorkItem( async_proc, async, WT_EXECUTELONGFUNCTION )) return S_OK; 191 return HRESULT_FROM_WIN32( GetLastError() ); 192 } 193 194 struct wbem_services 195 { 196 IWbemServices IWbemServices_iface; 197 LONG refs; 198 CRITICAL_SECTION cs; 199 WCHAR *namespace; 200 struct async_header *async; 201 }; 202 203 static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface ) 204 { 205 return CONTAINING_RECORD( iface, struct wbem_services, IWbemServices_iface ); 206 } 207 208 static ULONG WINAPI wbem_services_AddRef( 209 IWbemServices *iface ) 210 { 211 struct wbem_services *ws = impl_from_IWbemServices( iface ); 212 return InterlockedIncrement( &ws->refs ); 213 } 214 215 static ULONG WINAPI wbem_services_Release( 216 IWbemServices *iface ) 217 { 218 struct wbem_services *ws = impl_from_IWbemServices( iface ); 219 LONG refs = InterlockedDecrement( &ws->refs ); 220 if (!refs) 221 { 222 TRACE("destroying %p\n", ws); 223 224 EnterCriticalSection( &ws->cs ); 225 if (ws->async) SetEvent( ws->async->cancel ); 226 LeaveCriticalSection( &ws->cs ); 227 if (ws->async) 228 { 229 WaitForSingleObject( ws->async->wait, INFINITE ); 230 free_async( ws->async ); 231 } 232 ws->cs.DebugInfo->Spare[0] = 0; 233 DeleteCriticalSection( &ws->cs ); 234 heap_free( ws->namespace ); 235 heap_free( ws ); 236 } 237 return refs; 238 } 239 240 static HRESULT WINAPI wbem_services_QueryInterface( 241 IWbemServices *iface, 242 REFIID riid, 243 void **ppvObject ) 244 { 245 struct wbem_services *ws = impl_from_IWbemServices( iface ); 246 247 TRACE("%p %s %p\n", ws, debugstr_guid( riid ), ppvObject ); 248 249 if ( IsEqualGUID( riid, &IID_IWbemServices ) || 250 IsEqualGUID( riid, &IID_IUnknown ) ) 251 { 252 *ppvObject = ws; 253 } 254 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) ) 255 { 256 *ppvObject = &client_security; 257 return S_OK; 258 } 259 else 260 { 261 FIXME("interface %s not implemented\n", debugstr_guid(riid)); 262 return E_NOINTERFACE; 263 } 264 IWbemServices_AddRef( iface ); 265 return S_OK; 266 } 267 268 static HRESULT WINAPI wbem_services_OpenNamespace( 269 IWbemServices *iface, 270 const BSTR strNamespace, 271 LONG lFlags, 272 IWbemContext *pCtx, 273 IWbemServices **ppWorkingNamespace, 274 IWbemCallResult **ppResult ) 275 { 276 static const WCHAR cimv2W[] = {'c','i','m','v','2',0}; 277 static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0}; 278 struct wbem_services *ws = impl_from_IWbemServices( iface ); 279 280 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strNamespace), lFlags, 281 pCtx, ppWorkingNamespace, ppResult); 282 283 if ((wcsicmp( strNamespace, cimv2W ) && wcsicmp( strNamespace, defaultW )) || ws->namespace) 284 return WBEM_E_INVALID_NAMESPACE; 285 286 return WbemServices_create( cimv2W, (void **)ppWorkingNamespace ); 287 } 288 289 static HRESULT WINAPI wbem_services_CancelAsyncCall( 290 IWbemServices *iface, 291 IWbemObjectSink *pSink ) 292 { 293 struct wbem_services *services = impl_from_IWbemServices( iface ); 294 struct async_header *async; 295 296 TRACE("%p, %p\n", iface, pSink); 297 298 if (!pSink) return WBEM_E_INVALID_PARAMETER; 299 300 EnterCriticalSection( &services->cs ); 301 302 if (!(async = services->async)) 303 { 304 LeaveCriticalSection( &services->cs ); 305 return WBEM_E_INVALID_PARAMETER; 306 } 307 services->async = NULL; 308 SetEvent( async->cancel ); 309 310 LeaveCriticalSection( &services->cs ); 311 312 WaitForSingleObject( async->wait, INFINITE ); 313 free_async( async ); 314 return S_OK; 315 } 316 317 static HRESULT WINAPI wbem_services_QueryObjectSink( 318 IWbemServices *iface, 319 LONG lFlags, 320 IWbemObjectSink **ppResponseHandler ) 321 { 322 FIXME("\n"); 323 return WBEM_E_FAILED; 324 } 325 326 HRESULT parse_path( const WCHAR *str, struct path **ret ) 327 { 328 struct path *path; 329 const WCHAR *p = str, *q; 330 UINT len; 331 332 if (!(path = heap_alloc_zero( sizeof(*path) ))) return E_OUTOFMEMORY; 333 334 if (*p == '\\') 335 { 336 static const WCHAR cimv2W[] = {'R','O','O','T','\\','C','I','M','V','2',0}; 337 WCHAR server[MAX_COMPUTERNAME_LENGTH+1]; 338 DWORD server_len = ARRAY_SIZE(server); 339 340 p++; 341 if (*p != '\\') 342 { 343 heap_free( path ); 344 return WBEM_E_INVALID_OBJECT_PATH; 345 } 346 p++; 347 348 q = p; 349 while (*p && *p != '\\') p++; 350 if (!*p) 351 { 352 heap_free( path ); 353 return WBEM_E_INVALID_OBJECT_PATH; 354 } 355 356 len = p - q; 357 if (!GetComputerNameW( server, &server_len ) || server_len != len || _wcsnicmp( q, server, server_len )) 358 { 359 heap_free( path ); 360 return WBEM_E_NOT_SUPPORTED; 361 } 362 363 q = ++p; 364 while (*p && *p != ':') p++; 365 if (!*p) 366 { 367 heap_free( path ); 368 return WBEM_E_INVALID_OBJECT_PATH; 369 } 370 371 len = p - q; 372 if (len != ARRAY_SIZE(cimv2W) - 1 || _wcsnicmp( q, cimv2W, ARRAY_SIZE(cimv2W) - 1 )) 373 { 374 heap_free( path ); 375 return WBEM_E_INVALID_NAMESPACE; 376 } 377 p++; 378 } 379 380 q = p; 381 while (*p && *p != '.') p++; 382 383 len = p - q; 384 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) ))) 385 { 386 heap_free( path ); 387 return E_OUTOFMEMORY; 388 } 389 memcpy( path->class, q, len * sizeof(WCHAR) ); 390 path->class[len] = 0; 391 path->class_len = len; 392 393 if (p[0] == '.' && p[1]) 394 { 395 q = ++p; 396 while (*q) q++; 397 398 len = q - p; 399 if (!(path->filter = heap_alloc( (len + 1) * sizeof(WCHAR) ))) 400 { 401 heap_free( path->class ); 402 heap_free( path ); 403 return E_OUTOFMEMORY; 404 } 405 memcpy( path->filter, p, len * sizeof(WCHAR) ); 406 path->filter[len] = 0; 407 path->filter_len = len; 408 } 409 *ret = path; 410 return S_OK; 411 } 412 413 void free_path( struct path *path ) 414 { 415 if (!path) return; 416 heap_free( path->class ); 417 heap_free( path->filter ); 418 heap_free( path ); 419 } 420 421 WCHAR *query_from_path( const struct path *path ) 422 { 423 static const WCHAR selectW[] = 424 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','%','s',' ', 425 'W','H','E','R','E',' ','%','s',0}; 426 static const WCHAR select_allW[] = 427 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0}; 428 WCHAR *query; 429 UINT len; 430 431 if (path->filter) 432 { 433 len = path->class_len + path->filter_len + ARRAY_SIZE(selectW); 434 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return NULL; 435 swprintf( query, selectW, path->class, path->filter ); 436 } 437 else 438 { 439 len = path->class_len + ARRAY_SIZE(select_allW); 440 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return NULL; 441 lstrcpyW( query, select_allW ); 442 lstrcatW( query, path->class ); 443 } 444 return query; 445 } 446 447 static HRESULT create_instance_enum( const struct path *path, IEnumWbemClassObject **iter ) 448 { 449 WCHAR *query; 450 HRESULT hr; 451 452 if (!(query = query_from_path( path ))) return E_OUTOFMEMORY; 453 hr = exec_query( query, iter ); 454 heap_free( query ); 455 return hr; 456 } 457 458 HRESULT get_object( const WCHAR *object_path, IWbemClassObject **obj ) 459 { 460 IEnumWbemClassObject *iter; 461 struct path *path; 462 HRESULT hr; 463 464 hr = parse_path( object_path, &path ); 465 if (hr != S_OK) return hr; 466 467 hr = create_instance_enum( path, &iter ); 468 if (hr != S_OK) 469 { 470 free_path( path ); 471 return hr; 472 } 473 hr = create_class_object( path->class, iter, 0, NULL, obj ); 474 IEnumWbemClassObject_Release( iter ); 475 free_path( path ); 476 return hr; 477 } 478 479 static HRESULT WINAPI wbem_services_GetObject( 480 IWbemServices *iface, 481 const BSTR strObjectPath, 482 LONG lFlags, 483 IWbemContext *pCtx, 484 IWbemClassObject **ppObject, 485 IWbemCallResult **ppCallResult ) 486 { 487 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags, 488 pCtx, ppObject, ppCallResult); 489 490 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags); 491 492 if (!strObjectPath || !strObjectPath[0]) 493 return create_class_object( NULL, NULL, 0, NULL, ppObject ); 494 495 return get_object( strObjectPath, ppObject ); 496 } 497 498 static HRESULT WINAPI wbem_services_GetObjectAsync( 499 IWbemServices *iface, 500 const BSTR strObjectPath, 501 LONG lFlags, 502 IWbemContext *pCtx, 503 IWbemObjectSink *pResponseHandler ) 504 { 505 FIXME("\n"); 506 return WBEM_E_FAILED; 507 } 508 509 static HRESULT WINAPI wbem_services_PutClass( 510 IWbemServices *iface, 511 IWbemClassObject *pObject, 512 LONG lFlags, 513 IWbemContext *pCtx, 514 IWbemCallResult **ppCallResult ) 515 { 516 FIXME("\n"); 517 return WBEM_E_FAILED; 518 } 519 520 static HRESULT WINAPI wbem_services_PutClassAsync( 521 IWbemServices *iface, 522 IWbemClassObject *pObject, 523 LONG lFlags, 524 IWbemContext *pCtx, 525 IWbemObjectSink *pResponseHandler ) 526 { 527 FIXME("\n"); 528 return WBEM_E_FAILED; 529 } 530 531 static HRESULT WINAPI wbem_services_DeleteClass( 532 IWbemServices *iface, 533 const BSTR strClass, 534 LONG lFlags, 535 IWbemContext *pCtx, 536 IWbemCallResult **ppCallResult ) 537 { 538 FIXME("\n"); 539 return WBEM_E_FAILED; 540 } 541 542 static HRESULT WINAPI wbem_services_DeleteClassAsync( 543 IWbemServices *iface, 544 const BSTR strClass, 545 LONG lFlags, 546 IWbemContext *pCtx, 547 IWbemObjectSink *pResponseHandler ) 548 { 549 FIXME("\n"); 550 return WBEM_E_FAILED; 551 } 552 553 static HRESULT WINAPI wbem_services_CreateClassEnum( 554 IWbemServices *iface, 555 const BSTR strSuperclass, 556 LONG lFlags, 557 IWbemContext *pCtx, 558 IEnumWbemClassObject **ppEnum ) 559 { 560 FIXME("\n"); 561 return WBEM_E_FAILED; 562 } 563 564 static HRESULT WINAPI wbem_services_CreateClassEnumAsync( 565 IWbemServices *iface, 566 const BSTR strSuperclass, 567 LONG lFlags, 568 IWbemContext *pCtx, 569 IWbemObjectSink *pResponseHandler ) 570 { 571 FIXME("\n"); 572 return WBEM_E_FAILED; 573 } 574 575 static HRESULT WINAPI wbem_services_PutInstance( 576 IWbemServices *iface, 577 IWbemClassObject *pInst, 578 LONG lFlags, 579 IWbemContext *pCtx, 580 IWbemCallResult **ppCallResult ) 581 { 582 FIXME("\n"); 583 return WBEM_E_FAILED; 584 } 585 586 static HRESULT WINAPI wbem_services_PutInstanceAsync( 587 IWbemServices *iface, 588 IWbemClassObject *pInst, 589 LONG lFlags, 590 IWbemContext *pCtx, 591 IWbemObjectSink *pResponseHandler ) 592 { 593 FIXME("\n"); 594 return WBEM_E_FAILED; 595 } 596 597 static HRESULT WINAPI wbem_services_DeleteInstance( 598 IWbemServices *iface, 599 const BSTR strObjectPath, 600 LONG lFlags, 601 IWbemContext *pCtx, 602 IWbemCallResult **ppCallResult ) 603 { 604 FIXME("\n"); 605 return WBEM_E_FAILED; 606 } 607 608 static HRESULT WINAPI wbem_services_DeleteInstanceAsync( 609 IWbemServices *iface, 610 const BSTR strObjectPath, 611 LONG lFlags, 612 IWbemContext *pCtx, 613 IWbemObjectSink *pResponseHandler ) 614 { 615 FIXME("\n"); 616 return WBEM_E_FAILED; 617 } 618 619 static HRESULT WINAPI wbem_services_CreateInstanceEnum( 620 IWbemServices *iface, 621 const BSTR strClass, 622 LONG lFlags, 623 IWbemContext *pCtx, 624 IEnumWbemClassObject **ppEnum ) 625 { 626 struct path *path; 627 HRESULT hr; 628 629 TRACE("%p, %s, 0%08x, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum); 630 631 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags); 632 633 hr = parse_path( strClass, &path ); 634 if (hr != S_OK) return hr; 635 636 hr = create_instance_enum( path, ppEnum ); 637 free_path( path ); 638 return hr; 639 } 640 641 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync( 642 IWbemServices *iface, 643 const BSTR strFilter, 644 LONG lFlags, 645 IWbemContext *pCtx, 646 IWbemObjectSink *pResponseHandler ) 647 { 648 FIXME("\n"); 649 return WBEM_E_FAILED; 650 } 651 652 static HRESULT WINAPI wbem_services_ExecQuery( 653 IWbemServices *iface, 654 const BSTR strQueryLanguage, 655 const BSTR strQuery, 656 LONG lFlags, 657 IWbemContext *pCtx, 658 IEnumWbemClassObject **ppEnum ) 659 { 660 static const WCHAR wqlW[] = {'W','Q','L',0}; 661 662 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), 663 debugstr_w(strQuery), lFlags, pCtx, ppEnum); 664 665 if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER; 666 if (wcsicmp( strQueryLanguage, wqlW )) return WBEM_E_INVALID_QUERY_TYPE; 667 return exec_query( strQuery, ppEnum ); 668 } 669 670 static void async_exec_query( struct async_header *hdr ) 671 { 672 struct async_query *query = (struct async_query *)hdr; 673 IEnumWbemClassObject *result; 674 IWbemClassObject *obj; 675 ULONG count; 676 HRESULT hr; 677 678 hr = exec_query( query->str, &result ); 679 if (hr == S_OK) 680 { 681 for (;;) 682 { 683 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); 684 if (!count) break; 685 IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj ); 686 IWbemClassObject_Release( obj ); 687 } 688 IEnumWbemClassObject_Release( result ); 689 } 690 IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL ); 691 heap_free( query->str ); 692 } 693 694 static HRESULT WINAPI wbem_services_ExecQueryAsync( 695 IWbemServices *iface, 696 const BSTR strQueryLanguage, 697 const BSTR strQuery, 698 LONG lFlags, 699 IWbemContext *pCtx, 700 IWbemObjectSink *pResponseHandler ) 701 { 702 struct wbem_services *services = impl_from_IWbemServices( iface ); 703 IWbemObjectSink *sink; 704 HRESULT hr = E_OUTOFMEMORY; 705 struct async_header *async; 706 struct async_query *query; 707 708 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery), 709 lFlags, pCtx, pResponseHandler); 710 711 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER; 712 713 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink ); 714 if (FAILED(hr)) return hr; 715 716 EnterCriticalSection( &services->cs ); 717 718 if (services->async) 719 { 720 FIXME("handle more than one pending async\n"); 721 hr = WBEM_E_FAILED; 722 goto done; 723 } 724 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done; 725 async = (struct async_header *)query; 726 727 if (!(init_async( async, sink, async_exec_query ))) 728 { 729 free_async( async ); 730 goto done; 731 } 732 if (!(query->str = heap_strdupW( strQuery ))) 733 { 734 free_async( async ); 735 goto done; 736 } 737 hr = queue_async( async ); 738 if (hr == S_OK) services->async = async; 739 else 740 { 741 heap_free( query->str ); 742 free_async( async ); 743 } 744 745 done: 746 LeaveCriticalSection( &services->cs ); 747 IWbemObjectSink_Release( sink ); 748 return hr; 749 } 750 751 static HRESULT WINAPI wbem_services_ExecNotificationQuery( 752 IWbemServices *iface, 753 const BSTR strQueryLanguage, 754 const BSTR strQuery, 755 LONG lFlags, 756 IWbemContext *pCtx, 757 IEnumWbemClassObject **ppEnum ) 758 { 759 FIXME("\n"); 760 return WBEM_E_FAILED; 761 } 762 763 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync( 764 IWbemServices *iface, 765 const BSTR strQueryLanguage, 766 const BSTR strQuery, 767 LONG lFlags, 768 IWbemContext *pCtx, 769 IWbemObjectSink *pResponseHandler ) 770 { 771 struct wbem_services *services = impl_from_IWbemServices( iface ); 772 IWbemObjectSink *sink; 773 HRESULT hr = E_OUTOFMEMORY; 774 struct async_header *async; 775 struct async_query *query; 776 777 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery), 778 lFlags, pCtx, pResponseHandler); 779 780 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER; 781 782 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink ); 783 if (FAILED(hr)) return hr; 784 785 EnterCriticalSection( &services->cs ); 786 787 if (services->async) 788 { 789 FIXME("handle more than one pending async\n"); 790 hr = WBEM_E_FAILED; 791 goto done; 792 } 793 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done; 794 async = (struct async_header *)query; 795 796 if (!(init_async( async, sink, async_exec_query ))) 797 { 798 free_async( async ); 799 goto done; 800 } 801 if (!(query->str = heap_strdupW( strQuery ))) 802 { 803 free_async( async ); 804 goto done; 805 } 806 hr = queue_async( async ); 807 if (hr == S_OK) services->async = async; 808 else 809 { 810 heap_free( query->str ); 811 free_async( async ); 812 } 813 814 done: 815 LeaveCriticalSection( &services->cs ); 816 IWbemObjectSink_Release( sink ); 817 return hr; 818 } 819 820 static HRESULT WINAPI wbem_services_ExecMethod( 821 IWbemServices *iface, 822 const BSTR strObjectPath, 823 const BSTR strMethodName, 824 LONG lFlags, 825 IWbemContext *pCtx, 826 IWbemClassObject *pInParams, 827 IWbemClassObject **ppOutParams, 828 IWbemCallResult **ppCallResult ) 829 { 830 IEnumWbemClassObject *result = NULL; 831 IWbemClassObject *obj = NULL; 832 struct query *query = NULL; 833 struct path *path; 834 WCHAR *str; 835 class_method *func; 836 struct table *table; 837 HRESULT hr; 838 839 TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath), 840 debugstr_w(strMethodName), lFlags, pCtx, pInParams, ppOutParams, ppCallResult); 841 842 if (lFlags) FIXME("flags %08x not supported\n", lFlags); 843 844 if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr; 845 if (!(str = query_from_path( path ))) 846 { 847 hr = E_OUTOFMEMORY; 848 goto done; 849 } 850 if (!(query = create_query())) 851 { 852 hr = E_OUTOFMEMORY; 853 goto done; 854 } 855 hr = parse_query( str, &query->view, &query->mem ); 856 if (hr != S_OK) goto done; 857 858 hr = execute_view( query->view ); 859 if (hr != S_OK) goto done; 860 861 hr = EnumWbemClassObject_create( query, (void **)&result ); 862 if (hr != S_OK) goto done; 863 864 table = get_view_table( query->view, 0 ); 865 hr = create_class_object( table->name, result, 0, NULL, &obj ); 866 if (hr != S_OK) goto done; 867 868 hr = get_method( table, strMethodName, &func ); 869 if (hr != S_OK) goto done; 870 871 hr = func( obj, pInParams, ppOutParams ); 872 873 done: 874 if (result) IEnumWbemClassObject_Release( result ); 875 if (obj) IWbemClassObject_Release( obj ); 876 free_query( query ); 877 free_path( path ); 878 heap_free( str ); 879 return hr; 880 } 881 882 static HRESULT WINAPI wbem_services_ExecMethodAsync( 883 IWbemServices *iface, 884 const BSTR strObjectPath, 885 const BSTR strMethodName, 886 LONG lFlags, 887 IWbemContext *pCtx, 888 IWbemClassObject *pInParams, 889 IWbemObjectSink *pResponseHandler ) 890 { 891 FIXME("\n"); 892 return WBEM_E_FAILED; 893 } 894 895 static const IWbemServicesVtbl wbem_services_vtbl = 896 { 897 wbem_services_QueryInterface, 898 wbem_services_AddRef, 899 wbem_services_Release, 900 wbem_services_OpenNamespace, 901 wbem_services_CancelAsyncCall, 902 wbem_services_QueryObjectSink, 903 wbem_services_GetObject, 904 wbem_services_GetObjectAsync, 905 wbem_services_PutClass, 906 wbem_services_PutClassAsync, 907 wbem_services_DeleteClass, 908 wbem_services_DeleteClassAsync, 909 wbem_services_CreateClassEnum, 910 wbem_services_CreateClassEnumAsync, 911 wbem_services_PutInstance, 912 wbem_services_PutInstanceAsync, 913 wbem_services_DeleteInstance, 914 wbem_services_DeleteInstanceAsync, 915 wbem_services_CreateInstanceEnum, 916 wbem_services_CreateInstanceEnumAsync, 917 wbem_services_ExecQuery, 918 wbem_services_ExecQueryAsync, 919 wbem_services_ExecNotificationQuery, 920 wbem_services_ExecNotificationQueryAsync, 921 wbem_services_ExecMethod, 922 wbem_services_ExecMethodAsync 923 }; 924 925 HRESULT WbemServices_create( const WCHAR *namespace, LPVOID *ppObj ) 926 { 927 struct wbem_services *ws; 928 929 TRACE("(%p)\n", ppObj); 930 931 ws = heap_alloc( sizeof(*ws) ); 932 if (!ws) return E_OUTOFMEMORY; 933 934 ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl; 935 ws->refs = 1; 936 ws->namespace = heap_strdupW( namespace ); 937 ws->async = NULL; 938 InitializeCriticalSection( &ws->cs ); 939 ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs"); 940 941 *ppObj = &ws->IWbemServices_iface; 942 943 TRACE("returning iface %p\n", *ppObj); 944 return S_OK; 945 } 946