Release 1.5.29.
[wine] / dlls / wbemprox / services.c
1 /*
2  * Copyright 2012 Hans Leidekker for CodeWeavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18
19 #define COBJMACROS
20
21 #include "config.h"
22 #include <stdarg.h>
23
24 #include "windef.h"
25 #include "winbase.h"
26 #include "objbase.h"
27 #include "wbemcli.h"
28
29 #include "wine/debug.h"
30 #include "wine/unicode.h"
31 #include "wbemprox_private.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(wbemprox);
34
35 struct client_security
36 {
37     IClientSecurity IClientSecurity_iface;
38 };
39
40 static inline struct client_security *impl_from_IClientSecurity( IClientSecurity *iface )
41 {
42     return CONTAINING_RECORD( iface, struct client_security, IClientSecurity_iface );
43 }
44
45 static HRESULT WINAPI client_security_QueryInterface(
46     IClientSecurity *iface,
47     REFIID riid,
48     void **ppvObject )
49 {
50     struct client_security *cs = impl_from_IClientSecurity( iface );
51
52     TRACE("%p %s %p\n", cs, debugstr_guid( riid ), ppvObject );
53
54     if ( IsEqualGUID( riid, &IID_IClientSecurity ) ||
55          IsEqualGUID( riid, &IID_IUnknown ) )
56     {
57         *ppvObject = cs;
58     }
59     else
60     {
61         FIXME("interface %s not implemented\n", debugstr_guid(riid));
62         return E_NOINTERFACE;
63     }
64     IClientSecurity_AddRef( iface );
65     return S_OK;
66 }
67
68 static ULONG WINAPI client_security_AddRef(
69     IClientSecurity *iface )
70 {
71     FIXME("%p\n", iface);
72     return 2;
73 }
74
75 static ULONG WINAPI client_security_Release(
76     IClientSecurity *iface )
77 {
78     FIXME("%p\n", iface);
79     return 1;
80 }
81
82 static HRESULT WINAPI client_security_QueryBlanket(
83     IClientSecurity *iface,
84     IUnknown *pProxy,
85     DWORD *pAuthnSvc,
86     DWORD *pAuthzSvc,
87     OLECHAR **pServerPrincName,
88     DWORD *pAuthnLevel,
89     DWORD *pImpLevel,
90     void **pAuthInfo,
91     DWORD *pCapabilities )
92 {
93     FIXME("\n");
94     return WBEM_E_FAILED;
95 }
96
97 static HRESULT WINAPI client_security_SetBlanket(
98     IClientSecurity *iface,
99     IUnknown *pProxy,
100     DWORD AuthnSvc,
101     DWORD AuthzSvc,
102     OLECHAR *pServerPrincName,
103     DWORD AuthnLevel,
104     DWORD ImpLevel,
105     void *pAuthInfo,
106     DWORD Capabilities )
107 {
108     static const OLECHAR defaultW[] =
109         {'<','C','O','L','E','_','D','E','F','A','U','L','T','_','P','R','I','N','C','I','P','A','L','>',0};
110     const OLECHAR *princname = (pServerPrincName == COLE_DEFAULT_PRINCIPAL) ? defaultW : pServerPrincName;
111
112     FIXME("%p, %p, %u, %u, %s, %u, %u, %p, 0x%08x\n", iface, pProxy, AuthnSvc, AuthzSvc,
113           debugstr_w(princname), AuthnLevel, ImpLevel, pAuthInfo, Capabilities);
114     return WBEM_NO_ERROR;
115 }
116
117 static HRESULT WINAPI client_security_CopyProxy(
118     IClientSecurity *iface,
119     IUnknown *pProxy,
120     IUnknown **ppCopy )
121 {
122     FIXME("\n");
123     return WBEM_E_FAILED;
124 }
125
126 static const IClientSecurityVtbl client_security_vtbl =
127 {
128     client_security_QueryInterface,
129     client_security_AddRef,
130     client_security_Release,
131     client_security_QueryBlanket,
132     client_security_SetBlanket,
133     client_security_CopyProxy
134 };
135
136 IClientSecurity client_security = { &client_security_vtbl };
137
138 struct wbem_services
139 {
140     IWbemServices IWbemServices_iface;
141     LONG refs;
142     WCHAR *namespace;
143 };
144
145 static inline struct wbem_services *impl_from_IWbemServices( IWbemServices *iface )
146 {
147     return CONTAINING_RECORD( iface, struct wbem_services, IWbemServices_iface );
148 }
149
150 static ULONG WINAPI wbem_services_AddRef(
151     IWbemServices *iface )
152 {
153     struct wbem_services *ws = impl_from_IWbemServices( iface );
154     return InterlockedIncrement( &ws->refs );
155 }
156
157 static ULONG WINAPI wbem_services_Release(
158     IWbemServices *iface )
159 {
160     struct wbem_services *ws = impl_from_IWbemServices( iface );
161     LONG refs = InterlockedDecrement( &ws->refs );
162     if (!refs)
163     {
164         TRACE("destroying %p\n", ws);
165         heap_free( ws->namespace );
166         heap_free( ws );
167     }
168     return refs;
169 }
170
171 static HRESULT WINAPI wbem_services_QueryInterface(
172     IWbemServices *iface,
173     REFIID riid,
174     void **ppvObject )
175 {
176     struct wbem_services *ws = impl_from_IWbemServices( iface );
177
178     TRACE("%p %s %p\n", ws, debugstr_guid( riid ), ppvObject );
179
180     if ( IsEqualGUID( riid, &IID_IWbemServices ) ||
181          IsEqualGUID( riid, &IID_IUnknown ) )
182     {
183         *ppvObject = ws;
184     }
185     else if ( IsEqualGUID( riid, &IID_IClientSecurity ) )
186     {
187         *ppvObject = &client_security;
188         return S_OK;
189     }
190     else
191     {
192         FIXME("interface %s not implemented\n", debugstr_guid(riid));
193         return E_NOINTERFACE;
194     }
195     IWbemServices_AddRef( iface );
196     return S_OK;
197 }
198
199 static HRESULT WINAPI wbem_services_OpenNamespace(
200     IWbemServices *iface,
201     const BSTR strNamespace,
202     LONG lFlags,
203     IWbemContext *pCtx,
204     IWbemServices **ppWorkingNamespace,
205     IWbemCallResult **ppResult )
206 {
207     static const WCHAR cimv2W[] = {'c','i','m','v','2',0};
208     static const WCHAR defaultW[] = {'d','e','f','a','u','l','t',0};
209     struct wbem_services *ws = impl_from_IWbemServices( iface );
210
211     TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strNamespace), lFlags,
212           pCtx, ppWorkingNamespace, ppResult);
213
214     if ((strcmpiW( strNamespace, cimv2W ) && strcmpiW( strNamespace, defaultW )) || ws->namespace)
215         return WBEM_E_INVALID_NAMESPACE;
216
217     return WbemServices_create( NULL, cimv2W, (void **)ppWorkingNamespace );
218 }
219
220 static HRESULT WINAPI wbem_services_CancelAsyncCall(
221     IWbemServices *iface,
222     IWbemObjectSink *pSink )
223 {
224     FIXME("\n");
225     return WBEM_E_FAILED;
226 }
227
228 static HRESULT WINAPI wbem_services_QueryObjectSink(
229     IWbemServices *iface,
230     LONG lFlags,
231     IWbemObjectSink **ppResponseHandler )
232 {
233     FIXME("\n");
234     return WBEM_E_FAILED;
235 }
236
237 struct path
238 {
239     WCHAR *class;
240     UINT   class_len;
241     WCHAR *filter;
242     UINT   filter_len;
243 };
244
245 static HRESULT parse_path( const WCHAR *str, struct path **ret )
246 {
247     struct path *path;
248     const WCHAR *p = str, *q;
249     UINT len;
250
251     if (!(path = heap_alloc_zero( sizeof(*path) ))) return E_OUTOFMEMORY;
252
253     while (*p && *p != '.') p++;
254
255     len = p - str;
256     if (!(path->class = heap_alloc( (len + 1) * sizeof(WCHAR) )))
257     {
258         heap_free( path );
259         return E_OUTOFMEMORY;
260     }
261     memcpy( path->class, str, len * sizeof(WCHAR) );
262     path->class[len] = 0;
263     path->class_len = len;
264
265     if (p[0] == '.' && p[1])
266     {
267         q = ++p;
268         while (*q) q++;
269
270         len = q - p;
271         if (!(path->filter = heap_alloc( (len + 1) * sizeof(WCHAR) )))
272         {
273             heap_free( path->class );
274             heap_free( path );
275             return E_OUTOFMEMORY;
276         }
277         memcpy( path->filter, p, len * sizeof(WCHAR) );
278         path->filter[len] = 0;
279         path->filter_len = len;
280     }
281     *ret = path;
282     return S_OK;
283 }
284
285 static void free_path( struct path *path )
286 {
287     heap_free( path->class );
288     heap_free( path->filter );
289     heap_free( path );
290 }
291
292 static HRESULT create_instance_enum( const struct path *path, IEnumWbemClassObject **iter )
293 {
294     static const WCHAR selectW[] =
295         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','%','s',' ',
296          'W','H','E','R','E',' ','%','s',0};
297     static const WCHAR select_allW[] =
298         {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
299     WCHAR *query;
300     HRESULT hr;
301     UINT len;
302
303     if (path->filter)
304     {
305         len = path->class_len + path->filter_len + SIZEOF(selectW);
306         if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
307         sprintfW( query, selectW, path->class, path->filter );
308     }
309     else
310     {
311         len = path->class_len + SIZEOF(select_allW);
312         if (!(query = heap_alloc( len * sizeof(WCHAR) ))) return E_OUTOFMEMORY;
313         strcpyW( query, select_allW );
314         strcatW( query, path->class );
315     }
316     hr = exec_query( query, iter );
317     heap_free( query );
318     return hr;
319 }
320
321 HRESULT get_object( const WCHAR *object_path, IWbemClassObject **obj )
322 {
323     IEnumWbemClassObject *iter;
324     struct path *path;
325     HRESULT hr;
326
327     hr = parse_path( object_path, &path );
328     if (hr != S_OK) return hr;
329
330     hr = create_instance_enum( path, &iter );
331     if (hr != S_OK)
332     {
333         free_path( path );
334         return hr;
335     }
336     hr = create_class_object( path->class, iter, 0, NULL, obj );
337     IEnumWbemClassObject_Release( iter );
338     free_path( path );
339     return hr;
340 }
341
342 static HRESULT WINAPI wbem_services_GetObject(
343     IWbemServices *iface,
344     const BSTR strObjectPath,
345     LONG lFlags,
346     IWbemContext *pCtx,
347     IWbemClassObject **ppObject,
348     IWbemCallResult **ppCallResult )
349 {
350     TRACE("%p, %s, 0x%08x, %p, %p, %p\n", iface, debugstr_w(strObjectPath), lFlags,
351           pCtx, ppObject, ppCallResult);
352
353     if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
354
355     if (!strObjectPath || !strObjectPath[0])
356         return create_class_object( NULL, NULL, 0, NULL, ppObject );
357
358     return get_object( strObjectPath, ppObject );
359 }
360
361 static HRESULT WINAPI wbem_services_GetObjectAsync(
362     IWbemServices *iface,
363     const BSTR strObjectPath,
364     LONG lFlags,
365     IWbemContext *pCtx,
366     IWbemObjectSink *pResponseHandler )
367 {
368     FIXME("\n");
369     return WBEM_E_FAILED;
370 }
371
372 static HRESULT WINAPI wbem_services_PutClass(
373     IWbemServices *iface,
374     IWbemClassObject *pObject,
375     LONG lFlags,
376     IWbemContext *pCtx,
377     IWbemCallResult **ppCallResult )
378 {
379     FIXME("\n");
380     return WBEM_E_FAILED;
381 }
382
383 static HRESULT WINAPI wbem_services_PutClassAsync(
384     IWbemServices *iface,
385     IWbemClassObject *pObject,
386     LONG lFlags,
387     IWbemContext *pCtx,
388     IWbemObjectSink *pResponseHandler )
389 {
390     FIXME("\n");
391     return WBEM_E_FAILED;
392 }
393
394 static HRESULT WINAPI wbem_services_DeleteClass(
395     IWbemServices *iface,
396     const BSTR strClass,
397     LONG lFlags,
398     IWbemContext *pCtx,
399     IWbemCallResult **ppCallResult )
400 {
401     FIXME("\n");
402     return WBEM_E_FAILED;
403 }
404
405 static HRESULT WINAPI wbem_services_DeleteClassAsync(
406     IWbemServices *iface,
407     const BSTR strClass,
408     LONG lFlags,
409     IWbemContext *pCtx,
410     IWbemObjectSink *pResponseHandler )
411 {
412     FIXME("\n");
413     return WBEM_E_FAILED;
414 }
415
416 static HRESULT WINAPI wbem_services_CreateClassEnum(
417     IWbemServices *iface,
418     const BSTR strSuperclass,
419     LONG lFlags,
420     IWbemContext *pCtx,
421     IEnumWbemClassObject **ppEnum )
422 {
423     FIXME("\n");
424     return WBEM_E_FAILED;
425 }
426
427 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
428     IWbemServices *iface,
429     const BSTR strSuperclass,
430     LONG lFlags,
431     IWbemContext *pCtx,
432     IWbemObjectSink *pResponseHandler )
433 {
434     FIXME("\n");
435     return WBEM_E_FAILED;
436 }
437
438 static HRESULT WINAPI wbem_services_PutInstance(
439     IWbemServices *iface,
440     IWbemClassObject *pInst,
441     LONG lFlags,
442     IWbemContext *pCtx,
443     IWbemCallResult **ppCallResult )
444 {
445     FIXME("\n");
446     return WBEM_E_FAILED;
447 }
448
449 static HRESULT WINAPI wbem_services_PutInstanceAsync(
450     IWbemServices *iface,
451     IWbemClassObject *pInst,
452     LONG lFlags,
453     IWbemContext *pCtx,
454     IWbemObjectSink *pResponseHandler )
455 {
456     FIXME("\n");
457     return WBEM_E_FAILED;
458 }
459
460 static HRESULT WINAPI wbem_services_DeleteInstance(
461     IWbemServices *iface,
462     const BSTR strObjectPath,
463     LONG lFlags,
464     IWbemContext *pCtx,
465     IWbemCallResult **ppCallResult )
466 {
467     FIXME("\n");
468     return WBEM_E_FAILED;
469 }
470
471 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
472     IWbemServices *iface,
473     const BSTR strObjectPath,
474     LONG lFlags,
475     IWbemContext *pCtx,
476     IWbemObjectSink *pResponseHandler )
477 {
478     FIXME("\n");
479     return WBEM_E_FAILED;
480 }
481
482 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
483     IWbemServices *iface,
484     const BSTR strClass,
485     LONG lFlags,
486     IWbemContext *pCtx,
487     IEnumWbemClassObject **ppEnum )
488 {
489     struct path *path;
490     HRESULT hr;
491
492     TRACE("%p, %s, 0%08x, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum);
493
494     if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
495
496     hr = parse_path( strClass, &path );
497     if (hr != S_OK) return hr;
498
499     hr = create_instance_enum( path, ppEnum );
500     free_path( path );
501     return hr;
502 }
503
504 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
505     IWbemServices *iface,
506     const BSTR strFilter,
507     LONG lFlags,
508     IWbemContext *pCtx,
509     IWbemObjectSink *pResponseHandler )
510 {
511     FIXME("\n");
512     return WBEM_E_FAILED;
513 }
514
515 static HRESULT WINAPI wbem_services_ExecQuery(
516     IWbemServices *iface,
517     const BSTR strQueryLanguage,
518     const BSTR strQuery,
519     LONG lFlags,
520     IWbemContext *pCtx,
521     IEnumWbemClassObject **ppEnum )
522 {
523     static const WCHAR wqlW[] = {'W','Q','L',0};
524
525     TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
526           debugstr_w(strQuery), lFlags, pCtx, ppEnum);
527
528     if (!strQueryLanguage || !strQuery || !strQuery[0]) return WBEM_E_INVALID_PARAMETER;
529     if (strcmpiW( strQueryLanguage, wqlW )) return WBEM_E_INVALID_QUERY_TYPE;
530     return exec_query( strQuery, ppEnum );
531 }
532
533 static HRESULT WINAPI wbem_services_ExecQueryAsync(
534     IWbemServices *iface,
535     const BSTR strQueryLanguage,
536     const BSTR strQuery,
537     LONG lFlags,
538     IWbemContext *pCtx,
539     IWbemObjectSink *pResponseHandler )
540 {
541     FIXME("\n");
542     return WBEM_E_FAILED;
543 }
544
545 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
546     IWbemServices *iface,
547     const BSTR strQueryLanguage,
548     const BSTR strQuery,
549     LONG lFlags,
550     IWbemContext *pCtx,
551     IEnumWbemClassObject **ppEnum )
552 {
553     FIXME("\n");
554     return WBEM_E_FAILED;
555 }
556
557 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
558     IWbemServices *iface,
559     const BSTR strQueryLanguage,
560     const BSTR strQuery,
561     LONG lFlags,
562     IWbemContext *pCtx,
563     IWbemObjectSink *pResponseHandler )
564 {
565     FIXME("\n");
566     return WBEM_E_FAILED;
567 }
568
569 static HRESULT WINAPI wbem_services_ExecMethod(
570     IWbemServices *iface,
571     const BSTR strObjectPath,
572     const BSTR strMethodName,
573     LONG lFlags,
574     IWbemContext *pCtx,
575     IWbemClassObject *pInParams,
576     IWbemClassObject **ppOutParams,
577     IWbemCallResult **ppCallResult )
578 {
579     IWbemClassObject *obj;
580     struct table *table;
581     class_method *func;
582     struct path *path;
583     HRESULT hr;
584
585     TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
586           debugstr_w(strMethodName), lFlags, pCtx, pInParams, ppOutParams, ppCallResult);
587
588     if (lFlags) FIXME("flags %08x not supported\n", lFlags);
589
590     if ((hr = get_object( strObjectPath, &obj ))) return hr;
591     if ((hr = parse_path( strObjectPath, &path )) != S_OK)
592     {
593         IWbemClassObject_Release( obj );
594         return hr;
595     }
596     table = grab_table( path->class );
597     free_path( path );
598     if (!table)
599     {
600         IWbemClassObject_Release( obj );
601         return WBEM_E_NOT_FOUND;
602     }
603     hr = get_method( table, strMethodName, &func );
604     release_table( table );
605     if (hr != S_OK)
606     {
607         IWbemClassObject_Release( obj );
608         return hr;
609     }
610     hr = func( obj, pInParams, ppOutParams );
611     IWbemClassObject_Release( obj );
612     return hr;
613 }
614
615 static HRESULT WINAPI wbem_services_ExecMethodAsync(
616     IWbemServices *iface,
617     const BSTR strObjectPath,
618     const BSTR strMethodName,
619     LONG lFlags,
620     IWbemContext *pCtx,
621     IWbemClassObject *pInParams,
622     IWbemObjectSink *pResponseHandler )
623 {
624     FIXME("\n");
625     return WBEM_E_FAILED;
626 }
627
628 static const IWbemServicesVtbl wbem_services_vtbl =
629 {
630     wbem_services_QueryInterface,
631     wbem_services_AddRef,
632     wbem_services_Release,
633     wbem_services_OpenNamespace,
634     wbem_services_CancelAsyncCall,
635     wbem_services_QueryObjectSink,
636     wbem_services_GetObject,
637     wbem_services_GetObjectAsync,
638     wbem_services_PutClass,
639     wbem_services_PutClassAsync,
640     wbem_services_DeleteClass,
641     wbem_services_DeleteClassAsync,
642     wbem_services_CreateClassEnum,
643     wbem_services_CreateClassEnumAsync,
644     wbem_services_PutInstance,
645     wbem_services_PutInstanceAsync,
646     wbem_services_DeleteInstance,
647     wbem_services_DeleteInstanceAsync,
648     wbem_services_CreateInstanceEnum,
649     wbem_services_CreateInstanceEnumAsync,
650     wbem_services_ExecQuery,
651     wbem_services_ExecQueryAsync,
652     wbem_services_ExecNotificationQuery,
653     wbem_services_ExecNotificationQueryAsync,
654     wbem_services_ExecMethod,
655     wbem_services_ExecMethodAsync
656 };
657
658 HRESULT WbemServices_create( IUnknown *pUnkOuter, const WCHAR *namespace, LPVOID *ppObj )
659 {
660     struct wbem_services *ws;
661
662     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
663
664     ws = heap_alloc( sizeof(*ws) );
665     if (!ws) return E_OUTOFMEMORY;
666
667     ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
668     ws->refs = 1;
669     ws->namespace = heap_strdupW( namespace );
670
671     *ppObj = &ws->IWbemServices_iface;
672
673     TRACE("returning iface %p\n", *ppObj);
674     return S_OK;
675 }