[PATCH 0/6] MR10204: cfgmgr32: Get rid of setupapi dependency in DevObject* implementation (2/2).
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 | 9 +- 5 files changed, 102 insertions(+), 93 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..52368599ae2 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -1776,7 +1776,10 @@ static void test_DevGetObjects( void ) DEVPROP_FILTER_EXPRESSION *filters; const DEV_OBJECT *obj = &objects[j], *objects2; ULONG k, len2 = 0; - BOOL found = FALSE; + BOOL found = FALSE, todo; + + /* setupapi touches the DeviceInstance property, changing it to upper case when it shouldn't */ + todo = i == 0 && !wcsnicmp( obj->pszObjectId, L"\\\\?\\DISPLAY", 11 ); winetest_push_context( "device %s", debugstr_w( obj->pszObjectId ) ); ok( obj->ObjectType == test_cases[i].object_type, "got ObjectType %d\n", obj->ObjectType ); @@ -1796,7 +1799,7 @@ static void test_DevGetObjects( void ) * unique pair, so there should only be one object. */ if (test_cases[i].object_type == DevObjectTypeDeviceInterface || test_cases[i].object_type == DevObjectTypeDeviceInterfaceDisplay) - ok( len2 == 1, "got len2 %lu\n", len2 ); + todo_wine_if(todo) ok( len2 == 1, "got len2 %lu\n", len2 ); else ok( len2, "got len2 %lu\n", len2 ); for (k = 0; k < len2; k++) @@ -1807,7 +1810,7 @@ static void test_DevGetObjects( void ) break; } } - ok( found, "failed to get object using query filters\n" ); + todo_wine_if(todo) ok( found, "failed to get object using query filters\n" ); pDevFreeObjects( len2, objects2 ); free( filters ); winetest_pop_context(); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10204
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 ``` -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10204#note_130780
participants (3)
-
Alexandre Julliard (@julliard) -
Rémi Bernon -
Rémi Bernon (@rbernon)