include/mscvpdb.h: Use flexible array members for the rest of structures.
[wine.git] / dlls / wbemprox / services.c
blob3b55a534de9127c4e038b6d2e048e0117a00bcfd
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->IClientSecurity_iface;
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->IWbemServices_iface;
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 void free_path( struct path *path )
341 if (!path) return;
342 free( path->class );
343 free( path->filter );
344 free( path );
347 HRESULT parse_path( const WCHAR *str, struct path **ret )
349 struct path *path;
350 const WCHAR *p = str, *q;
351 UINT len;
353 if (!(path = calloc( 1, sizeof(*path) ))) return E_OUTOFMEMORY;
355 if (*p == '\\')
357 static const WCHAR cimv2W[] = L"ROOT\\CIMV2";
358 WCHAR server[MAX_COMPUTERNAME_LENGTH+1];
359 DWORD server_len = ARRAY_SIZE(server);
361 p++;
362 if (*p != '\\')
364 free( path );
365 return WBEM_E_INVALID_OBJECT_PATH;
367 p++;
369 q = p;
370 while (*p && *p != '\\') p++;
371 if (!*p)
373 free( path );
374 return WBEM_E_INVALID_OBJECT_PATH;
377 len = p - q;
378 if (!GetComputerNameW( server, &server_len ) || server_len != len || wcsnicmp( q, server, server_len ))
380 free( path );
381 return WBEM_E_NOT_SUPPORTED;
384 q = ++p;
385 while (*p && *p != ':') p++;
386 if (!*p)
388 free( path );
389 return WBEM_E_INVALID_OBJECT_PATH;
392 len = p - q;
393 if (len != ARRAY_SIZE(cimv2W) - 1 || wcsnicmp( q, cimv2W, ARRAY_SIZE(cimv2W) - 1 ))
395 free( path );
396 return WBEM_E_INVALID_NAMESPACE;
398 p++;
401 q = p;
402 while (*p && *p != '.' && *p != '=') p++;
404 len = p - q;
405 if (!(path->class = malloc( (len + 1) * sizeof(WCHAR) )))
407 free( path );
408 return E_OUTOFMEMORY;
410 memcpy( path->class, q, len * sizeof(WCHAR) );
411 path->class[len] = 0;
412 path->class_len = len;
414 if (p[0] == '.' && p[1])
416 q = ++p;
417 while (*q) q++;
419 len = q - p;
420 if (!(path->filter = malloc( (len + 1) * sizeof(WCHAR) )))
422 free_path( path );
423 return E_OUTOFMEMORY;
425 memcpy( path->filter, p, len * sizeof(WCHAR) );
426 path->filter[len] = 0;
427 path->filter_len = len;
429 else if (p[0] == '=' && p[1])
431 WCHAR *key;
432 UINT len_key;
434 while (*q) q++;
435 len = q - p;
437 if (!(key = get_first_key_property( WBEMPROX_NAMESPACE_CIMV2, path->class )))
439 free_path( path );
440 return WBEM_E_INVALID_OBJECT_PATH;
442 len_key = wcslen( key );
444 if (!(path->filter = malloc( (len + len_key + 1) * sizeof(WCHAR) )))
446 free( key );
447 free_path( path );
448 return E_OUTOFMEMORY;
450 wcscpy( path->filter, key );
451 memcpy( path->filter + len_key, p, len * sizeof(WCHAR) );
452 path->filter_len = len + len_key;
453 path->filter[path->filter_len] = 0;
454 free( key );
456 else if (p[0])
458 free_path( path );
459 return WBEM_E_INVALID_OBJECT_PATH;
462 *ret = path;
463 return S_OK;
466 WCHAR *query_from_path( const struct path *path )
468 static const WCHAR selectW[] = L"SELECT * FROM %s WHERE %s";
469 static const WCHAR select_allW[] = L"SELECT * FROM ";
470 WCHAR *query;
471 UINT len;
473 if (path->filter)
475 len = path->class_len + path->filter_len + ARRAY_SIZE(selectW);
476 if (!(query = malloc( len * sizeof(WCHAR) ))) return NULL;
477 swprintf( query, len, selectW, path->class, path->filter );
479 else
481 len = path->class_len + ARRAY_SIZE(select_allW);
482 if (!(query = malloc( len * sizeof(WCHAR) ))) return NULL;
483 lstrcpyW( query, select_allW );
484 lstrcatW( query, path->class );
486 return query;
489 static HRESULT create_instance_enum( enum wbm_namespace ns, const struct path *path, IEnumWbemClassObject **iter )
491 WCHAR *query;
492 HRESULT hr;
494 if (!(query = query_from_path( path ))) return E_OUTOFMEMORY;
495 hr = exec_query( ns, query, iter );
496 free( query );
497 return hr;
500 HRESULT get_object( enum wbm_namespace ns, const WCHAR *object_path, IWbemClassObject **obj )
502 IEnumWbemClassObject *iter;
503 struct path *path;
504 ULONG count;
505 HRESULT hr;
507 hr = parse_path( object_path, &path );
508 if (hr != S_OK) return hr;
510 hr = create_instance_enum( ns, path, &iter );
511 if (hr != S_OK)
513 free_path( path );
514 return hr;
516 hr = IEnumWbemClassObject_Next( iter, WBEM_INFINITE, 1, obj, &count );
517 if (hr == WBEM_S_FALSE)
519 hr = WBEM_E_NOT_FOUND;
520 *obj = NULL;
522 IEnumWbemClassObject_Release( iter );
523 free_path( path );
524 return hr;
527 static HRESULT WINAPI wbem_services_GetObject(
528 IWbemServices *iface,
529 const BSTR strObjectPath,
530 LONG lFlags,
531 IWbemContext *pCtx,
532 IWbemClassObject **ppObject,
533 IWbemCallResult **ppCallResult )
535 struct wbem_services *services = impl_from_IWbemServices( iface );
537 TRACE( "%p, %s, %#lx, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags,
538 pCtx, ppObject, ppCallResult );
540 if (lFlags) FIXME( "unsupported flags %#lx\n", lFlags );
542 if (!strObjectPath || !strObjectPath[0])
543 return create_class_object( services->ns, NULL, NULL, 0, NULL, ppObject );
545 return get_object( services->ns, strObjectPath, ppObject );
548 static HRESULT WINAPI wbem_services_GetObjectAsync(
549 IWbemServices *iface,
550 const BSTR strObjectPath,
551 LONG lFlags,
552 IWbemContext *pCtx,
553 IWbemObjectSink *pResponseHandler )
555 FIXME("\n");
556 return WBEM_E_FAILED;
559 static HRESULT WINAPI wbem_services_PutClass(
560 IWbemServices *iface,
561 IWbemClassObject *pObject,
562 LONG lFlags,
563 IWbemContext *pCtx,
564 IWbemCallResult **ppCallResult )
566 FIXME("\n");
567 return WBEM_E_FAILED;
570 static HRESULT WINAPI wbem_services_PutClassAsync(
571 IWbemServices *iface,
572 IWbemClassObject *pObject,
573 LONG lFlags,
574 IWbemContext *pCtx,
575 IWbemObjectSink *pResponseHandler )
577 FIXME("\n");
578 return WBEM_E_FAILED;
581 static HRESULT WINAPI wbem_services_DeleteClass(
582 IWbemServices *iface,
583 const BSTR strClass,
584 LONG lFlags,
585 IWbemContext *pCtx,
586 IWbemCallResult **ppCallResult )
588 FIXME("\n");
589 return WBEM_E_FAILED;
592 static HRESULT WINAPI wbem_services_DeleteClassAsync(
593 IWbemServices *iface,
594 const BSTR strClass,
595 LONG lFlags,
596 IWbemContext *pCtx,
597 IWbemObjectSink *pResponseHandler )
599 FIXME("\n");
600 return WBEM_E_FAILED;
603 static HRESULT WINAPI wbem_services_CreateClassEnum(
604 IWbemServices *iface,
605 const BSTR strSuperclass,
606 LONG lFlags,
607 IWbemContext *pCtx,
608 IEnumWbemClassObject **ppEnum )
610 FIXME("\n");
611 return WBEM_E_FAILED;
614 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
615 IWbemServices *iface,
616 const BSTR strSuperclass,
617 LONG lFlags,
618 IWbemContext *pCtx,
619 IWbemObjectSink *pResponseHandler )
621 FIXME("\n");
622 return WBEM_E_FAILED;
625 static HRESULT WINAPI wbem_services_PutInstance(
626 IWbemServices *iface,
627 IWbemClassObject *pInst,
628 LONG lFlags,
629 IWbemContext *pCtx,
630 IWbemCallResult **ppCallResult )
632 FIXME("\n");
633 return WBEM_E_FAILED;
636 static HRESULT WINAPI wbem_services_PutInstanceAsync(
637 IWbemServices *iface,
638 IWbemClassObject *pInst,
639 LONG lFlags,
640 IWbemContext *pCtx,
641 IWbemObjectSink *pResponseHandler )
643 FIXME("\n");
644 return WBEM_E_FAILED;
647 static HRESULT WINAPI wbem_services_DeleteInstance(
648 IWbemServices *iface,
649 const BSTR strObjectPath,
650 LONG lFlags,
651 IWbemContext *pCtx,
652 IWbemCallResult **ppCallResult )
654 FIXME("\n");
655 return WBEM_E_FAILED;
658 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
659 IWbemServices *iface,
660 const BSTR strObjectPath,
661 LONG lFlags,
662 IWbemContext *pCtx,
663 IWbemObjectSink *pResponseHandler )
665 FIXME("\n");
666 return WBEM_E_FAILED;
669 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
670 IWbemServices *iface,
671 const BSTR strClass,
672 LONG lFlags,
673 IWbemContext *pCtx,
674 IEnumWbemClassObject **ppEnum )
676 struct wbem_services *services = impl_from_IWbemServices( iface );
677 struct path *path;
678 HRESULT hr;
680 TRACE( "%p, %s, %#lx, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum );
682 if (lFlags) FIXME( "unsupported flags %#lx\n", lFlags );
684 hr = parse_path( strClass, &path );
685 if (hr != S_OK) return hr;
687 hr = create_instance_enum( services->ns, path, ppEnum );
688 free_path( path );
689 return hr;
692 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
693 IWbemServices *iface,
694 const BSTR strFilter,
695 LONG lFlags,
696 IWbemContext *pCtx,
697 IWbemObjectSink *pResponseHandler )
699 FIXME("\n");
700 return WBEM_E_FAILED;
703 static HRESULT WINAPI wbem_services_ExecQuery(
704 IWbemServices *iface,
705 const BSTR strQueryLanguage,
706 const BSTR strQuery,
707 LONG lFlags,
708 IWbemContext *pCtx,
709 IEnumWbemClassObject **ppEnum )
711 struct wbem_services *services = impl_from_IWbemServices( iface );
713 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage),
714 debugstr_w(strQuery), lFlags, pCtx, ppEnum );
716 if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER;
717 if (wcsicmp( strQueryLanguage, L"WQL" )) return WBEM_E_INVALID_QUERY_TYPE;
718 return exec_query( services->ns, strQuery, ppEnum );
721 static void async_exec_query( struct async_header *hdr )
723 struct async_query *query = (struct async_query *)hdr;
724 IEnumWbemClassObject *result;
725 IWbemClassObject *obj;
726 ULONG count;
727 HRESULT hr;
729 hr = exec_query( query->ns, query->str, &result );
730 if (hr == S_OK)
732 for (;;)
734 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
735 if (!count) break;
736 IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj );
737 IWbemClassObject_Release( obj );
739 IEnumWbemClassObject_Release( result );
741 IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL );
742 free( query->str );
745 static HRESULT WINAPI wbem_services_ExecQueryAsync(
746 IWbemServices *iface,
747 const BSTR strQueryLanguage,
748 const BSTR strQuery,
749 LONG lFlags,
750 IWbemContext *pCtx,
751 IWbemObjectSink *pResponseHandler )
753 struct wbem_services *services = impl_from_IWbemServices( iface );
754 IWbemObjectSink *sink;
755 HRESULT hr = E_OUTOFMEMORY;
756 struct async_header *async;
757 struct async_query *query;
759 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
760 lFlags, pCtx, pResponseHandler );
762 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
764 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
765 if (FAILED(hr)) return hr;
767 EnterCriticalSection( &services->cs );
769 if (services->async)
771 FIXME("handle more than one pending async\n");
772 hr = WBEM_E_FAILED;
773 goto done;
775 if (!(query = calloc( 1, sizeof(*query) ))) goto done;
776 query->ns = services->ns;
777 async = (struct async_header *)query;
779 if (!(init_async( async, sink, async_exec_query )))
781 free_async( async );
782 goto done;
784 if (!(query->str = wcsdup( strQuery )))
786 free_async( async );
787 goto done;
789 hr = queue_async( async );
790 if (hr == S_OK) services->async = async;
791 else
793 free( query->str );
794 free_async( async );
797 done:
798 LeaveCriticalSection( &services->cs );
799 IWbemObjectSink_Release( sink );
800 return hr;
803 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
804 IWbemServices *iface,
805 const BSTR strQueryLanguage,
806 const BSTR strQuery,
807 LONG lFlags,
808 IWbemContext *pCtx,
809 IEnumWbemClassObject **ppEnum )
811 FIXME("\n");
812 return WBEM_E_FAILED;
815 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
816 IWbemServices *iface,
817 const BSTR strQueryLanguage,
818 const BSTR strQuery,
819 LONG lFlags,
820 IWbemContext *pCtx,
821 IWbemObjectSink *pResponseHandler )
823 struct wbem_services *services = impl_from_IWbemServices( iface );
824 IWbemObjectSink *sink;
825 HRESULT hr = E_OUTOFMEMORY;
826 struct async_header *async;
827 struct async_query *query;
829 TRACE( "%p, %s, %s, %#lx, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
830 lFlags, pCtx, pResponseHandler );
832 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
834 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
835 if (FAILED(hr)) return hr;
837 EnterCriticalSection( &services->cs );
839 if (services->async)
841 FIXME("handle more than one pending async\n");
842 hr = WBEM_E_FAILED;
843 goto done;
845 if (!(query = calloc( 1, sizeof(*query) ))) goto done;
846 async = (struct async_header *)query;
848 if (!(init_async( async, sink, async_exec_query )))
850 free_async( async );
851 goto done;
853 if (!(query->str = wcsdup( strQuery )))
855 free_async( async );
856 goto done;
858 hr = queue_async( async );
859 if (hr == S_OK) services->async = async;
860 else
862 free( query->str );
863 free_async( async );
866 done:
867 LeaveCriticalSection( &services->cs );
868 IWbemObjectSink_Release( sink );
869 return hr;
872 static HRESULT WINAPI wbem_services_ExecMethod(
873 IWbemServices *iface,
874 const BSTR strObjectPath,
875 const BSTR strMethodName,
876 LONG lFlags,
877 IWbemContext *context,
878 IWbemClassObject *pInParams,
879 IWbemClassObject **ppOutParams,
880 IWbemCallResult **ppCallResult )
882 struct wbem_services *services = impl_from_IWbemServices( iface );
883 IEnumWbemClassObject *result = NULL;
884 IWbemClassObject *obj = NULL;
885 struct query *query = NULL;
886 struct path *path;
887 WCHAR *str;
888 class_method *func;
889 struct table *table;
890 HRESULT hr;
892 TRACE( "%p, %s, %s, %#lx, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
893 debugstr_w(strMethodName), lFlags, context, pInParams, ppOutParams, ppCallResult );
895 if (lFlags) FIXME( "flags %#lx not supported\n", lFlags );
897 if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr;
898 if (!(str = query_from_path( path )))
900 hr = E_OUTOFMEMORY;
901 goto done;
903 if (!(query = create_query( services->ns )))
905 hr = E_OUTOFMEMORY;
906 goto done;
908 hr = parse_query( services->ns, str, &query->view, &query->mem );
909 if (hr != S_OK) goto done;
911 hr = execute_view( query->view );
912 if (hr != S_OK) goto done;
914 hr = EnumWbemClassObject_create( query, (void **)&result );
915 if (hr != S_OK) goto done;
917 table = get_view_table( query->view, 0 );
918 hr = create_class_object( services->ns, table->name, result, 0, NULL, &obj );
919 if (hr != S_OK) goto done;
921 hr = get_method( table, strMethodName, &func );
922 if (hr != S_OK) goto done;
924 hr = func( obj, context ? context : services->context, pInParams, ppOutParams );
926 done:
927 if (result) IEnumWbemClassObject_Release( result );
928 if (obj) IWbemClassObject_Release( obj );
929 free_query( query );
930 free_path( path );
931 free( str );
932 return hr;
935 static HRESULT WINAPI wbem_services_ExecMethodAsync(
936 IWbemServices *iface,
937 const BSTR strObjectPath,
938 const BSTR strMethodName,
939 LONG lFlags,
940 IWbemContext *pCtx,
941 IWbemClassObject *pInParams,
942 IWbemObjectSink *pResponseHandler )
944 FIXME("\n");
945 return WBEM_E_FAILED;
948 static const IWbemServicesVtbl wbem_services_vtbl =
950 wbem_services_QueryInterface,
951 wbem_services_AddRef,
952 wbem_services_Release,
953 wbem_services_OpenNamespace,
954 wbem_services_CancelAsyncCall,
955 wbem_services_QueryObjectSink,
956 wbem_services_GetObject,
957 wbem_services_GetObjectAsync,
958 wbem_services_PutClass,
959 wbem_services_PutClassAsync,
960 wbem_services_DeleteClass,
961 wbem_services_DeleteClassAsync,
962 wbem_services_CreateClassEnum,
963 wbem_services_CreateClassEnumAsync,
964 wbem_services_PutInstance,
965 wbem_services_PutInstanceAsync,
966 wbem_services_DeleteInstance,
967 wbem_services_DeleteInstanceAsync,
968 wbem_services_CreateInstanceEnum,
969 wbem_services_CreateInstanceEnumAsync,
970 wbem_services_ExecQuery,
971 wbem_services_ExecQueryAsync,
972 wbem_services_ExecNotificationQuery,
973 wbem_services_ExecNotificationQueryAsync,
974 wbem_services_ExecMethod,
975 wbem_services_ExecMethodAsync
978 HRESULT WbemServices_create( const WCHAR *namespace, IWbemContext *context, LPVOID *ppObj )
980 struct wbem_services *ws;
981 enum wbm_namespace ns;
983 TRACE("namespace %s, context %p, ppObj %p.\n", debugstr_w(namespace), context, ppObj);
985 if (!namespace)
986 ns = WBEMPROX_NAMESPACE_LAST;
987 else if ((ns = get_namespace_from_string( namespace )) == WBEMPROX_NAMESPACE_LAST)
988 return WBEM_E_INVALID_NAMESPACE;
990 if (!(ws = calloc( 1, sizeof(*ws) ))) return E_OUTOFMEMORY;
992 ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
993 ws->refs = 1;
994 ws->ns = ns;
995 InitializeCriticalSectionEx( &ws->cs, 0, RTL_CRITICAL_SECTION_FLAG_FORCE_DEBUG_INFO );
996 ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs");
997 if (context)
998 IWbemContext_Clone( context, &ws->context );
1000 *ppObj = &ws->IWbemServices_iface;
1002 TRACE("returning iface %p\n", *ppObj);
1003 return S_OK;
1006 struct wbem_context_value
1008 struct list entry;
1009 WCHAR *name;
1010 VARIANT value;
1013 struct wbem_context
1015 IWbemContext IWbemContext_iface;
1016 LONG refs;
1017 struct list values;
1020 static void wbem_context_delete_values(struct wbem_context *context)
1022 struct wbem_context_value *value, *next;
1024 LIST_FOR_EACH_ENTRY_SAFE(value, next, &context->values, struct wbem_context_value, entry)
1026 list_remove( &value->entry );
1027 VariantClear( &value->value );
1028 free( value->name );
1029 free( value );
1033 static struct wbem_context *impl_from_IWbemContext( IWbemContext *iface )
1035 return CONTAINING_RECORD( iface, struct wbem_context, IWbemContext_iface );
1038 static HRESULT WINAPI wbem_context_QueryInterface(
1039 IWbemContext *iface,
1040 REFIID riid,
1041 void **obj)
1043 TRACE("%p, %s, %p\n", iface, debugstr_guid( riid ), obj );
1045 if ( IsEqualGUID( riid, &IID_IWbemContext ) ||
1046 IsEqualGUID( riid, &IID_IUnknown ) )
1048 *obj = iface;
1050 else
1052 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1053 return E_NOINTERFACE;
1056 IWbemContext_AddRef( iface );
1057 return S_OK;
1060 static ULONG WINAPI wbem_context_AddRef(
1061 IWbemContext *iface )
1063 struct wbem_context *context = impl_from_IWbemContext( iface );
1064 return InterlockedIncrement( &context->refs );
1067 static ULONG WINAPI wbem_context_Release(
1068 IWbemContext *iface )
1070 struct wbem_context *context = impl_from_IWbemContext( iface );
1071 LONG refs = InterlockedDecrement( &context->refs );
1073 if (!refs)
1075 TRACE("destroying %p\n", context);
1076 wbem_context_delete_values( context );
1077 free( context );
1079 return refs;
1082 static HRESULT WINAPI wbem_context_Clone(
1083 IWbemContext *iface,
1084 IWbemContext **newcopy )
1086 struct wbem_context *context = impl_from_IWbemContext( iface );
1087 struct wbem_context_value *value;
1088 IWbemContext *cloned_context;
1089 HRESULT hr;
1091 TRACE("%p, %p\n", iface, newcopy);
1093 if (SUCCEEDED(hr = WbemContext_create( (void **)&cloned_context, &IID_IWbemContext )))
1095 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1097 if (FAILED(hr = IWbemContext_SetValue( cloned_context, value->name, 0, &value->value ))) break;
1101 if (SUCCEEDED(hr))
1103 *newcopy = cloned_context;
1105 else
1107 *newcopy = NULL;
1108 IWbemContext_Release( cloned_context );
1111 return hr;
1114 static HRESULT WINAPI wbem_context_GetNames(
1115 IWbemContext *iface,
1116 LONG flags,
1117 SAFEARRAY **names )
1119 FIXME( "%p, %#lx, %p\n", iface, flags, names );
1121 return E_NOTIMPL;
1124 static HRESULT WINAPI wbem_context_BeginEnumeration(
1125 IWbemContext *iface,
1126 LONG flags )
1128 FIXME( "%p, %#lx\n", iface, flags );
1130 return E_NOTIMPL;
1133 static HRESULT WINAPI wbem_context_Next(
1134 IWbemContext *iface,
1135 LONG flags,
1136 BSTR *name,
1137 VARIANT *value )
1139 FIXME( "%p, %#lx, %p, %p\n", iface, flags, name, value );
1141 return E_NOTIMPL;
1144 static HRESULT WINAPI wbem_context_EndEnumeration(
1145 IWbemContext *iface )
1147 FIXME("%p\n", iface);
1149 return E_NOTIMPL;
1152 static struct wbem_context_value *wbem_context_get_value( struct wbem_context *context, const WCHAR *name )
1154 struct wbem_context_value *value;
1156 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1158 if (!lstrcmpiW( value->name, name )) return value;
1161 return NULL;
1164 static HRESULT WINAPI wbem_context_SetValue(
1165 IWbemContext *iface,
1166 LPCWSTR name,
1167 LONG flags,
1168 VARIANT *var )
1170 struct wbem_context *context = impl_from_IWbemContext( iface );
1171 struct wbem_context_value *value;
1172 HRESULT hr;
1174 TRACE( "%p, %s, %#lx, %s\n", iface, debugstr_w(name), flags, debugstr_variant(var) );
1176 if (!name || !var)
1177 return WBEM_E_INVALID_PARAMETER;
1179 if ((value = wbem_context_get_value( context, name )))
1181 VariantClear( &value->value );
1182 hr = VariantCopy( &value->value, var );
1184 else
1186 if (!(value = calloc( 1, sizeof(*value) ))) return E_OUTOFMEMORY;
1187 if (!(value->name = wcsdup( name )))
1189 free( value );
1190 return E_OUTOFMEMORY;
1192 if (FAILED(hr = VariantCopy( &value->value, var )))
1194 free( value->name );
1195 free( value );
1196 return hr;
1199 list_add_tail( &context->values, &value->entry );
1202 return hr;
1205 static HRESULT WINAPI wbem_context_GetValue(
1206 IWbemContext *iface,
1207 LPCWSTR name,
1208 LONG flags,
1209 VARIANT *var )
1211 struct wbem_context *context = impl_from_IWbemContext( iface );
1212 struct wbem_context_value *value;
1214 TRACE( "%p, %s, %#lx, %p\n", iface, debugstr_w(name), flags, var );
1216 if (!name || !var)
1217 return WBEM_E_INVALID_PARAMETER;
1219 if (!(value = wbem_context_get_value( context, name )))
1220 return WBEM_E_NOT_FOUND;
1222 V_VT(var) = VT_EMPTY;
1223 return VariantCopy( var, &value->value );
1226 static HRESULT WINAPI wbem_context_DeleteValue(
1227 IWbemContext *iface,
1228 LPCWSTR name,
1229 LONG flags )
1231 FIXME( "%p, %s, %#lx\n", iface, debugstr_w(name), flags );
1233 return E_NOTIMPL;
1236 static HRESULT WINAPI wbem_context_DeleteAll(
1237 IWbemContext *iface )
1239 FIXME("%p\n", iface);
1241 return E_NOTIMPL;
1244 static const IWbemContextVtbl wbem_context_vtbl =
1246 wbem_context_QueryInterface,
1247 wbem_context_AddRef,
1248 wbem_context_Release,
1249 wbem_context_Clone,
1250 wbem_context_GetNames,
1251 wbem_context_BeginEnumeration,
1252 wbem_context_Next,
1253 wbem_context_EndEnumeration,
1254 wbem_context_SetValue,
1255 wbem_context_GetValue,
1256 wbem_context_DeleteValue,
1257 wbem_context_DeleteAll,
1260 HRESULT WbemContext_create( void **obj, REFIID riid )
1262 struct wbem_context *context;
1264 TRACE("(%p)\n", obj);
1266 if ( !IsEqualGUID( riid, &IID_IWbemContext ) &&
1267 !IsEqualGUID( riid, &IID_IUnknown ) )
1268 return E_NOINTERFACE;
1270 if (!(context = malloc( sizeof(*context) ))) return E_OUTOFMEMORY;
1272 context->IWbemContext_iface.lpVtbl = &wbem_context_vtbl;
1273 context->refs = 1;
1274 list_init(&context->values);
1276 *obj = &context->IWbemContext_iface;
1278 TRACE("returning iface %p\n", *obj);
1279 return S_OK;