On Sun Sep 21 14:20:37 2025 +0000, Vibhav Pant wrote:
This function is called recursively for every sub-clause, so there would one call frame for the outer `AND_OPEN` expression, and then a recursive call for the inner `AND_OPEN`. Since logical operators are always paired, the code here in the inner call would skip to the nearest AND_CLOSE, set `expr_end_idx`, and then return. The outer call would then continue from `expr_end_idx+1.` I've added some more test cases to demonstrate this.
The function looks complicated, it's hard to tell and there's probably
a cleaner way to split the logic. Yes, this actually is two functions in one, so I have split this into `devprop_filter_eval_subexpr`, which gets called for evaluating sub-expressions inside a `{OPEN, ..., CLOSE}` expression and will recursively evaluate nested expressions, and the original `devprop_filter_matches_object`, which is only used for evaluating the outermost expression.
I don't think it works, for instance this test asserts:
``` memset( filters, 0, sizeof( filters ) ); filters[len++].Operator = DEVPROP_OPERATOR_OR_OPEN; filters[len++].Operator = DEVPROP_OPERATOR_AND_OPEN; filters[len++].Operator = DEVPROP_OPERATOR_NONE; filters[len++].Operator = DEVPROP_OPERATOR_AND_OPEN; filters[len++].Operator = DEVPROP_OPERATOR_NONE; filters[len++].Operator = DEVPROP_OPERATOR_AND_CLOSE; filters[len++].Operator = DEVPROP_OPERATOR_AND_CLOSE; filters[len++].Operator = DEVPROP_OPERATOR_NOT_OPEN; filters[len++].Operator = DEVPROP_OPERATOR_NONE; filters[len++].Operator = DEVPROP_OPERATOR_NOT_CLOSE; filters[len++].Operator = DEVPROP_OPERATOR_OR_CLOSE; objects = NULL; hr = pDevGetObjects( DevObjectTypeDeviceInterface, DevQueryFlagNone, 0, NULL, len, filters, &len, &objects ); ok( hr == S_OK, "got hr %#lx\n", hr ); pDevFreeObjects( len, objects ); ```