[PATCH v2 0/6] MR10204: cfgmgr32: Get rid of setupapi dependency in DevObject* implementation (2/2).
-- v2: cfgmgr32: Enumerate the registry keys directly in enum_dev_objects. cfgmgr32: Return LSTATUS from enum_dev_objects callback. cfgmgr32: Use the new helpers to read device interface properties. cfgmgr32: Use the new helpers to get device interface property keys. cfgmgr32: Return BOOL from devprop_filter_matches_properties. cfgmgr32: Initialize device_interface structs in DEV_OBJECT functions. https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 12 ++------- dlls/cfgmgr32/cfgmgr32_private.h | 11 +++++++++ dlls/cfgmgr32/devobject.c | 42 +++++++++++++++++++++++--------- 3 files changed, 44 insertions(+), 21 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index 651e873a81b..b3c1c2c4af5 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -333,15 +333,7 @@ static LSTATUS get_class_property_keys( const GUID *class, DEVPROPKEY *buffer, U return err; } -struct device_interface -{ - GUID class_guid; - WCHAR class[39]; - WCHAR name[MAX_PATH]; - WCHAR refstr[MAX_PATH]; -}; - -static LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ) +LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ) { WCHAR *tmp; UINT len; @@ -357,7 +349,7 @@ static LSTATUS init_device_interface( struct device_interface *iface, const WCHA return guid_from_string( wcscpy( iface->class, tmp + 1 ), &iface->class_guid ); } -static LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ) +LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ) { WCHAR path[MAX_PATH]; swprintf( path, ARRAY_SIZE(path), L"%s\\%s", iface->class, iface->name ); diff --git a/dlls/cfgmgr32/cfgmgr32_private.h b/dlls/cfgmgr32/cfgmgr32_private.h index 118be9c1d0d..83789969f01 100644 --- a/dlls/cfgmgr32/cfgmgr32_private.h +++ b/dlls/cfgmgr32/cfgmgr32_private.h @@ -59,3 +59,14 @@ struct property void *buffer; DWORD *size; }; + +struct device_interface +{ + GUID class_guid; + WCHAR class[39]; + WCHAR name[MAX_PATH]; + WCHAR refstr[MAX_PATH]; +}; + +extern LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ); +extern LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ); diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index 804257c0d15..7c9643bd7d5 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -460,7 +460,7 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro for (i = 0; SUCCEEDED( hr ); i++) { char buffer[sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA_W ) + MAX_PATH * sizeof( WCHAR )]; - SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof( iface )}; + SP_DEVICE_INTERFACE_DATA iface_data = {.cbSize = sizeof( iface_data )}; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; HDEVINFO set = INVALID_HANDLE_VALUE; WCHAR iface_guid_str[40]; @@ -487,21 +487,32 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro continue; } - for (j = 0; SUCCEEDED( hr ) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface ); j++) + for (j = 0; SUCCEEDED( hr ) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface_data ); j++) { ULONG keys_len = props_len, properties_len = 0; const DEVPROPCOMPKEY *keys = props; DEVPROPERTY *properties = NULL; + struct device_interface iface; + LSTATUS err; + HKEY hkey; detail->cbSize = sizeof( *detail ); - if (!SetupDiGetDeviceInterfaceDetailW( set, &iface, detail, sizeof( buffer ), NULL, NULL )) continue; + if (!SetupDiGetDeviceInterfaceDetailW( set, &iface_data, detail, sizeof( buffer ), NULL, NULL )) continue; + if ((err = init_device_interface( &iface, detail->DevicePath )) || + (err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) + { + hr = HRESULT_FROM_WIN32(err); + break; + } /* If we're also filtering objects, get all properties for this object. Once the filters have been * evaluated, free properties that have not been requested, and set cPropertyCount to props_len. */ - if ((all_props || filters) && FAILED(hr = dev_get_device_interface_property_keys( set, &iface, &keys, &keys_len ))) break; - - if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; - else hr = dev_object_iface_get_props( set, &iface, keys, keys_len, properties, &properties_len ); + if (all_props || filters) hr = dev_get_device_interface_property_keys( set, &iface_data, &keys, &keys_len ); + if (SUCCEEDED(hr)) + { + if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; + else hr = dev_object_iface_get_props( set, &iface_data, keys, keys_len, properties, &properties_len ); + } if (SUCCEEDED( hr )) { @@ -520,6 +531,7 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro DevFreeObjectProperties( properties_len, properties ); if (keys != props) free( (void *)keys ); + RegCloseKey( hkey ); } if (set != INVALID_HANDLE_VALUE) @@ -1132,26 +1144,33 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, case DevObjectTypeDeviceInterface: case DevObjectTypeDeviceInterfaceDisplay: { - SP_DEVICE_INTERFACE_DATA iface = {.cbSize = sizeof( iface )}; + SP_DEVICE_INTERFACE_DATA iface_data = {.cbSize = sizeof( iface_data )}; ULONG properties_len = 0, keys_len = props_len; const DEVPROPCOMPKEY *keys = props; DEVPROPERTY *properties = NULL; + struct device_interface iface; HDEVINFO set; + LSTATUS err; + HKEY hkey; + + if ((err = init_device_interface( &iface, id ))) return HRESULT_FROM_WIN32(err); + if ((err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) return HRESULT_FROM_WIN32(err); set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL ); if (set == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32( GetLastError() ); - if (!SetupDiOpenDeviceInterfaceW( set, id, 0, &iface )) + if (!SetupDiOpenDeviceInterfaceW( set, id, 0, &iface_data )) { DWORD err = GetLastError(); SetupDiDestroyDeviceInfoList( set ); + RegCloseKey( hkey ); return HRESULT_FROM_WIN32(err == ERROR_NO_SUCH_DEVICE_INTERFACE ? ERROR_FILE_NOT_FOUND : err); } - if (all_props) hr = dev_get_device_interface_property_keys( set, &iface, &keys, &keys_len ); + if (all_props) hr = dev_get_device_interface_property_keys( set, &iface_data, &keys, &keys_len ); if (SUCCEEDED(hr)) { if ((properties_len = keys_len) && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; - else hr = dev_object_iface_get_props( set, &iface, keys, keys_len, properties, &properties_len ); + else hr = dev_object_iface_get_props( set, &iface_data, keys, keys_len, properties, &properties_len ); } *buf = properties; @@ -1159,6 +1178,7 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, if (keys != props) free( (void *)keys ); SetupDiDestroyDeviceInfoList( set ); + RegCloseKey( hkey ); break; } default: -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/devobject.c | 53 +++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 30 deletions(-) diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index 7c9643bd7d5..10dd16fa2bf 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -71,7 +71,7 @@ static const char *debugstr_DEVPROP_FILTER_EXPRESSION( const DEVPROP_FILTER_EXPR } /* Evaluate a filter expression containing comparison operator. */ -static HRESULT devprop_filter_eval_compare( const DEVPROPERTY *props, UINT props_len, const DEVPROP_FILTER_EXPRESSION *filter ) +static BOOL devprop_filter_eval_compare( const DEVPROPERTY *props, UINT props_len, const DEVPROP_FILTER_EXPRESSION *filter ) { const DEVPROPERTY *cmp_prop = &filter->Property; DEVPROP_OPERATOR op = filter->Operator; @@ -80,9 +80,6 @@ static HRESULT devprop_filter_eval_compare( const DEVPROPERTY *props, UINT props TRACE( "(%p, %u, %s)\n", props, props_len, debugstr_DEVPROP_FILTER_EXPRESSION( filter ) ); - if ((op & DEVPROP_OPERATOR_MASK_MODIFIER) & ~(DEVPROP_OPERATOR_MODIFIER_NOT | DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE)) - return E_INVALIDARG; - switch (filter->Operator & DEVPROP_OPERATOR_MASK_EVAL) { case DEVPROP_OPERATOR_EXISTS: @@ -105,6 +102,7 @@ static HRESULT devprop_filter_eval_compare( const DEVPROPERTY *props, UINT props case DEVPROP_TYPE_STRING: cmp = op & DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE ? wcsicmp( prop->Buffer, cmp_prop->Buffer ) : wcscmp( prop->Buffer, cmp_prop->Buffer ); + TRACE( "%s vs %s -> %u\n", debugstr_w(prop->Buffer), debugstr_w(cmp_prop->Buffer), !!cmp ); break; case DEVPROP_TYPE_GUID: /* Any other comparison operator other than DEVPROP_OPERATOR_EQUALS with GUIDs evaluates to false. */ @@ -127,12 +125,12 @@ static HRESULT devprop_filter_eval_compare( const DEVPROPERTY *props, UINT props case DEVPROP_OPERATOR_CONTAINS: default: FIXME( "Unsupported operator: %s", debugstr_DEVPROP_OPERATOR( filter->Operator & DEVPROP_OPERATOR_MASK_EVAL ) ); - return S_OK; + return FALSE; } - if (op & DEVPROP_OPERATOR_MODIFIER_NOT) - ret = !ret; - return ret ? S_OK : S_FALSE; + if (op & DEVPROP_OPERATOR_MODIFIER_NOT) ret = !ret; + TRACE( "-> %u\n", ret ); + return ret; } static const DEVPROP_FILTER_EXPRESSION *find_closing_filter( const DEVPROP_FILTER_EXPRESSION *filter, const DEVPROP_FILTER_EXPRESSION *end ) @@ -149,11 +147,11 @@ static const DEVPROP_FILTER_EXPRESSION *find_closing_filter( const DEVPROP_FILTE return NULL; } -/* Return S_OK if the specified filter expressions match the object, S_FALSE if it doesn't. */ -static HRESULT devprop_filter_matches_properties( const DEVPROPERTY *props, UINT props_len, DEVPROP_OPERATOR op_outer_logical, - const DEVPROP_FILTER_EXPRESSION *filters, const DEVPROP_FILTER_EXPRESSION *end ) +/* Return TRUE if the specified filter expressions match the object, FALSE if it doesn't. */ +static BOOL devprop_filter_matches_properties( const DEVPROPERTY *props, UINT props_len, DEVPROP_OPERATOR op_outer_logical, + const DEVPROP_FILTER_EXPRESSION *filters, const DEVPROP_FILTER_EXPRESSION *end ) { - HRESULT hr = S_OK; + BOOL ret = TRUE; TRACE( "(%p, %u, %#x, %p, %p)\n", props, props_len, op_outer_logical, filters, end ); @@ -161,26 +159,22 @@ static HRESULT devprop_filter_matches_properties( const DEVPROPERTY *props, UINT { DEVPROP_OPERATOR op = filter->Operator; - if (op == DEVPROP_OPERATOR_NONE) - { - hr = S_FALSE; - } + if (op == DEVPROP_OPERATOR_NONE) ret = FALSE; else if (op & (DEVPROP_OPERATOR_MASK_LIST | DEVPROP_OPERATOR_MASK_ARRAY)) { FIXME( "Unsupported list/array operator: %s\n", debugstr_DEVPROP_OPERATOR( op ) ); - hr = S_FALSE; + ret = FALSE; } else if (op & DEVPROP_OPERATOR_MASK_LOGICAL) { const DEVPROP_FILTER_EXPRESSION *closing = find_closing_filter( filter, end ); - hr = devprop_filter_matches_properties( props, props_len, op & DEVPROP_OPERATOR_MASK_LOGICAL, filter + 1, closing ); + ret = devprop_filter_matches_properties( props, props_len, op & DEVPROP_OPERATOR_MASK_LOGICAL, filter + 1, closing ); filter = closing; } else if (op & DEVPROP_OPERATOR_MASK_EVAL) { - hr = devprop_filter_eval_compare( props, props_len, filter ); + ret = devprop_filter_eval_compare( props, props_len, filter ); } - if (FAILED( hr )) break; /* See if we can short-circuit. */ switch (op_outer_logical) @@ -189,10 +183,10 @@ static HRESULT devprop_filter_matches_properties( const DEVPROPERTY *props, UINT * short circuit here as well. */ case DEVPROP_OPERATOR_NOT_OPEN: case DEVPROP_OPERATOR_AND_OPEN: - if (hr == S_FALSE) goto done; + if (!ret) goto done; break; case DEVPROP_OPERATOR_OR_OPEN: - if (hr == S_OK) goto done; + if (ret) goto done; break; default: assert( 0 ); @@ -201,12 +195,9 @@ static HRESULT devprop_filter_matches_properties( const DEVPROPERTY *props, UINT } done: - if (op_outer_logical == DEVPROP_OPERATOR_NOT_OPEN) - { - if (hr == S_FALSE) hr = S_OK; - else if (hr == S_OK) hr = S_FALSE; - } - return hr; + if (op_outer_logical == DEVPROP_OPERATOR_NOT_OPEN) ret = !ret; + TRACE( "-> %u\n", ret ); + return ret; } static BOOL devprop_type_validate( DEVPROPTYPE type, ULONG buf_size ) @@ -516,16 +507,18 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro if (SUCCEEDED( hr )) { + BOOL matches; + /* Sort properties by DEVPROPCOMPKEY for faster filter evaluation. */ if (filters) qsort( properties, properties_len, sizeof(*properties), devproperty_compare ); /* By default, the evaluation is performed by AND-ing all individual filter expressions. */ - hr = devprop_filter_matches_properties( properties, properties_len, DEVPROP_OPERATOR_AND_OPEN, filters, filters_end ); + matches = devprop_filter_matches_properties( properties, properties_len, DEVPROP_OPERATOR_AND_OPEN, filters, filters_end ); /* Shrink properties to only the desired ones, unless DevQueryFlagAllProperties is set. */ if (!all_props) select_properties( props, props_len, &properties, &properties_len ); - if (hr == S_OK) hr = callback( type, detail->DevicePath, &properties_len, &properties, data ); + if (matches) hr = callback( type, detail->DevicePath, &properties_len, &properties, data ); } DevFreeObjectProperties( properties_len, properties ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 2 +- dlls/cfgmgr32/cfgmgr32_private.h | 1 + dlls/cfgmgr32/devobject.c | 38 +++++++++++++++++--------------- 3 files changed, 22 insertions(+), 19 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index b3c1c2c4af5..6832a24e8f1 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -458,7 +458,7 @@ static LSTATUS get_device_interface_property( const struct device_interface *ifa return err; } -static LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ) +LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ) { ULONG capacity = *size, count = 0; LSTATUS err = ERROR_SUCCESS; diff --git a/dlls/cfgmgr32/cfgmgr32_private.h b/dlls/cfgmgr32/cfgmgr32_private.h index 83789969f01..63b28be3057 100644 --- a/dlls/cfgmgr32/cfgmgr32_private.h +++ b/dlls/cfgmgr32/cfgmgr32_private.h @@ -70,3 +70,4 @@ struct device_interface extern LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ); extern LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ); +extern LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ); diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index 10dd16fa2bf..8fcf7e8f81b 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -334,29 +334,30 @@ static HRESULT dev_get_device_interface_property( HDEVINFO set, SP_DEVICE_INTERF return HRESULT_FROM_WIN32( GetLastError() ); } -static HRESULT get_property_compare_keys( const DEVPROPKEY *keys, ULONG keys_len, const DEVPROPCOMPKEY **comp_keys, ULONG *comp_keys_len ) +static LSTATUS get_property_compare_keys( const DEVPROPKEY *keys, ULONG keys_len, const DEVPROPCOMPKEY **comp_keys, ULONG *comp_keys_len ) { - if (!(*comp_keys_len = keys_len)) return S_OK; - if (!(*comp_keys = calloc( keys_len, sizeof(**comp_keys) ))) return E_OUTOFMEMORY; + if (!(*comp_keys_len = keys_len)) return ERROR_SUCCESS; + if (!(*comp_keys = calloc( keys_len, sizeof(**comp_keys) ))) return ERROR_OUTOFMEMORY; for (UINT i = 0; i < keys_len; ++i) ((DEVPROPCOMPKEY *)*comp_keys)[i].Key = keys[i]; - return S_OK; + return ERROR_SUCCESS; } -static HRESULT dev_get_device_interface_property_keys( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface_data, const DEVPROPCOMPKEY **comp_keys, ULONG *comp_keys_len ) +static LSTATUS copy_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, const DEVPROPCOMPKEY **comp_keys, ULONG *comp_keys_len ) { - DEVPROPKEY *keys; - HRESULT hr; + DEVPROPKEY *tmp, *keys = NULL; + LSTATUS err; - if (SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, NULL, 0, comp_keys_len, 0 )) return S_OK; - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return HRESULT_FROM_WIN32( GetLastError() ); - if (!*comp_keys_len) return S_OK; + for (;;) + { + if (!(err = enum_device_interface_property_keys( hkey, iface, keys, comp_keys_len ))) break; + if (err != ERROR_MORE_DATA) return err; + if (!(tmp = realloc( keys, *comp_keys_len * sizeof(*keys) ))) return ERROR_OUTOFMEMORY; + keys = tmp; + } - if (!(keys = malloc( *comp_keys_len * sizeof(*keys) ))) return E_OUTOFMEMORY; - if (!SetupDiGetDeviceInterfacePropertyKeys( set, iface_data, keys, *comp_keys_len, comp_keys_len, 0 )) hr = HRESULT_FROM_WIN32( GetLastError() ); - else hr = get_property_compare_keys( keys, *comp_keys_len, comp_keys, comp_keys_len ); + get_property_compare_keys( keys, *comp_keys_len, comp_keys, comp_keys_len ); free( keys ); - - return hr; + return ERROR_SUCCESS; } static HRESULT dev_object_iface_get_props( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface_data, const DEVPROPCOMPKEY *keys, ULONG keys_len, @@ -498,8 +499,9 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro /* If we're also filtering objects, get all properties for this object. Once the filters have been * evaluated, free properties that have not been requested, and set cPropertyCount to props_len. */ - if (all_props || filters) hr = dev_get_device_interface_property_keys( set, &iface_data, &keys, &keys_len ); - if (SUCCEEDED(hr)) + if (all_props || filters) err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ); + if (err) hr = HRESULT_FROM_WIN32(err); + else { if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; else hr = dev_object_iface_get_props( set, &iface_data, keys, keys_len, properties, &properties_len ); @@ -1159,7 +1161,7 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, return HRESULT_FROM_WIN32(err == ERROR_NO_SUCH_DEVICE_INTERFACE ? ERROR_FILE_NOT_FOUND : err); } - if (all_props) hr = dev_get_device_interface_property_keys( set, &iface_data, &keys, &keys_len ); + if (all_props && (err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ))) hr = HRESULT_FROM_WIN32( err ); if (SUCCEEDED(hr)) { if ((properties_len = keys_len) && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/cfgmgr32.c | 4 +- dlls/cfgmgr32/cfgmgr32_private.h | 3 + dlls/cfgmgr32/devobject.c | 98 ++++++++++++-------------------- 3 files changed, 41 insertions(+), 64 deletions(-) diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index 6832a24e8f1..481c595ac7a 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -120,7 +120,7 @@ static LSTATUS open_device_classes_key( HKEY root, const WCHAR *key, REGSAM acce return open_key( root, path, access, open, hkey ); } -static LSTATUS init_property( struct property *prop, const DEVPROPKEY *key, DEVPROPTYPE *type, void *buffer, DWORD *size ) +LSTATUS init_property( struct property *prop, const DEVPROPKEY *key, DEVPROPTYPE *type, void *buffer, DWORD *size ) { if (!key) return ERROR_INVALID_PARAMETER; if (!(prop->type = type) || !(prop->size = size)) return ERROR_INVALID_USER_BUFFER; @@ -420,7 +420,7 @@ static const struct property_desc device_interface_properties[] = { &DEVPKEY_DeviceInterface_FriendlyName, DEVPROP_TYPE_STRING, L"FriendlyName" }, }; -static LSTATUS query_device_interface_property( HKEY hkey, const struct device_interface *iface, struct property *prop ) +LSTATUS query_device_interface_property( HKEY hkey, const struct device_interface *iface, struct property *prop ) { WCHAR prefix[MAX_PATH]; diff --git a/dlls/cfgmgr32/cfgmgr32_private.h b/dlls/cfgmgr32/cfgmgr32_private.h index 63b28be3057..9d98da62585 100644 --- a/dlls/cfgmgr32/cfgmgr32_private.h +++ b/dlls/cfgmgr32/cfgmgr32_private.h @@ -60,6 +60,8 @@ struct property DWORD *size; }; +extern LSTATUS init_property( struct property *prop, const DEVPROPKEY *key, DEVPROPTYPE *type, void *buffer, DWORD *size ); + struct device_interface { GUID class_guid; @@ -71,3 +73,4 @@ struct device_interface extern LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ); extern LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ); extern LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ); +extern LSTATUS query_device_interface_property( HKEY hkey, const struct device_interface *iface, struct property *prop ); diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index 8fcf7e8f81b..7dc6606a122 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -22,17 +22,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(setupapi); -static void devproperty_init( DEVPROPERTY *property, const DEVPROPKEY *key, DEVPROPTYPE type, - ULONG buf_size, void *buf ) -{ - property->CompKey.Key = *key; - property->CompKey.Store = DEVPROP_STORE_SYSTEM; - property->CompKey.LocaleName = NULL; - property->Type = type; - property->BufferSize = buf_size; - property->Buffer = buf; -} - static int devproperty_compare( const void *p1, const void *p2 ) { const DEVPROPCOMPKEY *key1 = &((DEVPROPERTY *)p1)->CompKey; @@ -323,15 +312,37 @@ static BOOL devprop_filters_validate( const DEVPROP_FILTER_EXPRESSION *filters, return TRUE; } -static HRESULT dev_get_device_interface_property( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface_data, struct property *prop ) +static LSTATUS copy_device_interface_property( HKEY hkey, const struct device_interface *iface, DEVPROPERTY *property ) { - if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, &prop->key, prop->type, NULL, 0, prop->size, 0 )) return S_OK; - if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return S_OK; + struct property prop; + LSTATUS err; + + init_property( &prop, &property->CompKey.Key, &property->Type, property->Buffer, &property->BufferSize ); + if (!(err = query_device_interface_property( hkey, iface, &prop ))) return ERROR_SUCCESS; + if (err && err != ERROR_MORE_DATA) return ERROR_SUCCESS; - if (!(prop->buffer = malloc( *prop->size ))) return E_OUTOFMEMORY; - if (SetupDiGetDeviceInterfacePropertyW( set, iface_data, &prop->key, prop->type, prop->buffer, *prop->size, prop->size, 0 )) return S_OK; - free( prop->buffer ); - return HRESULT_FROM_WIN32( GetLastError() ); + if (!(prop.buffer = malloc( property->BufferSize ))) return E_OUTOFMEMORY; + if ((err = query_device_interface_property( hkey, iface, &prop ))) free( prop.buffer ); + else property->Buffer = prop.buffer; + + return err; +} + +static LSTATUS copy_device_interface_properties( HKEY hkey, const struct device_interface *iface, const DEVPROPCOMPKEY *keys, ULONG keys_len, + DEVPROPERTY *properties, ULONG *props_len ) +{ + const DEVPROPCOMPKEY *key, *end; + DEVPROPERTY *prop = properties; + LSTATUS err = ERROR_SUCCESS; + + for (key = keys, end = keys + keys_len; !err && key < end; key++, prop++) + { + prop->CompKey = *key; + err = copy_device_interface_property( hkey, iface, prop ); + } + *props_len = prop - properties; + + return err; } static LSTATUS get_property_compare_keys( const DEVPROPKEY *keys, ULONG keys_len, const DEVPROPCOMPKEY **comp_keys, ULONG *comp_keys_len ) @@ -360,31 +371,6 @@ static LSTATUS copy_device_interface_property_keys( HKEY hkey, const struct devi return ERROR_SUCCESS; } -static HRESULT dev_object_iface_get_props( HDEVINFO set, SP_DEVICE_INTERFACE_DATA *iface_data, const DEVPROPCOMPKEY *keys, ULONG keys_len, - DEVPROPERTY *properties, ULONG *properties_len ) -{ - HRESULT hr = S_OK; - DWORD i; - - for (i = 0; i < keys_len; i++) - { - DWORD size = 0; - DEVPROPTYPE type; - struct property prop = - { - .key = keys[i].Key, - .type = &type, - .size = &size, - }; - - if (FAILED(hr = dev_get_device_interface_property( set, iface_data, &prop ))) break; - devproperty_init( properties + i, &prop.key, *prop.type, *prop.size, prop.buffer ); - } - - *properties_len = i; - return hr; -} - typedef HRESULT (*enum_device_object_cb)( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *context ); static UINT select_property( const DEVPROPCOMPKEY *key, DEVPROPERTY *props, DEVPROPERTY *select_end, DEVPROPERTY *props_end ) @@ -500,12 +486,12 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro /* If we're also filtering objects, get all properties for this object. Once the filters have been * evaluated, free properties that have not been requested, and set cPropertyCount to props_len. */ if (all_props || filters) err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ); - if (err) hr = HRESULT_FROM_WIN32(err); - else + if (!err) { - if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; - else hr = dev_object_iface_get_props( set, &iface_data, keys, keys_len, properties, &properties_len ); + if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; + else err = copy_device_interface_properties( hkey, &iface, keys, keys_len, properties, &properties_len ); } + if (err) hr = HRESULT_FROM_WIN32(err); if (SUCCEEDED( hr )) { @@ -1139,40 +1125,28 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, case DevObjectTypeDeviceInterface: case DevObjectTypeDeviceInterfaceDisplay: { - SP_DEVICE_INTERFACE_DATA iface_data = {.cbSize = sizeof( iface_data )}; ULONG properties_len = 0, keys_len = props_len; const DEVPROPCOMPKEY *keys = props; DEVPROPERTY *properties = NULL; struct device_interface iface; - HDEVINFO set; LSTATUS err; HKEY hkey; if ((err = init_device_interface( &iface, id ))) return HRESULT_FROM_WIN32(err); if ((err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) return HRESULT_FROM_WIN32(err); - set = SetupDiCreateDeviceInfoListExW( NULL, NULL, NULL, NULL ); - if (set == INVALID_HANDLE_VALUE) return HRESULT_FROM_WIN32( GetLastError() ); - if (!SetupDiOpenDeviceInterfaceW( set, id, 0, &iface_data )) - { - DWORD err = GetLastError(); - SetupDiDestroyDeviceInfoList( set ); - RegCloseKey( hkey ); - return HRESULT_FROM_WIN32(err == ERROR_NO_SUCH_DEVICE_INTERFACE ? ERROR_FILE_NOT_FOUND : err); - } - if (all_props && (err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ))) hr = HRESULT_FROM_WIN32( err ); if (SUCCEEDED(hr)) { - if ((properties_len = keys_len) && !(properties = calloc( keys_len, sizeof(*properties) ))) hr = E_OUTOFMEMORY; - else hr = dev_object_iface_get_props( set, &iface_data, keys, keys_len, properties, &properties_len ); + if ((properties_len = keys_len) && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; + else err = copy_device_interface_properties( hkey, &iface, keys, keys_len, properties, &properties_len ); + if (err) hr = HRESULT_FROM_WIN32( err ); } *buf = properties; *buf_len = properties_len; if (keys != props) free( (void *)keys ); - SetupDiDestroyDeviceInfoList( set ); RegCloseKey( hkey ); break; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/devobject.c | 106 +++++++++++++++++--------------------- 1 file changed, 48 insertions(+), 58 deletions(-) diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index 7dc6606a122..fac4107b0ab 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -371,7 +371,7 @@ static LSTATUS copy_device_interface_property_keys( HKEY hkey, const struct devi return ERROR_SUCCESS; } -typedef HRESULT (*enum_device_object_cb)( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *context ); +typedef LSTATUS (*enum_device_object_cb)( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *context ); static UINT select_property( const DEVPROPCOMPKEY *key, DEVPROPERTY *props, DEVPROPERTY *select_end, DEVPROPERTY *props_end ) { @@ -403,13 +403,12 @@ static void select_properties( const DEVPROPCOMPKEY *keys, ULONG keys_len, DEVPR } } -static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *props, ULONG props_len, BOOL all_props, +static LSTATUS enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *props, ULONG props_len, BOOL all_props, const DEVPROP_FILTER_EXPRESSION *filters, const DEVPROP_FILTER_EXPRESSION *filters_end, enum_device_object_cb callback, void *data ) { + LSTATUS err = ERROR_SUCCESS; HKEY iface_key; - HRESULT hr = S_OK; - DWORD i; switch (type) @@ -429,35 +428,31 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro case DevObjectTypeAEPProtocol: FIXME("Unsupported DEV_OJBECT_TYPE: %d\n", type ); default: - return S_OK; + return ERROR_SUCCESS; } if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) return HRESULT_FROM_WIN32( GetLastError() ); - for (i = 0; SUCCEEDED( hr ); i++) + for (i = 0; !err; i++) { char buffer[sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA_W ) + MAX_PATH * sizeof( WCHAR )]; SP_DEVICE_INTERFACE_DATA iface_data = {.cbSize = sizeof( iface_data )}; SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; HDEVINFO set = INVALID_HANDLE_VALUE; WCHAR iface_guid_str[40]; - DWORD ret, len, j; + DWORD len, j; GUID iface_class; len = ARRAY_SIZE( iface_guid_str ); - ret = RegEnumKeyExW( iface_key, i, iface_guid_str, &len, NULL, NULL, NULL, NULL ); - if (ret) - { - hr = (ret == ERROR_NO_MORE_ITEMS) ? S_OK : HRESULT_FROM_WIN32( ret ); - break; - } + err = RegEnumKeyExW( iface_key, i, iface_guid_str, &len, NULL, NULL, NULL, NULL ); + if (err) break; iface_guid_str[37] = '\0'; if (!UuidFromStringW( &iface_guid_str[1], &iface_class )) { set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); - if (set == INVALID_HANDLE_VALUE) hr = HRESULT_FROM_WIN32( GetLastError() ); + if (set == INVALID_HANDLE_VALUE) err = GetLastError(); } else { @@ -465,23 +460,19 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro continue; } - for (j = 0; SUCCEEDED( hr ) && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface_data ); j++) + for (j = 0; !err && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface_data ); j++) { ULONG keys_len = props_len, properties_len = 0; const DEVPROPCOMPKEY *keys = props; DEVPROPERTY *properties = NULL; struct device_interface iface; - LSTATUS err; HKEY hkey; detail->cbSize = sizeof( *detail ); if (!SetupDiGetDeviceInterfaceDetailW( set, &iface_data, detail, sizeof( buffer ), NULL, NULL )) continue; if ((err = init_device_interface( &iface, detail->DevicePath )) || (err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) - { - hr = HRESULT_FROM_WIN32(err); break; - } /* If we're also filtering objects, get all properties for this object. Once the filters have been * evaluated, free properties that have not been requested, and set cPropertyCount to props_len. */ @@ -491,9 +482,8 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; else err = copy_device_interface_properties( hkey, &iface, keys, keys_len, properties, &properties_len ); } - if (err) hr = HRESULT_FROM_WIN32(err); - if (SUCCEEDED( hr )) + if (!err) { BOOL matches; @@ -506,7 +496,7 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro /* Shrink properties to only the desired ones, unless DevQueryFlagAllProperties is set. */ if (!all_props) select_properties( props, props_len, &properties, &properties_len ); - if (matches) hr = callback( type, detail->DevicePath, &properties_len, &properties, data ); + if (matches) err = callback( type, detail->DevicePath, &properties_len, &properties, data ); } DevFreeObjectProperties( properties_len, properties ); @@ -518,8 +508,10 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro if (set != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList( set ); } + if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS; + RegCloseKey( iface_key ); - return SUCCEEDED( hr ) ? S_OK : hr; + return err; } struct objects_list @@ -528,16 +520,16 @@ struct objects_list ULONG len; }; -static HRESULT dev_objects_append( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *data ) +static LSTATUS dev_objects_append( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *context ) { - struct objects_list *list = data; + struct objects_list *list = context; DEV_OBJECT *tmp, *obj; - if (!(tmp = realloc( list->objects, (list->len + 1) * sizeof(*list->objects) ))) return E_OUTOFMEMORY; + if (!(tmp = realloc( list->objects, (list->len + 1) * sizeof(*list->objects) ))) return ERROR_OUTOFMEMORY; list->objects = tmp; obj = list->objects + list->len; - if (!(obj->pszObjectId = wcsdup( id ))) return E_OUTOFMEMORY; + if (!(obj->pszObjectId = wcsdup( id ))) return ERROR_OUTOFMEMORY; obj->ObjectType = type; obj->cPropertyCount = *props_len; obj->pProperties = *props; @@ -545,7 +537,7 @@ static HRESULT dev_objects_append( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props = NULL; list->len++; - return S_OK; + return ERROR_SUCCESS; } HRESULT WINAPI DevGetObjects( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_len, const DEVPROPCOMPKEY *props, @@ -562,7 +554,7 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l { ULONG valid_flags = DevQueryFlagAllProperties | DevQueryFlagLocalize; struct objects_list objects = {0}; - HRESULT hr = S_OK; + LSTATUS err; TRACE( "(%d, %#lx, %lu, %p, %lu, %p, %lu, %p, %p, %p)\n", type, flags, props_len, props, filters_len, filters, params_len, params, objs_len, objs ); @@ -576,18 +568,16 @@ HRESULT WINAPI DevGetObjectsEx( DEV_OBJECT_TYPE type, ULONG flags, ULONG props_l *objs = NULL; *objs_len = 0; - - hr = enum_dev_objects( type, props, props_len, !!(flags & DevQueryFlagAllProperties), filters, filters + filters_len, - dev_objects_append, &objects ); - if (SUCCEEDED( hr )) + if ((err = enum_dev_objects( type, props, props_len, !!(flags & DevQueryFlagAllProperties), filters, filters + filters_len, + dev_objects_append, &objects ))) { - *objs = objects.objects; - *objs_len = objects.len; - } - else DevFreeObjects( objects.len, objects.objects ); + return HRESULT_FROM_WIN32(err); + } - return hr; + *objs = objects.objects; + *objs_len = objects.len; + return S_OK; } void WINAPI DevFreeObjects( ULONG objs_len, const DEV_OBJECT *objs ) @@ -636,7 +626,7 @@ struct device_query_context HCMNOTIFICATION notify; }; -static HRESULT device_query_context_add_object( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *data ) +static LSTATUS device_query_context_add_object( DEV_OBJECT_TYPE type, const WCHAR *id, ULONG *props_len, DEVPROPERTY **props, void *data ) { DEV_QUERY_RESULT_ACTION_DATA action_data = { @@ -651,7 +641,7 @@ static HRESULT device_query_context_add_object( DEV_OBJECT_TYPE type, const WCHA }; struct device_query_context *ctx = data; struct device_iface_path *iface_entry = NULL; - HRESULT hr = S_OK; + LSTATUS err = ERROR_SUCCESS; TRACE( "(%s, %p)\n", debugstr_w( id ), data ); @@ -659,14 +649,14 @@ static HRESULT device_query_context_add_object( DEV_OBJECT_TYPE type, const WCHA EnterCriticalSection( &ctx->cs ); if (ctx->state == DevQueryStateClosed) - hr = E_CHANGED_STATE; + err = ERROR_CANCELLED; else if (type == DevObjectTypeDeviceInterface || type == DevObjectTypeDeviceInterfaceDisplay) { if (!(iface_entry = calloc( 1, sizeof( *iface_entry ) )) || !(iface_entry->path = wcsdup( id ))) { if (iface_entry) free( iface_entry->path ); free( iface_entry ); - hr = E_OUTOFMEMORY; + err = ERROR_OUTOFMEMORY; } else if (rb_put( &ctx->known_ifaces, iface_entry->path, &iface_entry->entry )) { @@ -676,7 +666,7 @@ static HRESULT device_query_context_add_object( DEV_OBJECT_TYPE type, const WCHA } LeaveCriticalSection( &ctx->cs ); - return hr; + return err; } static HRESULT device_query_context_create( struct device_query_context **query, DEV_OBJECT_TYPE type, ULONG flags, @@ -934,20 +924,20 @@ abort: static void CALLBACK device_query_enum_objects_async( TP_CALLBACK_INSTANCE *instance, void *data ) { struct device_query_context *ctx = data; + LSTATUS err = ERROR_SUCCESS; BOOL success; - HRESULT hr = S_OK; if (!ctx->filters) - hr = enum_dev_objects( ctx->type, ctx->prop_keys, ctx->prop_keys_len, !!(ctx->flags & DevQueryFlagAllProperties), + err = enum_dev_objects( ctx->type, ctx->prop_keys, ctx->prop_keys_len, !!(ctx->flags & DevQueryFlagAllProperties), 0, NULL, device_query_context_add_object, ctx ); EnterCriticalSection( &ctx->cs ); if (ctx->state == DevQueryStateClosed) - hr = E_CHANGED_STATE; + err = ERROR_CANCELLED; - switch (hr) + switch (err) { - case S_OK: + case ERROR_SUCCESS: ctx->state = DevQueryStateEnumCompleted; success = TrySubmitThreadpoolCallback( device_query_context_notify_enum_completed_async, ctx, NULL ); if (ctx->filters || !(ctx->flags & DevQueryFlagUpdateResults)) @@ -978,7 +968,7 @@ static void CALLBACK device_query_enum_objects_async( TP_CALLBACK_INSTANCE *inst break; } break; - case E_CHANGED_STATE: + case ERROR_CANCELLED: if (!(ctx->flags & DevQueryFlagAsyncClose)) { LeaveCriticalSection( &ctx->cs ); @@ -1105,9 +1095,9 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, const DEVPROPCOMPKEY *props, ULONG params_len, const DEV_QUERY_PARAMETER *params, ULONG *buf_len, const DEVPROPERTY **buf ) { - HRESULT hr = S_OK; ULONG valid_flags = DevQueryFlagAllProperties | DevQueryFlagLocalize; BOOL all_props = flags & DevQueryFlagAllProperties; + LSTATUS err = ERROR_SUCCESS; TRACE( "(%d, %s, %#lx, %lu, %p, %lu, %p, %p, %p)\n", type, debugstr_w( id ), flags, props_len, props, params_len, params, buf_len, buf ); @@ -1129,18 +1119,16 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, const DEVPROPCOMPKEY *keys = props; DEVPROPERTY *properties = NULL; struct device_interface iface; - LSTATUS err; HKEY hkey; - if ((err = init_device_interface( &iface, id ))) return HRESULT_FROM_WIN32(err); - if ((err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) return HRESULT_FROM_WIN32(err); + if ((err = init_device_interface( &iface, id ))) break; + if ((err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) break; - if (all_props && (err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ))) hr = HRESULT_FROM_WIN32( err ); - if (SUCCEEDED(hr)) + if (all_props) err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ); + if (!err) { if ((properties_len = keys_len) && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; else err = copy_device_interface_properties( hkey, &iface, keys, keys_len, properties, &properties_len ); - if (err) hr = HRESULT_FROM_WIN32( err ); } *buf = properties; @@ -1152,10 +1140,12 @@ HRESULT WINAPI DevGetObjectPropertiesEx( DEV_OBJECT_TYPE type, const WCHAR *id, } default: FIXME( "Unsupported DEV_OBJECT_TYPE: %d\n", type ); - hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ); + err = ERROR_FILE_NOT_FOUND; + break; } - return hr; + if (err) return HRESULT_FROM_WIN32(err); + return S_OK; } const DEVPROPERTY *WINAPI DevFindProperty( const DEVPROPKEY *key, DEVPROPSTORE store, const WCHAR *locale, -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/cfgmgr32/Makefile.in | 2 +- dlls/cfgmgr32/cfgmgr32.c | 22 ++++- dlls/cfgmgr32/cfgmgr32_private.h | 8 ++ dlls/cfgmgr32/devobject.c | 154 ++++++++++++++----------------- dlls/cfgmgr32/tests/cfgmgr32.c | 8 ++ 5 files changed, 104 insertions(+), 90 deletions(-) diff --git a/dlls/cfgmgr32/Makefile.in b/dlls/cfgmgr32/Makefile.in index 1c04637124f..b33d300ce6a 100644 --- a/dlls/cfgmgr32/Makefile.in +++ b/dlls/cfgmgr32/Makefile.in @@ -1,6 +1,6 @@ MODULE = cfgmgr32.dll IMPORTLIB = cfgmgr32 -IMPORTS = advapi32 rpcrt4 sechost setupapi +IMPORTS = advapi32 rpcrt4 sechost SOURCES = \ cfgmgr32.c \ diff --git a/dlls/cfgmgr32/cfgmgr32.c b/dlls/cfgmgr32/cfgmgr32.c index 481c595ac7a..ff179295f02 100644 --- a/dlls/cfgmgr32/cfgmgr32.c +++ b/dlls/cfgmgr32/cfgmgr32.c @@ -191,8 +191,6 @@ static LSTATUS return_property_bool( struct property *prop, DEVPROP_BOOLEAN valu return return_property( prop, DEVPROP_TYPE_BOOLEAN, &value, sizeof(value) ); } -typedef LSTATUS (*enum_objects_cb)( HKEY hkey, const void *object, const WCHAR *path, UINT path_len, void *context ); - static LSTATUS enum_objects_size( HKEY hkey, const void *object, const WCHAR *path, UINT path_len, void *context ) { UINT *total = context; @@ -397,6 +395,26 @@ static LSTATUS enum_class_device_interfaces( HKEY root, struct device_interface return err; } +LSTATUS enum_device_interfaces( BOOL all, enum_objects_cb callback, void *context ) +{ + struct device_interface iface; + LSTATUS err = ERROR_SUCCESS; + HKEY root, class_key; + + if ((root = cache_root_key( HKEY_LOCAL_MACHINE, device_classesW, NULL )) == (HKEY)-1) return ERROR_FILE_NOT_FOUND; + + for (UINT i = 0; !err && !(err = RegEnumKeyW( root, i, iface.class, ARRAY_SIZE(iface.class) )); i++) + { + if ((err = guid_from_string( iface.class, &iface.class_guid ))) continue; + if ((err = open_key( root, iface.class, KEY_ENUMERATE_SUB_KEYS, TRUE, &class_key ))) continue; + err = enum_class_device_interfaces( class_key, &iface, NULL, all, callback, context ); + RegCloseKey( class_key ); + } + if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS; + + return err; +} + static LSTATUS enum_device_interface_list( GUID *class, DEVINSTID_W instance_id, BOOL all, enum_objects_cb callback, void *context ) { struct device_interface iface; diff --git a/dlls/cfgmgr32/cfgmgr32_private.h b/dlls/cfgmgr32/cfgmgr32_private.h index 9d98da62585..81ebd413c12 100644 --- a/dlls/cfgmgr32/cfgmgr32_private.h +++ b/dlls/cfgmgr32/cfgmgr32_private.h @@ -70,6 +70,14 @@ struct device_interface WCHAR refstr[MAX_PATH]; }; +static inline const char *debugstr_device_interface( const struct device_interface *iface ) +{ + return wine_dbg_sprintf( "{%s %s %s}", debugstr_w(iface->class), debugstr_w(iface->name), debugstr_w(iface->refstr) ); +} + +typedef LSTATUS (*enum_objects_cb)( HKEY hkey, const void *object, const WCHAR *path, UINT path_len, void *context ); +extern LSTATUS enum_device_interfaces( BOOL all, enum_objects_cb callback, void *context ); + extern LSTATUS init_device_interface( struct device_interface *iface, const WCHAR *name ); extern LSTATUS open_device_interface_key( const struct device_interface *iface, REGSAM access, BOOL open, HKEY *hkey ); extern LSTATUS enum_device_interface_property_keys( HKEY hkey, const struct device_interface *iface, DEVPROPKEY *buffer, ULONG *size ); diff --git a/dlls/cfgmgr32/devobject.c b/dlls/cfgmgr32/devobject.c index fac4107b0ab..2ee2c1f8387 100644 --- a/dlls/cfgmgr32/devobject.c +++ b/dlls/cfgmgr32/devobject.c @@ -403,19 +403,81 @@ static void select_properties( const DEVPROPCOMPKEY *keys, ULONG keys_len, DEVPR } } +struct enum_dev_object_params +{ + DEV_OBJECT_TYPE type; + const DEVPROPCOMPKEY *props; + ULONG props_len; + BOOL all_props; + const DEVPROP_FILTER_EXPRESSION *filters; + const DEVPROP_FILTER_EXPRESSION *filters_end; + enum_device_object_cb callback; + void *context; +}; + +static LSTATUS enum_dev_objects_device_interface( HKEY hkey, const void *object, const WCHAR *name, UINT name_len, void *context ) +{ + struct enum_dev_object_params *params = context; + ULONG keys_len = params->props_len, properties_len = 0; + const struct device_interface *iface = object; + const DEVPROPCOMPKEY *keys = params->props; + DEVPROPERTY *properties = NULL; + LSTATUS err = ERROR_SUCCESS; + BOOL matches; + + TRACE( "hkey %p object %s name %s\n", hkey, debugstr_device_interface(iface), debugstr_w(name) ); + + /* If we're also filtering objects, get all properties for this object. Once the filters have been + * evaluated, free properties that have not been requested, and set cPropertyCount to comp_keys_len. */ + if (params->all_props || params->filters) err = copy_device_interface_property_keys( hkey, iface, &keys, &keys_len ); + if (!err) + { + if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; + else err = copy_device_interface_properties( hkey, iface, keys, keys_len, properties, &properties_len ); + } + + if (!err) + { + /* Sort properties by DEVPROPCOMPKEY for faster filter evaluation. */ + if (params->filters) qsort( properties, properties_len, sizeof(*properties), devproperty_compare ); + + /* By default, the evaluation is performed by AND-ing all individual filter expressions. */ + matches = devprop_filter_matches_properties( properties, properties_len, DEVPROP_OPERATOR_AND_OPEN, params->filters, params->filters_end ); + + /* Shrink properties to only the desired ones, unless DevQueryFlagAllProperties is set. */ + if (!params->all_props) select_properties( params->props, params->props_len, &properties, &properties_len ); + + if (matches) err = params->callback( params->type, name, &properties_len, &properties, params->context ); + } + + DevFreeObjectProperties( properties_len, properties ); + if (params->all_props || params->filters) free( (void *)keys ); + + return err; +} + static LSTATUS enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *props, ULONG props_len, BOOL all_props, const DEVPROP_FILTER_EXPRESSION *filters, const DEVPROP_FILTER_EXPRESSION *filters_end, - enum_device_object_cb callback, void *data ) + enum_device_object_cb callback, void *context ) { - LSTATUS err = ERROR_SUCCESS; - HKEY iface_key; - DWORD i; + struct enum_dev_object_params params = + { + .type = type, + .props = props, + .props_len = props_len, + .all_props = all_props, + .filters = filters, + .filters_end = filters_end, + .callback = callback, + .context = context, + }; switch (type) { case DevObjectTypeDeviceInterface: case DevObjectTypeDeviceInterfaceDisplay: - break; + return enum_device_interfaces( TRUE, enum_dev_objects_device_interface, ¶ms ); + case DevObjectTypeDeviceContainer: case DevObjectTypeDevice: case DevObjectTypeDeviceInterfaceClass: @@ -430,88 +492,6 @@ static LSTATUS enum_dev_objects( DEV_OBJECT_TYPE type, const DEVPROPCOMPKEY *pro default: return ERROR_SUCCESS; } - - if (!(iface_key = SetupDiOpenClassRegKeyExW( NULL, KEY_ENUMERATE_SUB_KEYS, DIOCR_INTERFACE, NULL, NULL ))) - return HRESULT_FROM_WIN32( GetLastError() ); - - for (i = 0; !err; i++) - { - char buffer[sizeof( SP_DEVICE_INTERFACE_DETAIL_DATA_W ) + MAX_PATH * sizeof( WCHAR )]; - SP_DEVICE_INTERFACE_DATA iface_data = {.cbSize = sizeof( iface_data )}; - SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (void *)buffer; - HDEVINFO set = INVALID_HANDLE_VALUE; - WCHAR iface_guid_str[40]; - DWORD len, j; - GUID iface_class; - - len = ARRAY_SIZE( iface_guid_str ); - err = RegEnumKeyExW( iface_key, i, iface_guid_str, &len, NULL, NULL, NULL, NULL ); - if (err) break; - - iface_guid_str[37] = '\0'; - if (!UuidFromStringW( &iface_guid_str[1], &iface_class )) - { - set = SetupDiGetClassDevsW( &iface_class, NULL, NULL, DIGCF_DEVICEINTERFACE ); - if (set == INVALID_HANDLE_VALUE) err = GetLastError(); - } - else - { - ERR( "Could not parse device interface GUID %s\n", debugstr_w( iface_guid_str ) ); - continue; - } - - for (j = 0; !err && SetupDiEnumDeviceInterfaces( set, NULL, &iface_class, j, &iface_data ); j++) - { - ULONG keys_len = props_len, properties_len = 0; - const DEVPROPCOMPKEY *keys = props; - DEVPROPERTY *properties = NULL; - struct device_interface iface; - HKEY hkey; - - detail->cbSize = sizeof( *detail ); - if (!SetupDiGetDeviceInterfaceDetailW( set, &iface_data, detail, sizeof( buffer ), NULL, NULL )) continue; - if ((err = init_device_interface( &iface, detail->DevicePath )) || - (err = open_device_interface_key( &iface, KEY_ALL_ACCESS, TRUE, &hkey ))) - break; - - /* If we're also filtering objects, get all properties for this object. Once the filters have been - * evaluated, free properties that have not been requested, and set cPropertyCount to props_len. */ - if (all_props || filters) err = copy_device_interface_property_keys( hkey, &iface, &keys, &keys_len ); - if (!err) - { - if (keys_len && !(properties = calloc( keys_len, sizeof(*properties) ))) err = ERROR_OUTOFMEMORY; - else err = copy_device_interface_properties( hkey, &iface, keys, keys_len, properties, &properties_len ); - } - - if (!err) - { - BOOL matches; - - /* Sort properties by DEVPROPCOMPKEY for faster filter evaluation. */ - if (filters) qsort( properties, properties_len, sizeof(*properties), devproperty_compare ); - - /* By default, the evaluation is performed by AND-ing all individual filter expressions. */ - matches = devprop_filter_matches_properties( properties, properties_len, DEVPROP_OPERATOR_AND_OPEN, filters, filters_end ); - - /* Shrink properties to only the desired ones, unless DevQueryFlagAllProperties is set. */ - if (!all_props) select_properties( props, props_len, &properties, &properties_len ); - - if (matches) err = callback( type, detail->DevicePath, &properties_len, &properties, data ); - } - - DevFreeObjectProperties( properties_len, properties ); - - if (keys != props) free( (void *)keys ); - RegCloseKey( hkey ); - } - - if (set != INVALID_HANDLE_VALUE) - SetupDiDestroyDeviceInfoList( set ); - } - if (err == ERROR_NO_MORE_ITEMS) err = ERROR_SUCCESS; - - RegCloseKey( iface_key ); - return err; } struct objects_list diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index 676537c97bd..ae113c13bb1 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -1789,6 +1789,14 @@ static void test_DevGetObjects( void ) filters = calloc( obj->cPropertyCount, sizeof( *filters ) ); /* If there are no logical operators present, then logical AND is used. */ filter_add_props( filters, obj->cPropertyCount, obj->pProperties, TRUE ); + + /* setupapi touches the DeviceInstance property, changing it to upper case when it shouldn't */ + if (i == 0 && !wcsnicmp( obj->pszObjectId, L"\\\\?\\DISPLAY", 11 )) + { + for (UINT k = 0; k < obj->cPropertyCount; k++) + filters[k].Operator |= DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE; + } + hr = pDevGetObjects( test_cases[i].object_type, DevQueryFlagAllProperties, 0, NULL, obj->cPropertyCount, filters, &len2, &objects2 ); ok( hr == S_OK, "got hr %#lx\n", hr ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
On Mon Mar 2 11:08:40 2026 +0000, Alexandre Julliard wrote:
I'm getting test failures locally (but not on the CI), is that expected? ``` cfgmgr32.c:1802: Test succeeded inside todo block: test_cases[0]: device L"\\\\?\\DISPLAY#BNQ7954#0000&0000#{E6F07B5F-EE97-4A90-B076-33F57BF4EAA7}": got len2 1 cfgmgr32.c:1813: Test succeeded inside todo block: test_cases[0]: device L"\\\\?\\DISPLAY#BNQ7954#0000&0000#{E6F07B5F-EE97-4A90-B076-33F57BF4EAA7}": failed to get object using query filters ``` There was some property casing logic change, as going through setupapi modified the DeviceInstance property in the registry to uppercase, whereas the code now only reads the registry property, as keeps the casing it had. This made the tests to fail if the property wasn't always uppercase and I had added a todo for that, but in your case the device instance value was already uppercase.
I changed the test logic to make sure we compare the values case insensitively. The setupapi code needs to be fixed but that'll be done by changing it to use cfgmgr32. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10204#note_130896
participants (2)
-
Rémi Bernon -
Rémi Bernon (@rbernon)