Release 4.20.
[wine.git] / programs / wmic / main.c
blobf31a69a4241989b6c4b707a6a77703764dafe6b5
1 /*
2 * Copyright 2010 Louis Lenders
3 * Copyright 2012 Hans Leidekker for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define COBJMACROS
22 #include <stdio.h>
23 #include "windows.h"
24 #include "ocidl.h"
25 #include "initguid.h"
26 #include "objidl.h"
27 #include "wbemcli.h"
28 #include "wmic.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wmic);
34 static const WCHAR biosW[] =
35 {'b','i','o','s',0};
36 static const WCHAR computersystemW[] =
37 {'c','o','m','p','u','t','e','r','s','y','s','t','e','m',0};
38 static const WCHAR cpuW[] =
39 {'c','p','u',0};
40 static const WCHAR logicaldiskW[] =
41 {'L','o','g','i','c','a','l','D','i','s','k',0};
42 static const WCHAR nicW[] =
43 {'n','i','c',0};
44 static const WCHAR osW[] =
45 {'o','s',0};
46 static const WCHAR processW[] =
47 {'p','r','o','c','e','s','s',0};
49 static const WCHAR win32_biosW[] =
50 {'W','i','n','3','2','_','B','I','O','S',0};
51 static const WCHAR win32_computersystemW[] =
52 {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0};
53 static const WCHAR win32_logicaldiskW[] =
54 {'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k',0};
55 static const WCHAR win32_networkadapterW[] =
56 {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0};
57 static const WCHAR win32_operatingsystemW[] =
58 {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
59 static const WCHAR win32_processW[] =
60 {'W','i','n','3','2','_','P','r','o','c','e','s','s',0};
61 static const WCHAR win32_processorW[] =
62 {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
64 static const struct
66 const WCHAR *alias;
67 const WCHAR *class;
69 alias_map[] =
71 { biosW, win32_biosW },
72 { computersystemW, win32_computersystemW },
73 { cpuW, win32_processorW },
74 { logicaldiskW, win32_logicaldiskW },
75 { nicW, win32_networkadapterW },
76 { osW, win32_operatingsystemW },
77 { processW, win32_processW }
80 static const WCHAR *find_class( const WCHAR *alias )
82 unsigned int i;
84 for (i = 0; i < ARRAY_SIZE(alias_map); i++)
86 if (!wcsicmp( alias, alias_map[i].alias )) return alias_map[i].class;
88 return NULL;
91 static inline WCHAR *strdupW( const WCHAR *src )
93 WCHAR *dst;
94 if (!src) return NULL;
95 if (!(dst = HeapAlloc( GetProcessHeap(), 0, (lstrlenW( src ) + 1) * sizeof(WCHAR) ))) return NULL;
96 lstrcpyW( dst, src );
97 return dst;
100 static WCHAR *find_prop( IWbemClassObject *class, const WCHAR *prop )
102 SAFEARRAY *sa;
103 WCHAR *ret = NULL;
104 LONG i, last_index = 0;
105 BSTR str;
107 if (IWbemClassObject_GetNames( class, NULL, WBEM_FLAG_ALWAYS, NULL, &sa ) != S_OK) return NULL;
109 SafeArrayGetUBound( sa, 1, &last_index );
110 for (i = 0; i <= last_index; i++)
112 SafeArrayGetElement( sa, &i, &str );
113 if (!wcsicmp( str, prop ))
115 ret = strdupW( str );
116 break;
119 SafeArrayDestroy( sa );
120 return ret;
123 static int WINAPIV output_string( HANDLE handle, const WCHAR *msg, ... )
125 __ms_va_list va_args;
126 int len;
127 DWORD count;
128 WCHAR buffer[8192];
130 __ms_va_start( va_args, msg );
131 len = vswprintf( buffer, ARRAY_SIZE(buffer), msg, va_args );
132 __ms_va_end( va_args );
134 if (!WriteConsoleW( handle, buffer, len, &count, NULL ))
135 WriteFile( handle, buffer, len * sizeof(WCHAR), &count, FALSE );
137 return count;
140 static int output_error( int msg )
142 static const WCHAR fmtW[] = {'%','s',0};
143 WCHAR buffer[8192];
145 LoadStringW( GetModuleHandleW(NULL), msg, buffer, ARRAY_SIZE(buffer));
146 return output_string( GetStdHandle(STD_ERROR_HANDLE), fmtW, buffer );
149 static int output_header( const WCHAR *prop, ULONG column_width )
151 static const WCHAR bomW[] = {0xfeff}, fmtW[] = {'%','-','*','s','\r','\n',0};
152 int len;
153 DWORD count;
154 WCHAR buffer[8192];
156 len = swprintf( buffer, ARRAY_SIZE(buffer), fmtW, column_width, prop );
158 if (!WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE), buffer, len, &count, NULL )) /* redirected */
160 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), bomW, sizeof(bomW), &count, FALSE );
161 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE), buffer, len * sizeof(WCHAR), &count, FALSE );
162 count += sizeof(bomW);
165 return count;
168 static int output_line( const WCHAR *str, ULONG column_width )
170 static const WCHAR fmtW[] = {'%','-','*','s','\r','\n',0};
171 return output_string( GetStdHandle(STD_OUTPUT_HANDLE), fmtW, column_width, str );
174 static int query_prop( const WCHAR *class, const WCHAR *propname )
176 static const WCHAR select_allW[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
177 static const WCHAR cimv2W[] = {'R','O','O','T','\\','C','I','M','V','2',0};
178 static const WCHAR wqlW[] = {'W','Q','L',0};
179 HRESULT hr;
180 IWbemLocator *locator = NULL;
181 IWbemServices *services = NULL;
182 IEnumWbemClassObject *result = NULL;
183 LONG flags = WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY;
184 BSTR path = NULL, wql = NULL, query = NULL;
185 WCHAR *prop = NULL;
186 BOOL first = TRUE;
187 int len, ret = -1;
188 IWbemClassObject *obj;
189 ULONG count, width = 0;
190 VARIANT v;
192 WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propname));
194 CoInitialize( NULL );
195 CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
196 RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL );
198 hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator,
199 (void **)&locator );
200 if (hr != S_OK) goto done;
202 if (!(path = SysAllocString( cimv2W ))) goto done;
203 hr = IWbemLocator_ConnectServer( locator, path, NULL, NULL, NULL, 0, NULL, NULL, &services );
204 if (hr != S_OK) goto done;
206 len = lstrlenW( class ) + ARRAY_SIZE(select_allW);
207 if (!(query = SysAllocStringLen( NULL, len ))) goto done;
208 lstrcpyW( query, select_allW );
209 lstrcatW( query, class );
211 if (!(wql = SysAllocString( wqlW ))) goto done;
212 hr = IWbemServices_ExecQuery( services, wql, query, flags, NULL, &result );
213 if (hr != S_OK) goto done;
215 for (;;) /* get column width */
217 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
218 if (!count) break;
220 if (!prop && !(prop = find_prop( obj, propname )))
222 output_error( STRING_INVALID_QUERY );
223 goto done;
225 if (IWbemClassObject_Get( obj, prop, 0, &v, NULL, NULL ) == WBEM_S_NO_ERROR)
227 VariantChangeType( &v, &v, 0, VT_BSTR );
228 width = max( lstrlenW( V_BSTR( &v ) ), width );
229 VariantClear( &v );
231 IWbemClassObject_Release( obj );
233 width += 2;
235 IEnumWbemClassObject_Reset( result );
236 for (;;)
238 IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count );
239 if (!count) break;
241 if (first)
243 output_header( prop, width );
244 first = FALSE;
246 if (IWbemClassObject_Get( obj, prop, 0, &v, NULL, NULL ) == WBEM_S_NO_ERROR)
248 VariantChangeType( &v, &v, 0, VT_BSTR );
249 output_line( V_BSTR( &v ), width );
250 VariantClear( &v );
252 IWbemClassObject_Release( obj );
254 ret = 0;
256 done:
257 if (result) IEnumWbemClassObject_Release( result );
258 if (services) IWbemServices_Release( services );
259 if (locator) IWbemLocator_Release( locator );
260 SysFreeString( path );
261 SysFreeString( query );
262 SysFreeString( wql );
263 HeapFree( GetProcessHeap(), 0, prop );
264 CoUninitialize();
265 return ret;
268 int __cdecl wmain(int argc, WCHAR *argv[])
270 static const WCHAR getW[] = {'g','e','t',0};
271 static const WCHAR quitW[] = {'q','u','i','t',0};
272 static const WCHAR exitW[] = {'e','x','i','t',0};
273 static const WCHAR pathW[] = {'p','a','t','h',0};
274 static const WCHAR classW[] = {'c','l','a','s','s',0};
275 static const WCHAR contextW[] = {'c','o','n','t','e','x','t',0};
276 const WCHAR *class, *value;
277 int i;
279 for (i = 1; i < argc && argv[i][0] == '/'; i++)
280 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv[i]) );
282 if (i >= argc)
283 goto not_supported;
285 if (!wcsicmp( argv[i], quitW ) ||
286 !wcsicmp( argv[i], exitW ))
288 return 0;
291 if (!wcsicmp( argv[i], classW) ||
292 !wcsicmp( argv[i], contextW ))
294 WINE_FIXME( "command %s not supported\n", debugstr_w(argv[i]) );
295 goto not_supported;
298 if (!wcsicmp( argv[i], pathW ))
300 if (++i >= argc)
302 output_error( STRING_INVALID_PATH );
303 return 1;
305 class = argv[i];
307 else
309 class = find_class( argv[i] );
310 if (!class)
312 output_error( STRING_ALIAS_NOT_FOUND );
313 return 1;
317 if (++i >= argc)
318 goto not_supported;
320 if (!wcsicmp( argv[i], getW ))
322 if (++i >= argc)
323 goto not_supported;
324 value = argv[i];
325 return query_prop( class, value );
328 not_supported:
329 output_error( STRING_CMDLINE_NOT_SUPPORTED );
330 return 1;