Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/cfgmgr32/tests/cfgmgr32.c
8887 views
1
/*
2
* Copyright (C) 2023 Mohamad Al-Jaf
3
* Copyright (C) 2025 Vibhav Pant
4
*
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Lesser General Public
7
* License as published by the Free Software Foundation; either
8
* version 2.1 of the License, or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18
*/
19
20
#include <stddef.h>
21
#include <stdarg.h>
22
23
#include "ntstatus.h"
24
#define WIN32_NO_STATUS
25
#include "windef.h"
26
#include "winbase.h"
27
28
#include "winreg.h"
29
#include "winuser.h"
30
#include "winternl.h"
31
#include "objbase.h"
32
#include "devguid.h"
33
#include "initguid.h"
34
#include "devpkey.h"
35
#include "propkey.h"
36
#include "setupapi.h"
37
#include "cfgmgr32.h"
38
#include "ntddvdeo.h"
39
#include "devfiltertypes.h"
40
#include "devquery.h"
41
#include "ddk/hidclass.h"
42
43
#include "wine/test.h"
44
45
static const char *debugstr_ok( const char *cond )
46
{
47
int c, n = 0;
48
/* skip possible casts */
49
while ((c = *cond++))
50
{
51
if (c == '(') n++;
52
if (!n) break;
53
if (c == ')') n--;
54
}
55
if (!strchr( cond - 1, '(' )) return wine_dbg_sprintf( "got %s", cond - 1 );
56
return wine_dbg_sprintf( "%.*s returned", (int)strcspn( cond - 1, "( " ), cond - 1 );
57
}
58
59
#define ok_wcs( e, r ) \
60
do \
61
{ \
62
const WCHAR *v = (r); \
63
ok( !wcscmp( v, (e) ), "%s %s\n", debugstr_ok(#r), debugstr_w(v) ); \
64
} while (0)
65
#define ok_str( e, r ) \
66
do \
67
{ \
68
const char *v = (r); \
69
ok( !strcmp( v, (e) ), "%s %s\n", debugstr_ok(#r), debugstr_a(v) ); \
70
} while (0)
71
#define ok_ex( r, op, e, t, f, ... ) \
72
do \
73
{ \
74
t v = (r); \
75
ok( v op (e), "%s " f "\n", debugstr_ok( #r ), v, ##__VA_ARGS__ ); \
76
} while (0)
77
#define ok_u4( r, op, e ) ok_ex( r, op, e, UINT, "%u" )
78
#define ok_x4( r, op, e ) ok_ex( r, op, e, UINT, "%#x" )
79
80
static const WCHAR *guid_string( const GUID *guid, WCHAR *buffer, UINT length )
81
{
82
swprintf( buffer, length, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
83
guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2],
84
guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
85
return buffer;
86
}
87
88
static void test_CM_MapCrToWin32Err(void)
89
{
90
unsigned int i;
91
DWORD ret;
92
93
static const struct
94
{
95
CONFIGRET code;
96
DWORD win32_error;
97
}
98
map_codes[] =
99
{
100
{ CR_SUCCESS, ERROR_SUCCESS },
101
{ CR_OUT_OF_MEMORY, ERROR_NOT_ENOUGH_MEMORY },
102
{ CR_INVALID_POINTER, ERROR_INVALID_USER_BUFFER },
103
{ CR_INVALID_FLAG, ERROR_INVALID_FLAGS },
104
{ CR_INVALID_DEVNODE, ERROR_INVALID_DATA },
105
{ CR_INVALID_DEVINST, ERROR_INVALID_DATA },
106
{ CR_NO_SUCH_DEVNODE, ERROR_NOT_FOUND },
107
{ CR_NO_SUCH_DEVINST, ERROR_NOT_FOUND },
108
{ CR_ALREADY_SUCH_DEVNODE, ERROR_ALREADY_EXISTS },
109
{ CR_ALREADY_SUCH_DEVINST, ERROR_ALREADY_EXISTS },
110
{ CR_BUFFER_SMALL, ERROR_INSUFFICIENT_BUFFER },
111
{ CR_NO_REGISTRY_HANDLE, ERROR_INVALID_HANDLE },
112
{ CR_REGISTRY_ERROR, ERROR_REGISTRY_CORRUPT },
113
{ CR_INVALID_DEVICE_ID, ERROR_INVALID_DATA },
114
{ CR_NO_SUCH_VALUE, ERROR_NOT_FOUND },
115
{ CR_NO_SUCH_REGISTRY_KEY, ERROR_FILE_NOT_FOUND },
116
{ CR_INVALID_MACHINENAME, ERROR_INVALID_DATA },
117
{ CR_REMOTE_COMM_FAILURE, ERROR_SERVICE_NOT_ACTIVE },
118
{ CR_MACHINE_UNAVAILABLE, ERROR_SERVICE_NOT_ACTIVE },
119
{ CR_NO_CM_SERVICES, ERROR_SERVICE_NOT_ACTIVE },
120
{ CR_ACCESS_DENIED, ERROR_ACCESS_DENIED },
121
{ CR_CALL_NOT_IMPLEMENTED, ERROR_CALL_NOT_IMPLEMENTED },
122
{ CR_INVALID_PROPERTY, ERROR_INVALID_DATA },
123
{ CR_NO_SUCH_DEVICE_INTERFACE, ERROR_NOT_FOUND },
124
{ CR_INVALID_REFERENCE_STRING, ERROR_INVALID_DATA },
125
{ CR_DEFAULT, 0xdeadbeef },
126
{ CR_INVALID_RES_DES, 0xdeadbeef },
127
{ CR_INVALID_LOG_CONF, 0xdeadbeef },
128
{ CR_INVALID_ARBITRATOR, 0xdeadbeef },
129
{ CR_INVALID_NODELIST, 0xdeadbeef },
130
{ CR_DEVNODE_HAS_REQS, 0xdeadbeef },
131
{ CR_DEVINST_HAS_REQS, 0xdeadbeef },
132
{ CR_INVALID_RESOURCEID, 0xdeadbeef },
133
{ CR_DLVXD_NOT_FOUND, 0xdeadbeef },
134
{ CR_NO_MORE_LOG_CONF, 0xdeadbeef },
135
{ CR_NO_MORE_RES_DES, 0xdeadbeef },
136
{ CR_INVALID_RANGE_LIST, 0xdeadbeef },
137
{ CR_INVALID_RANGE, 0xdeadbeef },
138
{ CR_FAILURE, 0xdeadbeef },
139
{ CR_NO_SUCH_LOGICAL_DEV, 0xdeadbeef },
140
{ CR_CREATE_BLOCKED, 0xdeadbeef },
141
{ CR_NOT_SYSTEM_VM, 0xdeadbeef },
142
{ CR_REMOVE_VETOED, 0xdeadbeef },
143
{ CR_APM_VETOED, 0xdeadbeef },
144
{ CR_INVALID_LOAD_TYPE, 0xdeadbeef },
145
{ CR_NO_ARBITRATOR, 0xdeadbeef },
146
{ CR_INVALID_DATA, 0xdeadbeef },
147
{ CR_INVALID_API, 0xdeadbeef },
148
{ CR_DEVLOADER_NOT_READY, 0xdeadbeef },
149
{ CR_NEED_RESTART, 0xdeadbeef },
150
{ CR_NO_MORE_HW_PROFILES, 0xdeadbeef },
151
{ CR_DEVICE_NOT_THERE, 0xdeadbeef },
152
{ CR_WRONG_TYPE, 0xdeadbeef },
153
{ CR_INVALID_PRIORITY, 0xdeadbeef },
154
{ CR_NOT_DISABLEABLE, 0xdeadbeef },
155
{ CR_FREE_RESOURCES, 0xdeadbeef },
156
{ CR_QUERY_VETOED, 0xdeadbeef },
157
{ CR_CANT_SHARE_IRQ, 0xdeadbeef },
158
{ CR_NO_DEPENDENT, 0xdeadbeef },
159
{ CR_SAME_RESOURCES, 0xdeadbeef },
160
{ CR_DEVICE_INTERFACE_ACTIVE, 0xdeadbeef },
161
{ CR_INVALID_CONFLICT_LIST, 0xdeadbeef },
162
{ CR_INVALID_INDEX, 0xdeadbeef },
163
{ CR_INVALID_STRUCTURE_SIZE, 0xdeadbeef },
164
{ NUM_CR_RESULTS, 0xdeadbeef },
165
};
166
167
for ( i = 0; i < ARRAY_SIZE(map_codes); i++ )
168
{
169
ret = CM_MapCrToWin32Err( map_codes[i].code, 0xdeadbeef );
170
ok( ret == map_codes[i].win32_error, "%#lx returned unexpected %ld.\n", map_codes[i].code, ret );
171
}
172
}
173
174
HRESULT (WINAPI *pDevCreateObjectQuery)(DEV_OBJECT_TYPE, ULONG, ULONG, const DEVPROPCOMPKEY*, ULONG,
175
const DEVPROP_FILTER_EXPRESSION*, PDEV_QUERY_RESULT_CALLBACK, void*, HDEVQUERY*);
176
void (WINAPI *pDevCloseObjectQuery)(HDEVQUERY);
177
HRESULT (WINAPI *pDevGetObjects)(DEV_OBJECT_TYPE, ULONG, ULONG, const DEVPROPCOMPKEY*, ULONG,
178
const DEVPROP_FILTER_EXPRESSION*, ULONG*, const DEV_OBJECT**);
179
void (WINAPI *pDevFreeObjects)(ULONG, const DEV_OBJECT*);
180
HRESULT (WINAPI *pDevGetObjectProperties)(DEV_OBJECT_TYPE, const WCHAR *, ULONG, ULONG, const DEVPROPCOMPKEY *, ULONG *,
181
const DEVPROPERTY **);
182
void (WINAPI *pDevFreeObjectProperties)(ULONG, const DEVPROPERTY *);
183
const DEVPROPERTY* (WINAPI *pDevFindProperty)(const DEVPROPKEY *, DEVPROPSTORE, PCWSTR, ULONG, const DEVPROPERTY *);
184
185
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
186
187
static void test_CM_Get_Device_ID_List(void)
188
{
189
struct
190
{
191
WCHAR id[128];
192
DEVINST inst;
193
}
194
instances[128];
195
SP_DEVINFO_DATA device = { sizeof(device) };
196
unsigned int i, count, expected_count;
197
WCHAR wguid_str[64], id[128], *wbuf, *wp;
198
char guid_str[64], id_a[128], *buf, *p;
199
DEVINST devinst;
200
CONFIGRET ret;
201
HDEVINFO set;
202
ULONG len;
203
204
StringFromGUID2(&GUID_DEVCLASS_DISPLAY, wguid_str, ARRAY_SIZE(wguid_str));
205
wp = wguid_str;
206
p = guid_str;
207
while ((*p++ = *wp++))
208
;
209
210
ret = CM_Get_Device_ID_List_SizeW(NULL, wguid_str, CM_GETIDLIST_FILTER_CLASS);
211
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
212
len = 0xdeadbeef;
213
ret = CM_Get_Device_ID_List_SizeW(&len, NULL, CM_GETIDLIST_FILTER_CLASS);
214
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
215
ok(!len, "got %#lx.\n", len);
216
len = 0xdeadbeef;
217
ret = CM_Get_Device_ID_List_SizeW(&len, L"q", CM_GETIDLIST_FILTER_CLASS);
218
ok(ret == CR_INVALID_DATA, "got %#lx.\n", ret);
219
ok(!len, "got %#lx.\n", len);
220
221
ret = CM_Get_Device_ID_List_SizeA(NULL, guid_str, CM_GETIDLIST_FILTER_CLASS);
222
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
223
len = 0xdeadbeef;
224
ret = CM_Get_Device_ID_List_SizeA(&len, NULL, CM_GETIDLIST_FILTER_CLASS);
225
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
226
ok(!len, "got %#lx.\n", len);
227
len = 0xdeadbeef;
228
ret = CM_Get_Device_ID_List_SizeA(&len, "q", CM_GETIDLIST_FILTER_CLASS);
229
ok(ret == CR_INVALID_DATA, "got %#lx.\n", ret);
230
ok(!len, "got %#lx.\n", len);
231
232
len = 0xdeadbeef;
233
ret = CM_Get_Device_ID_List_SizeW(&len, NULL, 0);
234
ok(!ret, "got %#lx.\n", ret);
235
ok(len > 2, "got %#lx.\n", len);
236
237
wbuf = malloc(len * sizeof(*wbuf));
238
buf = malloc(len);
239
240
ret = CM_Get_Device_ID_ListW(NULL, wbuf, len, 0);
241
ok(!ret, "got %#lx.\n", ret);
242
243
len = 0xdeadbeef;
244
ret = CM_Get_Device_ID_List_SizeW(&len, wguid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
245
ok(!ret, "got %#lx.\n", ret);
246
ok(len > 2, "got %lu.\n", len);
247
memset(wbuf, 0xcc, len * sizeof(*wbuf));
248
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, 0, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
249
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
250
ok(wbuf[0] == 0xcccc, "got %#x.\n", wbuf[0]);
251
memset(wbuf, 0xcc, len * sizeof(*wbuf));
252
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, 1, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
253
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
254
ok(!wbuf[0], "got %#x.\n", wbuf[0]);
255
256
len = 0xdeadbeef;
257
ret = CM_Get_Device_ID_List_SizeA(&len, guid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
258
ok(!ret, "got %#lx.\n", ret);
259
ok(len > 2, "got %lu.\n", len);
260
memset(buf, 0x7c, len);
261
ret = CM_Get_Device_ID_ListA(guid_str, buf, 0, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
262
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
263
ok(buf[0] == 0x7c, "got %#x.\n", buf[0]);
264
memset(buf, 0x7c, len);
265
ret = CM_Get_Device_ID_ListA(guid_str, buf, 1, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
266
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
267
ok(buf[0] == 0x7c, "got %#x.\n", buf[0]);
268
269
set = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
270
ok(set != &GUID_DEVCLASS_DISPLAY, "got error %#lx.\n", GetLastError());
271
for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i)
272
{
273
ok(i < ARRAY_SIZE(instances), "got %u.\n", i);
274
ret = SetupDiGetDeviceInstanceIdW(set, &device, instances[i].id, sizeof(instances[i].id), NULL);
275
ok(ret, "got error %#lx.\n", GetLastError());
276
instances[i].inst = device.DevInst;
277
}
278
SetupDiDestroyDeviceInfoList(set);
279
expected_count = i;
280
ok(expected_count, "got 0.\n");
281
282
wcscpy(id, L"q");
283
devinst = 0xdeadbeef;
284
ret = CM_Locate_DevNodeW(&devinst, id, 0);
285
todo_wine_if(ret == CR_NO_SUCH_DEVNODE) ok(ret == CR_INVALID_DEVICE_ID, "got %#lx.\n", ret);
286
ok(!devinst, "got %#lx.\n", devinst);
287
288
wcscpy(id, instances[0].id);
289
id[0] = 'Q';
290
ret = CM_Locate_DevNodeW(&devinst, id, 0);
291
ok(ret == CR_NO_SUCH_DEVNODE, "got %#lx.\n", ret);
292
293
for (i = 0; i < expected_count; ++i)
294
{
295
DEVPROPTYPE type;
296
ULONG size;
297
298
*id = 0;
299
ret = CM_Get_Device_IDW(instances[i].inst, id, ARRAY_SIZE(id), 0);
300
ok(!ret, "got %#lx.\n", ret);
301
ok(!wcscmp(id, instances[i].id), "got %s, expected %s.\n", debugstr_w(id), debugstr_w(instances[i].id));
302
size = len;
303
ret = CM_Get_DevNode_PropertyW(instances[i].inst, &DEVPROPKEY_GPU_LUID, &type, (BYTE *)wbuf, &size, 0);
304
ok(!ret || ret == CR_NO_SUCH_VALUE, "got %#lx.\n", ret);
305
if (!ret)
306
ok(type == DEVPROP_TYPE_UINT64, "got %#lx.\n", type);
307
308
devinst = 0xdeadbeef;
309
ret = CM_Locate_DevNodeW(&devinst, instances[i].id, 0);
310
ok(!ret, "got %#lx, id %s.\n", ret, debugstr_w(instances[i].id));
311
ok(devinst == instances[i].inst, "got %#lx, expected %#lx.\n", devinst, instances[i].inst);
312
p = id_a;
313
wp = instances[i].id;
314
while((*p++ = *wp++))
315
;
316
devinst = 0xdeadbeef;
317
ret = CM_Locate_DevNodeA(&devinst, id_a, 0);
318
ok(!ret, "got %#lx, id %s.\n", ret, debugstr_a(id_a));
319
ok(devinst == instances[i].inst, "got %#lx, expected %#lx.\n", devinst, instances[i].inst);
320
}
321
322
memset(wbuf, 0xcc, len * sizeof(*wbuf));
323
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
324
ok(!ret, "got %#lx.\n", ret);
325
count = 0;
326
wp = wbuf;
327
while (*wp)
328
{
329
++count;
330
ok(!wcsnicmp(wp, L"PCI\\", 4) || !wcsnicmp(wp, L"VMBUS\\", 6), "got %s.\n", debugstr_w(wp));
331
wp += wcslen(wp) + 1;
332
}
333
ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
334
335
memset(buf, 0xcc, len * sizeof(*buf));
336
ret = CM_Get_Device_ID_ListA(guid_str, buf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
337
ok(!ret, "got %#lx.\n", ret);
338
count = 0;
339
p = buf;
340
while (*p)
341
{
342
++count;
343
ok(!strnicmp(p, "PCI\\", 4) || !strnicmp(p, "VMBUS\\", 6), "got %s.\n", debugstr_a(p));
344
p += strlen(p) + 1;
345
}
346
ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
347
348
free(wbuf);
349
free(buf);
350
}
351
352
DWORD WINAPI notify_callback( HCMNOTIFICATION notify, void *ctx, CM_NOTIFY_ACTION action,
353
CM_NOTIFY_EVENT_DATA *data, DWORD size )
354
{
355
return ERROR_SUCCESS;
356
}
357
358
static void test_CM_Register_Notification( void )
359
{
360
struct
361
{
362
CM_NOTIFY_FILTER filter;
363
CONFIGRET ret;
364
} test_cases[] = {
365
{
366
{ 0, CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0 },
367
CR_INVALID_DATA
368
},
369
{
370
{ sizeof( CM_NOTIFY_FILTER ) + 1, 0, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0,
371
.u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
372
CR_INVALID_DATA
373
},
374
{
375
{ sizeof( CM_NOTIFY_FILTER ), CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES,
376
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0, .u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
377
CR_INVALID_DATA
378
},
379
{
380
{ sizeof( CM_NOTIFY_FILTER ), CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES,
381
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0 },
382
CR_SUCCESS
383
},
384
{
385
{ sizeof( CM_NOTIFY_FILTER ), 0, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0,
386
.u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
387
CR_SUCCESS
388
}
389
};
390
DWORD (WINAPI *pCM_Register_Notification)(PCM_NOTIFY_FILTER,PVOID,PCM_NOTIFY_CALLBACK,PHCMNOTIFICATION) = NULL;
391
DWORD (WINAPI *pCM_Unregister_Notification)(HCMNOTIFICATION) = NULL;
392
HMODULE cfgmgr32 = GetModuleHandleW( L"cfgmgr32" );
393
DWORD i;
394
HCMNOTIFICATION notify = NULL;
395
CONFIGRET ret;
396
397
if (cfgmgr32)
398
{
399
pCM_Register_Notification = (void *)GetProcAddress( cfgmgr32, "CM_Register_Notification" );
400
pCM_Unregister_Notification = (void *)GetProcAddress( cfgmgr32, "CM_Unregister_Notification" );
401
}
402
403
if (!pCM_Register_Notification)
404
{
405
win_skip( "CM_Register_Notification not found, skipping tests\n" );
406
return;
407
}
408
409
ret = pCM_Register_Notification( NULL, NULL, NULL, NULL );
410
ok( ret == CR_FAILURE, "Expected 0x13, got %#lx.\n", ret );
411
412
ret = pCM_Register_Notification( NULL, NULL, NULL, &notify );
413
ok( ret == CR_INVALID_DATA, "Expected 0x1f, got %#lx.\n", ret );
414
ok( !notify, "Expected handle to be NULL, got %p\n", notify );
415
416
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
417
{
418
notify = NULL;
419
winetest_push_context( "test_cases %lu", i );
420
ret = pCM_Register_Notification( &test_cases[i].filter, NULL, notify_callback, &notify );
421
ok( test_cases[i].ret == ret, "Expected %#lx, got %#lx\n", test_cases[i].ret, ret );
422
if (test_cases[i].ret)
423
ok( !notify, "Expected handle to be NULL, got %p\n", notify );
424
if (notify)
425
{
426
ret = pCM_Unregister_Notification( notify );
427
ok( !ret, "Expected 0, got %#lx\n", ret );
428
}
429
winetest_pop_context();
430
}
431
}
432
433
static void check_device_path_casing(const WCHAR *original_path)
434
{
435
HKEY current_key, tmp;
436
WCHAR *path = wcsdup(original_path);
437
WCHAR key_name[MAX_PATH];
438
WCHAR separator[] = L"#";
439
WCHAR *token, *context = NULL;
440
LSTATUS ret;
441
DWORD i;
442
443
ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum", &current_key);
444
ok(!ret, "Failed to open enum key: %#lx.\n", ret);
445
446
token = wcstok_s(path + 4, separator, &context); /* skip \\?\ */
447
while (token)
448
{
449
if (token[0] == L'{' && wcslen(token) == 38) break; /* reached GUID part, done */
450
451
i = 0;
452
while (!(ret = RegEnumKeyW(current_key, i++, key_name, ARRAY_SIZE(key_name))))
453
{
454
if(!wcscmp(token, key_name))
455
{
456
ret = RegOpenKeyW(current_key, token, &tmp);
457
ok(!ret, "Failed to open registry key %s: %#lx.\n", debugstr_w(token), ret);
458
RegCloseKey(current_key);
459
current_key = tmp;
460
break;
461
}
462
}
463
ok(!ret, "Failed to find %s in registry: %#lx.\n", debugstr_w(token), ret);
464
if (ret) break;
465
466
token = wcstok_s(NULL, separator, &context);
467
}
468
469
RegCloseKey(current_key);
470
free(path);
471
}
472
473
static void test_CM_Get_Device_Interface_List(void)
474
{
475
BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)];
476
SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
477
SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data;
478
SP_DEVINFO_DATA device = { sizeof(device) };
479
WCHAR instance_id[256], expected_id[256];
480
DEVPROPKEY zero_key = {{0}, 0};
481
unsigned int count, count2;
482
char *buffera, *pa;
483
WCHAR *buffer, *p;
484
ULONG size, size2;
485
DEVPROPTYPE type;
486
CONFIGRET ret;
487
HDEVINFO set;
488
GUID guid;
489
BOOL bret;
490
491
guid = GUID_DEVINTERFACE_DISPLAY_ADAPTER;
492
493
ret = CM_Get_Device_Interface_List_SizeW(&size, &guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
494
ok(!ret, "got %#lx.\n", ret);
495
496
buffer = malloc(size * sizeof(*buffer));
497
ret = CM_Get_Device_Interface_ListW( &guid, NULL, buffer, size, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
498
ok(!ret, "got %#lx.\n", ret);
499
500
ret = CM_Get_Device_Interface_List_SizeA(&size2, &guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
501
ok(!ret, "got %#lx.\n", ret);
502
ok(size2 == size, "got %lu, %lu.\n", size, size2);
503
buffera = malloc(size2 * sizeof(*buffera));
504
ret = CM_Get_Device_Interface_ListA(&guid, NULL, buffera, size2, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
505
ok(!ret, "got %#lx.\n", ret);
506
p = malloc(size2 * sizeof(*p));
507
memset(p, 0xcc, size2 * sizeof(*p));
508
pa = buffera;
509
*p = 0;
510
while (*pa)
511
{
512
MultiByteToWideChar(CP_ACP, 0, pa, -1, p + (pa - buffera), size2 - (pa - buffera));
513
pa += strlen(pa) + 1;
514
}
515
p[pa - buffera] = 0;
516
ok(!memcmp(p, buffer, size * sizeof(*p)), "results differ, %s, %s.\n", debugstr_wn(p, size), debugstr_wn(buffer, size));
517
free(p);
518
free(buffera);
519
520
iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer;
521
522
count = 0;
523
p = buffer;
524
while (*p)
525
{
526
DEVPROP_BOOLEAN val = DEVPROP_FALSE;
527
528
check_device_path_casing(p);
529
set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
530
ok(set != INVALID_HANDLE_VALUE, "got %p.\n", set);
531
bret = SetupDiOpenDeviceInterfaceW(set, p, 0, &iface);
532
ok(bret, "got error %lu.\n", GetLastError());
533
memset(iface_detail_buffer, 0xcc, sizeof(iface_detail_buffer));
534
iface_data->cbSize = sizeof(*iface_data);
535
bret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, sizeof(iface_detail_buffer), NULL, &device);
536
ok(bret, "got error %lu.\n", GetLastError());
537
ok(!wcsicmp(iface_data->DevicePath, p), "got %s, expected %s.\n", debugstr_w(p), debugstr_w(iface_data->DevicePath));
538
bret = SetupDiGetDeviceInstanceIdW(set, &device, expected_id, ARRAY_SIZE(expected_id), NULL);
539
ok(bret, "got error %lu.\n", GetLastError());
540
SetupDiDestroyDeviceInfoList(set);
541
542
size = 0xdeadbeef;
543
type = 0xdeadbeef;
544
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
545
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
546
ok(type == 0xdeadbeef, "got type %#lx.\n", type);
547
ok(size == 0xdeadbeef, "got %#lx.\n", size);
548
549
size = 0;
550
type = 0xdeadbeef;
551
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
552
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
553
ok(type == DEVPROP_TYPE_STRING, "got type %#lx.\n", type);
554
ok(size && size != 0xdeadbeef, "got %#lx.\n", size);
555
556
ret = CM_Get_Device_Interface_PropertyW(p, NULL, &type, (BYTE *)instance_id, &size, 0);
557
ok(ret == CR_FAILURE, "got %#lx.\n", ret);
558
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, NULL, (BYTE *)instance_id, &size, 0);
559
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
560
ret = CM_Get_Device_Interface_PropertyW(NULL, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
561
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
562
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, NULL, 0);
563
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
564
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 1);
565
ok(ret == CR_INVALID_FLAG, "got %#lx.\n", ret);
566
567
size = 0;
568
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
569
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
570
571
--size;
572
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
573
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
574
575
type = 0xdeadbeef;
576
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
577
ok(!ret, "got %#lx.\n", ret);
578
ok(type == DEVPROP_TYPE_STRING, "got type %#lx.\n", type);
579
ok(!wcsicmp(instance_id, expected_id), "got %s, expected %s.\n", debugstr_w(instance_id), debugstr_w(expected_id));
580
581
type = 0xdeadbeef;
582
size = sizeof(val);
583
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_DeviceInterface_Enabled, &type, (BYTE *)&val, &size, 0);
584
ok(!ret, "got %#lx.\n", ret);
585
ok(type == DEVPROP_TYPE_BOOLEAN, "got type %#lx.\n", type);
586
ok(size == sizeof(val), "got size %lu.\n", size);
587
ok(val == DEVPROP_TRUE, "got val %d.\n", val);
588
589
size = 0;
590
ret = CM_Get_Device_Interface_PropertyW(p, &zero_key, &type, NULL, &size, 0);
591
ok(ret == CR_NO_SUCH_VALUE, "got %#lx.\n", ret);
592
p += wcslen(p) + 1;
593
++count;
594
}
595
596
free(buffer);
597
598
set = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
599
ok(set != INVALID_HANDLE_VALUE, "got %p.\n", set);
600
for (count2 = 0; SetupDiEnumDeviceInterfaces(set, NULL, &guid, count2, &iface); ++count2)
601
;
602
SetupDiDestroyDeviceInfoList(set);
603
ok(count == count2, "got %u, expected %u.\n", count, count2);
604
605
ret = CM_Get_Device_Interface_PropertyW(L"qqq", &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
606
ok(ret == CR_NO_SUCH_DEVICE_INTERFACE || broken(ret == CR_INVALID_DATA) /* w7 */, "got %#lx.\n", ret);
607
}
608
609
struct test_property
610
{
611
DEVPROPKEY key;
612
DEVPROPTYPE type;
613
};
614
615
DEFINE_DEVPROPKEY(DEVPKEY_dummy, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 1);
616
617
static BOOL dev_property_val_equal( const DEVPROPERTY *p1, const DEVPROPERTY *p2 )
618
{
619
if (!(p1->Type == p2->Type && p1->BufferSize == p2->BufferSize))
620
return FALSE;
621
switch (p1->Type)
622
{
623
case DEVPROP_TYPE_STRING:
624
return !wcsicmp( (WCHAR *)p1->Buffer, (WCHAR *)p2->Buffer );
625
default:
626
return !memcmp( p1->Buffer, p2->Buffer, p1->BufferSize );
627
}
628
}
629
630
static const char *debugstr_DEVPROP_val( const DEVPROPERTY *prop )
631
{
632
switch (prop->Type)
633
{
634
case DEVPROP_TYPE_STRING:
635
return wine_dbg_sprintf( "{type=%#lx buf=%s buf_len=%lu}", prop->Type, debugstr_w( prop->Buffer ), prop->BufferSize );
636
default:
637
return wine_dbg_sprintf( "{type=%#lx buf=%p buf_len=%lu}", prop->Type, prop->Buffer, prop->BufferSize );
638
}
639
}
640
641
static const char *debugstr_DEVPROPKEY( const DEVPROPKEY *key )
642
{
643
if (!key) return "(null)";
644
return wine_dbg_sprintf( "{%s, %04lx}", debugstr_guid( &key->fmtid ), key->pid );
645
}
646
647
static const char *debugstr_DEVPROPCOMPKEY( const DEVPROPCOMPKEY *key )
648
{
649
if (!key) return "(null)";
650
return wine_dbg_sprintf( "{%s, %d, %s}", debugstr_DEVPROPKEY( &key->Key ), key->Store,
651
debugstr_w( key->LocaleName ) );
652
}
653
654
static void test_DevGetObjectProperties( DEV_OBJECT_TYPE type, const WCHAR *id, const DEVPROPERTY *exp_props, ULONG props_len )
655
{
656
DEVPROPCOMPKEY dummy_propcompkey = { DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL };
657
ULONG buf_len, rem_props = props_len, i;
658
const DEVPROPERTY *buf;
659
DEVPROPCOMPKEY *keys;
660
HRESULT hr;
661
662
if (!pDevGetObjectProperties || !pDevFreeObjectProperties || !pDevFindProperty)
663
{
664
win_skip( "Functions unavailable, skipping test. (%p %p %p)\n", pDevGetObjects, pDevFreeObjects, pDevFindProperty );
665
return;
666
}
667
668
hr = pDevGetObjectProperties( type, id, DevQueryFlagUpdateResults, 0, NULL, NULL, NULL );
669
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
670
671
hr = pDevGetObjectProperties( type, id, DevQueryFlagAsyncClose, 0, NULL, &buf_len, &buf );
672
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
673
674
hr = pDevGetObjectProperties( type, id, DevQueryFlagAsyncClose, 0, NULL, &buf_len, &buf );
675
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
676
677
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 1, NULL, &buf_len, &buf );
678
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
679
680
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 0, (DEVPROPCOMPKEY *)0xdeadbeef, &buf_len, &buf );
681
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
682
683
buf = NULL;
684
buf_len = 0;
685
hr = pDevGetObjectProperties( type, id, DevQueryFlagAllProperties, 0, NULL, &buf_len, &buf );
686
ok( hr == S_OK, "got hr %#lx\n", hr );
687
ok( buf_len == props_len, "%lu != %lu\n", buf_len, props_len );
688
for (i = 0; i < props_len; i++)
689
{
690
ULONG j;
691
for (j = 0; j < buf_len; j++)
692
{
693
if (IsEqualDevPropKey( exp_props[i].CompKey.Key, buf[j].CompKey.Key ) && rem_props)
694
{
695
winetest_push_context( "%s", debugstr_DEVPROPKEY( &exp_props[i].CompKey.Key ) );
696
/* ItemNameDisplay for software devices has different values for properties obtained from DevGetObjects
697
* and DevGetObjectProperties. */
698
if (!IsEqualDevPropKey(PKEY_ItemNameDisplay, buf[j].CompKey.Key))
699
{
700
const DEVPROPERTY *found_prop;
701
702
ok( dev_property_val_equal( &exp_props[i], &buf[j] ), "%s != %s\n", debugstr_DEVPROP_val( &buf[j] ),
703
debugstr_DEVPROP_val( &exp_props[i] ) );
704
found_prop = pDevFindProperty( &exp_props[i].CompKey.Key, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
705
ok( found_prop == &buf[i], "got found_prop %p != %p\n", found_prop, &buf[i] );
706
}
707
winetest_pop_context();
708
rem_props--;
709
}
710
}
711
}
712
ok( rem_props == 0, "got rem_props %lu\n", rem_props );
713
pDevFreeObjectProperties( buf_len, buf );
714
715
buf = (DEVPROPERTY *)0xdeadbeef;
716
buf_len = 0xdeadbeef;
717
rem_props = props_len;
718
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 0, NULL, &buf_len, &buf );
719
ok( hr == S_OK, "got hr %#lx\n", hr );
720
ok( buf_len == 0, "got buf_len %lu\n", buf_len );
721
ok( !buf, "got buf %p\n", buf );
722
723
buf = NULL;
724
buf_len = 0;
725
keys = calloc( props_len, sizeof( *keys ) );
726
for (i = 0; i < props_len; i++)
727
keys[i] = exp_props[i].CompKey;
728
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, props_len, keys, &buf_len, &buf );
729
ok( hr == S_OK, "got hr %#lx\n", hr );
730
ok( buf_len == props_len, "%lu != %lu\n", buf_len, props_len );
731
for (i = 0; i < props_len; i++)
732
{
733
ULONG j;
734
for (j = 0; j < buf_len; j++)
735
{
736
if (IsEqualDevPropKey( exp_props[i].CompKey.Key, buf[j].CompKey.Key ))
737
{
738
const DEVPROPERTY *found_prop;
739
740
winetest_push_context( "%s", debugstr_DEVPROPKEY( &exp_props[i].CompKey.Key ) );
741
rem_props--;
742
found_prop = pDevFindProperty( &exp_props[i].CompKey.Key, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
743
ok( found_prop == &buf[j], "got found_prop %p != %p\n", found_prop, &buf[j] );
744
winetest_pop_context();
745
break;
746
}
747
}
748
}
749
ok( rem_props == 0, "got rem_props %lu\n", rem_props );
750
pDevFreeObjectProperties( buf_len, buf );
751
752
buf_len = 0;
753
buf = NULL;
754
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 1, &dummy_propcompkey, &buf_len, &buf );
755
ok( hr == S_OK, "got hr %#lx\n", hr );
756
ok( !!buf, "got buf %p\n", buf );
757
ok( buf_len == 1, "got buf_len %lu\n", buf_len );
758
if (buf)
759
{
760
const DEVPROPERTY *found_prop;
761
762
ok( IsEqualDevPropKey( buf[0].CompKey.Key, DEVPKEY_dummy ), "got propkey {%s, %#lx}\n",
763
debugstr_guid( &buf[0].CompKey.Key.fmtid ), buf[0].CompKey.Key.pid );
764
ok( buf[0].Type == DEVPROP_TYPE_EMPTY, "got Type %#lx\n", buf[0].Type );
765
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
766
ok( found_prop == &buf[0], "got found_prop %p != %p\n", found_prop, &buf[0] );
767
pDevFreeObjectProperties( buf_len, buf );
768
}
769
free( keys );
770
}
771
772
static void test_dev_object_iface_props( int line, const DEV_OBJECT *obj, const struct test_property *exp_props,
773
DWORD props_len )
774
{
775
DWORD i, err, rem_props = props_len;
776
HDEVINFO set;
777
778
set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL );
779
ok_( __FILE__, line )( set != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed: %lu\n",
780
GetLastError() );
781
ok_( __FILE__, line )( obj->cPropertyCount >= props_len, "got cPropertyCount %lu, should be >= %lu\n",
782
obj->cPropertyCount, props_len );
783
for (i = 0; i < obj->cPropertyCount && rem_props; i++)
784
{
785
const DEVPROPERTY *property = &obj->pProperties[i];
786
ULONG j;
787
788
for (j = 0; j < props_len; j++)
789
{
790
if (IsEqualDevPropKey( property->CompKey.Key, exp_props[j].key ))
791
{
792
SP_INTERFACE_DEVICE_DATA iface_data = {0};
793
DEVPROPTYPE type = DEVPROP_TYPE_EMPTY;
794
const DEVPROPERTY *found_prop;
795
ULONG size = 0;
796
CONFIGRET ret;
797
BYTE *buf;
798
799
winetest_push_context( "exp_props[%lu]", j );
800
rem_props--;
801
ok_( __FILE__, line )( property->Type == exp_props[j].type, "got type %#lx\n", property->Type );
802
/* Ensure the value matches the value retrieved via SetupDiGetDeviceInterfacePropertyW */
803
buf = calloc( property->BufferSize, 1 );
804
iface_data.cbSize = sizeof( iface_data );
805
ret = SetupDiOpenDeviceInterfaceW( set, obj->pszObjectId, 0, &iface_data );
806
err = GetLastError();
807
ok_( __FILE__, line )( ret || err == ERROR_NO_SUCH_DEVICE_INTERFACE, "SetupDiOpenDeviceInterfaceW failed: %lu\n", err );
808
if (!ret)
809
{
810
winetest_pop_context();
811
free( buf );
812
continue;
813
}
814
ret = SetupDiGetDeviceInterfacePropertyW( set, &iface_data, &property->CompKey.Key, &type, buf,
815
property->BufferSize, &size, 0 );
816
ok_( __FILE__, line )( ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", GetLastError() );
817
SetupDiDeleteDeviceInterfaceData( set, &iface_data );
818
819
ok_( __FILE__, line )( size == property->BufferSize, "got size %lu\n", size );
820
ok_( __FILE__, line )( type == property->Type, "got type %#lx\n", type );
821
if (size == property->BufferSize)
822
{
823
switch (type)
824
{
825
case DEVPROP_TYPE_STRING:
826
ok_( __FILE__, line )( !wcsicmp( (WCHAR *)buf, (WCHAR *)property->Buffer ),
827
"got instance id %s != %s\n", debugstr_w( (WCHAR *)buf ),
828
debugstr_w( (WCHAR *)property->Buffer ) );
829
break;
830
default:
831
ok_( __FILE__, line )( !memcmp( buf, property->Buffer, size ),
832
"got mistmatching property values\n" );
833
break;
834
}
835
}
836
837
found_prop = pDevFindProperty( &property->CompKey.Key, DEVPROP_STORE_SYSTEM, NULL,
838
obj->cPropertyCount, obj->pProperties );
839
ok( found_prop == property, "got found_prop %p != %p\n", found_prop, property );
840
free( buf );
841
winetest_pop_context();
842
break;
843
}
844
}
845
}
846
ok_( __FILE__, line )( rem_props == 0, "got rem %lu != 0\n", rem_props );
847
SetupDiDestroyDeviceInfoList( set );
848
}
849
850
static void filter_add_props( DEVPROP_FILTER_EXPRESSION *filters, ULONG props_len, const DEVPROPERTY *props, BOOL equals )
851
{
852
ULONG i;
853
854
for (i = 0; i < props_len; i++)
855
{
856
filters[i].Operator = equals ? DEVPROP_OPERATOR_EQUALS : DEVPROP_OPERATOR_NOT_EQUALS;
857
filters[i].Property = props[i];
858
}
859
}
860
861
static void test_DevGetObjects( void )
862
{
863
struct {
864
DEV_OBJECT_TYPE object_type;
865
struct test_property exp_props[3];
866
ULONG props_len;
867
} test_cases[] = {
868
{
869
DevObjectTypeDeviceInterface,
870
{
871
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
872
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
873
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
874
},
875
3,
876
},
877
{
878
DevObjectTypeDeviceInterfaceDisplay,
879
{
880
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
881
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
882
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
883
},
884
3,
885
},
886
};
887
static const DEVPROP_OPERATOR invalid_ops[] = {
888
/* Logical operators, need to paired with their CLOSE counterpart. */
889
DEVPROP_OPERATOR_AND_OPEN,
890
DEVPROP_OPERATOR_AND_CLOSE,
891
DEVPROP_OPERATOR_OR_OPEN,
892
DEVPROP_OPERATOR_OR_CLOSE,
893
DEVPROP_OPERATOR_NOT_OPEN,
894
DEVPROP_OPERATOR_NOT_CLOSE,
895
/* Mask value, cannot be used by itself in a filter. */
896
DEVPROP_OPERATOR_MASK_LOGICAL,
897
/* Non-existent operators */
898
0xdeadbeef,
899
};
900
static const DEVPROP_OPERATOR boolean_open_ops[] = {
901
DEVPROP_OPERATOR_AND_OPEN,
902
DEVPROP_OPERATOR_OR_OPEN,
903
DEVPROP_OPERATOR_NOT_OPEN,
904
};
905
/* The difference between CLOSE and OPEN operators is always 0x100000, this is just here for clariy's sake. */
906
static const DEVPROP_OPERATOR boolean_close_ops[] = {
907
DEVPROP_OPERATOR_AND_CLOSE,
908
DEVPROP_OPERATOR_OR_CLOSE,
909
DEVPROP_OPERATOR_NOT_CLOSE,
910
};
911
CHAR bool_val_extra[] = { DEVPROP_TRUE, 0xde, 0xad, 0xbe, 0xef };
912
DEVPROP_BOOLEAN bool_val = DEVPROP_TRUE;
913
const DEVPROP_FILTER_EXPRESSION valid_filter = {
914
DEVPROP_OPERATOR_EQUALS,
915
{
916
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL },
917
DEVPROP_TYPE_BOOLEAN,
918
sizeof( bool_val ),
919
&bool_val,
920
}
921
};
922
DEVPROP_FILTER_EXPRESSION filter_instance_id_exists = {
923
DEVPROP_OPERATOR_NOT_EQUALS, { { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL }, DEVPROP_TYPE_EMPTY, 0, NULL }
924
};
925
DEVPROP_FILTER_EXPRESSION filter_instance_id_not_exists = {
926
DEVPROP_OPERATOR_EQUALS, { { DEVPKEY_Device_InstanceId, DEVPROP_STORE_SYSTEM, NULL }, DEVPROP_TYPE_EMPTY, 0, NULL }
927
};
928
/* Test cases for filter expressions containing boolean operators. All of these filters are logically equivalent
929
* and should return identical objects */
930
struct {
931
DEVPROP_FILTER_EXPRESSION expr[12];
932
SIZE_T size;
933
} logical_op_test_cases[] = {
934
{
935
/* NOT (System.Devices.InstanceId := []) */
936
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE } },
937
3
938
},
939
{
940
/* NOT (NOT (System.Device.InstanceId :- [])) */
941
{ { DEVPROP_OPERATOR_NOT_OPEN }, { DEVPROP_OPERATOR_NOT_OPEN },
942
filter_instance_id_exists,
943
{ DEVPROP_OPERATOR_NOT_CLOSE }, { DEVPROP_OPERATOR_NOT_CLOSE } },
944
5
945
},
946
{
947
/* NOT ((System.Device.InstanceId := []) AND (System.Device.InstanceId :- [])) */
948
{ { DEVPROP_OPERATOR_NOT_OPEN },
949
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_not_exists, filter_instance_id_exists,{ DEVPROP_OPERATOR_AND_CLOSE },
950
{ DEVPROP_OPERATOR_NOT_CLOSE } },
951
6
952
},
953
{
954
/* NOT ((NOT (System.Device.InstanceId :- [])) AND (System.Device.InstanceId :- [])) */
955
{ { DEVPROP_OPERATOR_NOT_OPEN },
956
{ DEVPROP_OPERATOR_AND_OPEN },
957
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
958
filter_instance_id_exists,
959
{ DEVPROP_OPERATOR_AND_CLOSE },
960
{ DEVPROP_OPERATOR_NOT_CLOSE } },
961
8
962
},
963
{
964
/* ((System.Device.InstanceId :- []) OR (System.Device.InstanceId := [])) */
965
{ { DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE } },
966
4
967
},
968
{
969
/* ((System.Devices.InstanceId :- [] AND System.Devices.InstanceId :- []) OR System.Device.InstanceId := []) */
970
{ { DEVPROP_OPERATOR_OR_OPEN },
971
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_AND_CLOSE },
972
filter_instance_id_not_exists,
973
{ DEVPROP_OPERATOR_OR_CLOSE } },
974
7
975
},
976
{
977
/* ((System.Devices.InstanceId :- [] AND System.Devices.InstanceId :- []) AND System.Device.InstanceId :- []) */
978
{ { DEVPROP_OPERATOR_AND_OPEN },
979
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_AND_CLOSE },
980
filter_instance_id_exists,
981
{ DEVPROP_OPERATOR_AND_CLOSE } },
982
7
983
},
984
{
985
/* (System.Device.InstanceId :- [] AND (System.Devices.InstanceId :- [] AND System.Devices.InstanceId :- [])) */
986
{ { DEVPROP_OPERATOR_AND_OPEN },
987
filter_instance_id_exists,
988
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_AND_CLOSE },
989
{ DEVPROP_OPERATOR_AND_CLOSE } },
990
7
991
},
992
{
993
/* ((System.Devices.InstanceId := [] OR System.Devices.InstanceId := []) OR System.Device.InstanceId :- []) */
994
{ { DEVPROP_OPERATOR_OR_OPEN },
995
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE },
996
filter_instance_id_exists,
997
{ DEVPROP_OPERATOR_OR_CLOSE } },
998
7
999
},
1000
{
1001
/* (System.Device.InstanceId := [] OR (System.Devices.InstanceId := [] OR System.Devices.InstanceId :- [])) */
1002
{ { DEVPROP_OPERATOR_OR_OPEN },
1003
filter_instance_id_not_exists,
1004
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_OR_CLOSE },
1005
{ DEVPROP_OPERATOR_OR_CLOSE } },
1006
7
1007
},
1008
/* Logical operators with implicit AND. */
1009
{
1010
/* (NOT (System.Device.InstanceId := [])) System.Device.InstanceId :- [] */
1011
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1012
filter_instance_id_exists },
1013
4
1014
},
1015
{
1016
/* (NOT (System.Device.InstanceId := [])) (NOT (System.Device.InstanceId := [])) */
1017
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1018
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE } },
1019
6
1020
},
1021
{
1022
/* (NOT (System.Device.InstanceId :- [] AND System.Device.InstanceId := [])) System.Device.InstanceId :- [] */
1023
{ { DEVPROP_OPERATOR_NOT_OPEN },
1024
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_AND_CLOSE },
1025
{ DEVPROP_OPERATOR_NOT_CLOSE },
1026
filter_instance_id_exists },
1027
7
1028
},
1029
{
1030
/* (NOT (System.Device.InstanceId := [] OR System.Device.InstanceId := [])) System.Device.InstanceId :- [] */
1031
{ { DEVPROP_OPERATOR_NOT_OPEN },
1032
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE },
1033
{ DEVPROP_OPERATOR_NOT_CLOSE },
1034
filter_instance_id_exists },
1035
7
1036
},
1037
{
1038
/* (NOT (System.Device.InstanceId := [] OR System.Device.InstanceId := [])) (System.Device.InstanceId := [] OR System.Device.InstanceId :- []) */
1039
{ { DEVPROP_OPERATOR_NOT_OPEN },
1040
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE },
1041
{ DEVPROP_OPERATOR_NOT_CLOSE },
1042
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_OR_CLOSE } },
1043
10
1044
},
1045
{
1046
/* (NOT (System.Device.InstanceId := [] OR System.Device.InstanceId := [])) (NOT (System.Device.InstanceId :- [] AND System.Device.InstanceId := [])) */
1047
{ { DEVPROP_OPERATOR_NOT_OPEN },
1048
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE },
1049
{ DEVPROP_OPERATOR_NOT_CLOSE },
1050
{ DEVPROP_OPERATOR_NOT_OPEN },
1051
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_AND_CLOSE },
1052
{ DEVPROP_OPERATOR_NOT_CLOSE } },
1053
12
1054
},
1055
{
1056
/* ((System.Device.InstanceId := [] AND System.Device.InstanceId := []) OR (Syste.Device.InstanceId :- [])) */
1057
{ { DEVPROP_OPERATOR_OR_OPEN },
1058
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_not_exists,
1059
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_AND_CLOSE },
1060
{ DEVPROP_OPERATOR_AND_CLOSE },
1061
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1062
{ DEVPROP_OPERATOR_OR_CLOSE },
1063
},
1064
11
1065
}
1066
};
1067
/* Filters that return empty results */
1068
struct {
1069
DEVPROP_FILTER_EXPRESSION expr[14];
1070
SIZE_T size;
1071
} logical_op_empty_test_cases[] = {
1072
{
1073
/* (NOT (System.Devices.InstanceId :- [])) */
1074
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE } },
1075
3,
1076
},
1077
{
1078
/* (NOT (System.Devices.InstanceId :- [])) System.Devices.InstanceId := [] */
1079
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1080
filter_instance_id_not_exists },
1081
4,
1082
},
1083
{
1084
/* (NOT (System.Devices.InstanceId :- [])) (NOT (System.Devices.InstanceId :- [])) */
1085
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1086
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE } },
1087
6,
1088
},
1089
{
1090
/* (NOT (System.Devices.InstanceId :- [])) (NOT (System.Devices.InstanceId :- [] AND System.Devices.InstanceId :- [])) */
1091
{ { DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1092
{ DEVPROP_OPERATOR_NOT_OPEN },
1093
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_AND_CLOSE },
1094
{ DEVPROP_OPERATOR_NOT_CLOSE } },
1095
9,
1096
},
1097
{
1098
/* NOT (NOT (System.Devices.InstanceId := [] AND System.Devices.InstanceId :- [])) */
1099
{ { DEVPROP_OPERATOR_NOT_OPEN }, { DEVPROP_OPERATOR_NOT_OPEN },
1100
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_not_exists, filter_instance_id_exists, { DEVPROP_OPERATOR_AND_CLOSE },
1101
{ DEVPROP_OPERATOR_NOT_CLOSE }, { DEVPROP_OPERATOR_NOT_CLOSE } },
1102
8,
1103
},
1104
{
1105
/* (System.Devices.InstanceId := [] OR System.Devices.InstanceId := []) */
1106
{ { DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists, filter_instance_id_not_exists, { DEVPROP_OPERATOR_OR_CLOSE } },
1107
4,
1108
},
1109
{
1110
/* (NOT System.Devices.InstanceId :- []) OR (System.Devices.InstanceId := [] OR (NOT System.Devices.InstanceId :- []) OR (NOT System.Devices.InstanceId :- [])) */
1111
{ { DEVPROP_OPERATOR_OR_OPEN },
1112
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1113
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists,
1114
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1115
{ DEVPROP_OPERATOR_OR_CLOSE },
1116
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1117
{ DEVPROP_OPERATOR_OR_CLOSE } },
1118
14
1119
},
1120
{
1121
/* (NOT System.Devices.InstanceId :- []) OR (NOT System.Devices.InstanceId :- []) OR (System.Devices.InstanceId := [] OR (NOT System.Devices.InstanceId :- [])) */
1122
{ { DEVPROP_OPERATOR_OR_OPEN },
1123
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1124
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1125
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists,
1126
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1127
{ DEVPROP_OPERATOR_OR_CLOSE },
1128
{ DEVPROP_OPERATOR_OR_CLOSE } },
1129
14
1130
},
1131
{
1132
/* (NOT System.Devices.InstanceId :- []) OR (NOT System.Devices.InstanceId :- []) OR (System.Devices.InstanceId :- [] AND (NOT System.Devices.InstanceId :- [])) */
1133
{ { DEVPROP_OPERATOR_OR_OPEN },
1134
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1135
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1136
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists,
1137
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1138
{ DEVPROP_OPERATOR_AND_CLOSE },
1139
{ DEVPROP_OPERATOR_OR_CLOSE } },
1140
14
1141
},
1142
{
1143
/* (NOT System.Devices.InstanceId := []) AND (NOT System.Devices.InstanceId := []) AND (System.Devices.InstanceId :- [] AND (NOT System.Devices.InstanceId :- [])) */
1144
{ { DEVPROP_OPERATOR_AND_OPEN },
1145
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1146
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1147
{ DEVPROP_OPERATOR_AND_OPEN }, filter_instance_id_exists,
1148
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1149
{ DEVPROP_OPERATOR_AND_CLOSE },
1150
{ DEVPROP_OPERATOR_AND_CLOSE } },
1151
14
1152
},
1153
{
1154
/* (NOT System.Devices.InstanceId := []) AND (NOT System.Devices.InstanceId := []) AND (System.Devices.InstanceId := [] OR (NOT System.Devices.InstanceId :- [])) */
1155
{ { DEVPROP_OPERATOR_AND_OPEN },
1156
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1157
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_not_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1158
{ DEVPROP_OPERATOR_OR_OPEN }, filter_instance_id_not_exists,
1159
{ DEVPROP_OPERATOR_NOT_OPEN }, filter_instance_id_exists, { DEVPROP_OPERATOR_NOT_CLOSE },
1160
{ DEVPROP_OPERATOR_OR_CLOSE },
1161
{ DEVPROP_OPERATOR_AND_CLOSE } },
1162
14
1163
}
1164
};
1165
DEVPROPCOMPKEY prop_iface_class = { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL };
1166
DEVPROP_FILTER_EXPRESSION filters[4];
1167
const DEV_OBJECT *objects = NULL;
1168
DEVPROPCOMPKEY prop_key = {0};
1169
DEVPROPCOMPKEY props[2];
1170
HRESULT hr;
1171
ULONG i, len = 0;
1172
1173
if (!pDevGetObjects || !pDevFreeObjects || !pDevFindProperty)
1174
{
1175
win_skip("Functions unavailable, skipping test. (%p %p %p)\n", pDevGetObjects, pDevFreeObjects, pDevFindProperty);
1176
return;
1177
}
1178
1179
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 1, NULL, 0, NULL, &len, &objects );
1180
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1181
1182
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, NULL, &len, &objects );
1183
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1184
1185
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, (void *)0xdeadbeef, 0, NULL, &len, &objects );
1186
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1187
1188
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
1189
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1190
1191
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagUpdateResults, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
1192
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1193
1194
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAsyncClose, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
1195
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1196
1197
hr = pDevGetObjects( DevObjectTypeDeviceInterface, 0xdeadbeef, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
1198
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1199
1200
prop_key.Key = test_cases[0].exp_props[0].key;
1201
prop_key.Store = DEVPROP_STORE_SYSTEM;
1202
prop_key.LocaleName = NULL;
1203
/* DevQueryFlagAllProperties is mutually exlusive with requesting specific properties. */
1204
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 1, &prop_key, 0, NULL, &len, &objects );
1205
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1206
1207
len = 0xdeadbeef;
1208
objects = (DEV_OBJECT *)0xdeadbeef;
1209
hr = pDevGetObjects( DevObjectTypeUnknown, DevQueryFlagNone, 0, NULL, 0, NULL, &len, &objects );
1210
ok( hr == S_OK, "got hr %#lx\n", hr );
1211
ok( len == 0, "got len %lu\n", len );
1212
ok( !objects, "got objects %p\n", objects );
1213
1214
len = 0xdeadbeef;
1215
objects = (DEV_OBJECT *)0xdeadbeef;
1216
hr = pDevGetObjects( 0xdeadbeef, DevQueryFlagNone, 0, NULL, 0, NULL, &len, &objects );
1217
ok( hr == S_OK, "got hr %#lx\n", hr );
1218
ok( len == 0, "got len %lu\n", len );
1219
ok( !objects, "got objects %p\n", objects );
1220
1221
/* Filter expressions */
1222
memset( filters, 0, sizeof( filters ) );
1223
filters[0] = valid_filter;
1224
1225
/* Invalid buffer value */
1226
filters[0].Property.Buffer = NULL;
1227
len = 0xdeadbeef;
1228
objects = (DEV_OBJECT *)0xdeadbeef;
1229
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1230
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1231
/* Filters are validated before len and objects are modified. */
1232
ok( len == 0xdeadbeef, "got len %lu\n", len );
1233
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1234
1235
/* Mismatching BufferSize */
1236
len = 0xdeadbeef;
1237
objects = (DEV_OBJECT *)0xdeadbeef;
1238
filters[0].Property.Buffer = &bool_val;
1239
filters[0].Property.BufferSize = 0;
1240
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1241
/* BufferSize is not validated in Windows 10 and before, but no objects are returned. */
1242
ok( hr == E_INVALIDARG || broken( hr == S_OK ), "got hr %#lx\n", hr );
1243
ok( len == 0xdeadbeef || broken( !len ), "got len %lu\n", len );
1244
ok( objects == (DEV_OBJECT *)0xdeadbeef || broken( !objects ), "got objects %p\n", objects );
1245
1246
len = 0xdeadbeef;
1247
objects = (DEV_OBJECT *)0xdeadbeef;
1248
filters[0].Property.Buffer = bool_val_extra;
1249
filters[0].Property.BufferSize = sizeof( bool_val_extra );
1250
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1251
/* The extra bytes are ignored in Windows 10 and before. */
1252
ok( hr == E_INVALIDARG || broken( hr == S_OK ), "got hr %#lx\n", hr );
1253
ok( len == 0xdeadbeef || broken( len ), "got len %lu\n", len );
1254
ok( objects == (DEV_OBJECT *)0xdeadbeef || broken( !!objects ), "got objects %p\n", objects );
1255
if (SUCCEEDED( hr )) pDevFreeObjects( len, objects );
1256
1257
for (i = 0; i < ARRAY_SIZE( invalid_ops ); i++)
1258
{
1259
winetest_push_context( "invalid_ops[%lu]", i );
1260
filters[0].Operator = invalid_ops[i];
1261
1262
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, filters, &len, &objects );
1263
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1264
1265
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
1266
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1267
1268
winetest_pop_context();
1269
}
1270
1271
memset( &filters[0], 0, sizeof( *filters ) );
1272
/* MSDN says this is not a valid operator. However, using this does not fail, but the returned object list is empty. */
1273
filters[0].Operator = DEVPROP_OPERATOR_NONE;
1274
len = 0xdeadbeef;
1275
objects = (DEV_OBJECT *)0xdeadbeef;
1276
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1277
ok( hr == S_OK, "got hr %#lx\n", hr );
1278
ok( !len, "got len %lu\n", len );
1279
ok( !objects, "got objects %p\n", objects );
1280
1281
filters[1] = valid_filter;
1282
/* DEVPROP_OPERATOR_NONE preceeding the next filter expression has the same result. */
1283
len = 0xdeadbeef;
1284
objects = (DEV_OBJECT *)0xdeadbeef;
1285
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
1286
ok( hr == S_OK, "got hr %#lx\n", hr );
1287
ok( !len, "got len %lu\n", len );
1288
ok( !objects, "got objects %p\n", objects );
1289
1290
/* However, filter expressions are still validated. */
1291
filters[1].Property.Buffer = NULL;
1292
len = 0xdeadbeef;
1293
objects = (DEV_OBJECT *)0xdeadbeef;
1294
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
1295
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1296
ok( len == 0xdeadbeef, "got len %lu\n", len );
1297
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1298
1299
filters[0] = valid_filter;
1300
/* DEVPROP_OPERATOR_EXISTS ignores the property type. */
1301
len = 0;
1302
objects = NULL;
1303
filters[0].Operator = DEVPROP_OPERATOR_EXISTS;
1304
filters[0].Property.Type = DEVPROP_TYPE_GUID;
1305
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1306
ok( hr == S_OK, "got hr %#lx\n", hr );
1307
ok( len, "got len %lu\n", len );
1308
pDevFreeObjects( len, objects );
1309
1310
/* Don't fetch any properties, but still use them in the filter. */
1311
filters[0] = valid_filter;
1312
len = 0;
1313
objects = NULL;
1314
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, &filters[0], &len, &objects );
1315
ok( hr == S_OK, "got hr %#lx\n", hr );
1316
ok( len, "got len %lu\n", len );
1317
for (i = 0; i < len; i++)
1318
{
1319
/* No properties should have been fetched. */
1320
winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) );
1321
ok( !objects[i].cPropertyCount, "got cPropertyCount %lu\n", objects[i].cPropertyCount );
1322
ok( !objects[i].pProperties, "got pProperties %p\n", objects[i].pProperties );
1323
winetest_pop_context();
1324
}
1325
pDevFreeObjects( len, objects );
1326
1327
/* Request and filter different properties, make sure we *only* get the properties we requested. */
1328
len = 0;
1329
objects = NULL;
1330
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 1, &prop_iface_class, 1, &filters[0], &len, &objects );
1331
ok( hr == S_OK, "got hr %#lx\n", hr );
1332
ok( len, "got len %lu\n", len );
1333
for (i = 0; i < len; i++)
1334
{
1335
const DEVPROPERTY *prop;
1336
1337
winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) );
1338
ok( objects[i].cPropertyCount == 1, "got cPropertyCount %lu\n", objects[i].cPropertyCount );
1339
prop = pDevFindProperty( &prop_iface_class.Key, prop_iface_class.Store, prop_iface_class.LocaleName,
1340
objects[i].cPropertyCount, objects[i].pProperties );
1341
ok (!!prop, "got prop %p\n", prop );
1342
winetest_pop_context();
1343
}
1344
pDevFreeObjects( len, objects );
1345
1346
/* DevGetObjects will not de-duplicate properties. */
1347
len = 0;
1348
objects = NULL;
1349
props[0] = prop_iface_class;
1350
props[1] = prop_iface_class;
1351
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 2, props, 0, NULL, &len, &objects );
1352
ok( hr == S_OK, "got hr %#lx\n", hr );
1353
ok( len, "got len %lu\n", len );
1354
for (i = 0; i < len; i++)
1355
{
1356
const DEVPROPERTY *props = objects[i].pProperties;
1357
1358
winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) );
1359
ok( objects[i].cPropertyCount == 2, "got cPropertyCount %lu\n", objects[i].cPropertyCount );
1360
ok( IsEqualDevPropCompKey( props[0].CompKey, prop_iface_class ), "got props[0].CompKey %s\n",
1361
debugstr_DEVPROPCOMPKEY( &props[0].CompKey ) );
1362
ok( IsEqualDevPropCompKey( props[1].CompKey, prop_iface_class ), "got props[1].CompKey %s\n",
1363
debugstr_DEVPROPCOMPKEY( &props[1].CompKey ) );
1364
winetest_pop_context();
1365
}
1366
pDevFreeObjects( len, objects );
1367
1368
/* AND/OR with a single expression */
1369
memset( filters, 0, sizeof( filters ) );
1370
filters[0].Operator = DEVPROP_OPERATOR_AND_OPEN;
1371
filters[1] = valid_filter;
1372
filters[2].Operator = DEVPROP_OPERATOR_AND_CLOSE;
1373
len = 0;
1374
objects = NULL;
1375
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 3, filters, &len, &objects );
1376
ok( hr == S_OK, "got hr %#lx\n", hr );
1377
ok( len, "got len %lu\n", len );
1378
for (i = 0; i < len; i++)
1379
{
1380
const DEVPROPERTY *prop;
1381
1382
prop = pDevFindProperty( &valid_filter.Property.CompKey.Key, valid_filter.Property.CompKey.Store,
1383
valid_filter.Property.CompKey.LocaleName, objects[i].cPropertyCount,
1384
objects[i].pProperties );
1385
ok( !!prop, "got prop %p\n", prop );
1386
}
1387
pDevFreeObjects( len, objects );
1388
1389
filters[0].Operator = DEVPROP_OPERATOR_OR_OPEN;
1390
filters[2].Operator = DEVPROP_OPERATOR_OR_CLOSE;
1391
len = 0;
1392
objects = NULL;
1393
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 3, filters, &len, &objects );
1394
ok( hr == S_OK, "got hr %#lx\n", hr );
1395
ok( len, "got len %lu\n", len );
1396
for (i = 0; i < len; i++)
1397
{
1398
const DEVPROPERTY *prop;
1399
1400
prop = pDevFindProperty( &valid_filter.Property.CompKey.Key, valid_filter.Property.CompKey.Store,
1401
valid_filter.Property.CompKey.LocaleName, objects[i].cPropertyCount,
1402
objects[i].pProperties );
1403
ok( !!prop, "got prop %p\n", prop );
1404
}
1405
pDevFreeObjects( len, objects );
1406
1407
memset(filters, 0, sizeof( filters ) );
1408
filters[0] = valid_filter;
1409
filters[0].Operator = DEVPROP_OPERATOR_NOT_EXISTS;
1410
/* All device interfaces have this property, so this should not return any objects. */
1411
len = 0xdeadbeef;
1412
objects = (DEV_OBJECT *)0xdeadbeef;
1413
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, &filters[0], &len, &objects );
1414
ok( hr == S_OK, "got hr %#lx\n", hr );
1415
ok( len == 0, "got len %lu\n", len );
1416
ok( !objects, "got objects %p\n", objects );
1417
1418
/* Empty expressions */
1419
memset( filters, 0, sizeof( filters ) );
1420
for (i = 0; i < ARRAY_SIZE( boolean_open_ops ); i++)
1421
{
1422
DEVPROP_OPERATOR open = boolean_open_ops[i], close = boolean_close_ops[i];
1423
1424
winetest_push_context( "open=%#x, close=%#x", open, close );
1425
1426
filters[0].Operator = open;
1427
filters[1].Operator = close;
1428
len = 0xdeadbeef;
1429
objects = (DEV_OBJECT *)0xdeadbeef;
1430
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 2, filters, &len, &objects );
1431
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1432
ok( len == 0xdeadbeef, "got len %lu\n", len );
1433
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1434
1435
/* Empty nested expressions */
1436
filters[0].Operator = filters[1].Operator = open;
1437
filters[2].Operator = filters[3].Operator = close;
1438
len = 0xdeadbeef;
1439
objects = (DEV_OBJECT *)0xdeadbeef;
1440
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 4, filters, &len, &objects );
1441
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1442
ok( len == 0xdeadbeef, "got len %lu\n", len );
1443
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1444
1445
winetest_pop_context();
1446
}
1447
1448
memset( filters, 0, sizeof( filters ) );
1449
filters[1] = valid_filter;
1450
/* Improperly paired expressions */
1451
for (i = 0; i < ARRAY_SIZE( boolean_open_ops ); i++)
1452
{
1453
DEVPROP_OPERATOR open = boolean_open_ops[i];
1454
ULONG j;
1455
1456
for (j = 0; j < ARRAY_SIZE( boolean_close_ops ) && i != j; j++)
1457
{
1458
DEVPROP_OPERATOR close = boolean_close_ops[j];
1459
1460
winetest_push_context( "open=%#x, close=%#x", open, close );
1461
1462
filters[0].Operator = open;
1463
filters[2].Operator = close;
1464
len = 0xdeadbeef;
1465
objects = (DEV_OBJECT *)0xdeadbeef;
1466
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 3, filters, &len, &objects );
1467
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1468
ok( len == 0xdeadbeef, "got len %lu\n", len );
1469
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1470
1471
winetest_pop_context();
1472
}
1473
}
1474
1475
memset( filters, 0, sizeof( filters ) );
1476
for (i = DEVPROP_OPERATOR_GREATER_THAN; i <= DEVPROP_OPERATOR_LESS_THAN_EQUALS; i++)
1477
{
1478
GUID guid = {0};
1479
1480
winetest_push_context( "op=%#08lx", i );
1481
1482
/* Use the less/greater than operators with GUIDs will never result in a match. */
1483
filters[0].Operator = i;
1484
filters[0].Property.CompKey.Key = DEVPKEY_DeviceInterface_ClassGuid;
1485
filters[0].Property.Buffer = &guid;
1486
filters[0].Property.BufferSize = sizeof( guid );
1487
filters[0].Property.Type = DEVPROP_TYPE_GUID;
1488
len = 0xdeadbeef;
1489
objects = (DEV_OBJECT *)0xdeadbeef;
1490
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1491
ok( hr == S_OK, "got hr %#lx\n", hr );
1492
ok( !len, "got len %lu\n", len );
1493
ok( !objects, "got objects %p\n", objects );
1494
if (objects) pDevFreeObjects( len, objects );
1495
1496
/* Consequently, using the DEVPROP_OPERATOR_MODIFIER_NOT modifier will always match. */
1497
filters[0].Operator |= DEVPROP_OPERATOR_MODIFIER_NOT;
1498
len = 0;
1499
objects = NULL;
1500
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1501
ok( hr == S_OK, "got hr %#lx\n", hr );
1502
ok( len > 0, "got len %lu\n", len );
1503
ok( !!objects, "got objects %p\n", objects );
1504
pDevFreeObjects( len, objects );
1505
1506
/* Make sure we get the same results with the max GUID value as well. */
1507
memset( &guid, 0xff, sizeof( guid ) );
1508
filters[0].Operator = i;
1509
len = 0xdeadbeef;
1510
objects = (DEV_OBJECT *)0xdeadbeef;
1511
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1512
ok( hr == S_OK, "got hr %#lx\n", hr );
1513
ok( !len, "got len %lu\n", len );
1514
ok( !objects, "got objects %p\n", objects );
1515
if (objects) pDevFreeObjects( len, objects );
1516
1517
filters[0].Operator |= DEVPROP_OPERATOR_MODIFIER_NOT;
1518
len = 0;
1519
objects = NULL;
1520
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1521
ok( hr == S_OK, "got hr %#lx\n", hr );
1522
ok( len > 0, "got len %lu\n", len );
1523
ok( !!objects, "got objects %p\n", objects );
1524
pDevFreeObjects( len, objects );
1525
1526
winetest_pop_context();
1527
}
1528
1529
memset( filters, 0, sizeof( filters ) );
1530
filters[0] = valid_filter;
1531
filters[0].Operator = DEVPROP_OPERATOR_NOT_EQUALS;
1532
bool_val = FALSE;
1533
len = 0;
1534
objects = NULL;
1535
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1536
ok( hr == S_OK, "got hr %#lx\n", hr );
1537
ok( len > 0, "got len %lu\n", len );
1538
ok( !!objects, "got objects %p\n", objects );
1539
pDevFreeObjects( len, objects );
1540
bool_val = TRUE;
1541
1542
/* Get the number of objects that the filters in logical_op_test_cases should return. */
1543
filters[0] = filter_instance_id_exists;
1544
len = 0;
1545
objects = NULL;
1546
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects );
1547
ok( hr == S_OK, "got hr %#lx\n", hr );
1548
ok( len > 0, "got len %lu\n", len );
1549
ok( !!objects, "got objects %p\n", objects );
1550
pDevFreeObjects( len, objects );
1551
1552
for (i = 0; i < ARRAY_SIZE( logical_op_test_cases ); i++ )
1553
{
1554
ULONG len2 = 0;
1555
1556
winetest_push_context( "logical_op_test_cases[%lu]", i );
1557
1558
objects = NULL;
1559
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, logical_op_test_cases[i].size,
1560
logical_op_test_cases[i].expr, &len2, &objects );
1561
ok( hr == S_OK, "got hr %#lx\n", hr );
1562
ok( len2 == len, "got len2 %lu != %lu\n", len2, len );
1563
ok( !!objects, "got objects %p\n", objects );
1564
pDevFreeObjects( len2, objects );
1565
1566
winetest_pop_context();
1567
}
1568
1569
for (i = 0; i < ARRAY_SIZE ( logical_op_empty_test_cases ); i++ )
1570
{
1571
winetest_push_context( "logical_op_empty_test_cases[%lu]", i );
1572
1573
len = 0xdeadbeef;
1574
objects = (DEV_OBJECT *)0xdeadbeef;
1575
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL,
1576
logical_op_empty_test_cases[i].size, logical_op_empty_test_cases[i].expr, &len, &objects );
1577
ok( hr == S_OK, "got hr %#lx\n", hr );
1578
ok( !len, "got len %lu\n", len );
1579
ok( !objects, "got objects %p\n", objects );
1580
1581
winetest_pop_context();
1582
}
1583
1584
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
1585
{
1586
const DEV_OBJECT *objects = NULL;
1587
ULONG j, len = 0;
1588
1589
/* Get all objects of this type, with all properties. */
1590
objects = NULL;
1591
len = 0;
1592
winetest_push_context( "test_cases[%lu]", i );
1593
hr = pDevGetObjects( test_cases[i].object_type, DevQueryFlagAllProperties, 0, NULL, 0, NULL, &len, &objects );
1594
ok( hr == S_OK, "got hr %#lx\n", hr );
1595
for (j = 0; j < len; j++)
1596
{
1597
DEVPROP_FILTER_EXPRESSION *filters;
1598
const DEV_OBJECT *obj = &objects[j], *objects2;
1599
ULONG k, len2 = 0;
1600
BOOL found = FALSE;
1601
1602
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) );
1603
ok( obj->ObjectType == test_cases[i].object_type, "got ObjectType %d\n", obj->ObjectType );
1604
test_dev_object_iface_props( __LINE__, obj, test_cases[i].exp_props, test_cases[i].props_len );
1605
winetest_push_context( "%d", __LINE__ );
1606
test_DevGetObjectProperties( obj->ObjectType, obj->pszObjectId, obj->pProperties, obj->cPropertyCount );
1607
winetest_pop_context();
1608
1609
/* Create a filter for all properties of this object. */
1610
filters = calloc( obj->cPropertyCount, sizeof( *filters ) );
1611
/* If there are no logical operators present, then logical AND is used. */
1612
filter_add_props( filters, obj->cPropertyCount, obj->pProperties, TRUE );
1613
hr = pDevGetObjects( test_cases[i].object_type, DevQueryFlagAllProperties, 0, NULL, obj->cPropertyCount,
1614
filters, &len2, &objects2 );
1615
ok( hr == S_OK, "got hr %#lx\n", hr );
1616
/* For device interface objects, DEVPKEY_Device_Instance and DEVPKEY_DeviceInterface_ClassGuid are a
1617
* unique pair, so there should only be one object. */
1618
if (test_cases[i].object_type == DevObjectTypeDeviceInterface
1619
|| test_cases[i].object_type == DevObjectTypeDeviceInterfaceDisplay)
1620
ok( len2 == 1, "got len2 %lu\n", len2 );
1621
else
1622
ok( len2, "got len2 %lu\n", len2 );
1623
for (k = 0; k < len2; k++)
1624
{
1625
if (!wcsicmp( objects2[k].pszObjectId, obj->pszObjectId ))
1626
{
1627
found = TRUE;
1628
break;
1629
}
1630
}
1631
ok( found, "failed to get object using query filters\n" );
1632
pDevFreeObjects( len2, objects2 );
1633
free( filters );
1634
winetest_pop_context();
1635
}
1636
pDevFreeObjects( len, objects );
1637
1638
/* Get all objects of this type, but only with a single requested property. */
1639
for (j = 0; j < test_cases[i].props_len; j++)
1640
{
1641
const struct test_property *prop = &test_cases[i].exp_props[j];
1642
ULONG k;
1643
1644
winetest_push_context( "exp_props[%lu]", j );
1645
objects = NULL;
1646
len = 0;
1647
prop_key.Key = prop->key;
1648
prop_key.LocaleName = NULL;
1649
prop_key.Store = DEVPROP_STORE_SYSTEM;
1650
hr = pDevGetObjects( test_cases[i].object_type, 0, 1, &prop_key, 0, NULL, &len, &objects );
1651
ok( hr == S_OK, "got hr %#lx\n", hr );
1652
ok( len, "got buf_len %lu\n", len );
1653
ok( !!objects, "got objects %p\n", objects );
1654
for (k = 0; k < len; k++)
1655
{
1656
const DEV_OBJECT *obj = &objects[k];
1657
const DEVPROPERTY *found_prop;
1658
1659
winetest_push_context( "objects[%lu]", k );
1660
ok( obj->cPropertyCount == 1, "got cPropertyCount %lu != 1\n", obj->cPropertyCount );
1661
ok( !!obj->pProperties, "got pProperties %p\n", obj->pProperties );
1662
if (obj->pProperties)
1663
{
1664
ok( IsEqualDevPropKey( obj->pProperties[0].CompKey.Key, prop->key ), "got property {%s, %#lx} != {%s, %#lx}\n",
1665
debugstr_guid( &obj->pProperties[0].CompKey.Key.fmtid ), obj->pProperties[0].CompKey.Key.pid,
1666
debugstr_guid( &prop->key.fmtid ), prop->key.pid );
1667
found_prop = pDevFindProperty( &prop->key, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1668
ok( found_prop == &obj->pProperties[0], "got found_prop %p != %p\n", found_prop, &obj->pProperties[0] );
1669
}
1670
/* Search for a property not in obj->pProperties, we should get NULL, as we haven't requested this
1671
* property in the DevGetObjects call. */
1672
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1673
ok( !found_prop, "got found_prop %p\n", found_prop );
1674
1675
winetest_pop_context();
1676
}
1677
pDevFreeObjects( len, objects );
1678
winetest_pop_context();
1679
}
1680
1681
/* Get all objects of this type, but with a non existent property. The returned objects will still have this
1682
* property, albeit with Type set to DEVPROP_TYPE_EMPTY. */
1683
len = 0;
1684
objects = NULL;
1685
prop_key.Key = DEVPKEY_dummy;
1686
hr = pDevGetObjects( test_cases[i].object_type, 0, 1, &prop_key, 0, NULL, &len, &objects );
1687
ok( hr == S_OK, "got hr %#lx\n", hr );
1688
ok( len, "got len %lu\n", len );
1689
ok( !!objects, "got objects %p\n", objects );
1690
for (j = 0; j < len; j++)
1691
{
1692
const DEV_OBJECT *obj = &objects[j];
1693
1694
winetest_push_context( "objects[%lu]", j );
1695
ok( obj->cPropertyCount == 1, "got cPropertyCount %lu != 1\n", obj->cPropertyCount );
1696
ok( !!obj->pProperties, "got pProperties %p\n", obj->pProperties );
1697
if (obj->pProperties)
1698
{
1699
const DEVPROPERTY *found_prop;
1700
1701
ok( IsEqualDevPropKey( obj->pProperties[0].CompKey.Key, DEVPKEY_dummy ), "got property %s != %s\n",
1702
debugstr_DEVPROPKEY( &obj->pProperties[0].CompKey.Key ), debugstr_DEVPROPKEY( &DEVPKEY_dummy ) );
1703
ok( obj->pProperties[0].Type == DEVPROP_TYPE_EMPTY, "got Type %#lx != %#x\n", obj->pProperties[0].Type,
1704
DEVPROP_TYPE_EMPTY );
1705
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1706
ok( found_prop == &obj->pProperties[0], "got found_prop %p != %p\n", found_prop, &obj->pProperties[0] );
1707
}
1708
winetest_pop_context();
1709
}
1710
winetest_pop_context();
1711
pDevFreeObjects( len, objects );
1712
}
1713
}
1714
1715
struct query_callback_data
1716
{
1717
int line;
1718
DEV_OBJECT_TYPE exp_type;
1719
const struct test_property *exp_props;
1720
DWORD props_len;
1721
1722
HANDLE enum_completed;
1723
HANDLE closed;
1724
};
1725
1726
static void WINAPI query_result_callback( HDEVQUERY query, void *user_data, const DEV_QUERY_RESULT_ACTION_DATA *action_data )
1727
{
1728
struct query_callback_data *data = user_data;
1729
1730
ok( !!data, "got null user_data\n" );
1731
if (!data) return;
1732
1733
switch (action_data->Action)
1734
{
1735
case DevQueryResultStateChange:
1736
{
1737
DEV_QUERY_STATE state = action_data->Data.State;
1738
ok( state == DevQueryStateEnumCompleted || state == DevQueryStateClosed,
1739
"got unexpected Data.State value: %d\n", state );
1740
switch (state)
1741
{
1742
case DevQueryStateEnumCompleted:
1743
SetEvent( data->enum_completed );
1744
break;
1745
case DevQueryStateClosed:
1746
SetEvent( data->closed );
1747
default:
1748
break;
1749
}
1750
break;
1751
}
1752
case DevQueryResultAdd:
1753
{
1754
const DEV_OBJECT *obj = &action_data->Data.DeviceObject;
1755
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) );
1756
ok_( __FILE__, data->line )( obj->ObjectType == data->exp_type, "got DeviceObject.ObjectType %d != %d\n",
1757
obj->ObjectType, data->exp_type );
1758
test_dev_object_iface_props( data->line, &action_data->Data.DeviceObject, data->exp_props, data->props_len );
1759
winetest_pop_context();
1760
break;
1761
}
1762
default:
1763
ok( action_data->Action == DevQueryResultUpdate || action_data->Action == DevQueryResultRemove,
1764
"got unexpected Action %d\n", action_data->Action );
1765
break;
1766
}
1767
}
1768
1769
#define call_DevCreateObjectQuery( a, b, c, d, e, f, g, h, i ) \
1770
call_DevCreateObjectQuery_(__LINE__, (a), (b), (c), (d), (e), (f), (g), (h), (i))
1771
1772
static HRESULT call_DevCreateObjectQuery_( int line, DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len,
1773
const DEVPROPCOMPKEY *props, ULONG filters_len,
1774
const DEVPROP_FILTER_EXPRESSION *filters, PDEV_QUERY_RESULT_CALLBACK callback,
1775
struct query_callback_data *data, HDEVQUERY *devquery )
1776
{
1777
data->line = line;
1778
return pDevCreateObjectQuery( type, flags, props_len, props, filters_len, filters, callback, data, devquery );
1779
}
1780
1781
static void test_DevCreateObjectQuery( void )
1782
{
1783
struct test_property iface_props[3] = {
1784
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
1785
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
1786
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
1787
};
1788
struct query_callback_data data = {0};
1789
HDEVQUERY query = NULL;
1790
HRESULT hr;
1791
DWORD ret;
1792
1793
if (!pDevCreateObjectQuery || !pDevCloseObjectQuery)
1794
{
1795
win_skip("Functions unavailable, skipping test. (%p %p)\n", pDevCreateObjectQuery, pDevCloseObjectQuery);
1796
return;
1797
}
1798
1799
hr = pDevCreateObjectQuery( DevObjectTypeDeviceInterface, 0, 0, NULL, 0, NULL, NULL, NULL, &query );
1800
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1801
ok( !query, "got query %p\n", query );
1802
1803
hr = pDevCreateObjectQuery( DevObjectTypeDeviceInterface, 0xdeadbeef, 0, NULL, 0, NULL, query_result_callback,
1804
NULL, &query );
1805
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1806
ok( !query, "got query %p\n", query );
1807
1808
data.enum_completed = CreateEventW( NULL, FALSE, FALSE, NULL );
1809
data.closed = CreateEventW( NULL, FALSE, FALSE, NULL );
1810
1811
hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query );
1812
ok( hr == S_OK, "got hr %#lx\n", hr );
1813
ret = WaitForSingleObject( data.enum_completed, 1000 );
1814
ok( !ret, "got ret %lu\n", ret );
1815
pDevCloseObjectQuery( query );
1816
1817
hr = call_DevCreateObjectQuery( 0xdeadbeef, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query );
1818
ok( hr == S_OK, "got hr %#lx\n", hr );
1819
ret = WaitForSingleObject( data.enum_completed, 1000 );
1820
ok( !ret, "got ret %lu\n", ret );
1821
pDevCloseObjectQuery( query );
1822
1823
hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, DevQueryFlagAsyncClose, 0, NULL, 0, NULL, &query_result_callback,
1824
&data, &query );
1825
ok( hr == S_OK, "got hr %#lx\n", hr );
1826
ret = WaitForSingleObject( data.enum_completed, 1000 );
1827
ok( !ret, "got ret %lu\n", ret );
1828
pDevCloseObjectQuery( query );
1829
ret = WaitForSingleObject( data.closed, 1000 );
1830
ok( !ret, "got ret %lu\n", ret );
1831
1832
data.exp_props = iface_props;
1833
data.props_len = ARRAY_SIZE( iface_props );
1834
1835
data.exp_type = DevObjectTypeDeviceInterface;
1836
hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties | DevQueryFlagAsyncClose, 0,
1837
NULL, 0, NULL, &query_result_callback, &data, &query );
1838
ok( hr == S_OK, "got hr %#lx\n", hr );
1839
ret = WaitForSingleObject( data.enum_completed, 5000 );
1840
ok( !ret, "got ret %lu\n", ret );
1841
pDevCloseObjectQuery( query );
1842
ret = WaitForSingleObject( data.closed, 1000 );
1843
ok( !ret, "got ret %lu\n", ret );
1844
1845
data.exp_type = DevObjectTypeDeviceInterfaceDisplay;
1846
hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAllProperties | DevQueryFlagAsyncClose,
1847
0, NULL, 0, NULL, &query_result_callback, &data, &query );
1848
ok( hr == S_OK, "got hr %#lx\n", hr );
1849
ret = WaitForSingleObject( data.enum_completed, 5000 );
1850
ok( !ret, "got ret %lu\n", ret );
1851
pDevCloseObjectQuery( query );
1852
ret = WaitForSingleObject( data.closed, 1000 );
1853
ok( !ret, "got ret %lu\n", ret );
1854
1855
CloseHandle( data.enum_completed );
1856
CloseHandle( data.closed );
1857
}
1858
1859
static void test_DevGetObjectProperties_invalid( void )
1860
{
1861
HRESULT hr;
1862
1863
if (!pDevGetObjectProperties)
1864
{
1865
win_skip( "Functions unavailable, skipping test. (%p)\n", pDevGetObjectProperties );
1866
return;
1867
}
1868
1869
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 0, NULL, NULL, NULL );
1870
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1871
1872
hr = pDevGetObjectProperties( DevObjectTypeUnknown, L"", 0, 0, NULL, NULL, NULL );
1873
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1874
1875
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, DevQueryFlagAsyncClose, 0, NULL, NULL, NULL );
1876
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1877
1878
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", DevQueryFlagUpdateResults, 0, NULL, NULL, NULL );
1879
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1880
1881
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", 0xdeadbeef, 0, NULL, NULL, NULL );
1882
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1883
1884
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 1, NULL, NULL, NULL );
1885
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1886
1887
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 0, (DEVPROPCOMPKEY *)0xdeadbeef, NULL, NULL );
1888
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1889
1890
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", 0, 0, NULL, NULL, NULL );
1891
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1892
1893
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterfaceDisplay, L"foobar", 0, 0, NULL, NULL, NULL );
1894
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1895
1896
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, NULL, 0, 0, NULL, NULL, NULL );
1897
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1898
}
1899
1900
static void test_DevFindProperty_invalid( void )
1901
{
1902
const DEVPROPERTY *prop;
1903
1904
if (!pDevFindProperty)
1905
{
1906
win_skip( "Functions unavailable, skipping test. (%p)\n", pDevFindProperty );
1907
return;
1908
}
1909
1910
prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, 0, NULL );
1911
ok( !prop, "got prop %p\n", prop );
1912
1913
prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, 0, (DEVPROPERTY *)0xdeadbeef );
1914
ok( !prop, "got prop %p\n", prop );
1915
}
1916
1917
static void test_CM_Enumerate_Classes(void)
1918
{
1919
CONFIGRET ret;
1920
GUID guid;
1921
1922
ret = CM_Enumerate_Classes( 0, NULL, 0 );
1923
ok_x4( ret, ==, CR_INVALID_POINTER );
1924
for (UINT flag = 2; flag; flag <<= 1)
1925
{
1926
winetest_push_context( "%#x", flag );
1927
ret = CM_Enumerate_Classes( 0, &guid, flag );
1928
ok_x4( ret, ==, CR_INVALID_FLAG );
1929
winetest_pop_context();
1930
}
1931
ret = CM_Enumerate_Classes( -1, &guid, 0 );
1932
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
1933
1934
for (UINT i = 0; !(ret = CM_Enumerate_Classes( i, &guid, CM_ENUMERATE_CLASSES_INSTALLER )); i++)
1935
if (IsEqualGUID( &guid, &GUID_DEVINTERFACE_HID )) break;
1936
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
1937
for (UINT i = 0; !(ret = CM_Enumerate_Classes( i, &guid, CM_ENUMERATE_CLASSES_INSTALLER )); i++)
1938
if (IsEqualGUID( &guid, &GUID_DEVCLASS_HIDCLASS )) break;
1939
ok_x4( ret, ==, CR_SUCCESS );
1940
1941
for (UINT i = 0; !(ret = CM_Enumerate_Classes( i, &guid, CM_ENUMERATE_CLASSES_INTERFACE )); i++)
1942
if (IsEqualGUID( &guid, &GUID_DEVINTERFACE_HID )) break;
1943
ok_x4( ret, ==, CR_SUCCESS );
1944
for (UINT i = 0; !(ret = CM_Enumerate_Classes( i, &guid, CM_ENUMERATE_CLASSES_INTERFACE )); i++)
1945
if (IsEqualGUID( &guid, &GUID_DEVCLASS_HIDCLASS )) break;
1946
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
1947
}
1948
1949
static void test_CM_Enumerate_Enumerators(void)
1950
{
1951
WCHAR buffer[MAX_PATH], upper[MAX_PATH];
1952
CONFIGRET ret;
1953
ULONG len;
1954
1955
len = 0;
1956
ret = CM_Enumerate_EnumeratorsW( 0, NULL, &len, 0 );
1957
ok_x4( ret, ==, CR_INVALID_POINTER );
1958
ok_x4( len, ==, 0 );
1959
len = 1;
1960
ret = CM_Enumerate_EnumeratorsW( 0, NULL, &len, 0 );
1961
ok_x4( ret, ==, CR_INVALID_POINTER );
1962
ok_x4( len, ==, 1 );
1963
ret = CM_Enumerate_EnumeratorsW( 0, buffer, NULL, 0 );
1964
ok_x4( ret, ==, CR_INVALID_POINTER );
1965
len = 0;
1966
ret = CM_Enumerate_EnumeratorsW( 0, buffer, &len, 0 );
1967
ok_x4( ret, ==, CR_INVALID_DATA );
1968
ok_x4( len, ==, 0 );
1969
1970
for (UINT flag = 1; flag; flag <<= 1)
1971
{
1972
winetest_push_context( "%#x", flag );
1973
len = ARRAY_SIZE(buffer);
1974
ret = CM_Enumerate_EnumeratorsW( 0, buffer, &len, flag );
1975
ok_x4( ret, ==, CR_INVALID_FLAG );
1976
winetest_pop_context();
1977
}
1978
1979
len = ARRAY_SIZE(buffer);
1980
ret = CM_Enumerate_EnumeratorsW( -1, buffer, &len, 0 );
1981
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
1982
ok_x4( len, ==, ARRAY_SIZE(buffer) );
1983
1984
memset( buffer, 0xcd, sizeof(buffer) );
1985
for (ULONG i = 0, len = ARRAY_SIZE(buffer); !(ret = CM_Enumerate_EnumeratorsW( i, buffer, &len, 0 )); i++, len = ARRAY_SIZE(buffer))
1986
{
1987
wcscpy( upper, buffer );
1988
wcsupr( upper );
1989
ok_wcs( upper, buffer );
1990
if (!memcmp( buffer, L"HID\0\xcdcd", 5 )) break;
1991
memset( buffer, 0xcd, sizeof(buffer) );
1992
}
1993
ok_x4( ret, ==, CR_SUCCESS );
1994
}
1995
1996
static void test_CM_Get_Class_Key_Name(void)
1997
{
1998
GUID guid = GUID_DEVCLASS_DISPLAY;
1999
WCHAR buffer[MAX_PATH];
2000
CONFIGRET ret;
2001
ULONG len;
2002
2003
len = ARRAY_SIZE(buffer);
2004
ret = CM_Get_Class_Key_NameW( NULL, buffer, &len, 0 );
2005
ok_x4( ret, ==, CR_INVALID_POINTER );
2006
ok_u4( len, ==, ARRAY_SIZE(buffer) );
2007
2008
ret = CM_Get_Class_Key_NameW( &guid, NULL, NULL, 0 );
2009
ok_x4( ret, ==, CR_INVALID_POINTER );
2010
ok_u4( len, ==, ARRAY_SIZE(buffer) );
2011
2012
ret = CM_Get_Class_Key_NameW( &guid, buffer, NULL, 0 );
2013
ok_x4( ret, ==, CR_INVALID_POINTER );
2014
ok_u4( len, ==, ARRAY_SIZE(buffer) );
2015
2016
ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 );
2017
ok_x4( ret, ==, CR_INVALID_POINTER );
2018
ok_u4( len, ==, ARRAY_SIZE(buffer) );
2019
2020
len = 0;
2021
ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 );
2022
ok_x4( ret, ==, CR_BUFFER_SMALL );
2023
ok_u4( len, ==, 39 );
2024
len = 1;
2025
ret = CM_Get_Class_Key_NameW( &guid, NULL, &len, 0 );
2026
ok_x4( ret, ==, CR_INVALID_POINTER );
2027
ok_u4( len, ==, 1 );
2028
2029
len = 2;
2030
memset( buffer, 0xcd, sizeof(buffer) );
2031
ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 );
2032
ok_x4( ret, ==, CR_BUFFER_SMALL );
2033
ok_u4( len, ==, 39 );
2034
ok( *buffer == 0xcdcd, "got %s\n", debugstr_wn(buffer, 2) );
2035
2036
len = ARRAY_SIZE(buffer);
2037
ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 );
2038
ok_x4( ret, ==, CR_SUCCESS );
2039
ok_u4( len, ==, 39 );
2040
ok_wcs( L"{4d36e968-e325-11ce-bfc1-08002be10318}", buffer );
2041
2042
/* doesn't really check anything, it works with any GUID */
2043
guid = GUID_DEVINTERFACE_DISPLAY_ADAPTER;
2044
len = ARRAY_SIZE(buffer);
2045
ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 );
2046
ok_x4( ret, ==, CR_SUCCESS );
2047
ok_u4( len, ==, 39 );
2048
ok_wcs( L"{5b45201d-f2f2-4f3b-85bb-30ff1f953599}", buffer );
2049
2050
memset( &guid, 0xcd, sizeof(guid) );
2051
len = ARRAY_SIZE(buffer);
2052
ret = CM_Get_Class_Key_NameW( &guid, buffer, &len, 0 );
2053
ok_x4( ret, ==, CR_SUCCESS );
2054
ok_u4( len, ==, 39 );
2055
ok_wcs( L"{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}", buffer );
2056
}
2057
2058
static BOOL compare_unicode_string( const UNICODE_STRING *string, const WCHAR *expect )
2059
{
2060
return string->Length == wcslen( expect ) * sizeof(WCHAR) &&
2061
!wcsnicmp( string->Buffer, expect, string->Length / sizeof(WCHAR) );
2062
}
2063
2064
#define check_object_name( a, b ) _check_object_name( __LINE__, a, b )
2065
static void _check_object_name( unsigned line, HANDLE handle, const WCHAR *expected_name )
2066
{
2067
char buffer[1024];
2068
UNICODE_STRING *str = (UNICODE_STRING *)buffer, expect;
2069
ULONG len = 0;
2070
NTSTATUS status;
2071
2072
RtlInitUnicodeString( &expect, expected_name );
2073
2074
memset( buffer, 0, sizeof(buffer) );
2075
status = NtQueryObject( handle, ObjectNameInformation, buffer, sizeof(buffer), &len );
2076
ok_(__FILE__, line)( status == STATUS_SUCCESS, "NtQueryObject failed %lx\n", status );
2077
ok_(__FILE__, line)( len >= sizeof(OBJECT_NAME_INFORMATION) + str->Length, "unexpected len %lu\n", len );
2078
ok_(__FILE__, line)( compare_unicode_string( str, expected_name ), "got %s, expected %s\n",
2079
debugstr_w(str->Buffer), debugstr_w(expected_name) );
2080
}
2081
2082
static void test_CM_Open_Class_Key(void)
2083
{
2084
CONFIGRET ret;
2085
GUID guid;
2086
HKEY hkey;
2087
2088
ret = CM_Open_Class_KeyW( NULL, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INSTALLER );
2089
ok_x4( ret, ==, CR_SUCCESS );
2090
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\Class" );
2091
RegCloseKey( hkey );
2092
2093
ret = CM_Open_Class_KeyW( NULL, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INTERFACE );
2094
ok_x4( ret, ==, CR_SUCCESS );
2095
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses" );
2096
RegCloseKey( hkey );
2097
2098
guid = GUID_DEVCLASS_DISPLAY;
2099
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INSTALLER );
2100
ok_x4( ret, ==, CR_SUCCESS );
2101
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}" );
2102
RegCloseKey( hkey );
2103
2104
guid = GUID_DEVINTERFACE_DISPLAY_ADAPTER;
2105
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INTERFACE );
2106
ok_x4( ret, ==, CR_SUCCESS );
2107
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses\\{5b45201d-f2f2-4f3b-85bb-30ff1f953599}" );
2108
RegCloseKey( hkey );
2109
2110
memset( &guid, 0xcd, sizeof(guid) );
2111
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INSTALLER );
2112
ok_x4( ret, ==, CR_NO_SUCH_REGISTRY_KEY );
2113
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenAlways, &hkey, CM_OPEN_CLASS_KEY_INSTALLER );
2114
ok_x4( ret, ==, CR_SUCCESS );
2115
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\Class\\{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}" );
2116
RegCloseKey( hkey );
2117
ret = RegDeleteKeyW( HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Control\\Class\\{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}" );
2118
ok_x4( ret, ==, ERROR_SUCCESS );
2119
2120
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, CM_OPEN_CLASS_KEY_INTERFACE );
2121
ok_x4( ret, ==, CR_NO_SUCH_REGISTRY_KEY );
2122
ret = CM_Open_Class_KeyW( &guid, NULL, KEY_QUERY_VALUE, RegDisposition_OpenAlways, &hkey, CM_OPEN_CLASS_KEY_INTERFACE );
2123
ok_x4( ret, ==, CR_SUCCESS );
2124
check_object_name( hkey, L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses\\{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}" );
2125
RegCloseKey( hkey );
2126
ret = RegDeleteKeyW( HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Control\\DeviceClasses\\{cdcdcdcd-cdcd-cdcd-cdcd-cdcdcdcdcdcd}" );
2127
ok_x4( ret, ==, ERROR_SUCCESS );
2128
}
2129
2130
static void test_CM_Get_Class_Registry_Property(void)
2131
{
2132
GUID guid = GUID_DEVCLASS_DISPLAY;
2133
WCHAR buffer[MAX_PATH];
2134
char bufferA[MAX_PATH];
2135
DWORD type, len;
2136
CONFIGRET ret;
2137
2138
ret = CM_Get_Class_Registry_PropertyW( NULL, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2139
ok_x4( ret, ==, CR_INVALID_POINTER );
2140
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, NULL, NULL, NULL, 0, NULL );
2141
ok_x4( ret, ==, CR_INVALID_POINTER );
2142
ret = CM_Get_Class_Registry_PropertyW( NULL, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2143
ok_x4( ret, ==, CR_INVALID_POINTER );
2144
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, buffer, NULL, 0, NULL );
2145
ok_x4( ret, ==, CR_INVALID_POINTER );
2146
len = 1;
2147
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, NULL, &len, 0, NULL );
2148
ok_x4( ret, ==, CR_INVALID_POINTER );
2149
2150
len = 0;
2151
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, NULL, &len, 0, NULL );
2152
todo_wine ok_x4( ret, ==, CR_BUFFER_SMALL );
2153
todo_wine ok_x4( len, ==, 4 );
2154
len = 1;
2155
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2156
todo_wine ok_x4( ret, ==, CR_BUFFER_SMALL );
2157
todo_wine ok_x4( len, ==, 4 );
2158
2159
len = sizeof(buffer);
2160
memset( &guid, 0xcd, sizeof(guid) );
2161
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2162
ok_x4( ret, ==, CR_NO_SUCH_REGISTRY_KEY );
2163
ok_x4( len, ==, 0 );
2164
guid = GUID_DEVCLASS_DISPLAY;
2165
2166
2167
len = sizeof(buffer);
2168
ret = CM_Get_Class_Registry_PropertyW( &guid, 0, &type, buffer, &len, 0, NULL );
2169
ok_x4( ret, ==, CR_INVALID_PROPERTY );
2170
2171
len = sizeof(buffer);
2172
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_UPPERFILTERS, &type, buffer, &len, 0, NULL );
2173
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2174
ok_x4( len, ==, 0 );
2175
2176
len = sizeof(buffer);
2177
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_LOWERFILTERS, &type, buffer, &len, 0, NULL );
2178
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2179
ok_x4( len, ==, 0 );
2180
2181
type = 0xdeadbeef;
2182
len = sizeof(buffer);
2183
memset( buffer, 0xcd, sizeof(buffer) );
2184
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_SECURITY, &type, buffer, &len, 0, NULL );
2185
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2186
todo_wine ok_x4( type, ==, REG_BINARY );
2187
todo_wine ok_x4( len, ==, 0x30 );
2188
2189
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_SECURITY, NULL, buffer, &len, 0, NULL );
2190
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2191
2192
type = 0xdeadbeef;
2193
len = sizeof(buffer);
2194
memset( buffer, 0xcd, sizeof(buffer) );
2195
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_SECURITY_SDS, &type, buffer, &len, 0, NULL );
2196
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2197
todo_wine ok_x4( type, ==, REG_SZ );
2198
todo_wine ok_x4( len, ==, 0x20 );
2199
todo_wine ok_wcs( L"D:P(A;;GA;;;SY)", buffer );
2200
2201
2202
type = 0xdeadbeef;
2203
len = sizeof(bufferA);
2204
memset( bufferA, 0xcd, sizeof(bufferA) );
2205
ret = CM_Get_Class_Registry_PropertyA( &guid, CM_CRP_SECURITY, &type, bufferA, &len, 0, NULL );
2206
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2207
todo_wine ok_x4( type, ==, REG_BINARY );
2208
todo_wine ok_x4( len, ==, 0x30 );
2209
2210
type = 0xdeadbeef;
2211
len = sizeof(bufferA);
2212
memset( bufferA, 0xcd, sizeof(bufferA) );
2213
ret = CM_Get_Class_Registry_PropertyA( &guid, CM_CRP_SECURITY_SDS, &type, bufferA, &len, 0, NULL );
2214
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2215
todo_wine ok_x4( type, ==, REG_SZ );
2216
todo_wine ok_x4( len, ==, 0x10 );
2217
todo_wine ok_str( "D:P(A;;GA;;;SY)", bufferA );
2218
2219
2220
type = 0xdeadbeef;
2221
len = sizeof(buffer);
2222
memset( buffer, 0xcd, sizeof(buffer) );
2223
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2224
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2225
todo_wine ok_x4( type, ==, REG_DWORD );
2226
todo_wine ok_x4( len, ==, 4 );
2227
todo_wine ok_x4( *(DWORD *)buffer, ==, 0x23 /* FILE_DEVICE_VIDEO */ );
2228
2229
len = sizeof(buffer);
2230
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_EXCLUSIVE, &type, buffer, &len, 0, NULL );
2231
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2232
ok_x4( len, ==, 0 );
2233
2234
type = 0xdeadbeef;
2235
len = sizeof(buffer);
2236
memset( buffer, 0xcd, sizeof(buffer) );
2237
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_CHARACTERISTICS, &type, buffer, &len, 0, NULL );
2238
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2239
todo_wine ok_x4( type, ==, REG_DWORD );
2240
todo_wine ok_x4( len, ==, 4 );
2241
todo_wine ok_x4( *(DWORD *)buffer, ==, 0x100 );
2242
2243
2244
guid = GUID_DEVCLASS_HIDCLASS;
2245
len = sizeof(buffer);
2246
ret = CM_Get_Class_Registry_PropertyW( &guid, 0, &type, buffer, &len, 0, NULL );
2247
ok_x4( ret, ==, CR_INVALID_PROPERTY );
2248
len = sizeof(buffer);
2249
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_UPPERFILTERS, &type, buffer, &len, 0, NULL );
2250
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2251
len = sizeof(buffer);
2252
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_LOWERFILTERS, &type, buffer, &len, 0, NULL );
2253
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2254
len = sizeof(buffer);
2255
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_SECURITY, &type, buffer, &len, 0, NULL );
2256
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2257
len = sizeof(buffer);
2258
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_SECURITY_SDS, &type, buffer, &len, 0, NULL );
2259
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2260
len = sizeof(buffer);
2261
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_DEVTYPE, &type, buffer, &len, 0, NULL );
2262
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2263
len = sizeof(buffer);
2264
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_EXCLUSIVE, &type, buffer, &len, 0, NULL );
2265
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2266
len = sizeof(buffer);
2267
ret = CM_Get_Class_Registry_PropertyW( &guid, CM_CRP_CHARACTERISTICS, &type, buffer, &len, 0, NULL );
2268
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2269
}
2270
2271
static void test_CM_Get_Class_Property(void)
2272
{
2273
GUID guid = GUID_DEVCLASS_DISPLAY;
2274
BYTE buffer[1024];
2275
DWORD type, len;
2276
CONFIGRET ret;
2277
2278
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, NULL, NULL, NULL, 0, NULL );
2279
ok_x4( ret, ==, CR_INVALID_POINTER );
2280
ret = CM_Get_Class_Property_ExW( NULL, &DEVPKEY_DeviceClass_Name, &type, buffer, &len, 0, NULL );
2281
ok_x4( ret, ==, CR_INVALID_POINTER );
2282
ret = CM_Get_Class_Property_ExW( &guid, NULL, &type, buffer, &len, 0, NULL );
2283
ok_x4( ret, ==, CR_FAILURE );
2284
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, buffer, NULL, 0, NULL );
2285
ok_x4( ret, ==, CR_INVALID_POINTER );
2286
len = 1;
2287
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, NULL, &len, 0, NULL );
2288
ok_x4( ret, ==, CR_INVALID_POINTER );
2289
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, NULL, buffer, &len, 0, NULL );
2290
ok_x4( ret, ==, CR_INVALID_POINTER );
2291
2292
len = 0;
2293
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, NULL, &len, 0, NULL );
2294
ok_x4( ret, ==, CR_BUFFER_SMALL );
2295
ok_x4( len, ==, 0x22 );
2296
len = 1;
2297
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, buffer, &len, 0, NULL );
2298
ok_x4( ret, ==, CR_BUFFER_SMALL );
2299
ok_x4( len, ==, 0x22 );
2300
2301
len = sizeof(buffer);
2302
memset( &guid, 0xcd, sizeof(guid) );
2303
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, buffer, &len, 0, NULL );
2304
ok_x4( ret, ==, CR_NO_SUCH_REGISTRY_KEY );
2305
ok_x4( len, ==, 0 );
2306
2307
2308
guid = GUID_DEVCLASS_DISPLAY;
2309
len = sizeof(buffer);
2310
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceInterface_Enabled, &type, buffer, &len, 0, NULL );
2311
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2312
2313
type = 0xdeadbeef;
2314
len = sizeof(buffer);
2315
memset( buffer, 0xcd, sizeof(buffer) );
2316
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, buffer, &len, 0, NULL );
2317
ok_x4( ret, ==, CR_SUCCESS );
2318
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2319
ok_x4( len, ==, 0x22 );
2320
ok_wcs( L"Display adapters", (WCHAR *)buffer );
2321
2322
type = 0xdeadbeef;
2323
len = sizeof(buffer);
2324
memset( buffer, 0xcd, sizeof(buffer) );
2325
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_NAME, &type, buffer, &len, 0, NULL );
2326
ok_x4( ret, ==, CR_SUCCESS );
2327
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2328
ok_x4( len, ==, 0x22 );
2329
ok_wcs( L"Display adapters", (WCHAR *)buffer );
2330
2331
type = 0xdeadbeef;
2332
len = sizeof(buffer);
2333
memset( buffer, 0xcd, sizeof(buffer) );
2334
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_ClassName, &type, buffer, &len, 0, NULL );
2335
ok_x4( ret, ==, CR_SUCCESS );
2336
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2337
ok_x4( len, ==, 0x10 );
2338
ok_wcs( L"Display", (WCHAR *)buffer );
2339
2340
len = sizeof(buffer);
2341
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_UpperFilters, &type, buffer, &len, 0, NULL );
2342
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2343
ok_x4( len, ==, 0 );
2344
2345
len = sizeof(buffer);
2346
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_LowerFilters, &type, buffer, &len, 0, NULL );
2347
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2348
ok_x4( len, ==, 0 );
2349
2350
type = 0xdeadbeef;
2351
len = sizeof(buffer);
2352
memset( buffer, 0xcd, sizeof(buffer) );
2353
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Security, &type, buffer, &len, 0, NULL );
2354
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2355
todo_wine ok_x4( type, ==, DEVPROP_TYPE_SECURITY_DESCRIPTOR );
2356
todo_wine ok_x4( len, ==, 0x30 );
2357
2358
type = 0xdeadbeef;
2359
len = sizeof(buffer);
2360
memset( buffer, 0xcd, sizeof(buffer) );
2361
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_SecuritySDS, &type, buffer, &len, 0, NULL );
2362
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2363
todo_wine ok_x4( type, ==, DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING );
2364
todo_wine ok_x4( len, ==, 0x20 );
2365
todo_wine ok_wcs( L"D:P(A;;GA;;;SY)", (WCHAR *)buffer );
2366
2367
2368
type = 0xdeadbeef;
2369
len = sizeof(buffer);
2370
memset( buffer, 0xcd, sizeof(buffer) );
2371
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_DevType, &type, buffer, &len, 0, NULL );
2372
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2373
todo_wine ok_x4( type, ==, DEVPROP_TYPE_UINT32 );
2374
todo_wine ok_x4( len, ==, 4 );
2375
todo_wine ok_x4( *(DWORD *)buffer, ==, 0x23 /* FILE_DEVICE_VIDEO */ );
2376
2377
len = sizeof(buffer);
2378
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Exclusive, &type, buffer, &len, 0, NULL );
2379
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2380
ok_x4( len, ==, 0 );
2381
2382
type = 0xdeadbeef;
2383
len = sizeof(buffer);
2384
memset( buffer, 0xcd, sizeof(buffer) );
2385
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Characteristics, &type, buffer, &len, 0, NULL );
2386
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2387
todo_wine ok_x4( type, ==, DEVPROP_TYPE_UINT32 );
2388
todo_wine ok_x4( len, ==, 4 );
2389
todo_wine ok_x4( *(DWORD *)buffer, ==, 0x100 );
2390
2391
2392
guid = GUID_DEVCLASS_HIDCLASS;
2393
2394
type = 0xdeadbeef;
2395
len = sizeof(buffer);
2396
memset( buffer, 0xcd, sizeof(buffer) );
2397
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Name, &type, buffer, &len, 0, NULL );
2398
ok_x4( ret, ==, CR_SUCCESS );
2399
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2400
ok_x4( len, ==, 0x30 );
2401
ok_wcs( L"Human Interface Devices", (WCHAR *)buffer );
2402
2403
type = 0xdeadbeef;
2404
len = sizeof(buffer);
2405
memset( buffer, 0xcd, sizeof(buffer) );
2406
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_NAME, &type, buffer, &len, 0, NULL );
2407
ok_x4( ret, ==, CR_SUCCESS );
2408
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2409
ok_x4( len, ==, 0x30 );
2410
ok_wcs( L"Human Interface Devices", (WCHAR *)buffer );
2411
2412
type = 0xdeadbeef;
2413
len = sizeof(buffer);
2414
memset( buffer, 0xcd, sizeof(buffer) );
2415
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_ClassName, &type, buffer, &len, 0, NULL );
2416
ok_x4( ret, ==, CR_SUCCESS );
2417
ok_x4( type, ==, DEVPROP_TYPE_STRING );
2418
ok_x4( len, ==, 0x12 );
2419
ok_wcs( L"HIDClass", (WCHAR *)buffer );
2420
2421
len = sizeof(buffer);
2422
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_UpperFilters, &type, buffer, &len, 0, NULL );
2423
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2424
len = sizeof(buffer);
2425
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_LowerFilters, &type, buffer, &len, 0, NULL );
2426
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2427
len = sizeof(buffer);
2428
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Security, &type, buffer, &len, 0, NULL );
2429
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2430
len = sizeof(buffer);
2431
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_SecuritySDS, &type, buffer, &len, 0, NULL );
2432
todo_wine ok_x4( ret, ==, CR_SUCCESS );
2433
len = sizeof(buffer);
2434
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_DevType, &type, buffer, &len, 0, NULL );
2435
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2436
len = sizeof(buffer);
2437
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Exclusive, &type, buffer, &len, 0, NULL );
2438
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2439
len = sizeof(buffer);
2440
ret = CM_Get_Class_Property_ExW( &guid, &DEVPKEY_DeviceClass_Characteristics, &type, buffer, &len, 0, NULL );
2441
ok_x4( ret, ==, CR_NO_SUCH_VALUE );
2442
}
2443
2444
static void test_CM_Open_Device_Interface_Key(void)
2445
{
2446
WCHAR iface[4096], name[MAX_PATH], expect[MAX_PATH], buffer[39], *refstr;
2447
CONFIGRET ret;
2448
HKEY hkey;
2449
GUID guid;
2450
2451
guid = GUID_DEVINTERFACE_HID;
2452
ret = CM_Get_Device_Interface_ListW( &guid, NULL, iface, ARRAY_SIZE(iface), CM_GET_DEVICE_INTERFACE_LIST_PRESENT );
2453
ok_x4( ret, ==, CR_SUCCESS );
2454
2455
wcscpy( name, iface + 4 );
2456
if ((refstr = wcschr( name, '\\' ))) *refstr++ = 0;
2457
else refstr = (WCHAR *)L"";
2458
swprintf( expect, ARRAY_SIZE(expect), L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Control\\DeviceClasses\\%s\\##?#%s\\#%s\\Device Parameters",
2459
guid_string( &guid, buffer, ARRAY_SIZE(buffer) ), name, refstr );
2460
2461
ret = CM_Open_Device_Interface_KeyW( NULL, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, 0 );
2462
ok_x4( ret, ==, CR_INVALID_POINTER );
2463
ret = CM_Open_Device_Interface_KeyW( L"DISPLAY_ADAPTER", KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, 0 );
2464
ok_x4( ret, ==, CR_INVALID_DATA );
2465
ret = CM_Open_Device_Interface_KeyW( L"\\\\?\\WINETEST#WINETEST#0123456#{5b45201d-f2f2-4f3b-85bb-30ff1f953599}", KEY_QUERY_VALUE, RegDisposition_OpenAlways, &hkey, 0 );
2466
ok_x4( ret, ==, CR_NO_SUCH_DEVICE_INTERFACE );
2467
2468
ret = CM_Open_Device_Interface_KeyW( iface, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, 0 );
2469
if (ret == CR_NO_SUCH_REGISTRY_KEY) ret = CM_Open_Device_Interface_KeyW( iface, KEY_QUERY_VALUE, RegDisposition_OpenAlways, &hkey, 0 );
2470
ok_x4( ret, ==, CR_SUCCESS );
2471
check_object_name( hkey, expect );
2472
RegCloseKey( hkey );
2473
if (ret == CR_NO_SUCH_REGISTRY_KEY) RegDeleteKeyW( HKEY_LOCAL_MACHINE, expect + wcslen( L"\\REGISTRY\\MACHINE\\" ) );
2474
2475
for (UINT flag = 1; flag; flag <<= 1)
2476
{
2477
winetest_push_context( "%#x", flag );
2478
ret = CM_Open_Device_Interface_KeyW( iface, KEY_QUERY_VALUE, RegDisposition_OpenExisting, &hkey, flag );
2479
ok_x4( ret, ==, CR_INVALID_FLAG );
2480
winetest_pop_context();
2481
}
2482
}
2483
2484
START_TEST(cfgmgr32)
2485
{
2486
HMODULE mod = GetModuleHandleA("cfgmgr32.dll");
2487
pDevCreateObjectQuery = (void *)GetProcAddress(mod, "DevCreateObjectQuery");
2488
pDevCloseObjectQuery = (void *)GetProcAddress(mod, "DevCloseObjectQuery");
2489
pDevGetObjects = (void *)GetProcAddress(mod, "DevGetObjects");
2490
pDevFreeObjects = (void *)GetProcAddress(mod, "DevFreeObjects");
2491
pDevGetObjectProperties = (void *)GetProcAddress(mod, "DevGetObjectProperties");
2492
pDevFreeObjectProperties = (void *)GetProcAddress(mod, "DevFreeObjectProperties");
2493
pDevFindProperty = (void *)GetProcAddress(mod, "DevFindProperty");
2494
2495
test_CM_MapCrToWin32Err();
2496
test_CM_Enumerate_Classes();
2497
test_CM_Enumerate_Enumerators();
2498
test_CM_Get_Class_Key_Name();
2499
test_CM_Open_Class_Key();
2500
test_CM_Get_Class_Registry_Property();
2501
test_CM_Get_Class_Property();
2502
test_CM_Open_Device_Interface_Key();
2503
test_CM_Get_Device_ID_List();
2504
test_CM_Register_Notification();
2505
test_CM_Get_Device_Interface_List();
2506
test_DevGetObjects();
2507
test_DevCreateObjectQuery();
2508
test_DevGetObjectProperties_invalid();
2509
test_DevFindProperty_invalid();
2510
}
2511
2512