The first two patches are mostly needed to make wmic.exe work on Windows as well for easier testing and distinguishing between wmic.exe bugs and underlying libraries bugs (although it also makes sense not to depend on wbemprox implementation differences in Wine).
From: Paul Gofman pgofman@codeweavers.com
The result access is not forward only. --- programs/wmic/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c index cfc20e45ffd..2eb2895031e 100644 --- a/programs/wmic/main.c +++ b/programs/wmic/main.c @@ -171,7 +171,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) IWbemLocator *locator = NULL; IWbemServices *services = NULL; IEnumWbemClassObject *result = NULL; - LONG flags = WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY; + LONG flags = WBEM_FLAG_RETURN_IMMEDIATELY; BSTR path = NULL, wql = NULL, query = NULL, name, str = NULL; WCHAR *proplist = NULL; int len, ret = -1;
From: Paul Gofman pgofman@codeweavers.com
Otherwise enumeration fails on Windows. --- programs/wmic/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c index 2eb2895031e..72a54c09b57 100644 --- a/programs/wmic/main.c +++ b/programs/wmic/main.c @@ -224,6 +224,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); if (!count) break;
+ IWbemClassObject_BeginEnumeration( obj, 0 ); while (IWbemClassObject_Next( obj, 0, &name, &v, NULL, NULL ) == S_OK) { VariantChangeType( &v, &v, 0, VT_BSTR ); @@ -241,6 +242,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); if (count) { + IWbemClassObject_BeginEnumeration( obj, 0 ); while (IWbemClassObject_Next( obj, 0, &name, NULL, NULL, NULL ) == S_OK) { output_text( name, width ); @@ -256,7 +258,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) { IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); if (!count) break; - + IWbemClassObject_BeginEnumeration( obj, 0 ); while (IWbemClassObject_Next( obj, 0, NULL, &v, NULL, NULL ) == S_OK) { VariantChangeType( &v, &v, 0, VT_BSTR );
From: Paul Gofman pgofman@codeweavers.com
wmic currently crashes on, e. g., VT_EMPTY or VT_ARRAY types returned. --- programs/wmic/main.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c index 72a54c09b57..ef3ca5fff4e 100644 --- a/programs/wmic/main.c +++ b/programs/wmic/main.c @@ -165,6 +165,19 @@ static HRESULT process_property_list( IWbemClassObject *obj, const WCHAR *propli return hr; }
+static void convert_to_bstr( VARIANT *v ) +{ + VARTYPE vt; + + if (SUCCEEDED(VariantChangeType( v, v, 0, VT_BSTR ))) return; + vt = V_VT(v); + VariantClear( v ); + V_VT(v) = VT_BSTR; + V_BSTR(v) = SysAllocString( L"" ); + if (vt != VT_NULL && vt != VT_EMPTY) + WINE_FIXME( "Could not convert variant, vt %u.\n", vt ); +} + static int query_prop( const WCHAR *class, const WCHAR *propnames ) { HRESULT hr; @@ -227,7 +240,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) IWbemClassObject_BeginEnumeration( obj, 0 ); while (IWbemClassObject_Next( obj, 0, &name, &v, NULL, NULL ) == S_OK) { - VariantChangeType( &v, &v, 0, VT_BSTR ); + convert_to_bstr( &v ); width = max( lstrlenW( V_BSTR( &v ) ), width ); VariantClear( &v ); SysFreeString( name ); @@ -261,7 +274,7 @@ static int query_prop( const WCHAR *class, const WCHAR *propnames ) IWbemClassObject_BeginEnumeration( obj, 0 ); while (IWbemClassObject_Next( obj, 0, NULL, &v, NULL, NULL ) == S_OK) { - VariantChangeType( &v, &v, 0, VT_BSTR ); + convert_to_bstr( &v ); output_text( V_BSTR( &v ), width ); VariantClear( &v ); }
From: Paul Gofman pgofman@codeweavers.com
--- programs/wmic/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c index ef3ca5fff4e..e0ba498e5f6 100644 --- a/programs/wmic/main.c +++ b/programs/wmic/main.c @@ -47,7 +47,8 @@ alias_map[] = { L"process", L"Win32_Process" }, { L"baseboard", L"Win32_BaseBoard" }, { L"diskdrive", L"Win32_DiskDrive" }, - { L"memorychip", L"Win32_PhysicalMemory" } + { L"memorychip", L"Win32_PhysicalMemory" }, + { L"nicconfig", L"Win32_NetworkAdapterConfiguration" }, };
static const WCHAR *find_class( const WCHAR *alias )
From: Paul Gofman pgofman@codeweavers.com
--- programs/wmic/main.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/programs/wmic/main.c b/programs/wmic/main.c index e0ba498e5f6..c8ded9d85c2 100644 --- a/programs/wmic/main.c +++ b/programs/wmic/main.c @@ -172,6 +172,45 @@ static void convert_to_bstr( VARIANT *v )
if (SUCCEEDED(VariantChangeType( v, v, 0, VT_BSTR ))) return; vt = V_VT(v); + if (vt == (VT_ARRAY | VT_BSTR)) + { + unsigned int i, count, len; + BSTR *strings; + BSTR out; + + if (FAILED(SafeArrayAccessData( V_ARRAY(v), (void **)&strings ))) + { + WINE_ERR( "Could not access array.\n" ); + goto done; + } + count = V_ARRAY(v)->rgsabound->cElements; + len = 0; + for (i = 0; i < count; ++i) + len += wcslen( strings[i] ); + len += count * 2 + 2; + if (count) len += 2 * (count - 1); + V_VT(v) = VT_BSTR; + V_BSTR(v) = out = SysAllocStringLen( NULL, len ); + *out++ = '{'; + for (i = 0; i < count; ++i) + { + if (i) + { + memcpy( out, L", ", 2 * sizeof(*out) ); + out += 2; + } + *out++ = '"'; + len = wcslen( strings[i] ); + memcpy( out, strings[i], len * sizeof(*out) ); + out += len; + *out++ = '"'; + } + *out++ = '}'; + *out = 0; + SafeArrayUnaccessData( V_ARRAY(v) ); + return; + } +done: VariantClear( v ); V_VT(v) = VT_BSTR; V_BSTR(v) = SysAllocString( L"" );