Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/dlls/cfgmgr32/cfgmgr32.c
12343 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 "cfgmgr32_private.h"
21
#include "initguid.h"
22
#include "devpkey.h"
23
24
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
25
26
static LSTATUS guid_from_string( const WCHAR *str, GUID *guid )
27
{
28
UNICODE_STRING guid_str;
29
RtlInitUnicodeString( &guid_str, str );
30
if (RtlGUIDFromString( &guid_str, guid )) return ERROR_INVALID_DATA;
31
return ERROR_SUCCESS;
32
}
33
34
static const WCHAR *guid_string( const GUID *guid, WCHAR *buffer, UINT length )
35
{
36
swprintf( buffer, length, L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
37
guid->Data1, guid->Data2, guid->Data3, guid->Data4[0], guid->Data4[1], guid->Data4[2],
38
guid->Data4[3], guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7] );
39
return buffer;
40
}
41
42
static LSTATUS propkey_from_string( const WCHAR *str, DEVPROPKEY *key )
43
{
44
const WCHAR *pid;
45
LSTATUS err;
46
47
if (!(pid = wcsrchr( str, '\\' ))) return ERROR_INVALID_DATA;
48
if ((err = guid_from_string( str, &key->fmtid ))) return err;
49
if (swscanf( pid + 1, L"%04X", &key->pid ) != 1) return ERROR_INVALID_DATA;
50
return ERROR_SUCCESS;
51
}
52
53
static const WCHAR *propkey_string( const DEVPROPKEY *key, const WCHAR *prefix, WCHAR *buffer, UINT length )
54
{
55
swprintf( buffer, length, L"%s{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}\\%04X", prefix,
56
key->fmtid.Data1, key->fmtid.Data2, key->fmtid.Data3, key->fmtid.Data4[0], key->fmtid.Data4[1], key->fmtid.Data4[2],
57
key->fmtid.Data4[3], key->fmtid.Data4[4], key->fmtid.Data4[5], key->fmtid.Data4[6], key->fmtid.Data4[7], key->pid );
58
return buffer;
59
}
60
61
static const WCHAR control_classW[] = L"System\\CurrentControlSet\\Control\\Class\\";
62
static const WCHAR device_classesW[] = L"System\\CurrentControlSet\\Control\\DeviceClasses\\";
63
static const WCHAR enum_rootW[] = L"System\\CurrentControlSet\\Enum\\";
64
65
static struct key_cache
66
{
67
HKEY root;
68
const WCHAR *prefix;
69
UINT prefix_len;
70
HKEY hkey;
71
} cache[] =
72
{
73
{ HKEY_LOCAL_MACHINE, control_classW, ARRAY_SIZE(control_classW) - 1, (HKEY)-1 },
74
{ HKEY_LOCAL_MACHINE, device_classesW, ARRAY_SIZE(device_classesW) - 1, (HKEY)-1 },
75
{ HKEY_LOCAL_MACHINE, enum_rootW, ARRAY_SIZE(enum_rootW) - 1, (HKEY)-1 },
76
};
77
78
static HKEY cache_root_key( HKEY root, const WCHAR *key, const WCHAR **path )
79
{
80
HKEY hkey;
81
82
for (struct key_cache *entry = cache; entry < cache + ARRAY_SIZE(cache); entry++)
83
{
84
if (entry->root != root) continue;
85
if (wcsnicmp( key, entry->prefix, entry->prefix_len )) continue;
86
if (path) *path = key + entry->prefix_len;
87
88
if (entry->hkey != (HKEY)-1 || RegOpenKeyExW( root, entry->prefix, 0, KEY_ALL_ACCESS, &hkey )) return entry->hkey;
89
if (InterlockedCompareExchangePointer( (void *)&entry->hkey, hkey, (HKEY)-1 ) != (HKEY)-1) RegCloseKey( hkey );
90
return entry->hkey;
91
}
92
93
if (path) *path = key;
94
return root;
95
}
96
97
static LSTATUS open_key( HKEY root, const WCHAR *key, REGSAM access, BOOL open, HKEY *hkey )
98
{
99
if ((root = cache_root_key( root, key, &key )) == (HKEY)-1) return ERROR_FILE_NOT_FOUND;
100
if (open) return RegOpenKeyExW( root, key, 0, access, hkey );
101
return RegCreateKeyExW( root, key, 0, NULL, 0, access, NULL, hkey, NULL );
102
}
103
104
static LSTATUS query_value( HKEY hkey, const WCHAR *value, WCHAR *buffer, DWORD len )
105
{
106
return RegQueryValueExW( hkey, value, NULL, NULL, (BYTE *)buffer, &len );
107
}
108
109
static LSTATUS open_class_key( HKEY root, const WCHAR *key, REGSAM access, BOOL open, HKEY *hkey )
110
{
111
WCHAR path[MAX_PATH];
112
swprintf( path, ARRAY_SIZE(path), L"%s%s", control_classW, key );
113
return open_key( root, path, access, open, hkey );
114
}
115
116
static LSTATUS open_device_classes_key( HKEY root, const WCHAR *key, REGSAM access, BOOL open, HKEY *hkey )
117
{
118
WCHAR path[MAX_PATH];
119
swprintf( path, ARRAY_SIZE(path), L"%s%s", device_classesW, key );
120
return open_key( root, path, access, open, hkey );
121
}
122
123
LSTATUS init_property( struct property *prop, const DEVPROPKEY *key, DEVPROPTYPE *type, void *buffer, DWORD *size )
124
{
125
if (!key) return ERROR_INVALID_PARAMETER;
126
if (!(prop->type = type) || !(prop->size = size)) return ERROR_INVALID_USER_BUFFER;
127
if (!(prop->buffer = buffer) && (*prop->size)) return ERROR_INVALID_USER_BUFFER;
128
prop->ansi = FALSE;
129
prop->key = *key;
130
prop->reg_type = NULL;
131
return ERROR_SUCCESS;
132
}
133
134
static LSTATUS init_registry_property( struct property *prop, const DEVPROPKEY *base, UINT property, DWORD *type, void *buffer, DWORD *size, BOOL ansi )
135
{
136
if (!(prop->size = size)) return ERROR_INVALID_USER_BUFFER;
137
if (!(prop->buffer = buffer) && (*prop->size)) return ERROR_INVALID_USER_BUFFER;
138
prop->type = NULL;
139
prop->ansi = ansi;
140
memcpy( &prop->key, base, sizeof(prop->key) );
141
prop->key.pid = property + 1;
142
prop->reg_type = type;
143
return ERROR_SUCCESS;
144
}
145
146
static LSTATUS query_property( HKEY root, const WCHAR *prefix, DEVPROPTYPE type, struct property *prop )
147
{
148
WCHAR path[MAX_PATH];
149
ULONG reg_type;
150
LSTATUS err;
151
152
err = RegQueryValueExW( root, propkey_string( &prop->key, prefix, path, ARRAY_SIZE(path) ),
153
NULL, &reg_type, prop->buffer, prop->size );
154
if (type == DEVPROP_TYPE_EMPTY) type = reg_type & 0xffff;
155
156
if (!err && !prop->buffer) err = ERROR_MORE_DATA;
157
if ((!err || err == ERROR_MORE_DATA) && prop->type) *prop->type = type;
158
if (err == ERROR_FILE_NOT_FOUND) return ERROR_NOT_FOUND;
159
return err;
160
}
161
162
static LSTATUS query_named_property( HKEY hkey, const WCHAR *nameW, DEVPROPTYPE type, struct property *prop )
163
{
164
LSTATUS err;
165
166
if (!prop->ansi) err = RegQueryValueExW( hkey, nameW, NULL, prop->reg_type, prop->buffer, prop->size );
167
else
168
{
169
char nameA[MAX_PATH];
170
if (nameW) WideCharToMultiByte( CP_ACP, 0, nameW, -1, nameA, sizeof(nameA), NULL, NULL );
171
err = RegQueryValueExA( hkey, nameW ? nameA : NULL, NULL, prop->reg_type, prop->buffer, prop->size );
172
}
173
174
if (!err && !prop->buffer) err = ERROR_MORE_DATA;
175
if ((!err || err == ERROR_MORE_DATA) && prop->type) *prop->type = type;
176
if (err == ERROR_FILE_NOT_FOUND) return ERROR_NOT_FOUND;
177
return err;
178
}
179
180
static LSTATUS return_property( struct property *prop, DEVPROPTYPE type, const void *buffer, UINT size )
181
{
182
LSTATUS err = *prop->size >= size ? ERROR_SUCCESS : ERROR_MORE_DATA;
183
if (!err && prop->buffer) memcpy( prop->buffer, buffer, size );
184
*prop->size = size;
185
*prop->type = type;
186
return err;
187
}
188
189
static LSTATUS return_property_bool( struct property *prop, DEVPROP_BOOLEAN value )
190
{
191
return return_property( prop, DEVPROP_TYPE_BOOLEAN, &value, sizeof(value) );
192
}
193
194
static LSTATUS enum_objects_size( HKEY hkey, const void *object, const WCHAR *path, UINT path_len, void *context )
195
{
196
UINT *total = context;
197
*total += WideCharToMultiByte( CP_ACP, 0, path, path_len, NULL, 0, 0, 0 );
198
return ERROR_SUCCESS;
199
}
200
201
struct enum_objects_append_params
202
{
203
WCHAR *buffer;
204
UINT len;
205
};
206
207
static LSTATUS enum_objects_append( HKEY hkey, const void *object, const WCHAR *path, UINT path_len, void *context )
208
{
209
struct enum_objects_append_params *params = context;
210
211
if (path_len > params->len) return ERROR_MORE_DATA;
212
memcpy( params->buffer, path, path_len * sizeof(WCHAR) );
213
params->buffer += path_len;
214
params->len -= path_len;
215
216
return ERROR_SUCCESS;
217
}
218
219
struct property_desc
220
{
221
const DEVPROPKEY *key;
222
DEVPROPTYPE type;
223
const WCHAR *name;
224
};
225
226
static const struct property_desc class_properties[] =
227
{
228
{ &DEVPKEY_DeviceClass_ClassName, DEVPROP_TYPE_STRING, L"Class" },
229
{ &DEVPKEY_DeviceClass_Name, DEVPROP_TYPE_STRING, L"" },
230
{ &DEVPKEY_NAME, DEVPROP_TYPE_STRING, L"" },
231
/* ansi-compatible CM_CRP properties */
232
{ &DEVPKEY_DeviceClass_UpperFilters, DEVPROP_TYPE_STRING, L"UpperFilters" },
233
{ &DEVPKEY_DeviceClass_LowerFilters, DEVPROP_TYPE_STRING, L"LowerFilters" },
234
{ &DEVPKEY_DeviceClass_Security, DEVPROP_TYPE_SECURITY_DESCRIPTOR, L"Security" },
235
{ &DEVPKEY_DeviceClass_SecuritySDS, DEVPROP_TYPE_SECURITY_DESCRIPTOR_STRING, L"SecuritySDS" },
236
{ &DEVPKEY_DeviceClass_DevType, DEVPROP_TYPE_UINT32, L"DevType" },
237
{ &DEVPKEY_DeviceClass_Exclusive, DEVPROP_TYPE_BOOLEAN, L"Exclusive" },
238
{ &DEVPKEY_DeviceClass_Characteristics, DEVPROP_TYPE_INT32, L"Characteristics" },
239
/* unicode-only properties */
240
{ &DEVPKEY_DeviceClass_Icon, DEVPROP_TYPE_STRING },
241
{ &DEVPKEY_DeviceClass_ClassInstaller, DEVPROP_TYPE_STRING, L"Installer32" },
242
{ &DEVPKEY_DeviceClass_DefaultService, DEVPROP_TYPE_STRING, L"Default Service" },
243
{ &DEVPKEY_DeviceClass_IconPath, DEVPROP_TYPE_STRING_LIST, L"IconPath" },
244
{ &DEVPKEY_DeviceClass_NoDisplayClass, DEVPROP_TYPE_BOOLEAN, L"NoDisplayClass" },
245
{ &DEVPKEY_DeviceClass_NoInstallClass, DEVPROP_TYPE_BOOLEAN, L"NoInstallClass" },
246
{ &DEVPKEY_DeviceClass_NoUseClass, DEVPROP_TYPE_BOOLEAN, L"NoUseClass" },
247
{ &DEVPKEY_DeviceClass_PropPageProvider, DEVPROP_TYPE_STRING, L"EnumPropPages32" },
248
{ &DEVPKEY_DeviceClass_SilentInstall, DEVPROP_TYPE_BOOLEAN, L"SilentInstall" },
249
{ &DEVPKEY_DeviceClass_DHPRebalanceOptOut, DEVPROP_TYPE_BOOLEAN },
250
{ &DEVPKEY_DeviceClass_ClassCoInstallers, DEVPROP_TYPE_STRING_LIST },
251
};
252
253
static LSTATUS query_class_property( HKEY hkey, struct property *prop )
254
{
255
for (UINT i = 0; i < ARRAY_SIZE(class_properties); i++)
256
{
257
const struct property_desc *desc = class_properties + i;
258
if (memcmp( desc->key, &prop->key, sizeof(prop->key) )) continue;
259
if (!desc->name) return query_property( hkey, L"Properties\\", desc->type, prop );
260
return query_named_property( hkey, desc->name, desc->type, prop );
261
}
262
263
if (!memcmp( &DEVPKEY_DeviceClass_UpperFilters, &prop->key, sizeof(prop->key.fmtid) ))
264
{
265
FIXME( "property %#lx not implemented\n", prop->key.pid - 1 );
266
return ERROR_UNKNOWN_PROPERTY;
267
}
268
269
return query_property( hkey, L"Properties\\", DEVPROP_TYPE_EMPTY, prop );
270
}
271
272
static LSTATUS get_class_property( const GUID *class, struct property *prop )
273
{
274
WCHAR path[39];
275
LSTATUS err;
276
HKEY hkey;
277
278
guid_string( class, path, ARRAY_SIZE(path) );
279
if (!(err = open_class_key( HKEY_LOCAL_MACHINE, path, KEY_QUERY_VALUE, TRUE, &hkey )))
280
{
281
err = query_class_property( hkey, prop );
282
RegCloseKey( hkey );
283
}
284
285
if (err && err != ERROR_MORE_DATA) *prop->size = 0;
286
return err;
287
}
288
289
static LSTATUS enum_class_property_keys( HKEY hkey, DEVPROPKEY *buffer, ULONG *size )
290
{
291
ULONG capacity = *size, count = 0;
292
LSTATUS err = ERROR_SUCCESS;
293
HKEY props_key;
294
295
for (UINT i = 0; i < ARRAY_SIZE(class_properties); i++)
296
{
297
const struct property_desc *desc = class_properties + i;
298
if (desc->name && !RegQueryValueExW( hkey, desc->name, NULL, NULL, NULL, NULL ))
299
{
300
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
301
else buffer[count - 1] = *desc->key;
302
}
303
}
304
305
if (!open_key( hkey, L"Properties", KEY_ENUMERATE_SUB_KEYS, TRUE, &props_key ))
306
{
307
WCHAR name[MAX_PATH];
308
for (ULONG i = 0, len = ARRAY_SIZE(name); !RegEnumValueW( props_key, i, name, &len, 0, NULL, NULL, NULL ); i++, len = ARRAY_SIZE(name))
309
{
310
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
311
else err = propkey_from_string( name, buffer + count - 1 );
312
}
313
RegCloseKey( props_key );
314
}
315
316
*size = count;
317
return err;
318
}
319
320
static LSTATUS get_class_property_keys( const GUID *class, DEVPROPKEY *buffer, ULONG *size )
321
{
322
WCHAR path[39];
323
LSTATUS err;
324
HKEY hkey;
325
326
guid_string( class, path, ARRAY_SIZE(path) );
327
if ((err = open_class_key( HKEY_LOCAL_MACHINE, path, KEY_ALL_ACCESS, TRUE, &hkey ))) return err;
328
err = enum_class_property_keys( hkey, buffer, size );
329
RegCloseKey( hkey );
330
331
return err;
332
}
333
334
LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name )
335
{
336
WCHAR *tmp;
337
UINT len;
338
339
if (wcsncmp( name, L"\\\\?\\", 4 )) return ERROR_FILE_NOT_FOUND;
340
len = swprintf( iface->name, MAX_PATH, L"##?#%s", name + 4 );
341
342
if ((tmp = wcschr( iface->name, '\\' ))) *tmp++ = 0;
343
else tmp = iface->name + len;
344
swprintf( iface->refstr, MAX_PATH, L"#%s", tmp );
345
346
if (!(tmp = wcsrchr( iface->name, '#' ))) return ERROR_FILE_NOT_FOUND;
347
return guid_from_string( wcscpy( iface->class, tmp + 1 ), &iface->class_guid );
348
}
349
350
LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey )
351
{
352
WCHAR path[MAX_PATH];
353
swprintf( path, ARRAY_SIZE(path), L"%s\\%s", iface->class, iface->name );
354
return open_device_classes_key( HKEY_LOCAL_MACHINE, path, access, open, hkey );
355
}
356
357
static DEVPROP_BOOLEAN device_interface_enabled( HKEY hkey, const struct device_interface *iface )
358
{
359
DWORD linked, linked_size = sizeof(linked);
360
WCHAR control[MAX_PATH];
361
362
swprintf( control, ARRAY_SIZE(control), L"%s\\Control", iface->refstr );
363
if (RegGetValueW( hkey, control, L"Linked", RRF_RT_DWORD, NULL, &linked, &linked_size )) return DEVPROP_FALSE;
364
return linked ? DEVPROP_TRUE : DEVPROP_FALSE;
365
}
366
367
static LSTATUS enum_class_device_interfaces( HKEY root, struct device_interface *iface, DEVINSTID_W instance_id, BOOL all,
368
enum_objects_cb callback, void *context )
369
{
370
LSTATUS err = ERROR_SUCCESS;
371
HKEY iface_key;
372
373
for (UINT i = 0; !err && !(err = RegEnumKeyW( root, i, iface->name, ARRAY_SIZE(iface->name) )); i++)
374
{
375
WCHAR *tmp, instance[MAX_PATH], path[MAX_PATH];
376
377
if ((err = open_key( root, iface->name, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, TRUE, &iface_key ))) continue;
378
379
if (!(err = query_value( iface_key, L"DeviceInstance", instance, ARRAY_SIZE(instance) )) &&
380
(!instance_id || !wcsicmp( instance_id, instance )))
381
{
382
for (tmp = wcschr( instance, '\\' ); tmp; tmp = wcschr( tmp, '\\' )) *tmp = '#';
383
for (UINT j = 0; !err && !(err = RegEnumKeyW( iface_key, j, iface->refstr, ARRAY_SIZE(iface->refstr) )); j++)
384
{
385
ULONG len = swprintf( path, ARRAY_SIZE(path), L"\\\\?\\%s%s%s", instance, iface->refstr, iface->class );
386
if (all || device_interface_enabled( iface_key, iface )) err = callback( iface_key, iface, path, len + 1, context );
387
}
388
if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS;
389
}
390
391
RegCloseKey( iface_key );
392
}
393
if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS;
394
395
return err;
396
}
397
398
LSTATUS enum_device_interfaces( BOOL all, enum_objects_cb callback, void *context )
399
{
400
struct device_interface iface;
401
LSTATUS err = ERROR_SUCCESS;
402
HKEY root, class_key;
403
404
if ((root = cache_root_key( HKEY_LOCAL_MACHINE, device_classesW, NULL )) == (HKEY)-1) return ERROR_FILE_NOT_FOUND;
405
406
for (UINT i = 0; !err && !(err = RegEnumKeyW( root, i, iface.class, ARRAY_SIZE(iface.class) )); i++)
407
{
408
if ((err = guid_from_string( iface.class, &iface.class_guid ))) continue;
409
if ((err = open_key( root, iface.class, KEY_ENUMERATE_SUB_KEYS, TRUE, &class_key ))) continue;
410
err = enum_class_device_interfaces( class_key, &iface, NULL, all, callback, context );
411
RegCloseKey( class_key );
412
}
413
if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS;
414
415
return err;
416
}
417
418
static LSTATUS enum_device_interface_list( GUID *class, DEVINSTID_W instance_id, BOOL all, enum_objects_cb callback, void *context )
419
{
420
struct device_interface iface;
421
HKEY class_key;
422
LSTATUS err;
423
424
if (instance_id && !*instance_id) instance_id = NULL;
425
426
guid_string( class, iface.class, ARRAY_SIZE(iface.class) );
427
if ((err = open_device_classes_key( HKEY_LOCAL_MACHINE, iface.class, KEY_ENUMERATE_SUB_KEYS, TRUE, &class_key ))) return err;
428
err = enum_class_device_interfaces( class_key, &iface, instance_id, all, callback, context );
429
RegCloseKey( class_key );
430
431
if (!err) callback( NULL, NULL, L"", 1, context );
432
return err;
433
}
434
435
static const struct property_desc device_interface_properties[] =
436
{
437
{ &DEVPKEY_Device_ContainerId, DEVPROP_TYPE_GUID },
438
{ &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, L"FriendlyName" },
439
};
440
441
LSTATUS query_device_interface_property( HKEY hkey, const struct device_interface *iface, struct property *prop )
442
{
443
WCHAR prefix[MAX_PATH];
444
445
if (!memcmp( &DEVPKEY_DeviceInterface_Enabled, &prop->key, sizeof(prop->key) ))
446
return return_property_bool( prop, device_interface_enabled( hkey, iface ) );
447
if (!memcmp( &DEVPKEY_Device_InstanceId, &prop->key, sizeof(prop->key) ))
448
return query_named_property( hkey, L"DeviceInstance", DEVPROP_TYPE_STRING, prop );
449
if (!memcmp( &DEVPKEY_DeviceInterface_ClassGuid, &prop->key, sizeof(prop->key) ))
450
return return_property( prop, DEVPROP_TYPE_GUID, &iface->class_guid, sizeof(iface->class_guid) );
451
452
swprintf( prefix, ARRAY_SIZE(prefix), L"%s\\Properties\\", iface->refstr );
453
for (UINT i = 0; i < ARRAY_SIZE(device_interface_properties); i++)
454
{
455
const struct property_desc *desc = device_interface_properties + i;
456
if (memcmp( desc->key, &prop->key, sizeof(prop->key) )) continue;
457
if (!desc->name) return query_property( hkey, prefix, desc->type, prop );
458
return query_named_property( hkey, desc->name, desc->type, prop );
459
}
460
461
return query_property( hkey, prefix, DEVPROP_TYPE_EMPTY, prop );
462
}
463
464
static LSTATUS get_device_interface_property( const struct device_interface *iface, struct property *prop )
465
{
466
LSTATUS err;
467
HKEY hkey;
468
469
if (!(err = open_device_interface_key( iface, KEY_QUERY_VALUE, TRUE, &hkey )))
470
{
471
err = query_device_interface_property( hkey, iface, prop );
472
RegCloseKey( hkey );
473
}
474
475
if (err && err != ERROR_MORE_DATA) *prop->size = 0;
476
return err;
477
}
478
479
LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size )
480
{
481
ULONG capacity = *size, count = 0;
482
LSTATUS err = ERROR_SUCCESS;
483
WCHAR path[MAX_PATH];
484
HKEY props_key;
485
486
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
487
else buffer[count - 1] = DEVPKEY_DeviceInterface_Enabled;
488
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
489
else buffer[count - 1] = DEVPKEY_Device_InstanceId;
490
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
491
else buffer[count - 1] = DEVPKEY_DeviceInterface_ClassGuid;
492
493
for (UINT i = 0; i < ARRAY_SIZE(device_interface_properties); i++)
494
{
495
const struct property_desc *desc = device_interface_properties + i;
496
if (desc->name && !RegQueryValueExW( hkey, desc->name, NULL, NULL, NULL, NULL ))
497
{
498
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
499
else buffer[count - 1] = *desc->key;
500
}
501
}
502
503
swprintf( path, ARRAY_SIZE(path), L"%s\\Properties", iface->refstr );
504
if (!open_key( hkey, path, KEY_ENUMERATE_SUB_KEYS, TRUE, &props_key ))
505
{
506
WCHAR name[MAX_PATH];
507
for (ULONG i = 0, len = ARRAY_SIZE(name); !RegEnumValueW( props_key, i, name, &len, 0, NULL, NULL, NULL ); i++, len = ARRAY_SIZE(name))
508
{
509
if (capacity < ++count || !buffer) err = ERROR_MORE_DATA;
510
else err = propkey_from_string( name, buffer + count - 1 );
511
}
512
RegCloseKey( props_key );
513
}
514
515
*size = count;
516
return err;
517
}
518
519
static LSTATUS get_device_interface_property_keys( const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size )
520
{
521
LSTATUS err;
522
HKEY hkey;
523
524
if ((err = open_device_interface_key( iface, KEY_ALL_ACCESS, TRUE, &hkey ))) return err;
525
err = enum_device_interface_property_keys( hkey, iface, buffer, size );
526
RegCloseKey( hkey );
527
528
return err;
529
}
530
531
static CONFIGRET map_error( LSTATUS err )
532
{
533
switch (err)
534
{
535
case ERROR_INVALID_PARAMETER: return CR_FAILURE;
536
case ERROR_INVALID_USER_BUFFER: return CR_INVALID_POINTER;
537
case ERROR_FILE_NOT_FOUND: return CR_NO_SUCH_REGISTRY_KEY;
538
case ERROR_MORE_DATA: return CR_BUFFER_SMALL;
539
case ERROR_NO_MORE_ITEMS: return CR_NO_SUCH_VALUE;
540
case ERROR_NOT_FOUND: return CR_NO_SUCH_VALUE;
541
case ERROR_SUCCESS: return CR_SUCCESS;
542
case ERROR_UNKNOWN_PROPERTY: return CR_INVALID_PROPERTY;
543
default: WARN( "unmapped error %lu\n", err ); return CR_FAILURE;
544
}
545
}
546
547
/***********************************************************************
548
* CM_MapCrToWin32Err (cfgmgr32.@)
549
*/
550
DWORD WINAPI CM_MapCrToWin32Err( CONFIGRET code, DWORD default_error )
551
{
552
TRACE( "code: %#lx, default_error: %ld\n", code, default_error );
553
554
switch (code)
555
{
556
case CR_SUCCESS: return ERROR_SUCCESS;
557
case CR_OUT_OF_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
558
case CR_INVALID_POINTER: return ERROR_INVALID_USER_BUFFER;
559
case CR_INVALID_FLAG: return ERROR_INVALID_FLAGS;
560
case CR_INVALID_DEVNODE:
561
case CR_INVALID_DEVICE_ID:
562
case CR_INVALID_MACHINENAME:
563
case CR_INVALID_PROPERTY:
564
case CR_INVALID_REFERENCE_STRING: return ERROR_INVALID_DATA;
565
case CR_NO_SUCH_DEVNODE:
566
case CR_NO_SUCH_VALUE:
567
case CR_NO_SUCH_DEVICE_INTERFACE: return ERROR_NOT_FOUND;
568
case CR_ALREADY_SUCH_DEVNODE: return ERROR_ALREADY_EXISTS;
569
case CR_BUFFER_SMALL: return ERROR_INSUFFICIENT_BUFFER;
570
case CR_NO_REGISTRY_HANDLE: return ERROR_INVALID_HANDLE;
571
case CR_REGISTRY_ERROR: return ERROR_REGISTRY_CORRUPT;
572
case CR_NO_SUCH_REGISTRY_KEY: return ERROR_FILE_NOT_FOUND;
573
case CR_REMOTE_COMM_FAILURE:
574
case CR_MACHINE_UNAVAILABLE:
575
case CR_NO_CM_SERVICES: return ERROR_SERVICE_NOT_ACTIVE;
576
case CR_ACCESS_DENIED: return ERROR_ACCESS_DENIED;
577
case CR_CALL_NOT_IMPLEMENTED: return ERROR_CALL_NOT_IMPLEMENTED;
578
}
579
580
return default_error;
581
}
582
583
/***********************************************************************
584
* CM_Enumerate_Classes_Ex (cfgmgr32.@)
585
*/
586
CONFIGRET WINAPI CM_Enumerate_Classes_Ex( ULONG index, GUID *class, ULONG flags, HMACHINE machine )
587
{
588
WCHAR buffer[39];
589
LSTATUS err;
590
HKEY root;
591
592
TRACE( "index %lu, class %s, flags %#lx, machine %p\n", index, debugstr_guid(class), flags, machine );
593
if (machine) FIXME( "machine %p not implemented!\n", machine );
594
595
if (!class) return CR_INVALID_POINTER;
596
if (flags & ~CM_ENUMERATE_CLASSES_BITS) return CR_INVALID_FLAG;
597
598
if (flags == CM_ENUMERATE_CLASSES_INSTALLER) root = cache_root_key( HKEY_LOCAL_MACHINE, control_classW, NULL );
599
else root = cache_root_key( HKEY_LOCAL_MACHINE, device_classesW, NULL );
600
if (root == (HKEY)-1) return CR_NO_SUCH_REGISTRY_KEY;
601
602
if ((err = RegEnumKeyW( root, index, buffer, ARRAY_SIZE(buffer) ))) return map_error( err );
603
return map_error( guid_from_string( buffer, class ) );
604
}
605
606
/***********************************************************************
607
* CM_Enumerate_Classes (cfgmgr32.@)
608
*/
609
CONFIGRET WINAPI CM_Enumerate_Classes( ULONG index, GUID *class, ULONG flags )
610
{
611
return CM_Enumerate_Classes_Ex( index, class, flags, NULL );
612
}
613
614
/***********************************************************************
615
* CM_Enumerate_Enumerators_ExW (cfgmgr32.@)
616
*/
617
CONFIGRET WINAPI CM_Enumerate_Enumerators_ExW( ULONG index, WCHAR *buffer, ULONG *len, ULONG flags, HMACHINE machine )
618
{
619
LSTATUS err;
620
HKEY root;
621
622
TRACE( "index %lu, buffer %p, len %p, flags %#lx, machine %p\n", index, buffer, len, flags, machine );
623
if (machine) FIXME( "machine %p not implemented!\n", machine );
624
625
if (!buffer || !len) return CR_INVALID_POINTER;
626
if (!*len && buffer) return CR_INVALID_DATA;
627
if (flags) return CR_INVALID_FLAG;
628
629
root = cache_root_key( HKEY_LOCAL_MACHINE, enum_rootW, NULL );
630
if (root == (HKEY)-1) return CR_NO_SUCH_REGISTRY_KEY;
631
632
if (!(err = RegEnumKeyExW( root, index, buffer, len, NULL, NULL, NULL, NULL ))) *len += 1;
633
return map_error( err );
634
}
635
636
/***********************************************************************
637
* CM_Enumerate_Enumerators_ExA (cfgmgr32.@)
638
*/
639
CONFIGRET WINAPI CM_Enumerate_Enumerators_ExA( ULONG index, char *bufferA, ULONG *lenA, ULONG flags, HMACHINE machine )
640
{
641
WCHAR bufferW[MAX_PATH];
642
DWORD lenW = ARRAY_SIZE(bufferW), maxA;
643
CONFIGRET ret;
644
645
TRACE( "index %lu, bufferA %p, lenA %p, flags %#lx, machine %p\n", index, bufferA, lenA, flags, machine );
646
647
if (!bufferA || !lenA) return CR_INVALID_POINTER;
648
if (!(maxA = *lenA) && bufferA) return CR_INVALID_DATA;
649
650
if ((ret = CM_Enumerate_Enumerators_ExW( index, bufferW, &lenW, flags, NULL ))) return ret;
651
if ((*lenA = WideCharToMultiByte( CP_ACP, 0, bufferW, lenW, NULL, 0, NULL, NULL )) > maxA || !bufferA) return CR_BUFFER_SMALL;
652
WideCharToMultiByte( CP_ACP, 0, bufferW, lenW, bufferA, maxA, NULL, NULL );
653
654
return CR_SUCCESS;
655
}
656
657
/***********************************************************************
658
* CM_Enumerate_EnumeratorsW (cfgmgr32.@)
659
*/
660
CONFIGRET WINAPI CM_Enumerate_EnumeratorsW( ULONG index, WCHAR *buffer, ULONG *len, ULONG flags )
661
{
662
return CM_Enumerate_Enumerators_ExW( index, buffer, len, flags, NULL );
663
}
664
665
/***********************************************************************
666
* CM_Enumerate_EnumeratorsA (cfgmgr32.@)
667
*/
668
CONFIGRET WINAPI CM_Enumerate_EnumeratorsA( ULONG index, char *buffer, ULONG *len, ULONG flags )
669
{
670
return CM_Enumerate_Enumerators_ExA( index, buffer, len, flags, NULL );
671
}
672
673
/***********************************************************************
674
* CM_Get_Class_Key_Name_ExW (cfgmgr32.@)
675
*/
676
CONFIGRET WINAPI CM_Get_Class_Key_Name_ExW( GUID *guid, WCHAR *name, ULONG *len, ULONG flags, HMACHINE machine )
677
{
678
UINT capacity;
679
680
TRACE( "guid %s, name %p, len %p, flags %#lx, machine %p\n", debugstr_guid(guid), name, len, flags, machine );
681
if (machine) FIXME( "machine %p not implemented!\n", machine );
682
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
683
684
if (!guid || !len) return CR_INVALID_POINTER;
685
if ((capacity = *len) && !name) return CR_INVALID_POINTER;
686
687
*len = 39;
688
if (capacity < *len) return CR_BUFFER_SMALL;
689
guid_string( guid, name, capacity );
690
return CR_SUCCESS;
691
}
692
693
/***********************************************************************
694
* CM_Get_Class_Key_Name_ExA (cfgmgr32.@)
695
*/
696
CONFIGRET WINAPI CM_Get_Class_Key_Name_ExA( GUID *class, char *nameA, ULONG *len, ULONG flags, HMACHINE machine )
697
{
698
WCHAR nameW[39];
699
CONFIGRET ret;
700
701
if ((ret = CM_Get_Class_Key_Name_ExW( class, nameA ? nameW : NULL, len, flags, machine ))) return ret;
702
if (nameA) WideCharToMultiByte( CP_ACP, 0, nameW, 39, nameA, 39, NULL, NULL );
703
704
return CR_SUCCESS;
705
}
706
707
/***********************************************************************
708
* CM_Get_Class_Key_NameW (cfgmgr32.@)
709
*/
710
CONFIGRET WINAPI CM_Get_Class_Key_NameW( GUID *class, WCHAR *name, ULONG *len, ULONG flags )
711
{
712
return CM_Get_Class_Key_Name_ExW( class, name, len, flags, NULL );
713
}
714
715
/***********************************************************************
716
* CM_Get_Class_Key_NameA (cfgmgr32.@)
717
*/
718
CONFIGRET WINAPI CM_Get_Class_Key_NameA( GUID *class, char *name, ULONG *len, ULONG flags )
719
{
720
return CM_Get_Class_Key_Name_ExA( class, name, len, flags, NULL );
721
}
722
723
/***********************************************************************
724
* CM_Open_Class_Key_ExW (cfgmgr32.@)
725
*/
726
CONFIGRET WINAPI CM_Open_Class_Key_ExW( GUID *class, const WCHAR *name, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags, HMACHINE machine )
727
{
728
BOOL open = disposition == RegDisposition_OpenExisting;
729
WCHAR buffer[39];
730
731
TRACE( "class %s, name %s, access %#lx, disposition %#lx, hkey %p, flags %#lx\n", debugstr_guid(class), debugstr_w(name), access, disposition, hkey, flags );
732
if (machine) FIXME( "machine %p not implemented!\n", machine );
733
734
if (name) return CR_INVALID_DATA;
735
if (!hkey) return CR_INVALID_POINTER;
736
if (flags & ~CM_OPEN_CLASS_KEY_BITS) return CR_INVALID_FLAG;
737
738
if (!class) *buffer = 0;
739
else guid_string( class, buffer, ARRAY_SIZE(buffer) );
740
741
if (flags == CM_OPEN_CLASS_KEY_INSTALLER) return map_error( open_class_key( HKEY_LOCAL_MACHINE, buffer, access, open, hkey ) );
742
return map_error( open_device_classes_key( HKEY_LOCAL_MACHINE, buffer, access, open, hkey ) );
743
}
744
745
/***********************************************************************
746
* CM_Open_Class_Key_ExA (cfgmgr32.@)
747
*/
748
CONFIGRET WINAPI CM_Open_Class_Key_ExA( GUID *class, const char *nameA, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags, HMACHINE machine )
749
{
750
WCHAR nameW[MAX_PATH];
751
752
TRACE( "guid %s, nameA %s, access %#lx, disposition %#lx, hkey %p, flags %#lx\n", debugstr_guid(class), debugstr_a(nameA), access, disposition, hkey, flags );
753
754
if (nameA) MultiByteToWideChar( CP_ACP, 0, nameA, -1, nameW, ARRAY_SIZE(nameW) );
755
return CM_Open_Class_Key_ExW( class, nameA ? nameW : NULL, access, disposition, hkey, flags, machine );
756
}
757
758
/***********************************************************************
759
* CM_Open_Class_KeyW (cfgmgr32.@)
760
*/
761
CONFIGRET WINAPI CM_Open_Class_KeyW( GUID *class, const WCHAR *name, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags )
762
{
763
return CM_Open_Class_Key_ExW( class, name, access, disposition, hkey, flags, NULL );
764
}
765
766
/***********************************************************************
767
* CM_Open_Class_KeyA (cfgmgr32.@)
768
*/
769
CONFIGRET WINAPI CM_Open_Class_KeyA( GUID *class, const char *name, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags )
770
{
771
return CM_Open_Class_Key_ExA( class, name, access, disposition, hkey, flags, NULL );
772
}
773
774
/***********************************************************************
775
* CM_Get_Class_Registry_PropertyW (cfgmgr32.@)
776
*/
777
CONFIGRET WINAPI CM_Get_Class_Registry_PropertyW( GUID *class, ULONG property, ULONG *type, void *buffer, ULONG *len, ULONG flags, HMACHINE machine )
778
{
779
struct property prop;
780
LSTATUS err;
781
782
TRACE( "class %s, property %#lx, type %p, buffer %p, len %p, flags %#lx, machine %p\n", debugstr_guid(class), property, type, buffer, len, flags, machine );
783
if (machine) FIXME( "machine %p not implemented!\n", machine );
784
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
785
786
if (!class) return CR_INVALID_POINTER;
787
if ((err = init_registry_property( &prop, &DEVPKEY_DeviceClass_UpperFilters, property, type, buffer, len, FALSE ))) return map_error( err );
788
789
return map_error( get_class_property( class, &prop ) );
790
}
791
792
/***********************************************************************
793
* CM_Get_Class_Registry_PropertyA (cfgmgr32.@)
794
*/
795
CONFIGRET WINAPI CM_Get_Class_Registry_PropertyA( GUID *class, ULONG property, ULONG *type, void *buffer, ULONG *len, ULONG flags, HMACHINE machine )
796
{
797
struct property prop;
798
LSTATUS err;
799
800
TRACE( "class %s, property %#lx, type %p, buffer %p, len %p, flags %#lx, machine %p\n", debugstr_guid(class), property, type, buffer, len, flags, machine );
801
if (machine) FIXME( "machine %p not implemented!\n", machine );
802
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
803
804
if (!class) return CR_INVALID_POINTER;
805
if ((err = init_registry_property( &prop, &DEVPKEY_DeviceClass_UpperFilters, property, type, buffer, len, TRUE ))) return map_error( err );
806
807
return map_error( get_class_property( class, &prop ) );
808
}
809
810
/***********************************************************************
811
* CM_Get_Class_Property_ExW (cfgmgr32.@)
812
*/
813
CONFIGRET WINAPI CM_Get_Class_Property_ExW( const GUID *class, const DEVPROPKEY *key, DEVPROPTYPE *type, BYTE *buffer, ULONG *size, ULONG flags, HMACHINE machine )
814
{
815
struct property prop;
816
LSTATUS err;
817
818
TRACE( "class %s, key %s, type %p, buffer %p, size %p, flags %#lx, machine %p\n", debugstr_guid(class), debugstr_DEVPROPKEY(key), type, buffer, size, flags, machine );
819
if (machine) FIXME( "machine %p not implemented!\n", machine );
820
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
821
822
if (!class) return CR_INVALID_POINTER;
823
if ((err = init_property( &prop, key, type, buffer, size ))) return map_error( err );
824
return map_error( get_class_property( class, &prop ) );
825
}
826
827
/***********************************************************************
828
* CM_Get_Class_PropertyW (cfgmgr32.@)
829
*/
830
CONFIGRET WINAPI CM_Get_Class_PropertyW( const GUID *class, const DEVPROPKEY *key, DEVPROPTYPE *type, BYTE *buffer, ULONG *size, ULONG flags )
831
{
832
return CM_Get_Class_Property_ExW( class, key, type, buffer, size, flags, NULL );
833
}
834
835
/***********************************************************************
836
* CM_Get_Class_Property_Keys_Ex (cfgmgr32.@)
837
*/
838
CONFIGRET WINAPI CM_Get_Class_Property_Keys_Ex( const GUID *class, DEVPROPKEY *keys, ULONG *count, ULONG flags, HMACHINE machine )
839
{
840
LSTATUS err;
841
842
TRACE( "class %s, keys %p, size %p, flags %#lx, machine %p\n", debugstr_guid(class), keys, count, flags, machine );
843
if (machine) FIXME( "machine %p not implemented!\n", machine );
844
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
845
846
if (!class) return CR_INVALID_POINTER;
847
if (!count) return CR_INVALID_POINTER;
848
if (*count && !keys) return CR_INVALID_POINTER;
849
850
err = get_class_property_keys( class, keys, count );
851
if (err && err != ERROR_MORE_DATA) *count = 0;
852
return map_error( err );
853
}
854
855
/***********************************************************************
856
* CM_Get_Class_Property_Keys (cfgmgr32.@)
857
*/
858
CONFIGRET WINAPI CM_Get_Class_Property_Keys( const GUID *class, DEVPROPKEY *keys, ULONG *count, ULONG flags )
859
{
860
return CM_Get_Class_Property_Keys_Ex( class, keys, count, flags, NULL );
861
}
862
863
/***********************************************************************
864
* CM_Get_Device_Interface_List_Size_ExW (cfgmgr32.@)
865
*/
866
CONFIGRET WINAPI CM_Get_Device_Interface_List_Size_ExW( ULONG *len, GUID *class, DEVINSTID_W instance_id, ULONG flags, HMACHINE machine )
867
{
868
BOOL all = flags == CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES;
869
870
TRACE( "len %p, class %s, instance %s, flags %#lx, machine %p\n", len, debugstr_guid(class), debugstr_w(instance_id), flags, machine );
871
if (machine) FIXME( "machine %p not implemented!\n", machine );
872
873
if (!class) return CR_FAILURE;
874
if (!len) return CR_INVALID_POINTER;
875
if (flags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS) return CR_INVALID_FLAG;
876
877
*len = 0;
878
return map_error( enum_device_interface_list( class, instance_id, all, enum_objects_size, len ) );
879
}
880
881
/***********************************************************************
882
* CM_Get_Device_Interface_List_Size_ExA (cfgmgr32.@)
883
*/
884
CONFIGRET WINAPI CM_Get_Device_Interface_List_Size_ExA( ULONG *len, GUID *class, DEVINSTID_A instance_idA, ULONG flags, HMACHINE machine )
885
{
886
WCHAR instance_idW[MAX_PATH];
887
888
if (instance_idA) MultiByteToWideChar( CP_ACP, 0, instance_idA, -1, instance_idW, ARRAY_SIZE(instance_idW) );
889
return CM_Get_Device_Interface_List_Size_ExW( len, class, instance_idA ? instance_idW : NULL, flags, machine );
890
}
891
892
/***********************************************************************
893
* CM_Get_Device_Interface_List_SizeW (cfgmgr32.@)
894
*/
895
CONFIGRET WINAPI CM_Get_Device_Interface_List_SizeW( ULONG *len, GUID *class, DEVINSTID_W instance_id, ULONG flags )
896
{
897
return CM_Get_Device_Interface_List_Size_ExW( len, class, instance_id, flags, NULL );
898
}
899
900
/***********************************************************************
901
* CM_Get_Device_Interface_List_SizeA (cfgmgr32.@)
902
*/
903
CONFIGRET WINAPI CM_Get_Device_Interface_List_SizeA( ULONG *len, GUID *class, DEVINSTID_A instance_id, ULONG flags )
904
{
905
return CM_Get_Device_Interface_List_Size_ExA( len, class, instance_id, flags, NULL );
906
}
907
908
/***********************************************************************
909
* CM_Get_Device_Interface_List_ExW (cfgmgr32.@)
910
*/
911
CONFIGRET WINAPI CM_Get_Device_Interface_List_ExW( GUID *class, DEVINSTID_W instance_id, WCHAR *buffer, ULONG len, ULONG flags, HMACHINE machine )
912
{
913
struct enum_objects_append_params params = {.buffer = buffer, .len = len};
914
BOOL all = flags == CM_GET_DEVICE_INTERFACE_LIST_ALL_DEVICES;
915
916
TRACE( "class %s, instance %s, buffer %p, len %lu, flags %#lx, machine %p\n", debugstr_guid(class), debugstr_w(instance_id), buffer, len, flags, machine );
917
if (machine) FIXME( "machine %p not implemented!\n", machine );
918
919
if (!class) return CR_FAILURE;
920
if (!buffer) return CR_INVALID_POINTER;
921
if (!len) return CR_BUFFER_SMALL;
922
if (flags & ~CM_GET_DEVICE_INTERFACE_LIST_BITS) return CR_INVALID_FLAG;
923
924
memset( buffer, 0, len * sizeof(WCHAR) );
925
return map_error( enum_device_interface_list( class, instance_id, all, enum_objects_append, &params ) );
926
}
927
928
/***********************************************************************
929
* CM_Get_Device_Interface_List_ExA (cfgmgr32.@)
930
*/
931
CONFIGRET WINAPI CM_Get_Device_Interface_List_ExA( GUID *class, DEVINSTID_A instance_idA, char *bufferA, ULONG len, ULONG flags, HMACHINE machine )
932
{
933
WCHAR instance_idW[MAX_PATH], *bufferW;
934
CONFIGRET ret;
935
936
bufferW = bufferA ? malloc( len * sizeof(WCHAR) ) : NULL;
937
if (instance_idA) MultiByteToWideChar( CP_ACP, 0, instance_idA, -1, instance_idW, ARRAY_SIZE(instance_idW) );
938
ret = CM_Get_Device_Interface_List_ExW( class, instance_idA ? instance_idW : NULL, bufferA ? bufferW : NULL, len, flags, machine );
939
if (!ret && bufferA && !WideCharToMultiByte( CP_ACP, 0, bufferW, len, bufferA, len, 0, 0 ))
940
{
941
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) ret = CR_BUFFER_SMALL;
942
else ret = CR_FAILURE;
943
}
944
free( bufferW );
945
946
return ret;
947
}
948
949
/***********************************************************************
950
* CM_Get_Device_Interface_ListW (cfgmgr32.@)
951
*/
952
CONFIGRET WINAPI CM_Get_Device_Interface_ListW( GUID *class, DEVINSTID_W instance_id, WCHAR *buffer, ULONG len, ULONG flags )
953
{
954
return CM_Get_Device_Interface_List_ExW( class, instance_id, buffer, len, flags, NULL );
955
}
956
957
/***********************************************************************
958
* CM_Get_Device_Interface_ListA (cfgmgr32.@)
959
*/
960
CONFIGRET WINAPI CM_Get_Device_Interface_ListA( GUID *class, DEVINSTID_A instance_id, char *buffer, ULONG len, ULONG flags )
961
{
962
return CM_Get_Device_Interface_List_ExA( class, instance_id, buffer, len, flags, NULL );
963
}
964
965
/***********************************************************************
966
* CM_Open_Device_Interface_Key_ExW (cfgmgr32.@)
967
*/
968
CONFIGRET WINAPI CM_Open_Device_Interface_Key_ExW( const WCHAR *name, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags, HMACHINE machine )
969
{
970
BOOL open = disposition == RegDisposition_OpenExisting;
971
struct device_interface iface;
972
WCHAR path[MAX_PATH];
973
HKEY iface_key;
974
LSTATUS err;
975
976
TRACE( "name %s, access %#lx, disposition %#lx, hkey %p, flags %#lx\n", debugstr_w(name), access, disposition, hkey, flags );
977
if (machine) FIXME( "machine %p not implemented!\n", machine );
978
979
if (!name) return CR_INVALID_POINTER;
980
if (init_device_interface( &iface, name )) return CR_INVALID_DATA;
981
if (!hkey) return CR_INVALID_POINTER;
982
if (flags) return CR_INVALID_FLAG;
983
984
if (open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &iface_key )) return CR_NO_SUCH_DEVICE_INTERFACE;
985
swprintf( path, ARRAY_SIZE(path), L"%s\\Device Parameters", iface.refstr );
986
err = open_key( iface_key, path, access, open, hkey );
987
RegCloseKey( iface_key );
988
989
return map_error( err );
990
}
991
992
/***********************************************************************
993
* CM_Open_Device_Interface_Key_ExA (cfgmgr32.@)
994
*/
995
CONFIGRET WINAPI CM_Open_Device_Interface_Key_ExA( const char *ifaceA, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags, HMACHINE machine )
996
{
997
WCHAR ifaceW[MAX_PATH];
998
999
TRACE( "ifaceA %s, access %#lx, disposition %#lx, hkey %p, flags %#lx\n", debugstr_a(ifaceA), access, disposition, hkey, flags );
1000
1001
if (ifaceA) MultiByteToWideChar( CP_ACP, 0, ifaceA, -1, ifaceW, ARRAY_SIZE(ifaceW) );
1002
return CM_Open_Device_Interface_Key_ExW( ifaceA ? ifaceW : NULL, access, disposition, hkey, flags, machine );
1003
}
1004
1005
/***********************************************************************
1006
* CM_Open_Device_Interface_KeyW (cfgmgr32.@)
1007
*/
1008
CONFIGRET WINAPI CM_Open_Device_Interface_KeyW( const WCHAR *iface, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags )
1009
{
1010
return CM_Open_Device_Interface_Key_ExW( iface, access, disposition, hkey, flags, NULL );
1011
}
1012
1013
/***********************************************************************
1014
* CM_Open_Device_Interface_KeyA (cfgmgr32.@)
1015
*/
1016
CONFIGRET WINAPI CM_Open_Device_Interface_KeyA( const char *iface, REGSAM access, REGDISPOSITION disposition, HKEY *hkey, ULONG flags )
1017
{
1018
return CM_Open_Device_Interface_Key_ExA( iface, access, disposition, hkey, flags, NULL );
1019
}
1020
1021
/***********************************************************************
1022
* CM_Get_Device_Interface_Property_ExW (cfgmgr32.@)
1023
*/
1024
CONFIGRET WINAPI CM_Get_Device_Interface_Property_ExW( const WCHAR *name, const DEVPROPKEY *key, DEVPROPTYPE *type,
1025
BYTE *buffer, ULONG *size, ULONG flags, HMACHINE machine )
1026
{
1027
struct device_interface iface;
1028
struct property prop;
1029
LSTATUS err;
1030
1031
TRACE( "name %s, key %p, type %p, buffer %p, size %p, flags %#lx\n", debugstr_w(name), key, type, buffer, size, flags);
1032
if (machine) FIXME( "machine %p not implemented!\n", machine );
1033
1034
if (!name) return CR_INVALID_POINTER;
1035
if (init_device_interface( &iface, name )) return CR_NO_SUCH_DEVICE_INTERFACE;
1036
if ((err = init_property( &prop, key, type, buffer, size ))) return map_error( err );
1037
if (flags) return CR_INVALID_FLAG;
1038
1039
return map_error( get_device_interface_property( &iface, &prop ) );
1040
}
1041
1042
/***********************************************************************
1043
* CM_Get_Device_Interface_PropertyW (cfgmgr32.@)
1044
*/
1045
CONFIGRET WINAPI CM_Get_Device_Interface_PropertyW( const WCHAR *iface, const DEVPROPKEY *key, DEVPROPTYPE *type, BYTE *buffer, ULONG *size, ULONG flags )
1046
{
1047
return CM_Get_Device_Interface_Property_ExW( iface, key, type, buffer, size, flags, NULL );
1048
}
1049
1050
/***********************************************************************
1051
* CM_Get_Device_Interface_Property_Keys_ExW (cfgmgr32.@)
1052
*/
1053
CONFIGRET WINAPI CM_Get_Device_Interface_Property_Keys_ExW( const WCHAR *name, DEVPROPKEY *buffer, ULONG *size, ULONG flags, HMACHINE machine )
1054
{
1055
struct device_interface iface;
1056
LSTATUS err;
1057
1058
TRACE( "name %s, buffer %p, size %p, flags %#lx\n", debugstr_w(name), buffer, size, flags);
1059
if (machine) FIXME( "machine %p not implemented!\n", machine );
1060
if (flags) FIXME( "flags %#lx not implemented!\n", flags );
1061
1062
if (!name || !size) return CR_INVALID_POINTER;
1063
if (*size && !buffer) return CR_INVALID_POINTER;
1064
if (init_device_interface( &iface, name ))
1065
{
1066
*size = 0;
1067
return CR_INVALID_DATA;
1068
}
1069
1070
err = get_device_interface_property_keys( &iface, buffer, size );
1071
if (err && err != ERROR_MORE_DATA) *size = 0;
1072
if (err == ERROR_FILE_NOT_FOUND) return CR_NO_SUCH_DEVICE_INTERFACE;
1073
return map_error( err );
1074
}
1075
1076
/***********************************************************************
1077
* CM_Get_Device_Interface_Property_KeysW (cfgmgr32.@)
1078
*/
1079
CONFIGRET WINAPI CM_Get_Device_Interface_Property_KeysW( const WCHAR *iface, DEVPROPKEY *keys, ULONG *count, ULONG flags )
1080
{
1081
return CM_Get_Device_Interface_Property_Keys_ExW( iface, keys, count, flags, NULL );
1082
}
1083
1084