wined3d: Don't use persistent BOs from the client thread if we might need to do verte...
[wine.git] / dlls / wbemprox / services.c
blob9b9e1f37abd2cd57215f3e5867d07c1bc94131a6
1 /*
2 * Copyright 2012 Hans Leidekker for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "objbase.h"
26 #include "wbemcli.h"
28 #include "wine/debug.h"
29 #include "wbemprox_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
33 struct client_security
35 IClientSecurity IClientSecurity_iface;
38 static inline struct client_security *impl_from_IClientSecurity( IClientSecurity *iface )
40 return CONTAINING_RECORD( iface, struct client_security, IClientSecurity_iface );
43 static HRESULT WINAPI client_security_QueryInterface(
44 IClientSecurity *iface,
45 REFIID riid,
46 void **ppvObject )
48 struct client_security *cs = impl_from_IClientSecurity( iface );
50 TRACE("%p %s %p\n", cs, debugstr_guid( riid ), ppvObject );
52 if ( IsEqualGUID( riid, &IID_IClientSecurity ) ||
53 IsEqualGUID( riid, &IID_IUnknown ) )
55 *ppvObject = cs;
57 else
59 FIXME("interface %s not implemented\n", debugstr_guid(riid));
60 return E_NOINTERFACE;
62 IClientSecurity_AddRef( iface );
63 return S_OK;
66 static ULONG WINAPI client_security_AddRef(
67 IClientSecurity *iface )
69 FIXME("%p\n", iface);
70 return 2;
73 static ULONG WINAPI client_security_Release(
74 IClientSecurity *iface )
76 FIXME("%p\n", iface);
77 return 1;
80 static HRESULT WINAPI client_security_QueryBlanket(
81 IClientSecurity *iface,
82 IUnknown *pProxy,
83 DWORD *pAuthnSvc,
84 DWORD *pAuthzSvc,
85 OLECHAR **pServerPrincName,
86 DWORD *pAuthnLevel,
87 DWORD *pImpLevel,
88 void **pAuthInfo,
89 DWORD *pCapabilities )
91 FIXME("semi-stub.\n");
93 if (pAuthnSvc)
94 *pAuthnSvc = RPC_C_AUTHN_NONE;
95 if (pAuthzSvc)
96 *pAuthzSvc = RPC_C_AUTHZ_NONE;
97 if (pServerPrincName)
98 *pServerPrincName = NULL;
99 if (pAuthnLevel)
100 *pAuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
101 if (pImpLevel)
102 *pImpLevel = RPC_C_IMP_LEVEL_DEFAULT;
103 if (pAuthInfo)
104 *pAuthInfo = NULL;
105 if (pCapabilities)
106 *pCapabilities = 0;
108 return WBEM_NO_ERROR;
111 static HRESULT WINAPI client_security_SetBlanket(
112 IClientSecurity *iface,
113 IUnknown *pProxy,
114 DWORD AuthnSvc,
115 DWORD AuthzSvc,
116 OLECHAR *pServerPrincName,
117 DWORD AuthnLevel,
118 DWORD ImpLevel,
119 void *pAuthInfo,
120 DWORD Capabilities )
122 const OLECHAR *princname = (pServerPrincName == COLE_DEFAULT_PRINCIPAL) ?
123 L"<COLE_DEFAULT_PRINCIPAL>" : pServerPrincName;
125 FIXME( "%p, %p, %lu, %lu, %s, %lu, %lu, %p, %#lx\n", iface, pProxy, AuthnSvc, AuthzSvc,
126 debugstr_w(princname), AuthnLevel, ImpLevel, pAuthInfo, Capabilities );
127 return WBEM_NO_ERROR;
130 static HRESULT WINAPI client_security_CopyProxy(
131 IClientSecurity *iface,
132 IUnknown *pProxy,
133 IUnknown **ppCopy )
135 FIXME("\n");
136 return WBEM_E_FAILED;
139 static const IClientSecurityVtbl client_security_vtbl =
141 client_security_QueryInterface,
142 client_security_AddRef,
143 client_security_Release,
144 client_security_QueryBlanket,
145 client_security_SetBlanket,
146 client_security_CopyProxy
149 IClientSecurity client_security = { &client_security_vtbl };
151 struct async_header
153 IWbemObjectSink *sink;
154 void (*proc)( struct async_header * );
155 HANDLE cancel;
156 HANDLE wait;
159 struct async_query
161 struct async_header hdr;
162 enum wbm_namespace ns;
163 WCHAR *str;
166 static void free_async( struct async_header *async )
168 if (async->sink) IWbemObjectSink_Release( async->sink );
169 CloseHandle( async->cancel );
170 CloseHandle( async->wait );
171 free( async );
174 static BOOL init_async( struct async_header *async, IWbemObjectSink *sink,
175 void (*proc)(struct async_header *) )
177 if (!(async->wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
178 if (!(async->cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
180 CloseHandle( async->wait );
181 return FALSE;
183 async->proc = proc;
184 async->sink = sink;
185 IWbemObjectSink_AddRef( sink );
186 return TRUE;
189 static DWORD CALLBACK async_proc( LPVOID param )
191 struct async_header *async = param;
192 HANDLE wait = async->wait;
194 async->proc( async );
196 WaitForSingleObject( async->cancel, INFINITE );
197 SetEvent( wait );
198 return ERROR_SUCCESS;
201 static HRESULT queue_async( struct async_header *async )
203 if (QueueUserWorkItem( async_proc, async, WT_EXECUTELONGFUNCTION )) return S_OK;
204 return HRESULT_FROM_WIN32( GetLastError() );
207 struct wbem_services
209 IWbemServices IWbemServices_iface;
210 LONG refs;
211 CRITICAL_SECTION cs;
212 enum wbm_namespace ns;
213 struct async_header *async;
214 IWbemContext *context;
217 static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface )
219 return CONTAINING_RECORD( iface, struct wbem_services, IWbemServices_iface );
222 static ULONG WINAPI wbem_services_AddRef(
223 IWbemServices *iface )
225 struct wbem_services *ws = impl_from_IWbemServices( iface );
226 return InterlockedIncrement( &ws->refs );
229 static ULONG WINAPI wbem_services_Release(
230 IWbemServices *iface )
232 struct wbem_services *ws = impl_from_IWbemServices( iface );
233 LONG refs = InterlockedDecrement( &ws->refs );
234 if (!refs)
236 TRACE("destroying %p\n", ws);
238 EnterCriticalSection( &ws->cs );
239 if (ws->async) SetEvent( ws->async->cancel );
240 LeaveCriticalSection( &ws->cs );
241 if (ws->async)
243 WaitForSingleObject( ws->async->wait, INFINITE );
244 free_async( ws->async );
246 ws->cs.DebugInfo->Spare[0] = 0;
247 DeleteCriticalSection( &ws->cs );
248 if (ws->context)
249 IWbemContext_Release( ws->context );
250 free( ws );
252 return refs;
255 static HRESULT WINAPI wbem_services_QueryInterface(
256 IWbemServices *iface,
257 REFIID riid,
258 void **ppvObject )
260 struct wbem_services *ws = impl_from_IWbemServices( iface );
262 TRACE("%p %s %p\n", ws, debugstr_guid( riid ), ppvObject );
264 if ( IsEqualGUID( riid, &IID_IWbemServices ) ||
265 IsEqualGUID( riid, &IID_IUnknown ) )
267 *ppvObject = ws;
269 else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
271 *ppvObject = &client_security;
272 return S_OK;
274 else
276 FIXME("interface %s not implemented\n", debugstr_guid(riid));
277 return E_NOINTERFACE;
279 IWbemServices_AddRef( iface );
280 return S_OK;
283 static HRESULT WINAPI wbem_services_OpenNamespace(
284 IWbemServices *iface,
285 const BSTR strNamespace,
286 LONG lFlags,
287 IWbemContext *pCtx,
288 IWbemServices **ppWorkingNamespace,
289 IWbemCallResult **ppResult )
291 struct wbem_services *ws = impl_from_IWbemServices( iface );
293 TRACE( "%p, %s, %#lx, %p, %p, %p\n", iface, debugstr_w(strNamespace), lFlags,
294 pCtx, ppWorkingNamespace, ppResult );
296 if (ws->ns != WBEMPROX_NAMESPACE_LAST || !strNamespace)
297 return WBEM_E_INVALID_NAMESPACE;
299 return WbemServices_create( strNamespace, NULL, (void **)ppWorkingNamespace );
302 static HRESULT WINAPI wbem_services_CancelAsyncCall(
303 IWbemServices *iface,
304 IWbemObjectSink *pSink )
306 struct wbem_services *services = impl_from_IWbemServices( iface );
307 struct async_header *async;
309 TRACE("%p, %p\n", iface, pSink);
311 if (!pSink) return WBEM_E_INVALID_PARAMETER;
313 EnterCriticalSection( &services->cs );
315 if (!(async = services->async))
317 LeaveCriticalSection( &services->cs );
318 return WBEM_E_INVALID_PARAMETER;
320 services->async = NULL;
321 SetEvent( async->cancel );
323 LeaveCriticalSection( &services->cs );
325 WaitForSingleObject( async->wait, INFINITE );
326 free_async( async );
327 return S_OK;
330 static HRESULT WINAPI wbem_services_QueryObjectSink(
331 IWbemServices *iface,
332 LONG lFlags,
333 IWbemObjectSink **ppResponseHandler )
335 FIXME("\n");
336 return WBEM_E_FAILED;
339 HRESULT parse_path( const WCHAR *str, struct path **ret )
341 struct path *path;
342 const WCHAR *p = str, *q;
343 UINT len;
345 if (!(path = calloc( 1, sizeof(*path) ))) return E_OUTOFMEMORY;
347 if (*p == '\\')
349 static const WCHAR cimv2W[] = L"ROOT\\CIMV2";
350 WCHAR server[MAX_COMPUTERNAME_LENGTH+1];
351 DWORD server_len = ARRAY_SIZE(server);
353 p++;
354 if (*p != '\\')
356 free( path );
357 return WBEM_E_INVALID_OBJECT_PATH;
359 p++;
361 q = p;
362 while (*p && *p != '\\') p++;
363 if (!*p)
365 free( path );
366 return WBEM_E_INVALID_OBJECT_PATH;
369 len = p - q;
370 if (!GetComputerNameW( server, &server_len ) || server_len != len || wcsnicmp( q, server, server_len ))
372 free( path );
373 return WBEM_E_NOT_SUPPORTED;
376 q = ++p;
377 while (*p && *p != ':') p++;
378 if (!*p)
380 free( path );
381 return WBEM_E_INVALID_OBJECT_PATH;
384 len = p - q;
385 if (len != ARRAY_SIZE(cimv2W) - 1 || wcsnicmp( q, cimv2W, ARRAY_SIZE(cimv2W) - 1 ))
387 free( path );
388 return WBEM_E_INVALID_NAMESPACE;
390 p++;
393 q = p;
394 while (*p && *p != '.') p++;
396 len = p - q;
397 if (!(path->class = malloc( (len + 1) * sizeof(WCHAR) )))
399 free( path );
400 return E_OUTOFMEMORY;
402 memcpy( path->class, q, len * sizeof(WCHAR) );
403 path->class[len] = 0;
404 path->class_len = len;
406 if (p[0] == '.' && p[1])
408 q = ++p;
409 while (*q) q++;
411 len = q - p;
412 if (!(path->filter = malloc( (len + 1) * sizeof(WCHAR) )))
414 free( path->class );
415 free( path );
416 return E_OUTOFMEMORY;
418 memcpy( path->filter, p, len * sizeof(WCHAR) );
419 path->filter[len] = 0;
420 path->filter_len = len;
422 *ret = path;
423 return S_OK;
426 void free_path( struct path *path )
428 if (!path) return;
429 free( path->class );
430 free( path->filter );
431 free( path );
434 WCHAR *query_from_path( const struct path *path )
436 static const WCHAR selectW[] = L"SELECT * FROM %s WHERE %s";
437 static const WCHAR select_allW[] = L"SELECT * FROM ";
438 WCHAR *query;
439 UINT len;
441 if (path->filter)
443 len = path->class_len + path->filter_len + ARRAY_SIZE(selectW);
444 if (!(query = malloc( len * sizeof(WCHAR) ))) return NULL;
445 swprintf( query, len, selectW, path->class, path->filter );
447 else
449 len = path->class_len + ARRAY_SIZE(select_allW);
450 if (!(query = malloc( len * sizeof(WCHAR) ))) return NULL;
451 lstrcpyW( query, select_allW );
452 lstrcatW( query, path->class );
454 return query;
457 static HRESULT create_instance_enum( enum wbm_namespace ns, const struct path *path, IEnumWbemClassObject **iter )
459 WCHAR *query;
460 HRESULT hr;
462 if (!(query = query_from_path( path ))) return E_OUTOFMEMORY;
463 hr = exec_query( ns, query, iter );
464 free( query );
465 return hr;
468 HRESULT get_object( enum wbm_namespace ns, const WCHAR *object_path, IWbemClassObject **obj )
470 IEnumWbemClassObject *iter;
471 struct path *path;
472 ULONG count;
473 HRESULT hr;
475 hr = parse_path( object_path, &path );
476 if (hr != S_OK) return hr;
478 hr = create_instance_enum( ns, path, &iter );
479 if (hr != S_OK)
481 free_path( path );
482 return hr;
484 hr = IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, obj, &count );
485 if (hr == WBEM_S_FALSE)
487 hr = WBEM_E_NOT_FOUND;
488 *obj = NULL;
490 IEnumWbemClassObject_Release( iter );
491 free_path( path );
492 return hr;
495 static HRESULT WINAPI wbem_services_GetObject(
496 IWbemServices *iface,
497 const BSTR strObjectPath,
498 LONG lFlags,
499 IWbemContext *pCtx,
500 IWbemClassObject **ppObject,
501 IWbemCallResult **ppCallResult )
503 struct wbem_services *services = impl_from_IWbemServices( iface );
505 TRACE( "%p, %s, %#lx, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags,
506 pCtx, ppObject, ppCallResult );
508 if (lFlags) FIXME( "unsupported flags %#lx\n", lFlags );
510 if (!strObjectPath || !strObjectPath[0])
511 return create_class_object( services->ns, NULL, NULL, 0, NULL, ppObject );
513 return get_object( services->ns, strObjectPath, ppObject );
516 static HRESULT WINAPI wbem_services_GetObjectAsync(
517 IWbemServices *iface,
518 const BSTR strObjectPath,
519 LONG lFlags,
520 IWbemContext *pCtx,
521 IWbemObjectSink *pResponseHandler )
523 FIXME("\n");
524 return WBEM_E_FAILED;
527 static HRESULT WINAPI wbem_services_PutClass(
528 IWbemServices *iface,
529 IWbemClassObject *pObject,
530 LONG lFlags,
531 IWbemContext *pCtx,
532 IWbemCallResult **ppCallResult )
534 FIXME("\n");
535 return WBEM_E_FAILED;
538 static HRESULT WINAPI wbem_services_PutClassAsync(
539 IWbemServices *iface,
540 IWbemClassObject *pObject,
541 LONG lFlags,
542 IWbemContext *pCtx,
543 IWbemObjectSink *pResponseHandler )
545 FIXME("\n");
546 return WBEM_E_FAILED;
549 static HRESULT WINAPI wbem_services_DeleteClass(
550 IWbemServices *iface,
551 const BSTR strClass,
552 LONG lFlags,
553 IWbemContext *pCtx,
554 IWbemCallResult **ppCallResult )
556 FIXME("\n");
557 return WBEM_E_FAILED;
560 static HRESULT WINAPI wbem_services_DeleteClassAsync(
561 IWbemServices *iface,
562 const BSTR strClass,
563 LONG lFlags,
564 IWbemContext *pCtx,
565 IWbemObjectSink *pResponseHandler )
567 FIXME("\n");
568 return WBEM_E_FAILED;
571 static HRESULT WINAPI wbem_services_CreateClassEnum(
572 IWbemServices *iface,
573 const BSTR strSuperclass,
574 LONG lFlags,
575 IWbemContext *pCtx,
576 IEnumWbemClassObject **ppEnum )
578 FIXME("\n");
579 return WBEM_E_FAILED;
582 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
583 IWbemServices *iface,
584 const BSTR strSuperclass,
585 LONG lFlags,
586 IWbemContext *pCtx,
587 IWbemObjectSink *pResponseHandler )
589 FIXME("\n");
590 return WBEM_E_FAILED;
593 static HRESULT WINAPI wbem_services_PutInstance(
594 IWbemServices *iface,
595 IWbemClassObject *pInst,
596 LONG lFlags,
597 IWbemContext *pCtx,
598 IWbemCallResult **ppCallResult )
600 FIXME("\n");
601 return WBEM_E_FAILED;
604 static HRESULT WINAPI wbem_services_PutInstanceAsync(
605 IWbemServices *iface,
606 IWbemClassObject *pInst,
607 LONG lFlags,
608 IWbemContext *pCtx,
609 IWbemObjectSink *pResponseHandler )
611 FIXME("\n");
612 return WBEM_E_FAILED;
615 static HRESULT WINAPI wbem_services_DeleteInstance(
616 IWbemServices *iface,
617 const BSTR strObjectPath,
618 LONG lFlags,
619 IWbemContext *pCtx,
620 IWbemCallResult **ppCallResult )
622 FIXME("\n");
623 return WBEM_E_FAILED;
626 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
627 IWbemServices *iface,
628 const BSTR strObjectPath,
629 LONG lFlags,
630 IWbemContext *pCtx,
631 IWbemObjectSink *pResponseHandler )
633 FIXME("\n");
634 return WBEM_E_FAILED;
637 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
638 IWbemServices *iface,
639 const BSTR strClass,
640 LONG lFlags,
641 IWbemContext *pCtx,
642 IEnumWbemClassObject **ppEnum )
644 struct wbem_services *services = impl_from_IWbemServices( iface );
645 struct path *path;
646 HRESULT hr;
648 TRACE( "%p, %s, %#lx, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum );
650 if (lFlags) FIXME( "unsupported flags %#lx\n", lFlags );
652 hr = parse_path( strClass, &path );
653 if (hr != S_OK) return hr;
655 hr = create_instance_enum( services->ns, path, ppEnum );
656 free_path( path );
657 return hr;
660 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
661 IWbemServices *iface,
662 const BSTR strFilter,
663 LONG lFlags,
664 IWbemContext *pCtx,
665 IWbemObjectSink *pResponseHandler )
667 FIXME("\n");
668 return WBEM_E_FAILED;
671 static HRESULT WINAPI wbem_services_ExecQuery(
672 IWbemServices *iface,
673 const BSTR strQueryLanguage,
674 const BSTR strQuery,
675 LONG lFlags,
676 IWbemContext *pCtx,
677 IEnumWbemClassObject **ppEnum )
679 struct wbem_services *services = impl_from_IWbemServices( iface );
681 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage),
682 debugstr_w(strQuery), lFlags, pCtx, ppEnum );
684 if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER;
685 if (wcsicmp( strQueryLanguage, L"WQL" )) return WBEM_E_INVALID_QUERY_TYPE;
686 return exec_query( services->ns, strQuery, ppEnum );
689 static void async_exec_query( struct async_header *hdr )
691 struct async_query *query = (struct async_query *)hdr;
692 IEnumWbemClassObject *result;
693 IWbemClassObject *obj;
694 ULONG count;
695 HRESULT hr;
697 hr = exec_query( query->ns, query->str, &result );
698 if (hr == S_OK)
700 for (;;)
702 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
703 if (!count) break;
704 IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj );
705 IWbemClassObject_Release( obj );
707 IEnumWbemClassObject_Release( result );
709 IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL );
710 free( query->str );
713 static HRESULT WINAPI wbem_services_ExecQueryAsync(
714 IWbemServices *iface,
715 const BSTR strQueryLanguage,
716 const BSTR strQuery,
717 LONG lFlags,
718 IWbemContext *pCtx,
719 IWbemObjectSink *pResponseHandler )
721 struct wbem_services *services = impl_from_IWbemServices( iface );
722 IWbemObjectSink *sink;
723 HRESULT hr = E_OUTOFMEMORY;
724 struct async_header *async;
725 struct async_query *query;
727 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
728 lFlags, pCtx, pResponseHandler );
730 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
732 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
733 if (FAILED(hr)) return hr;
735 EnterCriticalSection( &services->cs );
737 if (services->async)
739 FIXME("handle more than one pending async\n");
740 hr = WBEM_E_FAILED;
741 goto done;
743 if (!(query = calloc( 1, sizeof(*query) ))) goto done;
744 query->ns = services->ns;
745 async = (struct async_header *)query;
747 if (!(init_async( async, sink, async_exec_query )))
749 free_async( async );
750 goto done;
752 if (!(query->str = heap_strdupW( strQuery )))
754 free_async( async );
755 goto done;
757 hr = queue_async( async );
758 if (hr == S_OK) services->async = async;
759 else
761 free( query->str );
762 free_async( async );
765 done:
766 LeaveCriticalSection( &services->cs );
767 IWbemObjectSink_Release( sink );
768 return hr;
771 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
772 IWbemServices *iface,
773 const BSTR strQueryLanguage,
774 const BSTR strQuery,
775 LONG lFlags,
776 IWbemContext *pCtx,
777 IEnumWbemClassObject **ppEnum )
779 FIXME("\n");
780 return WBEM_E_FAILED;
783 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
784 IWbemServices *iface,
785 const BSTR strQueryLanguage,
786 const BSTR strQuery,
787 LONG lFlags,
788 IWbemContext *pCtx,
789 IWbemObjectSink *pResponseHandler )
791 struct wbem_services *services = impl_from_IWbemServices( iface );
792 IWbemObjectSink *sink;
793 HRESULT hr = E_OUTOFMEMORY;
794 struct async_header *async;
795 struct async_query *query;
797 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
798 lFlags, pCtx, pResponseHandler );
800 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
802 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
803 if (FAILED(hr)) return hr;
805 EnterCriticalSection( &services->cs );
807 if (services->async)
809 FIXME("handle more than one pending async\n");
810 hr = WBEM_E_FAILED;
811 goto done;
813 if (!(query = calloc( 1, sizeof(*query) ))) goto done;
814 async = (struct async_header *)query;
816 if (!(init_async( async, sink, async_exec_query )))
818 free_async( async );
819 goto done;
821 if (!(query->str = heap_strdupW( strQuery )))
823 free_async( async );
824 goto done;
826 hr = queue_async( async );
827 if (hr == S_OK) services->async = async;
828 else
830 free( query->str );
831 free_async( async );
834 done:
835 LeaveCriticalSection( &services->cs );
836 IWbemObjectSink_Release( sink );
837 return hr;
840 static HRESULT WINAPI wbem_services_ExecMethod(
841 IWbemServices *iface,
842 const BSTR strObjectPath,
843 const BSTR strMethodName,
844 LONG lFlags,
845 IWbemContext *context,
846 IWbemClassObject *pInParams,
847 IWbemClassObject **ppOutParams,
848 IWbemCallResult **ppCallResult )
850 struct wbem_services *services = impl_from_IWbemServices( iface );
851 IEnumWbemClassObject *result = NULL;
852 IWbemClassObject *obj = NULL;
853 struct query *query = NULL;
854 struct path *path;
855 WCHAR *str;
856 class_method *func;
857 struct table *table;
858 HRESULT hr;
860 TRACE( "%p, %s, %s, %#lx, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
861 debugstr_w(strMethodName), lFlags, context, pInParams, ppOutParams, ppCallResult );
863 if (lFlags) FIXME( "flags %#lx not supported\n", lFlags );
865 if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr;
866 if (!(str = query_from_path( path )))
868 hr = E_OUTOFMEMORY;
869 goto done;
871 if (!(query = create_query( services->ns )))
873 hr = E_OUTOFMEMORY;
874 goto done;
876 hr = parse_query( services->ns, str, &query->view, &query->mem );
877 if (hr != S_OK) goto done;
879 hr = execute_view( query->view );
880 if (hr != S_OK) goto done;
882 hr = EnumWbemClassObject_create( query, (void **)&result );
883 if (hr != S_OK) goto done;
885 table = get_view_table( query->view, 0 );
886 hr = create_class_object( services->ns, table->name, result, 0, NULL, &obj );
887 if (hr != S_OK) goto done;
889 hr = get_method( table, strMethodName, &func );
890 if (hr != S_OK) goto done;
892 hr = func( obj, context ? context : services->context, pInParams, ppOutParams );
894 done:
895 if (result) IEnumWbemClassObject_Release( result );
896 if (obj) IWbemClassObject_Release( obj );
897 free_query( query );
898 free_path( path );
899 free( str );
900 return hr;
903 static HRESULT WINAPI wbem_services_ExecMethodAsync(
904 IWbemServices *iface,
905 const BSTR strObjectPath,
906 const BSTR strMethodName,
907 LONG lFlags,
908 IWbemContext *pCtx,
909 IWbemClassObject *pInParams,
910 IWbemObjectSink *pResponseHandler )
912 FIXME("\n");
913 return WBEM_E_FAILED;
916 static const IWbemServicesVtbl wbem_services_vtbl =
918 wbem_services_QueryInterface,
919 wbem_services_AddRef,
920 wbem_services_Release,
921 wbem_services_OpenNamespace,
922 wbem_services_CancelAsyncCall,
923 wbem_services_QueryObjectSink,
924 wbem_services_GetObject,
925 wbem_services_GetObjectAsync,
926 wbem_services_PutClass,
927 wbem_services_PutClassAsync,
928 wbem_services_DeleteClass,
929 wbem_services_DeleteClassAsync,
930 wbem_services_CreateClassEnum,
931 wbem_services_CreateClassEnumAsync,
932 wbem_services_PutInstance,
933 wbem_services_PutInstanceAsync,
934 wbem_services_DeleteInstance,
935 wbem_services_DeleteInstanceAsync,
936 wbem_services_CreateInstanceEnum,
937 wbem_services_CreateInstanceEnumAsync,
938 wbem_services_ExecQuery,
939 wbem_services_ExecQueryAsync,
940 wbem_services_ExecNotificationQuery,
941 wbem_services_ExecNotificationQueryAsync,
942 wbem_services_ExecMethod,
943 wbem_services_ExecMethodAsync
946 HRESULT WbemServices_create( const WCHAR *namespace, IWbemContext *context, LPVOID *ppObj )
948 struct wbem_services *ws;
949 enum wbm_namespace ns;
951 TRACE("namespace %s, context %p, ppObj %p.\n", debugstr_w(namespace), context, ppObj);
953 if (!namespace)
954 ns = WBEMPROX_NAMESPACE_LAST;
955 else if ((ns = get_namespace_from_string( namespace )) == WBEMPROX_NAMESPACE_LAST)
956 return WBEM_E_INVALID_NAMESPACE;
958 if (!(ws = calloc( 1, sizeof(*ws) ))) return E_OUTOFMEMORY;
960 ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
961 ws->refs = 1;
962 ws->ns = ns;
963 InitializeCriticalSection( &ws->cs );
964 ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs");
965 if (context)
966 IWbemContext_Clone( context, &ws->context );
968 *ppObj = &ws->IWbemServices_iface;
970 TRACE("returning iface %p\n", *ppObj);
971 return S_OK;
974 struct wbem_context_value
976 struct list entry;
977 WCHAR *name;
978 VARIANT value;
981 struct wbem_context
983 IWbemContext IWbemContext_iface;
984 LONG refs;
985 struct list values;
988 static void wbem_context_delete_values(struct wbem_context *context)
990 struct wbem_context_value *value, *next;
992 LIST_FOR_EACH_ENTRY_SAFE(value, next, &context->values, struct wbem_context_value, entry)
994 list_remove( &value->entry );
995 VariantClear( &value->value );
996 free( value->name );
997 free( value );
1001 static struct wbem_context *impl_from_IWbemContext( IWbemContext *iface )
1003 return CONTAINING_RECORD( iface, struct wbem_context, IWbemContext_iface );
1006 static HRESULT WINAPI wbem_context_QueryInterface(
1007 IWbemContext *iface,
1008 REFIID riid,
1009 void **obj)
1011 TRACE("%p, %s, %p\n", iface, debugstr_guid( riid ), obj );
1013 if ( IsEqualGUID( riid, &IID_IWbemContext ) ||
1014 IsEqualGUID( riid, &IID_IUnknown ) )
1016 *obj = iface;
1018 else
1020 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1021 return E_NOINTERFACE;
1024 IWbemContext_AddRef( iface );
1025 return S_OK;
1028 static ULONG WINAPI wbem_context_AddRef(
1029 IWbemContext *iface )
1031 struct wbem_context *context = impl_from_IWbemContext( iface );
1032 return InterlockedIncrement( &context->refs );
1035 static ULONG WINAPI wbem_context_Release(
1036 IWbemContext *iface )
1038 struct wbem_context *context = impl_from_IWbemContext( iface );
1039 LONG refs = InterlockedDecrement( &context->refs );
1041 if (!refs)
1043 TRACE("destroying %p\n", context);
1044 wbem_context_delete_values( context );
1045 free( context );
1047 return refs;
1050 static HRESULT WINAPI wbem_context_Clone(
1051 IWbemContext *iface,
1052 IWbemContext **newcopy )
1054 struct wbem_context *context = impl_from_IWbemContext( iface );
1055 struct wbem_context_value *value;
1056 IWbemContext *cloned_context;
1057 HRESULT hr;
1059 TRACE("%p, %p\n", iface, newcopy);
1061 if (SUCCEEDED(hr = WbemContext_create( (void **)&cloned_context )))
1063 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1065 if (FAILED(hr = IWbemContext_SetValue( cloned_context, value->name, 0, &value->value ))) break;
1069 if (SUCCEEDED(hr))
1071 *newcopy = cloned_context;
1073 else
1075 *newcopy = NULL;
1076 IWbemContext_Release( cloned_context );
1079 return hr;
1082 static HRESULT WINAPI wbem_context_GetNames(
1083 IWbemContext *iface,
1084 LONG flags,
1085 SAFEARRAY **names )
1087 FIXME( "%p, %#lx, %p\n", iface, flags, names );
1089 return E_NOTIMPL;
1092 static HRESULT WINAPI wbem_context_BeginEnumeration(
1093 IWbemContext *iface,
1094 LONG flags )
1096 FIXME( "%p, %#lx\n", iface, flags );
1098 return E_NOTIMPL;
1101 static HRESULT WINAPI wbem_context_Next(
1102 IWbemContext *iface,
1103 LONG flags,
1104 BSTR *name,
1105 VARIANT *value )
1107 FIXME( "%p, %#lx, %p, %p\n", iface, flags, name, value );
1109 return E_NOTIMPL;
1112 static HRESULT WINAPI wbem_context_EndEnumeration(
1113 IWbemContext *iface )
1115 FIXME("%p\n", iface);
1117 return E_NOTIMPL;
1120 static struct wbem_context_value *wbem_context_get_value( struct wbem_context *context, const WCHAR *name )
1122 struct wbem_context_value *value;
1124 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1126 if (!lstrcmpiW( value->name, name )) return value;
1129 return NULL;
1132 static HRESULT WINAPI wbem_context_SetValue(
1133 IWbemContext *iface,
1134 LPCWSTR name,
1135 LONG flags,
1136 VARIANT *var )
1138 struct wbem_context *context = impl_from_IWbemContext( iface );
1139 struct wbem_context_value *value;
1140 HRESULT hr;
1142 TRACE( "%p, %s, %#lx, %s\n", iface, debugstr_w(name), flags, debugstr_variant(var) );
1144 if (!name || !var)
1145 return WBEM_E_INVALID_PARAMETER;
1147 if ((value = wbem_context_get_value( context, name )))
1149 VariantClear( &value->value );
1150 hr = VariantCopy( &value->value, var );
1152 else
1154 if (!(value = calloc( 1, sizeof(*value) ))) return E_OUTOFMEMORY;
1155 if (!(value->name = heap_strdupW( name )))
1157 free( value );
1158 return E_OUTOFMEMORY;
1160 if (FAILED(hr = VariantCopy( &value->value, var )))
1162 free( value->name );
1163 free( value );
1164 return hr;
1167 list_add_tail( &context->values, &value->entry );
1170 return hr;
1173 static HRESULT WINAPI wbem_context_GetValue(
1174 IWbemContext *iface,
1175 LPCWSTR name,
1176 LONG flags,
1177 VARIANT *var )
1179 struct wbem_context *context = impl_from_IWbemContext( iface );
1180 struct wbem_context_value *value;
1182 TRACE( "%p, %s, %#lx, %p\n", iface, debugstr_w(name), flags, var );
1184 if (!name || !var)
1185 return WBEM_E_INVALID_PARAMETER;
1187 if (!(value = wbem_context_get_value( context, name )))
1188 return WBEM_E_NOT_FOUND;
1190 V_VT(var) = VT_EMPTY;
1191 return VariantCopy( var, &value->value );
1194 static HRESULT WINAPI wbem_context_DeleteValue(
1195 IWbemContext *iface,
1196 LPCWSTR name,
1197 LONG flags )
1199 FIXME( "%p, %s, %#lx\n", iface, debugstr_w(name), flags );
1201 return E_NOTIMPL;
1204 static HRESULT WINAPI wbem_context_DeleteAll(
1205 IWbemContext *iface )
1207 FIXME("%p\n", iface);
1209 return E_NOTIMPL;
1212 static const IWbemContextVtbl wbem_context_vtbl =
1214 wbem_context_QueryInterface,
1215 wbem_context_AddRef,
1216 wbem_context_Release,
1217 wbem_context_Clone,
1218 wbem_context_GetNames,
1219 wbem_context_BeginEnumeration,
1220 wbem_context_Next,
1221 wbem_context_EndEnumeration,
1222 wbem_context_SetValue,
1223 wbem_context_GetValue,
1224 wbem_context_DeleteValue,
1225 wbem_context_DeleteAll,
1228 HRESULT WbemContext_create( void **obj )
1230 struct wbem_context *context;
1232 TRACE("(%p)\n", obj);
1234 if (!(context = malloc( sizeof(*context) ))) return E_OUTOFMEMORY;
1236 context->IWbemContext_iface.lpVtbl = &wbem_context_vtbl;
1237 context->refs = 1;
1238 list_init(&context->values);
1240 *obj = &context->IWbemContext_iface;
1242 TRACE("returning iface %p\n", *obj);
1243 return S_OK;