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
< sizeof(alias_map
)/sizeof(alias_map
[0]); 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( const WCHAR
*msg
, ... )
131 va_start( va_args
, msg
);
132 vsprintfW( buffer
, msg
, va_args
);
135 wlen
= strlenW( buffer
);
136 ret
= WriteConsoleW( GetStdHandle(STD_OUTPUT_HANDLE
), buffer
, wlen
, &count
, NULL
);
142 /* On Windows WriteConsoleW() fails if the output is redirected. So fall
143 * back to WriteFile(), assuming the console encoding is still the right
146 len
= WideCharToMultiByte( GetConsoleOutputCP(), 0, buffer
, wlen
, NULL
, 0, NULL
, NULL
);
147 if (!(msgA
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(char) ))) return 0;
149 WideCharToMultiByte( GetConsoleOutputCP(), 0, buffer
, wlen
, msgA
, len
, NULL
, NULL
);
150 WriteFile( GetStdHandle(STD_OUTPUT_HANDLE
), msgA
, len
, &count
, FALSE
);
151 HeapFree( GetProcessHeap(), 0, msgA
);
156 static int output_message( int msg
)
158 static const WCHAR fmtW
[] = {'%','s',0};
161 LoadStringW( GetModuleHandleW(NULL
), msg
, buffer
, sizeof(buffer
)/sizeof(WCHAR
) );
162 return output_string( fmtW
, buffer
);
165 static int query_prop( const WCHAR
*class, const WCHAR
*propname
)
167 static const WCHAR select_allW
[] = {'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ',0};
168 static const WCHAR cimv2W
[] = {'R','O','O','T','\\','C','I','M','V','2',0};
169 static const WCHAR wqlW
[] = {'W','Q','L',0};
170 static const WCHAR newlineW
[] = {'\n',0};
171 static const WCHAR fmtW
[] = {'%','s','\n',0};
173 IWbemLocator
*locator
= NULL
;
174 IWbemServices
*services
= NULL
;
175 IEnumWbemClassObject
*result
= NULL
;
176 LONG flags
= WBEM_FLAG_RETURN_IMMEDIATELY
| WBEM_FLAG_FORWARD_ONLY
;
177 BSTR path
= NULL
, wql
= NULL
, query
= NULL
;
182 WINE_TRACE("%s, %s\n", debugstr_w(class), debugstr_w(propname
));
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( cimv2W
))) goto done
;
193 hr
= IWbemLocator_ConnectServer( locator
, path
, NULL
, NULL
, NULL
, 0, NULL
, NULL
, &services
);
194 if (hr
!= S_OK
) goto done
;
196 len
= strlenW( class ) + sizeof(select_allW
) / sizeof(select_allW
[0]);
197 if (!(query
= SysAllocStringLen( NULL
, len
))) goto done
;
198 strcpyW( query
, select_allW
);
199 strcatW( query
, class );
201 if (!(wql
= SysAllocString( wqlW
))) goto done
;
202 hr
= IWbemServices_ExecQuery( services
, wql
, query
, flags
, NULL
, &result
);
203 if (hr
!= S_OK
) goto done
;
207 IWbemClassObject
*obj
;
211 IEnumWbemClassObject_Next( result
, WBEM_INFINITE
, 1, &obj
, &count
);
216 if (!(prop
= find_prop( obj
, propname
)))
218 output_message( STRING_INVALID_QUERY
);
221 output_string( fmtW
, prop
);
224 if (IWbemClassObject_Get( obj
, prop
, 0, &v
, NULL
, NULL
) == WBEM_S_NO_ERROR
)
226 VariantChangeType( &v
, &v
, 0, VT_BSTR
);
227 output_string( fmtW
, V_BSTR( &v
) );
230 IWbemClassObject_Release( obj
);
232 output_string( newlineW
);
236 if (result
) IEnumWbemClassObject_Release( result
);
237 if (services
) IWbemServices_Release( services
);
238 if (locator
) IWbemLocator_Release( locator
);
239 SysFreeString( path
);
240 SysFreeString( query
);
241 SysFreeString( wql
);
242 HeapFree( GetProcessHeap(), 0, prop
);
247 int wmain(int argc
, WCHAR
*argv
[])
249 static const WCHAR getW
[] = {'g','e','t',0};
250 static const WCHAR quitW
[] = {'q','u','i','t',0};
251 static const WCHAR exitW
[] = {'e','x','i','t',0};
252 static const WCHAR pathW
[] = {'p','a','t','h',0};
253 static const WCHAR classW
[] = {'c','l','a','s','s',0};
254 static const WCHAR contextW
[] = {'c','o','n','t','e','x','t',0};
255 const WCHAR
*class, *value
;
258 for (i
= 1; i
< argc
&& argv
[i
][0] == '/'; i
++)
259 WINE_FIXME( "command line switch %s not supported\n", debugstr_w(argv
[i
]) );
264 if (!strcmpiW( argv
[i
], quitW
) ||
265 !strcmpiW( argv
[i
], exitW
))
270 if (!strcmpiW( argv
[i
], classW
) ||
271 !strcmpiW( argv
[i
], contextW
))
273 WINE_FIXME( "command %s not supported\n", debugstr_w(argv
[i
]) );
277 if (!strcmpiW( argv
[i
], pathW
))
281 output_message( STRING_INVALID_PATH
);
288 class = find_class( argv
[i
] );
291 output_message( STRING_ALIAS_NOT_FOUND
);
299 if (!strcmpiW( argv
[i
], getW
))
304 return query_prop( class, value
);
308 output_message( STRING_CMDLINE_NOT_SUPPORTED
);