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
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31 #include "wbemprox_private.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox
);
35 struct client_security
37 IClientSecurity IClientSecurity_iface
;
40 static inline struct client_security
*impl_from_IClientSecurity( IClientSecurity
*iface
)
42 return CONTAINING_RECORD( iface
, struct client_security
, IClientSecurity_iface
);
45 static HRESULT WINAPI
client_security_QueryInterface(
46 IClientSecurity
*iface
,
50 struct client_security
*cs
= impl_from_IClientSecurity( iface
);
52 TRACE("%p %s %p\n", cs
, debugstr_guid( riid
), ppvObject
);
54 if ( IsEqualGUID( riid
, &IID_IClientSecurity
) ||
55 IsEqualGUID( riid
, &IID_IUnknown
) )
61 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
64 IClientSecurity_AddRef( iface
);
68 static ULONG WINAPI
client_security_AddRef(
69 IClientSecurity
*iface
)
75 static ULONG WINAPI
client_security_Release(
76 IClientSecurity
*iface
)
82 static HRESULT WINAPI
client_security_QueryBlanket(
83 IClientSecurity
*iface
,
87 OLECHAR
**pServerPrincName
,
91 DWORD
*pCapabilities
)
97 static HRESULT WINAPI
client_security_SetBlanket(
98 IClientSecurity
*iface
,
102 OLECHAR
*pServerPrincName
,
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
;
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
;
117 static HRESULT WINAPI
client_security_CopyProxy(
118 IClientSecurity
*iface
,
123 return WBEM_E_FAILED
;
126 static const IClientSecurityVtbl client_security_vtbl
=
128 client_security_QueryInterface
,
129 client_security_AddRef
,
130 client_security_Release
,
131 client_security_QueryBlanket
,
132 client_security_SetBlanket
,
133 client_security_CopyProxy
136 IClientSecurity client_security
= { &client_security_vtbl
};
140 IWbemObjectSink
*sink
;
141 void (*proc
)( struct async_header
* );
148 struct async_header hdr
;
152 static void free_async( struct async_header
*async
)
154 if (async
->sink
) IWbemObjectSink_Release( async
->sink
);
155 CloseHandle( async
->cancel
);
156 CloseHandle( async
->wait
);
160 static BOOL
init_async( struct async_header
*async
, IWbemObjectSink
*sink
,
161 void (*proc
)(struct async_header
*) )
163 if (!(async
->wait
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
))) return FALSE
;
164 if (!(async
->cancel
= CreateEventW( NULL
, FALSE
, FALSE
, NULL
)))
166 CloseHandle( async
->wait
);
171 IWbemObjectSink_AddRef( sink
);
175 static DWORD CALLBACK
async_proc( LPVOID param
)
177 struct async_header
*async
= param
;
178 HANDLE wait
= async
->wait
;
180 async
->proc( async
);
182 WaitForSingleObject( async
->cancel
, INFINITE
);
184 return ERROR_SUCCESS
;
187 static HRESULT
queue_async( struct async_header
*async
)
189 if (QueueUserWorkItem( async_proc
, async
, WT_EXECUTELONGFUNCTION
)) return S_OK
;
190 return HRESULT_FROM_WIN32( GetLastError() );
195 IWbemServices IWbemServices_iface
;
199 struct async_header
*async
;
202 static inline struct wbem_services
*impl_from_IWbemServices( IWbemServices
*iface
)
204 return CONTAINING_RECORD( iface
, struct wbem_services
, IWbemServices_iface
);
207 static ULONG WINAPI
wbem_services_AddRef(
208 IWbemServices
*iface
)
210 struct wbem_services
*ws
= impl_from_IWbemServices( iface
);
211 return InterlockedIncrement( &ws
->refs
);
214 static ULONG WINAPI
wbem_services_Release(
215 IWbemServices
*iface
)
217 struct wbem_services
*ws
= impl_from_IWbemServices( iface
);
218 LONG refs
= InterlockedDecrement( &ws
->refs
);
221 TRACE("destroying %p\n", ws
);
223 EnterCriticalSection( &ws
->cs
);
224 if (ws
->async
) SetEvent( ws
->async
->cancel
);
225 LeaveCriticalSection( &ws
->cs
);
228 WaitForSingleObject( ws
->async
->wait
, INFINITE
);
229 free_async( ws
->async
);
231 ws
->cs
.DebugInfo
->Spare
[0] = 0;
232 DeleteCriticalSection( &ws
->cs
);
233 heap_free( ws
->namespace );
239 static HRESULT WINAPI
wbem_services_QueryInterface(
240 IWbemServices
*iface
,
244 struct wbem_services
*ws
= impl_from_IWbemServices( iface
);
246 TRACE("%p %s %p\n", ws
, debugstr_guid( riid
), ppvObject
);
248 if ( IsEqualGUID( riid
, &IID_IWbemServices
) ||
249 IsEqualGUID( riid
, &IID_IUnknown
) )
253 else if ( IsEqualGUID( riid
, &IID_IClientSecurity
) )
255 *ppvObject
= &client_security
;
260 FIXME("interface %s not implemented\n", debugstr_guid(riid
));
261 return E_NOINTERFACE
;
263 IWbemServices_AddRef( iface
);
267 static HRESULT WINAPI
wbem_services_OpenNamespace(
268 IWbemServices
*iface
,
269 const BSTR strNamespace
,
272 IWbemServices
**ppWorkingNamespace
,
273 IWbemCallResult
**ppResult
)
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
);
279 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface
, debugstr_w(strNamespace
), lFlags
,
280 pCtx
, ppWorkingNamespace
, ppResult
);
282 if ((strcmpiW( strNamespace
, cimv2W
) && strcmpiW( strNamespace
, defaultW
)) || ws
->namespace)
283 return WBEM_E_INVALID_NAMESPACE
;
285 return WbemServices_create( cimv2W
, (void **)ppWorkingNamespace
);
288 static HRESULT WINAPI
wbem_services_CancelAsyncCall(
289 IWbemServices
*iface
,
290 IWbemObjectSink
*pSink
)
292 struct wbem_services
*services
= impl_from_IWbemServices( iface
);
293 struct async_header
*async
;
295 TRACE("%p, %p\n", iface
, pSink
);
297 if (!pSink
) return WBEM_E_INVALID_PARAMETER
;
299 EnterCriticalSection( &services
->cs
);
301 if (!(async
= services
->async
))
303 LeaveCriticalSection( &services
->cs
);
304 return WBEM_E_INVALID_PARAMETER
;
306 services
->async
= NULL
;
307 SetEvent( async
->cancel
);
309 LeaveCriticalSection( &services
->cs
);
311 WaitForSingleObject( async
->wait
, INFINITE
);
316 static HRESULT WINAPI
wbem_services_QueryObjectSink(
317 IWbemServices
*iface
,
319 IWbemObjectSink
**ppResponseHandler
)
322 return WBEM_E_FAILED
;
333 static HRESULT
parse_path( const WCHAR
*str
, struct path
**ret
)
336 const WCHAR
*p
= str
, *q
;
339 if (!(path
= heap_alloc_zero( sizeof(*path
) ))) return E_OUTOFMEMORY
;
341 while (*p
&& *p
!= '.') p
++;
344 if (!(path
->class = heap_alloc( (len
+ 1) * sizeof(WCHAR
) )))
347 return E_OUTOFMEMORY
;
349 memcpy( path
->class, str
, len
* sizeof(WCHAR
) );
350 path
->class[len
] = 0;
351 path
->class_len
= len
;
353 if (p
[0] == '.' && p
[1])
359 if (!(path
->filter
= heap_alloc( (len
+ 1) * sizeof(WCHAR
) )))
361 heap_free( path
->class );
363 return E_OUTOFMEMORY
;
365 memcpy( path
->filter
, p
, len
* sizeof(WCHAR
) );
366 path
->filter
[len
] = 0;
367 path
->filter_len
= len
;
373 static void free_path( struct path
*path
)
375 heap_free( path
->class );
376 heap_free( path
->filter
);
380 static WCHAR
*query_from_path( const struct path
*path
)
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};
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
);
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 );
406 static HRESULT
create_instance_enum( const struct path
*path
, IEnumWbemClassObject
**iter
)
411 if (!(query
= query_from_path( path
))) return E_OUTOFMEMORY
;
412 hr
= exec_query( query
, iter
);
417 HRESULT
get_object( const WCHAR
*object_path
, IWbemClassObject
**obj
)
419 IEnumWbemClassObject
*iter
;
423 hr
= parse_path( object_path
, &path
);
424 if (hr
!= S_OK
) return hr
;
426 hr
= create_instance_enum( path
, &iter
);
432 hr
= create_class_object( path
->class, iter
, 0, NULL
, obj
);
433 IEnumWbemClassObject_Release( iter
);
438 static HRESULT WINAPI
wbem_services_GetObject(
439 IWbemServices
*iface
,
440 const BSTR strObjectPath
,
443 IWbemClassObject
**ppObject
,
444 IWbemCallResult
**ppCallResult
)
446 TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface
, debugstr_w(strObjectPath
), lFlags
,
447 pCtx
, ppObject
, ppCallResult
);
449 if (lFlags
) FIXME("unsupported flags 0x%08x\n", lFlags
);
451 if (!strObjectPath
|| !strObjectPath
[0])
452 return create_class_object( NULL
, NULL
, 0, NULL
, ppObject
);
454 return get_object( strObjectPath
, ppObject
);
457 static HRESULT WINAPI
wbem_services_GetObjectAsync(
458 IWbemServices
*iface
,
459 const BSTR strObjectPath
,
462 IWbemObjectSink
*pResponseHandler
)
465 return WBEM_E_FAILED
;
468 static HRESULT WINAPI
wbem_services_PutClass(
469 IWbemServices
*iface
,
470 IWbemClassObject
*pObject
,
473 IWbemCallResult
**ppCallResult
)
476 return WBEM_E_FAILED
;
479 static HRESULT WINAPI
wbem_services_PutClassAsync(
480 IWbemServices
*iface
,
481 IWbemClassObject
*pObject
,
484 IWbemObjectSink
*pResponseHandler
)
487 return WBEM_E_FAILED
;
490 static HRESULT WINAPI
wbem_services_DeleteClass(
491 IWbemServices
*iface
,
495 IWbemCallResult
**ppCallResult
)
498 return WBEM_E_FAILED
;
501 static HRESULT WINAPI
wbem_services_DeleteClassAsync(
502 IWbemServices
*iface
,
506 IWbemObjectSink
*pResponseHandler
)
509 return WBEM_E_FAILED
;
512 static HRESULT WINAPI
wbem_services_CreateClassEnum(
513 IWbemServices
*iface
,
514 const BSTR strSuperclass
,
517 IEnumWbemClassObject
**ppEnum
)
520 return WBEM_E_FAILED
;
523 static HRESULT WINAPI
wbem_services_CreateClassEnumAsync(
524 IWbemServices
*iface
,
525 const BSTR strSuperclass
,
528 IWbemObjectSink
*pResponseHandler
)
531 return WBEM_E_FAILED
;
534 static HRESULT WINAPI
wbem_services_PutInstance(
535 IWbemServices
*iface
,
536 IWbemClassObject
*pInst
,
539 IWbemCallResult
**ppCallResult
)
542 return WBEM_E_FAILED
;
545 static HRESULT WINAPI
wbem_services_PutInstanceAsync(
546 IWbemServices
*iface
,
547 IWbemClassObject
*pInst
,
550 IWbemObjectSink
*pResponseHandler
)
553 return WBEM_E_FAILED
;
556 static HRESULT WINAPI
wbem_services_DeleteInstance(
557 IWbemServices
*iface
,
558 const BSTR strObjectPath
,
561 IWbemCallResult
**ppCallResult
)
564 return WBEM_E_FAILED
;
567 static HRESULT WINAPI
wbem_services_DeleteInstanceAsync(
568 IWbemServices
*iface
,
569 const BSTR strObjectPath
,
572 IWbemObjectSink
*pResponseHandler
)
575 return WBEM_E_FAILED
;
578 static HRESULT WINAPI
wbem_services_CreateInstanceEnum(
579 IWbemServices
*iface
,
583 IEnumWbemClassObject
**ppEnum
)
588 TRACE("%p, %s, 0%08x, %p, %p\n", iface
, debugstr_w(strClass
), lFlags
, pCtx
, ppEnum
);
590 if (lFlags
) FIXME("unsupported flags 0x%08x\n", lFlags
);
592 hr
= parse_path( strClass
, &path
);
593 if (hr
!= S_OK
) return hr
;
595 hr
= create_instance_enum( path
, ppEnum
);
600 static HRESULT WINAPI
wbem_services_CreateInstanceEnumAsync(
601 IWbemServices
*iface
,
602 const BSTR strFilter
,
605 IWbemObjectSink
*pResponseHandler
)
608 return WBEM_E_FAILED
;
611 static HRESULT WINAPI
wbem_services_ExecQuery(
612 IWbemServices
*iface
,
613 const BSTR strQueryLanguage
,
617 IEnumWbemClassObject
**ppEnum
)
619 static const WCHAR wqlW
[] = {'W','Q','L',0};
621 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface
, debugstr_w(strQueryLanguage
),
622 debugstr_w(strQuery
), lFlags
, pCtx
, ppEnum
);
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
);
629 static void async_exec_query( struct async_header
*hdr
)
631 struct async_query
*query
= (struct async_query
*)hdr
;
632 IEnumWbemClassObject
*result
;
633 IWbemClassObject
*obj
;
637 hr
= exec_query( query
->str
, &result
);
642 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
644 IWbemObjectSink_Indicate( query
->hdr
.sink
, 1, &obj
);
645 IWbemClassObject_Release( obj
);
647 IEnumWbemClassObject_Release( result
);
649 IWbemObjectSink_SetStatus( query
->hdr
.sink
, WBEM_STATUS_COMPLETE
, hr
, NULL
, NULL
);
650 heap_free( query
->str
);
653 static HRESULT WINAPI
wbem_services_ExecQueryAsync(
654 IWbemServices
*iface
,
655 const BSTR strQueryLanguage
,
659 IWbemObjectSink
*pResponseHandler
)
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
;
667 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface
, debugstr_w(strQueryLanguage
), debugstr_w(strQuery
),
668 lFlags
, pCtx
, pResponseHandler
);
670 if (!pResponseHandler
) return WBEM_E_INVALID_PARAMETER
;
672 hr
= IWbemObjectSink_QueryInterface( pResponseHandler
, &IID_IWbemObjectSink
, (void **)&sink
);
673 if (FAILED(hr
)) return hr
;
675 EnterCriticalSection( &services
->cs
);
679 FIXME("handle more than one pending async\n");
683 if (!(query
= heap_alloc_zero( sizeof(*query
) ))) goto done
;
684 async
= (struct async_header
*)query
;
686 if (!(init_async( async
, sink
, async_exec_query
)))
691 if (!(query
->str
= heap_strdupW( strQuery
)))
696 hr
= queue_async( async
);
697 if (hr
== S_OK
) services
->async
= async
;
700 heap_free( query
->str
);
705 LeaveCriticalSection( &services
->cs
);
706 IWbemObjectSink_Release( sink
);
710 static HRESULT WINAPI
wbem_services_ExecNotificationQuery(
711 IWbemServices
*iface
,
712 const BSTR strQueryLanguage
,
716 IEnumWbemClassObject
**ppEnum
)
719 return WBEM_E_FAILED
;
722 static HRESULT WINAPI
wbem_services_ExecNotificationQueryAsync(
723 IWbemServices
*iface
,
724 const BSTR strQueryLanguage
,
728 IWbemObjectSink
*pResponseHandler
)
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
;
736 TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface
, debugstr_w(strQueryLanguage
), debugstr_w(strQuery
),
737 lFlags
, pCtx
, pResponseHandler
);
739 if (!pResponseHandler
) return WBEM_E_INVALID_PARAMETER
;
741 hr
= IWbemObjectSink_QueryInterface( pResponseHandler
, &IID_IWbemObjectSink
, (void **)&sink
);
742 if (FAILED(hr
)) return hr
;
744 EnterCriticalSection( &services
->cs
);
748 FIXME("handle more than one pending async\n");
752 if (!(query
= heap_alloc_zero( sizeof(*query
) ))) goto done
;
753 async
= (struct async_header
*)query
;
755 if (!(init_async( async
, sink
, async_exec_query
)))
760 if (!(query
->str
= heap_strdupW( strQuery
)))
765 hr
= queue_async( async
);
766 if (hr
== S_OK
) services
->async
= async
;
769 heap_free( query
->str
);
774 LeaveCriticalSection( &services
->cs
);
775 IWbemObjectSink_Release( sink
);
779 static HRESULT WINAPI
wbem_services_ExecMethod(
780 IWbemServices
*iface
,
781 const BSTR strObjectPath
,
782 const BSTR strMethodName
,
785 IWbemClassObject
*pInParams
,
786 IWbemClassObject
**ppOutParams
,
787 IWbemCallResult
**ppCallResult
)
789 IEnumWbemClassObject
*result
= NULL
;
790 IWbemClassObject
*obj
= NULL
;
791 struct query
*query
= NULL
;
797 TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface
, debugstr_w(strObjectPath
),
798 debugstr_w(strMethodName
), lFlags
, pCtx
, pInParams
, ppOutParams
, ppCallResult
);
800 if (lFlags
) FIXME("flags %08x not supported\n", lFlags
);
802 if ((hr
= parse_path( strObjectPath
, &path
)) != S_OK
) return hr
;
803 if (!(str
= query_from_path( path
)))
808 if (!(query
= create_query()))
813 hr
= parse_query( str
, &query
->view
, &query
->mem
);
814 if (hr
!= S_OK
) goto done
;
816 hr
= execute_view( query
->view
);
817 if (hr
!= S_OK
) goto done
;
819 hr
= EnumWbemClassObject_create( query
, (void **)&result
);
820 if (hr
!= S_OK
) goto done
;
822 hr
= create_class_object( query
->view
->table
->name
, result
, 0, NULL
, &obj
);
823 if (hr
!= S_OK
) goto done
;
825 hr
= get_method( query
->view
->table
, strMethodName
, &func
);
826 if (hr
!= S_OK
) goto done
;
828 hr
= func( obj
, pInParams
, ppOutParams
);
831 if (result
) IEnumWbemClassObject_Release( result
);
832 if (obj
) IWbemClassObject_Release( obj
);
839 static HRESULT WINAPI
wbem_services_ExecMethodAsync(
840 IWbemServices
*iface
,
841 const BSTR strObjectPath
,
842 const BSTR strMethodName
,
845 IWbemClassObject
*pInParams
,
846 IWbemObjectSink
*pResponseHandler
)
849 return WBEM_E_FAILED
;
852 static const IWbemServicesVtbl wbem_services_vtbl
=
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
882 HRESULT
WbemServices_create( const WCHAR
*namespace, LPVOID
*ppObj
)
884 struct wbem_services
*ws
;
886 TRACE("(%p)\n", ppObj
);
888 ws
= heap_alloc( sizeof(*ws
) );
889 if (!ws
) return E_OUTOFMEMORY
;
891 ws
->IWbemServices_iface
.lpVtbl
= &wbem_services_vtbl
;
893 ws
->namespace = heap_strdupW( namespace );
895 InitializeCriticalSection( &ws
->cs
);
896 ws
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": wbemprox_services.cs");
898 *ppObj
= &ws
->IWbemServices_iface
;
900 TRACE("returning iface %p\n", *ppObj
);