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.
6 #include "base/basictypes.h"
7 #include "base/scoped_bstr_win.h"
8 #include "base/scoped_comptr_win.h"
10 #pragma comment(lib, "wbemuuid.lib")
12 #include "base/wmi_util.h"
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
{
22 explicit VariantHelper(VARTYPE type
) {
29 DISALLOW_COPY_AND_ASSIGN(VariantHelper
);
34 bool WMIUtil::CreateLocalConnection(bool set_blanket
,
35 IWbemServices
** wmi_services
) {
36 ScopedComPtr
<IWbemLocator
> wmi_locator
;
37 HRESULT hr
= wmi_locator
.CreateInstance(CLSID_WbemLocator
, NULL
,
38 CLSCTX_INPROC_SERVER
);
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());
49 hr
= ::CoSetProxyBlanket(wmi_services_r
,
53 RPC_C_AUTHN_LEVEL_CALL
,
54 RPC_C_IMP_LEVEL_IMPERSONATE
,
61 *wmi_services
= wmi_services_r
.Detach();
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.
71 ScopedBstr
b_class_name(class_name
.c_str());
72 ScopedBstr
b_method_name(method_name
.c_str());
73 ScopedComPtr
<IWbemClassObject
> class_object
;
75 hr
= wmi_services
->GetObject(b_class_name
, 0, NULL
,
76 class_object
.Receive(), NULL
);
80 ScopedComPtr
<IWbemClassObject
> params_def
;
81 hr
= class_object
->GetMethod(b_method_name
, 0, params_def
.Receive(), NULL
);
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.
91 hr
= params_def
->SpawnInstance(0, class_instance
);
92 return(SUCCEEDED(hr
));
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);
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
106 bool WMIProcessUtil::Launch(const std::wstring
& command_line
, int* process_id
) {
107 ScopedComPtr
<IWbemServices
> wmi_local
;
108 if (!WMIUtil::CreateLocalConnection(true, wmi_local
.Receive()))
111 const wchar_t class_name
[] = L
"Win32_Process";
112 const wchar_t method_name
[] = L
"Create";
113 ScopedComPtr
<IWbemClassObject
> process_create
;
114 if (!WMIUtil::CreateClassMethodObject(wmi_local
, class_name
, method_name
,
115 process_create
.Receive()))
118 VariantHelper
b_command_line(VT_BSTR
);
119 b_command_line
.bstrVal
= ::SysAllocString(command_line
.c_str());
121 if (!SetParameter(process_create
, L
"CommandLine", &b_command_line
))
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(),
132 VariantHelper ret_value
;
133 hr
= out_params
->Get(L
"ReturnValue", 0, &ret_value
, NULL
, 0);
134 if (FAILED(hr
) || (0 != ret_value
.uintVal
))
138 hr
= out_params
->Get(L
"ProcessId", 0, &pid
, NULL
, 0);
139 if (FAILED(hr
) || (0 == pid
.intVal
))
143 *process_id
= pid
.intVal
;