- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / installer / util / wmi.cc
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.
4
5 #include "chrome/installer/util/wmi.h"
6
7 #include <windows.h>
8
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"
13
14 #pragma comment(lib, "wbemuuid.lib")
15
16 using base::win::ScopedVariant;
17
18 namespace installer {
19
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;
27
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;
34
35   if (set_blanket) {
36     hr = ::CoSetProxyBlanket(wmi_services_r,
37                              RPC_C_AUTHN_WINNT,
38                              RPC_C_AUTHZ_NONE,
39                              NULL,
40                              RPC_C_AUTHN_LEVEL_CALL,
41                              RPC_C_IMP_LEVEL_IMPERSONATE,
42                              NULL,
43                              EOAC_NONE);
44     if (FAILED(hr))
45       return false;
46   }
47
48   *wmi_services = wmi_services_r.Detach();
49   return true;
50 }
51
52 bool WMI::CreateClassMethodObject(IWbemServices* wmi_services,
53                                   const std::wstring& class_name,
54                                   const std::wstring& method_name,
55                                   IWbemClassObject** class_instance) {
56   // We attempt to instantiate a COM object that represents a WMI object plus
57   // a method rolled into one entity.
58   base::win::ScopedBstr b_class_name(class_name.c_str());
59   base::win::ScopedBstr b_method_name(method_name.c_str());
60   base::win::ScopedComPtr<IWbemClassObject> class_object;
61   HRESULT hr;
62   hr = wmi_services->GetObject(b_class_name, 0, NULL,
63                                class_object.Receive(), NULL);
64   if (FAILED(hr))
65     return false;
66
67   base::win::ScopedComPtr<IWbemClassObject> params_def;
68   hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL);
69   if (FAILED(hr))
70     return false;
71
72   if (NULL == params_def) {
73     // You hit this special case if the WMI class is not a CIM class. MSDN
74     // sometimes tells you this. Welcome to WMI hell.
75     return false;
76   }
77
78   hr = params_def->SpawnInstance(0, class_instance);
79   return(SUCCEEDED(hr));
80 }
81
82 bool SetParameter(IWbemClassObject* class_method,
83                   const std::wstring& parameter_name, VARIANT* parameter) {
84   HRESULT hr = class_method->Put(parameter_name.c_str(), 0, parameter, 0);
85   return SUCCEEDED(hr);
86 }
87
88
89 // The code in Launch() basically calls the Create Method of the Win32_Process
90 // CIM class is documented here:
91 // http://msdn2.microsoft.com/en-us/library/aa389388(VS.85).aspx
92 // NOTE: The documentation for the Create method suggests that the ProcessId
93 // parameter and return value are of type uint32, but when we call the method
94 // the values in the returned out_params, are VT_I4, which is int32.
95
96 bool WMIProcess::Launch(const std::wstring& command_line, int* process_id) {
97   base::win::ScopedComPtr<IWbemServices> wmi_local;
98   if (!WMI::CreateLocalConnection(true, wmi_local.Receive()))
99     return false;
100
101   const wchar_t class_name[] = L"Win32_Process";
102   const wchar_t method_name[] = L"Create";
103   base::win::ScopedComPtr<IWbemClassObject> process_create;
104   if (!WMI::CreateClassMethodObject(wmi_local, class_name, method_name,
105                                     process_create.Receive()))
106     return false;
107
108   ScopedVariant b_command_line(command_line.c_str());
109
110   if (!SetParameter(process_create, L"CommandLine", b_command_line.AsInput()))
111     return false;
112
113   base::win::ScopedComPtr<IWbemClassObject> out_params;
114   HRESULT hr = wmi_local->ExecMethod(base::win::ScopedBstr(class_name),
115                                      base::win::ScopedBstr(method_name),
116                                      0, NULL, process_create,
117                                      out_params.Receive(), NULL);
118   if (FAILED(hr))
119     return false;
120
121   // We're only expecting int32 or uint32 values, so no need for ScopedVariant.
122   VARIANT ret_value = {VT_EMPTY};
123   hr = out_params->Get(L"ReturnValue", 0, &ret_value, NULL, 0);
124   if (FAILED(hr) || 0 != V_I4(&ret_value))
125     return false;
126
127   VARIANT pid = {VT_EMPTY};
128   hr = out_params->Get(L"ProcessId", 0, &pid, NULL, 0);
129   if (FAILED(hr) || 0 == V_I4(&pid))
130     return false;
131
132   if (process_id)
133     *process_id = V_I4(&pid);
134
135   return true;
136 }
137
138 string16 WMIComputerSystem::GetModel() {
139   base::win::ScopedComPtr<IWbemServices> services;
140   if (!WMI::CreateLocalConnection(true, services.Receive()))
141     return string16();
142
143   base::win::ScopedBstr query_language(L"WQL");
144   base::win::ScopedBstr query(L"SELECT * FROM Win32_ComputerSystem");
145   base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
146   HRESULT hr = services->ExecQuery(
147       query_language, query,
148       WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
149       enumerator.Receive());
150   if (FAILED(hr) || !enumerator)
151     return string16();
152
153   base::win::ScopedComPtr<IWbemClassObject> class_object;
154   ULONG items_returned = 0;
155   hr = enumerator->Next(WBEM_INFINITE, 1,  class_object.Receive(),
156                         &items_returned);
157   if (!items_returned)
158     return string16();
159
160   base::win::ScopedVariant manufacturer;
161   class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
162   base::win::ScopedVariant model;
163   class_object->Get(L"Model", 0, model.Receive(), 0, 0);
164
165   string16 model_string;
166   if (manufacturer.type() == VT_BSTR) {
167     model_string = V_BSTR(&manufacturer);
168     if (model.type() == VT_BSTR)
169       model_string += L" ";
170   }
171   if (model.type() == VT_BSTR)
172     model_string += V_BSTR(&model);
173
174   return model_string;
175 }
176
177 }  // namespace installer