From 268e8b2366acfd910bebfce4c5c6d07519d89e9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sat, 26 Oct 2013 01:02:19 +0000 Subject: [PATCH] [WMIC] Import WMIC ("Windows Management Instrumentation Console") from Wine 1.7.5 (just released yesterday, 25/10/2013), in which we include only the necessary headers. Sync up README.WINE too. WMIC is needed (amongst other things) for retrieving the date of the build when configuring a new build using RosBE. Dedicated to Sylvain Petreolle and Amine Khaldi. svn path=/trunk/; revision=60748 --- .../base/applications/cmdutils/CMakeLists.txt | 1 + .../applications/cmdutils/wmic/CMakeLists.txt | 6 + .../base/applications/cmdutils/wmic/wmic.c | 265 ++++++++++++++++++ .../base/applications/cmdutils/wmic/wmic.h | 23 ++ .../base/applications/cmdutils/wmic/wmic.rc | 28 ++ reactos/media/doc/README.WINE | 28 +- 6 files changed, 338 insertions(+), 13 deletions(-) create mode 100644 reactos/base/applications/cmdutils/wmic/CMakeLists.txt create mode 100644 reactos/base/applications/cmdutils/wmic/wmic.c create mode 100644 reactos/base/applications/cmdutils/wmic/wmic.h create mode 100644 reactos/base/applications/cmdutils/wmic/wmic.rc diff --git a/reactos/base/applications/cmdutils/CMakeLists.txt b/reactos/base/applications/cmdutils/CMakeLists.txt index e6f7394b254..a64f6ad523a 100644 --- a/reactos/base/applications/cmdutils/CMakeLists.txt +++ b/reactos/base/applications/cmdutils/CMakeLists.txt @@ -7,4 +7,5 @@ add_subdirectory(lodctr) add_subdirectory(more) add_subdirectory(reg) add_subdirectory(taskkill) +add_subdirectory(wmic) add_subdirectory(xcopy) diff --git a/reactos/base/applications/cmdutils/wmic/CMakeLists.txt b/reactos/base/applications/cmdutils/wmic/CMakeLists.txt new file mode 100644 index 00000000000..e30508bd19f --- /dev/null +++ b/reactos/base/applications/cmdutils/wmic/CMakeLists.txt @@ -0,0 +1,6 @@ + +add_executable(wmic wmic.c wmic.rc) +target_link_libraries(wmic wine) +set_module_type(wmic win32cui UNICODE) +add_importlibs(wmic oleaut32 ole32 user32 msvcrt kernel32 ntdll) +add_cd_file(TARGET wmic DESTINATION reactos/system32 FOR all) diff --git a/reactos/base/applications/cmdutils/wmic/wmic.c b/reactos/base/applications/cmdutils/wmic/wmic.c new file mode 100644 index 00000000000..8f6b61bbfd6 --- /dev/null +++ b/reactos/base/applications/cmdutils/wmic/wmic.c @@ -0,0 +1,265 @@ +/* + * Copyright 2010 Louis Lenders + * Copyright 2012 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#define COBJMACROS + +#include +#include +#include +#include +#include +#include +#include "objidl.h" +#include "wbemcli.h" +#include +#include + +#include "wmic.h" + +WINE_DEFAULT_DEBUG_CHANNEL(wmic); + +static const WCHAR biosW[] = + {'b','i','o','s',0}; +static const WCHAR computersystemW[] = + {'c','o','m','p','u','t','e','r','s','y','s','t','e','m',0}; +static const WCHAR cpuW[] = + {'c','p','u',0}; +static const WCHAR logicaldiskW[] = + {'L','o','g','i','c','a','l','D','i','s','k',0}; +static const WCHAR nicW[] = + {'n','i','c',0}; +static const WCHAR osW[] = + {'o','s',0}; +static const WCHAR processW[] = + {'p','r','o','c','e','s','s',0}; + +static const WCHAR win32_biosW[] = + {'W','i','n','3','2','_','B','I','O','S',0}; +static const WCHAR win32_computersystemW[] = + {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0}; +static const WCHAR win32_logicaldiskW[] = + {'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k',0}; +static const WCHAR win32_networkadapterW[] = + {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0}; +static const WCHAR win32_operatingsystemW[] = + {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0}; +static const WCHAR win32_processW[] = + {'W','i','n','3','2','_','P','r','o','c','e','s','s',0}; +static const WCHAR win32_processorW[] = + {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0}; + +static const struct +{ + const WCHAR *alias; + const WCHAR *class; +} +alias_map[] = +{ + { biosW, win32_biosW }, + { computersystemW, win32_computersystemW }, + { cpuW, win32_processorW }, + { logicaldiskW, win32_logicaldiskW }, + { nicW, win32_networkadapterW }, + { osW, win32_operatingsystemW }, + { processW, win32_processW } +}; + +static const WCHAR *find_class( const WCHAR *alias ) +{ + unsigned int i; + + for (i = 0; i < sizeof(alias_map)/sizeof(alias_map[0]); i++) + { + if (!strcmpiW( alias, alias_map[i].alias )) return alias_map[i].class; + } + return NULL; +} + +static inline WCHAR *strdupW( const WCHAR *src ) +{ + WCHAR *dst; + if (!src) return NULL; + if (!(dst = HeapAlloc( GetProcessHeap(), 0, (strlenW( src ) + 1) * sizeof(WCHAR) ))) return NULL; + strcpyW( dst, src ); + return dst; +} + +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 (!strcmpiW( str, prop )) + { + ret = strdupW( str ); + break; + } + } + SafeArrayDestroy( sa ); + return ret; +} + +static int output_string( const WCHAR *msg, ... ) +{ + va_list va_args; + int wlen; + DWORD count, ret; + WCHAR buffer[8192]; + + va_start( va_args, msg ); + vsprintfW( buffer, msg, va_args ); + va_end( va_args ); + + wlen = strlenW( buffer ); + ret = WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), buffer, wlen, &count, NULL ); + if (!ret) + { + DWORD len; + char *msgA; + + /* On Windows WriteConsoleW() fails if the output is redirected. So fall + * back to WriteFile(), assuming the console encoding is still the right + * one in that case. + */ + len = WideCharToMultiByte( GetConsoleOutputCP(), 0, buffer, wlen, NULL, 0, NULL, NULL ); + if (!(msgA = HeapAlloc( GetProcessHeap(), 0, len * sizeof(char) ))) return 0; + + WideCharToMultiByte( GetConsoleOutputCP(), 0, buffer, wlen, msgA, len, NULL, NULL ); + WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), msgA, len, &count, FALSE ); + HeapFree( GetProcessHeap(), 0, msgA ); + } + return count; +} + +static int output_message( int msg ) +{ + static const WCHAR fmtW[] = {'%','s',0}; + WCHAR buffer[8192]; + + LoadStringW( GetModuleHandleW(NULL), msg, buffer, sizeof(buffer)/sizeof(WCHAR) ); + return output_string( fmtW, buffer ); +} + +static int query_prop( const WCHAR *alias, const WCHAR *propname ) +{ + static const WCHAR select_allW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0}; + static const WCHAR cimv2W[] = {'R','O','O','T','\\','C','I','M','V','2',0}; + static const WCHAR wqlW[] = {'W','Q','L',0}; + static const WCHAR newlineW[] = {'\n',0}; + static const WCHAR fmtW[] = {'%','s','\n',0}; + 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; + const WCHAR *class; + WCHAR *prop = NULL; + BOOL first = TRUE; + int len, ret = -1; + + WINE_TRACE("%s, %s\n", debugstr_w(alias), debugstr_w(propname)); + + if (!(class = find_class( alias ))) + { + output_message( STRING_ALIAS_NOT_FOUND ); + return -1; + } + CoInitialize( NULL ); + CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); + + hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, + (void **)&locator ); + if (hr != S_OK) goto done; + + if (!(path = SysAllocString( cimv2W ))) goto done; + hr = IWbemLocator_ConnectServer( locator, path, NULL, NULL, NULL, 0, NULL, NULL, &services ); + if (hr != S_OK) goto done; + + len = strlenW( class ) + sizeof(select_allW) / sizeof(select_allW[0]); + if (!(query = SysAllocStringLen( NULL, len ))) goto done; + strcpyW( query, select_allW ); + strcatW( query, class ); + + if (!(wql = SysAllocString( wqlW ))) goto done; + hr = IWbemServices_ExecQuery( services, wql, query, flags, NULL, &result ); + if (hr != S_OK) goto done; + + for (;;) + { + IWbemClassObject *obj; + ULONG count; + VARIANT v; + + IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); + if (!count) break; + + if (first) + { + if (!(prop = find_prop( obj, propname ))) + { + output_message( STRING_INVALID_QUERY ); + goto done; + } + output_string( fmtW, prop ); + first = FALSE; + } + if (IWbemClassObject_Get( obj, prop, 0, &v, NULL, NULL ) == WBEM_S_NO_ERROR) + { + VariantChangeType( &v, &v, 0, VT_BSTR ); + output_string( fmtW, V_BSTR( &v ) ); + VariantClear( &v ); + } + IWbemClassObject_Release( obj ); + } + output_string( newlineW ); + ret = 0; + +done: + if (result) IEnumWbemClassObject_Release( result ); + if (services) IWbemServices_Release( services ); + if (locator) IWbemLocator_Release( locator ); + SysFreeString( path ); + SysFreeString( query ); + SysFreeString( wql ); + HeapFree( GetProcessHeap(), 0, prop ); + CoUninitialize(); + return ret; +} + +int wmain(int argc, WCHAR *argv[]) +{ + static const WCHAR getW[] = {'g','e','t',0}; + + if (argc != 4 || strcmpiW( argv[2], getW )) + { + output_message( STRING_CMDLINE_NOT_SUPPORTED ); + return -1; + } + return query_prop( argv[1], argv[3] ); +} diff --git a/reactos/base/applications/cmdutils/wmic/wmic.h b/reactos/base/applications/cmdutils/wmic/wmic.h new file mode 100644 index 00000000000..ee56d8e9642 --- /dev/null +++ b/reactos/base/applications/cmdutils/wmic/wmic.h @@ -0,0 +1,23 @@ +/* + * Copyright 2012 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#define STRING_CMDLINE_NOT_SUPPORTED 101 +#define STRING_ALIAS_NOT_FOUND 102 +#define STRING_INVALID_QUERY 103 diff --git a/reactos/base/applications/cmdutils/wmic/wmic.rc b/reactos/base/applications/cmdutils/wmic/wmic.rc new file mode 100644 index 00000000000..d9087900ed7 --- /dev/null +++ b/reactos/base/applications/cmdutils/wmic/wmic.rc @@ -0,0 +1,28 @@ +/* + * Copyright 2012 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "wmic.h" + +LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT + +STRINGTABLE +{ + STRING_CMDLINE_NOT_SUPPORTED, "Error: Command line not supported\n" + STRING_ALIAS_NOT_FOUND, "Error: Alias not found\n" + STRING_INVALID_QUERY, "Error: Invalid query\n" +} diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 938a0b560f0..c6cec0041d8 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -225,19 +225,21 @@ reactos/dll/cpl/inetcpl # Synced to Wine-1.3.21 ReactOS shares the following programs with Winehq. -reactos/base/applications/cmdutils/xcopy # Synced to Wine-1.3.37 -reactos/base/applications/games/winmine # Forked at Wine-1_3_5 -reactos/base/applications/extrac32 # Autosync -reactos/base/applications/iexplore # Synced to Wine-1.5.26 -reactos/base/applications/notepad # Forked at Wine-20041201 -reactos/base/applications/reg # Autosync -reactos/base/applications/regedit # Out of sync -reactos/base/applications/winhlp32 # Synced to Wine-1.5.26 -reactos/base/applications/wordpad # Synced to Wine-1.5.26 -reactos/base/services/rpcss # Synced to Wine-1.7.1 -reactos/base/system/expand # Synced to Wine-1.5.26 -reactos/base/system/msiexec # Synced to Wine-1.5.26 -reactos/modules/rosapps/winfile # Autosync +reactos/base/applications/cmdutils/reg # Synced to Wine-1.1.40 +reactos/base/applications/cmdutils/taskkill # Synced to Wine-1.5.25 +reactos/base/applications/cmdutils/wmic # Synced to Wine-1.7.5 +reactos/base/applications/cmdutils/xcopy # Synced to Wine-1.3.37 +reactos/base/applications/games/winmine # Forked at Wine-1_3_5 +reactos/base/applications/extrac32 # Autosync +reactos/base/applications/iexplore # Synced to Wine-1.5.26 +reactos/base/applications/notepad # Forked at Wine-20041201 +reactos/base/applications/regedit # Out of sync +reactos/base/applications/winhlp32 # Synced to Wine-1.5.26 +reactos/base/applications/wordpad # Synced to Wine-1.5.26 +reactos/base/services/rpcss # Synced to Wine-1.7.1 +reactos/base/system/expand # Synced to Wine-1.5.26 +reactos/base/system/msiexec # Synced to Wine-1.5.26 +reactos/modules/rosapps/winfile # Autosync In addition the following libs, dlls and source files are mostly based on code ported from Winehq CVS. If you are looking to update something in these files