license.bot | f003cfe | 2008-08-24 09:55:55 +0900 | [diff] [blame] | 1 | // Copyright (c) 2006-2008 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. |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 4 | |
| 5 | #include <windows.h> |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 6 | #include "base/basictypes.h" |
| 7 | #include "base/scoped_bstr_win.h" |
| 8 | #include "base/scoped_comptr_win.h" |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 9 | |
| 10 | #pragma comment(lib, "wbemuuid.lib") |
| 11 | |
| 12 | #include "base/wmi_util.h" |
| 13 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 14 | namespace { |
| 15 | // Simple class to manage the lifetime of a variant. |
| 16 | // TODO(tommi): Replace this for a more useful class. |
| 17 | class VariantHelper : public VARIANT { |
| 18 | public: |
| 19 | VariantHelper() { |
| 20 | vt = VT_EMPTY; |
| 21 | } |
| 22 | explicit VariantHelper(VARTYPE type) { |
| 23 | vt = type; |
| 24 | } |
| 25 | ~VariantHelper() { |
| 26 | ::VariantClear(this); |
| 27 | } |
| 28 | private: |
| 29 | DISALLOW_COPY_AND_ASSIGN(VariantHelper); |
| 30 | }; |
| 31 | |
| 32 | } // namespace |
| 33 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 34 | bool WMIUtil::CreateLocalConnection(bool set_blanket, |
| 35 | IWbemServices** wmi_services) { |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 36 | ScopedComPtr<IWbemLocator> wmi_locator; |
| 37 | HRESULT hr = wmi_locator.CreateInstance(CLSID_WbemLocator, NULL, |
| 38 | CLSCTX_INPROC_SERVER); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 39 | if (FAILED(hr)) |
| 40 | return false; |
| 41 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 42 | ScopedComPtr<IWbemServices> wmi_services_r; |
| 43 | hr = wmi_locator->ConnectServer(StackBstr(L"ROOT\\CIMV2"), NULL, NULL, 0, |
| 44 | NULL, 0, 0, wmi_services_r.Receive()); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 45 | if (FAILED(hr)) |
| 46 | return false; |
| 47 | |
| 48 | if (set_blanket) { |
| 49 | hr = ::CoSetProxyBlanket(wmi_services_r, |
| 50 | RPC_C_AUTHN_WINNT, |
| 51 | RPC_C_AUTHZ_NONE, |
| 52 | NULL, |
| 53 | RPC_C_AUTHN_LEVEL_CALL, |
| 54 | RPC_C_IMP_LEVEL_IMPERSONATE, |
| 55 | NULL, |
| 56 | EOAC_NONE); |
| 57 | if (FAILED(hr)) |
| 58 | return false; |
| 59 | } |
| 60 | |
| 61 | *wmi_services = wmi_services_r.Detach(); |
| 62 | return true; |
| 63 | } |
| 64 | |
| 65 | bool WMIUtil::CreateClassMethodObject(IWbemServices* wmi_services, |
| 66 | const std::wstring& class_name, |
| 67 | const std::wstring& method_name, |
| 68 | IWbemClassObject** class_instance) { |
| 69 | // We attempt to instantiate a COM object that represents a WMI object plus |
| 70 | // a method rolled into one entity. |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 71 | ScopedBstr b_class_name(class_name.c_str()); |
| 72 | ScopedBstr b_method_name(method_name.c_str()); |
| 73 | ScopedComPtr<IWbemClassObject> class_object; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 74 | HRESULT hr; |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 75 | hr = wmi_services->GetObject(b_class_name, 0, NULL, |
| 76 | class_object.Receive(), NULL); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 77 | if (FAILED(hr)) |
| 78 | return false; |
| 79 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 80 | ScopedComPtr<IWbemClassObject> params_def; |
| 81 | hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 82 | if (FAILED(hr)) |
| 83 | return false; |
| 84 | |
| 85 | if (NULL == params_def) { |
| 86 | // You hit this special case if the WMI class is not a CIM class. MSDN |
| 87 | // sometimes tells you this. Welcome to WMI hell. |
| 88 | return false; |
| 89 | } |
| 90 | |
| 91 | hr = params_def->SpawnInstance(0, class_instance); |
| 92 | return(SUCCEEDED(hr)); |
| 93 | } |
| 94 | |
| 95 | bool SetParameter(IWbemClassObject* class_method, |
| 96 | const std::wstring& parameter_name, VARIANT* parameter) { |
| 97 | HRESULT hr = class_method->Put(parameter_name.c_str(), 0, parameter, 0); |
| 98 | return SUCCEEDED(hr); |
| 99 | } |
| 100 | |
| 101 | |
| 102 | // The code in Launch() basically calls the Create Method of the Win32_Process |
| 103 | // CIM class is documented here: |
| 104 | // http://msdn2.microsoft.com/en-us/library/aa389388(VS.85).aspx |
| 105 | |
| 106 | bool WMIProcessUtil::Launch(const std::wstring& command_line, int* process_id) { |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 107 | ScopedComPtr<IWbemServices> wmi_local; |
| 108 | if (!WMIUtil::CreateLocalConnection(true, wmi_local.Receive())) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 109 | return false; |
| 110 | |
| 111 | const wchar_t class_name[] = L"Win32_Process"; |
| 112 | const wchar_t method_name[] = L"Create"; |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 113 | ScopedComPtr<IWbemClassObject> process_create; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 114 | if (!WMIUtil::CreateClassMethodObject(wmi_local, class_name, method_name, |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 115 | process_create.Receive())) |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 116 | return false; |
| 117 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 118 | VariantHelper b_command_line(VT_BSTR); |
| 119 | b_command_line.bstrVal = ::SysAllocString(command_line.c_str()); |
| 120 | |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 121 | if (!SetParameter(process_create, L"CommandLine", &b_command_line)) |
| 122 | return false; |
| 123 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 124 | ScopedComPtr<IWbemClassObject> out_params; |
| 125 | HRESULT hr = wmi_local->ExecMethod(StackBstr(class_name), |
| 126 | StackBstr(method_name), 0, NULL, |
| 127 | process_create, out_params.Receive(), |
| 128 | NULL); |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 129 | if (FAILED(hr)) |
| 130 | return false; |
| 131 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 132 | VariantHelper ret_value; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 133 | hr = out_params->Get(L"ReturnValue", 0, &ret_value, NULL, 0); |
| 134 | if (FAILED(hr) || (0 != ret_value.uintVal)) |
| 135 | return false; |
| 136 | |
cpu@google.com | f9de2f4 | 2009-01-22 08:55:02 +0900 | [diff] [blame] | 137 | VariantHelper pid; |
initial.commit | 3f4a732 | 2008-07-27 06:49:38 +0900 | [diff] [blame] | 138 | hr = out_params->Get(L"ProcessId", 0, &pid, NULL, 0); |
| 139 | if (FAILED(hr) || (0 == pid.intVal)) |
| 140 | return false; |
| 141 | |
| 142 | if (process_id) |
| 143 | *process_id = pid.intVal; |
| 144 | |
| 145 | return true; |
| 146 | } |