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
);
41 { L
"bios", L
"Win32_BIOS" },
42 { L
"computersystem", L
"Win32_ComputerSystem" },
43 { L
"cpu", L
"Win32_Processor" },
44 { L
"LogicalDisk", L
"Win32_LogicalDisk" },
45 { L
"nic", L
"Win32_NetworkAdapter" },
46 { L
"os", L
"Win32_OperatingSystem" },
47 { L
"process", L
"Win32_Process" },
48 { L
"baseboard", L
"Win32_BaseBoard" },
49 { L
"diskdrive", L
"Win32_DiskDrive" },
50 { L
"memorychip", L
"Win32_PhysicalMemory" }
53 static const WCHAR
*find_class( const WCHAR
*alias
)
57 for (i
= 0; i
< ARRAY_SIZE(alias_map
); i
++)
59 if (!wcsicmp( alias
, alias_map
[i
].alias
)) return alias_map
[i
].class;
64 static int WINAPIV
output_string( HANDLE handle
, const WCHAR
*msg
, ... )
66 BOOL output
= GetStdHandle(STD_OUTPUT_HANDLE
) == handle
;
67 static const WCHAR bomW
[] = {0xfeff};
71 DWORD count
, bom_count
= 0;
74 va_start( va_args
, msg
);
75 len
= vswprintf( buffer
, ARRAY_SIZE(buffer
), msg
, va_args
);
78 if (!WriteConsoleW( handle
, buffer
, len
, &count
, NULL
))
82 WriteFile( handle
, bomW
, sizeof(bomW
), &bom_count
, FALSE
);
85 WriteFile( handle
, buffer
, len
* sizeof(WCHAR
), &count
, FALSE
);
88 return count
+ bom_count
;
91 static int output_error( int msg
)
95 LoadStringW( GetModuleHandleW(NULL
), msg
, buffer
, ARRAY_SIZE(buffer
));
96 return output_string( GetStdHandle(STD_ERROR_HANDLE
), L
"%s", buffer
);
99 static int output_text( const WCHAR
*str
, ULONG column_width
)
101 return output_string( GetStdHandle(STD_OUTPUT_HANDLE
), L
"%-*s", column_width
, str
);
104 static int output_newline( void )
106 return output_string( GetStdHandle(STD_OUTPUT_HANDLE
), L
"\r\n" );
109 static WCHAR
* strip_spaces(WCHAR
*start
)
111 WCHAR
*str
= start
, *end
;
116 end
= start
+ lstrlenW(start
) - 1;
117 while (end
>= start
&& *end
== ' ')
126 static HRESULT
process_property_list( IWbemClassObject
*obj
, const WCHAR
*proplist
, WCHAR
**ret
)
128 WCHAR
*p
, *ctx
, *ptr
, *stripped
;
131 if (!(p
= wcsdup( proplist
))) return E_OUTOFMEMORY
;
133 if (!(stripped
= malloc( (wcslen( proplist
) + 1) * sizeof(**ret
) )))
136 return E_OUTOFMEMORY
;
140 /* Validate that every requested property is supported. */
141 ptr
= wcstok_s( p
, L
",", &ctx
);
144 ptr
= strip_spaces( ptr
);
146 if (FAILED(IWbemClassObject_Get( obj
, ptr
, 0, NULL
, NULL
, NULL
)))
151 if (*stripped
) wcscat( stripped
, L
"," );
152 wcscat( stripped
, ptr
);
153 ptr
= wcstok_s( NULL
, L
",", &ctx
);
168 static int query_prop( const WCHAR
*class, const WCHAR
*propnames
)
171 IWbemLocator
*locator
= NULL
;
172 IWbemServices
*services
= NULL
;
173 IEnumWbemClassObject
*result
= NULL
;
174 LONG flags
= WBEM_FLAG_RETURN_IMMEDIATELY
| WBEM_FLAG_FORWARD_ONLY
;
175 BSTR path
= NULL
, wql
= NULL
, query
= NULL
, name
, str
= NULL
;
176 WCHAR
*proplist
= NULL
;
178 IWbemClassObject
*obj
;
179 ULONG count
, width
= 0;
182 WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propnames
));
184 CoInitialize( NULL
);
185 CoInitializeSecurity( NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_DEFAULT
,
186 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, EOAC_NONE
, NULL
);
188 hr
= CoCreateInstance( &CLSID_WbemLocator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWbemLocator
,
190 if (hr
!= S_OK
) goto done
;
192 if (!(path
= SysAllocString(L
"ROOT\\CIMV2" ))) goto done
;
193 hr
= IWbemLocator_ConnectServer( locator
, path
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &services
);
194 if (hr
!= S_OK
) goto done
;
196 if (!(str
= SysAllocString( class ))) goto done
;
197 hr
= IWbemServices_GetObject( services
, str
, 0, NULL
, &obj
, NULL
);
198 SysFreeString( str
);
201 WARN("Unrecognized class %s.\n", debugstr_w(class));
205 /* Check that this class supports all requested properties. */
206 hr
= process_property_list( obj
, propnames
, &proplist
);
207 IWbemClassObject_Release( obj
);
210 output_error( STRING_INVALID_QUERY
);
214 len
= lstrlenW( class ) + lstrlenW( proplist
) + ARRAY_SIZE(L
"SELECT * FROM ");
215 if (!(query
= SysAllocStringLen( NULL
, len
))) goto done
;
216 swprintf( query
, len
, L
"SELECT %s FROM %s", proplist
, class );
218 if (!(wql
= SysAllocString(L
"WQL" ))) goto done
;
219 hr
= IWbemServices_ExecQuery( services
, wql
, query
, flags
, NULL
, &result
);
220 if (hr
!= S_OK
) goto done
;
222 for (;;) /* get column width */
224 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
227 while (IWbemClassObject_Next( obj
, 0, &name
, &v
, NULL
, NULL
) == S_OK
)
229 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
230 width
= max( lstrlenW( V_BSTR( &v
) ), width
);
232 SysFreeString( name
);
235 IWbemClassObject_Release( obj
);
240 IEnumWbemClassObject_Reset( result
);
241 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
244 while (IWbemClassObject_Next( obj
, 0, &name
, NULL
, NULL
, NULL
) == S_OK
)
246 output_text( name
, width
);
247 SysFreeString( name
);
250 IWbemClassObject_Release( obj
);
254 IEnumWbemClassObject_Reset( result
);
257 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
260 while (IWbemClassObject_Next( obj
, 0, NULL
, &v
, NULL
, NULL
) == S_OK
)
262 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
263 output_text( V_BSTR( &v
), width
);
267 IWbemClassObject_Release( obj
);
272 if (result
) IEnumWbemClassObject_Release( result
);
273 if (services
) IWbemServices_Release( services
);
274 if (locator
) IWbemLocator_Release( locator
);
275 SysFreeString( path
);
276 SysFreeString( query
);
277 SysFreeString( wql
);
283 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
285 const WCHAR
*class, *value
;
288 for (i
= 1; i
< argc
&& argv
[i
][0] == '/'; i
++)
289 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv
[i
]) );
294 if (!wcsicmp( argv
[i
], L
"quit" ) || !wcsicmp( argv
[i
], L
"exit" ))
299 if (!wcsicmp( argv
[i
], L
"class") || !wcsicmp( argv
[i
], L
"context" ))
301 WINE_FIXME( "command %s not supported\n", debugstr_w(argv
[i
]) );
305 if (!wcsicmp( argv
[i
], L
"path" ))
309 output_error( STRING_INVALID_PATH
);
316 class = find_class( argv
[i
] );
319 output_error( STRING_ALIAS_NOT_FOUND
);
327 if (!wcsicmp( argv
[i
], L
"get" ))
332 return query_prop( class, value
);
336 output_error( STRING_CMDLINE_NOT_SUPPORTED
);