Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / installer / util / wmi.cc
blob2040ceb05e39700c4d8e5a0083f111a6e9cf238c
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"
7 #include <windows.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;
18 namespace installer {
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);
25 if (FAILED(hr))
26 return false;
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());
32 if (FAILED(hr))
33 return false;
35 if (set_blanket) {
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);
39 if (FAILED(hr))
40 return false;
43 *wmi_services = wmi_services_r.Detach();
44 return true;
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;
56 HRESULT hr;
57 hr = wmi_services->GetObject(b_class_name, 0, NULL,
58 class_object.Receive(), NULL);
59 if (FAILED(hr))
60 return false;
62 base::win::ScopedComPtr<IWbemClassObject> params_def;
63 hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL);
64 if (FAILED(hr))
65 return false;
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.
70 return false;
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);
80 return SUCCEEDED(hr);
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()))
94 return false;
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()))
101 return false;
103 ScopedVariant b_command_line(command_line.c_str());
105 if (!SetParameter(process_create.get(), L"CommandLine",
106 b_command_line.AsInput()))
107 return false;
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);
113 if (FAILED(hr))
114 return false;
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))
120 return false;
122 VARIANT pid = {{{VT_EMPTY}}};
123 hr = out_params->Get(L"ProcessId", 0, &pid, NULL, 0);
124 if (FAILED(hr) || 0 == V_I4(&pid))
125 return false;
127 if (process_id)
128 *process_id = V_I4(&pid);
130 return true;
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(),
151 &items_returned);
152 if (!items_returned)
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.ptr());
163 if (model.type() == VT_BSTR)
164 model_string += L" ";
166 if (model.type() == VT_BSTR)
167 model_string += V_BSTR(model.ptr());
169 return model_string;
172 } // namespace installer