fd87feb12ed75fd2e80f9dae64b09e79180abdb7
[reactos.git] / dll / win32 / wbemprox / services.c
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #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 while (*p && *p != '.') p++;
342
343 len = p - str;
344 if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) )))
345 {
346 heap_free( path );
347 return E_OUTOFMEMORY;
348 }
349 memcpy( path->class, str, len * sizeof(WCHAR) );
350 path->class[len] = 0;
351 path->class_len = len;
352
353 if (p[0] == '.' && p[1])
354 {
355 q = ++p;
356 while (*q) q++;
357
358 len = q - p;
359 if (!(path->filter = heap_alloc( (len + 1) * sizeof(WCHAR) )))
360 {
361 heap_free( path->class );
362 heap_free( path );
363 return E_OUTOFMEMORY;
364 }
365 memcpy( path->filter, p, len * sizeof(WCHAR) );
366 path->filter[len] = 0;
367 path->filter_len = len;
368 }
369 *ret = path;
370 return S_OK;
371 }
372
373 static void free_path( struct path *path )
374 {
375 heap_free( path->class );
376 heap_free( path->filter );
377 heap_free( path );
378 }
379
380 static WCHAR *query_from_path( const struct path *path )
381 {
382 static const WCHAR selectW[] =
383 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','%','s',' ',
384 'W','H','E','R','E',' ','%','s',0};
385 static const WCHAR select_allW[] =
386 {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
387 WCHAR *query;
388 UINT len;
389
390 if (path->filter)
391 {
392 len = path->class_len + path->filter_len + SIZEOF(selectW);
393 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
394 sprintfW( query, selectW, path->class, path->filter );
395 }
396 else
397 {
398 len = path->class_len + SIZEOF(select_allW);
399 if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
400 strcpyW( query, select_allW );
401 strcatW( query, path->class );
402 }
403 return query;
404 }
405
406 static HRESULT create_instance_enum( const struct path *path, IEnumWbemClassObject **iter )
407 {
408 WCHAR *query;
409 HRESULT hr;
410
411 if (!(query = query_from_path( path ))) return E_OUTOFMEMORY;
412 hr = exec_query( query, iter );
413 heap_free( query );
414 return hr;
415 }
416
417 HRESULT get_object( const WCHAR *object_path, IWbemClassObject **obj )
418 {
419 IEnumWbemClassObject *iter;
420 struct path *path;
421 HRESULT hr;
422
423 hr = parse_path( object_path, &path );
424 if (hr != S_OK) return hr;
425
426 hr = create_instance_enum( path, &iter );
427 if (hr != S_OK)
428 {
429 free_path( path );
430 return hr;
431 }
432 hr = create_class_object( path->class, iter, 0, NULL, obj );
433 IEnumWbemClassObject_Release( iter );
434 free_path( path );
435 return hr;
436 }
437
438 static HRESULT WINAPI wbem_services_GetObject(
439 IWbemServices *iface,
440 const BSTR strObjectPath,
441 LONG lFlags,
442 IWbemContext *pCtx,
443 IWbemClassObject **ppObject,
444 IWbemCallResult **ppCallResult )
445 {
446 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags,
447 pCtx, ppObject, ppCallResult);
448
449 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
450
451 if (!strObjectPath || !strObjectPath[0])
452 return create_class_object( NULL, NULL, 0, NULL, ppObject );
453
454 return get_object( strObjectPath, ppObject );
455 }
456
457 static HRESULT WINAPI wbem_services_GetObjectAsync(
458 IWbemServices *iface,
459 const BSTR strObjectPath,
460 LONG lFlags,
461 IWbemContext *pCtx,
462 IWbemObjectSink *pResponseHandler )
463 {
464 FIXME("\n");
465 return WBEM_E_FAILED;
466 }
467
468 static HRESULT WINAPI wbem_services_PutClass(
469 IWbemServices *iface,
470 IWbemClassObject *pObject,
471 LONG lFlags,
472 IWbemContext *pCtx,
473 IWbemCallResult **ppCallResult )
474 {
475 FIXME("\n");
476 return WBEM_E_FAILED;
477 }
478
479 static HRESULT WINAPI wbem_services_PutClassAsync(
480 IWbemServices *iface,
481 IWbemClassObject *pObject,
482 LONG lFlags,
483 IWbemContext *pCtx,
484 IWbemObjectSink *pResponseHandler )
485 {
486 FIXME("\n");
487 return WBEM_E_FAILED;
488 }
489
490 static HRESULT WINAPI wbem_services_DeleteClass(
491 IWbemServices *iface,
492 const BSTR strClass,
493 LONG lFlags,
494 IWbemContext *pCtx,
495 IWbemCallResult **ppCallResult )
496 {
497 FIXME("\n");
498 return WBEM_E_FAILED;
499 }
500
501 static HRESULT WINAPI wbem_services_DeleteClassAsync(
502 IWbemServices *iface,
503 const BSTR strClass,
504 LONG lFlags,
505 IWbemContext *pCtx,
506 IWbemObjectSink *pResponseHandler )
507 {
508 FIXME("\n");
509 return WBEM_E_FAILED;
510 }
511
512 static HRESULT WINAPI wbem_services_CreateClassEnum(
513 IWbemServices *iface,
514 const BSTR strSuperclass,
515 LONG lFlags,
516 IWbemContext *pCtx,
517 IEnumWbemClassObject **ppEnum )
518 {
519 FIXME("\n");
520 return WBEM_E_FAILED;
521 }
522
523 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
524 IWbemServices *iface,
525 const BSTR strSuperclass,
526 LONG lFlags,
527 IWbemContext *pCtx,
528 IWbemObjectSink *pResponseHandler )
529 {
530 FIXME("\n");
531 return WBEM_E_FAILED;
532 }
533
534 static HRESULT WINAPI wbem_services_PutInstance(
535 IWbemServices *iface,
536 IWbemClassObject *pInst,
537 LONG lFlags,
538 IWbemContext *pCtx,
539 IWbemCallResult **ppCallResult )
540 {
541 FIXME("\n");
542 return WBEM_E_FAILED;
543 }
544
545 static HRESULT WINAPI wbem_services_PutInstanceAsync(
546 IWbemServices *iface,
547 IWbemClassObject *pInst,
548 LONG lFlags,
549 IWbemContext *pCtx,
550 IWbemObjectSink *pResponseHandler )
551 {
552 FIXME("\n");
553 return WBEM_E_FAILED;
554 }
555
556 static HRESULT WINAPI wbem_services_DeleteInstance(
557 IWbemServices *iface,
558 const BSTR strObjectPath,
559 LONG lFlags,
560 IWbemContext *pCtx,
561 IWbemCallResult **ppCallResult )
562 {
563 FIXME("\n");
564 return WBEM_E_FAILED;
565 }
566
567 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
568 IWbemServices *iface,
569 const BSTR strObjectPath,
570 LONG lFlags,
571 IWbemContext *pCtx,
572 IWbemObjectSink *pResponseHandler )
573 {
574 FIXME("\n");
575 return WBEM_E_FAILED;
576 }
577
578 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
579 IWbemServices *iface,
580 const BSTR strClass,
581 LONG lFlags,
582 IWbemContext *pCtx,
583 IEnumWbemClassObject **ppEnum )
584 {
585 struct path *path;
586 HRESULT hr;
587
588 TRACE("%p, %s, 0%08x, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum);
589
590 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
591
592 hr = parse_path( strClass, &path );
593 if (hr != S_OK) return hr;
594
595 hr = create_instance_enum( path, ppEnum );
596 free_path( path );
597 return hr;
598 }
599
600 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
601 IWbemServices *iface,
602 const BSTR strFilter,
603 LONG lFlags,
604 IWbemContext *pCtx,
605 IWbemObjectSink *pResponseHandler )
606 {
607 FIXME("\n");
608 return WBEM_E_FAILED;
609 }
610
611 static HRESULT WINAPI wbem_services_ExecQuery(
612 IWbemServices *iface,
613 const BSTR strQueryLanguage,
614 const BSTR strQuery,
615 LONG lFlags,
616 IWbemContext *pCtx,
617 IEnumWbemClassObject **ppEnum )
618 {
619 static const WCHAR wqlW[] = {'W','Q','L',0};
620
621 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
622 debugstr_w(strQuery), lFlags, pCtx, ppEnum);
623
624 if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER;
625 if (strcmpiW( strQueryLanguage, wqlW )) return WBEM_E_INVALID_QUERY_TYPE;
626 return exec_query( strQuery, ppEnum );
627 }
628
629 static void async_exec_query( struct async_header *hdr )
630 {
631 struct async_query *query = (struct async_query *)hdr;
632 IEnumWbemClassObject *result;
633 IWbemClassObject *obj;
634 ULONG count;
635 HRESULT hr;
636
637 hr = exec_query( query->str, &result );
638 if (hr == S_OK)
639 {
640 for (;;)
641 {
642 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
643 if (!count) break;
644 IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj );
645 IWbemClassObject_Release( obj );
646 }
647 IEnumWbemClassObject_Release( result );
648 }
649 IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL );
650 heap_free( query->str );
651 }
652
653 static HRESULT WINAPI wbem_services_ExecQueryAsync(
654 IWbemServices *iface,
655 const BSTR strQueryLanguage,
656 const BSTR strQuery,
657 LONG lFlags,
658 IWbemContext *pCtx,
659 IWbemObjectSink *pResponseHandler )
660 {
661 struct wbem_services *services = impl_from_IWbemServices( iface );
662 IWbemObjectSink *sink;
663 HRESULT hr = E_OUTOFMEMORY;
664 struct async_header *async;
665 struct async_query *query;
666
667 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
668 lFlags, pCtx, pResponseHandler);
669
670 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
671
672 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
673 if (FAILED(hr)) return hr;
674
675 EnterCriticalSection( &services->cs );
676
677 if (services->async)
678 {
679 FIXME("handle more than one pending async\n");
680 hr = WBEM_E_FAILED;
681 goto done;
682 }
683 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
684 async = (struct async_header *)query;
685
686 if (!(init_async( async, sink, async_exec_query )))
687 {
688 free_async( async );
689 goto done;
690 }
691 if (!(query->str = heap_strdupW( strQuery )))
692 {
693 free_async( async );
694 goto done;
695 }
696 hr = queue_async( async );
697 if (hr == S_OK) services->async = async;
698 else
699 {
700 heap_free( query->str );
701 free_async( async );
702 }
703
704 done:
705 LeaveCriticalSection( &services->cs );
706 IWbemObjectSink_Release( sink );
707 return hr;
708 }
709
710 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
711 IWbemServices *iface,
712 const BSTR strQueryLanguage,
713 const BSTR strQuery,
714 LONG lFlags,
715 IWbemContext *pCtx,
716 IEnumWbemClassObject **ppEnum )
717 {
718 FIXME("\n");
719 return WBEM_E_FAILED;
720 }
721
722 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
723 IWbemServices *iface,
724 const BSTR strQueryLanguage,
725 const BSTR strQuery,
726 LONG lFlags,
727 IWbemContext *pCtx,
728 IWbemObjectSink *pResponseHandler )
729 {
730 struct wbem_services *services = impl_from_IWbemServices( iface );
731 IWbemObjectSink *sink;
732 HRESULT hr = E_OUTOFMEMORY;
733 struct async_header *async;
734 struct async_query *query;
735
736 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
737 lFlags, pCtx, pResponseHandler);
738
739 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
740
741 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
742 if (FAILED(hr)) return hr;
743
744 EnterCriticalSection( &services->cs );
745
746 if (services->async)
747 {
748 FIXME("handle more than one pending async\n");
749 hr = WBEM_E_FAILED;
750 goto done;
751 }
752 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
753 async = (struct async_header *)query;
754
755 if (!(init_async( async, sink, async_exec_query )))
756 {
757 free_async( async );
758 goto done;
759 }
760 if (!(query->str = heap_strdupW( strQuery )))
761 {
762 free_async( async );
763 goto done;
764 }
765 hr = queue_async( async );
766 if (hr == S_OK) services->async = async;
767 else
768 {
769 heap_free( query->str );
770 free_async( async );
771 }
772
773 done:
774 LeaveCriticalSection( &services->cs );
775 IWbemObjectSink_Release( sink );
776 return hr;
777 }
778
779 static HRESULT WINAPI wbem_services_ExecMethod(
780 IWbemServices *iface,
781 const BSTR strObjectPath,
782 const BSTR strMethodName,
783 LONG lFlags,
784 IWbemContext *pCtx,
785 IWbemClassObject *pInParams,
786 IWbemClassObject **ppOutParams,
787 IWbemCallResult **ppCallResult )
788 {
789 IEnumWbemClassObject *result = NULL;
790 IWbemClassObject *obj = NULL;
791 struct query *query = NULL;
792 struct path *path;
793 WCHAR *str;
794 class_method *func;
795 HRESULT hr;
796
797 TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
798 debugstr_w(strMethodName), lFlags, pCtx, pInParams, ppOutParams, ppCallResult);
799
800 if (lFlags) FIXME("flags %08x not supported\n", lFlags);
801
802 if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr;
803 if (!(str = query_from_path( path )))
804 {
805 hr = E_OUTOFMEMORY;
806 goto done;
807 }
808 if (!(query = create_query()))
809 {
810 hr = E_OUTOFMEMORY;
811 goto done;
812 }
813 hr = parse_query( str, &query->view, &query->mem );
814 if (hr != S_OK) goto done;
815
816 hr = execute_view( query->view );
817 if (hr != S_OK) goto done;
818
819 hr = EnumWbemClassObject_create( query, (void **)&result );
820 if (hr != S_OK) goto done;
821
822 hr = create_class_object( query->view->table->name, result, 0, NULL, &obj );
823 if (hr != S_OK) goto done;
824
825 hr = get_method( query->view->table, strMethodName, &func );
826 if (hr != S_OK) goto done;
827
828 hr = func( obj, pInParams, ppOutParams );
829
830 done:
831 if (result) IEnumWbemClassObject_Release( result );
832 if (obj) IWbemClassObject_Release( obj );
833 free_query( query );
834 free_path( path );
835 heap_free( str );
836 return hr;
837 }
838
839 static HRESULT WINAPI wbem_services_ExecMethodAsync(
840 IWbemServices *iface,
841 const BSTR strObjectPath,
842 const BSTR strMethodName,
843 LONG lFlags,
844 IWbemContext *pCtx,
845 IWbemClassObject *pInParams,
846 IWbemObjectSink *pResponseHandler )
847 {
848 FIXME("\n");
849 return WBEM_E_FAILED;
850 }
851
852 static const IWbemServicesVtbl wbem_services_vtbl =
853 {
854 wbem_services_QueryInterface,
855 wbem_services_AddRef,
856 wbem_services_Release,
857 wbem_services_OpenNamespace,
858 wbem_services_CancelAsyncCall,
859 wbem_services_QueryObjectSink,
860 wbem_services_GetObject,
861 wbem_services_GetObjectAsync,
862 wbem_services_PutClass,
863 wbem_services_PutClassAsync,
864 wbem_services_DeleteClass,
865 wbem_services_DeleteClassAsync,
866 wbem_services_CreateClassEnum,
867 wbem_services_CreateClassEnumAsync,
868 wbem_services_PutInstance,
869 wbem_services_PutInstanceAsync,
870 wbem_services_DeleteInstance,
871 wbem_services_DeleteInstanceAsync,
872 wbem_services_CreateInstanceEnum,
873 wbem_services_CreateInstanceEnumAsync,
874 wbem_services_ExecQuery,
875 wbem_services_ExecQueryAsync,
876 wbem_services_ExecNotificationQuery,
877 wbem_services_ExecNotificationQueryAsync,
878 wbem_services_ExecMethod,
879 wbem_services_ExecMethodAsync
880 };
881
882 HRESULT WbemServices_create( const WCHAR *namespace, LPVOID *ppObj )
883 {
884 struct wbem_services *ws;
885
886 TRACE("(%p)\n", ppObj);
887
888 ws = heap_alloc( sizeof(*ws) );
889 if (!ws) return E_OUTOFMEMORY;
890
891 ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
892 ws->refs = 1;
893 ws->namespace = heap_strdupW( namespace );
894 ws->async = NULL;
895 InitializeCriticalSection( &ws->cs );
896 ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs");
897
898 *ppObj = &ws->IWbemServices_iface;
899
900 TRACE("returning iface %p\n", *ppObj);
901 return S_OK;
902 }