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.

1660 lines
51 KiB

  1. /*++
  2. Copyright (C) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. smlogs.cpp
  5. Abstract:
  6. Implementation of the base class representing the
  7. Performance Logs and Alerts service.
  8. --*/
  9. #include "Stdafx.h"
  10. // Define the following to use the minimum of shlwapip.h
  11. #ifndef NO_SHLWAPI_PATH
  12. #define NO_SHLWAPI_PATH
  13. #endif
  14. #ifndef NO_SHLWAPI_REG
  15. #define NO_SHLWAPI_REG
  16. #endif
  17. #ifndef NO_SHLWAPI_UALSTR
  18. #define NO_SHLWAPI_UALSTR
  19. #endif
  20. #ifndef NO_SHLWAPI_STREAM
  21. #define NO_SHLWAPI_STREAM
  22. #endif
  23. #ifndef NO_SHLWAPI_HTTP
  24. #define NO_SHLWAPI_HTTP
  25. #endif
  26. #ifndef NO_SHLWAPI_INTERNAL
  27. #define NO_SHLWAPI_INTERNAL
  28. #endif
  29. #ifndef NO_SHLWAPI_GDI
  30. #define NO_SHLWAPI_GDI
  31. #endif
  32. #ifndef NO_SHLWAPI_UNITHUNK
  33. #define NO_SHLWAPI_UNITHUNK
  34. #endif
  35. #ifndef NO_SHLWAPI_TPS
  36. #define NO_SHLWAPI_TPS
  37. #endif
  38. #ifndef NO_SHLWAPI_MLUI
  39. #define NO_SHLWAPI_MLUI
  40. #endif
  41. #include <shlwapi.h> // For SHLoadIndirectString
  42. #include <shlwapip.h> // For SHLoadIndirectString
  43. #include <strsafe.h>
  44. #include <pdh.h> // For MIN_TIME_VALUE, MAX_TIME_VALUE
  45. #include <pdhp.h> // For pdhi methods
  46. #include <Wbemidl.h>
  47. #include "smlogres.h"
  48. #include "smcfgmsg.h"
  49. #include "smalrtq.h"
  50. #include "smctrqry.h"
  51. #include "smtraceq.h"
  52. #include "strnoloc.h"
  53. #include "smrootnd.h"
  54. #include "smlogs.h"
  55. USE_HANDLE_MACROS("SMLOGCFG(smlogs.cpp)");
  56. #define DEFAULT_LOG_FILE_FOLDER L"%SystemDrive%\\PerfLogs"
  57. //
  58. // Constructor
  59. CSmLogService::CSmLogService()
  60. : m_hKeyMachine ( NULL ),
  61. m_hKeyLogService ( NULL ),
  62. m_hKeyLogServiceRoot ( NULL ),
  63. m_bIsOpen ( FALSE ),
  64. m_bReadOnly ( FALSE ),
  65. m_bRefreshOnShow ( FALSE ),
  66. m_pRootNode ( NULL )
  67. {
  68. // String allocation errors are thrown, to be
  69. // captured by rootnode alloc exception handler
  70. m_QueryList.RemoveAll(); // initialize the list
  71. ZeroMemory(&m_OSVersion, sizeof(m_OSVersion));
  72. return;
  73. }
  74. //
  75. // Destructor
  76. CSmLogService::~CSmLogService()
  77. {
  78. // make sure Close method was called first!
  79. ASSERT ( NULL == m_QueryList.GetHeadPosition() );
  80. ASSERT ( NULL == m_hKeyMachine );
  81. ASSERT ( NULL == m_hKeyLogService );
  82. ASSERT ( NULL == m_hKeyLogServiceRoot );
  83. return;
  84. }
  85. PSLQUERY
  86. CSmLogService::CreateTypedQuery (
  87. const CString& rstrName,
  88. DWORD dwLogType )
  89. {
  90. HKEY hKeyQuery;
  91. PSLQUERY pNewLogQuery = NULL;
  92. DWORD dwStatus = ERROR_SUCCESS;
  93. DWORD dwDisposition;
  94. DWORD dwRegValue;
  95. UUID uuidNew;
  96. RPC_STATUS rpcStat = RPC_S_OK;
  97. LPWSTR pszUuid = NULL;
  98. INT iBufLen = rstrName.GetLength()+1;
  99. LPWSTR pszName = NULL;
  100. LPWSTR pStat = NULL;
  101. BOOL bDupFound = FALSE;
  102. CString strNewQueryName;
  103. CString strCollectionName;
  104. if (m_bReadOnly) {
  105. SetLastError (SMCFG_NO_MODIFY_ACCESS);
  106. return NULL; // unable to create without WRITE access
  107. } else {
  108. // Initialize to success status.
  109. SetLastError( dwStatus );
  110. }
  111. if ( OS_WIN2K != TargetOs()) {
  112. // For servers later than Windows2000, use a GUID as the key name for a query.
  113. rpcStat = UuidCreate( &uuidNew );
  114. if ( RPC_S_OK != rpcStat && RPC_S_UUID_LOCAL_ONLY != rpcStat ) {
  115. rpcStat = UuidCreateSequential ( &uuidNew );
  116. }
  117. if ( RPC_S_OK == rpcStat || RPC_S_UUID_LOCAL_ONLY == rpcStat ) {
  118. rpcStat = UuidToString ( &uuidNew, &pszUuid );
  119. if ( RPC_S_OK == rpcStat ) {
  120. ASSERT ( NULL != pszUuid );
  121. MFC_TRY
  122. strNewQueryName.Format ( L"{%s}", pszUuid );
  123. MFC_CATCH_DWSTATUS
  124. RpcStringFree ( &pszUuid );
  125. } else {
  126. dwStatus = rpcStat;
  127. }
  128. }
  129. // RPC_STATUS values in rpcnterr.h correspond to appropriate values.
  130. dwStatus = rpcStat;
  131. } else {
  132. // For Windows 2000, use query name as registry key name.
  133. MFC_TRY
  134. strNewQueryName = rstrName;
  135. MFC_CATCH_DWSTATUS
  136. }
  137. if ( ERROR_SUCCESS == dwStatus ) {
  138. // Query key name created
  139. // Create the query specified, checking for duplicate query by key name.
  140. dwStatus = RegCreateKeyExW (
  141. m_hKeyLogService,
  142. strNewQueryName,
  143. 0,
  144. NULL, 0,
  145. KEY_READ | KEY_WRITE,
  146. NULL,
  147. &hKeyQuery,
  148. &dwDisposition);
  149. if ( REG_OPENED_EXISTING_KEY == dwDisposition ) {
  150. dwStatus = SMCFG_DUP_QUERY_NAME;
  151. }
  152. }
  153. if ( ERROR_SUCCESS == dwStatus ) {
  154. // Initialize the current state value. After it is
  155. // initialized, it is only modified when:
  156. // 1) Set to Stopped or Started by the service
  157. // 2) Set to Start Pending by the config snapin.
  158. dwRegValue = SLQ_QUERY_STOPPED;
  159. dwStatus = RegSetValueEx (
  160. hKeyQuery,
  161. CGlobalString::m_cszRegCurrentState,
  162. 0L,
  163. REG_DWORD,
  164. (CONST BYTE *)&dwRegValue,
  165. sizeof(DWORD));
  166. if ( ERROR_SUCCESS == dwStatus ) {
  167. // Initialize the log type to "new" to indicate partially created logs
  168. dwRegValue = SLQ_NEW_LOG;
  169. dwStatus = RegSetValueEx (
  170. hKeyQuery,
  171. CGlobalString::m_cszRegLogType,
  172. 0L,
  173. REG_DWORD,
  174. (CONST BYTE *)&dwRegValue,
  175. sizeof(DWORD));
  176. }
  177. if ( ERROR_SUCCESS == dwStatus && (OS_WIN2K != TargetOs()) ) {
  178. // Initialize the collection name for post Windows 2000 systems
  179. MFC_TRY
  180. strCollectionName = rstrName;
  181. MFC_CATCH_DWSTATUS
  182. if ( ERROR_SUCCESS == dwStatus ) {
  183. dwStatus = RegSetValueEx (
  184. hKeyQuery,
  185. CGlobalString::m_cszRegCollectionName,
  186. 0L,
  187. REG_SZ,
  188. (CONST BYTE *)strCollectionName.GetBufferSetLength( strCollectionName.GetLength() ),
  189. strCollectionName.GetLength()*sizeof(WCHAR) );
  190. strCollectionName.ReleaseBuffer();
  191. }
  192. // For post Windows 2000 counters, search for duplicate by collection name.
  193. if ( ERROR_SUCCESS == dwStatus ) {
  194. dwStatus = FindDuplicateQuery ( rstrName, bDupFound );
  195. }
  196. }
  197. if ( ERROR_SUCCESS == dwStatus && !bDupFound ) {
  198. // create a new object and add it to the query list
  199. dwStatus = LoadSingleQuery (
  200. &pNewLogQuery,
  201. dwLogType,
  202. rstrName,
  203. strNewQueryName,
  204. hKeyQuery,
  205. TRUE );
  206. } else {
  207. if ( bDupFound ) {
  208. dwStatus = SMCFG_DUP_QUERY_NAME;
  209. }
  210. }
  211. }
  212. if ( ERROR_SUCCESS != dwStatus ) {
  213. // Delete also closes the registry key hKeyQuery.
  214. if ( !strNewQueryName.IsEmpty() ) {
  215. RegDeleteKeyW ( m_hKeyLogService, strNewQueryName );
  216. SetLastError ( dwStatus );
  217. }
  218. }
  219. return pNewLogQuery;
  220. }
  221. DWORD
  222. CSmLogService::UnloadSingleQuery (PSLQUERY pQuery)
  223. {
  224. DWORD dwStatus = ERROR_SUCCESS;
  225. PSLQUERY pLogQuery = NULL;
  226. POSITION listPos = NULL;
  227. BOOL bFoundEntry = FALSE;
  228. // find matching entry
  229. if (!m_QueryList.IsEmpty()) {
  230. listPos = m_QueryList.Find (pQuery, NULL);
  231. if ( NULL != listPos ) {
  232. pLogQuery = m_QueryList.GetAt(listPos);
  233. bFoundEntry = TRUE;
  234. }
  235. }
  236. if (bFoundEntry) {
  237. ASSERT ( NULL != listPos );
  238. // remove from list
  239. m_QueryList.RemoveAt (listPos);
  240. pLogQuery->Close();
  241. delete pLogQuery;
  242. } else {
  243. // not found
  244. dwStatus = ERROR_FILE_NOT_FOUND;
  245. }
  246. return dwStatus;
  247. }
  248. DWORD
  249. CSmLogService::DeleteQuery ( PSLQUERY pQuery )
  250. {
  251. PSLQUERY pLogQuery = NULL;
  252. DWORD dwStatus = ERROR_SUCCESS;
  253. POSITION listPos = NULL;
  254. BOOL bFoundEntry = FALSE;
  255. CString strLogKeyName;
  256. if (m_bReadOnly) {
  257. dwStatus = ERROR_ACCESS_DENIED;
  258. } else {
  259. // find matching entry
  260. if (!m_QueryList.IsEmpty()) {
  261. listPos = m_QueryList.Find (pQuery, NULL);
  262. if (listPos != NULL) {
  263. pLogQuery = m_QueryList.GetAt(listPos);
  264. bFoundEntry = TRUE;
  265. }
  266. }
  267. if (bFoundEntry) {
  268. ASSERT (listPos != NULL);
  269. MFC_TRY
  270. pLogQuery->GetLogKeyName( strLogKeyName );
  271. MFC_CATCH_DWSTATUS;
  272. if ( ERROR_SUCCESS == dwStatus ) {
  273. // remove from list
  274. m_QueryList.RemoveAt (listPos);
  275. pLogQuery->Close();
  276. // Delete in the registry
  277. RegDeleteKeyW ( m_hKeyLogService, strLogKeyName );
  278. delete pLogQuery;
  279. if ( NULL != GetRootNode() ) {
  280. GetRootNode()->UpdateServiceConfig();
  281. }
  282. }
  283. } else {
  284. // not found
  285. dwStatus = ERROR_FILE_NOT_FOUND;
  286. }
  287. }
  288. return dwStatus;
  289. }
  290. DWORD
  291. CSmLogService::DeleteQuery ( const CString& rstrName )
  292. {
  293. PSLQUERY pLogQuery = NULL;
  294. DWORD dwStatus = ERROR_SUCCESS;
  295. POSITION listPos;
  296. BOOL bFoundEntry = FALSE;
  297. if (m_bReadOnly) {
  298. dwStatus = ERROR_ACCESS_DENIED;
  299. } else {
  300. // find matching entry
  301. if (!m_QueryList.IsEmpty()) {
  302. listPos = m_QueryList.GetHeadPosition();
  303. while (listPos != NULL) {
  304. pLogQuery = m_QueryList.GetNext(listPos);
  305. if ( 0 == rstrName.CompareNoCase ( pLogQuery->GetLogName() ) ) {
  306. // match found so bail here
  307. bFoundEntry = TRUE;
  308. break;
  309. }
  310. }
  311. }
  312. if (bFoundEntry) {
  313. dwStatus = DeleteQuery ( pLogQuery );
  314. } else {
  315. // not found
  316. dwStatus = ERROR_FILE_NOT_FOUND;
  317. }
  318. }
  319. return dwStatus;
  320. }
  321. DWORD
  322. CSmLogService::LoadDefaultLogFileFolder ( void )
  323. {
  324. DWORD dwStatus = ERROR_SUCCESS;
  325. LPWSTR szLocalPath = NULL;
  326. WCHAR* szExpanded = NULL;
  327. INT cchLen;
  328. INT cchExpandedLen;
  329. DWORD dwBufferSize = 0;
  330. m_strDefaultLogFileFolder.Empty();
  331. if ( NULL != m_hKeyLogServiceRoot ) {
  332. dwStatus = CSmLogQuery::ReadRegistryStringValue (
  333. m_hKeyLogServiceRoot,
  334. (LPCWSTR)L"DefaultLogFileFolder",
  335. (LPCWSTR)L"DefaultLogFileFolder",
  336. NULL,
  337. &szLocalPath,
  338. &dwBufferSize );
  339. //
  340. // No message on error. If error, just load the default.
  341. //
  342. MFC_TRY
  343. if ( sizeof(WCHAR) >= dwBufferSize ) {
  344. ResourceStateManager rsm;
  345. CString strFolderName;
  346. strFolderName.LoadString ( IDS_DEFAULT_LOG_FILE_FOLDER );
  347. if ( NULL != szLocalPath ) {
  348. delete [] szLocalPath;
  349. szLocalPath = NULL;
  350. }
  351. szLocalPath = new WCHAR [strFolderName.GetLength() + 1];
  352. StringCchCopy ( szLocalPath, (strFolderName.GetLength() + 1), strFolderName );
  353. }
  354. if ( IsLocalMachine() ) {
  355. cchLen = 0;
  356. cchExpandedLen = 0;
  357. cchLen = ExpandEnvironmentStrings ( szLocalPath, NULL, 0 );
  358. if ( 0 < cchLen ) {
  359. szExpanded = new WCHAR[cchLen];
  360. cchExpandedLen = ExpandEnvironmentStrings (
  361. szLocalPath,
  362. szExpanded,
  363. cchLen );
  364. if ( 0 < cchExpandedLen ) {
  365. m_strDefaultLogFileFolder = szExpanded;
  366. } else {
  367. dwStatus = GetLastError();
  368. m_strDefaultLogFileFolder.Empty();
  369. }
  370. } else {
  371. dwStatus = GetLastError();
  372. }
  373. } else {
  374. m_strDefaultLogFileFolder = szLocalPath;
  375. }
  376. MFC_CATCH_DWSTATUS
  377. }
  378. if ( NULL != szLocalPath ) {
  379. delete [] szLocalPath;
  380. }
  381. if ( NULL != szExpanded ) {
  382. delete [] szExpanded;
  383. }
  384. return dwStatus;
  385. }
  386. DWORD
  387. CSmLogService::LoadSingleQuery (
  388. PSLQUERY* ppQuery,
  389. DWORD dwLogType,
  390. const CString& rstrName,
  391. const CString& rstrLogKeyName,
  392. HKEY hKeyQuery,
  393. BOOL bNew )
  394. {
  395. DWORD dwStatus = ERROR_SUCCESS;
  396. PSLQUERY pNewQuery = NULL;
  397. if ( NULL != ppQuery ) {
  398. *ppQuery = NULL;
  399. // create a new query object and add it to the query list
  400. MFC_TRY
  401. if ( SLQ_COUNTER_LOG == dwLogType ) {
  402. pNewQuery = new SLCTRQUERY ( this );
  403. } else if ( SLQ_TRACE_LOG == dwLogType ) {
  404. pNewQuery = new SLTRACEQUERY ( this );
  405. } else if ( SLQ_ALERT == dwLogType ) {
  406. pNewQuery = new SLALERTQUERY ( this );
  407. }
  408. MFC_CATCH_DWSTATUS
  409. if ( ERROR_SUCCESS == dwStatus && NULL != pNewQuery ) {
  410. pNewQuery->SetNew ( bNew );
  411. dwStatus = pNewQuery->Open(
  412. rstrName,
  413. hKeyQuery,
  414. m_bReadOnly );
  415. if ( ERROR_SUCCESS == dwStatus ) {
  416. dwStatus = pNewQuery->SetLogKeyName ( rstrLogKeyName );
  417. }
  418. if ( ERROR_SUCCESS == dwStatus ) {
  419. // then add it to the list
  420. MFC_TRY
  421. m_QueryList.AddHead ( pNewQuery );
  422. MFC_CATCH_DWSTATUS
  423. if ( ERROR_SUCCESS != dwStatus ) {
  424. // close this query object
  425. pNewQuery->Close();
  426. }
  427. }
  428. if ( ERROR_SUCCESS != dwStatus ) {
  429. // delete this query object
  430. delete pNewQuery;
  431. }
  432. }
  433. if ( ERROR_SUCCESS == dwStatus ) {
  434. *ppQuery = pNewQuery;
  435. }
  436. } else {
  437. dwStatus = ERROR_INVALID_PARAMETER;
  438. }
  439. return dwStatus;
  440. }
  441. DWORD
  442. CSmLogService::LoadQueries ( DWORD dwLogType )
  443. {
  444. DWORD dwStatus = ERROR_SUCCESS;
  445. DWORD dwQueryIndex = 0;
  446. LONG lEnumStatus = ERROR_SUCCESS;
  447. WCHAR szQueryKeyName[MAX_PATH + 1];
  448. DWORD dwQueryKeyNameLen;
  449. LPWSTR szCollectionName = NULL;
  450. UINT uiCollectionNameLen = 0;
  451. FILETIME ftLastWritten;
  452. HKEY hKeyQuery;
  453. PSLQUERY pNewLogQuery = NULL;
  454. DWORD dwType = 0;
  455. DWORD dwBufferSize = sizeof(DWORD);
  456. DWORD dwRegValue;
  457. CString strQueryName;
  458. // Load all queries for the specified registry key.
  459. // Enumerate the log names and create a new log object
  460. // for each one found.
  461. dwQueryKeyNameLen = sizeof ( szQueryKeyName ) / sizeof ( WCHAR );
  462. memset (szQueryKeyName, 0, sizeof (szQueryKeyName));
  463. while ( ERROR_SUCCESS == ( lEnumStatus = RegEnumKeyExW (
  464. m_hKeyLogService,
  465. dwQueryIndex,
  466. szQueryKeyName,
  467. &dwQueryKeyNameLen,
  468. NULL,
  469. NULL,
  470. NULL,
  471. &ftLastWritten ) ) ) {
  472. // open the query specified
  473. dwStatus = RegOpenKeyExW (
  474. m_hKeyLogService,
  475. szQueryKeyName,
  476. 0,
  477. (m_bReadOnly ? KEY_READ : KEY_READ | KEY_WRITE ),
  478. &hKeyQuery);
  479. if ( ERROR_SUCCESS == dwStatus ) {
  480. // create a new object and add it to the query list
  481. // Determine the log type.
  482. dwType = 0;
  483. dwStatus = RegQueryValueExW (
  484. hKeyQuery,
  485. CGlobalString::m_cszRegLogType,
  486. NULL,
  487. &dwType,
  488. (LPBYTE)&dwRegValue,
  489. &dwBufferSize );
  490. if ( ( ERROR_SUCCESS == dwStatus )
  491. && ( dwLogType == dwRegValue ) ) {
  492. dwStatus = CSmLogQuery::SmNoLocReadRegIndStrVal (
  493. hKeyQuery,
  494. IDS_REG_COLLECTION_NAME,
  495. NULL,
  496. &szCollectionName,
  497. &uiCollectionNameLen );
  498. MFC_TRY
  499. if ( ERROR_SUCCESS == dwStatus
  500. && NULL != szCollectionName ) {
  501. if ( 0 < lstrlen ( szCollectionName ) ) {
  502. strQueryName = szCollectionName;
  503. } else {
  504. strQueryName = szQueryKeyName;
  505. dwStatus = ERROR_SUCCESS;
  506. }
  507. } else {
  508. strQueryName = szQueryKeyName;
  509. dwStatus = ERROR_SUCCESS;
  510. }
  511. MFC_CATCH_DWSTATUS;
  512. if ( NULL != szCollectionName ) {
  513. G_FREE ( szCollectionName );
  514. szCollectionName = NULL;
  515. uiCollectionNameLen = 0;
  516. }
  517. if ( ERROR_SUCCESS == dwStatus ) {
  518. dwStatus = LoadSingleQuery (
  519. &pNewLogQuery,
  520. dwRegValue,
  521. strQueryName,
  522. szQueryKeyName,
  523. hKeyQuery,
  524. FALSE );
  525. if ( ERROR_SUCCESS != dwStatus ) {
  526. // Todo: Error message
  527. dwStatus = ERROR_SUCCESS;
  528. }
  529. }
  530. } else {
  531. // Try the next item in the list
  532. RegCloseKey (hKeyQuery);
  533. dwStatus = ERROR_SUCCESS;
  534. }
  535. }
  536. // set up for the next item in the list
  537. dwQueryKeyNameLen = sizeof (szQueryKeyName) / sizeof (szQueryKeyName[0]);
  538. memset (szQueryKeyName, 0, sizeof (szQueryKeyName));
  539. dwQueryIndex++;
  540. }
  541. return dwStatus;
  542. }
  543. //
  544. // Open function. Opens all existing log query entries.
  545. //
  546. DWORD
  547. CSmLogService::Open ( const CString& rstrMachineName)
  548. {
  549. DWORD dwStatus = ERROR_SUCCESS;
  550. // Initialize strings
  551. SetMachineName ( rstrMachineName );
  552. SetDisplayName ( m_strBaseName );
  553. if ( rstrMachineName.IsEmpty() ) {
  554. m_hKeyMachine = HKEY_LOCAL_MACHINE;
  555. } else {
  556. dwStatus = RegConnectRegistryW (
  557. rstrMachineName,
  558. HKEY_LOCAL_MACHINE,
  559. &m_hKeyMachine);
  560. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  561. dwStatus = SMCFG_NO_READ_ACCESS;
  562. }
  563. }
  564. if (dwStatus == ERROR_SUCCESS) {
  565. // open a read-only key to the registry root key for this service, to obtain
  566. // root-level values.
  567. dwStatus = RegOpenKeyExW (
  568. m_hKeyMachine,
  569. (LPCWSTR)L"SYSTEM\\CurrentControlSet\\Services\\SysmonLog",
  570. 0,
  571. KEY_READ,
  572. &m_hKeyLogServiceRoot);
  573. // No message on failure. Currently only affects default log file folder name.
  574. // open a key to the registry log queries key for this service
  575. dwStatus = RegOpenKeyExW (
  576. m_hKeyMachine,
  577. (LPCWSTR)L"SYSTEM\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
  578. 0,
  579. KEY_READ | KEY_WRITE,
  580. &m_hKeyLogService);
  581. if (dwStatus != ERROR_SUCCESS) {
  582. // unable to access the key for write access, so try read only
  583. dwStatus = RegOpenKeyExW (
  584. m_hKeyMachine,
  585. (LPCWSTR)L"SYSTEM\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
  586. 0,
  587. KEY_READ,
  588. &m_hKeyLogService);
  589. if (dwStatus != ERROR_SUCCESS) {
  590. // unable to open the key for read access so bail out
  591. // assume the service has not been installed
  592. // (though we should probably check first to make sure)
  593. m_hKeyLogService = NULL;
  594. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  595. dwStatus = SMCFG_NO_READ_ACCESS;
  596. }
  597. } else {
  598. // opened for read access so set the flag
  599. m_bReadOnly = TRUE;
  600. }
  601. }
  602. }
  603. // Install the service if necessary.
  604. if ( ( dwStatus != SMCFG_NO_READ_ACCESS ) ) {
  605. dwStatus = Install( rstrMachineName );
  606. }
  607. // Load all queries
  608. if ( ( dwStatus == ERROR_SUCCESS ) && ( NULL != m_hKeyLogService ) ) {
  609. dwStatus = LoadQueries();
  610. }
  611. if ( ERROR_SUCCESS == dwStatus ) {
  612. SetOpen ( TRUE );
  613. }
  614. return dwStatus;
  615. }
  616. DWORD
  617. CSmLogService::CheckForActiveQueries (PSLQUERY* ppActiveQuery)
  618. {
  619. DWORD dwStatus = ERROR_SUCCESS;
  620. PSLQUERY pQuery = NULL;
  621. POSITION Pos = m_QueryList.GetHeadPosition();
  622. while ( Pos != NULL) {
  623. pQuery = m_QueryList.GetNext( Pos );
  624. if ( NULL != pQuery->GetActivePropertySheet() ) {
  625. dwStatus = IDS_ERRMSG_REFRESH_OPEN_QUERY;
  626. if ( NULL != ppActiveQuery ) {
  627. *ppActiveQuery = pQuery;
  628. }
  629. break;
  630. }
  631. }
  632. return dwStatus;
  633. }
  634. DWORD
  635. CSmLogService::UnloadQueries (PSLQUERY* ppActiveQuery)
  636. {
  637. DWORD dwStatus = ERROR_SUCCESS;
  638. PSLQUERY pQuery = NULL;
  639. POSITION Pos = m_QueryList.GetHeadPosition();
  640. // Ensure that all property dialogs are closed before unloading queries.
  641. dwStatus = CheckForActiveQueries ( ppActiveQuery );
  642. if ( ERROR_SUCCESS == dwStatus ) {
  643. Pos = m_QueryList.GetHeadPosition();
  644. // Update each query in this service by walking down the list.
  645. while ( Pos != NULL) {
  646. pQuery = m_QueryList.GetNext( Pos );
  647. pQuery->Close();
  648. delete (pQuery);
  649. }
  650. // Empty the list now that everything has been closed;
  651. m_QueryList.RemoveAll();
  652. }
  653. return dwStatus;
  654. }
  655. //
  656. // Close Function
  657. // closes registry handles and frees allocated memory
  658. //
  659. DWORD
  660. CSmLogService::Close ()
  661. {
  662. LOCALTRACE (L"Closing SysmonLog Service Object\n");
  663. UnloadQueries();
  664. // close any open registry keys
  665. if (m_hKeyMachine != NULL) {
  666. RegCloseKey (m_hKeyMachine);
  667. m_hKeyMachine = NULL;
  668. }
  669. if (m_hKeyLogService != NULL) {
  670. RegCloseKey (m_hKeyLogService);
  671. m_hKeyLogService = NULL;
  672. }
  673. if (m_hKeyLogServiceRoot!= NULL) {
  674. RegCloseKey (m_hKeyLogServiceRoot);
  675. m_hKeyLogServiceRoot = NULL;
  676. }
  677. SetOpen ( FALSE );
  678. return ERROR_SUCCESS;
  679. }
  680. BOOL
  681. CSmLogService::IsAutoStart ( void )
  682. {
  683. BOOL bAutoStart = FALSE;
  684. POSITION listPos = NULL;
  685. PSLQUERY pLogQuery = NULL;
  686. if (!m_QueryList.IsEmpty()) {
  687. listPos = m_QueryList.GetHeadPosition();
  688. while (listPos != NULL) {
  689. pLogQuery = m_QueryList.GetNext(listPos);
  690. if ( pLogQuery->IsAutoStart() ) {
  691. bAutoStart = TRUE;
  692. break;
  693. }
  694. }
  695. }
  696. return bAutoStart;
  697. }
  698. //
  699. // SyncWithRegistry()
  700. // reads the current values for all queries from the registry
  701. // and reloads the internal values to match
  702. //
  703. DWORD CSmLogService::SyncWithRegistry ( PSLQUERY* ppActiveQuery )
  704. {
  705. DWORD dwStatus = ERROR_SUCCESS;
  706. CString strDesc;
  707. ResourceStateManager rsm;
  708. // Unload queries and reload, to capture new queries.
  709. // This is necessary for monitoring remote systems,
  710. // and if multiple users are active on the same system.
  711. dwStatus = UnloadQueries ( ppActiveQuery );
  712. if ( ERROR_SUCCESS == dwStatus ) {
  713. dwStatus = LoadQueries ();
  714. }
  715. return dwStatus;
  716. }
  717. DWORD
  718. CSmLogService::GetState( void )
  719. {
  720. // Check the status of the log service via the service controller.
  721. // 0 returned in case of error.
  722. LONG dwStatus = ERROR_SUCCESS;
  723. DWORD dwState = 0; // Error by default.
  724. SERVICE_STATUS ssData;
  725. SC_HANDLE hSC;
  726. SC_HANDLE hLogService;
  727. // open SC database
  728. hSC = OpenSCManager ( GetMachineName(), NULL, SC_MANAGER_CONNECT);
  729. if (hSC != NULL) {
  730. // open service
  731. hLogService = OpenService (
  732. hSC,
  733. L"SysmonLog",
  734. SERVICE_INTERROGATE );
  735. if (hLogService != NULL) {
  736. if ( ControlService (
  737. hLogService,
  738. SERVICE_CONTROL_INTERROGATE,
  739. &ssData)) {
  740. dwState = ssData.dwCurrentState;
  741. } else {
  742. dwStatus = GetLastError();
  743. dwState = SERVICE_STOPPED;
  744. }
  745. CloseServiceHandle (hLogService);
  746. } else {
  747. dwStatus = GetLastError();
  748. }
  749. CloseServiceHandle (hSC);
  750. } else {
  751. dwStatus = GetLastError();
  752. } // OpenSCManager
  753. return dwState;
  754. }
  755. BOOL
  756. CSmLogService::IsRunning( void )
  757. {
  758. DWORD dwState = GetState();
  759. BOOL bRunning = FALSE;
  760. if ( 0 != dwState
  761. && SERVICE_STOPPED != dwState
  762. && SERVICE_STOP_PENDING != dwState ) {
  763. bRunning = TRUE;
  764. }
  765. return bRunning;
  766. }
  767. DWORD
  768. CSmLogService::CreateDefaultLogQueries( void )
  769. {
  770. DWORD dwStatus = ERROR_SUCCESS;
  771. PSLQUERY pQuery = NULL;
  772. CString strTemp;
  773. CString strModuleName;
  774. BOOL bRegistryUpdated;
  775. BOOL bDupFound = FALSE;
  776. ResourceStateManager rsm;
  777. // Creates default "System Overview" counter log query
  778. MFC_TRY
  779. strTemp.LoadString ( IDS_DEFAULT_CTRLOG_QUERY_NAME );
  780. MFC_CATCH_DWSTATUS;
  781. if ( ERROR_SUCCESS == dwStatus ) {
  782. pQuery = CreateTypedQuery ( strTemp, SLQ_COUNTER_LOG );
  783. if ( NULL != pQuery && (OS_WIN2K != TargetOs()) ) {
  784. // Default query collection name is stored as MUI indirect string after Windows 2000
  785. MFC_TRY
  786. ::GetModuleFileName(
  787. AfxGetInstanceHandle(),
  788. strModuleName.GetBufferSetLength(MAX_PATH),
  789. MAX_PATH );
  790. strTemp.Format (L"@%s,-%d", strModuleName, IDS_DEFAULT_CTRLOG_QUERY_NAME );
  791. strModuleName.ReleaseBuffer();
  792. MFC_CATCH_DWSTATUS;
  793. if ( ERROR_SUCCESS == dwStatus ) {
  794. dwStatus = RegSetValueEx (
  795. pQuery->GetQueryKey(),
  796. CGlobalString::m_cszRegCollectionNameInd,
  797. 0L,
  798. REG_SZ,
  799. (CONST BYTE *)strTemp.GetBufferSetLength( strTemp.GetLength() ),
  800. strTemp.GetLength()*sizeof(WCHAR) );
  801. strTemp.ReleaseBuffer();
  802. }
  803. // CreateTypedQuery checks for the existence of the default query
  804. // using the the query name.
  805. // Check for the existence of the default query under the MUI indirect
  806. // name as well.
  807. if ( NULL != pQuery ) {
  808. if ( ERROR_SUCCESS == dwStatus ) {
  809. FindDuplicateQuery ( strTemp, bDupFound );
  810. if ( bDupFound ) {
  811. DeleteQuery ( pQuery );
  812. pQuery = NULL;
  813. dwStatus = ERROR_SUCCESS;
  814. }
  815. }
  816. }
  817. }
  818. if ( NULL != pQuery ) {
  819. SLQ_TIME_INFO slqTime;
  820. PSLCTRQUERY pCtrQuery = NULL;
  821. MFC_TRY
  822. pCtrQuery = pQuery->CastToCounterLogQuery();
  823. pCtrQuery->SetFileNameAutoFormat ( SLF_NAME_NONE );
  824. pCtrQuery->SetLogFileType ( SLF_BIN_FILE );
  825. pCtrQuery->SetDataStoreAppendMode ( SLF_DATA_STORE_OVERWRITE );
  826. strTemp.LoadString ( IDS_DEFAULT_CTRLOG_COMMENT );
  827. pCtrQuery->SetLogComment ( strTemp );
  828. if ( OS_WIN2K != TargetOs() ) {
  829. strTemp.Format (L"@%s,-%d", strModuleName, IDS_DEFAULT_CTRLOG_COMMENT );
  830. pCtrQuery->SetLogCommentIndirect ( strTemp );
  831. }
  832. strTemp.LoadString ( IDS_DEFAULT_CTRLOG_FILE_NAME );
  833. pCtrQuery->SetLogFileName ( strTemp );
  834. if ( OS_WIN2K != TargetOs() ) {
  835. strTemp.Format (L"@%s,-%d", strModuleName, IDS_DEFAULT_CTRLOG_FILE_NAME );
  836. pCtrQuery->SetLogFileNameIndirect ( strTemp );
  837. }
  838. pCtrQuery->AddCounter ( CGlobalString::m_cszDefaultCtrLogCpuPath );
  839. pCtrQuery->AddCounter ( CGlobalString::m_cszDefaultCtrLogMemoryPath );
  840. pCtrQuery->AddCounter ( CGlobalString::m_cszDefaultCtrLogDiskPath );
  841. // Start mode and time
  842. memset (&slqTime, 0, sizeof(slqTime));
  843. slqTime.wTimeType = SLQ_TT_TTYPE_START;
  844. slqTime.wDataType = SLQ_TT_DTYPE_DATETIME;
  845. slqTime.dwAutoMode = SLQ_AUTO_MODE_NONE;
  846. slqTime.llDateTime = MAX_TIME_VALUE;
  847. pCtrQuery->SetLogTime (&slqTime, (DWORD)slqTime.wTimeType);
  848. // Stop mode and time
  849. slqTime.wTimeType = SLQ_TT_TTYPE_STOP;
  850. slqTime.llDateTime = MIN_TIME_VALUE;
  851. pCtrQuery->SetLogTime (&slqTime, (DWORD)slqTime.wTimeType);
  852. pCtrQuery->UpdateService( bRegistryUpdated );
  853. // Set the default log to Execute Only.
  854. dwStatus = pCtrQuery->UpdateExecuteOnly ();
  855. MFC_CATCH_DWSTATUS
  856. if ( ERROR_SUCCESS == dwStatus && NULL != pCtrQuery ) {
  857. VERIFY ( ERROR_SUCCESS == UnloadSingleQuery ( pCtrQuery ) );
  858. } else if ( NULL != pCtrQuery ) {
  859. DeleteQuery ( pCtrQuery );
  860. }
  861. } else {
  862. dwStatus = GetLastError();
  863. if ( SMCFG_DUP_QUERY_NAME == dwStatus ) {
  864. dwStatus = ERROR_SUCCESS;
  865. }
  866. }
  867. }
  868. return dwStatus;
  869. }
  870. DWORD
  871. CSmLogService::Install (
  872. const CString& rstrMachineName )
  873. {
  874. DWORD dwStatus = ERROR_SUCCESS;
  875. DWORD dwDisposition = 0;
  876. HKEY hKeyPerfLog = NULL;
  877. DWORD dwType;
  878. DWORD dwRegValue;
  879. DWORD dwBufferSize;
  880. BOOL bReadOnlyPerfLogKey = FALSE;
  881. BOOL bReadOnlyLogQueriesKey = FALSE;
  882. ResourceStateManager rsm;
  883. //
  884. // Get machine OS version
  885. //
  886. PdhiPlaGetVersion( rstrMachineName, &m_OSVersion );
  887. if ( NULL == m_hKeyMachine ) {
  888. if ( rstrMachineName.IsEmpty() ) {
  889. m_hKeyMachine = HKEY_LOCAL_MACHINE;
  890. } else {
  891. dwStatus = RegConnectRegistryW (
  892. rstrMachineName,
  893. HKEY_LOCAL_MACHINE,
  894. &m_hKeyMachine);
  895. }
  896. }
  897. if ( ERROR_SUCCESS == dwStatus ) {
  898. dwStatus = RegOpenKeyEx (
  899. m_hKeyMachine,
  900. L"System\\CurrentControlSet\\Services\\SysmonLog",
  901. 0,
  902. KEY_READ | KEY_WRITE,
  903. &hKeyPerfLog);
  904. if (dwStatus != ERROR_SUCCESS) {
  905. // unable to access the key for write access, so try read only
  906. dwStatus = RegOpenKeyEx (
  907. m_hKeyMachine,
  908. L"System\\CurrentControlSet\\Services\\SysmonLog",
  909. 0,
  910. KEY_READ,
  911. &hKeyPerfLog);
  912. if ( ERROR_SUCCESS == dwStatus ) {
  913. bReadOnlyPerfLogKey = TRUE;
  914. }
  915. }
  916. }
  917. EnterCriticalSection ( &g_critsectInstallDefaultQueries );
  918. // In Windows 2000, the Log Queries key is created by the snapin.
  919. // After Windows 2000, the Log Queries key is created by system setup,
  920. // along with a "Default Installed" registry flag.
  921. if ( ERROR_SUCCESS == dwStatus && NULL == m_hKeyLogService ) {
  922. if ( !bReadOnlyPerfLogKey ) {
  923. // add registry subkey for Log Queries
  924. dwStatus = RegCreateKeyEx (
  925. hKeyPerfLog,
  926. L"Log Queries",
  927. 0,
  928. NULL,
  929. REG_OPTION_NON_VOLATILE,
  930. KEY_READ | KEY_WRITE,
  931. NULL,
  932. &m_hKeyLogService,
  933. &dwDisposition);
  934. } else {
  935. // ReadOnly SysmonLog key. Still possible to succeed if Log Queries
  936. // exists with read/write access.
  937. dwStatus = RegOpenKeyEx (
  938. m_hKeyMachine,
  939. L"System\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
  940. 0,
  941. KEY_READ | KEY_WRITE,
  942. &m_hKeyLogService);
  943. if (dwStatus == ERROR_SUCCESS) {
  944. bReadOnlyLogQueriesKey = FALSE;
  945. } else {
  946. // unable to access the key for write access, so try read only
  947. dwStatus = RegOpenKeyExW (
  948. m_hKeyMachine,
  949. (LPCWSTR)L"SYSTEM\\CurrentControlSet\\Services\\SysmonLog\\Log Queries",
  950. 0,
  951. KEY_READ,
  952. &m_hKeyLogService);
  953. if ( ERROR_SUCCESS == dwStatus ) {
  954. bReadOnlyLogQueriesKey = TRUE;
  955. }
  956. }
  957. }
  958. } else if ( m_bReadOnly ) {
  959. bReadOnlyLogQueriesKey = TRUE;
  960. }
  961. if ( ERROR_SUCCESS == dwStatus ) {
  962. // Log queries key now exists.
  963. dwType = REG_DWORD;
  964. dwRegValue = 0;
  965. dwBufferSize = sizeof(DWORD);
  966. dwStatus = RegQueryValueExW (
  967. m_hKeyLogService,
  968. CGlobalString::m_cszDefaultsInstalled,
  969. NULL,
  970. &dwType,
  971. (LPBYTE)&dwRegValue,
  972. &dwBufferSize );
  973. if ( ERROR_SUCCESS != dwStatus
  974. || 0 == dwRegValue )
  975. {
  976. if ( !bReadOnlyLogQueriesKey ) {
  977. // Create default counter log query.
  978. // Todo: Message on error.
  979. dwStatus = CreateDefaultLogQueries();
  980. if ( ERROR_SUCCESS == dwStatus ) {
  981. dwRegValue = SLQ_DEFAULT_SYS_QUERY;
  982. dwStatus = RegSetValueEx (
  983. m_hKeyLogService,
  984. CGlobalString::m_cszDefaultsInstalled,
  985. 0L,
  986. REG_DWORD,
  987. (CONST BYTE *)&dwRegValue,
  988. dwBufferSize);
  989. }
  990. } else {
  991. dwStatus = SMCFG_NO_INSTALL_ACCESS;
  992. }
  993. }
  994. }
  995. if ( ERROR_SUCCESS == dwStatus ) {
  996. RegFlushKey ( m_hKeyLogService );
  997. // Ignore status.
  998. }
  999. LeaveCriticalSection ( &g_critsectInstallDefaultQueries );
  1000. if (NULL != hKeyPerfLog ) {
  1001. RegCloseKey (hKeyPerfLog);
  1002. }
  1003. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  1004. dwStatus = SMCFG_NO_INSTALL_ACCESS;
  1005. }
  1006. return dwStatus;
  1007. }
  1008. DWORD
  1009. CSmLogService::Synchronize( void )
  1010. {
  1011. // If the service is running, tell it to synchronize itself,
  1012. // Check the state afterwards to see if it got the message.
  1013. // If stop pending or stopped, wait until the service is
  1014. // stopped and then attempt to start it. The service
  1015. // synchronizes itself from the registry when it is started.
  1016. // Return 0 for success, other for failure.
  1017. SC_HANDLE hSC = NULL;
  1018. SC_HANDLE hService = NULL;
  1019. SERVICE_STATUS ssData;
  1020. DWORD dwCurrentState;
  1021. DWORD dwTimeout = 50;
  1022. LONG dwStatus = ERROR_SUCCESS;
  1023. BOOL bServiceStarted = FALSE;
  1024. dwCurrentState = GetState();
  1025. if ( 0 == dwCurrentState ) {
  1026. dwStatus = 1;
  1027. } else {
  1028. // open SC database
  1029. hSC = OpenSCManager ( GetMachineName(), NULL, GENERIC_READ);
  1030. if ( NULL != hSC ) {
  1031. // open service
  1032. hService = OpenService (
  1033. hSC,
  1034. L"SysmonLog",
  1035. SERVICE_USER_DEFINED_CONTROL
  1036. | SERVICE_START );
  1037. if ( NULL != hService ) {
  1038. if ( ( SERVICE_STOPPED != dwCurrentState )
  1039. && ( SERVICE_STOP_PENDING != dwCurrentState ) ) {
  1040. // Wait 100 milliseconds before synchronizing service,
  1041. // to ensure that registry values are written.
  1042. Sleep ( 100 );
  1043. ControlService (
  1044. hService,
  1045. SERVICE_CONTROL_SYNCHRONIZE,
  1046. &ssData);
  1047. dwCurrentState = ssData.dwCurrentState;
  1048. }
  1049. // Make sure that the ControlService call reached the service
  1050. // while it was in run state.
  1051. if ( ( SERVICE_STOPPED == dwCurrentState )
  1052. || ( SERVICE_STOP_PENDING == dwCurrentState ) ) {
  1053. if ( SERVICE_STOP_PENDING == dwCurrentState ) {
  1054. // wait for the service to stop before starting it.
  1055. while (--dwTimeout) {
  1056. dwCurrentState = GetState();
  1057. if ( SERVICE_STOP_PENDING == dwCurrentState ) {
  1058. Sleep(200);
  1059. } else {
  1060. break;
  1061. }
  1062. }
  1063. }
  1064. dwTimeout = 50;
  1065. if ( SERVICE_STOPPED == dwCurrentState ) {
  1066. bServiceStarted = StartService (hService, 0, NULL);
  1067. if ( !bServiceStarted ) {
  1068. dwStatus = GetLastError();
  1069. if ( ERROR_SERVICE_ALREADY_RUNNING == dwStatus ) {
  1070. // Okay if started during the time window since
  1071. // the last GetState() call.
  1072. dwStatus = ERROR_SUCCESS;
  1073. bServiceStarted = TRUE;
  1074. } // else error
  1075. }
  1076. if ( bServiceStarted ) {
  1077. // wait for the service to start or stop
  1078. // before returning
  1079. while (--dwTimeout) {
  1080. dwCurrentState = GetState();
  1081. if ( SERVICE_START_PENDING == dwCurrentState ) {
  1082. Sleep(200);
  1083. } else {
  1084. break;
  1085. }
  1086. }
  1087. }
  1088. }
  1089. }
  1090. CloseServiceHandle (hService);
  1091. } else {
  1092. dwStatus = GetLastError();
  1093. }
  1094. CloseServiceHandle (hSC);
  1095. } else {
  1096. dwStatus = GetLastError();
  1097. }
  1098. }
  1099. // Update the service configuration for automatic
  1100. // vs. manual start
  1101. if ( ERROR_SUCCESS == dwStatus ) {
  1102. // Ignore errors
  1103. if ( NULL != GetRootNode() ) {
  1104. GetRootNode()->UpdateServiceConfig();
  1105. }
  1106. }
  1107. return dwStatus;
  1108. }
  1109. void
  1110. CSmLogService::SetBaseName( const CString& rstrName )
  1111. {
  1112. // This method is only called within the service constructor,
  1113. // so throw any errors
  1114. m_strBaseName = rstrName;
  1115. return;
  1116. }
  1117. const CString&
  1118. CSmLogService::GetDefaultLogFileFolder()
  1119. {
  1120. if ( m_strDefaultLogFileFolder.IsEmpty() ) {
  1121. LoadDefaultLogFileFolder();
  1122. }
  1123. return m_strDefaultLogFileFolder;
  1124. }
  1125. INT
  1126. CSmLogService::GetQueryCount()
  1127. {
  1128. INT iQueryCount = -1;
  1129. // The query count is only valid if the service is open.
  1130. if ( IsOpen() ) {
  1131. iQueryCount = (int) m_QueryList.GetCount();
  1132. } else {
  1133. ASSERT ( FALSE );
  1134. }
  1135. return iQueryCount;
  1136. }
  1137. DWORD
  1138. CSmLogService::FindDuplicateQuery (
  1139. const CString cstrName,
  1140. BOOL& rbFound )
  1141. {
  1142. DWORD dwStatus = ERROR_SUCCESS;
  1143. HRESULT hrLocal = NOERROR;
  1144. DWORD dwQueryIndex = 0;
  1145. LONG lEnumStatus = ERROR_SUCCESS;
  1146. WCHAR szQueryKeyName[MAX_PATH + 1];
  1147. DWORD dwQueryKeyNameLen;
  1148. LPWSTR szCollectionName = NULL;
  1149. UINT uiCollectionNameLen = 0;
  1150. FILETIME ftLastWritten;
  1151. HKEY hKeyQuery = NULL;
  1152. BOOL bFoundFirst = FALSE;
  1153. CString strDirectName;
  1154. CString strLocalName;
  1155. ASSERT ( !cstrName.IsEmpty() );
  1156. rbFound = FALSE;
  1157. if ( !cstrName.IsEmpty() ) {
  1158. MFC_TRY
  1159. strLocalName = cstrName;
  1160. MFC_CATCH_DWSTATUS;
  1161. if ( ERROR_SUCCESS == dwStatus ) {
  1162. // Translate new query name if necessary
  1163. hrLocal = SHLoadIndirectString(
  1164. strLocalName.GetBufferSetLength ( strLocalName.GetLength() ),
  1165. strDirectName.GetBufferSetLength ( MAX_PATH ),
  1166. MAX_PATH,
  1167. NULL );
  1168. strLocalName.ReleaseBuffer();
  1169. strDirectName.ReleaseBuffer();
  1170. if ( FAILED ( hrLocal ) ) {
  1171. // Query name is not an indirect string
  1172. dwStatus = ERROR_SUCCESS;
  1173. MFC_TRY
  1174. strDirectName = strLocalName;
  1175. MFC_CATCH_DWSTATUS;
  1176. }
  1177. }
  1178. }
  1179. if ( ERROR_SUCCESS == dwStatus ) {
  1180. // Search all queries for the specified query.
  1181. dwQueryKeyNameLen = sizeof ( szQueryKeyName ) / sizeof ( WCHAR );
  1182. memset (szQueryKeyName, 0, sizeof (szQueryKeyName));
  1183. while ( ERROR_SUCCESS == ( lEnumStatus = RegEnumKeyExW (
  1184. m_hKeyLogService,
  1185. dwQueryIndex,
  1186. szQueryKeyName,
  1187. &dwQueryKeyNameLen,
  1188. NULL,
  1189. NULL,
  1190. NULL,
  1191. &ftLastWritten ) ) ) {
  1192. // open the query specified
  1193. dwStatus = RegOpenKeyExW (
  1194. m_hKeyLogService,
  1195. szQueryKeyName,
  1196. 0,
  1197. KEY_READ,
  1198. &hKeyQuery);
  1199. if ( ERROR_SUCCESS == dwStatus ) {
  1200. // Query key is Guid if written by post Win2000 snapin.
  1201. // Query key is name if written by Win2000 snapin.
  1202. if ( 0 == strDirectName.CompareNoCase ( szQueryKeyName ) ) {
  1203. if ( TRUE == bFoundFirst ) {
  1204. rbFound = TRUE;
  1205. break;
  1206. } else {
  1207. bFoundFirst = TRUE;
  1208. }
  1209. } else {
  1210. dwStatus = CSmLogQuery::SmNoLocReadRegIndStrVal (
  1211. hKeyQuery,
  1212. IDS_REG_COLLECTION_NAME,
  1213. NULL,
  1214. &szCollectionName,
  1215. &uiCollectionNameLen );
  1216. ASSERT ( MAX_PATH >= uiCollectionNameLen );
  1217. if ( ERROR_SUCCESS == dwStatus ) {
  1218. if ( MAX_PATH >= uiCollectionNameLen ) {
  1219. if ( NULL != szCollectionName ) {
  1220. if ( L'\0' == *szCollectionName ) {
  1221. G_FREE ( szCollectionName );
  1222. szCollectionName = NULL;
  1223. }
  1224. }
  1225. if ( NULL == szCollectionName ) {
  1226. MFC_TRY
  1227. szCollectionName = (LPWSTR)G_ALLOC ( (lstrlen(szQueryKeyName)+1)*sizeof(WCHAR));
  1228. MFC_CATCH_DWSTATUS;
  1229. if ( ERROR_SUCCESS == dwStatus && NULL != szCollectionName ) {
  1230. StringCchCopy ( szCollectionName, lstrlen(szQueryKeyName)+1, szQueryKeyName );
  1231. }
  1232. }
  1233. if ( NULL != szCollectionName ) {
  1234. // Compare found name to input name.
  1235. if ( 0 == strDirectName.CompareNoCase ( szCollectionName ) ) {
  1236. if ( TRUE == bFoundFirst ) {
  1237. rbFound = TRUE;
  1238. break;
  1239. } else {
  1240. bFoundFirst = TRUE;
  1241. }
  1242. }
  1243. } // Todo: else report message?
  1244. }
  1245. } // Todo: else report message?
  1246. } // Todo: else report message?
  1247. }
  1248. // set up for the next item in the list
  1249. dwQueryKeyNameLen = sizeof (szQueryKeyName) / sizeof (szQueryKeyName[0]);
  1250. memset (szQueryKeyName, 0, sizeof (szQueryKeyName));
  1251. if ( NULL != hKeyQuery ) {
  1252. RegCloseKey( hKeyQuery );
  1253. hKeyQuery = NULL;
  1254. }
  1255. if ( NULL != szCollectionName ) {
  1256. G_FREE ( szCollectionName );
  1257. szCollectionName = NULL;
  1258. uiCollectionNameLen = 0;
  1259. }
  1260. dwQueryIndex++;
  1261. }
  1262. } else {
  1263. dwStatus = ERROR_INVALID_PARAMETER;
  1264. }
  1265. if ( NULL != szCollectionName ) {
  1266. G_FREE ( szCollectionName );
  1267. szCollectionName = NULL;
  1268. uiCollectionNameLen = 0;
  1269. }
  1270. if ( NULL != hKeyQuery ) {
  1271. RegCloseKey( hKeyQuery );
  1272. hKeyQuery = NULL;
  1273. }
  1274. return dwStatus;
  1275. }
  1276. OS_TYPE
  1277. CSmLogService::TargetOs( void )
  1278. {
  1279. if ( 5 == m_OSVersion.dwMajorVersion) {
  1280. if (2195 == m_OSVersion.dwBuild ) {
  1281. return OS_WIN2K;
  1282. } else if (2600 == m_OSVersion.dwBuild) {
  1283. return OS_WINXP;
  1284. } else if (OS_DOT_NET(m_OSVersion.dwBuild)) {
  1285. return OS_WINNET;
  1286. }
  1287. }
  1288. return OS_NOT_SUPPORTED;
  1289. }
  1290. void
  1291. CSmLogService::SetRootNode ( CSmRootNode* pRootNode )
  1292. {
  1293. m_pRootNode = pRootNode;
  1294. }
  1295. CSmRootNode*
  1296. CSmLogService::GetRootNode ( void )
  1297. {
  1298. return m_pRootNode;
  1299. }
  1300. BOOL
  1301. CSmLogService::CanAccessWbemRemote()
  1302. {
  1303. HRESULT hr;
  1304. IWbemLocator *pLocator = NULL;
  1305. IWbemServices* pWbemServices = NULL;
  1306. LPCWSTR szRoot[2] = { L"root\\perfmon",
  1307. L"root\\wmi"
  1308. };
  1309. LPCWSTR szMask = L"\\\\%s\\%s";
  1310. BSTR bszClass = SysAllocString(L"SysmonLog");
  1311. BSTR bszNamespace = NULL;
  1312. LPWSTR buffer = NULL;
  1313. DWORD dwBufLen;
  1314. hr = CoCreateInstance(
  1315. CLSID_WbemLocator,
  1316. 0,
  1317. CLSCTX_INPROC_SERVER,
  1318. IID_IWbemLocator,
  1319. (LPVOID*)&pLocator );
  1320. if (!SUCCEEDED(hr)) {
  1321. goto Cleanup;
  1322. }
  1323. if ( !GetMachineName().IsEmpty()) {
  1324. dwBufLen = max(wcslen(szRoot[0]), wcslen(szRoot[1])) +
  1325. GetMachineName().GetLength() +
  1326. wcslen( szMask );
  1327. buffer = new WCHAR[dwBufLen];
  1328. if ( buffer == NULL ){
  1329. hr = ERROR_OUTOFMEMORY;
  1330. goto Cleanup;
  1331. }
  1332. }
  1333. //
  1334. // First try root\\perfmon, then root\\wmi, order matters
  1335. //
  1336. for (int i = 0; i < 2; i++) {
  1337. if (bszNamespace) {
  1338. SysFreeString(bszNamespace);
  1339. bszNamespace = NULL;
  1340. }
  1341. if (buffer) {
  1342. StringCchPrintf( buffer, dwBufLen, szMask, GetMachineName(), szRoot[i] );
  1343. bszNamespace = SysAllocString( buffer );
  1344. }
  1345. else {
  1346. bszNamespace = SysAllocString(szRoot[i]);
  1347. }
  1348. hr = pLocator->ConnectServer(
  1349. bszNamespace,
  1350. NULL,
  1351. NULL,
  1352. NULL,
  1353. 0,
  1354. NULL,
  1355. NULL,
  1356. &pWbemServices);
  1357. if (SUCCEEDED(hr)) {
  1358. break;
  1359. }
  1360. }
  1361. Cleanup:
  1362. if (buffer) {
  1363. delete [] buffer;
  1364. }
  1365. if (bszNamespace) {
  1366. SysFreeString(bszNamespace);
  1367. }
  1368. if (pLocator) {
  1369. pLocator->Release();
  1370. }
  1371. if (pWbemServices) {
  1372. pWbemServices->Release();
  1373. }
  1374. m_hWbemAccessStatus = hr;
  1375. if (SUCCEEDED(hr)) {
  1376. return TRUE;
  1377. }
  1378. else {
  1379. return FALSE;
  1380. }
  1381. }