Current implementation handles correctly % only at the end of the string. Nothing else matches.
The new implementation while naïve and recursive handles both _ and * correctly.
From: Arkadiusz Hiler ahiler@codeweavers.com
Current implementation handles correctly % only at the end of the string. Nothing else matches.
The new implementation while naïve and recursive handles both _ and * correctly. --- dlls/wbemprox/query.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
diff --git a/dlls/wbemprox/query.c b/dlls/wbemprox/query.c index 1087e271837..d7990305003 100644 --- a/dlls/wbemprox/query.c +++ b/dlls/wbemprox/query.c @@ -93,23 +93,30 @@ void destroy_view( struct view *view ) free( view ); }
-static BOOL eval_like( const WCHAR *lstr, const WCHAR *rstr ) +static BOOL eval_like( const WCHAR *text, const WCHAR *pattern ) { - const WCHAR *p = lstr, *q = rstr; + if (wcsstr( pattern, L"[" )) FIXME( "character ranges (i.e. [abc], [^a-z]) are not supported\n" );
- while (*p && *q) + while (*text) { - if (q[0] == '\' && q[1] == '\') q++; - if (*q == '%') + if (pattern[0] == '\' && pattern[1] == '\') pattern++; + + if (*pattern == '%') { - while (*q == '%') q++; - if (!*q) return TRUE; - while (*p && *q && towupper( *p ) == towupper( *q )) { p++; q++; }; - if (!*p && !*q) return TRUE; + while (*pattern == '%') pattern++; + if (!*pattern) return TRUE; + while (!eval_like( text, pattern ) && *text) text++; + + return !!*text; } - if (*q != '%' && towupper( *p++ ) != towupper( *q++ )) return FALSE; + + if (*pattern != '_' && towupper( *text ) != towupper( *pattern )) return FALSE; + text++; pattern++; } - return TRUE; + + while (*pattern == '%') pattern++; + + return *pattern == '\0'; }
static HRESULT eval_strcmp( UINT op, const WCHAR *lstr, const WCHAR *rstr, LONGLONG *val )
It matches both at the beginning and at the end here. This could use some tests.
It matches both at the beginning and at the end here.
It doesn't read like it does. Also not according to my testing using [this](https://gitlab.winehq.org/wine/wine/-/snippets/12):
<details> <summary>This MR</summary>
``` query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB%"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "6&2"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%6&2"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "MI_01%"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%MI_01"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%MI_01%"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB%MI_01%"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; }; ``` </details>
<details> <summary>Current Master</summary>
``` query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB%"
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_00\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_01\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&4&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
instance of Win32_PnPEntity { DeviceId = "USB\VID_1050&PID_0407&MI_02\512&1347&6&2"; Manufacturer = "The Wine Project"; Name = "Wine PnP Device"; };
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "6&2"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%6&2"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "MI_01%"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%MI_01"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "%MI_01%"
query: SELECT DeviceID FROM Win32_PnPEntity WHERE DeviceID LIKE "USB%MI_01%" ``` </details>
This could use some tests.
Definitely! I've been testing it via the program I've linked when I was writing this implementation. Do you have any idea how to made them work reliably? We cannot guarantee any devices on different system to be present. Especially between Windows and Linux. I've looked at some of the existing tests and they are just executing, never checking the result.
I've also haven't seen anything being unit tested in Wine. It might be fitting approach here.
You could have a test_like_query() modeled after test_select() and an exec_like_query() modeled after exec_query() that also checks the number of objects returned.
For queries you could use variations of this: `` SELECT * FROM Win32_Process WHERE Caption LIKE 'explorer.%' ``
Will do. Thanks for having a look and for the suggestion :-)