There seem to be a few special cases here, of which the main one is `DEVPKEY_DeviceInterface_Enabled`. This property key does not have an actual registry entry, but the value read by `SetupDiGetDeviceInterfacePropertyW` corresponds to whether the interface is enabled/linked or not. Likewise, the key cannot be written to either, with `SetupDiSetDeviceInterfacePropertyW` returning `ERROR_ACCESS DENIED`.
-- v4: ntoskrnl.exe/test: Add tests for SetupDiGetDeviceInterfacePropertyW with enabled interfaces. setupapi: Implement SetupDiGetDeviceInterfacePropertyW. setupapi: Implement SetupDiSetDeviceInterfacePropertyW.
From: Vibhav Pant vibhavp@gmail.com
--- dlls/setupapi/devinst.c | 20 +++++ dlls/setupapi/setupapi.spec | 2 + dlls/setupapi/tests/devinst.c | 153 ++++++++++++++++++++++++++++++++++ include/setupapi.h | 2 + 4 files changed, 177 insertions(+)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 9b6b49aeb93..fdd9edcd6ec 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -3106,6 +3106,26 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO devinfo, SP_DEVICE_INTERFA return ret; }
+BOOL WINAPI SetupDiGetDeviceInterfacePropertyW( HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *iface_data, + const DEVPROPKEY *key, DEVPROPTYPE *type, BYTE *buf, DWORD buf_size, + DWORD *req_size, DWORD flags ) +{ + FIXME( "devinfo %p, iface_data %p, key %p, type %p, buf %p, buf_size %lu, req_size %p, flags %#lx: stub!\n", + devinfo, iface_data, key, type, buf, buf_size, req_size, flags ); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} + +BOOL WINAPI SetupDiSetDeviceInterfacePropertyW( HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *iface_data, + const DEVPROPKEY *key, DEVPROPTYPE type, const BYTE *buf, + DWORD buf_size, DWORD flags ) +{ + FIXME( "devinfo %p, iface_data %p, key %p, type %#lx, buf %p, buf_size %lu, flags %#lx: stub!\n", devinfo, + iface_data, key, type, buf, buf_size, flags ); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); + return FALSE; +} + /*********************************************************************** * SetupDiGetDeviceRegistryPropertyA (SETUPAPI.@) */ diff --git a/dlls/setupapi/setupapi.spec b/dlls/setupapi/setupapi.spec index d5beb4e1ab7..3eef37658f9 100644 --- a/dlls/setupapi/setupapi.spec +++ b/dlls/setupapi/setupapi.spec @@ -357,6 +357,7 @@ @ stub SetupDiGetDeviceInterfaceAlias @ stdcall SetupDiGetDeviceInterfaceDetailA(long ptr ptr long ptr ptr) @ stdcall SetupDiGetDeviceInterfaceDetailW(long ptr ptr long ptr ptr) +@ stdcall SetupDiGetDeviceInterfacePropertyW(ptr ptr ptr ptr ptr long ptr long) @ stdcall SetupDiGetDevicePropertyKeys(ptr ptr ptr long ptr long) @ stdcall SetupDiGetDevicePropertyW(ptr ptr ptr ptr ptr long ptr long) @ stdcall SetupDiGetDeviceRegistryPropertyA(long ptr long ptr ptr long ptr) @@ -407,6 +408,7 @@ @ stdcall SetupDiSetClassInstallParamsW(ptr ptr ptr long) @ stdcall SetupDiSetDeviceInstallParamsA(ptr ptr ptr) @ stdcall SetupDiSetDeviceInstallParamsW(ptr ptr ptr) +@ stdcall SetupDiSetDeviceInterfacePropertyW(ptr ptr ptr long ptr long long) @ stdcall SetupDiSetDevicePropertyW(ptr ptr ptr long ptr long long) @ stdcall SetupDiSetDeviceRegistryPropertyA(ptr ptr long ptr long) @ stdcall SetupDiSetDeviceRegistryPropertyW(ptr ptr long ptr long) diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 0faa0d68f90..6357b694366 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -2725,6 +2725,158 @@ static void test_open_device_interface_key(void) ok(ret, "Failed to destroy device list, error %#lx.\n", GetLastError()); }
+static void test_device_interface_properties(void) +{ + const WCHAR str[] = L"Wine is not an emulator."; + DEVPROPTYPE type = DEVPROP_TYPE_EMPTY; + DEVPROP_BOOLEAN boolean = DEVPROP_TRUE; + SP_DEVICE_INTERFACE_DATA iface; + SP_DEVINFO_DATA device; + DWORD err, req; + WCHAR buf[50]; + HDEVINFO set; + BOOL ret; + + set = SetupDiCreateDeviceInfoList(&guid, NULL); + ok(set != INVALID_HANDLE_VALUE, "Failed to create device list, error %#lx\n", GetLastError()); + + device.cbSize = sizeof(device); + ret = SetupDiCreateDeviceInfoA(set, "ROOT\LEGACY_BOGUS\0000", &guid, NULL, NULL, 0, &device); + ok(ret, "Failed to create device, error %#lx.\n", GetLastError()); + + iface.cbSize = sizeof(iface); + ret = SetupDiCreateDeviceInterfaceA(set, &device, &guid, NULL, 0, &iface); + ok(ret, "Failed to create interface, error %#lx.\n", GetLastError()); + + ret = SetupDiSetDeviceInterfacePropertyW(NULL, NULL, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE); + + ret = SetupDiSetDeviceInterfacePropertyW(set, NULL, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, + NULL, 0, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, + (BYTE *)str, 0, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, + NULL, 1, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, + (BYTE *)str, sizeof(str), 1); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS); + + ret = SetupDiGetDeviceInterfacePropertyW(NULL, NULL, NULL, NULL, NULL, 0, NULL, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE); + + ret = SetupDiGetDeviceInterfacePropertyW(set, NULL, NULL, NULL, NULL, 0, NULL, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, NULL, NULL, NULL, 0, NULL, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, NULL, NULL, 0, NULL, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, NULL, sizeof(buf), &req, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), NULL, 1); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), NULL, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), &req, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, + (const BYTE *)str, sizeof(str), 0); + err = GetLastError(); + todo_wine ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err); + + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, NULL, 0, &req, 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "%lu != %d\n", err, ERROR_INSUFFICIENT_BUFFER); + todo_wine ok(type == DEVPROP_TYPE_STRING, "%#lx != %#x\n", type, DEVPROP_TYPE_STRING); + todo_wine ok(req == sizeof(str), "%lu != %lu\n", req, (DWORD)sizeof(str)); + + buf[0] = '\0'; + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, + sizeof(buf), &req, 0); + err = GetLastError(); + todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + todo_wine ok(!wcscmp(buf, str), "%s != %s\n", debugstr_w(buf), debugstr_w(str)); + + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_EMPTY, + NULL, 0, 0); + err = GetLastError(); + todo_wine ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err); + + /* DEVPKEY_DeviceInterface_Enabled is a "special" key, as it does not seem to be actually stored in the registry. */ + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, &type, (BYTE *)&boolean, + sizeof(boolean), &req, 0); + err = GetLastError(); + todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + todo_wine ok(req == sizeof(boolean), "%lu != %lu\n", req, (DWORD)sizeof(boolean)); + todo_wine ok(boolean == DEVPROP_FALSE, "%d != %d\n", boolean, DEVPROP_FALSE); + + boolean = DEVPROP_TRUE; + /* DEVPKEY_DeviceInterface_Enabled cannot be toggled for interfaces. */ + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, + (const BYTE *)&boolean, sizeof(boolean), 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_ACCESS_DENIED, "%lu != %d\n", err, ERROR_ACCESS_DENIED); + + /* Nor can it be set to anything that's not a DEVPROP_TYPE_BOOLEAN. */ + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_STRING, + (const BYTE *)str, sizeof(str), 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + + /* It can however, be "set" to to its current value, i.e whether the interface is enabled. This seems to be a no-op. */ + boolean = DEVPROP_FALSE; + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, + (const BYTE *)&boolean, sizeof(boolean), 0); + err = GetLastError(); + todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + + boolean = 0xde; + ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, + (const BYTE *)&boolean, sizeof(boolean), 0); + err = GetLastError(); + todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + + ret = SetupDiRemoveDeviceInterface(set, &iface); + ok(ret, "Failed to remove device interface, error %#lx.\n", GetLastError()); + ret = SetupDiRemoveDevice(set, &device); + ok(ret, "Failed to remove device, error %#lx.\n", GetLastError()); + ret = SetupDiDestroyDeviceInfoList(set); + ok(ret, "Failed to destroy device list, error %#lx.\n", GetLastError()); +} + static void test_device_install_params(void) { SP_DEVINFO_DATA device = {sizeof(device)}; @@ -4845,6 +4997,7 @@ START_TEST(devinst) test_devnode(); test_device_interface_key(); test_open_device_interface_key(); + test_device_interface_properties(); test_device_install_params(); test_driver_list(); test_call_class_installer(); diff --git a/include/setupapi.h b/include/setupapi.h index ba61ce421f7..e46f35ca2d4 100644 --- a/include/setupapi.h +++ b/include/setupapi.h @@ -1573,6 +1573,7 @@ WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceAlias(HDEVINFO, PSP_DEVICE_ WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailA(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_A, DWORD, PDWORD, PSP_DEVINFO_DATA); WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, PSP_DEVICE_INTERFACE_DETAIL_DATA_W, DWORD, PDWORD, PSP_DEVINFO_DATA); #define SetupDiGetDeviceInterfaceDetail WINELIB_NAME_AW(SetupDiGetDeviceInterfaceDetail) +WINSETUPAPI BOOL WINAPI SetupDiGetDeviceInterfacePropertyW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD); WINSETUPAPI BOOL WINAPI SetupDiGetDevicePropertyKeys(HDEVINFO, PSP_DEVINFO_DATA, DEVPROPKEY *, DWORD, DWORD *, DWORD); WINSETUPAPI BOOL WINAPI SetupDiGetDevicePropertyW(HDEVINFO, PSP_DEVINFO_DATA, const DEVPROPKEY *, DEVPROPTYPE *, BYTE *, DWORD, DWORD *, DWORD); #define SetupDiGetDeviceProperty WINELIB_NAME_AW(SetupDiGetDeviceProperty) /* note: A function doesn't exist */ @@ -1640,6 +1641,7 @@ WINSETUPAPI BOOL WINAPI SetupDiSetClassRegistryPropertyA(const GUID *, DWORD WINSETUPAPI BOOL WINAPI SetupDiSetClassRegistryPropertyW(const GUID *, DWORD, const BYTE *, DWORD, PCWSTR, PVOID); #define SetupDiSetClassRegistryProperty WINELIB_NAME_AW(SetupDiSetClassRegistryProperty) WINSETUPAPI BOOL WINAPI SetupDiSetDeviceInterfaceDefault(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, DWORD, PVOID); +WINSETUPAPI BOOL WINAPI SetupDiSetDeviceInterfacePropertyW(HDEVINFO, PSP_DEVICE_INTERFACE_DATA, const DEVPROPKEY *, DEVPROPTYPE, const BYTE *, DWORD, DWORD); WINSETUPAPI BOOL WINAPI SetupDiSetDeviceInstallParamsA(HDEVINFO, PSP_DEVINFO_DATA, PSP_DEVINSTALL_PARAMS_A); WINSETUPAPI BOOL WINAPI SetupDiSetDeviceInstallParamsW(HDEVINFO, PSP_DEVINFO_DATA, PSP_DEVINSTALL_PARAMS_W); #define SetupDiSetDeviceInstallParams WINELIB_NAME_AW(SetupDiSetDeviceInstallParams)
From: Vibhav Pant vibhavp@gmail.com
--- dlls/setupapi/devinst.c | 142 ++++++++++++++++++++++------------ dlls/setupapi/tests/devinst.c | 26 +++---- 2 files changed, 107 insertions(+), 61 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index fdd9edcd6ec..9fbffb349e8 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -46,6 +46,8 @@
#include "setupapi_private.h"
+#include "initguid.h" +#include "devpkey.h"
WINE_DEFAULT_DEBUG_CHANNEL(setupapi);
@@ -3116,14 +3118,99 @@ BOOL WINAPI SetupDiGetDeviceInterfacePropertyW( HDEVINFO devinfo, SP_DEVICE_INTE return FALSE; }
+static DWORD set_device_reg_property( HKEY base_key, const DEVPROPKEY *key, DEVPROPTYPE type, const BYTE *buf, + DWORD buf_size ) +{ + HKEY properties, property; + WCHAR prop_path[44]; + LSTATUS ret; + + ret = RegCreateKeyExW( base_key, L"Properties", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &properties, NULL ); + if (ret) + { + SetLastError( ret ); + return FALSE; + } + + SETUPDI_GuidToString( &key->fmtid, prop_path ); + swprintf( &prop_path[38], ARRAY_SIZE( prop_path ) - 38, L"\%04X", key->pid ); + switch (type) + { + case DEVPROP_TYPE_EMPTY: + ret = RegDeleteKeyW( properties, prop_path ); + SetLastError( ret == ERROR_FILE_NOT_FOUND ? ERROR_NOT_FOUND : ret ); + break; + case DEVPROP_TYPE_NULL: + if (!(ret = RegOpenKeyW( properties, prop_path, &property ))) + { + ret = RegDeleteValueW( property, NULL ); + RegCloseKey( property ); + } + break; + default: + if (!(ret = RegCreateKeyExW( properties, prop_path, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &property, NULL ))) + { + ret = RegSetValueExW( property, NULL, 0, 0xffff0000 | (0xffff & type), buf, buf_size ); + RegCloseKey( property ); + } + break; + } + + RegCloseKey( properties ); + return ret == ERROR_FILE_NOT_FOUND ? ERROR_NOT_FOUND : ret; +} + BOOL WINAPI SetupDiSetDeviceInterfacePropertyW( HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *iface_data, const DEVPROPKEY *key, DEVPROPTYPE type, const BYTE *buf, DWORD buf_size, DWORD flags ) { - FIXME( "devinfo %p, iface_data %p, key %p, type %#lx, buf %p, buf_size %lu, flags %#lx: stub!\n", devinfo, + struct device_iface *iface; + DWORD ret; + + TRACE( "devinfo %p, iface_data %p, key %p, type %#lx, buf %p, buf_size %lu, flags %#lx\n", devinfo, iface_data, key, type, buf, buf_size, flags ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + + if (!(iface = get_device_iface( devinfo, iface_data ))) + return FALSE; + if (buf_size && !buf) + { + SetLastError( ERROR_INVALID_USER_BUFFER ); + return FALSE; + } + if (!key || !is_valid_property_type(type) + || (!(buf && buf_size) && !(type == DEVPROP_TYPE_EMPTY || type == DEVPROP_TYPE_NULL)) + || (buf && buf_size && (type == DEVPROP_TYPE_EMPTY || type == DEVPROP_TYPE_NULL))) + { + SetLastError( ERROR_INVALID_DATA ); + return FALSE; + } + if (flags) + { + SetLastError( ERROR_INVALID_FLAGS ); + return FALSE; + } + + + if (IsEqualDevPropKey( *key, DEVPKEY_DeviceInterface_Enabled )) + { + DEVPROP_BOOLEAN val = *(DEVPROP_BOOLEAN *)buf; + + if (type != DEVPROP_TYPE_BOOLEAN || buf_size != sizeof( DEVPROP_BOOLEAN ) + || !(val == DEVPROP_FALSE || val == DEVPROP_TRUE)) + { + SetLastError( ERROR_INVALID_DATA ); + return FALSE; + } + + ret = !!(iface->flags & SPINT_ACTIVE) == !!val ? ERROR_SUCCESS : ERROR_ACCESS_DENIED; + /* Setting this to the interface's current status is a no-op, otherwise return ERROR_ACCESS_DENEID. */ + SetLastError( ret ); + return !ret; + } + + ret = set_device_reg_property( iface->refstr_key, key, type, buf, buf_size ); + SetLastError( ret ); + return !ret; }
/*********************************************************************** @@ -4092,9 +4179,7 @@ BOOL WINAPI SetupDiSetDevicePropertyW(HDEVINFO devinfo, PSP_DEVINFO_DATA device_ DEVPROPTYPE type, const BYTE *buffer, DWORD size, DWORD flags) { struct device *device; - HKEY properties_hkey, property_hkey; - WCHAR property_hkey_path[44]; - LSTATUS ls; + DWORD ret;
TRACE("%p %p %p %#lx %p %ld %#lx\n", devinfo, device_data, key, type, buffer, size, flags);
@@ -4121,48 +4206,9 @@ BOOL WINAPI SetupDiSetDevicePropertyW(HDEVINFO devinfo, PSP_DEVINFO_DATA device_ return FALSE; }
- ls = RegCreateKeyExW(device->key, L"Properties", 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, &properties_hkey, NULL); - if (ls) - { - SetLastError(ls); - return FALSE; - } - - SETUPDI_GuidToString(&key->fmtid, property_hkey_path); - swprintf(property_hkey_path + 38, ARRAY_SIZE(property_hkey_path) - 38, L"\%04X", key->pid); - - if (type == DEVPROP_TYPE_EMPTY) - { - ls = RegDeleteKeyW(properties_hkey, property_hkey_path); - RegCloseKey(properties_hkey); - SetLastError(ls == ERROR_FILE_NOT_FOUND ? ERROR_NOT_FOUND : ls); - return !ls; - } - else if (type == DEVPROP_TYPE_NULL) - { - if (!(ls = RegOpenKeyW(properties_hkey, property_hkey_path, &property_hkey))) - { - ls = RegDeleteValueW(property_hkey, NULL); - RegCloseKey(property_hkey); - } - - RegCloseKey(properties_hkey); - SetLastError(ls == ERROR_FILE_NOT_FOUND ? ERROR_NOT_FOUND : ls); - return !ls; - } - else - { - if (!(ls = RegCreateKeyExW(properties_hkey, property_hkey_path, 0, NULL, 0, KEY_READ | KEY_WRITE, NULL, - &property_hkey, NULL))) - { - ls = RegSetValueExW(property_hkey, NULL, 0, 0xffff0000 | (0xffff & type), buffer, size); - RegCloseKey(property_hkey); - } - - RegCloseKey(properties_hkey); - SetLastError(ls); - return !ls; - } + ret = set_device_reg_property( device->key, key, type, buffer, size ); + SetLastError( ret ); + return !ret; }
/*********************************************************************** diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index 6357b694366..d1a7418e29b 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -2750,35 +2750,35 @@ static void test_device_interface_properties(void)
ret = SetupDiSetDeviceInterfacePropertyW(NULL, NULL, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE); + ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE);
ret = SetupDiSetDeviceInterfacePropertyW(set, NULL, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER); + ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, NULL, DEVPROP_TYPE_STRING, NULL, 0, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, NULL, 0, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, (BYTE *)str, 0, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, NULL, 1, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, (BYTE *)str, sizeof(str), 1); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS); + ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS);
ret = SetupDiGetDeviceInterfacePropertyW(NULL, NULL, NULL, NULL, NULL, 0, NULL, 0); err = GetLastError(); @@ -2815,7 +2815,7 @@ static void test_device_interface_properties(void) ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, (const BYTE *)str, sizeof(str), 0); err = GetLastError(); - todo_wine ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err); + ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, NULL, 0, &req, 0); err = GetLastError(); @@ -2833,7 +2833,7 @@ static void test_device_interface_properties(void) ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_EMPTY, NULL, 0, 0); err = GetLastError(); - todo_wine ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err); + ok(ret, "SetupDiSetDeviceInterfacePropertyW failed: %lu\n", err);
/* DEVPKEY_DeviceInterface_Enabled is a "special" key, as it does not seem to be actually stored in the registry. */ ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, &type, (BYTE *)&boolean, @@ -2848,26 +2848,26 @@ static void test_device_interface_properties(void) ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, (const BYTE *)&boolean, sizeof(boolean), 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_ACCESS_DENIED, "%lu != %d\n", err, ERROR_ACCESS_DENIED); + ok(!ret && err == ERROR_ACCESS_DENIED, "%lu != %d\n", err, ERROR_ACCESS_DENIED);
/* Nor can it be set to anything that's not a DEVPROP_TYPE_BOOLEAN. */ ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_STRING, (const BYTE *)str, sizeof(str), 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA);
/* It can however, be "set" to to its current value, i.e whether the interface is enabled. This seems to be a no-op. */ boolean = DEVPROP_FALSE; ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, (const BYTE *)&boolean, sizeof(boolean), 0); err = GetLastError(); - todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err);
boolean = 0xde; ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, DEVPROP_TYPE_BOOLEAN, (const BYTE *)&boolean, sizeof(boolean), 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA); + ok(!ret && err == ERROR_INVALID_DATA, "%lu != %d\n", err, ERROR_INVALID_DATA);
ret = SetupDiRemoveDeviceInterface(set, &iface); ok(ret, "Failed to remove device interface, error %#lx.\n", GetLastError());
From: Vibhav Pant vibhavp@gmail.com
--- dlls/setupapi/devinst.c | 124 ++++++++++++++++++++++------------ dlls/setupapi/tests/devinst.c | 32 ++++----- 2 files changed, 97 insertions(+), 59 deletions(-)
diff --git a/dlls/setupapi/devinst.c b/dlls/setupapi/devinst.c index 9fbffb349e8..aae3efbfdf4 100644 --- a/dlls/setupapi/devinst.c +++ b/dlls/setupapi/devinst.c @@ -3108,14 +3108,91 @@ BOOL WINAPI SetupDiGetDeviceInterfaceDetailW(HDEVINFO devinfo, SP_DEVICE_INTERFA return ret; }
+static DWORD get_device_reg_property( HKEY base_key, const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type, + BYTE *buf, DWORD buf_size, DWORD *req_size ) +{ + WCHAR prop_path[55] = L"Properties\"; + HKEY property; + DWORD size = 0, val_type; + LSTATUS ret; + + SETUPDI_GuidToString( &prop_key->fmtid, prop_path + 11 ); + swprintf( prop_path + 49, ARRAY_SIZE( prop_path ) - 49, L"\%04X", prop_key->pid ); + if (!(ret = RegOpenKeyExW( base_key, prop_path, 0, KEY_QUERY_VALUE, &property ))) + { + size = buf_size; + ret = RegQueryValueExW( property, NULL, NULL, &val_type, buf, &size ); + RegCloseKey( property ); + } + + switch (ret) + { + case ERROR_SUCCESS: + case ERROR_MORE_DATA: + *prop_type = val_type & 0xffff; + ret = (ret == ERROR_MORE_DATA || !buf) ? ERROR_INSUFFICIENT_BUFFER : ERROR_SUCCESS; + break; + case ERROR_FILE_NOT_FOUND: + *prop_type = DEVPROP_TYPE_EMPTY; + size = 0; + ret = ERROR_NOT_FOUND; + break; + default: + *prop_type = DEVPROP_TYPE_EMPTY; + size = 0; + FIXME( "Unhandled error: %lu\n", ret ); + break; + } + + if (req_size) + *req_size = size; + return ret; +} + BOOL WINAPI SetupDiGetDeviceInterfacePropertyW( HDEVINFO devinfo, SP_DEVICE_INTERFACE_DATA *iface_data, const DEVPROPKEY *key, DEVPROPTYPE *type, BYTE *buf, DWORD buf_size, DWORD *req_size, DWORD flags ) { - FIXME( "devinfo %p, iface_data %p, key %p, type %p, buf %p, buf_size %lu, req_size %p, flags %#lx: stub!\n", + struct device_iface *iface; + LSTATUS ret; + + TRACE( "devinfo %p, iface_data %p, key %p, type %p, buf %p, buf_size %lu, req_size %p, flags %#lx\n", devinfo, iface_data, key, type, buf, buf_size, req_size, flags ); - SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); - return FALSE; + + if (!(iface = get_device_iface( devinfo, iface_data ))) + return FALSE; + if (!type || (!buf && buf_size)) + { + SetLastError( ERROR_INVALID_USER_BUFFER ); + return FALSE; + } + if (!key) + { + SetLastError( ERROR_INVALID_DATA ); + return FALSE; + } + if (flags) + { + SetLastError( ERROR_INVALID_FLAGS ); + return FALSE; + } + + if (IsEqualDevPropKey( *key, DEVPKEY_DeviceInterface_Enabled )) + { + *type = DEVPROP_TYPE_BOOLEAN; + ret = ERROR_SUCCESS; + if (buf_size >= sizeof( DEVPROP_BOOLEAN )) + *buf = (iface->flags & SPINT_ACTIVE) ? DEVPROP_TRUE : DEVPROP_FALSE; + else + ret = ERROR_INSUFFICIENT_BUFFER; + if (req_size) + *req_size = sizeof( DEVPROP_BOOLEAN ); + } + else + ret = get_device_reg_property( iface->refstr_key, key, type, buf, buf_size, req_size ); + + SetLastError( ret ); + return !ret; }
static DWORD set_device_reg_property( HKEY base_key, const DEVPROPKEY *key, DEVPROPTYPE type, const BYTE *buf, @@ -5024,12 +5101,6 @@ out: static LSTATUS get_device_property(struct device *device, const DEVPROPKEY *prop_key, DEVPROPTYPE *prop_type, BYTE *prop_buff, DWORD prop_buff_size, DWORD *required_size, DWORD flags) { - WCHAR key_path[55] = L"Properties\"; - HKEY hkey; - DWORD value_type; - DWORD value_size = 0; - LSTATUS ls; - if (!prop_key) return ERROR_INVALID_DATA;
@@ -5039,40 +5110,7 @@ static LSTATUS get_device_property(struct device *device, const DEVPROPKEY *prop if (flags) return ERROR_INVALID_FLAGS;
- SETUPDI_GuidToString(&prop_key->fmtid, key_path + 11); - swprintf(key_path + 49, ARRAY_SIZE(key_path) - 49, L"\%04X", prop_key->pid); - - ls = RegOpenKeyExW(device->key, key_path, 0, KEY_QUERY_VALUE, &hkey); - if (!ls) - { - value_size = prop_buff_size; - ls = RegQueryValueExW(hkey, NULL, NULL, &value_type, prop_buff, &value_size); - RegCloseKey(hkey); - } - - switch (ls) - { - case NO_ERROR: - case ERROR_MORE_DATA: - *prop_type = 0xffff & value_type; - ls = (ls == ERROR_MORE_DATA || !prop_buff) ? ERROR_INSUFFICIENT_BUFFER : NO_ERROR; - break; - case ERROR_FILE_NOT_FOUND: - *prop_type = DEVPROP_TYPE_EMPTY; - value_size = 0; - ls = ERROR_NOT_FOUND; - break; - default: - *prop_type = DEVPROP_TYPE_EMPTY; - value_size = 0; - FIXME("Unhandled error %#lx\n", ls); - break; - } - - if (required_size) - *required_size = value_size; - - return ls; + return get_device_reg_property( device->key, prop_key, prop_type, prop_buff, prop_buff_size, required_size ); }
BOOL WINAPI SetupDiGetDevicePropertyKeys( HDEVINFO devinfo, PSP_DEVINFO_DATA device_data, diff --git a/dlls/setupapi/tests/devinst.c b/dlls/setupapi/tests/devinst.c index d1a7418e29b..1ff00b1282d 100644 --- a/dlls/setupapi/tests/devinst.c +++ b/dlls/setupapi/tests/devinst.c @@ -2782,35 +2782,35 @@ static void test_device_interface_properties(void)
ret = SetupDiGetDeviceInterfacePropertyW(NULL, NULL, NULL, NULL, NULL, 0, NULL, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE); + ok(!ret && err == ERROR_INVALID_HANDLE, "%lu != %d\n", err, ERROR_INVALID_HANDLE);
ret = SetupDiGetDeviceInterfacePropertyW(set, NULL, NULL, NULL, NULL, 0, NULL, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER); + ok(!ret && err == ERROR_INVALID_PARAMETER, "%lu != %d\n", err, ERROR_INVALID_PARAMETER);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, NULL, NULL, NULL, 0, NULL, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, NULL, NULL, 0, NULL, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, NULL, sizeof(buf), &req, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER); + ok(!ret && err == ERROR_INVALID_USER_BUFFER, "%lu != %d\n", err, ERROR_INVALID_USER_BUFFER);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), NULL, 1); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS); + ok(!ret && err == ERROR_INVALID_FLAGS, "%lu != %d\n", err, ERROR_INVALID_FLAGS);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), NULL, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND); + ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND);
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), &req, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND); + ok(!ret && err == ERROR_NOT_FOUND, "%lu != %d\n", err, ERROR_NOT_FOUND);
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, (const BYTE *)str, sizeof(str), 0); @@ -2819,16 +2819,16 @@ static void test_device_interface_properties(void)
ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, NULL, 0, &req, 0); err = GetLastError(); - todo_wine ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "%lu != %d\n", err, ERROR_INSUFFICIENT_BUFFER); - todo_wine ok(type == DEVPROP_TYPE_STRING, "%#lx != %#x\n", type, DEVPROP_TYPE_STRING); - todo_wine ok(req == sizeof(str), "%lu != %lu\n", req, (DWORD)sizeof(str)); + ok(!ret && err == ERROR_INSUFFICIENT_BUFFER, "%lu != %d\n", err, ERROR_INSUFFICIENT_BUFFER); + ok(type == DEVPROP_TYPE_STRING, "%#lx != %#x\n", type, DEVPROP_TYPE_STRING); + ok(req == sizeof(str), "%lu != %lu\n", req, (DWORD)sizeof(str));
buf[0] = '\0'; ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, &type, (BYTE *)buf, sizeof(buf), &req, 0); err = GetLastError(); - todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); - todo_wine ok(!wcscmp(buf, str), "%s != %s\n", debugstr_w(buf), debugstr_w(str)); + ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + ok(!wcscmp(buf, str), "%s != %s\n", debugstr_w(buf), debugstr_w(str));
ret = SetupDiSetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_EMPTY, NULL, 0, 0); @@ -2839,9 +2839,9 @@ static void test_device_interface_properties(void) ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, &type, (BYTE *)&boolean, sizeof(boolean), &req, 0); err = GetLastError(); - todo_wine ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); - todo_wine ok(req == sizeof(boolean), "%lu != %lu\n", req, (DWORD)sizeof(boolean)); - todo_wine ok(boolean == DEVPROP_FALSE, "%d != %d\n", boolean, DEVPROP_FALSE); + ok(ret, "SetupDiGetDeviceInterfacePropertyW failed: %lu\n", err); + ok(req == sizeof(boolean), "%lu != %lu\n", req, (DWORD)sizeof(boolean)); + ok(boolean == DEVPROP_FALSE, "%d != %d\n", boolean, DEVPROP_FALSE);
boolean = DEVPROP_TRUE; /* DEVPKEY_DeviceInterface_Enabled cannot be toggled for interfaces. */
From: Vibhav Pant vibhavp@gmail.com
--- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index 517b3cf4791..819d1497ff9 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -40,6 +40,7 @@ #include "dbt.h" #include "initguid.h" #include "devguid.h" +#include "devpkey.h" #include "ddk/hidclass.h" #include "ddk/hidsdi.h" #include "ddk/hidpi.h" @@ -1456,6 +1457,8 @@ static void test_pnp_devices(void) SP_DEVICE_INTERFACE_DETAIL_DATA_A *iface_detail = (void *)buffer; SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)}; SP_DEVINFO_DATA device = {sizeof(device)}; + DEVPROP_BOOLEAN enabled = DEVPROP_FALSE; + DEVPROPTYPE prop_type = DEVPROP_TYPE_EMPTY; DEV_BROADCAST_DEVICEINTERFACE_A filter = { .dbcc_size = sizeof(filter), @@ -1467,7 +1470,7 @@ static void test_pnp_devices(void) .lpfnWndProc = device_notify_proc, }; HDEVNOTIFY notify_handle; - DWORD size, type, dword; + DWORD size = 0, type, dword; HANDLE bus, child, tmp; OBJECT_ATTRIBUTES attr; UNICODE_STRING string; @@ -1510,6 +1513,13 @@ static void test_pnp_devices(void) ok(!strcmp(iface_detail->DevicePath, "\\?\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}"), "wrong path %s\n", debugstr_a(iface_detail->DevicePath));
+ ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, &prop_type, + (BYTE *)&enabled, sizeof(enabled), &size, 0); + ok(ret, "failed to get device interface property, got error %lu\n", GetLastError()); + ok(prop_type == DEVPROP_TYPE_BOOLEAN, "got prop_type %#lx\n", prop_type); + ok(size == sizeof(enabled), "got size %lu\n", size); + ok(enabled == DEVPROP_TRUE, "got enabled %d\n", enabled); + /* Create a device parameter for testing IoOpenDeviceRegistryKey */ key = SetupDiCreateDevRegKeyA(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL); ok(key != INVALID_HANDLE_VALUE, "failed to create a hardware parameters key, got error %#lx\n", GetLastError()); @@ -1689,6 +1699,16 @@ static void test_pnp_devices(void) ok(!strcmp(iface_detail->DevicePath, "\\?\wine#test#1#{deadbeef-29ef-4538-a5fd-b69573a362c2}"), "wrong path %s\n", debugstr_a(iface_detail->DevicePath));
+ prop_type = DEVPROP_TYPE_EMPTY; + size = 0; + enabled = DEVPROP_FALSE; + ret = SetupDiGetDeviceInterfacePropertyW(set, &iface, &DEVPKEY_DeviceInterface_Enabled, &prop_type, + (BYTE *)&enabled, sizeof(enabled), &size, 0); + ok(ret, "failed to get device interface property, got error %lu\n", GetLastError()); + ok(prop_type == DEVPROP_TYPE_BOOLEAN, "got prop_type %#lx\n", prop_type); + ok(size == sizeof(enabled), "got size %lu\n", size); + ok(enabled == DEVPROP_TRUE, "got enabled %d\n", enabled); + /* Create a device parameter for testing IoOpenDeviceRegistryKey */ key = SetupDiCreateDevRegKeyA(set, &device, DICS_FLAG_GLOBAL, 0, DIREG_DEV, NULL, NULL); ok(key != INVALID_HANDLE_VALUE, "failed to create a hardware parameters key, got error %#lx\n", GetLastError());
On Fri Jun 20 14:28:00 2025 +0000, Elizabeth Figura wrote:
Is there a nice way we can factor out most of the common code with SetupDi[GS]etDeviceProperty()?
Good point. The check for `DEVPKEY_DeviceInterface_Enabled` makes some duplications necessary, but I have tried to factor out most of the logic into `{set, get}_device_reg_property`. Thanks
On Fri Jun 20 13:59:52 2025 +0000, Vibhav Pant wrote:
changed this line in [version 3 of the diff](/wine/wine/-/merge_requests/8379/diffs?diff_id=187332&start_sha=8c1b0f3a2de15fd5f41fa1fa5b99070f0187cd75#ec76fe5c6a4ced08d2a20468fd1a904a90d50c2c_3168_3226)
Oops, fixed this, thanks.
v2:
* Factor out the read/write logic into `{set, get}_device_reg_property`. * Add additional tests to `ntoskrnl` to make sure `DEVPKEY_DeviceInterface_Enabled` is correctly set for device interfaces that have been enabled by the kernel.