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.

643 lines
20 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. smtprov.cpp
  5. Abstract:
  6. This object is used to store the list of all current
  7. trace providers in the system.
  8. --*/
  9. #include "Stdafx.h"
  10. #include <wbemidl.h>
  11. #include <initguid.h>
  12. #include <wmistr.h>
  13. #include <evntrace.h>
  14. #include "smtracsv.h"
  15. #include "smtprov.h"
  16. USE_HANDLE_MACROS("SMLOGCFG(smtprov.cpp)");
  17. #define WIN32_FROM_HRESULT(x)((x) & 0x0000FFFF)
  18. LPCWSTR CSmTraceProviders::m_cszBackslash = TEXT ( "\\" );
  19. LPCWSTR CSmTraceProviders::m_cszKernelLogger = TEXT ( "NT Kernel Logger" );
  20. LPCWSTR CSmTraceProviders::m_cszDefaultNamespace = TEXT ( "root\\wmi" );
  21. LPCWSTR CSmTraceProviders::m_cszTraceProviderClass = TEXT ( "EventTrace" );
  22. LPCWSTR CSmTraceProviders::m_cszRegisteredGuidsClass = TEXT ( "RegisteredGuids" );
  23. LPCWSTR CSmTraceProviders::m_cszDescription = TEXT ( "Description" );
  24. LPCWSTR CSmTraceProviders::m_cszGuid = TEXT ( "Guid" );
  25. //
  26. // Constructor
  27. CSmTraceProviders::CSmTraceProviders ( CSmTraceLogService* pSvc )
  28. : m_pWbemServices ( NULL ),
  29. m_pTraceLogService ( pSvc ),
  30. m_iBootState ( -1 )
  31. {
  32. m_KernelTraceProvider.strDescription = _T("");
  33. m_KernelTraceProvider.strGuid = _T("");
  34. return;
  35. }
  36. //
  37. // Destructor
  38. CSmTraceProviders::~CSmTraceProviders ( )
  39. {
  40. ASSERT ( 0 == (INT)m_arrGenTraceProvider.GetSize ( ) );
  41. m_arrGenTraceProvider.RemoveAll ( );
  42. return;
  43. }
  44. //
  45. // Open function. Initialize provider array from Wbem.
  46. //
  47. DWORD
  48. CSmTraceProviders::Open ( const CString& rstrMachineName )
  49. {
  50. DWORD dwStatus = ERROR_SUCCESS;
  51. DWORD dwLength;
  52. CString strTemp;
  53. MFC_TRY
  54. if ( !rstrMachineName.IsEmpty ( ) ) {
  55. m_strMachineName = rstrMachineName;
  56. if ( 0 != lstrcmpi ( m_cszBackslash, m_strMachineName.Left(1) ) ) {
  57. strTemp = m_cszBackslash;
  58. strTemp += m_cszBackslash;
  59. m_strMachineName = strTemp + m_strMachineName;
  60. }
  61. } else {
  62. // get the local machine name & default name space if the caller
  63. // has passed in a NULL machine name
  64. dwLength = MAX_COMPUTERNAME_LENGTH + 1;
  65. if ( GetComputerName (
  66. m_strMachineName.GetBufferSetLength( dwLength ),
  67. &dwLength ) ) {
  68. m_strMachineName.ReleaseBuffer();
  69. strTemp = m_cszBackslash;
  70. strTemp += m_cszBackslash;
  71. m_strMachineName = strTemp + m_strMachineName;
  72. } else {
  73. dwStatus = GetLastError();
  74. m_strMachineName.ReleaseBuffer();
  75. }
  76. }
  77. MFC_CATCH_DWSTATUS
  78. if ( ERROR_SUCCESS != dwStatus ) {
  79. m_strMachineName.Empty();
  80. }
  81. return dwStatus;
  82. }
  83. //
  84. // Close Function
  85. // Frees allocated memory
  86. //
  87. DWORD
  88. CSmTraceProviders::Close ( )
  89. {
  90. DWORD dwStatus = ERROR_SUCCESS;
  91. m_arrGenTraceProvider.RemoveAll ( );
  92. if ( NULL != m_pWbemServices ) {
  93. m_pWbemServices->Release ( );
  94. m_pWbemServices = NULL;
  95. }
  96. return dwStatus;
  97. }
  98. //
  99. // AddProvider
  100. // Add the specified provider strings to the array
  101. //
  102. DWORD
  103. CSmTraceProviders::AddProvider (
  104. const CString& rstrDescription,
  105. const CString& rstrGuid,
  106. INT iIsEnabled,
  107. INT iIsActive )
  108. {
  109. DWORD dwStatus = ERROR_SUCCESS;
  110. SLQ_TRACE_PROVIDER slqTProv;
  111. // If inactive, cannot be enabled.
  112. ASSERT ( ( 0 == iIsActive ) ? ( 0 == iIsEnabled ) : TRUE );
  113. MFC_TRY
  114. slqTProv.strDescription = rstrDescription;
  115. slqTProv.strGuid = rstrGuid;
  116. slqTProv.iIsEnabled = iIsEnabled;
  117. slqTProv.iIsActive = iIsActive;
  118. m_arrGenTraceProvider.Add( slqTProv );
  119. MFC_CATCH_DWSTATUS
  120. return dwStatus;
  121. }
  122. //
  123. // ConnectToServer
  124. // Connects to the Wbem server.
  125. //
  126. HRESULT
  127. CSmTraceProviders::ConnectToServer ( void )
  128. {
  129. HRESULT hr = NOERROR;
  130. if ( NULL == m_pWbemServices ) {
  131. IWbemLocator *pWbemLocator = NULL;
  132. IWbemServices *pWbemServices = NULL;
  133. // connect to locator
  134. hr = CoCreateInstance (
  135. CLSID_WbemLocator,
  136. 0,
  137. CLSCTX_INPROC_SERVER,
  138. IID_IWbemLocator,
  139. ( LPVOID * )&pWbemLocator );
  140. if ( SUCCEEDED (hr) ) {
  141. BSTR bstrTemp = NULL;
  142. CString strNamespace;
  143. MFC_TRY
  144. strNamespace = m_strMachineName;
  145. strNamespace += m_cszBackslash;
  146. strNamespace += m_cszDefaultNamespace;
  147. bstrTemp = strNamespace.AllocSysString();
  148. MFC_CATCH_HR
  149. if ( SUCCEEDED ( hr ) ) {
  150. // try to connect to the service
  151. hr = pWbemLocator->ConnectServer (
  152. bstrTemp,
  153. NULL,
  154. NULL,
  155. 0,
  156. 0L,
  157. 0,
  158. 0,
  159. &pWbemServices );
  160. ::SysFreeString ( bstrTemp );
  161. }
  162. if ( SUCCEEDED ( hr ) ) {
  163. hr = CoSetProxyBlanket((IUnknown*)pWbemServices,
  164. RPC_C_AUTHN_WINNT,
  165. RPC_C_AUTHZ_NONE,
  166. NULL,
  167. RPC_C_AUTHN_LEVEL_PKT,
  168. RPC_C_IMP_LEVEL_IMPERSONATE,
  169. NULL,
  170. EOAC_NONE);
  171. }
  172. // free the locator
  173. pWbemLocator->Release ( );
  174. }
  175. if ( SUCCEEDED ( hr ) ) {
  176. m_pWbemServices = pWbemServices;
  177. }
  178. }
  179. return hr;
  180. }
  181. //
  182. // GetBootState
  183. // Connects to the registry.
  184. //
  185. HRESULT
  186. CSmTraceProviders::GetBootState ( INT& riBootState )
  187. {
  188. HRESULT hr = NOERROR;
  189. if ( -1 == m_iBootState ) {
  190. HKEY hKeyMachine;
  191. ASSERT ( NULL != m_pTraceLogService );
  192. hKeyMachine = m_pTraceLogService->GetMachineKey ( );
  193. if ( NULL != hKeyMachine ) {
  194. HKEY hKeyOption;
  195. DWORD dwStatus = ERROR_SUCCESS;
  196. dwStatus = RegOpenKeyEx (
  197. hKeyMachine,
  198. (LPCWSTR)L"System\\CurrentControlSet\\Control\\Safeboot\\Option",
  199. 0,
  200. KEY_READ,
  201. &hKeyOption );
  202. // The Option key and OptionValue value only exist if booting in
  203. // safe mode, so failure indicates Normal mode (0).
  204. // Safe mode = 1, Safe mode with network = 2.
  205. if ( ERROR_SUCCESS ) {
  206. DWORD dwType = 0;
  207. DWORD dwBufSize = sizeof (INT );
  208. dwStatus = RegQueryValueExW (
  209. hKeyOption,
  210. L"OptionValue",
  211. NULL,
  212. &dwType,
  213. (LPBYTE)&m_iBootState,
  214. &dwBufSize);
  215. if ( ERROR_SUCCESS != dwStatus ) {
  216. // Normal mode
  217. m_iBootState = 0;
  218. }
  219. } else {
  220. // Normal mode
  221. m_iBootState = 0;
  222. }
  223. } else {
  224. // Unable to access registry
  225. hr = E_FAIL;
  226. }
  227. }
  228. riBootState = m_iBootState;
  229. return hr;
  230. }
  231. //
  232. // SyncWithConfiguration
  233. // Reads the current list of providers from Wbem
  234. // and reloads the internal values to match
  235. //
  236. HRESULT
  237. CSmTraceProviders::SyncWithConfiguration ( void )
  238. {
  239. IEnumWbemClassObject *pEnumProviders = NULL;
  240. IEnumWbemClassObject *pEnumRegGuids = NULL;
  241. CString strDescription;
  242. CString strGuid;
  243. CString strBracketedGuid;
  244. IWbemClassObject* pRegisteredGuid = NULL;
  245. BSTR bstrTemp;
  246. INT iIndex;
  247. CArray<PREGISTERED_GUID_DATA, PREGISTERED_GUID_DATA&> arrRegisteredGuids;
  248. INT iIsEnabled =0;
  249. HRESULT hr;
  250. m_arrGenTraceProvider.RemoveAll ( );
  251. hr = ConnectToServer( );
  252. //If Connection Succeeded
  253. if ( SUCCEEDED ( hr ) ) {
  254. //Get the Registered Guids (Up to date Data) from Wbem.
  255. MFC_TRY
  256. bstrTemp = SysAllocString(m_cszRegisteredGuidsClass);
  257. hr = m_pWbemServices->CreateInstanceEnum (
  258. bstrTemp,
  259. WBEM_FLAG_SHALLOW|WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  260. NULL,
  261. &pEnumRegGuids );
  262. ::SysFreeString ( bstrTemp );
  263. MFC_CATCH_HR
  264. if ( SUCCEEDED ( hr ) ) {
  265. ULONG uReturned = 1;
  266. while(uReturned == 1)
  267. {
  268. pRegisteredGuid = NULL;
  269. //---------------------------
  270. // enumerate through the resultset.
  271. hr = pEnumRegGuids->Next(
  272. 2000, // timeout in two seconds
  273. 1, // return just one instance
  274. &pRegisteredGuid, // pointer to Registered Guid
  275. &uReturned); // number obtained: one or zero
  276. if ( SUCCEEDED(hr) && ( 1 == uReturned ))
  277. {
  278. VARIANT vValue ;
  279. // Get the "GuidType" system property.
  280. MFC_TRY
  281. bstrTemp = SysAllocString(L"GuidType");
  282. VariantInit ( &vValue );
  283. vValue.vt = VT_I4;
  284. hr = pRegisteredGuid->Get(
  285. bstrTemp, // property name
  286. 0L,
  287. &vValue, // output to this variant
  288. NULL,
  289. NULL);
  290. ::SysFreeString ( bstrTemp );
  291. MFC_CATCH_HR
  292. // Filter on GuidType == 0
  293. if (SUCCEEDED(hr) && (0 == vValue.iVal)){
  294. CString strProvider;
  295. // Get the "InstanceName" system property.
  296. MFC_TRY
  297. bstrTemp = SysAllocString(L"InstanceName");
  298. VariantClear ( &vValue );
  299. vValue.vt = VT_BSTR;
  300. hr = pRegisteredGuid->Get(
  301. bstrTemp, // property name
  302. 0L,
  303. &vValue, // output to this variant
  304. NULL,
  305. NULL);
  306. ::SysFreeString ( bstrTemp );
  307. MFC_CATCH_HR
  308. if (SUCCEEDED(hr)){
  309. MFC_TRY
  310. strProvider = ( LPWSTR )V_BSTR (&vValue);
  311. bstrTemp = SysAllocString(L"IsEnabled");
  312. VariantInit(&vValue);
  313. vValue.vt = VT_BOOL;
  314. hr = pRegisteredGuid->Get(
  315. bstrTemp, // property name
  316. 0L,
  317. &vValue, // output to this variant
  318. NULL,
  319. NULL);
  320. ::SysFreeString ( bstrTemp );
  321. MFC_CATCH_HR
  322. }
  323. if ( SUCCEEDED(hr) ) {
  324. PREGISTERED_GUID_DATA pRegGuidData = NULL;
  325. iIsEnabled = vValue.boolVal ? 1 : 0;
  326. MFC_TRY
  327. pRegGuidData = new ( CRegisteredGuidData );
  328. pRegGuidData->m_strGuid = strProvider;
  329. pRegGuidData->m_iIsEnabled = iIsEnabled;
  330. arrRegisteredGuids.Add(pRegGuidData);
  331. MFC_CATCH_HR
  332. }
  333. }
  334. VariantClear(&vValue);
  335. pRegisteredGuid->Release();
  336. }
  337. } // end while
  338. }
  339. }
  340. //If Connection succeeded and registered Guids gathered.
  341. if ( SUCCEEDED ( hr ) ) {
  342. // Create an enumerator of the Trace Provider class
  343. MFC_TRY
  344. bstrTemp = SysAllocString(m_cszTraceProviderClass);
  345. hr = m_pWbemServices->CreateClassEnum (
  346. bstrTemp,
  347. WBEM_FLAG_SHALLOW|WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  348. NULL,
  349. &pEnumProviders );
  350. ::SysFreeString ( bstrTemp );
  351. MFC_CATCH_HR
  352. if ( SUCCEEDED ( hr ) ) {
  353. BSTR bsDescription = NULL;
  354. BSTR bsGuid = NULL;
  355. VARIANT vValue;
  356. DWORD dwRtnCount;
  357. IWbemQualifierSet *pQualSet = NULL;
  358. IWbemClassObject *pThisClass = NULL;
  359. WCHAR szSystemTraceControlGuid[39];
  360. ULONG Status;
  361. VariantInit ( &vValue );
  362. ZeroMemory ( szSystemTraceControlGuid, sizeof ( szSystemTraceControlGuid ) );
  363. ::StringFromGUID2( SystemTraceControlGuid, szSystemTraceControlGuid, 39);
  364. MFC_TRY
  365. bsDescription = SysAllocString(m_cszDescription);
  366. bsGuid = SysAllocString(m_cszGuid);
  367. MFC_CATCH_HR
  368. if ( SUCCEEDED ( hr ) ) {
  369. iIsEnabled = 0;
  370. while ( SUCCEEDED ( hr ) ) {
  371. hr = pEnumProviders->Next (
  372. 0, // timeout
  373. 1, // return only 1 object
  374. &pThisClass,
  375. &dwRtnCount );
  376. if ( SUCCEEDED ( hr ) ) {
  377. // no more classes
  378. if ( dwRtnCount == 0 ) break;
  379. pThisClass->GetQualifierSet ( &pQualSet );
  380. if ( pQualSet != NULL ) {
  381. hr = pQualSet->Get ( bsGuid, 0, &vValue, 0 );
  382. if ( SUCCEEDED ( hr ) ) {
  383. strGuid = ( LPWSTR )V_BSTR ( &vValue );
  384. VariantClear ( &vValue );
  385. hr = pQualSet->Get ( bsDescription, 0, &vValue, 0 );
  386. if ( SUCCEEDED ( hr ) ) {
  387. strDescription = ( LPWSTR )V_BSTR ( &vValue );
  388. VariantClear ( &vValue );
  389. }else{
  390. hr = ERROR_SUCCESS;
  391. strDescription = strGuid;
  392. }
  393. }
  394. pQualSet->Release();
  395. }
  396. // The Win2000 Kernel trace provider is handled separately.
  397. if ( SUCCEEDED ( hr ) ) {
  398. MFC_TRY
  399. if ( L'{' != strGuid[0] ) {
  400. strBracketedGuid.Format ( L"{%s}", strGuid );
  401. } else {
  402. strBracketedGuid = strGuid;
  403. }
  404. MFC_CATCH_HR
  405. if ( 0 == strBracketedGuid.CompareNoCase( szSystemTraceControlGuid ) ) {
  406. EVENT_TRACE_PROPERTIES LoggerInfo;
  407. TRACEHANDLE LoggerHandle = 0;
  408. TCHAR szLoggerName[MAX_PATH];
  409. TCHAR szLogFileName[MAX_PATH];
  410. // Kernel trace provider. Need to pass GUID as name.
  411. MFC_TRY
  412. ZeroMemory ( &LoggerInfo, sizeof ( LoggerInfo ) );
  413. LoggerInfo.Wnode.BufferSize = sizeof( LoggerInfo );
  414. LoggerInfo.Wnode.Flags = WNODE_FLAG_TRACED_GUID;
  415. szLoggerName[0] = 0;
  416. szLogFileName[0] = 0;
  417. LoggerInfo.Wnode.Guid = SystemTraceControlGuid;
  418. Status = QueryTrace(LoggerHandle, m_cszKernelLogger, &LoggerInfo);
  419. iIsEnabled = (Status == 0) ? 1 : 0;
  420. m_KernelTraceProvider.strDescription = strDescription;
  421. m_KernelTraceProvider.strGuid = strBracketedGuid;
  422. m_KernelTraceProvider.iIsEnabled = iIsEnabled;
  423. m_KernelTraceProvider.iIsActive = 1;
  424. MFC_CATCH_HR
  425. } else {
  426. //loop on all the registered guids
  427. INT iIsActive = 0;
  428. for (iIndex = 0 ; iIndex < (INT)arrRegisteredGuids.GetSize(); iIndex ++){
  429. if (0 == strGuid.CompareNoCase((LPCTSTR)(arrRegisteredGuids[iIndex]->m_strGuid))){
  430. DWORD dwStatus;
  431. iIsActive = 1;
  432. dwStatus = AddProvider (
  433. strDescription,
  434. strBracketedGuid,
  435. arrRegisteredGuids[iIndex]->m_iIsEnabled,
  436. iIsActive );
  437. if ( ERROR_OUTOFMEMORY == dwStatus ) {
  438. hr = E_OUTOFMEMORY;
  439. } else if ( ERROR_SUCCESS != dwStatus ) {
  440. hr = E_FAIL;
  441. }
  442. break;
  443. }
  444. }
  445. if ( 0 == iIsActive ) {
  446. DWORD dwStatus;
  447. dwStatus = AddProvider (
  448. strDescription,
  449. strBracketedGuid,
  450. 0,
  451. iIsActive );
  452. if ( ERROR_OUTOFMEMORY == dwStatus ) {
  453. hr = E_OUTOFMEMORY;
  454. } else if ( ERROR_SUCCESS != dwStatus ) {
  455. hr = E_FAIL;
  456. }
  457. }
  458. }
  459. }
  460. pThisClass->Release ( );
  461. }
  462. }
  463. ::SysFreeString ( bsGuid );
  464. ::SysFreeString ( bsDescription );
  465. }
  466. }
  467. }
  468. for (iIndex = 0 ; iIndex < (INT)arrRegisteredGuids.GetSize(); iIndex ++){
  469. delete arrRegisteredGuids[iIndex];
  470. }
  471. arrRegisteredGuids.RemoveAll ( );
  472. // Done with these objects.
  473. if ( NULL != pEnumProviders ) {
  474. pEnumProviders->Release ( );
  475. }
  476. if ( NULL != pEnumRegGuids ) {
  477. pEnumRegGuids->Release ( );
  478. }
  479. return hr;
  480. }
  481. //
  482. // Get specified provider in provider list
  483. //
  484. SLQ_TRACE_PROVIDER*
  485. CSmTraceProviders::GetProviderInfo ( INT iIndex )
  486. {
  487. return &m_arrGenTraceProvider[iIndex];
  488. }
  489. //
  490. // Return a pointer to the Kernel provider.
  491. //
  492. SLQ_TRACE_PROVIDER*
  493. CSmTraceProviders::GetKernelProviderInfo ( void )
  494. {
  495. return &m_KernelTraceProvider;
  496. }
  497. //
  498. // Return the index of the provider specified by Guid
  499. //
  500. INT
  501. CSmTraceProviders::IndexFromGuid ( const CString& rstrGuid )
  502. {
  503. int iIndex;
  504. int iCount = (INT)m_arrGenTraceProvider.GetSize ( );
  505. for ( iIndex = 0; iIndex < iCount; iIndex++ ) {
  506. if ( 0 == m_arrGenTraceProvider[iIndex].strGuid.CompareNoCase( rstrGuid ) ) {
  507. break;
  508. }
  509. }
  510. // Signal not found with -1.
  511. if ( iIndex == iCount ) {
  512. iIndex = -1;
  513. }
  514. return iIndex;
  515. }
  516. //
  517. // Get provider list count
  518. //
  519. INT
  520. CSmTraceProviders::GetGenProvCount ( )
  521. {
  522. return (INT)m_arrGenTraceProvider.GetSize ( );
  523. }