1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/installer/util/wmi.h"
9 #include "base/basictypes.h"
10 #include "base/win/scoped_bstr.h"
11 #include "base/win/scoped_comptr.h"
12 #include "base/win/scoped_variant.h"
14 #pragma comment(lib, "wbemuuid.lib")
16 using base::win::ScopedVariant
;
20 bool WMI::CreateLocalConnection(bool set_blanket
,
21 IWbemServices
** wmi_services
) {
22 base::win::ScopedComPtr
<IWbemLocator
> wmi_locator
;
23 HRESULT hr
= wmi_locator
.CreateInstance(CLSID_WbemLocator
, NULL
,
24 CLSCTX_INPROC_SERVER
);
28 base::win::ScopedComPtr
<IWbemServices
> wmi_services_r
;
29 hr
= wmi_locator
->ConnectServer(base::win::ScopedBstr(L
"ROOT\\CIMV2"),
30 NULL
, NULL
, 0, NULL
, 0, 0,
31 wmi_services_r
.Receive());
36 hr
= ::CoSetProxyBlanket(wmi_services_r
.get(), RPC_C_AUTHN_WINNT
,
37 RPC_C_AUTHZ_NONE
, NULL
, RPC_C_AUTHN_LEVEL_CALL
,
38 RPC_C_IMP_LEVEL_IMPERSONATE
, NULL
, EOAC_NONE
);
43 *wmi_services
= wmi_services_r
.Detach();
47 bool WMI::CreateClassMethodObject(IWbemServices
* wmi_services
,
48 const std::wstring
& class_name
,
49 const std::wstring
& method_name
,
50 IWbemClassObject
** class_instance
) {
51 // We attempt to instantiate a COM object that represents a WMI object plus
52 // a method rolled into one entity.
53 base::win::ScopedBstr
b_class_name(class_name
.c_str());
54 base::win::ScopedBstr
b_method_name(method_name
.c_str());
55 base::win::ScopedComPtr
<IWbemClassObject
> class_object
;
57 hr
= wmi_services
->GetObject(b_class_name
, 0, NULL
,
58 class_object
.Receive(), NULL
);
62 base::win::ScopedComPtr
<IWbemClassObject
> params_def
;
63 hr
= class_object
->GetMethod(b_method_name
, 0, params_def
.Receive(), NULL
);
67 if (NULL
== params_def
.get()) {
68 // You hit this special case if the WMI class is not a CIM class. MSDN
69 // sometimes tells you this. Welcome to WMI hell.
73 hr
= params_def
->SpawnInstance(0, class_instance
);
74 return(SUCCEEDED(hr
));
77 bool SetParameter(IWbemClassObject
* class_method
,
78 const std::wstring
& parameter_name
, VARIANT
* parameter
) {
79 HRESULT hr
= class_method
->Put(parameter_name
.c_str(), 0, parameter
, 0);
84 // The code in Launch() basically calls the Create Method of the Win32_Process
85 // CIM class is documented here:
86 // http://msdn2.microsoft.com/en-us/library/aa389388(VS.85).aspx
87 // NOTE: The documentation for the Create method suggests that the ProcessId
88 // parameter and return value are of type uint32, but when we call the method
89 // the values in the returned out_params, are VT_I4, which is int32.
91 bool WMIProcess::Launch(const std::wstring
& command_line
, int* process_id
) {
92 base::win::ScopedComPtr
<IWbemServices
> wmi_local
;
93 if (!WMI::CreateLocalConnection(true, wmi_local
.Receive()))
96 const wchar_t class_name
[] = L
"Win32_Process";
97 const wchar_t method_name
[] = L
"Create";
98 base::win::ScopedComPtr
<IWbemClassObject
> process_create
;
99 if (!WMI::CreateClassMethodObject(wmi_local
.get(), class_name
, method_name
,
100 process_create
.Receive()))
103 ScopedVariant
b_command_line(command_line
.c_str());
105 if (!SetParameter(process_create
.get(), L
"CommandLine",
106 b_command_line
.AsInput()))
109 base::win::ScopedComPtr
<IWbemClassObject
> out_params
;
110 HRESULT hr
= wmi_local
->ExecMethod(
111 base::win::ScopedBstr(class_name
), base::win::ScopedBstr(method_name
), 0,
112 NULL
, process_create
.get(), out_params
.Receive(), NULL
);
116 // We're only expecting int32 or uint32 values, so no need for ScopedVariant.
117 VARIANT ret_value
= {VT_EMPTY
};
118 hr
= out_params
->Get(L
"ReturnValue", 0, &ret_value
, NULL
, 0);
119 if (FAILED(hr
) || 0 != V_I4(&ret_value
))
122 VARIANT pid
= {VT_EMPTY
};
123 hr
= out_params
->Get(L
"ProcessId", 0, &pid
, NULL
, 0);
124 if (FAILED(hr
) || 0 == V_I4(&pid
))
128 *process_id
= V_I4(&pid
);
133 base::string16
WMIComputerSystem::GetModel() {
134 base::win::ScopedComPtr
<IWbemServices
> services
;
135 if (!WMI::CreateLocalConnection(true, services
.Receive()))
136 return base::string16();
138 base::win::ScopedBstr
query_language(L
"WQL");
139 base::win::ScopedBstr
query(L
"SELECT * FROM Win32_ComputerSystem");
140 base::win::ScopedComPtr
<IEnumWbemClassObject
> enumerator
;
141 HRESULT hr
= services
->ExecQuery(
142 query_language
, query
,
143 WBEM_FLAG_FORWARD_ONLY
| WBEM_FLAG_RETURN_IMMEDIATELY
, NULL
,
144 enumerator
.Receive());
145 if (FAILED(hr
) || !enumerator
.get())
146 return base::string16();
148 base::win::ScopedComPtr
<IWbemClassObject
> class_object
;
149 ULONG items_returned
= 0;
150 hr
= enumerator
->Next(WBEM_INFINITE
, 1, class_object
.Receive(),
153 return base::string16();
155 base::win::ScopedVariant manufacturer
;
156 class_object
->Get(L
"Manufacturer", 0, manufacturer
.Receive(), 0, 0);
157 base::win::ScopedVariant model
;
158 class_object
->Get(L
"Model", 0, model
.Receive(), 0, 0);
160 base::string16 model_string
;
161 if (manufacturer
.type() == VT_BSTR
) {
162 model_string
= V_BSTR(&manufacturer
);
163 if (model
.type() == VT_BSTR
)
164 model_string
+= L
" ";
166 if (model
.type() == VT_BSTR
)
167 model_string
+= V_BSTR(&model
);
172 } // namespace installer