Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

440 lines
12 KiB

  1. //=============================================================================
  2. // Code used to manage threaded WMI refreshes.
  3. //=============================================================================
  4. #include "stdafx.h"
  5. #if FALSE
  6. //-----------------------------------------------------------------------------
  7. // The CWMIObject abstract base class encapsulates a WMI object, which may
  8. // in reality be a live WMI object, or an object recreated from the XML
  9. // storage of an object.
  10. //-----------------------------------------------------------------------------
  11. class CWMIObject
  12. {
  13. public:
  14. CWMIObject();
  15. virtual ~CWMIObject();
  16. // The following methods return information about a property of this object.
  17. //
  18. // S_OK implies success
  19. // E_MSINFO_NOPROPERTY means the named property doesn't exist
  20. // E_MSINFO_NOVALUE means the property exists, but is empty
  21. virtual HRESULT GetValue(LPCTSTR szProperty, VARIANT * pvarValue);
  22. virtual HRESULT GetValueString(LPCTSTR szProperty, LPTSTR * pszValue);
  23. virtual HRESULT GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue);
  24. virtual HRESULT GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue);
  25. virtual HRESULT GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue);
  26. virtual HRESULT GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue);
  27. };
  28. //-----------------------------------------------------------------------------
  29. // The CWMIObjectCollection abstract base class encapsulates a collection
  30. // of CWMIObject's. This collection may be treated like an enumeration.
  31. // Subclases of this class may implement the collection as a WMI enumerator,
  32. // or an existing blob of XML data.
  33. //-----------------------------------------------------------------------------
  34. class CWMIObjectCollection
  35. {
  36. public:
  37. CWMIObjectCollection();
  38. virtual ~CWMIObjectCollection();
  39. // The Create function creates the collection of objects (note - Create
  40. // may be called multiple times on the same object). If the szProperties
  41. // parameter is non-NULL, then it contains a comma delimited list of the
  42. // minimum set of properties which should be included in the collection
  43. // of objects. If it's NULL, then all available properties should be
  44. // included.
  45. virtual HRESULT Create(LPCTSTR szClass, LPCTSTR szProperties = NULL);
  46. // The following two functions are used to manage the enumeration. GetNext
  47. // returns the next enumerated CWMIObject. When there are no more objects,
  48. // GetNext returns S_FALSE. Obviously, the caller is responsible for
  49. // deleting the object returned.
  50. virtual HRESULT GetNext(CWMIObject ** ppObject);
  51. };
  52. //-----------------------------------------------------------------------------
  53. // The CWMILiveObject implements a CWMIObject using a real WMI object. It
  54. // can be created with either a IWbemClassObject pointer, or a services
  55. // pointer and a path.
  56. //-----------------------------------------------------------------------------
  57. class CWMILiveObject : public CWMIObject
  58. {
  59. public:
  60. CWMILiveObject();
  61. virtual ~CWMILiveObject();
  62. // Functions inherited from the base class:
  63. HRESULT GetValue(LPCTSTR szProperty, VARIANT * pvarValue);
  64. HRESULT GetValueString(LPCTSTR szProperty, LPTSTR * pszValue);
  65. HRESULT GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue);
  66. HRESULT GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue);
  67. HRESULT GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue);
  68. HRESULT GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue);
  69. // Functions specific to this subclass:
  70. //
  71. // Note - Create with an object pointer will addref() the pointer:
  72. HRESULT Create(IWbemClassObject * pObject);
  73. HRESULT Create(IWbemServices * pServices, LPCTSTR szObjectPath);
  74. private:
  75. IWbemClassObject * m_pObject;
  76. };
  77. //-----------------------------------------------------------------------------
  78. // The CWMILiveObjectCollection implements a collection of live WMI objects
  79. // using a WMI enumerator. This collection can be created from an existing
  80. // IEnumWbemClassObject pointer, from a WQL statement or from a WMI class name.
  81. //-----------------------------------------------------------------------------
  82. class CWMILiveObjectCollection
  83. {
  84. public:
  85. CWMILiveObjectCollection(IWbemServices * pServices);
  86. virtual ~CWMILiveObjectCollection();
  87. // Functions inherited from the base class:
  88. HRESULT Create(LPCTSTR szClass, LPCTSTR szProperties = NULL);
  89. HRESULT GetNext(CWMIObject ** ppObject);
  90. // Functions specific to this subclass:
  91. //
  92. // Note - Create with an enum pointer will addref() the pointer:
  93. public:
  94. HRESULT Create(IEnumWbemClassObject * pEnum);
  95. private:
  96. IEnumWbemClassObject * m_pEnum;
  97. IWbemServices * m_pServices;
  98. };
  99. //-----------------------------------------------------------------------------
  100. // The constructor and destructor for CWMILiveObjectCollection are very
  101. // straightforward.
  102. //-----------------------------------------------------------------------------
  103. CWMILiveObjectCollection::CWMILiveObjectCollection(IWbemServices * pServices) : m_pServices(pServices), m_pEnum(NULL)
  104. {
  105. ASSERT(m_pServices);
  106. if (m_pServices)
  107. m_pServices->AddRef();
  108. }
  109. CWMILiveObjectCollection::~CWMILiveObjectCollection()
  110. {
  111. if (m_pServices)
  112. m_pServices->Release();
  113. if (m_pEnum)
  114. m_pEnum->Release();
  115. }
  116. //-----------------------------------------------------------------------------
  117. // Create the collection of WMI objects (a WMI enumerator) based on the
  118. // class name and the requested properties.
  119. //-----------------------------------------------------------------------------
  120. HRESULT CWMILiveObjectCollection::Create(LPCTSTR szClass, LPCTSTR szProperties)
  121. {
  122. ASSERT(szClass);
  123. if (m_pEnum)
  124. m_pEnum->Release();
  125. // Build the appopriate WQL query statement from the class and requested properties.
  126. LPCTSTR szWQLProperties = (szProperties) ? szProperties : _T("*");
  127. LPTSTR szQuery = new TCHAR[_tcsclen(szWQLProperties) + _tcsclen(szClass) + 14 /* length of "SELECT FROM " + 1 */);
  128. if (szQuery == NULL)
  129. return E_OUTOFMEMORY;
  130. wsprintf(szQuery, _T("SELECT %s FROM %s"), szClass, szWQLProperties);
  131. // Perform the query using our saved services pointer.
  132. HRESULT hr;
  133. BSTR bstrLanguage = SysAllocString(L"WQL");
  134. #ifdef UNICODE
  135. BSTR bstrQuery = SysAllocString(szQuery);
  136. #else
  137. USES_CONVERSION;
  138. LPOLESTR szWideQuery = T2OLE(szQuery);
  139. BSTR bstrQuery = SysAllocString(szWideQuery);
  140. #endif
  141. if (bstrLanguage && bstrQuery)
  142. hr = pService->ExecQuery(bstrLanguage, bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY, 0, &m_pEnum);
  143. else
  144. hr = E_OUTOFMEMORY;
  145. if (bstrQuery)
  146. SysFreeString(bstrQuery);
  147. if (bstrLanguage)
  148. SysFreeString(bstrLanguage);
  149. delete [] szQuery;
  150. return hr;
  151. }
  152. //-----------------------------------------------------------------------------
  153. // Create this class of an existing enumerator. This may be a little odd,
  154. // since the enumerators will interact if both are advancing.
  155. //-----------------------------------------------------------------------------
  156. HRESULT CWMILiveObjectCollection::Create(IEnumWbemClassObject * pEnum)
  157. {
  158. if (m_pEnum)
  159. m_pEnum->Release();
  160. m_pEnum = pEnum;
  161. if (m_pEnum)
  162. m_pEnum->AddRef();
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Return the next item in the WMI enumerator as a CWMILiveObject object.
  166. //-----------------------------------------------------------------------------
  167. HRESULT CWMILiveObjectCollection::GetNext(CWMIObject ** ppObject)
  168. {
  169. ASSERT(ppObject);
  170. if (m_pEnum == NULL)
  171. {
  172. ASSERT(0 && "CWMILiveObjectCollection::GetNext called on a null enumerator");
  173. return E_FAIL;
  174. }
  175. IWbemClassObject * pRealWMIObject = NULL;
  176. ULONG uReturned;
  177. HRESULT hr = m_pEnum->Next(TIMEOUT, 1, &pRealWMIObject, &uReturned);
  178. if (hr == S_OK && uReturned = 1)
  179. {
  180. *ppObject = new CWMILiveObject;
  181. if (*ppObject)
  182. hr = (*ppObject)->Create(pRealWMIObject);
  183. else
  184. hr = E_FAIL; // TBD memory error
  185. }
  186. return hr;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // The constructor/destructor are really straight forward.
  190. //-----------------------------------------------------------------------------
  191. CWMILiveObject::CWMILiveObject() : m_pObject(NULL)
  192. {
  193. }
  194. CWMILiveObject::~CWMILiveObject()
  195. {
  196. if (m_pObject != NULL)
  197. {
  198. m_pObject->Release();
  199. m_pObject = NULL;
  200. }
  201. }
  202. //-----------------------------------------------------------------------------
  203. // The Create functions will either create the object from a WMI object, or
  204. // from a service pointer and a path.
  205. //-----------------------------------------------------------------------------
  206. HRESULT CWMILiveObject::Create(IWbemClassObject * pObject)
  207. {
  208. ASSERT(pObject && "calling CWMILiveObject::Create with a null object");
  209. if (m_pObject != NULL)
  210. {
  211. ASSERT(0 && "calling create on an already created CWMILiveObject");
  212. m_pObject->Release();
  213. }
  214. m_pObject = pObject;
  215. if (m_pObject)
  216. m_pObject->AddRef();
  217. return S_OK;
  218. }
  219. HRESULT CWMILiveObject::Create(IWbemServices * pServices, LPCTSTR szObjectPath)
  220. {
  221. ASSERT(pServices && szObjectPath);
  222. if (m_pObject != NULL)
  223. {
  224. ASSERT(0 && "calling create on an already created CWMILiveObject");
  225. m_pObject->Release();
  226. m_pObject = NULL; // must be NULL or GetObject bitches
  227. }
  228. #ifdef UNICODE
  229. BSTR bstrPath = SysAllocString(szObjectPath);
  230. #else
  231. USES_CONVERSION;
  232. LPOLESTR szWidePath = T2OLE(szObjectPath);
  233. BSTR bstrPath = SysAllocString(szWidePath);
  234. #endif
  235. HRESULT hr;
  236. if (bstrPath)
  237. {
  238. hr = pServices->GetObject(bstrPath, 0L, NULL, &m_pObject, NULL);
  239. SysFreeString(bstrPath);
  240. }
  241. else
  242. hr = E_FAIL;
  243. return hr;
  244. }
  245. //-----------------------------------------------------------------------------
  246. // The simple GetValue returns the named value as a variant.
  247. //
  248. // The pointer to an existing uninitialized VARIANT structure that receives
  249. // the property value, if found. Because this is an output parameter, this
  250. // method calls VariantInit on this VARIANT, so you must be sure that this
  251. // is not pointing to an active VARIANT.
  252. //
  253. // Note: You must call VariantClear on the returned VARIANT when its value
  254. // is no longer required. This will prevent memory leaks in the client process.
  255. //-----------------------------------------------------------------------------
  256. HRESULT CWMILiveObject::GetValue(LPCTSTR szProperty, VARIANT * pvarValue)
  257. {
  258. ASSERT(szProperty && pvarValue);
  259. if (m_pObject == NULL)
  260. {
  261. ASSERT(0 && "CWMILiveObject::GetValue called on a null object");
  262. return E_FAIL;
  263. }
  264. #ifdef UNICODE
  265. BSTR bstrProperty = SysAllocString(szProperty);
  266. #else
  267. USES_CONVERSION;
  268. LPOLESTR szWideProperty = T2OLE(szProperty);
  269. BSTR bstrProperty = SysAllocString(szWideProperty);
  270. #endif
  271. HRESULT hr;
  272. if (bstrProperty)
  273. {
  274. hr = pObject->Get(bstrProperty, 0L, pvarValue, NULL, NULL);
  275. SysFreeString(bstrProperty);
  276. if (FAILED(hr))
  277. hr = E_MSINFO_NOPROPERTY;
  278. }
  279. else
  280. hr = E_FAIL;
  281. return hr;
  282. }
  283. //-----------------------------------------------------------------------------
  284. // Get the named value as a string.
  285. //-----------------------------------------------------------------------------
  286. HRESULT CWMILiveObject::GetValueString(LPCTSTR szProperty, LPTSTR * pszValue)
  287. {
  288. VARIANT variant;
  289. HRESULT hr = GetValue(szProperty, &variant);
  290. if (SUCCEEDED(hr))
  291. {
  292. // If the property we just got is an array, we should convert it to string
  293. // containing a list of the items in the array.
  294. if ((variant.vt & VT_ARRAY) && (variant.vt & VT_BSTR) && variant.parray)
  295. {
  296. if (SafeArrayGetDim(variant.parray) == 1)
  297. {
  298. long lLower = 0, lUpper = 0;
  299. SafeArrayGetLBound(variant.parray, 0, &lLower);
  300. SafeArrayGetUBound(variant.parray, 0, &lUpper);
  301. CString strWorking;
  302. BSTR bstr = NULL;
  303. for (long i = lLower; i <= lUpper; i++)
  304. if (SUCCEEDED(SafeArrayGetElement(variant.parray, &i, (wchar_t*)&bstr)))
  305. {
  306. if (i != lLower)
  307. strWorking += _T(", ");
  308. strWorking += bstr;
  309. }
  310. *pstrValue = strWorking;
  311. }
  312. }
  313. else if (VariantChangeType(&variant, &variant, 0, VT_BSTR) == S_OK)
  314. {
  315. *pstrValue = V_BSTR(&variant);
  316. }
  317. else
  318. {
  319. hr = E_MSINFO_NOVALUE;
  320. }
  321. }
  322. return hr;
  323. }
  324. HRESULT CWMILiveObject::GetValueDWORD(LPCTSTR szProperty, DWORD * pdwValue)
  325. {
  326. return E_FAIL;
  327. }
  328. HRESULT CWMILiveObject::GetValueTime(LPCTSTR szProperty, SYSTEMTIME * psystimeValue)
  329. {
  330. return E_FAIL;
  331. }
  332. HRESULT CWMILiveObject::GetValueDoubleFloat(LPCTSTR szProperty, double * pdblValue)
  333. {
  334. return E_FAIL;
  335. }
  336. HRESULT CWMILiveObject::GetValueValueMap(LPCTSTR szProperty, LPTSTR * pszValue)
  337. {
  338. return E_FAIL;
  339. }
  340. #endif