widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / wbemprox / services.c
blobfaed31b79afab17eeaf64c05ed0c5496f59b3237
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, %u, %u, %s, %u, %u, %p, 0x%08x\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 WCHAR *str;
165 static void free_async( struct async_header *async )
167 if (async->sink) IWbemObjectSink_Release( async->sink );
168 CloseHandle( async->cancel );
169 CloseHandle( async->wait );
170 heap_free( async );
173 static BOOL init_async( struct async_header *async, IWbemObjectSink *sink,
174 void (*proc)(struct async_header *) )
176 if (!(async->wait = CreateEventW( NULL, FALSE, FALSE, NULL ))) return FALSE;
177 if (!(async->cancel = CreateEventW( NULL, FALSE, FALSE, NULL )))
179 CloseHandle( async->wait );
180 return FALSE;
182 async->proc = proc;
183 async->sink = sink;
184 IWbemObjectSink_AddRef( sink );
185 return TRUE;
188 static DWORD CALLBACK async_proc( LPVOID param )
190 struct async_header *async = param;
191 HANDLE wait = async->wait;
193 async->proc( async );
195 WaitForSingleObject( async->cancel, INFINITE );
196 SetEvent( wait );
197 return ERROR_SUCCESS;
200 static HRESULT queue_async( struct async_header *async )
202 if (QueueUserWorkItem( async_proc, async, WT_EXECUTELONGFUNCTION )) return S_OK;
203 return HRESULT_FROM_WIN32( GetLastError() );
206 struct wbem_services
208 IWbemServices IWbemServices_iface;
209 LONG refs;
210 CRITICAL_SECTION cs;
211 WCHAR *namespace;
212 struct async_header *async;
213 IWbemContext *context;
216 static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface )
218 return CONTAINING_RECORD( iface, struct wbem_services, IWbemServices_iface );
221 static ULONG WINAPI wbem_services_AddRef(
222 IWbemServices *iface )
224 struct wbem_services *ws = impl_from_IWbemServices( iface );
225 return InterlockedIncrement( &ws->refs );
228 static ULONG WINAPI wbem_services_Release(
229 IWbemServices *iface )
231 struct wbem_services *ws = impl_from_IWbemServices( iface );
232 LONG refs = InterlockedDecrement( &ws->refs );
233 if (!refs)
235 TRACE("destroying %p\n", ws);
237 EnterCriticalSection( &ws->cs );
238 if (ws->async) SetEvent( ws->async->cancel );
239 LeaveCriticalSection( &ws->cs );
240 if (ws->async)
242 WaitForSingleObject( ws->async->wait, INFINITE );
243 free_async( ws->async );
245 ws->cs.DebugInfo->Spare[0] = 0;
246 DeleteCriticalSection( &ws->cs );
247 if (ws->context)
248 IWbemContext_Release( ws->context );
249 heap_free( ws->namespace );
250 heap_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, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strNamespace), lFlags,
294 pCtx, ppWorkingNamespace, ppResult);
296 if ((wcsicmp( strNamespace, L"cimv2" ) && wcsicmp( strNamespace, L"default" )) || ws->namespace)
297 return WBEM_E_INVALID_NAMESPACE;
299 return WbemServices_create( L"cimv2", 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 = heap_alloc_zero( 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 heap_free( path );
357 return WBEM_E_INVALID_OBJECT_PATH;
359 p++;
361 q = p;
362 while (*p && *p != '\\') p++;
363 if (!*p)
365 heap_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 heap_free( path );
373 return WBEM_E_NOT_SUPPORTED;
376 q = ++p;
377 while (*p && *p != ':') p++;
378 if (!*p)
380 heap_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 heap_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 = heap_alloc( (len + 1) * sizeof(WCHAR) )))
399 heap_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 = heap_alloc( (len + 1) * sizeof(WCHAR) )))
414 heap_free( path->class );
415 heap_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 heap_free( path->class );
430 heap_free( path->filter );
431 heap_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 = heap_alloc( 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 = heap_alloc( len * sizeof(WCHAR) ))) return NULL;
451 lstrcpyW( query, select_allW );
452 lstrcatW( query, path->class );
454 return query;
457 static HRESULT create_instance_enum( 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( query, iter );
464 heap_free( query );
465 return hr;
468 HRESULT get_object( 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( 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 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags,
504 pCtx, ppObject, ppCallResult);
506 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
508 if (!strObjectPath || !strObjectPath[0])
509 return create_class_object( NULL, NULL, 0, NULL, ppObject );
511 return get_object( strObjectPath, ppObject );
514 static HRESULT WINAPI wbem_services_GetObjectAsync(
515 IWbemServices *iface,
516 const BSTR strObjectPath,
517 LONG lFlags,
518 IWbemContext *pCtx,
519 IWbemObjectSink *pResponseHandler )
521 FIXME("\n");
522 return WBEM_E_FAILED;
525 static HRESULT WINAPI wbem_services_PutClass(
526 IWbemServices *iface,
527 IWbemClassObject *pObject,
528 LONG lFlags,
529 IWbemContext *pCtx,
530 IWbemCallResult **ppCallResult )
532 FIXME("\n");
533 return WBEM_E_FAILED;
536 static HRESULT WINAPI wbem_services_PutClassAsync(
537 IWbemServices *iface,
538 IWbemClassObject *pObject,
539 LONG lFlags,
540 IWbemContext *pCtx,
541 IWbemObjectSink *pResponseHandler )
543 FIXME("\n");
544 return WBEM_E_FAILED;
547 static HRESULT WINAPI wbem_services_DeleteClass(
548 IWbemServices *iface,
549 const BSTR strClass,
550 LONG lFlags,
551 IWbemContext *pCtx,
552 IWbemCallResult **ppCallResult )
554 FIXME("\n");
555 return WBEM_E_FAILED;
558 static HRESULT WINAPI wbem_services_DeleteClassAsync(
559 IWbemServices *iface,
560 const BSTR strClass,
561 LONG lFlags,
562 IWbemContext *pCtx,
563 IWbemObjectSink *pResponseHandler )
565 FIXME("\n");
566 return WBEM_E_FAILED;
569 static HRESULT WINAPI wbem_services_CreateClassEnum(
570 IWbemServices *iface,
571 const BSTR strSuperclass,
572 LONG lFlags,
573 IWbemContext *pCtx,
574 IEnumWbemClassObject **ppEnum )
576 FIXME("\n");
577 return WBEM_E_FAILED;
580 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
581 IWbemServices *iface,
582 const BSTR strSuperclass,
583 LONG lFlags,
584 IWbemContext *pCtx,
585 IWbemObjectSink *pResponseHandler )
587 FIXME("\n");
588 return WBEM_E_FAILED;
591 static HRESULT WINAPI wbem_services_PutInstance(
592 IWbemServices *iface,
593 IWbemClassObject *pInst,
594 LONG lFlags,
595 IWbemContext *pCtx,
596 IWbemCallResult **ppCallResult )
598 FIXME("\n");
599 return WBEM_E_FAILED;
602 static HRESULT WINAPI wbem_services_PutInstanceAsync(
603 IWbemServices *iface,
604 IWbemClassObject *pInst,
605 LONG lFlags,
606 IWbemContext *pCtx,
607 IWbemObjectSink *pResponseHandler )
609 FIXME("\n");
610 return WBEM_E_FAILED;
613 static HRESULT WINAPI wbem_services_DeleteInstance(
614 IWbemServices *iface,
615 const BSTR strObjectPath,
616 LONG lFlags,
617 IWbemContext *pCtx,
618 IWbemCallResult **ppCallResult )
620 FIXME("\n");
621 return WBEM_E_FAILED;
624 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
625 IWbemServices *iface,
626 const BSTR strObjectPath,
627 LONG lFlags,
628 IWbemContext *pCtx,
629 IWbemObjectSink *pResponseHandler )
631 FIXME("\n");
632 return WBEM_E_FAILED;
635 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
636 IWbemServices *iface,
637 const BSTR strClass,
638 LONG lFlags,
639 IWbemContext *pCtx,
640 IEnumWbemClassObject **ppEnum )
642 struct path *path;
643 HRESULT hr;
645 TRACE("%p, %s, 0%08x, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum);
647 if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
649 hr = parse_path( strClass, &path );
650 if (hr != S_OK) return hr;
652 hr = create_instance_enum( path, ppEnum );
653 free_path( path );
654 return hr;
657 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
658 IWbemServices *iface,
659 const BSTR strFilter,
660 LONG lFlags,
661 IWbemContext *pCtx,
662 IWbemObjectSink *pResponseHandler )
664 FIXME("\n");
665 return WBEM_E_FAILED;
668 static HRESULT WINAPI wbem_services_ExecQuery(
669 IWbemServices *iface,
670 const BSTR strQueryLanguage,
671 const BSTR strQuery,
672 LONG lFlags,
673 IWbemContext *pCtx,
674 IEnumWbemClassObject **ppEnum )
676 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
677 debugstr_w(strQuery), lFlags, pCtx, ppEnum);
679 if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER;
680 if (wcsicmp( strQueryLanguage, L"WQL" )) return WBEM_E_INVALID_QUERY_TYPE;
681 return exec_query( strQuery, ppEnum );
684 static void async_exec_query( struct async_header *hdr )
686 struct async_query *query = (struct async_query *)hdr;
687 IEnumWbemClassObject *result;
688 IWbemClassObject *obj;
689 ULONG count;
690 HRESULT hr;
692 hr = exec_query( query->str, &result );
693 if (hr == S_OK)
695 for (;;)
697 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
698 if (!count) break;
699 IWbemObjectSink_Indicate( query->hdr.sink, 1, &obj );
700 IWbemClassObject_Release( obj );
702 IEnumWbemClassObject_Release( result );
704 IWbemObjectSink_SetStatus( query->hdr.sink, WBEM_STATUS_COMPLETE, hr, NULL, NULL );
705 heap_free( query->str );
708 static HRESULT WINAPI wbem_services_ExecQueryAsync(
709 IWbemServices *iface,
710 const BSTR strQueryLanguage,
711 const BSTR strQuery,
712 LONG lFlags,
713 IWbemContext *pCtx,
714 IWbemObjectSink *pResponseHandler )
716 struct wbem_services *services = impl_from_IWbemServices( iface );
717 IWbemObjectSink *sink;
718 HRESULT hr = E_OUTOFMEMORY;
719 struct async_header *async;
720 struct async_query *query;
722 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
723 lFlags, pCtx, pResponseHandler);
725 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
727 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
728 if (FAILED(hr)) return hr;
730 EnterCriticalSection( &services->cs );
732 if (services->async)
734 FIXME("handle more than one pending async\n");
735 hr = WBEM_E_FAILED;
736 goto done;
738 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
739 async = (struct async_header *)query;
741 if (!(init_async( async, sink, async_exec_query )))
743 free_async( async );
744 goto done;
746 if (!(query->str = heap_strdupW( strQuery )))
748 free_async( async );
749 goto done;
751 hr = queue_async( async );
752 if (hr == S_OK) services->async = async;
753 else
755 heap_free( query->str );
756 free_async( async );
759 done:
760 LeaveCriticalSection( &services->cs );
761 IWbemObjectSink_Release( sink );
762 return hr;
765 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
766 IWbemServices *iface,
767 const BSTR strQueryLanguage,
768 const BSTR strQuery,
769 LONG lFlags,
770 IWbemContext *pCtx,
771 IEnumWbemClassObject **ppEnum )
773 FIXME("\n");
774 return WBEM_E_FAILED;
777 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
778 IWbemServices *iface,
779 const BSTR strQueryLanguage,
780 const BSTR strQuery,
781 LONG lFlags,
782 IWbemContext *pCtx,
783 IWbemObjectSink *pResponseHandler )
785 struct wbem_services *services = impl_from_IWbemServices( iface );
786 IWbemObjectSink *sink;
787 HRESULT hr = E_OUTOFMEMORY;
788 struct async_header *async;
789 struct async_query *query;
791 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage), debugstr_w(strQuery),
792 lFlags, pCtx, pResponseHandler);
794 if (!pResponseHandler) return WBEM_E_INVALID_PARAMETER;
796 hr = IWbemObjectSink_QueryInterface( pResponseHandler, &IID_IWbemObjectSink, (void **)&sink );
797 if (FAILED(hr)) return hr;
799 EnterCriticalSection( &services->cs );
801 if (services->async)
803 FIXME("handle more than one pending async\n");
804 hr = WBEM_E_FAILED;
805 goto done;
807 if (!(query = heap_alloc_zero( sizeof(*query) ))) goto done;
808 async = (struct async_header *)query;
810 if (!(init_async( async, sink, async_exec_query )))
812 free_async( async );
813 goto done;
815 if (!(query->str = heap_strdupW( strQuery )))
817 free_async( async );
818 goto done;
820 hr = queue_async( async );
821 if (hr == S_OK) services->async = async;
822 else
824 heap_free( query->str );
825 free_async( async );
828 done:
829 LeaveCriticalSection( &services->cs );
830 IWbemObjectSink_Release( sink );
831 return hr;
834 static HRESULT WINAPI wbem_services_ExecMethod(
835 IWbemServices *iface,
836 const BSTR strObjectPath,
837 const BSTR strMethodName,
838 LONG lFlags,
839 IWbemContext *context,
840 IWbemClassObject *pInParams,
841 IWbemClassObject **ppOutParams,
842 IWbemCallResult **ppCallResult )
844 struct wbem_services *services = impl_from_IWbemServices( iface );
845 IEnumWbemClassObject *result = NULL;
846 IWbemClassObject *obj = NULL;
847 struct query *query = NULL;
848 struct path *path;
849 WCHAR *str;
850 class_method *func;
851 struct table *table;
852 HRESULT hr;
854 TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
855 debugstr_w(strMethodName), lFlags, context, pInParams, ppOutParams, ppCallResult);
857 if (lFlags) FIXME("flags %08x not supported\n", lFlags);
859 if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr;
860 if (!(str = query_from_path( path )))
862 hr = E_OUTOFMEMORY;
863 goto done;
865 if (!(query = create_query()))
867 hr = E_OUTOFMEMORY;
868 goto done;
870 hr = parse_query( str, &query->view, &query->mem );
871 if (hr != S_OK) goto done;
873 hr = execute_view( query->view );
874 if (hr != S_OK) goto done;
876 hr = EnumWbemClassObject_create( query, (void **)&result );
877 if (hr != S_OK) goto done;
879 table = get_view_table( query->view, 0 );
880 hr = create_class_object( table->name, result, 0, NULL, &obj );
881 if (hr != S_OK) goto done;
883 hr = get_method( table, strMethodName, &func );
884 if (hr != S_OK) goto done;
886 hr = func( obj, context ? context : services->context, pInParams, ppOutParams );
888 done:
889 if (result) IEnumWbemClassObject_Release( result );
890 if (obj) IWbemClassObject_Release( obj );
891 free_query( query );
892 free_path( path );
893 heap_free( str );
894 return hr;
897 static HRESULT WINAPI wbem_services_ExecMethodAsync(
898 IWbemServices *iface,
899 const BSTR strObjectPath,
900 const BSTR strMethodName,
901 LONG lFlags,
902 IWbemContext *pCtx,
903 IWbemClassObject *pInParams,
904 IWbemObjectSink *pResponseHandler )
906 FIXME("\n");
907 return WBEM_E_FAILED;
910 static const IWbemServicesVtbl wbem_services_vtbl =
912 wbem_services_QueryInterface,
913 wbem_services_AddRef,
914 wbem_services_Release,
915 wbem_services_OpenNamespace,
916 wbem_services_CancelAsyncCall,
917 wbem_services_QueryObjectSink,
918 wbem_services_GetObject,
919 wbem_services_GetObjectAsync,
920 wbem_services_PutClass,
921 wbem_services_PutClassAsync,
922 wbem_services_DeleteClass,
923 wbem_services_DeleteClassAsync,
924 wbem_services_CreateClassEnum,
925 wbem_services_CreateClassEnumAsync,
926 wbem_services_PutInstance,
927 wbem_services_PutInstanceAsync,
928 wbem_services_DeleteInstance,
929 wbem_services_DeleteInstanceAsync,
930 wbem_services_CreateInstanceEnum,
931 wbem_services_CreateInstanceEnumAsync,
932 wbem_services_ExecQuery,
933 wbem_services_ExecQueryAsync,
934 wbem_services_ExecNotificationQuery,
935 wbem_services_ExecNotificationQueryAsync,
936 wbem_services_ExecMethod,
937 wbem_services_ExecMethodAsync
940 HRESULT WbemServices_create( const WCHAR *namespace, IWbemContext *context, LPVOID *ppObj )
942 struct wbem_services *ws;
944 TRACE("(%p)\n", ppObj);
946 ws = heap_alloc_zero( sizeof(*ws) );
947 if (!ws) return E_OUTOFMEMORY;
949 ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
950 ws->refs = 1;
951 ws->namespace = heap_strdupW( namespace );
952 InitializeCriticalSection( &ws->cs );
953 ws->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": wbemprox_services.cs");
954 if (context)
955 IWbemContext_Clone( context, &ws->context );
957 *ppObj = &ws->IWbemServices_iface;
959 TRACE("returning iface %p\n", *ppObj);
960 return S_OK;
963 struct wbem_context_value
965 struct list entry;
966 WCHAR *name;
967 VARIANT value;
970 struct wbem_context
972 IWbemContext IWbemContext_iface;
973 LONG refs;
974 struct list values;
977 static void wbem_context_delete_values(struct wbem_context *context)
979 struct wbem_context_value *value, *next;
981 LIST_FOR_EACH_ENTRY_SAFE(value, next, &context->values, struct wbem_context_value, entry)
983 list_remove( &value->entry );
984 VariantClear( &value->value );
985 heap_free( value->name );
986 heap_free( value );
990 static struct wbem_context *impl_from_IWbemContext( IWbemContext *iface )
992 return CONTAINING_RECORD( iface, struct wbem_context, IWbemContext_iface );
995 static HRESULT WINAPI wbem_context_QueryInterface(
996 IWbemContext *iface,
997 REFIID riid,
998 void **obj)
1000 TRACE("%p, %s, %p\n", iface, debugstr_guid( riid ), obj );
1002 if ( IsEqualGUID( riid, &IID_IWbemContext ) ||
1003 IsEqualGUID( riid, &IID_IUnknown ) )
1005 *obj = iface;
1007 else
1009 FIXME("interface %s not implemented\n", debugstr_guid(riid));
1010 return E_NOINTERFACE;
1013 IWbemContext_AddRef( iface );
1014 return S_OK;
1017 static ULONG WINAPI wbem_context_AddRef(
1018 IWbemContext *iface )
1020 struct wbem_context *context = impl_from_IWbemContext( iface );
1021 return InterlockedIncrement( &context->refs );
1024 static ULONG WINAPI wbem_context_Release(
1025 IWbemContext *iface )
1027 struct wbem_context *context = impl_from_IWbemContext( iface );
1028 LONG refs = InterlockedDecrement( &context->refs );
1030 if (!refs)
1032 TRACE("destroying %p\n", context);
1033 wbem_context_delete_values( context );
1034 heap_free( context );
1036 return refs;
1039 static HRESULT WINAPI wbem_context_Clone(
1040 IWbemContext *iface,
1041 IWbemContext **newcopy )
1043 struct wbem_context *context = impl_from_IWbemContext( iface );
1044 struct wbem_context_value *value;
1045 IWbemContext *cloned_context;
1046 HRESULT hr;
1048 TRACE("%p, %p\n", iface, newcopy);
1050 if (SUCCEEDED(hr = WbemContext_create( (void **)&cloned_context )))
1052 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1054 if (FAILED(hr = IWbemContext_SetValue( cloned_context, value->name, 0, &value->value ))) break;
1058 if (SUCCEEDED(hr))
1060 *newcopy = cloned_context;
1062 else
1064 *newcopy = NULL;
1065 IWbemContext_Release( cloned_context );
1068 return hr;
1071 static HRESULT WINAPI wbem_context_GetNames(
1072 IWbemContext *iface,
1073 LONG flags,
1074 SAFEARRAY **names )
1076 FIXME("%p, %#x, %p\n", iface, flags, names);
1078 return E_NOTIMPL;
1081 static HRESULT WINAPI wbem_context_BeginEnumeration(
1082 IWbemContext *iface,
1083 LONG flags )
1085 FIXME("%p, %#x\n", iface, flags);
1087 return E_NOTIMPL;
1090 static HRESULT WINAPI wbem_context_Next(
1091 IWbemContext *iface,
1092 LONG flags,
1093 BSTR *name,
1094 VARIANT *value )
1096 FIXME("%p, %#x, %p, %p\n", iface, flags, name, value);
1098 return E_NOTIMPL;
1101 static HRESULT WINAPI wbem_context_EndEnumeration(
1102 IWbemContext *iface )
1104 FIXME("%p\n", iface);
1106 return E_NOTIMPL;
1109 static struct wbem_context_value *wbem_context_get_value( struct wbem_context *context, const WCHAR *name )
1111 struct wbem_context_value *value;
1113 LIST_FOR_EACH_ENTRY( value, &context->values, struct wbem_context_value, entry )
1115 if (!lstrcmpiW( value->name, name )) return value;
1118 return NULL;
1121 static HRESULT WINAPI wbem_context_SetValue(
1122 IWbemContext *iface,
1123 LPCWSTR name,
1124 LONG flags,
1125 VARIANT *var )
1127 struct wbem_context *context = impl_from_IWbemContext( iface );
1128 struct wbem_context_value *value;
1129 HRESULT hr;
1131 TRACE("%p, %s, %#x, %s\n", iface, debugstr_w(name), flags, debugstr_variant(var));
1133 if (!name || !var)
1134 return WBEM_E_INVALID_PARAMETER;
1136 if ((value = wbem_context_get_value( context, name )))
1138 VariantClear( &value->value );
1139 hr = VariantCopy( &value->value, var );
1141 else
1143 if (!(value = heap_alloc_zero( sizeof(*value) ))) return E_OUTOFMEMORY;
1144 if (!(value->name = heap_strdupW( name )))
1146 heap_free( value );
1147 return E_OUTOFMEMORY;
1149 if (FAILED(hr = VariantCopy( &value->value, var )))
1151 heap_free( value->name );
1152 heap_free( value );
1153 return hr;
1156 list_add_tail( &context->values, &value->entry );
1159 return hr;
1162 static HRESULT WINAPI wbem_context_GetValue(
1163 IWbemContext *iface,
1164 LPCWSTR name,
1165 LONG flags,
1166 VARIANT *var )
1168 struct wbem_context *context = impl_from_IWbemContext( iface );
1169 struct wbem_context_value *value;
1171 TRACE("%p, %s, %#x, %p\n", iface, debugstr_w(name), flags, var);
1173 if (!name || !var)
1174 return WBEM_E_INVALID_PARAMETER;
1176 if (!(value = wbem_context_get_value( context, name )))
1177 return WBEM_E_NOT_FOUND;
1179 V_VT(var) = VT_EMPTY;
1180 return VariantCopy( var, &value->value );
1183 static HRESULT WINAPI wbem_context_DeleteValue(
1184 IWbemContext *iface,
1185 LPCWSTR name,
1186 LONG flags )
1188 FIXME("%p, %s, %#x\n", iface, debugstr_w(name), flags);
1190 return E_NOTIMPL;
1193 static HRESULT WINAPI wbem_context_DeleteAll(
1194 IWbemContext *iface )
1196 FIXME("%p\n", iface);
1198 return E_NOTIMPL;
1201 static const IWbemContextVtbl wbem_context_vtbl =
1203 wbem_context_QueryInterface,
1204 wbem_context_AddRef,
1205 wbem_context_Release,
1206 wbem_context_Clone,
1207 wbem_context_GetNames,
1208 wbem_context_BeginEnumeration,
1209 wbem_context_Next,
1210 wbem_context_EndEnumeration,
1211 wbem_context_SetValue,
1212 wbem_context_GetValue,
1213 wbem_context_DeleteValue,
1214 wbem_context_DeleteAll,
1217 HRESULT WbemContext_create( void **obj )
1219 struct wbem_context *context;
1221 TRACE("(%p)\n", obj);
1223 context = heap_alloc( sizeof(*context) );
1224 if (!context) return E_OUTOFMEMORY;
1226 context->IWbemContext_iface.lpVtbl = &wbem_context_vtbl;
1227 context->refs = 1;
1228 list_init(&context->values);
1230 *obj = &context->IWbemContext_iface;
1232 TRACE("returning iface %p\n", *obj);
1233 return S_OK;