From: Vibhav Pant vibhavp@gmail.com
--- dlls/cfgmgr32/main.c | 53 ++++++++++++++----- dlls/cfgmgr32/tests/cfgmgr32.c | 24 ++++----- .../tests/devices.c | 4 +- 3 files changed, 54 insertions(+), 27 deletions(-)
diff --git a/dlls/cfgmgr32/main.c b/dlls/cfgmgr32/main.c index b7f5051fe47..8ae08e7c7e8 100644 --- a/dlls/cfgmgr32/main.c +++ b/dlls/cfgmgr32/main.c @@ -17,6 +17,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <assert.h> + #include "wine/debug.h" #include "wine/rbtree.h" #include "winreg.h" @@ -414,6 +416,9 @@ static HRESULT devprop_filter_eval_compare( const DEV_OBJECT *obj, const DEVPROP cmp = op & DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE ? wcsicmp( prop->Buffer, cmp_prop->Buffer ) : wcscmp( prop->Buffer, cmp_prop->Buffer ); break; + case DEVPROP_TYPE_GUID: + /* Any other comparison operator other than DEVPROP_OPERATOR_EQUALS with GUIDs evaluates to false. */ + if (!(op & DEVPROP_OPERATOR_EQUALS)) break; default: cmp = memcmp( prop->Buffer, cmp_prop->Buffer, prop->BufferSize ); break; @@ -455,14 +460,13 @@ static const DEVPROP_FILTER_EXPRESSION *find_closing_filter( const DEVPROP_FILTE }
/* Return S_OK if the specified filter expressions match the object, S_FALSE if it doesn't. */ -static HRESULT devprop_filter_matches_object( const DEV_OBJECT *obj, const DEVPROP_FILTER_EXPRESSION *filters, +static HRESULT devprop_filter_matches_object( const DEV_OBJECT *obj, DEVPROP_OPERATOR op_outer_logical, const DEVPROP_FILTER_EXPRESSION *filters, const DEVPROP_FILTER_EXPRESSION *end ) { HRESULT hr = S_OK;
- TRACE( "(%s, %p, %p)\n", debugstr_DEV_OBJECT( obj ), filters, end ); + TRACE( "(%s, %#x, %p, %p)\n", debugstr_DEV_OBJECT( obj ), op_outer_logical, filters, end );
- /* By default, the evaluation is performed by AND-ing all individual filter expressions. */ for (const DEVPROP_FILTER_EXPRESSION *filter = filters; filter < end; filter++) { DEVPROP_OPERATOR op = filter->Operator; @@ -470,26 +474,48 @@ static HRESULT devprop_filter_matches_object( const DEV_OBJECT *obj, const DEVPR if (op == DEVPROP_OPERATOR_NONE) { hr = S_FALSE; - break; } - if (op & (DEVPROP_OPERATOR_MASK_LIST | DEVPROP_OPERATOR_MASK_ARRAY)) + else if (op & (DEVPROP_OPERATOR_MASK_LIST | DEVPROP_OPERATOR_MASK_ARRAY)) { FIXME( "Unsupported list/array operator: %s\n", debugstr_DEVPROP_OPERATOR( op ) ); - continue; + hr = S_FALSE; } - if (op & DEVPROP_OPERATOR_MASK_LOGICAL) + else if (op & DEVPROP_OPERATOR_MASK_LOGICAL) { - FIXME( "Unsupported logical operator: %s\n", debugstr_DEVPROP_OPERATOR( op ) ); - continue; + const DEVPROP_FILTER_EXPRESSION *closing = find_closing_filter( filter, end ); + hr = devprop_filter_matches_object( obj, op & DEVPROP_OPERATOR_MASK_LOGICAL, filter + 1, closing ); + filter = closing; } - if (op & DEVPROP_OPERATOR_MASK_EVAL) + else if (op & DEVPROP_OPERATOR_MASK_EVAL) { hr = devprop_filter_eval_compare( obj, filter ); - if (FAILED( hr ) || hr == S_FALSE) - break; + } + if (FAILED( hr )) break; + + /* See if we can short-circuit. */ + switch (op_outer_logical) + { + /* {NOT_OPEN, ..., NOT_CLOSE} is the same as {NOT_OPEN, AND_OPEN, ..., AND_CLOSE, NOT_CLOSE}, so we can + * short circuit here as well. */ + case DEVPROP_OPERATOR_NOT_OPEN: + case DEVPROP_OPERATOR_AND_OPEN: + if (hr == S_FALSE) goto done; + break; + case DEVPROP_OPERATOR_OR_OPEN: + if (hr == S_OK) goto done; + break; + default: + assert( 0 ); + break; } }
+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; }
@@ -820,7 +846,8 @@ static HRESULT enum_dev_objects( DEV_OBJECT_TYPE type, ULONG props_len, const DE hr = dev_object_iface_get_props( &obj, set, &iface, props_len, props, all_props, FALSE ); if (SUCCEEDED( hr )) { - hr = devprop_filter_matches_object( &obj, filters, filters_end ); + /* By default, the evaluation is performed by AND-ing all individual filter expressions. */ + hr = devprop_filter_matches_object( &obj, DEVPROP_OPERATOR_AND_OPEN, filters, filters_end ); /* Shrink pProperties to only the desired ones, unless DevQueryFlagAllProperties is set. */ if (!all_props) dev_object_remove_unwanted_props( &obj, props_len, props ); diff --git a/dlls/cfgmgr32/tests/cfgmgr32.c b/dlls/cfgmgr32/tests/cfgmgr32.c index d08456521f8..6e78c2e6aa9 100644 --- a/dlls/cfgmgr32/tests/cfgmgr32.c +++ b/dlls/cfgmgr32/tests/cfgmgr32.c @@ -1406,8 +1406,8 @@ static void test_DevGetObjects( void ) objects = (DEV_OBJECT *)0xdeadbeef; hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if (len) ok( !len, "got len %lu\n", len ); - todo_wine_if (len) ok( !objects, "got objects %p\n", objects ); + ok( !len, "got len %lu\n", len ); + ok( !objects, "got objects %p\n", objects ); if (objects) pDevFreeObjects( len, objects );
/* Consequently, using the DEVPROP_OPERATOR_MODIFIER_NOT modifier will always match. */ @@ -1416,8 +1416,8 @@ static void test_DevGetObjects( void ) objects = NULL; hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if (!len) ok( len > 0, "got len %lu\n", len ); - todo_wine_if (!len) ok( !!objects, "got objects %p\n", objects ); + ok( len > 0, "got len %lu\n", len ); + ok( !!objects, "got objects %p\n", objects ); pDevFreeObjects( len, objects );
/* Make sure we get the same results with the max GUID value as well. */ @@ -1427,8 +1427,8 @@ static void test_DevGetObjects( void ) objects = (DEV_OBJECT *)0xdeadbeef; hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if (len) ok( !len, "got len %lu\n", len ); - todo_wine_if (len) ok( !objects, "got objects %p\n", objects ); + ok( !len, "got len %lu\n", len ); + ok( !objects, "got objects %p\n", objects ); if (objects) pDevFreeObjects( len, objects );
filters[0].Operator |= DEVPROP_OPERATOR_MODIFIER_NOT; @@ -1436,8 +1436,8 @@ static void test_DevGetObjects( void ) objects = NULL; hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, 1, filters, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if (!len) ok( len > 0, "got len %lu\n", len ); - todo_wine_if (!len) ok( !!objects, "got objects %p\n", objects ); + ok( len > 0, "got len %lu\n", len ); + ok( !!objects, "got objects %p\n", objects ); pDevFreeObjects( len, objects );
winetest_pop_context(); @@ -1476,8 +1476,8 @@ static void test_DevGetObjects( void ) hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, logical_op_test_cases[i].size, logical_op_test_cases[i].expr, &len2, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if( !len2 ) ok( len2 == len, "got len2 %lu != %lu\n", len2, len ); - todo_wine_if( !len2 ) ok( !!objects, "got objects %p\n", objects ); + ok( len2 == len, "got len2 %lu != %lu\n", len2, len ); + ok( !!objects, "got objects %p\n", objects ); pDevFreeObjects( len2, objects );
winetest_pop_context(); @@ -1492,8 +1492,8 @@ static void test_DevGetObjects( void ) hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, logical_op_empty_test_cases[i].size, logical_op_empty_test_cases[i].expr, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); - todo_wine_if( len ) ok( !len, "got len %lu\n", len ); - todo_wine_if( len ) ok( !objects, "got objects %p\n", objects ); + ok( !len, "got len %lu\n", len ); + ok( !objects, "got objects %p\n", objects );
winetest_pop_context(); } diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c index 433f9c33f2b..5c7e1fdc0f2 100644 --- a/dlls/windows.devices.enumeration/tests/devices.c +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -818,7 +818,7 @@ static void test_aqs_filters( void ) test_FindAllAsyncAqsFilter( statics, filters_empty, FALSE, FALSE ); test_CreateWatcherAqsFilter( statics, filters_empty, FALSE, FALSE, FALSE, FALSE );
- test_FindAllAsyncAqsFilter( statics, filters_boolean_op, FALSE, TRUE ); + test_FindAllAsyncAqsFilter( statics, filters_boolean_op, FALSE, FALSE ); test_CreateWatcherAqsFilter( statics, filters_boolean_op, FALSE, FALSE, FALSE, TRUE );
test_FindAllAsyncAqsFilter( statics, filters_simple, FALSE, FALSE ); @@ -827,7 +827,7 @@ static void test_aqs_filters( void ) test_FindAllAsyncAqsFilter( statics, filters_case_insensitive, TRUE, FALSE ); test_CreateWatcherAqsFilter( statics, filters_case_insensitive, TRUE, FALSE, FALSE, FALSE );
- test_FindAllAsyncAqsFilter( statics, filters_precedence, FALSE, TRUE ); + test_FindAllAsyncAqsFilter( statics, filters_precedence, FALSE, FALSE ); test_CreateWatcherAqsFilter( statics, filters_precedence, FALSE, FALSE, FALSE, TRUE );
test_FindAllAsyncAqsFilter( statics, filters_no_results, FALSE, FALSE );