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"
31 #include "wine/unicode.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(wmic
);
35 static const WCHAR biosW
[] =
37 static const WCHAR computersystemW
[] =
38 {'c','o','m','p','u','t','e','r','s','y','s','t','e','m',0};
39 static const WCHAR cpuW
[] =
41 static const WCHAR logicaldiskW
[] =
42 {'L','o','g','i','c','a','l','D','i','s','k',0};
43 static const WCHAR nicW
[] =
45 static const WCHAR osW
[] =
47 static const WCHAR processW
[] =
48 {'p','r','o','c','e','s','s',0};
50 static const WCHAR win32_biosW
[] =
51 {'W','i','n','3','2','_','B','I','O','S',0};
52 static const WCHAR win32_computersystemW
[] =
53 {'W','i','n','3','2','_','C','o','m','p','u','t','e','r','S','y','s','t','e','m',0};
54 static const WCHAR win32_logicaldiskW
[] =
55 {'W','i','n','3','2','_','L','o','g','i','c','a','l','D','i','s','k',0};
56 static const WCHAR win32_networkadapterW
[] =
57 {'W','i','n','3','2','_','N','e','t','w','o','r','k','A','d','a','p','t','e','r',0};
58 static const WCHAR win32_operatingsystemW
[] =
59 {'W','i','n','3','2','_','O','p','e','r','a','t','i','n','g','S','y','s','t','e','m',0};
60 static const WCHAR win32_processW
[] =
61 {'W','i','n','3','2','_','P','r','o','c','e','s','s',0};
62 static const WCHAR win32_processorW
[] =
63 {'W','i','n','3','2','_','P','r','o','c','e','s','s','o','r',0};
72 { biosW
, win32_biosW
},
73 { computersystemW
, win32_computersystemW
},
74 { cpuW
, win32_processorW
},
75 { logicaldiskW
, win32_logicaldiskW
},
76 { nicW
, win32_networkadapterW
},
77 { osW
, win32_operatingsystemW
},
78 { processW
, win32_processW
}
81 static const WCHAR
*find_class( const WCHAR
*alias
)
85 for (i
= 0; i
< ARRAY_SIZE(alias_map
); i
++)
87 if (!strcmpiW( alias
, alias_map
[i
].alias
)) return alias_map
[i
].class;
92 static inline WCHAR
*strdupW( const WCHAR
*src
)
95 if (!src
) return NULL
;
96 if (!(dst
= HeapAlloc( GetProcessHeap(), 0, (strlenW( src
) + 1) * sizeof(WCHAR
) ))) return NULL
;
101 static WCHAR
*find_prop( IWbemClassObject
*class, const WCHAR
*prop
)
105 LONG i
, last_index
= 0;
108 if (IWbemClassObject_GetNames( class, NULL
, WBEM_FLAG_ALWAYS
, NULL
, &sa
) != S_OK
) return NULL
;
110 SafeArrayGetUBound( sa
, 1, &last_index
);
111 for (i
= 0; i
<= last_index
; i
++)
113 SafeArrayGetElement( sa
, &i
, &str
);
114 if (!strcmpiW( str
, prop
))
116 ret
= strdupW( str
);
120 SafeArrayDestroy( sa
);
124 static int output_string( HANDLE handle
, const WCHAR
*msg
, ... )
131 va_start( va_args
, msg
);
132 len
= vsnprintfW( buffer
, ARRAY_SIZE(buffer
), msg
, va_args
);
135 if (!WriteConsoleW( handle
, buffer
, len
, &count
, NULL
))
136 WriteFile( handle
, buffer
, len
* sizeof(WCHAR
), &count
, FALSE
);
141 static int output_error( int msg
)
143 static const WCHAR fmtW
[] = {'%','s',0};
146 LoadStringW( GetModuleHandleW(NULL
), msg
, buffer
, ARRAY_SIZE(buffer
));
147 return output_string( GetStdHandle(STD_ERROR_HANDLE
), fmtW
, buffer
);
150 static int output_header( const WCHAR
*prop
, ULONG column_width
)
152 static const WCHAR bomW
[] = {0xfeff}, fmtW
[] = {'%','-','*','s','\r','\n',0};
157 len
= snprintfW( buffer
, ARRAY_SIZE(buffer
), fmtW
, column_width
, prop
);
159 if (!WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE
), buffer
, len
, &count
, NULL
)) /* redirected */
161 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE
), bomW
, sizeof(bomW
), &count
, FALSE
);
162 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE
), buffer
, len
* sizeof(WCHAR
), &count
, FALSE
);
163 count
+= sizeof(bomW
);
169 static int output_line( const WCHAR
*str
, ULONG column_width
)
171 static const WCHAR fmtW
[] = {'%','-','*','s','\r','\n',0};
172 return output_string( GetStdHandle(STD_OUTPUT_HANDLE
), fmtW
, column_width
, str
);
175 static int query_prop( const WCHAR
*class, const WCHAR
*propname
)
177 static const WCHAR select_allW
[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
178 static const WCHAR cimv2W
[] = {'R','O','O','T','\\','C','I','M','V','2',0};
179 static const WCHAR wqlW
[] = {'W','Q','L',0};
181 IWbemLocator
*locator
= NULL
;
182 IWbemServices
*services
= NULL
;
183 IEnumWbemClassObject
*result
= NULL
;
184 LONG flags
= WBEM_FLAG_RETURN_IMMEDIATELY
| WBEM_FLAG_FORWARD_ONLY
;
185 BSTR path
= NULL
, wql
= NULL
, query
= NULL
;
189 IWbemClassObject
*obj
;
190 ULONG count
, width
= 0;
193 WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propname
));
195 CoInitialize( NULL
);
196 CoInitializeSecurity( NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_DEFAULT
,
197 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, EOAC_NONE
, NULL
);
199 hr
= CoCreateInstance( &CLSID_WbemLocator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWbemLocator
,
201 if (hr
!= S_OK
) goto done
;
203 if (!(path
= SysAllocString( cimv2W
))) goto done
;
204 hr
= IWbemLocator_ConnectServer( locator
, path
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &services
);
205 if (hr
!= S_OK
) goto done
;
207 len
= strlenW( class ) + ARRAY_SIZE(select_allW
);
208 if (!(query
= SysAllocStringLen( NULL
, len
))) goto done
;
209 strcpyW( query
, select_allW
);
210 strcatW( query
, class );
212 if (!(wql
= SysAllocString( wqlW
))) goto done
;
213 hr
= IWbemServices_ExecQuery( services
, wql
, query
, flags
, NULL
, &result
);
214 if (hr
!= S_OK
) goto done
;
216 for (;;) /* get column width */
218 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
221 if (!prop
&& !(prop
= find_prop( obj
, propname
)))
223 output_error( STRING_INVALID_QUERY
);
226 if (IWbemClassObject_Get( obj
, prop
, 0, &v
, NULL
, NULL
) == WBEM_S_NO_ERROR
)
228 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
229 width
= max( strlenW( V_BSTR( &v
) ), width
);
232 IWbemClassObject_Release( obj
);
236 IEnumWbemClassObject_Reset( result
);
239 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
244 output_header( prop
, width
);
247 if (IWbemClassObject_Get( obj
, prop
, 0, &v
, NULL
, NULL
) == WBEM_S_NO_ERROR
)
249 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
250 output_line( V_BSTR( &v
), width
);
253 IWbemClassObject_Release( obj
);
258 if (result
) IEnumWbemClassObject_Release( result
);
259 if (services
) IWbemServices_Release( services
);
260 if (locator
) IWbemLocator_Release( locator
);
261 SysFreeString( path
);
262 SysFreeString( query
);
263 SysFreeString( wql
);
264 HeapFree( GetProcessHeap(), 0, prop
);
269 int wmain(int argc
, WCHAR
*argv
[])
271 static const WCHAR getW
[] = {'g','e','t',0};
272 static const WCHAR quitW
[] = {'q','u','i','t',0};
273 static const WCHAR exitW
[] = {'e','x','i','t',0};
274 static const WCHAR pathW
[] = {'p','a','t','h',0};
275 static const WCHAR classW
[] = {'c','l','a','s','s',0};
276 static const WCHAR contextW
[] = {'c','o','n','t','e','x','t',0};
277 const WCHAR
*class, *value
;
280 for (i
= 1; i
< argc
&& argv
[i
][0] == '/'; i
++)
281 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv
[i
]) );
286 if (!strcmpiW( argv
[i
], quitW
) ||
287 !strcmpiW( argv
[i
], exitW
))
292 if (!strcmpiW( argv
[i
], classW
) ||
293 !strcmpiW( argv
[i
], contextW
))
295 WINE_FIXME( "command %s not supported\n", debugstr_w(argv
[i
]) );
299 if (!strcmpiW( argv
[i
], pathW
))
303 output_error( STRING_INVALID_PATH
);
310 class = find_class( argv
[i
] );
313 output_error( STRING_ALIAS_NOT_FOUND
);
321 if (!strcmpiW( argv
[i
], getW
))
326 return query_prop( class, value
);
330 output_error( STRING_CMDLINE_NOT_SUPPORTED
);