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
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(wmic
);
34 static const WCHAR biosW
[] =
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
[] =
40 static const WCHAR logicaldiskW
[] =
41 {'L','o','g','i','c','a','l','D','i','s','k',0};
42 static const WCHAR nicW
[] =
44 static const WCHAR osW
[] =
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};
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
)
84 for (i
= 0; i
< ARRAY_SIZE(alias_map
); i
++)
86 if (!wcsicmp( alias
, alias_map
[i
].alias
)) return alias_map
[i
].class;
91 static inline WCHAR
*strdupW( const WCHAR
*src
)
94 if (!src
) return NULL
;
95 if (!(dst
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW( src
) + 1) * sizeof(WCHAR
) ))) return NULL
;
100 static WCHAR
*find_prop( IWbemClassObject
*class, const WCHAR
*prop
)
104 LONG i
, last_index
= 0;
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
);
119 SafeArrayDestroy( sa
);
123 static int WINAPIV
output_string( HANDLE handle
, const WCHAR
*msg
, ... )
125 __ms_va_list va_args
;
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
);
140 static int output_error( int msg
)
142 static const WCHAR fmtW
[] = {'%','s',0};
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};
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
);
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};
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
;
188 IWbemClassObject
*obj
;
189 ULONG count
, width
= 0;
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
,
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
);
220 if (!prop
&& !(prop
= find_prop( obj
, propname
)))
222 output_error( STRING_INVALID_QUERY
);
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
);
231 IWbemClassObject_Release( obj
);
235 IEnumWbemClassObject_Reset( result
);
238 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
243 output_header( prop
, width
);
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
);
252 IWbemClassObject_Release( obj
);
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
);
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
;
279 for (i
= 1; i
< argc
&& argv
[i
][0] == '/'; i
++)
280 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv
[i
]) );
285 if (!wcsicmp( argv
[i
], quitW
) ||
286 !wcsicmp( argv
[i
], exitW
))
291 if (!wcsicmp( argv
[i
], classW
) ||
292 !wcsicmp( argv
[i
], contextW
))
294 WINE_FIXME( "command %s not supported\n", debugstr_w(argv
[i
]) );
298 if (!wcsicmp( argv
[i
], pathW
))
302 output_error( STRING_INVALID_PATH
);
309 class = find_class( argv
[i
] );
312 output_error( STRING_ALIAS_NOT_FOUND
);
320 if (!wcsicmp( argv
[i
], getW
))
325 return query_prop( class, value
);
329 output_error( STRING_CMDLINE_NOT_SUPPORTED
);