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