cmd: Convert wcmd_for to use WCMD_parameter.
[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)
356     {
357         FIXME("no support for creating new classes\n");
358         return WBEM_E_FAILED;
359     }
360     return get_object( strObjectPath, ppObject );
361 }
362
363 static HRESULT WINAPI wbem_services_GetObjectAsync(
364     IWbemServices *iface,
365     const BSTR strObjectPath,
366     LONG lFlags,
367     IWbemContext *pCtx,
368     IWbemObjectSink *pResponseHandler )
369 {
370     FIXME("\n");
371     return WBEM_E_FAILED;
372 }
373
374 static HRESULT WINAPI wbem_services_PutClass(
375     IWbemServices *iface,
376     IWbemClassObject *pObject,
377     LONG lFlags,
378     IWbemContext *pCtx,
379     IWbemCallResult **ppCallResult )
380 {
381     FIXME("\n");
382     return WBEM_E_FAILED;
383 }
384
385 static HRESULT WINAPI wbem_services_PutClassAsync(
386     IWbemServices *iface,
387     IWbemClassObject *pObject,
388     LONG lFlags,
389     IWbemContext *pCtx,
390     IWbemObjectSink *pResponseHandler )
391 {
392     FIXME("\n");
393     return WBEM_E_FAILED;
394 }
395
396 static HRESULT WINAPI wbem_services_DeleteClass(
397     IWbemServices *iface,
398     const BSTR strClass,
399     LONG lFlags,
400     IWbemContext *pCtx,
401     IWbemCallResult **ppCallResult )
402 {
403     FIXME("\n");
404     return WBEM_E_FAILED;
405 }
406
407 static HRESULT WINAPI wbem_services_DeleteClassAsync(
408     IWbemServices *iface,
409     const BSTR strClass,
410     LONG lFlags,
411     IWbemContext *pCtx,
412     IWbemObjectSink *pResponseHandler )
413 {
414     FIXME("\n");
415     return WBEM_E_FAILED;
416 }
417
418 static HRESULT WINAPI wbem_services_CreateClassEnum(
419     IWbemServices *iface,
420     const BSTR strSuperclass,
421     LONG lFlags,
422     IWbemContext *pCtx,
423     IEnumWbemClassObject **ppEnum )
424 {
425     FIXME("\n");
426     return WBEM_E_FAILED;
427 }
428
429 static HRESULT WINAPI wbem_services_CreateClassEnumAsync(
430     IWbemServices *iface,
431     const BSTR strSuperclass,
432     LONG lFlags,
433     IWbemContext *pCtx,
434     IWbemObjectSink *pResponseHandler )
435 {
436     FIXME("\n");
437     return WBEM_E_FAILED;
438 }
439
440 static HRESULT WINAPI wbem_services_PutInstance(
441     IWbemServices *iface,
442     IWbemClassObject *pInst,
443     LONG lFlags,
444     IWbemContext *pCtx,
445     IWbemCallResult **ppCallResult )
446 {
447     FIXME("\n");
448     return WBEM_E_FAILED;
449 }
450
451 static HRESULT WINAPI wbem_services_PutInstanceAsync(
452     IWbemServices *iface,
453     IWbemClassObject *pInst,
454     LONG lFlags,
455     IWbemContext *pCtx,
456     IWbemObjectSink *pResponseHandler )
457 {
458     FIXME("\n");
459     return WBEM_E_FAILED;
460 }
461
462 static HRESULT WINAPI wbem_services_DeleteInstance(
463     IWbemServices *iface,
464     const BSTR strObjectPath,
465     LONG lFlags,
466     IWbemContext *pCtx,
467     IWbemCallResult **ppCallResult )
468 {
469     FIXME("\n");
470     return WBEM_E_FAILED;
471 }
472
473 static HRESULT WINAPI wbem_services_DeleteInstanceAsync(
474     IWbemServices *iface,
475     const BSTR strObjectPath,
476     LONG lFlags,
477     IWbemContext *pCtx,
478     IWbemObjectSink *pResponseHandler )
479 {
480     FIXME("\n");
481     return WBEM_E_FAILED;
482 }
483
484 static HRESULT WINAPI wbem_services_CreateInstanceEnum(
485     IWbemServices *iface,
486     const BSTR strClass,
487     LONG lFlags,
488     IWbemContext *pCtx,
489     IEnumWbemClassObject **ppEnum )
490 {
491     struct path *path;
492     HRESULT hr;
493
494     TRACE("%p, %s, 0%08x, %p, %p\n", iface, debugstr_w(strClass), lFlags, pCtx, ppEnum);
495
496     if (lFlags) FIXME("unsupported flags 0x%08x\n", lFlags);
497
498     hr = parse_path( strClass, &path );
499     if (hr != S_OK) return hr;
500
501     hr = create_instance_enum( path, ppEnum );
502     free_path( path );
503     return hr;
504 }
505
506 static HRESULT WINAPI wbem_services_CreateInstanceEnumAsync(
507     IWbemServices *iface,
508     const BSTR strFilter,
509     LONG lFlags,
510     IWbemContext *pCtx,
511     IWbemObjectSink *pResponseHandler )
512 {
513     FIXME("\n");
514     return WBEM_E_FAILED;
515 }
516
517 static HRESULT WINAPI wbem_services_ExecQuery(
518     IWbemServices *iface,
519     const BSTR strQueryLanguage,
520     const BSTR strQuery,
521     LONG lFlags,
522     IWbemContext *pCtx,
523     IEnumWbemClassObject **ppEnum )
524 {
525     static const WCHAR wqlW[] = {'W','Q','L',0};
526
527     TRACE("%p, %s, %s, 0x%08x, %p, %p\n", iface, debugstr_w(strQueryLanguage),
528           debugstr_w(strQuery), lFlags, pCtx, ppEnum);
529
530     if (!strQueryLanguage || !strQuery) return WBEM_E_INVALID_PARAMETER;
531     if (strcmpiW( strQueryLanguage, wqlW )) return WBEM_E_INVALID_QUERY_TYPE;
532     return exec_query( strQuery, ppEnum );
533 }
534
535 static HRESULT WINAPI wbem_services_ExecQueryAsync(
536     IWbemServices *iface,
537     const BSTR strQueryLanguage,
538     const BSTR strQuery,
539     LONG lFlags,
540     IWbemContext *pCtx,
541     IWbemObjectSink *pResponseHandler )
542 {
543     FIXME("\n");
544     return WBEM_E_FAILED;
545 }
546
547 static HRESULT WINAPI wbem_services_ExecNotificationQuery(
548     IWbemServices *iface,
549     const BSTR strQueryLanguage,
550     const BSTR strQuery,
551     LONG lFlags,
552     IWbemContext *pCtx,
553     IEnumWbemClassObject **ppEnum )
554 {
555     FIXME("\n");
556     return WBEM_E_FAILED;
557 }
558
559 static HRESULT WINAPI wbem_services_ExecNotificationQueryAsync(
560     IWbemServices *iface,
561     const BSTR strQueryLanguage,
562     const BSTR strQuery,
563     LONG lFlags,
564     IWbemContext *pCtx,
565     IWbemObjectSink *pResponseHandler )
566 {
567     FIXME("\n");
568     return WBEM_E_FAILED;
569 }
570
571 static HRESULT WINAPI wbem_services_ExecMethod(
572     IWbemServices *iface,
573     const BSTR strObjectPath,
574     const BSTR strMethodName,
575     LONG lFlags,
576     IWbemContext *pCtx,
577     IWbemClassObject *pInParams,
578     IWbemClassObject **ppOutParams,
579     IWbemCallResult **ppCallResult )
580 {
581     const struct table *table;
582     class_method *func;
583     struct path *path;
584     HRESULT hr;
585
586     TRACE("%p, %s, %s, %08x, %p, %p, %p, %p\n", iface, debugstr_w(strObjectPath),
587           debugstr_w(strMethodName), lFlags, pCtx, pInParams, ppOutParams, ppCallResult);
588
589     if (lFlags) FIXME("flags %08x not supported\n", lFlags);
590
591     if ((hr = parse_path( strObjectPath, &path )) != S_OK) return hr;
592
593     table = get_table( path->class );
594     free_path( path );
595     if (!table) return WBEM_E_NOT_FOUND;
596
597     if ((hr = get_method( table, strMethodName, &func )) != S_OK) return hr;
598     return func( pInParams, ppOutParams );
599 }
600
601 static HRESULT WINAPI wbem_services_ExecMethodAsync(
602     IWbemServices *iface,
603     const BSTR strObjectPath,
604     const BSTR strMethodName,
605     LONG lFlags,
606     IWbemContext *pCtx,
607     IWbemClassObject *pInParams,
608     IWbemObjectSink *pResponseHandler )
609 {
610     FIXME("\n");
611     return WBEM_E_FAILED;
612 }
613
614 static const IWbemServicesVtbl wbem_services_vtbl =
615 {
616     wbem_services_QueryInterface,
617     wbem_services_AddRef,
618     wbem_services_Release,
619     wbem_services_OpenNamespace,
620     wbem_services_CancelAsyncCall,
621     wbem_services_QueryObjectSink,
622     wbem_services_GetObject,
623     wbem_services_GetObjectAsync,
624     wbem_services_PutClass,
625     wbem_services_PutClassAsync,
626     wbem_services_DeleteClass,
627     wbem_services_DeleteClassAsync,
628     wbem_services_CreateClassEnum,
629     wbem_services_CreateClassEnumAsync,
630     wbem_services_PutInstance,
631     wbem_services_PutInstanceAsync,
632     wbem_services_DeleteInstance,
633     wbem_services_DeleteInstanceAsync,
634     wbem_services_CreateInstanceEnum,
635     wbem_services_CreateInstanceEnumAsync,
636     wbem_services_ExecQuery,
637     wbem_services_ExecQueryAsync,
638     wbem_services_ExecNotificationQuery,
639     wbem_services_ExecNotificationQueryAsync,
640     wbem_services_ExecMethod,
641     wbem_services_ExecMethodAsync
642 };
643
644 HRESULT WbemServices_create( IUnknown *pUnkOuter, const WCHAR *namespace, LPVOID *ppObj )
645 {
646     struct wbem_services *ws;
647
648     TRACE("(%p,%p)\n", pUnkOuter, ppObj);
649
650     ws = heap_alloc( sizeof(*ws) );
651     if (!ws) return E_OUTOFMEMORY;
652
653     ws->IWbemServices_iface.lpVtbl = &wbem_services_vtbl;
654     ws->refs = 1;
655     ws->namespace = heap_strdupW( namespace );
656
657     *ppObj = &ws->IWbemServices_iface;
658
659     TRACE("returning iface %p\n", *ppObj);
660     return S_OK;
661 }