Leaked source code of windows server 2003
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.

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