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 178