Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
wmi.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2011 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * wrapper for Windows Management Instrumentation
25  */
26 
27 #include "precompiled.h"
28 #include "lib/sysdep/os/win/wmi.h"
29 
30 #include <wbemidl.h>
31 
32 #include "lib/module_init.h"
33 
34 #pragma comment(lib, "wbemuuid.lib")
35 
36 
37 static IWbemServices* pSvc;
38 
39 _COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator));
40 _COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
41 _COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
42 
44 
45 static bool didInitCOM = false;
46 
47 static Status Init()
48 {
49  HRESULT hr;
50 
51  hr = CoInitialize(0);
52  ENSURE(hr == S_OK || hr == S_FALSE); // S_FALSE => already initialized
53 
54  // balance calls to CoInitialize and CoUninitialize
55  if (hr == S_FALSE)
56  CoUninitialize();
57  else if (hr == S_OK)
58  didInitCOM = true;
59 
60  hr = CoInitializeSecurity(0, -1, 0, 0, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE, 0);
61  if(FAILED(hr))
63 
64  {
65  IWbemLocatorPtr pLoc = 0;
66  hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (void**)&pLoc);
67  if(FAILED(hr))
69 
70  hr = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), 0, 0, 0, 0, 0, 0, &pSvc);
71  if(FAILED(hr))
72  return ERR::_4; // NOWARN (happens if WMI service is disabled)
73  }
74 
75  hr = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, 0, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, 0, EOAC_NONE);
76  if(FAILED(hr))
78 
79  return INFO::OK;
80 }
81 
82 static void Shutdown()
83 {
84  pSvc->Release();
85 
86  if (didInitCOM)
87  {
88  /* From MSDN documentation: A thread must call CoUninitialize once for each successful call
89  * it has made to the CoInitialize or CoInitializeEx function, including any call that returns
90  * S_FALSE. Only the CoUninitialize call corresponding to the CoInitialize or CoInitializeEx
91  * call that initialized the library can close it.
92  *
93  * So it should be perfectly safe to call this, since it balances out the CoInitialize in Init
94  */
95  CoUninitialize();
96  didInitCOM = false;
97  }
98 }
99 
101 {
102  ModuleShutdown(&initState, Shutdown);
103 }
104 
105 
106 Status wmi_GetClassInstances(const wchar_t* className, WmiInstances& instances)
107 {
108  RETURN_STATUS_IF_ERR(ModuleInit(&initState, Init));
109 
110  IEnumWbemClassObjectPtr pEnum = 0;
111  wchar_t query[200];
112  swprintf_s(query, ARRAY_SIZE(query), L"SELECT * FROM %ls", className);
113  HRESULT hr = pSvc->ExecQuery(L"WQL", _bstr_t(query), WBEM_FLAG_FORWARD_ONLY|WBEM_FLAG_RETURN_IMMEDIATELY, 0, &pEnum);
114  if(FAILED(hr))
116  ENSURE(pEnum);
117 
118  for(;;)
119  {
120  IWbemClassObjectPtr pObj = 0;
121  ULONG numReturned = 0;
122  hr = pEnum->Next((LONG)WBEM_INFINITE, 1, &pObj, &numReturned);
123  if(FAILED(hr))
125  if(numReturned == 0)
126  break;
127  ENSURE(pEnum);
128 
129  WmiInstance instance;
130  pObj->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
131  for(;;)
132  {
133  BSTR name = NULL;
134  VARIANT value;
135  VariantInit(&value);
136  if(pObj->Next(0, &name, &value, 0, 0) != WBEM_S_NO_ERROR)
137  {
138  SysFreeString(name);
139  break;
140  }
141  instance[name] = value;
142  SysFreeString(name);
143  }
144  instances.push_back(instance);
145  }
146 
147  return INFO::OK;
148 }
const Status _4
Definition: status.h:444
const Status OK
Definition: status.h:386
static Status Init()
Definition: h_mgr.cpp:744
static void Shutdown()
Definition: h_mgr.cpp:762
const Status _3
Definition: status.h:443
void wmi_Shutdown()
Definition: wmi.cpp:100
int swprintf_s(wchar_t *buf, size_t max_chars, const wchar_t *fmt,...) WPRINTF_ARGS(3)
std::vector< WmiInstance > WmiInstances
Definition: wmi.h:42
#define ARRAY_SIZE(name)
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
intptr_t ModuleInitState
initialization state of a module (class, source file, etc.) must be initialized to zero (e...
Definition: module_init.h:35
Status wmi_GetClassInstances(const wchar_t *className, WmiInstances &instances)
get all instances of the requested class.
Definition: wmi.cpp:106
const Status _5
Definition: status.h:445
i64 Status
Error handling system.
Definition: status.h:171
static IWbemServices * pSvc
Definition: wmi.cpp:37
Status ModuleShutdown(volatile ModuleInitState *initState, void(*shutdown)())
calls a user-defined shutdown function if initState is &quot;initialized&quot;.
Definition: module_init.cpp:65
_COM_SMARTPTR_TYPEDEF(IWbemLocator, __uuidof(IWbemLocator))
std::map< std::wstring, VARIANT > WmiInstance
Definition: wmi.h:40
#define WARN_RETURN(status)
Definition: status.h:255
static bool didInitCOM
Definition: wmi.cpp:45
const Status FAIL
Definition: status.h:406
const Status _2
Definition: status.h:442
static ModuleInitState initState
Definition: wmi.cpp:43
long LONG
Definition: wgl.h:55
Status ModuleInit(volatile ModuleInitState *initState, Status(*init)())
calls a user-defined init function if initState is zero.
Definition: module_init.cpp:40
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276