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 inline WCHAR
*strdupW( const WCHAR
*src
)
67 if (!src
) return NULL
;
68 if (!(dst
= HeapAlloc( GetProcessHeap(), 0, (lstrlenW( src
) + 1) * sizeof(WCHAR
) ))) return NULL
;
73 static WCHAR
*find_prop( IWbemClassObject
*class, const WCHAR
*prop
)
77 LONG i
, last_index
= 0;
80 if (IWbemClassObject_GetNames( class, NULL
, WBEM_FLAG_ALWAYS
, NULL
, &sa
) != S_OK
) return NULL
;
82 SafeArrayGetUBound( sa
, 1, &last_index
);
83 for (i
= 0; i
<= last_index
; i
++)
85 SafeArrayGetElement( sa
, &i
, &str
);
86 if (!wcsicmp( str
, prop
))
92 SafeArrayDestroy( sa
);
96 static int WINAPIV
output_string( HANDLE handle
, const WCHAR
*msg
, ... )
103 __ms_va_start( va_args
, msg
);
104 len
= vswprintf( buffer
, ARRAY_SIZE(buffer
), msg
, va_args
);
105 __ms_va_end( va_args
);
107 if (!WriteConsoleW( handle
, buffer
, len
, &count
, NULL
))
108 WriteFile( handle
, buffer
, len
* sizeof(WCHAR
), &count
, FALSE
);
113 static int output_error( int msg
)
117 LoadStringW( GetModuleHandleW(NULL
), msg
, buffer
, ARRAY_SIZE(buffer
));
118 return output_string( GetStdHandle(STD_ERROR_HANDLE
), L
"%s", buffer
);
121 static int output_header( const WCHAR
*prop
, ULONG column_width
)
123 static const WCHAR bomW
[] = {0xfeff};
128 len
= swprintf( buffer
, ARRAY_SIZE(buffer
), L
"%-*s\r\n", column_width
, prop
);
130 if (!WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE
), buffer
, len
, &count
, NULL
)) /* redirected */
132 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE
), bomW
, sizeof(bomW
), &count
, FALSE
);
133 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE
), buffer
, len
* sizeof(WCHAR
), &count
, FALSE
);
134 count
+= sizeof(bomW
);
140 static int output_line( const WCHAR
*str
, ULONG column_width
)
142 return output_string( GetStdHandle(STD_OUTPUT_HANDLE
), L
"%-*s\r\n", column_width
, str
);
145 static int query_prop( const WCHAR
*class, const WCHAR
*propname
)
148 IWbemLocator
*locator
= NULL
;
149 IWbemServices
*services
= NULL
;
150 IEnumWbemClassObject
*result
= NULL
;
151 LONG flags
= WBEM_FLAG_RETURN_IMMEDIATELY
| WBEM_FLAG_FORWARD_ONLY
;
152 BSTR path
= NULL
, wql
= NULL
, query
= NULL
;
156 IWbemClassObject
*obj
;
157 ULONG count
, width
= 0;
160 WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propname
));
162 CoInitialize( NULL
);
163 CoInitializeSecurity( NULL
, -1, NULL
, NULL
, RPC_C_AUTHN_LEVEL_DEFAULT
,
164 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, EOAC_NONE
, NULL
);
166 hr
= CoCreateInstance( &CLSID_WbemLocator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IWbemLocator
,
168 if (hr
!= S_OK
) goto done
;
170 if (!(path
= SysAllocString(L
"ROOT\\CIMV2" ))) goto done
;
171 hr
= IWbemLocator_ConnectServer( locator
, path
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &services
);
172 if (hr
!= S_OK
) goto done
;
174 len
= lstrlenW( class ) + ARRAY_SIZE(L
"SELECT * FROM ");
175 if (!(query
= SysAllocStringLen( NULL
, len
))) goto done
;
176 lstrcpyW( query
, L
"SELECT * FROM " );
177 lstrcatW( query
, class );
179 if (!(wql
= SysAllocString(L
"WQL" ))) goto done
;
180 hr
= IWbemServices_ExecQuery( services
, wql
, query
, flags
, NULL
, &result
);
181 if (hr
!= S_OK
) goto done
;
183 for (;;) /* get column width */
185 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
188 if (!prop
&& !(prop
= find_prop( obj
, propname
)))
190 output_error( STRING_INVALID_QUERY
);
193 if (IWbemClassObject_Get( obj
, prop
, 0, &v
, NULL
, NULL
) == WBEM_S_NO_ERROR
)
195 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
196 width
= max( lstrlenW( V_BSTR( &v
) ), width
);
199 IWbemClassObject_Release( obj
);
203 IEnumWbemClassObject_Reset( result
);
206 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
211 output_header( prop
, width
);
214 if (IWbemClassObject_Get( obj
, prop
, 0, &v
, NULL
, NULL
) == WBEM_S_NO_ERROR
)
216 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
217 output_line( V_BSTR( &v
), width
);
220 IWbemClassObject_Release( obj
);
225 if (result
) IEnumWbemClassObject_Release( result
);
226 if (services
) IWbemServices_Release( services
);
227 if (locator
) IWbemLocator_Release( locator
);
228 SysFreeString( path
);
229 SysFreeString( query
);
230 SysFreeString( wql
);
231 HeapFree( GetProcessHeap(), 0, prop
);
236 int __cdecl
wmain(int argc
, WCHAR
*argv
[])
238 const WCHAR
*class, *value
;
241 for (i
= 1; i
< argc
&& argv
[i
][0] == '/'; i
++)
242 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv
[i
]) );
247 if (!wcsicmp( argv
[i
], L
"quit" ) || !wcsicmp( argv
[i
], L
"exit" ))
252 if (!wcsicmp( argv
[i
], L
"class") || !wcsicmp( argv
[i
], L
"context" ))
254 WINE_FIXME( "command %s not supported\n", debugstr_w(argv
[i
]) );
258 if (!wcsicmp( argv
[i
], L
"path" ))
262 output_error( STRING_INVALID_PATH
);
269 class = find_class( argv
[i
] );
272 output_error( STRING_ALIAS_NOT_FOUND
);
280 if (!wcsicmp( argv
[i
], L
"get" ))
285 return query_prop( class, value
);
289 output_error( STRING_CMDLINE_NOT_SUPPORTED
);