1 /*
2  * Copyright 2015 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 <stdio.h>
22 #include "windows.h"
23 #include "initguid.h"
24 #include "objidl.h"
25 #include "wbemdisp.h"
26 #include "wbemcli.h"
27 #include "wine/test.h"
28 
29 DEFINE_GUID(CLSID_WINMGMTS,0x172bddf8,0xceea,0x11d1,0x8b,0x05,0x00,0x60,0x08,0x06,0xd9,0xb6);
30 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
31 
32 static const LCID english = MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),SORT_DEFAULT);
33 
34 static void test_ParseDisplayName(void)
35 {
36     static const WCHAR biosW[] = {'W','i','n','3','2','_','B','i','o','s',0};
37     static const WCHAR manufacturerW[] = {'M','a','n','u','f','a','c','t','u','r','e','r',0};
38     static const WCHAR versionW[] = {'v','e','r','s','i','o','n',0};
39     static const WCHAR nosuchW[] = {'N','o','S','u','c','h',0};
40     static const WCHAR name1[] =
41         {'w','i','n','m','g','m','t','s',':',0};
42     static const WCHAR name2[] =
43         {'w','i','n','m','g','m','t','s',':','\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',0};
44     static const WCHAR name3[] =
45         {'w','i','n','m','g','m','t','s',':','\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':',
46          'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k','.',
47          'D','e','v','i','c','e','I','D','=','\'','C',':','\'',0};
48     static const WCHAR name4[] =
49         {'w','i','n','m','g','m','t','s',':','\\','\\','.','\\','r','o','o','t','\\','c','i','m','v','2',':',
50          'W','i','n','3','2','_','S','e','r','v','i','c','e',0};
51     static const WCHAR stdregprovW[] =
52         {'w','i','n','m','g','m','t','s',':','\\','\\','.','\\','r','o','o','t','\\','d','e','f','a','u','l','t',':',
53          'S','t','d','R','e','g','P','r','o','v',0};
54     static const WCHAR getstringvalueW[] =
55         {'G','e','t','S','t','r','i','n','g','V','a','l','u','e',0};
56     static const struct
57     {
58         const WCHAR *name;
59         HRESULT      hr;
60         REFIID       iid;
61         ULONG        eaten;
62     } tests[] =
63     {
64         { name1, S_OK, &IID_ISWbemServices, ARRAY_SIZE( name1 ) - 1 },
65         { name2, S_OK, &IID_ISWbemServices, ARRAY_SIZE( name2 ) - 1 },
66         { name3, S_OK, &IID_ISWbemObject, ARRAY_SIZE( name3 ) - 1 },
67         { name4, S_OK, &IID_ISWbemObject, ARRAY_SIZE( name4 ) - 1 }
68     };
69     IParseDisplayName *displayname;
70     IBindCtx *ctx;
71     IMoniker *moniker;
72     IUnknown *obj;
73     BSTR str;
74     ULONG i, eaten, count;
75     HRESULT hr;
76 
77     hr = CoCreateInstance( &CLSID_WINMGMTS, NULL, CLSCTX_INPROC_SERVER, &IID_IParseDisplayName, (void **)&displayname );
78     if (hr != S_OK)
79     {
80         win_skip( "can't create instance of WINMGMTS\n" );
81         return;
82     }
83 
84     hr = CreateBindCtx( 0, &ctx );
85     ok( hr == S_OK, "got %x\n", hr );
86 
87     for (i =0; i < ARRAY_SIZE( tests ); i++)
88     {
89         str = SysAllocString( tests[i].name );
90         eaten = 0xdeadbeef;
91         moniker = NULL;
92         hr = IParseDisplayName_ParseDisplayName( displayname, NULL, str, &eaten, &moniker );
93         SysFreeString( str );
94         ok( hr == tests[i].hr, "%u: got %x\n", i, hr );
95         ok( eaten == tests[i].eaten, "%u: got %u\n", i, eaten );
96         if (moniker)
97         {
98             obj = NULL;
99             hr = IMoniker_BindToObject( moniker, ctx, NULL, tests[i].iid, (void **)&obj );
100             ok( hr == S_OK, "%u: got %x\n", i, hr );
101             if (obj) IUnknown_Release( obj );
102             IMoniker_Release( moniker );
103         }
104     }
105 
106     str = SysAllocString( name1 );
107     eaten = 0xdeadbeef;
108     moniker = NULL;
109     hr = IParseDisplayName_ParseDisplayName( displayname, NULL, str, &eaten, &moniker );
110     SysFreeString( str );
111     ok( hr == S_OK, "got %x\n", hr );
112     ok( eaten == lstrlenW(name1), "got %u\n", eaten );
113     if (moniker)
114     {
115         ISWbemServices *services = NULL;
116 
117         hr = IMoniker_BindToObject( moniker, ctx, NULL, &IID_IUnknown, (void **)&services );
118         ok( hr == S_OK, "got %x\n", hr );
119         if (services)
120         {
121             ISWbemObjectSet *objectset = NULL;
122 
123             str = SysAllocString( biosW );
124             hr = ISWbemServices_InstancesOf( services, str, 0, NULL, &objectset );
125             SysFreeString( str );
126             ok( hr == S_OK, "got %x\n", hr );
127             if (objectset)
128             {
129                 hr = ISWbemObjectSet_get__NewEnum( objectset, &obj );
130                 ok( hr == S_OK, "got %x\n", hr );
131                 if (obj)
132                 {
133                     IEnumVARIANT *enumvar = NULL;
134 
135                     hr = IUnknown_QueryInterface( obj, &IID_IEnumVARIANT, (void **)&enumvar );
136                     ok( hr == S_OK, "got %x\n", hr );
137 
138                     if (enumvar)
139                     {
140                         VARIANT var, res;
141                         ULONG fetched;
142                         IDispatch *dispatch = NULL;
143                         DISPID dispid;
144                         DISPPARAMS params;
145                         UINT arg_err;
146 
147                         fetched = 0xdeadbeef;
148                         hr = IEnumVARIANT_Next( enumvar, 0, &var, &fetched );
149                         ok( hr == S_OK, "got %x\n", hr );
150                         ok( !fetched, "got %u\n", fetched );
151 
152                         fetched = 0xdeadbeef;
153                         V_VT( &var ) = VT_ERROR;
154                         V_ERROR( &var ) = 0xdeadbeef;
155                         hr = IEnumVARIANT_Next( enumvar, 1, &var, &fetched );
156                         ok( hr == S_OK, "got %x\n", hr );
157                         ok( fetched == 1, "got %u\n", fetched );
158                         ok( V_VT( &var ) == VT_DISPATCH, "got %u\n", V_VT( &var ) );
159                         ok( V_DISPATCH( &var ) != (IDispatch *)0xdeadbeef, "got %u\n", V_VT( &var ) );
160 
161                         dispatch = V_DISPATCH( &var );
162                         count = 0;
163                         hr = IDispatch_GetTypeInfoCount( dispatch, &count );
164                         ok( hr == S_OK, "got %x\n", hr );
165                         ok( count == 1, "got %u\n", count );
166 
167                         str = SysAllocString( manufacturerW );
168                         dispid = 0xdeadbeef;
169                         hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid );
170                         SysFreeString( str );
171                         ok( hr == S_OK, "got %x\n", hr );
172                         ok( dispid == 0x1800001 || dispid == 0x10b /* win2k */, "got %x\n", dispid );
173 
174                         str = SysAllocString( versionW );
175                         dispid = 0xdeadbeef;
176                         hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid );
177                         SysFreeString( str );
178                         ok( hr == S_OK, "got %x\n", hr );
179                         ok( dispid == 0x1800002 || dispid == 0x119 /* win2k */, "got %x\n", dispid );
180 
181                         str = SysAllocString( nosuchW );
182                         dispid = 0xdeadbeef;
183                         hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid );
184                         SysFreeString( str );
185                         ok( hr == DISP_E_UNKNOWNNAME, "got %x\n", hr );
186                         ok( dispid == DISPID_UNKNOWN, "got %x\n", dispid );
187 
188                         str = SysAllocString( manufacturerW );
189                         dispid = 0xdeadbeef;
190                         hr = IDispatch_GetIDsOfNames( dispatch, &IID_NULL, &str, 1, english, &dispid );
191                         SysFreeString( str );
192                         ok( hr == S_OK, "got %x\n", hr );
193                         ok( dispid == 0x1800001 || dispid == 0x10b /* win2k */, "got %x\n", dispid );
194 
195                         if (dispid == 0x1800001) /* crashes on win2k */
196                         {
197                             V_VT( &res ) = VT_ERROR;
198                             V_BSTR( &res ) = (BSTR)0xdeadbeef;
199                             params.rgvarg = (VARIANTARG *)0xdeadbeef;
200                             params.rgdispidNamedArgs = (DISPID *)0xdeadbeef;
201                             params.cArgs = params.cNamedArgs = 0xdeadbeef;
202                             arg_err = 0xdeadbeef;
203                             hr = IDispatch_Invoke( dispatch, DISPID_UNKNOWN, &IID_NULL, english,
204                                                    DISPATCH_METHOD|DISPATCH_PROPERTYGET,
205                                                    &params, &res, NULL, &arg_err );
206                             ok( hr == DISP_E_MEMBERNOTFOUND || hr == S_OK /* winxp */, "got %x\n", hr );
207                             ok( params.rgvarg == (VARIANTARG *)0xdeadbeef, "got %p\n", params.rgvarg );
208                             ok( params.rgdispidNamedArgs == (DISPID *)0xdeadbeef, "got %p\n", params.rgdispidNamedArgs );
209                             ok( params.cArgs == 0xdeadbeef, "got %u\n", params.cArgs );
210                             ok( params.cNamedArgs == 0xdeadbeef, "got %u\n", params.cNamedArgs );
211                             ok( V_VT( &res ) == VT_ERROR, "got %u\n", V_VT( &res ) );
212                             ok( V_ERROR( &res ) == 0xdeadbeef, "got %u\n", V_VT( &res ) );
213                             ok( arg_err == 0xdeadbeef, "got %u\n", arg_err );
214                             if (hr == S_OK) VariantClear( &res );
215                         }
216 
217                         V_VT( &res ) = VT_ERROR;
218                         V_BSTR( &res ) = (BSTR)0xdeadbeef;
219                         memset( &params, 0, sizeof(params) );
220                         hr = IDispatch_Invoke( dispatch, dispid, &IID_NULL, english,
221                                                DISPATCH_METHOD|DISPATCH_PROPERTYGET,
222                                                &params, &res, NULL, NULL );
223                         ok( hr == S_OK, "got %x\n", hr );
224                         ok( params.rgvarg == NULL, "got %p\n", params.rgvarg );
225                         ok( params.rgdispidNamedArgs == NULL, "got %p\n", params.rgdispidNamedArgs );
226                         ok( !params.cArgs, "got %u\n", params.cArgs );
227                         ok( !params.cNamedArgs, "got %u\n", params.cNamedArgs );
228                         ok( V_VT( &res ) == VT_BSTR, "got %u\n", V_VT( &res ) );
229                         ok( V_BSTR( &res ) != (BSTR)0xdeadbeef, "got %u\n", V_VT( &res ) );
230                         VariantClear( &res );
231                         VariantClear( &var );
232 
233                         fetched = 0xdeadbeef;
234                         hr = IEnumVARIANT_Next( enumvar, 1, &var, &fetched );
235                         ok( hr == S_FALSE, "got %x\n", hr );
236                         ok( !fetched, "got %u\n", fetched );
237 
238                         IEnumVARIANT_Release( enumvar );
239                     }
240                     IUnknown_Release( obj );
241                 }
242                 ISWbemObjectSet_Release( objectset );
243             }
244             IUnknown_Release( services );
245         }
246         IMoniker_Release( moniker );
247     }
248 
249     IBindCtx_Release( ctx );
250 
251     hr = CreateBindCtx( 0, &ctx );
252     ok( hr == S_OK, "got %x\n", hr );
253 
254     str = SysAllocString( stdregprovW );
255     hr = IParseDisplayName_ParseDisplayName( displayname, NULL, str, &eaten, &moniker );
256     ok( hr == S_OK, "got %x\n", hr );
257     SysFreeString( str );
258 
259     if (moniker)
260     {
261         ISWbemObject *sobj = NULL;
262         hr = IMoniker_BindToObject( moniker, ctx, NULL, &IID_ISWbemObject, (void **)&sobj );
263         ok( hr == S_OK, "got %x\n",hr );
264         if (sobj)
265         {
266             DISPID dispid = 0xdeadbeef;
267 
268             str = SysAllocString( getstringvalueW );
269             hr = ISWbemObject_GetIDsOfNames( sobj, &IID_NULL, &str, 1, english, &dispid );
270             ok( hr == S_OK, "got %x\n", hr );
271             ok( dispid == 0x1000001, "got %x\n", dispid );
272 
273             ISWbemObject_Release( sobj );
274             SysFreeString( str );
275         }
276         IMoniker_Release( moniker );
277     }
278 
279     IBindCtx_Release(ctx);
280     IParseDisplayName_Release( displayname );
281 }
282 
283 static const WCHAR localhost[] = {'l','o','c','a','l','h','o','s','t',0};
284 static const WCHAR root[] = {'r','o','o','t','\\','C','I','M','V','2',0};
285 static const WCHAR query[] = {'S','e','l','e','c','t',' ','P','r','o','c','e','s','s','o','r','I','d',' ','f','r','o','m',
286                               ' ','W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
287 static const WCHAR lang[] = {'W','Q','L',0};
288 static const WCHAR props[] = {'P','r','o','p','e','r','t','i','e','s','_',0};
289 static const WCHAR procid[] = {'P','r','o','c','e','s','s','o','r','I','d',0};
290 
291 static void test_locator(void)
292 {
293     HRESULT hr;
294     DISPID id;
295     BSTR host_bstr, root_bstr, query_bstr, lang_bstr, props_bstr, procid_bstr;
296     ISWbemLocator *locator;
297     ISWbemServices *services;
298     ISWbemObjectSet *object_set;
299     IEnumVARIANT *enum_var;
300     ISWbemObject *object;
301     ISWbemPropertySet *prop_set;
302     ISWbemProperty *prop;
303     ISWbemSecurity *security;
304     VARIANT var;
305     LONG count;
306     WbemImpersonationLevelEnum imp_level;
307     WbemAuthenticationLevelEnum auth_level;
308 
309     hr = CoCreateInstance( &CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_ISWbemLocator, (void **)&locator );
310     ok( hr == S_OK, "got %x\n", hr );
311 
312     host_bstr = SysAllocString(localhost);
313     root_bstr = SysAllocString(root);
314     hr = ISWbemLocator_ConnectServer( locator, host_bstr, root_bstr, NULL, NULL, NULL, NULL, 0, NULL, &services);
315     ok( hr == S_OK, "got %x\n", hr );
316     SysFreeString( root_bstr );
317     SysFreeString( host_bstr );
318 
319     query_bstr = SysAllocString(query);
320     lang_bstr = SysAllocString(lang);
321     hr = ISWbemServices_ExecQuery( services, query_bstr, lang_bstr, wbemFlagForwardOnly, NULL, &object_set);
322     ok( hr == S_OK, "got %x\n", hr );
323     SysFreeString( lang_bstr );
324     SysFreeString( query_bstr );
325 
326     hr = ISWbemLocator_get_Security_( locator, &security );
327     ok( hr == S_OK, "got %x\n", hr );
328     imp_level = 0xdeadbeef;
329     hr = ISWbemSecurity_get_ImpersonationLevel( security, &imp_level );
330     ok( hr == S_OK, "got %x\n", hr );
331     ok( imp_level == wbemImpersonationLevelImpersonate, "got %u\n", imp_level );
332     hr = ISWbemSecurity_put_ImpersonationLevel( security, wbemImpersonationLevelAnonymous );
333     ok( hr == S_OK, "got %x\n", hr );
334     imp_level = 0xdeadbeef;
335     hr = ISWbemSecurity_get_ImpersonationLevel( security, &imp_level );
336     ok( hr == S_OK, "got %x\n", hr );
337     ok( imp_level == wbemImpersonationLevelAnonymous, "got %u\n", imp_level );
338 
339     auth_level = 0xdeadbeef;
340     hr = ISWbemSecurity_get_AuthenticationLevel( security, &auth_level );
341     todo_wine {
342     ok( hr == WBEM_E_FAILED, "got %x\n", hr );
343     ok( auth_level == 0xdeadbeef, "got %u\n", auth_level );
344     }
345     hr = ISWbemSecurity_put_AuthenticationLevel( security, wbemAuthenticationLevelNone );
346     ok( hr == S_OK, "got %x\n", hr );
347     auth_level = 0xdeadbeef;
348     hr = ISWbemSecurity_get_AuthenticationLevel( security, &auth_level );
349     ok( hr == S_OK, "got %x\n", hr );
350     ok( auth_level == wbemAuthenticationLevelNone, "got %u\n", auth_level );
351     ISWbemSecurity_Release( security );
352     security = NULL;
353 
354     hr = ISWbemObjectSet_get__NewEnum( object_set, (IUnknown**)&enum_var );
355     ok( hr == S_OK, "got %x\n", hr );
356 
357     VariantInit( &var );
358     hr = IEnumVARIANT_Next( enum_var, 1, &var, NULL );
359     ok( hr == S_OK, "got %x\n", hr );
360     ok( V_VT(&var) == VT_DISPATCH, "got %x\n", V_VT(&var));
361 
362     props_bstr = SysAllocString( props );
363     hr = IDispatch_GetIDsOfNames( V_DISPATCH(&var), &IID_NULL, &props_bstr, 1, english, &id );
364     ok( hr == S_OK, "got %x\n", hr );
365     ok( id == 21, "got %d\n", id );
366 
367     hr = IDispatch_QueryInterface( V_DISPATCH(&var), &IID_ISWbemObject, (void**)&object );
368     ok( hr == S_OK, "got %x\n", hr );
369     VariantClear( &var );
370 
371     hr = ISWbemObject_get_Properties_( object, &prop_set );
372     ok( hr == S_OK, "got %x\n", hr );
373 
374     hr = ISWbemPropertySet_Item( prop_set, props_bstr, 0, &prop );
375     ok( hr == WBEM_E_NOT_FOUND, "got %x\n", hr );
376     SysFreeString( props_bstr );
377 
378     procid_bstr = SysAllocString( procid );
379     hr = ISWbemPropertySet_Item( prop_set, procid_bstr, 0, &prop );
380     ok( hr == S_OK, "got %x\n", hr );
381     SysFreeString( procid_bstr );
382 
383     count = 0;
384     hr = ISWbemPropertySet_get_Count( prop_set, &count );
385     ok( hr == S_OK, "got %x\n", hr );
386     ok( count > 0, "got %d\n", count );
387 
388     hr = ISWbemProperty_get_Value( prop, &var );
389     ok( hr == S_OK, "got %x\n", hr );
390     ok( V_VT(&var) == VT_BSTR, "got %x\n", V_VT(&var) );
391     VariantClear( &var );
392 
393     hr = ISWbemServices_get_Security_( services, &security );
394     ok( hr == S_OK, "got %x\n", hr );
395     imp_level = 0xdeadbeef;
396     hr = ISWbemSecurity_get_ImpersonationLevel( security, &imp_level );
397     ok( hr == S_OK, "got %x\n", hr );
398     ok( imp_level == wbemImpersonationLevelImpersonate, "got %u\n", imp_level );
399     auth_level = 0xdeadbeef;
400     hr = ISWbemSecurity_get_AuthenticationLevel( security, &auth_level );
401     ok( hr == S_OK, "got %x\n", hr );
402     ok( auth_level == wbemAuthenticationLevelPktPrivacy, "got %u\n", auth_level );
403 
404     ISWbemSecurity_Release(security);
405     ISWbemProperty_Release( prop );
406     ISWbemPropertySet_Release( prop_set );
407     ISWbemObject_Release( object );
408     IEnumVARIANT_Release( enum_var );
409     ISWbemObjectSet_Release( object_set );
410     ISWbemServices_Release( services );
411     ISWbemLocator_Release( locator );
412 }
413 
414 START_TEST(wbemdisp)
415 {
416     CoInitialize( NULL );
417 
418     test_ParseDisplayName();
419     test_locator();
420 
421     CoUninitialize();
422 }
423