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.

610 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000, Microsoft Corporation
  3. Module Name:
  4. dglogswmi.cpp
  5. Abstract:
  6. The file contains the methods for class CWmi. CWmi retrives information from WMI
  7. --*/
  8. #include "StdAfx.h"
  9. #include "WmiGateway.h"
  10. #include <wbemtime.h>
  11. /*++
  12. Routine Description
  13. The worker thread uses this function to check if the main thread has canceled the worker thread.
  14. i.e. the work thread should abort what ever it is doing, clean up and terminate.
  15. Arguments
  16. none
  17. Return Value
  18. TRUE the worker thread has been terminated
  19. FALSE the worker thread has not been terminated
  20. --*/
  21. inline BOOL CWmiGateway::ShouldTerminate()
  22. {
  23. if( m_bTerminate )
  24. {
  25. return TRUE;
  26. }
  27. if (WaitForSingleObject(m_hTerminateThread, 0) == WAIT_OBJECT_0)
  28. {
  29. m_bTerminate = FALSE;
  30. return TRUE;
  31. }
  32. else
  33. {
  34. return FALSE;
  35. }
  36. }
  37. CWmiGateway::CWmiGateway()
  38. /*++
  39. Routine Description
  40. Constructor, initializes member variables and creates the Wbem class object
  41. Arguments
  42. none
  43. Return Value
  44. none
  45. --*/
  46. {
  47. HRESULT hr = S_OK;
  48. m_wstrMachine = L".";
  49. m_pWbemLocater = NULL;
  50. }
  51. BOOL
  52. CWmiGateway::WbemInitialize(INTERFACE_TYPE bInterface)
  53. {
  54. HRESULT hr = E_FAIL;
  55. // Initialize COM
  56. //
  57. if( bInterface == COM_INTERFACE )
  58. {
  59. hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); //COINIT_APARTMENTTHREADED );
  60. }
  61. else if( bInterface == NETSH_INTERFACE )
  62. {
  63. hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); //COINIT_APARTMENTTHREADED );
  64. }
  65. if( FAILED(hr) ) // RPC_E_CHANGED_MODE
  66. {
  67. // Failed to initialize com
  68. //
  69. return E_FAIL;
  70. }
  71. // Create the WMI object
  72. //
  73. hr = CoCreateInstance(CLSID_WbemLocator,
  74. NULL,
  75. CLSCTX_INPROC_SERVER,
  76. IID_IWbemLocator,
  77. (void **)&m_pWbemLocater);
  78. if( FAILED(hr) )
  79. {
  80. m_pWbemLocater = NULL;
  81. return FALSE;
  82. }
  83. return TRUE;
  84. }
  85. VOID CWmiGateway::SetMachine(WCHAR *pszwMachine)
  86. {
  87. EmptyCache();
  88. m_wstrMachine = pszwMachine;
  89. }
  90. IWbemServices *
  91. CWmiGateway::GetWbemService(
  92. IN LPCTSTR pszwService
  93. )
  94. /*++
  95. Routine Description
  96. Connects to a Wbem Service (Repository i.e. root\default). The connection to the Wbem service
  97. is cached so if the Service is requested again, the service is retrived from the cache. When
  98. the class is destroyed the connection to the cached Wbem services is released.
  99. Arguments
  100. pszwService Wbem Service to connect to. (i.e. root\default)
  101. Return Value
  102. A pointer to the Wbem service connection.
  103. If the connection fails, the method returns NULL
  104. --*/
  105. {
  106. WbemServiceCache::iterator iter;
  107. IWbemServices *pWbemServices = NULL;
  108. //WCHAR szPath[MAX_PATH];
  109. _bstr_t bstrService;
  110. HRESULT hr;
  111. if( !m_pWbemLocater )
  112. {
  113. // Wbem class object was not created.
  114. //
  115. return NULL;
  116. }
  117. //wsprintf(szPath,L"\\\\%s%s", L"."/*m_wstrMachine.c_str()*/, pszwService); //L"\\\\%s%s", /*m_wstrMachine.c_str()*/L".\\", pszwService );
  118. //MessageBox(NULL,szPath,NULL,MB_OK);
  119. // Check if the wbem service is cached.
  120. //
  121. iter = m_WbemServiceCache.find(pszwService);
  122. if( iter == m_WbemServiceCache.end() )
  123. {
  124. // We did not create and cache the wbem service yet, do it now
  125. //
  126. hr = m_pWbemLocater->ConnectServer(_bstr_t(pszwService),
  127. NULL, // User name
  128. NULL, // user password
  129. NULL,NULL,NULL,NULL,
  130. &pWbemServices);
  131. if( SUCCEEDED(hr) )
  132. {
  133. // Set the authentication information for the WbemService
  134. //
  135. hr = CoSetProxyBlanket(pWbemServices,
  136. RPC_C_AUTHN_WINNT,
  137. RPC_C_AUTHZ_NONE,
  138. NULL,
  139. RPC_C_AUTHN_LEVEL_CALL,
  140. RPC_C_IMP_LEVEL_IMPERSONATE,
  141. NULL,
  142. EOAC_NONE);
  143. if( SUCCEEDED(hr) )
  144. {
  145. // Cache the newly created WbemService
  146. //
  147. m_WbemServiceCache[pszwService] = pWbemServices;
  148. }
  149. else
  150. {
  151. // Failed to set the proxy blankey on the service, release the wbem service
  152. //
  153. pWbemServices->Release();
  154. pWbemServices = NULL;
  155. }
  156. }
  157. return pWbemServices;
  158. }
  159. // We found the requested WbemService in our cache, return it
  160. //
  161. return iter->second;
  162. }
  163. IEnumWbemClassObject *
  164. CWmiGateway::GetEnumWbemClassObject(
  165. IN LPCTSTR pszwService,
  166. IN LPCTSTR pszwNameSpace
  167. )
  168. /*++
  169. Routine Description
  170. Creates an IEnumWbemClassObject. The IEnumWbemClassObject contains all of the instance
  171. of a class object. This pointer is not chached, since the instances are a snap shot
  172. of WMI at the time the object is created. So if we reuse the class object the data
  173. will be out-of-date. The caller must release the created IEnumWbemClassObject
  174. (i.e. pEnumWbemClassObject->Release() );
  175. Arguments
  176. pszwService Wbem Service to connect to. (i.e. root\default)
  177. pszwNameSpace Wbem Name space to connect to. (i.e. NetDiagnostics, Win32_NetworkAdapterConfiguration)
  178. Return Value
  179. A pointer to the IEnumWbemClassObject.
  180. If the the class object can not be created, the method reurns NULL
  181. --*/
  182. {
  183. IWbemServices *pWbemServices = NULL;
  184. IEnumWbemClassObject *pEnumWbemClassObject = NULL;
  185. // Get the requested WbemService
  186. //
  187. pWbemServices = GetWbemService(pszwService);
  188. if( pWbemServices )
  189. {
  190. // Create the EnumWbemClassObject. No need to check the
  191. // return value. If this function fails pEnumWbemClassObject
  192. // will be NULL
  193. //
  194. (void)pWbemServices->CreateInstanceEnum(_bstr_t(pszwNameSpace),
  195. 0L,
  196. NULL,
  197. &pEnumWbemClassObject);
  198. }
  199. return pEnumWbemClassObject;
  200. }
  201. IWbemClassObject *
  202. CWmiGateway::GetWbemClassObject(
  203. LPCTSTR pszwService,
  204. LPCTSTR pszwNameSpace,
  205. const int nInstance)
  206. /*++
  207. Routine Description
  208. Creates an IWbemClassObject. The IWbemClassObject is an instance of the IEnumWbemClassObject
  209. This pointer is not chached, since the instance is a snap shot of WMI at the time the object
  210. is created. So if we reuse the class object the data will be out-of-date. The caller must release
  211. the IWbemClassObject (i.e. pWbemClassObject->Release() )
  212. Arguments
  213. pszwService Wbem Service to connect to. (i.e. root\default)
  214. pszwNameSpace Wbem Name space to connect to. (i.e. NetDiagnostics, Win32_NetworkAdapterConfiguration)
  215. nInstance The instance of IEnumWbemClassObject to retrive. Default is to grab the first instance (nInstance 0)
  216. Return Value
  217. A pointer to the IWbemClassObject
  218. If the class object can not be created, the method returns NULL.
  219. --*/
  220. {
  221. IEnumWbemClassObject *pEnumWbemClassObject = NULL;
  222. IWbemClassObject *pWbemClassObject = NULL;
  223. ULONG uReturned;
  224. HRESULT hr;
  225. // Get the EnumWbemClass object (Contains all of the instances)
  226. //
  227. pEnumWbemClassObject = GetEnumWbemClassObject(pszwService,pszwNameSpace);
  228. if( pEnumWbemClassObject )
  229. {
  230. // Jump to the nth instance
  231. //
  232. hr = pEnumWbemClassObject->Skip(WBEM_INFINITE, nInstance);
  233. if( WBEM_S_NO_ERROR == hr )
  234. {
  235. // Get the nth classobject (i.e. instance). If this call fails pWbemClassObject is NULL
  236. // Next grabs the instances you skipped to.
  237. //
  238. hr = pEnumWbemClassObject->Next(WBEM_INFINITE,
  239. 1,
  240. &pWbemClassObject,
  241. &uReturned);
  242. }
  243. // Release the IEnumWbemClassObject
  244. //
  245. pEnumWbemClassObject->Release();
  246. }
  247. return pWbemClassObject;
  248. }
  249. void CWmiGateway::ReleaseAll(IEnumWbemClassObject *pEnumWbemClassObject, IWbemClassObject *pWbemClassObject[], int nInstances)
  250. {
  251. if( pWbemClassObject )
  252. {
  253. for(ULONG i = 0; i < nInstances; i++)
  254. {
  255. if( pWbemClassObject[i] )
  256. {
  257. pWbemClassObject[i]->Release();
  258. pWbemClassObject[i] = NULL;
  259. }
  260. }
  261. }
  262. if( pEnumWbemClassObject )
  263. {
  264. pEnumWbemClassObject->Release();
  265. }
  266. }
  267. HRESULT
  268. CWmiGateway::GetWbemProperties(
  269. IN OUT EnumWbemProperty &EnumProp
  270. )
  271. {
  272. HRESULT hr = S_OK;
  273. EnumWbemProperty::iterator iter, iter2;
  274. IWbemServices *pWbemServices = NULL;
  275. IEnumWbemClassObject *pEnumWbemClassObject = NULL;
  276. IWbemClassObject *pWbemClassObject[100]; // = NULL;
  277. WCHAR pszwRepository[MAX_PATH * 80] = L"";
  278. WCHAR pszwNamespace[MAX_PATH * 80] = L"";
  279. ULONG nInstances = 0;
  280. m_wstrWbemError = L"";
  281. for( iter = EnumProp.begin(); iter != EnumProp.end(); iter++)
  282. {
  283. if( iter->pszwRepository && lstrcmpi(iter->pszwRepository,pszwRepository) != 0 )
  284. {
  285. if( pWbemServices )
  286. {
  287. pWbemServices->Release();
  288. pWbemServices = NULL;
  289. }
  290. lstrcpy(pszwRepository,iter->pszwRepository);
  291. lstrcpy(pszwNamespace, L"");
  292. pWbemServices = GetWbemService(pszwRepository);
  293. if( ShouldTerminate() ) goto End;
  294. if( !pWbemServices )
  295. {
  296. if( !m_wstrWbemError.empty() )
  297. {
  298. m_wstrWbemError += L";";
  299. }
  300. m_wstrWbemError += wstring(L"Unable to connect to WMI service '") + wstring(pszwRepository) + wstring(L"'");
  301. }
  302. }
  303. if( iter->pszwNamespace && lstrcmpi(pszwNamespace, iter->pszwNamespace) != 0 )
  304. {
  305. lstrcpy(pszwNamespace, iter->pszwNamespace);
  306. if( pWbemServices )
  307. {
  308. ReleaseAll(pEnumWbemClassObject,pWbemClassObject,nInstances);
  309. hr = pWbemServices->CreateInstanceEnum(_bstr_t(pszwNamespace),
  310. 0L,
  311. NULL,
  312. &pEnumWbemClassObject);
  313. if( SUCCEEDED(hr) )
  314. {
  315. hr = pEnumWbemClassObject->Next(WBEM_INFINITE,
  316. 100, // Get all of the instances
  317. pWbemClassObject,
  318. &nInstances);
  319. if( ShouldTerminate() ) goto End;
  320. if( SUCCEEDED(hr) )
  321. {
  322. for(ULONG i = 0; i< nInstances; i++)
  323. {
  324. (void)pWbemClassObject[i]->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  325. }
  326. }
  327. }
  328. else
  329. {
  330. if( !m_wstrWbemError.empty() )
  331. {
  332. m_wstrWbemError += L";";
  333. }
  334. m_wstrWbemError += wstring(L"Unable to connect to WMI namespace '") + wstring(pszwNamespace) + wstring(L"'");
  335. }
  336. }
  337. }
  338. if( pWbemClassObject && nInstances)
  339. {
  340. VARIANT vValue;
  341. VariantInit(&vValue);
  342. if( !iter->pszwName || lstrcmp(iter->pszwName,L"") == 0)
  343. {
  344. BSTR bstrFieldname;
  345. int nProperty = 0;
  346. CIMTYPE CimType;
  347. while( WBEM_S_NO_ERROR == pWbemClassObject[0]->Next(0,&bstrFieldname, NULL, &CimType, NULL) )
  348. {
  349. if( ShouldTerminate() ) goto End;
  350. if( lstrcmp((WCHAR *)bstrFieldname,L"OEMLogoBitmap")==0 ) continue;
  351. // Do not get arrays they are to did handles i.e. bitmaps
  352. //if( CimType == CIM_FLAG_ARRAY ) continue;
  353. if( nProperty == 0 )
  354. {
  355. iter->SetProperty((WCHAR *)bstrFieldname,0);
  356. iter2 = iter;
  357. iter2++;
  358. }
  359. else
  360. {
  361. if( iter2 == EnumProp.end() )
  362. {
  363. EnumProp.push_back(WbemProperty((WCHAR *)bstrFieldname,0,NULL,NULL));
  364. iter2 = EnumProp.end();
  365. }
  366. else
  367. {
  368. iter2 = EnumProp.insert(iter2,WbemProperty((WCHAR *)bstrFieldname,0,NULL,NULL));
  369. iter2++;
  370. }
  371. }
  372. SysFreeString(bstrFieldname);
  373. nProperty++;
  374. }
  375. }
  376. for(ULONG i = 0; i < nInstances; i++)
  377. {
  378. HRESULT hr;
  379. CIMTYPE vtType;
  380. hr = pWbemClassObject[i]->Get(iter->pszwName,0,&vValue,&vtType,NULL);
  381. if( ShouldTerminate() ) goto End;
  382. if( SUCCEEDED(hr) )
  383. {
  384. if( vValue.vt != VT_NULL && vtType == CIM_DATETIME && vValue.bstrVal!= NULL && lstrcmp((WCHAR *)vValue.bstrVal,L"")!=0 )
  385. {
  386. WBEMTime wt(vValue.bstrVal);
  387. WCHAR szBuff[MAX_PATH];
  388. WCHAR szwDateTime[MAX_PATH*2];
  389. SYSTEMTIME SysTime;
  390. if( wt.GetSYSTEMTIME(&SysTime) )
  391. {
  392. FILETIME FileTime, LocalFileTime;
  393. SYSTEMTIME UTCTIme, LocalTime;
  394. memcpy(&UTCTIme,&SysTime,sizeof(SYSTEMTIME));
  395. SystemTimeToFileTime(&UTCTIme,&FileTime);
  396. FileTimeToLocalFileTime(&FileTime, &LocalFileTime);
  397. FileTimeToSystemTime(&LocalFileTime, &LocalTime);
  398. memcpy(&SysTime,&LocalTime,sizeof(SYSTEMTIME));
  399. lstrcpy(szwDateTime,L"");
  400. if (0 != GetTimeFormat(LOCALE_USER_DEFAULT, //GetThreadLocale(),
  401. 0,
  402. &SysTime,
  403. NULL,
  404. szBuff,
  405. sizeof(szBuff)))
  406. {
  407. //vValue.bstrVal = szBuff;
  408. lstrcpy(szwDateTime,szBuff);
  409. }
  410. if (0 != GetDateFormat(LOCALE_USER_DEFAULT, //GetThreadLocale(),
  411. 0,
  412. &SysTime,
  413. NULL,
  414. szBuff,
  415. sizeof(szBuff)))
  416. {
  417. //vValue.bstrVal = szBuff;
  418. wsprintf(szwDateTime,L"%s %s",szwDateTime,szBuff);
  419. }
  420. //SysFreeString(vValue.bstrVal);
  421. VariantClear(&vValue);
  422. vValue.bstrVal = SysAllocString((WCHAR *)szwDateTime);
  423. vValue.vt = VT_BSTR;
  424. }
  425. }
  426. iter->Value.push_back(vValue);
  427. VariantClear(&vValue);
  428. }
  429. }
  430. }
  431. }
  432. End:
  433. ReleaseAll(pEnumWbemClassObject,pWbemClassObject,nInstances);
  434. return hr;
  435. }
  436. HRESULT
  437. CWmiGateway::GetWbemProperty(
  438. IN LPCTSTR pszwService,
  439. IN LPCTSTR pszwNameSpace,
  440. IN LPCTSTR pszwField,
  441. OUT _variant_t & vValue
  442. )
  443. {
  444. IWbemClassObject *pWbemClassObject;
  445. HRESULT hr = S_OK;
  446. pWbemClassObject = GetWbemClassObject(pszwService,pszwNameSpace);
  447. if( pWbemClassObject )
  448. {
  449. hr = pWbemClassObject->Get(pszwField,
  450. 0,
  451. &vValue,
  452. NULL,
  453. NULL);
  454. pWbemClassObject->Release();
  455. }
  456. return hr;
  457. }
  458. void CWmiGateway::EmptyCache()
  459. {
  460. // Empty the WbemService cache
  461. //
  462. //DebugBreak();
  463. m_WbemServiceCache.erase(m_WbemServiceCache.begin(),
  464. m_WbemServiceCache.end());
  465. }
  466. // Netsh does not free its helpers if it is aborted or the user runs netsh with /?
  467. // The Wbem object dissapears from under neath us. try and except do not work inside
  468. // of the destructor.
  469. //
  470. ReleaseWbemObject(IWbemLocator *p)
  471. {
  472. __try
  473. {
  474. p->Release();
  475. }
  476. __except(EXCEPTION_EXECUTE_HANDLER)
  477. {
  478. //DebugBreak();
  479. }
  480. return 0;
  481. }
  482. CWmiGateway::~CWmiGateway()
  483. /*++
  484. Routine Description
  485. Destructor, free all member variables and release the wbem connection
  486. Arguments
  487. none
  488. Return Value
  489. none
  490. --*/
  491. {
  492. //DebugBreak();
  493. EmptyCache();
  494. if( m_pWbemLocater )
  495. {
  496. ReleaseWbemObject(m_pWbemLocater);
  497. m_pWbemLocater = NULL;
  498. }
  499. CoUninitialize();
  500. }