[PATCH 1/1] wmic: Handle properly list for GET verb.
Nikolay Sivov
wine at gitlab.winehq.org
Mon Jul 4 10:46:23 CDT 2022
From: Nikolay Sivov <nsivov at codeweavers.com>
Instead of querying all properties and then matching to requested one,
first check if all requested properties are supported by given class.
Then select just that subset.
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
programs/wmic/main.c | 176 ++++++++++++++++++++++++++++---------------
1 file changed, 116 insertions(+), 60 deletions(-)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c
index 15b590098e7..cfc20e45ffd 100644
--- a/programs/wmic/main.c
+++ b/programs/wmic/main.c
@@ -61,34 +61,14 @@ static const WCHAR *find_class( const WCHAR *alias )
return NULL;
}
-static WCHAR *find_prop( IWbemClassObject *class, const WCHAR *prop )
-{
- SAFEARRAY *sa;
- WCHAR *ret = NULL;
- LONG i, last_index = 0;
- BSTR str;
-
- if (IWbemClassObject_GetNames( class, NULL, WBEM_FLAG_ALWAYS, NULL, &sa ) != S_OK) return NULL;
-
- SafeArrayGetUBound( sa, 1, &last_index );
- for (i = 0; i <= last_index; i++)
- {
- SafeArrayGetElement( sa, &i, &str );
- if (!wcsicmp( str, prop ))
- {
- ret = wcsdup( str );
- break;
- }
- }
- SafeArrayDestroy( sa );
- return ret;
-}
-
static int WINAPIV output_string( HANDLE handle, const WCHAR *msg, ... )
{
+ BOOL output = GetStdHandle(STD_OUTPUT_HANDLE) == handle;
+ static const WCHAR bomW[] = {0xfeff};
+ static BOOL bom;
va_list va_args;
int len;
- DWORD count;
+ DWORD count, bom_count = 0;
WCHAR buffer[8192];
va_start( va_args, msg );
@@ -96,9 +76,16 @@ static int WINAPIV output_string( HANDLE handle, const WCHAR *msg, ... )
va_end( va_args );
if (!WriteConsoleW( handle, buffer, len, &count, NULL ))
+ {
+ if (output && !bom)
+ {
+ WriteFile( handle, bomW, sizeof(bomW), &bom_count, FALSE );
+ bom = TRUE;
+ }
WriteFile( handle, buffer, len * sizeof(WCHAR), &count, FALSE );
+ }
- return count;
+ return count + bom_count;
}
static int output_error( int msg )
@@ -109,46 +96,90 @@ static int output_error( int msg )
return output_string( GetStdHandle(STD_ERROR_HANDLE), L"%s", buffer );
}
-static int output_header( const WCHAR *prop, ULONG column_width )
+static int output_text( const WCHAR *str, ULONG column_width )
{
- static const WCHAR bomW[] = {0xfeff};
- int len;
- DWORD count;
- WCHAR buffer[8192];
+ return output_string( GetStdHandle(STD_OUTPUT_HANDLE), L"%-*s", column_width, str );
+}
- len = swprintf( buffer, ARRAY_SIZE(buffer), L"%-*s\r\n", column_width, prop );
+static int output_newline( void )
+{
+ return output_string( GetStdHandle(STD_OUTPUT_HANDLE), L"\r\n" );
+}
- if (!WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, &count, NULL )) /* redirected */
+static WCHAR * strip_spaces(WCHAR *start)
+{
+ WCHAR *str = start, *end;
+
+ while (*str == ' ')
+ str++;
+
+ end = start + lstrlenW(start) - 1;
+ while (end >= start && *end == ' ')
{
- WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), bomW, sizeof(bomW), &count, FALSE );
- WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), buffer, len * sizeof(WCHAR), &count, FALSE );
- count += sizeof(bomW);
+ *end = '\0';
+ end--;
}
- return count;
+ return str;
}
-static int output_line( const WCHAR *str, ULONG column_width )
+static HRESULT process_property_list( IWbemClassObject *obj, const WCHAR *proplist, WCHAR **ret )
{
- return output_string( GetStdHandle(STD_OUTPUT_HANDLE), L"%-*s\r\n", column_width, str );
+ WCHAR *p, *ctx, *ptr, *stripped;
+ HRESULT hr = S_OK;
+
+ if (!(p = wcsdup( proplist ))) return E_OUTOFMEMORY;
+
+ if (!(stripped = malloc( (wcslen( proplist ) + 1) * sizeof(**ret) )))
+ {
+ free( p );
+ return E_OUTOFMEMORY;
+ }
+ *stripped = 0;
+
+ /* Validate that every requested property is supported. */
+ ptr = wcstok_s( p, L",", &ctx );
+ while (ptr)
+ {
+ ptr = strip_spaces( ptr );
+
+ if (FAILED(IWbemClassObject_Get( obj, ptr, 0, NULL, NULL, NULL )))
+ {
+ hr = E_FAIL;
+ break;
+ }
+ if (*stripped) wcscat( stripped, L"," );
+ wcscat( stripped, ptr );
+ ptr = wcstok_s( NULL, L",", &ctx );
+ }
+ free( p );
+
+ if (SUCCEEDED(hr))
+ *ret = stripped;
+ else
+ {
+ free( stripped );
+ *ret = NULL;
+ }
+
+ return hr;
}
-static int query_prop( const WCHAR *class, const WCHAR *propname )
+static int query_prop( const WCHAR *class, const WCHAR *propnames )
{
HRESULT hr;
IWbemLocator *locator = NULL;
IWbemServices *services = NULL;
IEnumWbemClassObject *result = NULL;
LONG flags = WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY;
- BSTR path = NULL, wql = NULL, query = NULL;
- WCHAR *prop = NULL;
- BOOL first = TRUE;
+ BSTR path = NULL, wql = NULL, query = NULL, name, str = NULL;
+ WCHAR *proplist = NULL;
int len, ret = -1;
IWbemClassObject *obj;
ULONG count, width = 0;
VARIANT v;
- WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propname));
+ WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propnames));
CoInitialize( NULL );
CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
@@ -162,10 +193,27 @@ static int query_prop( const WCHAR *class, const WCHAR *propname )
hr = IWbemLocator_ConnectServer( locator, path, NULL, NULL, NULL, 0, NULL, NULL, &services );
if (hr != S_OK) goto done;
- len = lstrlenW( class ) + ARRAY_SIZE(L"SELECT * FROM ");
+ if (!(str = SysAllocString( class ))) goto done;
+ hr = IWbemServices_GetObject( services, str, 0, NULL, &obj, NULL );
+ SysFreeString( str );
+ if (hr != S_OK)
+ {
+ WARN("Unrecognized class %s.\n", debugstr_w(class));
+ goto done;
+ }
+
+ /* Check that this class supports all requested properties. */
+ hr = process_property_list( obj, propnames, &proplist );
+ IWbemClassObject_Release( obj );
+ if (FAILED(hr))
+ {
+ output_error( STRING_INVALID_QUERY );
+ goto done;
+ }
+
+ len = lstrlenW( class ) + lstrlenW( proplist ) + ARRAY_SIZE(L"SELECT * FROM ");
if (!(query = SysAllocStringLen( NULL, len ))) goto done;
- lstrcpyW( query, L"SELECT * FROM " );
- lstrcatW( query, class );
+ swprintf( query, len, L"SELECT %s FROM %s", proplist, class );
if (!(wql = SysAllocString(L"WQL" ))) goto done;
hr = IWbemServices_ExecQuery( services, wql, query, flags, NULL, &result );
@@ -176,38 +224,46 @@ static int query_prop( const WCHAR *class, const WCHAR *propname )
IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
if (!count) break;
- if (!prop && !(prop = find_prop( obj, propname )))
- {
- output_error( STRING_INVALID_QUERY );
- goto done;
- }
- if (IWbemClassObject_Get( obj, prop, 0, &v, NULL, NULL ) == WBEM_S_NO_ERROR)
+ while (IWbemClassObject_Next( obj, 0, &name, &v, NULL, NULL ) == S_OK)
{
VariantChangeType( &v, &v, 0, VT_BSTR );
width = max( lstrlenW( V_BSTR( &v ) ), width );
VariantClear( &v );
+ SysFreeString( name );
}
+
IWbemClassObject_Release( obj );
}
width += 2;
+ /* Header */
+ IEnumWbemClassObject_Reset( result );
+ IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
+ if (count)
+ {
+ while (IWbemClassObject_Next( obj, 0, &name, NULL, NULL, NULL ) == S_OK)
+ {
+ output_text( name, width );
+ SysFreeString( name );
+ }
+ output_newline();
+ IWbemClassObject_Release( obj );
+ }
+
+ /* Values */
IEnumWbemClassObject_Reset( result );
for (;;)
{
IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
if (!count) break;
- if (first)
- {
- output_header( prop, width );
- first = FALSE;
- }
- if (IWbemClassObject_Get( obj, prop, 0, &v, NULL, NULL ) == WBEM_S_NO_ERROR)
+ while (IWbemClassObject_Next( obj, 0, NULL, &v, NULL, NULL ) == S_OK)
{
VariantChangeType( &v, &v, 0, VT_BSTR );
- output_line( V_BSTR( &v ), width );
+ output_text( V_BSTR( &v ), width );
VariantClear( &v );
}
+ output_newline();
IWbemClassObject_Release( obj );
}
ret = 0;
@@ -219,7 +275,7 @@ done:
SysFreeString( path );
SysFreeString( query );
SysFreeString( wql );
- free( prop );
+ free( proplist );
CoUninitialize();
return ret;
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/371
More information about the wine-devel
mailing list