blob: 8b56a86d93645f7b24f7da3a869934120fa40ff6 [file] [log] [blame]
license.botf003cfe2008-08-24 09:55:55 +09001// 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.commit3f4a7322008-07-27 06:49:38 +09004
5#include <windows.h>
cpu@google.comf9de2f42009-01-22 08:55:02 +09006#include "base/basictypes.h"
7#include "base/scoped_bstr_win.h"
8#include "base/scoped_comptr_win.h"
initial.commit3f4a7322008-07-27 06:49:38 +09009
10#pragma comment(lib, "wbemuuid.lib")
11
12#include "base/wmi_util.h"
13
cpu@google.comf9de2f42009-01-22 08:55:02 +090014namespace {
15// Simple class to manage the lifetime of a variant.
16// TODO(tommi): Replace this for a more useful class.
17class 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.commit3f4a7322008-07-27 06:49:38 +090034bool WMIUtil::CreateLocalConnection(bool set_blanket,
35 IWbemServices** wmi_services) {
cpu@google.comf9de2f42009-01-22 08:55:02 +090036 ScopedComPtr<IWbemLocator> wmi_locator;
37 HRESULT hr = wmi_locator.CreateInstance(CLSID_WbemLocator, NULL,
38 CLSCTX_INPROC_SERVER);
initial.commit3f4a7322008-07-27 06:49:38 +090039 if (FAILED(hr))
40 return false;
41
cpu@google.comf9de2f42009-01-22 08:55:02 +090042 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.commit3f4a7322008-07-27 06:49:38 +090045 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
65bool 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.comf9de2f42009-01-22 08:55:02 +090071 ScopedBstr b_class_name(class_name.c_str());
72 ScopedBstr b_method_name(method_name.c_str());
73 ScopedComPtr<IWbemClassObject> class_object;
initial.commit3f4a7322008-07-27 06:49:38 +090074 HRESULT hr;
cpu@google.comf9de2f42009-01-22 08:55:02 +090075 hr = wmi_services->GetObject(b_class_name, 0, NULL,
76 class_object.Receive(), NULL);
initial.commit3f4a7322008-07-27 06:49:38 +090077 if (FAILED(hr))
78 return false;
79
cpu@google.comf9de2f42009-01-22 08:55:02 +090080 ScopedComPtr<IWbemClassObject> params_def;
81 hr = class_object->GetMethod(b_method_name, 0, params_def.Receive(), NULL);
initial.commit3f4a7322008-07-27 06:49:38 +090082 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
95bool 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
106bool WMIProcessUtil::Launch(const std::wstring& command_line, int* process_id) {
cpu@google.comf9de2f42009-01-22 08:55:02 +0900107 ScopedComPtr<IWbemServices> wmi_local;
108 if (!WMIUtil::CreateLocalConnection(true, wmi_local.Receive()))
initial.commit3f4a7322008-07-27 06:49:38 +0900109 return false;
110
111 const wchar_t class_name[] = L"Win32_Process";
112 const wchar_t method_name[] = L"Create";
cpu@google.comf9de2f42009-01-22 08:55:02 +0900113 ScopedComPtr<IWbemClassObject> process_create;
initial.commit3f4a7322008-07-27 06:49:38 +0900114 if (!WMIUtil::CreateClassMethodObject(wmi_local, class_name, method_name,
cpu@google.comf9de2f42009-01-22 08:55:02 +0900115 process_create.Receive()))
initial.commit3f4a7322008-07-27 06:49:38 +0900116 return false;
117
cpu@google.comf9de2f42009-01-22 08:55:02 +0900118 VariantHelper b_command_line(VT_BSTR);
119 b_command_line.bstrVal = ::SysAllocString(command_line.c_str());
120
initial.commit3f4a7322008-07-27 06:49:38 +0900121 if (!SetParameter(process_create, L"CommandLine", &b_command_line))
122 return false;
123
cpu@google.comf9de2f42009-01-22 08:55:02 +0900124 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.commit3f4a7322008-07-27 06:49:38 +0900129 if (FAILED(hr))
130 return false;
131
cpu@google.comf9de2f42009-01-22 08:55:02 +0900132 VariantHelper ret_value;
initial.commit3f4a7322008-07-27 06:49:38 +0900133 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.comf9de2f42009-01-22 08:55:02 +0900137 VariantHelper pid;
initial.commit3f4a7322008-07-27 06:49:38 +0900138 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}