Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/cfgmgr32/tests/cfgmgr32.c
4393 views
1
/*
2
* Copyright (C) 2023 Mohamad Al-Jaf
3
*
4
* This library is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU Lesser General Public
6
* License as published by the Free Software Foundation; either
7
* version 2.1 of the License, or (at your option) any later version.
8
*
9
* This library is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12
* Lesser General Public License for more details.
13
*
14
* You should have received a copy of the GNU Lesser General Public
15
* License along with this library; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17
*/
18
19
#include "wine/test.h"
20
#include "winreg.h"
21
#include "windef.h"
22
#include "winbase.h"
23
#include "winuser.h"
24
#include "objbase.h"
25
#include "devguid.h"
26
#include "initguid.h"
27
#include "devpkey.h"
28
#include "propkey.h"
29
#include "setupapi.h"
30
#include "cfgmgr32.h"
31
#include "ntddvdeo.h"
32
#include "devfiltertypes.h"
33
#include "devquery.h"
34
35
static void test_CM_MapCrToWin32Err(void)
36
{
37
unsigned int i;
38
DWORD ret;
39
40
static const struct
41
{
42
CONFIGRET code;
43
DWORD win32_error;
44
}
45
map_codes[] =
46
{
47
{ CR_SUCCESS, ERROR_SUCCESS },
48
{ CR_OUT_OF_MEMORY, ERROR_NOT_ENOUGH_MEMORY },
49
{ CR_INVALID_POINTER, ERROR_INVALID_USER_BUFFER },
50
{ CR_INVALID_FLAG, ERROR_INVALID_FLAGS },
51
{ CR_INVALID_DEVNODE, ERROR_INVALID_DATA },
52
{ CR_INVALID_DEVINST, ERROR_INVALID_DATA },
53
{ CR_NO_SUCH_DEVNODE, ERROR_NOT_FOUND },
54
{ CR_NO_SUCH_DEVINST, ERROR_NOT_FOUND },
55
{ CR_ALREADY_SUCH_DEVNODE, ERROR_ALREADY_EXISTS },
56
{ CR_ALREADY_SUCH_DEVINST, ERROR_ALREADY_EXISTS },
57
{ CR_BUFFER_SMALL, ERROR_INSUFFICIENT_BUFFER },
58
{ CR_NO_REGISTRY_HANDLE, ERROR_INVALID_HANDLE },
59
{ CR_REGISTRY_ERROR, ERROR_REGISTRY_CORRUPT },
60
{ CR_INVALID_DEVICE_ID, ERROR_INVALID_DATA },
61
{ CR_NO_SUCH_VALUE, ERROR_NOT_FOUND },
62
{ CR_NO_SUCH_REGISTRY_KEY, ERROR_FILE_NOT_FOUND },
63
{ CR_INVALID_MACHINENAME, ERROR_INVALID_DATA },
64
{ CR_REMOTE_COMM_FAILURE, ERROR_SERVICE_NOT_ACTIVE },
65
{ CR_MACHINE_UNAVAILABLE, ERROR_SERVICE_NOT_ACTIVE },
66
{ CR_NO_CM_SERVICES, ERROR_SERVICE_NOT_ACTIVE },
67
{ CR_ACCESS_DENIED, ERROR_ACCESS_DENIED },
68
{ CR_CALL_NOT_IMPLEMENTED, ERROR_CALL_NOT_IMPLEMENTED },
69
{ CR_INVALID_PROPERTY, ERROR_INVALID_DATA },
70
{ CR_NO_SUCH_DEVICE_INTERFACE, ERROR_NOT_FOUND },
71
{ CR_INVALID_REFERENCE_STRING, ERROR_INVALID_DATA },
72
{ CR_DEFAULT, 0xdeadbeef },
73
{ CR_INVALID_RES_DES, 0xdeadbeef },
74
{ CR_INVALID_LOG_CONF, 0xdeadbeef },
75
{ CR_INVALID_ARBITRATOR, 0xdeadbeef },
76
{ CR_INVALID_NODELIST, 0xdeadbeef },
77
{ CR_DEVNODE_HAS_REQS, 0xdeadbeef },
78
{ CR_DEVINST_HAS_REQS, 0xdeadbeef },
79
{ CR_INVALID_RESOURCEID, 0xdeadbeef },
80
{ CR_DLVXD_NOT_FOUND, 0xdeadbeef },
81
{ CR_NO_MORE_LOG_CONF, 0xdeadbeef },
82
{ CR_NO_MORE_RES_DES, 0xdeadbeef },
83
{ CR_INVALID_RANGE_LIST, 0xdeadbeef },
84
{ CR_INVALID_RANGE, 0xdeadbeef },
85
{ CR_FAILURE, 0xdeadbeef },
86
{ CR_NO_SUCH_LOGICAL_DEV, 0xdeadbeef },
87
{ CR_CREATE_BLOCKED, 0xdeadbeef },
88
{ CR_NOT_SYSTEM_VM, 0xdeadbeef },
89
{ CR_REMOVE_VETOED, 0xdeadbeef },
90
{ CR_APM_VETOED, 0xdeadbeef },
91
{ CR_INVALID_LOAD_TYPE, 0xdeadbeef },
92
{ CR_NO_ARBITRATOR, 0xdeadbeef },
93
{ CR_INVALID_DATA, 0xdeadbeef },
94
{ CR_INVALID_API, 0xdeadbeef },
95
{ CR_DEVLOADER_NOT_READY, 0xdeadbeef },
96
{ CR_NEED_RESTART, 0xdeadbeef },
97
{ CR_NO_MORE_HW_PROFILES, 0xdeadbeef },
98
{ CR_DEVICE_NOT_THERE, 0xdeadbeef },
99
{ CR_WRONG_TYPE, 0xdeadbeef },
100
{ CR_INVALID_PRIORITY, 0xdeadbeef },
101
{ CR_NOT_DISABLEABLE, 0xdeadbeef },
102
{ CR_FREE_RESOURCES, 0xdeadbeef },
103
{ CR_QUERY_VETOED, 0xdeadbeef },
104
{ CR_CANT_SHARE_IRQ, 0xdeadbeef },
105
{ CR_NO_DEPENDENT, 0xdeadbeef },
106
{ CR_SAME_RESOURCES, 0xdeadbeef },
107
{ CR_DEVICE_INTERFACE_ACTIVE, 0xdeadbeef },
108
{ CR_INVALID_CONFLICT_LIST, 0xdeadbeef },
109
{ CR_INVALID_INDEX, 0xdeadbeef },
110
{ CR_INVALID_STRUCTURE_SIZE, 0xdeadbeef },
111
{ NUM_CR_RESULTS, 0xdeadbeef },
112
};
113
114
for ( i = 0; i < ARRAY_SIZE(map_codes); i++ )
115
{
116
ret = CM_MapCrToWin32Err( map_codes[i].code, 0xdeadbeef );
117
ok( ret == map_codes[i].win32_error, "%#lx returned unexpected %ld.\n", map_codes[i].code, ret );
118
}
119
}
120
121
HRESULT (WINAPI *pDevCreateObjectQuery)(DEV_OBJECT_TYPE, ULONG, ULONG, const DEVPROPCOMPKEY*, ULONG,
122
const DEVPROP_FILTER_EXPRESSION*, PDEV_QUERY_RESULT_CALLBACK, void*, HDEVQUERY*);
123
void (WINAPI *pDevCloseObjectQuery)(HDEVQUERY);
124
HRESULT (WINAPI *pDevGetObjects)(DEV_OBJECT_TYPE, ULONG, ULONG, const DEVPROPCOMPKEY*, ULONG,
125
const DEVPROP_FILTER_EXPRESSION*, ULONG*, const DEV_OBJECT**);
126
void (WINAPI *pDevFreeObjects)(ULONG, const DEV_OBJECT*);
127
HRESULT (WINAPI *pDevGetObjectProperties)(DEV_OBJECT_TYPE, const WCHAR *, ULONG, ULONG, const DEVPROPCOMPKEY *, ULONG *,
128
const DEVPROPERTY **);
129
void (WINAPI *pDevFreeObjectProperties)(ULONG, const DEVPROPERTY *);
130
const DEVPROPERTY* (WINAPI *pDevFindProperty)(const DEVPROPKEY *, DEVPROPSTORE, PCWSTR, ULONG, const DEVPROPERTY *);
131
132
DEFINE_DEVPROPKEY(DEVPROPKEY_GPU_LUID, 0x60b193cb, 0x5276, 0x4d0f, 0x96, 0xfc, 0xf1, 0x73, 0xab, 0xad, 0x3e, 0xc6, 2);
133
134
static void test_CM_Get_Device_ID_List(void)
135
{
136
struct
137
{
138
WCHAR id[128];
139
DEVINST inst;
140
}
141
instances[128];
142
SP_DEVINFO_DATA device = { sizeof(device) };
143
unsigned int i, count, expected_count;
144
WCHAR wguid_str[64], id[128], *wbuf, *wp;
145
char guid_str[64], id_a[128], *buf, *p;
146
DEVINST devinst;
147
CONFIGRET ret;
148
HDEVINFO set;
149
ULONG len;
150
151
StringFromGUID2(&GUID_DEVCLASS_DISPLAY, wguid_str, ARRAY_SIZE(wguid_str));
152
wp = wguid_str;
153
p = guid_str;
154
while ((*p++ = *wp++))
155
;
156
157
ret = CM_Get_Device_ID_List_SizeW(NULL, wguid_str, CM_GETIDLIST_FILTER_CLASS);
158
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
159
len = 0xdeadbeef;
160
ret = CM_Get_Device_ID_List_SizeW(&len, NULL, CM_GETIDLIST_FILTER_CLASS);
161
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
162
ok(!len, "got %#lx.\n", len);
163
len = 0xdeadbeef;
164
ret = CM_Get_Device_ID_List_SizeW(&len, L"q", CM_GETIDLIST_FILTER_CLASS);
165
ok(ret == CR_INVALID_DATA, "got %#lx.\n", ret);
166
ok(!len, "got %#lx.\n", len);
167
168
ret = CM_Get_Device_ID_List_SizeA(NULL, guid_str, CM_GETIDLIST_FILTER_CLASS);
169
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
170
len = 0xdeadbeef;
171
ret = CM_Get_Device_ID_List_SizeA(&len, NULL, CM_GETIDLIST_FILTER_CLASS);
172
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
173
ok(!len, "got %#lx.\n", len);
174
len = 0xdeadbeef;
175
ret = CM_Get_Device_ID_List_SizeA(&len, "q", CM_GETIDLIST_FILTER_CLASS);
176
ok(ret == CR_INVALID_DATA, "got %#lx.\n", ret);
177
ok(!len, "got %#lx.\n", len);
178
179
len = 0xdeadbeef;
180
ret = CM_Get_Device_ID_List_SizeW(&len, NULL, 0);
181
ok(!ret, "got %#lx.\n", ret);
182
ok(len > 2, "got %#lx.\n", len);
183
184
wbuf = malloc(len * sizeof(*wbuf));
185
buf = malloc(len);
186
187
ret = CM_Get_Device_ID_ListW(NULL, wbuf, len, 0);
188
ok(!ret, "got %#lx.\n", ret);
189
190
len = 0xdeadbeef;
191
ret = CM_Get_Device_ID_List_SizeW(&len, wguid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
192
ok(!ret, "got %#lx.\n", ret);
193
ok(len > 2, "got %lu.\n", len);
194
memset(wbuf, 0xcc, len * sizeof(*wbuf));
195
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, 0, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
196
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
197
ok(wbuf[0] == 0xcccc, "got %#x.\n", wbuf[0]);
198
memset(wbuf, 0xcc, len * sizeof(*wbuf));
199
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, 1, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
200
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
201
ok(!wbuf[0], "got %#x.\n", wbuf[0]);
202
203
len = 0xdeadbeef;
204
ret = CM_Get_Device_ID_List_SizeA(&len, guid_str, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
205
ok(!ret, "got %#lx.\n", ret);
206
ok(len > 2, "got %lu.\n", len);
207
memset(buf, 0x7c, len);
208
ret = CM_Get_Device_ID_ListA(guid_str, buf, 0, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
209
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
210
ok(buf[0] == 0x7c, "got %#x.\n", buf[0]);
211
memset(buf, 0x7c, len);
212
ret = CM_Get_Device_ID_ListA(guid_str, buf, 1, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
213
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
214
ok(buf[0] == 0x7c, "got %#x.\n", buf[0]);
215
216
set = SetupDiGetClassDevsW(&GUID_DEVCLASS_DISPLAY, NULL, NULL, DIGCF_PRESENT);
217
ok(set != &GUID_DEVCLASS_DISPLAY, "got error %#lx.\n", GetLastError());
218
for (i = 0; SetupDiEnumDeviceInfo(set, i, &device); ++i)
219
{
220
ok(i < ARRAY_SIZE(instances), "got %u.\n", i);
221
ret = SetupDiGetDeviceInstanceIdW(set, &device, instances[i].id, sizeof(instances[i].id), NULL);
222
ok(ret, "got error %#lx.\n", GetLastError());
223
instances[i].inst = device.DevInst;
224
}
225
SetupDiDestroyDeviceInfoList(set);
226
expected_count = i;
227
ok(expected_count, "got 0.\n");
228
229
wcscpy(id, L"q");
230
devinst = 0xdeadbeef;
231
ret = CM_Locate_DevNodeW(&devinst, id, 0);
232
todo_wine_if(ret == CR_NO_SUCH_DEVNODE) ok(ret == CR_INVALID_DEVICE_ID, "got %#lx.\n", ret);
233
ok(!devinst, "got %#lx.\n", devinst);
234
235
wcscpy(id, instances[0].id);
236
id[0] = 'Q';
237
ret = CM_Locate_DevNodeW(&devinst, id, 0);
238
ok(ret == CR_NO_SUCH_DEVNODE, "got %#lx.\n", ret);
239
240
for (i = 0; i < expected_count; ++i)
241
{
242
DEVPROPTYPE type;
243
ULONG size;
244
245
*id = 0;
246
ret = CM_Get_Device_IDW(instances[i].inst, id, ARRAY_SIZE(id), 0);
247
ok(!ret, "got %#lx.\n", ret);
248
ok(!wcscmp(id, instances[i].id), "got %s, expected %s.\n", debugstr_w(id), debugstr_w(instances[i].id));
249
size = len;
250
ret = CM_Get_DevNode_PropertyW(instances[i].inst, &DEVPROPKEY_GPU_LUID, &type, wbuf, &size, 0);
251
ok(!ret || ret == CR_NO_SUCH_VALUE, "got %#lx.\n", ret);
252
if (!ret)
253
ok(type == DEVPROP_TYPE_UINT64, "got %#lx.\n", type);
254
255
devinst = 0xdeadbeef;
256
ret = CM_Locate_DevNodeW(&devinst, instances[i].id, 0);
257
ok(!ret, "got %#lx, id %s.\n", ret, debugstr_w(instances[i].id));
258
ok(devinst == instances[i].inst, "got %#lx, expected %#lx.\n", devinst, instances[i].inst);
259
p = id_a;
260
wp = instances[i].id;
261
while((*p++ = *wp++))
262
;
263
devinst = 0xdeadbeef;
264
ret = CM_Locate_DevNodeA(&devinst, id_a, 0);
265
ok(!ret, "got %#lx, id %s.\n", ret, debugstr_a(id_a));
266
ok(devinst == instances[i].inst, "got %#lx, expected %#lx.\n", devinst, instances[i].inst);
267
}
268
269
memset(wbuf, 0xcc, len * sizeof(*wbuf));
270
ret = CM_Get_Device_ID_ListW(wguid_str, wbuf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
271
ok(!ret, "got %#lx.\n", ret);
272
count = 0;
273
wp = wbuf;
274
while (*wp)
275
{
276
++count;
277
ok(!wcsnicmp(wp, L"PCI\\", 4) || !wcsnicmp(wp, L"VMBUS\\", 6), "got %s.\n", debugstr_w(wp));
278
wp += wcslen(wp) + 1;
279
}
280
ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
281
282
memset(buf, 0xcc, len * sizeof(*buf));
283
ret = CM_Get_Device_ID_ListA(guid_str, buf, len, CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT);
284
ok(!ret, "got %#lx.\n", ret);
285
count = 0;
286
p = buf;
287
while (*p)
288
{
289
++count;
290
ok(!strnicmp(p, "PCI\\", 4) || !strnicmp(p, "VMBUS\\", 6), "got %s.\n", debugstr_a(p));
291
p += strlen(p) + 1;
292
}
293
ok(count == expected_count, "got %u, expected %u.\n", count, expected_count);
294
295
free(wbuf);
296
free(buf);
297
}
298
299
DWORD WINAPI notify_callback( HCMNOTIFICATION notify, void *ctx, CM_NOTIFY_ACTION action,
300
CM_NOTIFY_EVENT_DATA *data, DWORD size )
301
{
302
return ERROR_SUCCESS;
303
}
304
305
static void test_CM_Register_Notification( void )
306
{
307
struct
308
{
309
CM_NOTIFY_FILTER filter;
310
CONFIGRET ret;
311
} test_cases[] = {
312
{
313
{ 0, CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0 },
314
CR_INVALID_DATA
315
},
316
{
317
{ sizeof( CM_NOTIFY_FILTER ) + 1, 0, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0,
318
.u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
319
CR_INVALID_DATA
320
},
321
{
322
{ sizeof( CM_NOTIFY_FILTER ), CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES,
323
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0, .u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
324
CR_INVALID_DATA
325
},
326
{
327
{ sizeof( CM_NOTIFY_FILTER ), CM_NOTIFY_FILTER_FLAG_ALL_INTERFACE_CLASSES,
328
CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0 },
329
CR_SUCCESS
330
},
331
{
332
{ sizeof( CM_NOTIFY_FILTER ), 0, CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, 0,
333
.u.DeviceInterface = { GUID_DEVINTERFACE_DISPLAY_ADAPTER } },
334
CR_SUCCESS
335
}
336
};
337
DWORD (WINAPI *pCM_Register_Notification)(PCM_NOTIFY_FILTER,PVOID,PCM_NOTIFY_CALLBACK,PHCMNOTIFICATION) = NULL;
338
DWORD (WINAPI *pCM_Unregister_Notification)(HCMNOTIFICATION) = NULL;
339
HMODULE cfgmgr32 = GetModuleHandleW( L"cfgmgr32" );
340
DWORD i;
341
HCMNOTIFICATION notify = NULL;
342
CONFIGRET ret;
343
344
if (cfgmgr32)
345
{
346
pCM_Register_Notification = (void *)GetProcAddress( cfgmgr32, "CM_Register_Notification" );
347
pCM_Unregister_Notification = (void *)GetProcAddress( cfgmgr32, "CM_Unregister_Notification" );
348
}
349
350
if (!pCM_Register_Notification)
351
{
352
win_skip( "CM_Register_Notification not found, skipping tests\n" );
353
return;
354
}
355
356
ret = pCM_Register_Notification( NULL, NULL, NULL, NULL );
357
ok( ret == CR_FAILURE, "Expected 0x13, got %#lx.\n", ret );
358
359
ret = pCM_Register_Notification( NULL, NULL, NULL, &notify );
360
ok( ret == CR_INVALID_DATA, "Expected 0x1f, got %#lx.\n", ret );
361
ok( !notify, "Expected handle to be NULL, got %p\n", notify );
362
363
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
364
{
365
notify = NULL;
366
winetest_push_context( "test_cases %lu", i );
367
ret = pCM_Register_Notification( &test_cases[i].filter, NULL, notify_callback, &notify );
368
ok( test_cases[i].ret == ret, "Expected %#lx, got %#lx\n", test_cases[i].ret, ret );
369
if (test_cases[i].ret)
370
ok( !notify, "Expected handle to be NULL, got %p\n", notify );
371
if (notify)
372
{
373
ret = pCM_Unregister_Notification( notify );
374
ok( !ret, "Expected 0, got %#lx\n", ret );
375
}
376
winetest_pop_context();
377
}
378
}
379
380
static void check_device_path_casing(const WCHAR *original_path)
381
{
382
HKEY current_key, tmp;
383
WCHAR *path = wcsdup(original_path);
384
WCHAR key_name[MAX_PATH];
385
WCHAR separator[] = L"#";
386
WCHAR *token, *context = NULL;
387
LSTATUS ret;
388
DWORD i;
389
390
ret = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Enum", &current_key);
391
ok(!ret, "Failed to open enum key: %#lx.\n", ret);
392
393
token = wcstok_s(path + 4, separator, &context); /* skip \\?\ */
394
while (token)
395
{
396
if (token[0] == L'{' && wcslen(token) == 38) break; /* reached GUID part, done */
397
398
i = 0;
399
while (!(ret = RegEnumKeyW(current_key, i++, key_name, ARRAY_SIZE(key_name))))
400
{
401
if(!wcscmp(token, key_name))
402
{
403
ret = RegOpenKeyW(current_key, token, &tmp);
404
ok(!ret, "Failed to open registry key %s: %#lx.\n", debugstr_w(token), ret);
405
RegCloseKey(current_key);
406
current_key = tmp;
407
break;
408
}
409
}
410
ok(!ret, "Failed to find %s in registry: %#lx.\n", debugstr_w(token), ret);
411
if (ret) break;
412
413
token = wcstok_s(NULL, separator, &context);
414
}
415
416
RegCloseKey(current_key);
417
free(path);
418
}
419
420
static void test_CM_Get_Device_Interface_List(void)
421
{
422
BYTE iface_detail_buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + 256 * sizeof(WCHAR)];
423
SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
424
SP_DEVICE_INTERFACE_DETAIL_DATA_W *iface_data;
425
SP_DEVINFO_DATA device = { sizeof(device) };
426
WCHAR instance_id[256], expected_id[256];
427
DEVPROPKEY zero_key = {{0}, 0};
428
unsigned int count, count2;
429
char *buffera, *pa;
430
WCHAR *buffer, *p;
431
ULONG size, size2;
432
DEVPROPTYPE type;
433
CONFIGRET ret;
434
HDEVINFO set;
435
GUID guid;
436
BOOL bret;
437
438
guid = GUID_DEVINTERFACE_DISPLAY_ADAPTER;
439
440
ret = CM_Get_Device_Interface_List_SizeW(&size, &guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
441
ok(!ret, "got %#lx.\n", ret);
442
443
buffer = malloc(size * sizeof(*buffer));
444
ret = CM_Get_Device_Interface_ListW( &guid, NULL, buffer, size, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
445
ok(!ret, "got %#lx.\n", ret);
446
447
ret = CM_Get_Device_Interface_List_SizeA(&size2, &guid, NULL, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
448
ok(!ret, "got %#lx.\n", ret);
449
ok(size2 == size, "got %lu, %lu.\n", size, size2);
450
buffera = malloc(size2 * sizeof(*buffera));
451
ret = CM_Get_Device_Interface_ListA(&guid, NULL, buffera, size2, CM_GET_DEVICE_INTERFACE_LIST_PRESENT);
452
ok(!ret, "got %#lx.\n", ret);
453
p = malloc(size2 * sizeof(*p));
454
memset(p, 0xcc, size2 * sizeof(*p));
455
pa = buffera;
456
*p = 0;
457
while (*pa)
458
{
459
MultiByteToWideChar(CP_ACP, 0, pa, -1, p + (pa - buffera), size2 - (pa - buffera));
460
pa += strlen(pa) + 1;
461
}
462
p[pa - buffera] = 0;
463
ok(!memcmp(p, buffer, size * sizeof(*p)), "results differ, %s, %s.\n", debugstr_wn(p, size), debugstr_wn(buffer, size));
464
free(p);
465
free(buffera);
466
467
iface_data = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)iface_detail_buffer;
468
469
count = 0;
470
p = buffer;
471
while (*p)
472
{
473
DEVPROP_BOOLEAN val = DEVPROP_FALSE;
474
475
check_device_path_casing(p);
476
set = SetupDiCreateDeviceInfoListExW(NULL, NULL, NULL, NULL);
477
ok(set != INVALID_HANDLE_VALUE, "got %p.\n", set);
478
bret = SetupDiOpenDeviceInterfaceW(set, p, 0, &iface);
479
ok(bret, "got error %lu.\n", GetLastError());
480
memset(iface_detail_buffer, 0xcc, sizeof(iface_detail_buffer));
481
iface_data->cbSize = sizeof(*iface_data);
482
bret = SetupDiGetDeviceInterfaceDetailW(set, &iface, iface_data, sizeof(iface_detail_buffer), NULL, &device);
483
ok(bret, "got error %lu.\n", GetLastError());
484
ok(!wcsicmp(iface_data->DevicePath, p), "got %s, expected %s.\n", debugstr_w(p), debugstr_w(iface_data->DevicePath));
485
bret = SetupDiGetDeviceInstanceIdW(set, &device, expected_id, ARRAY_SIZE(expected_id), NULL);
486
ok(bret, "got error %lu.\n", GetLastError());
487
SetupDiDestroyDeviceInfoList(set);
488
489
size = 0xdeadbeef;
490
type = 0xdeadbeef;
491
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
492
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
493
ok(type == 0xdeadbeef, "got type %#lx.\n", type);
494
ok(size == 0xdeadbeef, "got %#lx.\n", size);
495
496
size = 0;
497
type = 0xdeadbeef;
498
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
499
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
500
ok(type == DEVPROP_TYPE_STRING, "got type %#lx.\n", type);
501
ok(size && size != 0xdeadbeef, "got %#lx.\n", size);
502
503
ret = CM_Get_Device_Interface_PropertyW(p, NULL, &type, (BYTE *)instance_id, &size, 0);
504
ok(ret == CR_FAILURE, "got %#lx.\n", ret);
505
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, NULL, (BYTE *)instance_id, &size, 0);
506
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
507
ret = CM_Get_Device_Interface_PropertyW(NULL, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
508
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
509
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, NULL, 0);
510
ok(ret == CR_INVALID_POINTER, "got %#lx.\n", ret);
511
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 1);
512
ok(ret == CR_INVALID_FLAG, "got %#lx.\n", ret);
513
514
size = 0;
515
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, NULL, &size, 0);
516
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
517
518
--size;
519
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
520
ok(ret == CR_BUFFER_SMALL, "got %#lx.\n", ret);
521
522
type = 0xdeadbeef;
523
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
524
ok(!ret, "got %#lx.\n", ret);
525
ok(type == DEVPROP_TYPE_STRING, "got type %#lx.\n", type);
526
ok(!wcsicmp(instance_id, expected_id), "got %s, expected %s.\n", debugstr_w(instance_id), debugstr_w(expected_id));
527
528
type = 0xdeadbeef;
529
size = sizeof(val);
530
ret = CM_Get_Device_Interface_PropertyW(p, &DEVPKEY_DeviceInterface_Enabled, &type, (BYTE *)&val, &size, 0);
531
ok(!ret, "got %#lx.\n", ret);
532
ok(type == DEVPROP_TYPE_BOOLEAN, "got type %#lx.\n", type);
533
ok(size == sizeof(val), "got size %lu.\n", size);
534
ok(val == DEVPROP_TRUE, "got val %d.\n", val);
535
536
size = 0;
537
ret = CM_Get_Device_Interface_PropertyW(p, &zero_key, &type, NULL, &size, 0);
538
ok(ret == CR_NO_SUCH_VALUE, "got %#lx.\n", ret);
539
p += wcslen(p) + 1;
540
++count;
541
}
542
543
free(buffer);
544
545
set = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
546
ok(set != INVALID_HANDLE_VALUE, "got %p.\n", set);
547
for (count2 = 0; SetupDiEnumDeviceInterfaces(set, NULL, &guid, count2, &iface); ++count2)
548
;
549
SetupDiDestroyDeviceInfoList(set);
550
ok(count == count2, "got %u, expected %u.\n", count, count2);
551
552
ret = CM_Get_Device_Interface_PropertyW(L"qqq", &DEVPKEY_Device_InstanceId, &type, (BYTE *)instance_id, &size, 0);
553
ok(ret == CR_NO_SUCH_DEVICE_INTERFACE || broken(ret == CR_INVALID_DATA) /* w7 */, "got %#lx.\n", ret);
554
}
555
556
struct test_property
557
{
558
DEVPROPKEY key;
559
DEVPROPTYPE type;
560
};
561
562
DEFINE_DEVPROPKEY(DEVPKEY_dummy, 0xdeadbeef, 0xdead, 0xbeef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 1);
563
564
static BOOL dev_property_val_equal( const DEVPROPERTY *p1, const DEVPROPERTY *p2 )
565
{
566
if (!(p1->Type == p2->Type && p1->BufferSize == p2->BufferSize))
567
return FALSE;
568
switch (p1->Type)
569
{
570
case DEVPROP_TYPE_STRING:
571
return !wcsicmp( (WCHAR *)p1->Buffer, (WCHAR *)p2->Buffer );
572
default:
573
return !memcmp( p1->Buffer, p2->Buffer, p1->BufferSize );
574
}
575
}
576
577
static const char *debugstr_DEVPROP_val( const DEVPROPERTY *prop )
578
{
579
switch (prop->Type)
580
{
581
case DEVPROP_TYPE_STRING:
582
return wine_dbg_sprintf( "{type=%#lx buf=%s buf_len=%lu}", prop->Type, debugstr_w( prop->Buffer ), prop->BufferSize );
583
default:
584
return wine_dbg_sprintf( "{type=%#lx buf=%p buf_len=%lu}", prop->Type, prop->Buffer, prop->BufferSize );
585
}
586
}
587
588
static const char *debugstr_DEVPROPKEY( const DEVPROPKEY *key )
589
{
590
if (!key) return "(null)";
591
return wine_dbg_sprintf( "{%s, %04lx}", debugstr_guid( &key->fmtid ), key->pid );
592
}
593
594
static void test_DevGetObjectProperties( DEV_OBJECT_TYPE type, const WCHAR *id, const DEVPROPERTY *exp_props, ULONG props_len )
595
{
596
DEVPROPCOMPKEY dummy_propcompkey = { DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL };
597
ULONG buf_len, rem_props = props_len, i;
598
const DEVPROPERTY *buf;
599
DEVPROPCOMPKEY *keys;
600
HRESULT hr;
601
602
if (!pDevGetObjectProperties || !pDevFreeObjectProperties || !pDevFindProperty)
603
{
604
win_skip( "Functions unavailable, skipping test. (%p %p %p)\n", pDevGetObjects, pDevFreeObjects, pDevFindProperty );
605
return;
606
}
607
608
hr = pDevGetObjectProperties( type, id, DevQueryFlagUpdateResults, 0, NULL, NULL, NULL );
609
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
610
611
hr = pDevGetObjectProperties( type, id, DevQueryFlagAsyncClose, 0, NULL, &buf_len, &buf );
612
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
613
614
hr = pDevGetObjectProperties( type, id, DevQueryFlagAsyncClose, 0, NULL, &buf_len, &buf );
615
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
616
617
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 1, NULL, &buf_len, &buf );
618
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
619
620
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 0, (DEVPROPCOMPKEY *)0xdeadbeef, &buf_len, &buf );
621
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
622
623
buf = NULL;
624
buf_len = 0;
625
hr = pDevGetObjectProperties( type, id, DevQueryFlagAllProperties, 0, NULL, &buf_len, &buf );
626
ok( hr == S_OK, "got hr %#lx\n", hr );
627
ok( buf_len == props_len, "%lu != %lu\n", buf_len, props_len );
628
for (i = 0; i < props_len; i++)
629
{
630
ULONG j;
631
for (j = 0; j < buf_len; j++)
632
{
633
if (IsEqualDevPropKey( exp_props[i].CompKey.Key, buf[j].CompKey.Key ) && rem_props)
634
{
635
winetest_push_context( "%s", debugstr_DEVPROPKEY( &exp_props[i].CompKey.Key ) );
636
/* ItemNameDisplay for software devices has different values for properties obtained from DevGetObjects
637
* and DevGetObjectProperties. */
638
if (!IsEqualDevPropKey(PKEY_ItemNameDisplay, buf[j].CompKey.Key))
639
{
640
const DEVPROPERTY *found_prop;
641
642
ok( dev_property_val_equal( &exp_props[i], &buf[j] ), "%s != %s\n", debugstr_DEVPROP_val( &buf[j] ),
643
debugstr_DEVPROP_val( &exp_props[i] ) );
644
found_prop = pDevFindProperty( &exp_props[i].CompKey.Key, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
645
ok( found_prop == &buf[i], "got found_prop %p != %p\n", found_prop, &buf[i] );
646
}
647
winetest_pop_context();
648
rem_props--;
649
}
650
}
651
}
652
ok( rem_props == 0, "got rem_props %lu\n", rem_props );
653
pDevFreeObjectProperties( buf_len, buf );
654
655
buf = (DEVPROPERTY *)0xdeadbeef;
656
buf_len = 0xdeadbeef;
657
rem_props = props_len;
658
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 0, NULL, &buf_len, &buf );
659
ok( hr == S_OK, "got hr %#lx\n", hr );
660
ok( buf_len == 0, "got buf_len %lu\n", buf_len );
661
ok( !buf, "got buf %p\n", buf );
662
663
buf = NULL;
664
buf_len = 0;
665
keys = calloc( props_len, sizeof( *keys ) );
666
for (i = 0; i < props_len; i++)
667
keys[i] = exp_props[i].CompKey;
668
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, props_len, keys, &buf_len, &buf );
669
ok( hr == S_OK, "got hr %#lx\n", hr );
670
ok( buf_len == props_len, "%lu != %lu\n", buf_len, props_len );
671
for (i = 0; i < props_len; i++)
672
{
673
ULONG j;
674
for (j = 0; j < buf_len; j++)
675
{
676
if (IsEqualDevPropKey( exp_props[i].CompKey.Key, buf[j].CompKey.Key ))
677
{
678
const DEVPROPERTY *found_prop;
679
680
winetest_push_context( "%s", debugstr_DEVPROPKEY( &exp_props[i].CompKey.Key ) );
681
rem_props--;
682
found_prop = pDevFindProperty( &exp_props[i].CompKey.Key, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
683
ok( found_prop == &buf[j], "got found_prop %p != %p\n", found_prop, &buf[j] );
684
winetest_pop_context();
685
break;
686
}
687
}
688
}
689
ok( rem_props == 0, "got rem_props %lu\n", rem_props );
690
pDevFreeObjectProperties( buf_len, buf );
691
692
buf_len = 0;
693
buf = NULL;
694
hr = pDevGetObjectProperties( type, id, DevQueryFlagNone, 1, &dummy_propcompkey, &buf_len, &buf );
695
ok( hr == S_OK, "got hr %#lx\n", hr );
696
ok( !!buf, "got buf %p", buf );
697
ok( buf_len == 1, "got buf_len %lu\n", buf_len );
698
if (buf)
699
{
700
const DEVPROPERTY *found_prop;
701
702
ok( IsEqualDevPropKey( buf[0].CompKey.Key, DEVPKEY_dummy ), "got propkey {%s, %#lx}\n",
703
debugstr_guid( &buf[0].CompKey.Key.fmtid ), buf[0].CompKey.Key.pid );
704
ok( buf[0].Type == DEVPROP_TYPE_EMPTY, "got Type %#lx\n", buf[0].Type );
705
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, buf_len, buf );
706
ok( found_prop == &buf[0], "got found_prop %p != %p\n", found_prop, &buf[0] );
707
pDevFreeObjectProperties( buf_len, buf );
708
}
709
free( keys );
710
}
711
712
static void test_dev_object_iface_props( int line, const DEV_OBJECT *obj, const struct test_property *exp_props,
713
DWORD props_len )
714
{
715
DWORD i, err, rem_props = props_len;
716
HDEVINFO set;
717
718
set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL );
719
ok_( __FILE__, line )( set != INVALID_HANDLE_VALUE, "SetupDiCreateDeviceInfoListExW failed: %lu\n",
720
GetLastError() );
721
ok_( __FILE__, line )( obj->cPropertyCount >= props_len, "got cPropertyCount %lu, should be >= %lu\n",
722
obj->cPropertyCount, props_len );
723
for (i = 0; i < obj->cPropertyCount && rem_props; i++)
724
{
725
const DEVPROPERTY *property = &obj->pProperties[i];
726
ULONG j;
727
728
for (j = 0; j < props_len; j++)
729
{
730
if (IsEqualDevPropKey( property->CompKey.Key, exp_props[j].key ))
731
{
732
SP_INTERFACE_DEVICE_DATA iface_data = {0};
733
DEVPROPTYPE type = DEVPROP_TYPE_EMPTY;
734
const DEVPROPERTY *found_prop;
735
ULONG size = 0;
736
CONFIGRET ret;
737
BYTE *buf;
738
739
winetest_push_context( "exp_props[%lu]", j );
740
rem_props--;
741
ok_( __FILE__, line )( property->Type == exp_props[j].type, "got type %#lx\n", property->Type );
742
/* Ensure the value matches the value retrieved via SetupDiGetDeviceInterfacePropertyW */
743
buf = calloc( property->BufferSize, 1 );
744
iface_data.cbSize = sizeof( iface_data );
745
ret = SetupDiOpenDeviceInterfaceW( set, obj->pszObjectId, 0, &iface_data );
746
err = GetLastError();
747
ok_( __FILE__, line )( ret || err == ERROR_NO_SUCH_DEVICE_INTERFACE, "SetupDiOpenDeviceInterfaceW failed: %lu\n", err );
748
if (!ret)
749
{
750
winetest_pop_context();
751
free( buf );
752
continue;
753
}
754
ret = SetupDiGetDeviceInterfacePropertyW( set, &iface_data, &property->CompKey.Key, &type, buf,
755
property->BufferSize, &size, 0 );
756
ok_( __FILE__, line )( ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", GetLastError() );
757
SetupDiDeleteDeviceInterfaceData( set, &iface_data );
758
759
ok_( __FILE__, line )( size == property->BufferSize, "got size %lu\n", size );
760
ok_( __FILE__, line )( type == property->Type, "got type %#lx\n", type );
761
if (size == property->BufferSize)
762
{
763
switch (type)
764
{
765
case DEVPROP_TYPE_STRING:
766
ok_( __FILE__, line )( !wcsicmp( (WCHAR *)buf, (WCHAR *)property->Buffer ),
767
"got instance id %s != %s\n", debugstr_w( (WCHAR *)buf ),
768
debugstr_w( (WCHAR *)property->Buffer ) );
769
break;
770
default:
771
ok_( __FILE__, line )( !memcmp( buf, property->Buffer, size ),
772
"got mistmatching property values\n" );
773
break;
774
}
775
}
776
777
found_prop = pDevFindProperty( &property->CompKey.Key, DEVPROP_STORE_SYSTEM, NULL,
778
obj->cPropertyCount, obj->pProperties );
779
ok( found_prop == property, "got found_prop %p != %p\n", found_prop, property );
780
free( buf );
781
winetest_pop_context();
782
break;
783
}
784
}
785
}
786
ok_( __FILE__, line )( rem_props == 0, "got rem %lu != 0\n", rem_props );
787
SetupDiDestroyDeviceInfoList( set );
788
}
789
790
static void filter_add_props( DEVPROP_FILTER_EXPRESSION *filters, ULONG props_len, const DEVPROPERTY *props, BOOL equals )
791
{
792
ULONG i;
793
794
for (i = 0; i < props_len; i++)
795
{
796
filters[i].Operator = equals ? DEVPROP_OPERATOR_EQUALS : DEVPROP_OPERATOR_NOT_EQUALS;
797
filters[i].Property = props[i];
798
}
799
}
800
801
static void test_DevGetObjects( void )
802
{
803
struct {
804
DEV_OBJECT_TYPE object_type;
805
struct test_property exp_props[3];
806
ULONG props_len;
807
} test_cases[] = {
808
{
809
DevObjectTypeDeviceInterface,
810
{
811
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
812
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
813
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
814
},
815
3,
816
},
817
{
818
DevObjectTypeDeviceInterfaceDisplay,
819
{
820
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
821
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
822
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
823
},
824
3,
825
},
826
};
827
static const DEVPROP_OPERATOR invalid_ops[] = {
828
/* Logical operators, need to paired with their CLOSE counterpart. */
829
DEVPROP_OPERATOR_AND_OPEN,
830
DEVPROP_OPERATOR_AND_CLOSE,
831
DEVPROP_OPERATOR_OR_OPEN,
832
DEVPROP_OPERATOR_OR_CLOSE,
833
DEVPROP_OPERATOR_NOT_OPEN,
834
DEVPROP_OPERATOR_NOT_CLOSE,
835
/* Mask value, cannot be used by itself in a filter. */
836
DEVPROP_OPERATOR_MASK_LOGICAL,
837
/* Non-existent operators */
838
0xdeadbeef,
839
};
840
static const DEVPROP_OPERATOR boolean_open_ops[] = {
841
DEVPROP_OPERATOR_AND_OPEN,
842
DEVPROP_OPERATOR_OR_OPEN,
843
DEVPROP_OPERATOR_NOT_OPEN,
844
};
845
/* The difference between CLOSE and OPEN operators is always 0x100000, this is just here for clariy's sake. */
846
static const DEVPROP_OPERATOR boolean_close_ops[] = {
847
DEVPROP_OPERATOR_AND_CLOSE,
848
DEVPROP_OPERATOR_OR_CLOSE,
849
DEVPROP_OPERATOR_NOT_CLOSE,
850
};
851
CHAR bool_val_extra[] = { DEVPROP_TRUE, 0xde, 0xad, 0xbe, 0xef };
852
DEVPROP_BOOLEAN bool_val = DEVPROP_TRUE;
853
const DEVPROP_FILTER_EXPRESSION valid_filter = {
854
DEVPROP_OPERATOR_EQUALS,
855
{
856
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_STORE_SYSTEM, NULL },
857
DEVPROP_TYPE_BOOLEAN,
858
sizeof( bool_val ),
859
&bool_val,
860
}
861
};
862
DEVPROPCOMPKEY prop_iface_class = { DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_STORE_SYSTEM, NULL };
863
DEVPROP_FILTER_EXPRESSION filters[4];
864
const DEV_OBJECT *objects = NULL;
865
DEVPROPCOMPKEY prop_key = {0};
866
HRESULT hr;
867
ULONG i, len = 0;
868
869
if (!pDevGetObjects || !pDevFreeObjects || !pDevFindProperty)
870
{
871
win_skip("Functions unavailable, skipping test. (%p %p %p)\n", pDevGetObjects, pDevFreeObjects, pDevFindProperty);
872
return;
873
}
874
875
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 1, NULL, 0, NULL, &len, &objects );
876
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
877
878
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, NULL, &len, &objects );
879
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
880
881
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, (void *)0xdeadbeef, 0, NULL, &len, &objects );
882
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
883
884
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
885
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
886
887
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagUpdateResults, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
888
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
889
890
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAsyncClose, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
891
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
892
893
hr = pDevGetObjects( DevObjectTypeDeviceInterface, 0xdeadbeef, 0, NULL, 0, (void *)0xdeadbeef, &len, &objects );
894
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
895
896
prop_key.Key = test_cases[0].exp_props[0].key;
897
prop_key.Store = DEVPROP_STORE_SYSTEM;
898
prop_key.LocaleName = NULL;
899
/* DevQueryFlagAllProperties is mutually exlusive with requesting specific properties. */
900
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 1, &prop_key, 0, NULL, &len, &objects );
901
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
902
903
len = 0xdeadbeef;
904
objects = (DEV_OBJECT *)0xdeadbeef;
905
hr = pDevGetObjects( DevObjectTypeUnknown, DevQueryFlagNone, 0, NULL, 0, NULL, &len, &objects );
906
ok( hr == S_OK, "got hr %#lx\n", hr );
907
ok( len == 0, "got len %lu\n", len );
908
ok( !objects, "got objects %p\n", objects );
909
910
len = 0xdeadbeef;
911
objects = (DEV_OBJECT *)0xdeadbeef;
912
hr = pDevGetObjects( 0xdeadbeef, DevQueryFlagNone, 0, NULL, 0, NULL, &len, &objects );
913
ok( hr == S_OK, "got hr %#lx\n", hr );
914
ok( len == 0, "got len %lu\n", len );
915
ok( !objects, "got objects %p\n", objects );
916
917
/* Filter expressions */
918
memset( filters, 0, sizeof( filters ) );
919
filters[0] = valid_filter;
920
921
/* Invalid buffer value */
922
filters[0].Property.Buffer = NULL;
923
len = 0xdeadbeef;
924
objects = (DEV_OBJECT *)0xdeadbeef;
925
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
926
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
927
/* Filters are validated before len and objects are modified. */
928
ok( len == 0xdeadbeef, "got len %lu\n", len );
929
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
930
931
/* Mismatching BufferSize */
932
len = 0xdeadbeef;
933
objects = (DEV_OBJECT *)0xdeadbeef;
934
filters[0].Property.Buffer = &bool_val;
935
filters[0].Property.BufferSize = 0;
936
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
937
/* BufferSize is not validated in Windows 10 and before, but no objects are returned. */
938
ok( hr == E_INVALIDARG || broken( hr == S_OK ), "got hr %#lx\n", hr );
939
ok( len == 0xdeadbeef || broken( !len ), "got len %lu\n", len );
940
ok( objects == (DEV_OBJECT *)0xdeadbeef || broken( !objects ), "got objects %p\n", objects );
941
942
len = 0xdeadbeef;
943
objects = (DEV_OBJECT *)0xdeadbeef;
944
filters[0].Property.Buffer = bool_val_extra;
945
filters[0].Property.BufferSize = sizeof( bool_val_extra );
946
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
947
/* The extra bytes are ignored in Windows 10 and before. */
948
ok( hr == E_INVALIDARG || broken( hr == S_OK ), "got hr %#lx\n", hr );
949
ok( len == 0xdeadbeef || broken( len ), "got len %lu\n", len );
950
ok( objects == (DEV_OBJECT *)0xdeadbeef || broken( !!objects ), "got objects %p\n", objects );
951
if (SUCCEEDED( hr )) pDevFreeObjects( len, objects );
952
953
for (i = 0; i < ARRAY_SIZE( invalid_ops ); i++)
954
{
955
winetest_push_context( "invalid_ops[%lu]", i );
956
filters[0].Operator = invalid_ops[i];
957
958
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, filters, &len, &objects );
959
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
960
961
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
962
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
963
964
winetest_pop_context();
965
}
966
967
memset( &filters[0], 0, sizeof( *filters ) );
968
/* MSDN says this is not a valid operator. However, using this does not fail, but the returned object list is empty. */
969
filters[0].Operator = DEVPROP_OPERATOR_NONE;
970
len = 0xdeadbeef;
971
objects = (DEV_OBJECT *)0xdeadbeef;
972
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
973
ok( hr == S_OK, "got hr %#lx\n", hr );
974
ok( !len, "got len %lu\n", len );
975
ok( !objects, "got objects %p\n", objects );
976
977
filters[1] = valid_filter;
978
/* DEVPROP_OPERATOR_NONE preceeding the next filter expression has the same result. */
979
len = 0xdeadbeef;
980
objects = (DEV_OBJECT *)0xdeadbeef;
981
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
982
ok( hr == S_OK, "got hr %#lx\n", hr );
983
ok( !len, "got len %lu\n", len );
984
ok( !objects, "got objects %p\n", objects );
985
986
/* However, filter expressions are still validated. */
987
filters[1].Property.Buffer = NULL;
988
len = 0xdeadbeef;
989
objects = (DEV_OBJECT *)0xdeadbeef;
990
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 2, filters, &len, &objects );
991
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
992
ok( len == 0xdeadbeef, "got len %lu\n", len );
993
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
994
995
filters[0] = valid_filter;
996
/* DEVPROP_OPERATOR_EXISTS ignores the property type. */
997
len = 0;
998
objects = NULL;
999
filters[0].Operator = DEVPROP_OPERATOR_EXISTS;
1000
filters[0].Property.Type = DEVPROP_TYPE_GUID;
1001
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 1, &filters[0], &len, &objects );
1002
ok( hr == S_OK, "got hr %#lx\n", hr );
1003
ok( len, "got len %lu\n", len );
1004
pDevFreeObjects( len, objects );
1005
1006
/* Don't fetch any properties, but still use them in the filter. */
1007
filters[0] = valid_filter;
1008
len = 0;
1009
objects = NULL;
1010
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, &filters[0], &len, &objects );
1011
ok( hr == S_OK, "got hr %#lx\n", hr );
1012
ok( len, "got len %lu\n", len );
1013
for (i = 0; i < len; i++)
1014
{
1015
/* No properties should have been fetched. */
1016
winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) );
1017
ok( !objects[i].cPropertyCount, "got cPropertyCount %lu\n", objects[i].cPropertyCount );
1018
ok( !objects[i].pProperties, "got pProperties %p\n", objects[i].pProperties );
1019
winetest_pop_context();
1020
}
1021
pDevFreeObjects( len, objects );
1022
1023
/* Request and filter different properties, make sure we *only* get the properties we requested. */
1024
len = 0;
1025
objects = NULL;
1026
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 1, &prop_iface_class, 1, &filters[0], &len, &objects );
1027
ok( hr == S_OK, "got hr %#lx\n", hr );
1028
ok( len, "got len %lu\n", len );
1029
for (i = 0; i < len; i++)
1030
{
1031
const DEVPROPERTY *prop;
1032
1033
winetest_push_context( "object %s", debugstr_w( objects[i].pszObjectId ) );
1034
ok( objects[i].cPropertyCount == 1, "got cPropertyCount %lu\n", objects[i].cPropertyCount );
1035
prop = pDevFindProperty( &prop_iface_class.Key, prop_iface_class.Store, prop_iface_class.LocaleName,
1036
objects[i].cPropertyCount, objects[i].pProperties );
1037
ok (!!prop, "got prop %p\n", prop );
1038
winetest_pop_context();
1039
}
1040
1041
/* AND/OR with a single expression */
1042
memset( filters, 0, sizeof( filters ) );
1043
filters[0].Operator = DEVPROP_OPERATOR_AND_OPEN;
1044
filters[1] = valid_filter;
1045
filters[2].Operator = DEVPROP_OPERATOR_AND_CLOSE;
1046
len = 0;
1047
objects = NULL;
1048
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 3, filters, &len, &objects );
1049
ok( hr == S_OK, "got hr %#lx\n", hr );
1050
ok( len, "got len %lu\n", len );
1051
for (i = 0; i < len; i++)
1052
{
1053
const DEVPROPERTY *prop;
1054
1055
prop = pDevFindProperty( &valid_filter.Property.CompKey.Key, valid_filter.Property.CompKey.Store,
1056
valid_filter.Property.CompKey.LocaleName, objects[i].cPropertyCount,
1057
objects[i].pProperties );
1058
ok( !!prop, "got prop %p\n", prop );
1059
}
1060
pDevFreeObjects( len, objects );
1061
1062
filters[0].Operator = DEVPROP_OPERATOR_OR_OPEN;
1063
filters[2].Operator = DEVPROP_OPERATOR_OR_CLOSE;
1064
len = 0;
1065
objects = NULL;
1066
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties, 0, NULL, 3, filters, &len, &objects );
1067
ok( hr == S_OK, "got hr %#lx\n", hr );
1068
ok( len, "got len %lu\n", len );
1069
for (i = 0; i < len; i++)
1070
{
1071
const DEVPROPERTY *prop;
1072
1073
prop = pDevFindProperty( &valid_filter.Property.CompKey.Key, valid_filter.Property.CompKey.Store,
1074
valid_filter.Property.CompKey.LocaleName, objects[i].cPropertyCount,
1075
objects[i].pProperties );
1076
ok( !!prop, "got prop %p\n", prop );
1077
}
1078
pDevFreeObjects( len, objects );
1079
1080
memset(filters, 0, sizeof( filters ) );
1081
filters[0] = valid_filter;
1082
filters[0].Operator = DEVPROP_OPERATOR_NOT_EXISTS;
1083
/* All device interfaces have this property, so this should not return any objects. */
1084
len = 0xdeadbeef;
1085
objects = (DEV_OBJECT *)0xdeadbeef;
1086
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, &filters[0], &len, &objects );
1087
ok( hr == S_OK, "got hr %#lx\n", hr );
1088
ok( len == 0, "got len %lu\n", len );
1089
ok( !objects, "got objects %p\n", objects );
1090
1091
/* Empty expressions */
1092
memset( filters, 0, sizeof( filters ) );
1093
for (i = 0; i < ARRAY_SIZE( boolean_open_ops ); i++)
1094
{
1095
DEVPROP_OPERATOR open = boolean_open_ops[i], close = boolean_close_ops[i];
1096
1097
winetest_push_context( "open=%#x, close=%#x", open, close );
1098
1099
filters[0].Operator = open;
1100
filters[1].Operator = close;
1101
len = 0xdeadbeef;
1102
objects = (DEV_OBJECT *)0xdeadbeef;
1103
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 2, filters, &len, &objects );
1104
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1105
ok( len == 0xdeadbeef, "got len %lu\n", len );
1106
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1107
1108
/* Empty nested expressions */
1109
filters[0].Operator = filters[1].Operator = open;
1110
filters[2].Operator = filters[3].Operator = close;
1111
len = 0xdeadbeef;
1112
objects = (DEV_OBJECT *)0xdeadbeef;
1113
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 4, filters, &len, &objects );
1114
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1115
ok( len == 0xdeadbeef, "got len %lu\n", len );
1116
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1117
1118
winetest_pop_context();
1119
}
1120
1121
memset( filters, 0, sizeof( filters ) );
1122
filters[1] = valid_filter;
1123
/* Improperly paired expressions */
1124
for (i = 0; i < ARRAY_SIZE( boolean_open_ops ); i++)
1125
{
1126
DEVPROP_OPERATOR open = boolean_open_ops[i];
1127
ULONG j;
1128
1129
for (j = 0; j < ARRAY_SIZE( boolean_close_ops ) && i != j; j++)
1130
{
1131
DEVPROP_OPERATOR close = boolean_close_ops[j];
1132
1133
winetest_push_context( "open=%#x, close=%#x", open, close );
1134
1135
filters[0].Operator = open;
1136
filters[2].Operator = close;
1137
len = 0xdeadbeef;
1138
objects = (DEV_OBJECT *)0xdeadbeef;
1139
hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 3, filters, &len, &objects );
1140
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1141
ok( len == 0xdeadbeef, "got len %lu\n", len );
1142
ok( objects == (DEV_OBJECT *)0xdeadbeef, "got objects %p\n", objects );
1143
1144
winetest_pop_context();
1145
}
1146
}
1147
1148
for (i = 0; i < ARRAY_SIZE( test_cases ); i++)
1149
{
1150
const DEV_OBJECT *objects = NULL;
1151
ULONG j, len = 0;
1152
1153
/* Get all objects of this type, with all properties. */
1154
objects = NULL;
1155
len = 0;
1156
winetest_push_context( "test_cases[%lu]", i );
1157
hr = pDevGetObjects( test_cases[i].object_type, DevQueryFlagAllProperties, 0, NULL, 0, NULL, &len, &objects );
1158
ok( hr == S_OK, "got hr %#lx\n", hr );
1159
for (j = 0; j < len; j++)
1160
{
1161
DEVPROP_FILTER_EXPRESSION *filters;
1162
const DEV_OBJECT *obj = &objects[j], *objects2;
1163
ULONG k, len2 = 0;
1164
BOOL found = FALSE;
1165
1166
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) );
1167
ok( obj->ObjectType == test_cases[i].object_type, "got ObjectType %d\n", obj->ObjectType );
1168
test_dev_object_iface_props( __LINE__, obj, test_cases[i].exp_props, test_cases[i].props_len );
1169
winetest_push_context( "%d", __LINE__ );
1170
test_DevGetObjectProperties( obj->ObjectType, obj->pszObjectId, obj->pProperties, obj->cPropertyCount );
1171
winetest_pop_context();
1172
1173
/* Create a filter for all properties of this object. */
1174
filters = calloc( obj->cPropertyCount, sizeof( *filters ) );
1175
/* If there are no logical operators present, then logical AND is used. */
1176
filter_add_props( filters, obj->cPropertyCount, obj->pProperties, TRUE );
1177
hr = pDevGetObjects( test_cases[i].object_type, DevQueryFlagAllProperties, 0, NULL, obj->cPropertyCount,
1178
filters, &len2, &objects2 );
1179
ok( hr == S_OK, "got hr %#lx\n", hr );
1180
/* For device interface objects, DEVPKEY_Device_Instance and DEVPKEY_DeviceInterface_ClassGuid are a
1181
* unique pair, so there should only be one object. */
1182
if (test_cases[i].object_type == DevObjectTypeDeviceInterface
1183
|| test_cases[i].object_type == DevObjectTypeDeviceInterfaceDisplay)
1184
ok( len2 == 1, "got len2 %lu\n", len2 );
1185
else
1186
ok( len2, "got len2 %lu\n", len2 );
1187
for (k = 0; k < len2; k++)
1188
{
1189
if (!wcsicmp( objects2[k].pszObjectId, obj->pszObjectId ))
1190
{
1191
found = TRUE;
1192
break;
1193
}
1194
}
1195
ok( found, "failed to get object using query filters\n" );
1196
pDevFreeObjects( len2, objects2 );
1197
free( filters );
1198
winetest_pop_context();
1199
}
1200
pDevFreeObjects( len, objects );
1201
1202
/* Get all objects of this type, but only with a single requested property. */
1203
for (j = 0; j < test_cases[i].props_len; j++)
1204
{
1205
const struct test_property *prop = &test_cases[i].exp_props[j];
1206
ULONG k;
1207
1208
winetest_push_context( "exp_props[%lu]", j );
1209
objects = NULL;
1210
len = 0;
1211
prop_key.Key = prop->key;
1212
prop_key.LocaleName = NULL;
1213
prop_key.Store = DEVPROP_STORE_SYSTEM;
1214
hr = pDevGetObjects( test_cases[i].object_type, 0, 1, &prop_key, 0, NULL, &len, &objects );
1215
ok( hr == S_OK, "got hr %#lx\n", hr );
1216
ok( len, "got buf_len %lu\n", len );
1217
ok( !!objects, "got objects %p\n", objects );
1218
for (k = 0; k < len; k++)
1219
{
1220
const DEV_OBJECT *obj = &objects[k];
1221
const DEVPROPERTY *found_prop;
1222
1223
winetest_push_context( "objects[%lu]", k );
1224
ok( obj->cPropertyCount == 1, "got cPropertyCount %lu != 1\n", obj->cPropertyCount );
1225
ok( !!obj->pProperties, "got pProperties %p\n", obj->pProperties );
1226
if (obj->pProperties)
1227
{
1228
ok( IsEqualDevPropKey( obj->pProperties[0].CompKey.Key, prop->key ), "got property {%s, %#lx} != {%s, %#lx}\n",
1229
debugstr_guid( &obj->pProperties[0].CompKey.Key.fmtid ), obj->pProperties[0].CompKey.Key.pid,
1230
debugstr_guid( &prop->key.fmtid ), prop->key.pid );
1231
found_prop = pDevFindProperty( &prop->key, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1232
ok( found_prop == &obj->pProperties[0], "got found_prop %p != %p\n", found_prop, &obj->pProperties[0] );
1233
}
1234
/* Search for a property not in obj->pProperties, we should get NULL, as we haven't requested this
1235
* property in the DevGetObjects call. */
1236
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1237
ok( !found_prop, "got found_prop %p\n", found_prop );
1238
1239
winetest_pop_context();
1240
}
1241
pDevFreeObjects( len, objects );
1242
winetest_pop_context();
1243
}
1244
1245
/* Get all objects of this type, but with a non existent property. The returned objects will still have this
1246
* property, albeit with Type set to DEVPROP_TYPE_EMPTY. */
1247
len = 0;
1248
objects = NULL;
1249
prop_key.Key = DEVPKEY_dummy;
1250
hr = pDevGetObjects( test_cases[i].object_type, 0, 1, &prop_key, 0, NULL, &len, &objects );
1251
ok( hr == S_OK, "got hr %#lx\n", hr );
1252
ok( len, "got len %lu\n", len );
1253
ok( !!objects, "got objects %p\n", objects );
1254
for (j = 0; j < len; j++)
1255
{
1256
const DEV_OBJECT *obj = &objects[j];
1257
1258
winetest_push_context( "objects[%lu]", j );
1259
ok( obj->cPropertyCount == 1, "got cPropertyCount %lu != 1\n", obj->cPropertyCount );
1260
ok( !!obj->pProperties, "got pProperties %p\n", obj->pProperties );
1261
if (obj->pProperties)
1262
{
1263
const DEVPROPERTY *found_prop;
1264
1265
ok( IsEqualDevPropKey( obj->pProperties[0].CompKey.Key, DEVPKEY_dummy ), "got property %s != %s\n",
1266
debugstr_DEVPROPKEY( &obj->pProperties[0].CompKey.Key ), debugstr_DEVPROPKEY( &DEVPKEY_dummy ) );
1267
ok( obj->pProperties[0].Type == DEVPROP_TYPE_EMPTY, "got Type %#lx != %#x", obj->pProperties[0].Type,
1268
DEVPROP_TYPE_EMPTY );
1269
found_prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, obj->cPropertyCount, obj->pProperties );
1270
ok( found_prop == &obj->pProperties[0], "got found_prop %p != %p\n", found_prop, &obj->pProperties[0] );
1271
}
1272
winetest_pop_context();
1273
}
1274
winetest_pop_context();
1275
pDevFreeObjects( len, objects );
1276
}
1277
}
1278
1279
struct query_callback_data
1280
{
1281
int line;
1282
DEV_OBJECT_TYPE exp_type;
1283
const struct test_property *exp_props;
1284
DWORD props_len;
1285
1286
HANDLE enum_completed;
1287
HANDLE closed;
1288
};
1289
1290
static void WINAPI query_result_callback( HDEVQUERY query, void *user_data, const DEV_QUERY_RESULT_ACTION_DATA *action_data )
1291
{
1292
struct query_callback_data *data = user_data;
1293
1294
ok( !!data, "got null user_data\n" );
1295
if (!data) return;
1296
1297
switch (action_data->Action)
1298
{
1299
case DevQueryResultStateChange:
1300
{
1301
DEV_QUERY_STATE state = action_data->Data.State;
1302
ok( state == DevQueryStateEnumCompleted || state == DevQueryStateClosed,
1303
"got unexpected Data.State value: %d\n", state );
1304
switch (state)
1305
{
1306
case DevQueryStateEnumCompleted:
1307
SetEvent( data->enum_completed );
1308
break;
1309
case DevQueryStateClosed:
1310
SetEvent( data->closed );
1311
default:
1312
break;
1313
}
1314
break;
1315
}
1316
case DevQueryResultAdd:
1317
{
1318
const DEV_OBJECT *obj = &action_data->Data.DeviceObject;
1319
winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) );
1320
ok_( __FILE__, data->line )( obj->ObjectType == data->exp_type, "got DeviceObject.ObjectType %d != %d",
1321
obj->ObjectType, data->exp_type );
1322
test_dev_object_iface_props( data->line, &action_data->Data.DeviceObject, data->exp_props, data->props_len );
1323
winetest_pop_context();
1324
break;
1325
}
1326
default:
1327
ok( action_data->Action == DevQueryResultUpdate || action_data->Action == DevQueryResultRemove,
1328
"got unexpected Action %d\n", action_data->Action );
1329
break;
1330
}
1331
}
1332
1333
#define call_DevCreateObjectQuery( a, b, c, d, e, f, g, h, i ) \
1334
call_DevCreateObjectQuery_(__LINE__, (a), (b), (c), (d), (e), (f), (g), (h), (i))
1335
1336
static HRESULT call_DevCreateObjectQuery_( int line, DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len,
1337
const DEVPROPCOMPKEY *props, ULONG filters_len,
1338
const DEVPROP_FILTER_EXPRESSION *filters, PDEV_QUERY_RESULT_CALLBACK callback,
1339
struct query_callback_data *data, HDEVQUERY *devquery )
1340
{
1341
data->line = line;
1342
return pDevCreateObjectQuery( type, flags, props_len, props, filters_len, filters, callback, data, devquery );
1343
}
1344
1345
static void test_DevCreateObjectQuery( void )
1346
{
1347
struct test_property iface_props[3] = {
1348
{ DEVPKEY_DeviceInterface_ClassGuid, DEVPROP_TYPE_GUID },
1349
{ DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN },
1350
{ DEVPKEY_Device_InstanceId, DEVPROP_TYPE_STRING }
1351
};
1352
struct query_callback_data data = {0};
1353
HDEVQUERY query = NULL;
1354
HRESULT hr;
1355
DWORD ret;
1356
1357
if (!pDevCreateObjectQuery || !pDevCloseObjectQuery)
1358
{
1359
win_skip("Functions unavailable, skipping test. (%p %p)\n", pDevCreateObjectQuery, pDevCloseObjectQuery);
1360
return;
1361
}
1362
1363
hr = pDevCreateObjectQuery( DevObjectTypeDeviceInterface, 0, 0, NULL, 0, NULL, NULL, NULL, &query );
1364
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1365
ok( !query, "got query %p\n", query );
1366
1367
hr = pDevCreateObjectQuery( DevObjectTypeDeviceInterface, 0xdeadbeef, 0, NULL, 0, NULL, query_result_callback,
1368
NULL, &query );
1369
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1370
ok( !query, "got query %p\n", query );
1371
1372
data.enum_completed = CreateEventW( NULL, FALSE, FALSE, NULL );
1373
data.closed = CreateEventW( NULL, FALSE, FALSE, NULL );
1374
1375
hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query );
1376
ok( hr == S_OK, "got hr %#lx\n", hr );
1377
ret = WaitForSingleObject( data.enum_completed, 1000 );
1378
ok( !ret, "got ret %lu\n", ret );
1379
pDevCloseObjectQuery( query );
1380
1381
hr = call_DevCreateObjectQuery( 0xdeadbeef, 0, 0, NULL, 0, NULL, &query_result_callback, &data, &query );
1382
ok( hr == S_OK, "got hr %#lx\n", hr );
1383
ret = WaitForSingleObject( data.enum_completed, 1000 );
1384
ok( !ret, "got ret %lu\n", ret );
1385
pDevCloseObjectQuery( query );
1386
1387
hr = call_DevCreateObjectQuery( DevObjectTypeUnknown, DevQueryFlagAsyncClose, 0, NULL, 0, NULL, &query_result_callback,
1388
&data, &query );
1389
ok( hr == S_OK, "got hr %#lx\n", hr );
1390
ret = WaitForSingleObject( data.enum_completed, 1000 );
1391
ok( !ret, "got ret %lu\n", ret );
1392
pDevCloseObjectQuery( query );
1393
ret = WaitForSingleObject( data.closed, 1000 );
1394
ok( !ret, "got ret %lu\n", ret );
1395
1396
data.exp_props = iface_props;
1397
data.props_len = ARRAY_SIZE( iface_props );
1398
1399
data.exp_type = DevObjectTypeDeviceInterface;
1400
hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterface, DevQueryFlagAllProperties | DevQueryFlagAsyncClose, 0,
1401
NULL, 0, NULL, &query_result_callback, &data, &query );
1402
ok( hr == S_OK, "got hr %#lx\n", hr );
1403
ret = WaitForSingleObject( data.enum_completed, 5000 );
1404
ok( !ret, "got ret %lu\n", ret );
1405
pDevCloseObjectQuery( query );
1406
ret = WaitForSingleObject( data.closed, 1000 );
1407
ok( !ret, "got ret %lu\n", ret );
1408
1409
data.exp_type = DevObjectTypeDeviceInterfaceDisplay;
1410
hr = call_DevCreateObjectQuery( DevObjectTypeDeviceInterfaceDisplay, DevQueryFlagAllProperties | DevQueryFlagAsyncClose,
1411
0, NULL, 0, NULL, &query_result_callback, &data, &query );
1412
ok( hr == S_OK, "got hr %#lx\n", hr );
1413
ret = WaitForSingleObject( data.enum_completed, 5000 );
1414
ok( !ret, "got ret %lu\n", ret );
1415
pDevCloseObjectQuery( query );
1416
ret = WaitForSingleObject( data.closed, 1000 );
1417
ok( !ret, "got ret %lu\n", ret );
1418
1419
CloseHandle( data.enum_completed );
1420
CloseHandle( data.closed );
1421
}
1422
1423
static void test_DevGetObjectProperties_invalid( void )
1424
{
1425
HRESULT hr;
1426
1427
if (!pDevGetObjectProperties)
1428
{
1429
win_skip( "Functions unavailable, skipping test. (%p)\n", pDevGetObjectProperties );
1430
return;
1431
}
1432
1433
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 0, NULL, NULL, NULL );
1434
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1435
1436
hr = pDevGetObjectProperties( DevObjectTypeUnknown, L"", 0, 0, NULL, NULL, NULL );
1437
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1438
1439
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, DevQueryFlagAsyncClose, 0, NULL, NULL, NULL );
1440
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1441
1442
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", DevQueryFlagUpdateResults, 0, NULL, NULL, NULL );
1443
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1444
1445
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", 0xdeadbeef, 0, NULL, NULL, NULL );
1446
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1447
1448
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 1, NULL, NULL, NULL );
1449
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1450
1451
hr = pDevGetObjectProperties( DevObjectTypeUnknown, NULL, 0, 0, (DEVPROPCOMPKEY *)0xdeadbeef, NULL, NULL );
1452
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1453
1454
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, L"foobar", 0, 0, NULL, NULL, NULL );
1455
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1456
1457
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterfaceDisplay, L"foobar", 0, 0, NULL, NULL, NULL );
1458
ok( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ), "got hr %#lx\n", hr );
1459
1460
hr = pDevGetObjectProperties( DevObjectTypeDeviceInterface, NULL, 0, 0, NULL, NULL, NULL );
1461
ok( hr == E_INVALIDARG, "got hr %#lx\n", hr );
1462
}
1463
1464
static void test_DevFindProperty_invalid( void )
1465
{
1466
const DEVPROPERTY *prop;
1467
1468
if (!pDevFindProperty)
1469
{
1470
win_skip( "Functions unavailable, skipping test. (%p)\n", pDevFindProperty );
1471
return;
1472
}
1473
1474
prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, 0, NULL );
1475
ok( !prop, "got prop %p\n", prop );
1476
1477
prop = pDevFindProperty( &DEVPKEY_dummy, DEVPROP_STORE_SYSTEM, NULL, 0, (DEVPROPERTY *)0xdeadbeef );
1478
ok( !prop, "got prop %p\n", prop );
1479
}
1480
1481
START_TEST(cfgmgr32)
1482
{
1483
HMODULE mod = GetModuleHandleA("cfgmgr32.dll");
1484
pDevCreateObjectQuery = (void *)GetProcAddress(mod, "DevCreateObjectQuery");
1485
pDevCloseObjectQuery = (void *)GetProcAddress(mod, "DevCloseObjectQuery");
1486
pDevGetObjects = (void *)GetProcAddress(mod, "DevGetObjects");
1487
pDevFreeObjects = (void *)GetProcAddress(mod, "DevFreeObjects");
1488
pDevGetObjectProperties = (void *)GetProcAddress(mod, "DevGetObjectProperties");
1489
pDevFreeObjectProperties = (void *)GetProcAddress(mod, "DevFreeObjectProperties");
1490
pDevFindProperty = (void *)GetProcAddress(mod, "DevFindProperty");
1491
1492
test_CM_MapCrToWin32Err();
1493
test_CM_Get_Device_ID_List();
1494
test_CM_Register_Notification();
1495
test_CM_Get_Device_Interface_List();
1496
test_DevGetObjects();
1497
test_DevCreateObjectQuery();
1498
test_DevGetObjectProperties_invalid();
1499
test_DevFindProperty_invalid();
1500
}
1501
1502