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.

1588 lines
50 KiB

  1. // logman.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include "strings.h"
  5. #include "unihelpr.h"
  6. #include "utils.h"
  7. #include "proputil.h"
  8. #include "propbag.h"
  9. #include "logman.h"
  10. #include "resource.h"
  11. #include "varg.c"
  12. //
  13. // Forward routines:
  14. //
  15. ARG_RECORD Commands[] = {
  16. IDS_HELP_DEBUG,
  17. IDS_ARG1_DEBUG, NULL,
  18. IDS_ARG2_DEBUG, NULL,
  19. IDS_PARAM_DEFAULT, NULL,
  20. ARG_TYPE_DEBUG, ARG_FLAG_OPTIONAL|ARG_FLAG_HIDDEN,
  21. (CMD_TYPE)0,
  22. 0, NULL,
  23. IDS_HELP_HELP,
  24. IDS_ARG1_HELP, NULL,
  25. IDS_ARG2_HELP, NULL,
  26. 0, NULL,
  27. ARG_TYPE_HELP, ARG_FLAG_OPTIONAL,
  28. (CMD_TYPE)FALSE,
  29. 0, NULL,
  30. IDS_HELP_COMPUTER,
  31. IDS_ARG1_COMPUTER, NULL,
  32. IDS_ARG2_COMPUTER, NULL,
  33. IDS_ARG1_COMPUTER, NULL,
  34. ARG_TYPE_STR, ARG_FLAG_OPTIONAL,
  35. (CMD_TYPE)NULL,
  36. 0, NULL,
  37. IDS_HELP_NAME,
  38. IDS_ARG1_NAME, NULL,
  39. IDS_ARG2_NAME, NULL,
  40. IDS_ARG1_NAME, NULL,
  41. ARG_TYPE_STR, ARG_FLAG_CONDITIONAL|ARG_FLAG_NOFLAG,
  42. (CMD_TYPE)NULL,
  43. 0, NULL,
  44. IDS_HELP_START,
  45. IDS_ARG1_START, NULL,
  46. IDS_ARG2_START, NULL,
  47. 0, NULL,
  48. ARG_TYPE_BOOL, ARG_FLAG_OPTIONAL,
  49. (CMD_TYPE)NULL,
  50. 0, NULL,
  51. IDS_HELP_STOP,
  52. IDS_ARG1_STOP, NULL,
  53. IDS_ARG2_STOP, NULL,
  54. 0,NULL,
  55. ARG_TYPE_BOOL, ARG_FLAG_OPTIONAL,
  56. (CMD_TYPE)NULL,
  57. 0, NULL,
  58. IDS_HELP_SETTINGS,
  59. IDS_ARG1_SETTINGS, NULL,
  60. IDS_ARG2_SETTINGS, NULL,
  61. IDS_PARAM_FILENAME, NULL,
  62. ARG_TYPE_STR, ARG_FLAG_CONDITIONAL,
  63. (CMD_TYPE)NULL,
  64. 0, NULL,
  65. IDS_HELP_OVER,
  66. IDS_ARG1_OVER, NULL,
  67. IDS_ARG2_OVER, NULL,
  68. 0, NULL,
  69. ARG_TYPE_BOOL, ARG_FLAG_OPTIONAL,
  70. (CMD_TYPE)NULL,
  71. 0, NULL,
  72. ARG_TERMINATOR
  73. };
  74. enum _Commands {
  75. eDebug,
  76. eHelp,
  77. eComputer,
  78. eName,
  79. eStart,
  80. eStop,
  81. eSettings,
  82. eOverwrite
  83. };
  84. DWORD _stdcall
  85. ValidateComputerName (
  86. LPCTSTR szComputerName );
  87. DWORD _stdcall
  88. LoadSettingsFile (
  89. LPCTSTR szFileName,
  90. LPTSTR& szFileBuffer );
  91. DWORD _stdcall
  92. DeleteQuery (
  93. HKEY hkeyLogQueries,
  94. LPCWSTR szQueryName );
  95. DWORD _stdcall
  96. InitializeNewQuery (
  97. HKEY hkeyLogQueries,
  98. HKEY& rhKeyQuery,
  99. LPCWSTR szQueryName );
  100. DWORD _stdcall
  101. CreateDefaultLogQueries (
  102. HKEY hkeyLogQueries );
  103. DWORD _stdcall
  104. Install (
  105. HKEY hkeyMachine,
  106. HKEY& rhkeyLogQueries );
  107. DWORD _stdcall
  108. ConnectToRegistry (
  109. LPCTSTR szComputerName,
  110. HKEY& rhkeyLogQueries );
  111. DWORD _stdcall
  112. WriteRegistryLastModified (
  113. HKEY hkeyQuery );
  114. DWORD _stdcall
  115. WriteToRegistry (
  116. HKEY hkeyLogQueries,
  117. CPropertyBag* pPropBag,
  118. LPWSTR szQueryName,
  119. DWORD& rdwLogType );
  120. DWORD _stdcall
  121. ValidateProperties (
  122. HKEY hkeyLogQueries,
  123. CPropertyBag* pPropBag,
  124. DWORD* pdwLogType,
  125. LPWSTR szQueryName,
  126. DWORD* pdwNameBufLen );
  127. DWORD _stdcall
  128. ProcessSettingsObject (
  129. HKEY hkeyLogQueries,
  130. CPropertyBag* pPropBag );
  131. DWORD _stdcall
  132. ProcessSettingsFile (
  133. LPCTSTR szComputerName,
  134. LPCTSTR szFileName );
  135. DWORD _stdcall
  136. StartQuery (
  137. LPCTSTR szComputerName,
  138. LPCTSTR szQueryName );
  139. DWORD _stdcall
  140. StopQuery (
  141. LPCTSTR szComputerName,
  142. LPCTSTR szQueryName );
  143. DWORD _stdcall
  144. ConnectToQuery (
  145. LPCTSTR szComputerName,
  146. LPCTSTR szQueryName,
  147. HKEY* phkeyQuery );
  148. DWORD _stdcall
  149. GetState (
  150. LPCTSTR szComputerName,
  151. DWORD& rdwState );
  152. DWORD _stdcall
  153. Synchronize (
  154. LPCTSTR szComputerName );
  155. //
  156. // Routines
  157. //
  158. DWORD _stdcall
  159. ValidateComputerName (
  160. LPCTSTR szComputerName )
  161. {
  162. DWORD dwStatus = ERROR_SUCCESS;
  163. if ( NULL != szComputerName ) {
  164. if ( ! ( MAX_COMPUTERNAME_LENGTH < lstrlen ( szComputerName ) ) ) {
  165. } else {
  166. dwStatus = ERROR_INVALID_COMPUTERNAME;
  167. }
  168. }
  169. return dwStatus;
  170. }
  171. DWORD _stdcall
  172. LoadSettingsFile (
  173. LPCTSTR szFileName,
  174. LPTSTR& szFileBuffer )
  175. {
  176. DWORD dwStatus = ERROR_SUCCESS;
  177. DWORD dwLogManStatus = ERROR_SUCCESS;
  178. HANDLE hOpenFile = NULL;
  179. TCHAR szLocalName [MAX_PATH]; // Todo: Allocate
  180. LPTSTR pFileNameStart = NULL;
  181. HANDLE hFindFile = NULL;
  182. LPTSTR szData = NULL;
  183. WIN32_FIND_DATA FindFileInfo;
  184. INT iNameOffset;
  185. USES_CONVERSION;
  186. lstrcpy ( szLocalName, szFileName ); // Todo: Handle error
  187. szFileBuffer = NULL;
  188. pFileNameStart = ExtractFileName (szLocalName) ;
  189. iNameOffset = (INT)(pFileNameStart - szLocalName);
  190. // convert short filename to long NTFS filename if necessary
  191. hFindFile = FindFirstFile ( szLocalName, &FindFileInfo) ;
  192. if (hFindFile && hFindFile != INVALID_HANDLE_VALUE) {
  193. // append the file name back to the path name
  194. lstrcpy (&szLocalName[iNameOffset], FindFileInfo.cFileName) ;
  195. FindClose (hFindFile) ;
  196. // Open the file
  197. hOpenFile = CreateFile (
  198. szLocalName,
  199. GENERIC_READ,
  200. 0, // Not shared
  201. NULL, // Security attributes
  202. OPEN_EXISTING,
  203. FILE_ATTRIBUTE_NORMAL,
  204. NULL );
  205. if ( hOpenFile && hOpenFile != INVALID_HANDLE_VALUE ) {
  206. DWORD dwFileSize;
  207. DWORD dwFileSizeHigh;
  208. // Read the file contents into a memory buffer.
  209. dwFileSize = GetFileSize ( hOpenFile, &dwFileSizeHigh );
  210. assert ( 0 == dwFileSizeHigh );
  211. // Todo: Handle non-zero file size high
  212. szData = new TCHAR[(dwFileSize + sizeof(TCHAR))/sizeof(TCHAR)];
  213. if ( NULL != szData ) {
  214. if ( FileRead ( hOpenFile, szData, dwFileSize ) ) {
  215. szFileBuffer = szData;
  216. } else {
  217. dwLogManStatus = LOGMAN_SETTINGS_FILE_NOT_LOADED;
  218. dwStatus = GetLastError();
  219. }
  220. } else {
  221. dwLogManStatus = LOGMAN_SETTINGS_FILE_NOT_LOADED;
  222. dwStatus = ERROR_OUTOFMEMORY;
  223. }
  224. CloseHandle ( hOpenFile );
  225. } else {
  226. dwLogManStatus = LOGMAN_SETTINGS_FILE_NOT_OPEN;
  227. dwStatus = GetLastError();
  228. }
  229. } else {
  230. dwLogManStatus = LOGMAN_SETTINGS_FILE_NOT_OPEN;
  231. dwStatus = GetLastError();
  232. }
  233. if ( ERROR_SUCCESS != dwLogManStatus ) {
  234. DisplayErrorMessage ( dwLogManStatus, T2W(szFileName) );
  235. }
  236. if ( ERROR_SUCCESS != dwStatus ) {
  237. DisplayErrorMessage ( dwStatus );
  238. }
  239. dwStatus = dwLogManStatus;
  240. return dwStatus;
  241. }
  242. DWORD _stdcall
  243. DeleteQuery (
  244. HKEY hkeyLogQueries,
  245. LPCWSTR szQueryName )
  246. {
  247. DWORD dwStatus = ERROR_SUCCESS;
  248. // Delete in the registry
  249. dwStatus = RegDeleteKeyW ( hkeyLogQueries, szQueryName );
  250. return dwStatus;
  251. }
  252. DWORD _stdcall
  253. InitializeNewQuery (
  254. HKEY hkeyLogQueries,
  255. HKEY& rhKeyQuery,
  256. LPCWSTR szQueryName )
  257. {
  258. DWORD dwStatus = ERROR_SUCCESS;
  259. DWORD dwDisposition = 0;
  260. // Create the query specified, checking for duplicate query.
  261. dwStatus = RegCreateKeyExW (
  262. hkeyLogQueries,
  263. szQueryName,
  264. 0,
  265. NULL,
  266. 0,
  267. KEY_ALL_ACCESS,
  268. NULL,
  269. &rhKeyQuery,
  270. &dwDisposition);
  271. if ( ERROR_SUCCESS == dwStatus ) {
  272. if ( REG_OPENED_EXISTING_KEY == dwDisposition && !Commands[eOverwrite].bValue ) {
  273. dwStatus = LOGMAN_DUP_QUERY_NAME;
  274. } else {
  275. DWORD dwRegValue;
  276. // Initialize the current state value. After it is
  277. // initialized, it is only modified when:
  278. // 1) Set to Stopped or Started by the service
  279. // 2) Set to Start Pending by the config snapin.
  280. dwRegValue = SLQ_QUERY_STOPPED;
  281. dwStatus = WriteRegistryDwordValue (
  282. rhKeyQuery,
  283. cwszRegCurrentState,
  284. &dwRegValue );
  285. if ( ERROR_SUCCESS == dwStatus ) {
  286. // Initialize the log type to "new" to indicate partially created logs
  287. dwRegValue = SLQ_NEW_LOG;
  288. dwStatus = WriteRegistryDwordValue (
  289. rhKeyQuery,
  290. cwszRegLogType,
  291. &dwRegValue );
  292. }
  293. }
  294. }
  295. return dwStatus;
  296. }
  297. DWORD _stdcall
  298. CreateDefaultLogQueries (
  299. HKEY hkeyLogQueries )
  300. {
  301. DWORD dwStatus = ERROR_SUCCESS;
  302. HRESULT hr = NOERROR;
  303. LPWSTR szPropValue;
  304. HKEY hkeyQuery = NULL;
  305. LPWSTR szMszBuf = NULL;
  306. DWORD dwMszBufLen = 0;
  307. DWORD dwMszStringLen = 0;
  308. // Create default "System Overview" counter log query
  309. // Todo: check and translate HRESULT failures
  310. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_QUERY_NAME );
  311. if ( ERROR_SUCCESS == dwStatus ) {
  312. //Todo: ResourceString return failure how?
  313. dwStatus = InitializeNewQuery (
  314. hkeyLogQueries,
  315. hkeyQuery,
  316. szPropValue );
  317. }
  318. if ( ERROR_SUCCESS == dwStatus ) {
  319. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_CPU_PATH );
  320. hr = AddStringToMszBufferAlloc (
  321. szPropValue,
  322. &szMszBuf,
  323. &dwMszBufLen,
  324. &dwMszStringLen );
  325. if ( SUCCEEDED ( hr ) ) {
  326. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_MEMORY_PATH );
  327. hr = AddStringToMszBufferAlloc (
  328. szPropValue,
  329. &szMszBuf,
  330. &dwMszBufLen,
  331. &dwMszStringLen );
  332. if ( SUCCEEDED ( hr ) ) {
  333. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_DISK_PATH );
  334. hr = AddStringToMszBufferAlloc (
  335. szPropValue,
  336. &szMszBuf,
  337. &dwMszBufLen,
  338. &dwMszStringLen );
  339. }
  340. }
  341. if ( SUCCEEDED ( hr ) ) {
  342. dwStatus = WriteRegistryStringValue (
  343. hkeyQuery,
  344. cwszRegCounterList,
  345. REG_MULTI_SZ,
  346. szMszBuf,
  347. dwMszStringLen );
  348. if ( ERROR_SUCCESS != dwStatus ) {
  349. hr = HRESULT_FROM_WIN32 ( dwStatus );
  350. }
  351. }
  352. if ( NULL != szMszBuf ) {
  353. delete szMszBuf;
  354. }
  355. }
  356. // Counter strings are required fields.
  357. if ( SUCCEEDED ( hr ) && ERROR_SUCCESS == dwStatus ) {
  358. DWORD dwTemp;
  359. SLQ_TIME_INFO stiData;
  360. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_COMMENT );
  361. dwStatus = WriteRegistryStringValue (
  362. hkeyQuery,
  363. cwszRegComment,
  364. REG_SZ,
  365. szPropValue,
  366. lstrlenW ( szPropValue ) );
  367. dwTemp = SLF_NAME_NONE;
  368. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogFileAutoFormat, &dwTemp );
  369. // Start mode and time set to manual
  370. memset (&stiData, 0, sizeof(stiData));
  371. stiData.wTimeType = SLQ_TT_TTYPE_START;
  372. stiData.wDataType = SLQ_TT_DTYPE_DATETIME;
  373. stiData.dwAutoMode = SLQ_AUTO_MODE_NONE;
  374. stiData.llDateTime = MAX_TIME_VALUE;
  375. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStartTime, &stiData );
  376. // Stop and Sample time fields are defaults, but Smlogsvc generates
  377. // warning events if fields are missing.
  378. InitDefaultSlqTimeInfo ( SLQ_COUNTER_LOG, SLQ_TT_TTYPE_STOP, &stiData );
  379. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStopTime, &stiData );
  380. InitDefaultSlqTimeInfo ( SLQ_COUNTER_LOG, SLQ_TT_TTYPE_SAMPLE, &stiData );
  381. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegSampleInterval, &stiData );
  382. // The following file fields are defaults, but Smlogsvc generates
  383. // warning events if fields are missing.
  384. dwStatus = WriteRegistryStringValue (
  385. hkeyQuery,
  386. cwszRegLogFileFolder,
  387. REG_SZ,
  388. cwszDefaultLogFileFolder,
  389. lstrlenW ( cwszDefaultLogFileFolder ) );
  390. dwTemp = DEFAULT_LOG_FILE_SERIAL_NUMBER;
  391. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogFileSerialNumber, &dwTemp );
  392. dwTemp = DEFAULT_LOG_FILE_MAX_SIZE;
  393. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogFileMaxSize, &dwTemp );
  394. dwTemp = SLF_BIN_FILE;
  395. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogFileType, &dwTemp );
  396. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_QUERY_NAME );
  397. dwStatus = WriteRegistryStringValue (
  398. hkeyQuery,
  399. cwszRegLogFileBaseName,
  400. REG_SZ,
  401. szPropValue,
  402. lstrlenW ( szPropValue ) );
  403. // The sample query is "ExecuteOnly"
  404. dwTemp = 1;
  405. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegExecuteOnly, &dwTemp );
  406. // Reset the log type from "new" to real type
  407. dwTemp = SLQ_COUNTER_LOG;
  408. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogType, &dwTemp );
  409. dwStatus = WriteRegistryLastModified ( hkeyQuery );
  410. dwStatus = ERROR_SUCCESS; // Non-required fields.
  411. } else {
  412. // Todo: Translate status, display message re: default log not installed
  413. if ( ERROR_SUCCESS == dwStatus ) {
  414. dwStatus = (DWORD) hr;
  415. }
  416. szPropValue = ResourceString ( IDS_DEFAULT_CTRLOG_QUERY_NAME );
  417. if ( NULL != hkeyQuery ) {
  418. RegCloseKey ( hkeyQuery );
  419. hkeyQuery = NULL;
  420. }
  421. DeleteQuery ( hkeyLogQueries, szPropValue );
  422. }
  423. if ( NULL != hkeyQuery ) {
  424. RegCloseKey ( hkeyQuery );
  425. }
  426. return dwStatus;
  427. }
  428. DWORD _stdcall
  429. Install (
  430. HKEY hkeyMachine,
  431. HKEY& rhkeyLogQueries )
  432. {
  433. DWORD dwStatus = ERROR_SUCCESS;
  434. HKEY hkeySysmonLog;
  435. DWORD dwDisposition;
  436. assert ( NULL != hkeyMachine );
  437. rhkeyLogQueries = NULL;
  438. dwStatus = RegOpenKeyExW (
  439. hkeyMachine,
  440. cwszRegKeySysmonLog,
  441. 0,
  442. KEY_READ | KEY_WRITE,
  443. &hkeySysmonLog);
  444. if ( ERROR_SUCCESS == dwStatus ) {
  445. // Create registry subkey for Log Queries
  446. dwStatus = RegCreateKeyExW (
  447. hkeySysmonLog,
  448. cwszRegKeyLogQueries,
  449. 0,
  450. NULL,
  451. REG_OPTION_NON_VOLATILE,
  452. KEY_READ | KEY_WRITE,
  453. NULL,
  454. &rhkeyLogQueries,
  455. &dwDisposition);
  456. }
  457. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  458. dwStatus = LOGMAN_INSTALL_ACCESS_DENIED;
  459. DisplayErrorMessage ( dwStatus );
  460. } else if ( ERROR_SUCCESS == dwStatus ) {
  461. dwStatus = CreateDefaultLogQueries( rhkeyLogQueries );
  462. // Todo: Handle failure
  463. }
  464. return dwStatus;
  465. }
  466. DWORD _stdcall
  467. ConnectToRegistry (
  468. LPCTSTR szComputerName,
  469. HKEY& rhkeyLogQueries )
  470. {
  471. DWORD dwStatus = ERROR_SUCCESS;
  472. HKEY hkeyMachine = HKEY_LOCAL_MACHINE;
  473. WCHAR wszComputerName[MAX_COMPUTERNAME_LENGTH+1];
  474. USES_CONVERSION;
  475. wszComputerName[0] = NULL_W;
  476. // Connect to registry on specified machine.
  477. if ( NULL != szComputerName ) {
  478. if ( NULL_T != szComputerName[0] ) {
  479. lstrcpyW ( wszComputerName, T2W ( szComputerName ) );
  480. dwStatus = RegConnectRegistryW (
  481. wszComputerName,
  482. HKEY_LOCAL_MACHINE,
  483. &hkeyMachine );
  484. } else {
  485. hkeyMachine = HKEY_LOCAL_MACHINE;
  486. }
  487. } else {
  488. hkeyMachine = HKEY_LOCAL_MACHINE;
  489. }
  490. if ( ERROR_SUCCESS == dwStatus ) {
  491. assert ( NULL != hkeyMachine );
  492. dwStatus = RegOpenKeyExW (
  493. hkeyMachine,
  494. cwszRegKeyFullLogQueries,
  495. 0,
  496. KEY_ALL_ACCESS,
  497. &rhkeyLogQueries );
  498. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  499. dwStatus = IDS_LOGMAN_REG_ACCESS_DENIED;
  500. } else if ( ERROR_SUCCESS != dwStatus ) {
  501. // Install displays error messages
  502. dwStatus = Install ( hkeyMachine, rhkeyLogQueries );
  503. }
  504. } else {
  505. if ( 0 == lstrlenW ( wszComputerName ) ) {
  506. lstrcpyW ( wszComputerName, cwszLocalComputer );
  507. }
  508. DisplayErrorMessage ( LOGMAN_NO_COMPUTER_CONNECT, wszComputerName );
  509. DisplayErrorMessage ( dwStatus );
  510. dwStatus = LOGMAN_NO_COMPUTER_CONNECT;
  511. }
  512. if ( NULL != hkeyMachine ) {
  513. RegCloseKey ( hkeyMachine );
  514. }
  515. return dwStatus;
  516. }
  517. //
  518. // WriteRegistryLastModified function.
  519. // Copies the current "last modified date" to the registry where
  520. // it is read by the log service.
  521. //
  522. DWORD _stdcall
  523. WriteRegistryLastModified ( HKEY hkeyQuery )
  524. {
  525. LONG dwStatus = ERROR_SUCCESS;
  526. SLQ_TIME_INFO plqLastModified;
  527. SYSTEMTIME stLocalTime;
  528. FILETIME ftLocalTime;
  529. // Get local time for last modified value.
  530. GetLocalTime (&stLocalTime);
  531. SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
  532. plqLastModified.wDataType = SLQ_TT_DTYPE_DATETIME;
  533. plqLastModified.wTimeType = SLQ_TT_TTYPE_LAST_MODIFIED;
  534. plqLastModified.dwAutoMode = SLQ_AUTO_MODE_NONE; // not used.
  535. plqLastModified.llDateTime = *(LONGLONG *)&ftLocalTime;
  536. dwStatus = WriteRegistrySlqTime (
  537. hkeyQuery,
  538. cwszRegLastModified,
  539. &plqLastModified);
  540. return dwStatus;
  541. }
  542. DWORD _stdcall
  543. ValidateProperties (
  544. HKEY hkeyLogQueries,
  545. CPropertyBag* pPropBag,
  546. DWORD* pdwLogType,
  547. LPWSTR szQueryName,
  548. DWORD* pdwNameBufLen )
  549. {
  550. DWORD dwStatus = ERROR_SUCCESS;
  551. HRESULT hr = NOERROR;
  552. LPWSTR szPropBagBuf = NULL;
  553. DWORD dwPropBagBufLen = 0;
  554. DWORD dwPropBagStringLen = 0;
  555. DWORD dwLocalLogType;
  556. // Query key is not necessary for validation, so set it to NULL.
  557. CPropertyUtils cPropertyUtils ( Commands[eComputer].strValue, NULL, pPropBag, NULL, hkeyLogQueries );
  558. USES_CONVERSION;
  559. *pdwLogType = 0;
  560. szQueryName[0] = NULL_W;
  561. // Todo: Version info
  562. // Query type and name are required properties.
  563. hr = DwordFromPropertyBag (
  564. pPropBag,
  565. cwszHtmlLogType,
  566. dwLocalLogType );
  567. if ( SUCCEEDED ( hr ) ) {
  568. if ( SLQ_ALERT != dwLocalLogType ) {
  569. hr = StringFromPropBagAlloc ( pPropBag, cwszHtmlLogName, &szPropBagBuf, &dwPropBagBufLen, &dwPropBagStringLen );
  570. } else {
  571. hr = StringFromPropBagAlloc ( pPropBag, cwszHtmlAlertName, &szPropBagBuf, &dwPropBagBufLen, &dwPropBagStringLen );
  572. }
  573. if ( FAILED ( hr ) ) {
  574. dwStatus = LOGMAN_NO_OBJECT_NAME;
  575. /* } else {
  576. // Validate query name.
  577. // Todo: Length check. Must be <= MAX_PATH;
  578. lstrcpynW ( szTempCheck, szPropBagBuf, MAX_PATH );
  579. szTokenCheck = _tcstok ( szTempCheck, cwszInvalidLogNameChars );
  580. if ( 0 != lstrcmpi (szTempCheck, szTokenCheck ) ) {
  581. dwStatus = LOGMAN_INVALID_QUERY_NAME;
  582. }
  583. */
  584. }
  585. } else {
  586. dwStatus = LOGMAN_NO_OBJECT_LOGTYPE;
  587. }
  588. // At this point, any hr failure is reflected in dwStatus.
  589. if ( ERROR_SUCCESS == dwStatus ) {
  590. if ( NULL == szQueryName
  591. || ( *pdwNameBufLen < ( dwPropBagStringLen + 1 ) ) ) {
  592. dwStatus = ERROR_INSUFFICIENT_BUFFER;
  593. } else {
  594. lstrcpyW ( szQueryName, szPropBagBuf ) ;
  595. }
  596. *pdwNameBufLen = dwPropBagStringLen + 1; // Room for NULL.
  597. *pdwLogType = dwLocalLogType;
  598. }
  599. // If required query type and name exist, then validate all other properties
  600. if ( ERROR_SUCCESS != dwStatus ) {
  601. // Todo: Error message re: Validation failure -or print that and write success messages
  602. // in the "Process object" method.
  603. // Todo: Handle "invalid query name" elsewhere.
  604. if ( LOGMAN_INVALID_QUERY_NAME == dwStatus ) {
  605. DisplayErrorMessage ( dwStatus, szQueryName );
  606. } else {
  607. DisplayErrorMessage ( dwStatus );
  608. }
  609. } else {
  610. // Initialize the query name string in CPropertyUtils, for error message display.
  611. cPropertyUtils.SetQueryName ( szQueryName );
  612. // Validate required parameters first:
  613. if ( SLQ_TRACE_LOG == dwLocalLogType ) {
  614. //DWORD dwKernelValid;
  615. dwStatus = cPropertyUtils.Validate ( IdGuidListProp, dwLocalLogType );
  616. // Todo: Check for kernel flags. Must have Guids or Kernel, cannot have both.
  617. } else {
  618. assert ( SLQ_COUNTER_LOG == dwLocalLogType || SLQ_ALERT == dwLocalLogType );
  619. dwStatus = cPropertyUtils.Validate ( IdCounterListProp, dwLocalLogType );
  620. // Todo: Validate Alert action flags here. If all subfields are messed up,
  621. // do not continue processing (?)
  622. }
  623. // All other fields are non-required
  624. if ( ERROR_SUCCESS == dwStatus ) {
  625. // Handle failures individually? Use exception handling?
  626. if ( SLQ_TRACE_LOG == dwLocalLogType ) {
  627. dwStatus = cPropertyUtils.Validate ( IdTraceBufferSizeProp );
  628. dwStatus = cPropertyUtils.Validate ( IdTraceBufferMinCountProp );
  629. dwStatus = cPropertyUtils.Validate ( IdTraceBufferMaxCountProp );
  630. dwStatus = cPropertyUtils.Validate ( IdTraceBufferFlushIntProp );
  631. } else if ( SLQ_ALERT == dwLocalLogType ) {
  632. dwStatus = cPropertyUtils.Validate ( IdActionFlagsProp );
  633. dwStatus = cPropertyUtils.Validate ( IdCommandFileProp );
  634. // Validated as part of action flags validation dwStatus = cPropertyUtils.Validate ( IdNetworkNameProp );
  635. dwStatus = cPropertyUtils.Validate ( IdUserTextProp );
  636. dwStatus = cPropertyUtils.Validate ( IdPerfLogNameProp );
  637. }
  638. // Properties common to counter and trace logs
  639. if ( SLQ_COUNTER_LOG == dwLocalLogType
  640. || SLQ_TRACE_LOG == dwLocalLogType ) {
  641. dwStatus = cPropertyUtils.Validate ( IdLogFileTypeProp );
  642. dwStatus = cPropertyUtils.Validate ( IdLogFileAutoFormatProp );
  643. dwStatus = cPropertyUtils.Validate ( IdLogFileSerialNumberProp );
  644. dwStatus = cPropertyUtils.Validate ( IdLogFileBaseNameProp );
  645. dwStatus = cPropertyUtils.Validate ( IdLogFileMaxSizeProp );
  646. dwStatus = cPropertyUtils.Validate ( IdLogFileFolderProp );
  647. dwStatus = cPropertyUtils.Validate ( IdEofCommandFileProp );
  648. }
  649. // Properties common to alerts and counter logs
  650. if ( SLQ_COUNTER_LOG == dwLocalLogType
  651. || SLQ_ALERT == dwLocalLogType ) {
  652. dwStatus = cPropertyUtils.Validate ( IdSampleProp );
  653. }
  654. // Properties common to all query types
  655. dwStatus = cPropertyUtils.Validate ( IdCommentProp );
  656. dwStatus = cPropertyUtils.Validate ( IdRestartProp, dwLocalLogType );
  657. dwStatus = cPropertyUtils.Validate ( IdStartProp, dwLocalLogType );
  658. dwStatus = cPropertyUtils.Validate ( IdStopProp, dwLocalLogType );
  659. // Todo: Validation is currently ignored until fully implemented
  660. dwStatus = ERROR_SUCCESS;
  661. } else {
  662. // Display error message re: missing required property.
  663. // Need log-type specific message.
  664. if ( SLQ_COUNTER_LOG == dwLocalLogType ) {
  665. // DisplayErrorMessage ( dwStatus );
  666. } else if ( SLQ_TRACE_LOG == dwLocalLogType ) {
  667. // Attempt to load kernel trace flags
  668. // dwStatus = cPropertyUtils.Validate ( IdTraceFlagsProp );
  669. if ( ERROR_SUCCESS == dwStatus ) {
  670. // Todo: Check for kernel flag. Need either Kernel flag OR provider GUIDs
  671. // and NOT both.
  672. }
  673. } else if ( SLQ_ALERT == dwLocalLogType ) {
  674. }
  675. // Todo: Need status processing method to determine if any required subfields are incorrect.
  676. // If so, then stop processing this HTML file.
  677. // Todo: Validation is currently ignored until fully implemented
  678. dwStatus = ERROR_SUCCESS;
  679. }
  680. }
  681. // Todo: Validation is currently ignored until fully implemented
  682. dwStatus = ERROR_SUCCESS;
  683. return dwStatus;
  684. }
  685. DWORD _stdcall
  686. WriteToRegistry (
  687. HKEY hkeyLogQueries,
  688. CPropertyBag* pPropBag,
  689. LPWSTR szQueryName,
  690. DWORD& rdwLogType )
  691. {
  692. DWORD dwStatus = ERROR_SUCCESS;
  693. HRESULT hr = NOERROR;
  694. HKEY hkeyQuery = NULL;
  695. CPropertyUtils cPropertyUtils ( Commands[eComputer].strValue );
  696. USES_CONVERSION;
  697. // Write all properties to the registry.
  698. // All errors are displayed as messages within this
  699. // routine or its subroutines.
  700. // Create log key
  701. dwStatus = InitializeNewQuery (
  702. hkeyLogQueries,
  703. hkeyQuery,
  704. szQueryName );
  705. if ( ERROR_SUCCESS != dwStatus ) {
  706. if ( LOGMAN_DUP_QUERY_NAME == dwStatus ) {
  707. if ( Commands[eOverwrite].bValue ) {
  708. // If Overwrite option specified, overwrite after displaying warning.
  709. DisplayErrorMessage ( LOGMAN_OVERWRITE_DUP_QUERY, szQueryName );
  710. dwStatus = DeleteQuery ( hkeyLogQueries, szQueryName );
  711. if ( ERROR_SUCCESS == dwStatus ) {
  712. dwStatus = InitializeNewQuery (
  713. hkeyLogQueries,
  714. hkeyQuery,
  715. szQueryName );
  716. if ( ERROR_SUCCESS != dwStatus ) {
  717. DisplayErrorMessage ( dwStatus );
  718. }
  719. }
  720. } else {
  721. DisplayErrorMessage ( dwStatus, szQueryName );
  722. }
  723. } else {
  724. DisplayErrorMessage ( dwStatus );
  725. }
  726. }
  727. // If failed before this point, do not continue loading.
  728. if ( ERROR_SUCCESS == dwStatus ) {
  729. // Use log key to write properties to the registry.
  730. // When loading properties, continue even if errors.
  731. //
  732. // On error, nothing is written to the registry.
  733. // In this case, the default value will
  734. // be read in by the log service.
  735. // Note: StringFromPropBagAlloc and AddStringToMszBuffer
  736. // allocate data buffers that must be deleted by the caller.
  737. // These methods also indicate length of string returned
  738. // vs. length of buffer returned.
  739. // hkeyQueryList is not required for writing to the the registry,
  740. // so leave it NULL.
  741. // Todo: Some fields will require validation in this method,
  742. // to ensure that default values are used instead of incorrect values.
  743. cPropertyUtils.SetQueryName ( szQueryName );
  744. cPropertyUtils.SetPropertyBag ( pPropBag );
  745. cPropertyUtils.SetQueryKey ( hkeyQuery );
  746. // Required properties: Counter list for counter logs and alerts,
  747. // provider guid list or kernel flags for trace logs.
  748. if ( SLQ_TRACE_LOG == rdwLogType ) {
  749. hr = cPropertyUtils.BagToRegistry ( IdGuidListProp, rdwLogType );
  750. } else {
  751. assert ( SLQ_COUNTER_LOG == rdwLogType || SLQ_ALERT == rdwLogType );
  752. hr = cPropertyUtils.BagToRegistry ( IdCounterListProp, rdwLogType );
  753. }
  754. if ( FAILED ( hr ) ) {
  755. // Todo: At this point, the problem would be an internal error,
  756. // because validated previous to this.
  757. // Todo: Type - specific error message
  758. if ( SLQ_COUNTER_LOG == rdwLogType ) {
  759. } else if ( SLQ_TRACE_LOG == rdwLogType ) {
  760. // Attemp to load kernel trace flags
  761. hr = cPropertyUtils.BagToRegistry ( IdTraceFlagsProp );
  762. if ( FAILED ( hr ) ) {
  763. //Todo: Check for kernel flag. Need either Kernel flag OR provider GUIDs
  764. }
  765. } else if ( SLQ_ALERT == rdwLogType ) {
  766. // Todo: Special case to write action properties. Only write correct ones?
  767. // Or stop processing if any invalid?
  768. }
  769. } else {
  770. if ( SLQ_TRACE_LOG == rdwLogType ) {
  771. hr = cPropertyUtils.BagToRegistry ( IdTraceBufferSizeProp );
  772. hr = cPropertyUtils.BagToRegistry ( IdTraceBufferMinCountProp );
  773. hr = cPropertyUtils.BagToRegistry ( IdTraceBufferMaxCountProp );
  774. hr = cPropertyUtils.BagToRegistry ( IdTraceBufferFlushIntProp );
  775. } else if ( SLQ_ALERT == rdwLogType ) {
  776. hr = cPropertyUtils.BagToRegistry ( IdActionFlagsProp );
  777. hr = cPropertyUtils.BagToRegistry ( IdCommandFileProp );
  778. hr = cPropertyUtils.BagToRegistry ( IdNetworkNameProp );
  779. hr = cPropertyUtils.BagToRegistry ( IdUserTextProp );
  780. hr = cPropertyUtils.BagToRegistry ( IdPerfLogNameProp );
  781. }
  782. hr = NOERROR;
  783. // Todo: ensure dwLogType is valid
  784. // Properties common to counter and trace logs
  785. if ( SLQ_COUNTER_LOG == rdwLogType
  786. || SLQ_TRACE_LOG == rdwLogType ) {
  787. hr = cPropertyUtils.BagToRegistry ( IdLogFileMaxSizeProp );
  788. hr = cPropertyUtils.BagToRegistry ( IdLogFileTypeProp );
  789. hr = cPropertyUtils.BagToRegistry ( IdLogFileAutoFormatProp );
  790. hr = cPropertyUtils.BagToRegistry ( IdLogFileSerialNumberProp );
  791. hr = cPropertyUtils.BagToRegistry ( IdLogFileBaseNameProp );
  792. hr = cPropertyUtils.BagToRegistry ( IdLogFileMaxSizeProp );
  793. hr = cPropertyUtils.BagToRegistry ( IdLogFileFolderProp );
  794. hr = cPropertyUtils.BagToRegistry ( IdEofCommandFileProp );
  795. hr = NOERROR;
  796. }
  797. // Properties common to alerts and counter logs
  798. if ( SLQ_COUNTER_LOG == rdwLogType
  799. || SLQ_ALERT == rdwLogType ) {
  800. // Time values default if error
  801. hr = cPropertyUtils.BagToRegistry ( IdSampleProp );
  802. hr = NOERROR;
  803. }
  804. // Properties common to all query types
  805. hr = cPropertyUtils.BagToRegistry ( IdCommentProp );
  806. hr = cPropertyUtils.BagToRegistry ( IdRestartProp, rdwLogType );
  807. hr = cPropertyUtils.BagToRegistry ( IdStartProp, rdwLogType );
  808. hr = cPropertyUtils.BagToRegistry ( IdStopProp, rdwLogType );
  809. hr = NOERROR;
  810. dwStatus = ERROR_SUCCESS; // Non-required fields
  811. // Required fields, ending the creation process.
  812. // Reset the log type from "new" to real type
  813. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegLogType, &rdwLogType );
  814. if ( ERROR_SUCCESS == dwStatus ) {
  815. dwStatus = WriteRegistryLastModified ( hkeyQuery );
  816. }
  817. if ( ERROR_SUCCESS == dwStatus ) {
  818. DisplayErrorMessage ( IDS_LOGMAN_QUERY_CONFIG_SUCCESS, szQueryName );
  819. } /* else //Todo: Error message re: unable to complete query in the registry */
  820. }
  821. if ( FAILED ( hr ) || ( ERROR_SUCCESS != dwStatus ) ) {
  822. RegCloseKey ( hkeyQuery );
  823. hkeyQuery = NULL;
  824. DeleteQuery ( hkeyLogQueries, szQueryName );
  825. }
  826. }
  827. if ( NULL != hkeyQuery ) {
  828. RegCloseKey ( hkeyQuery );
  829. }
  830. return dwStatus;
  831. }
  832. DWORD _stdcall
  833. ProcessSettingsObject (
  834. HKEY hkeyLogQueries,
  835. CPropertyBag* pPropBag )
  836. {
  837. DWORD dwStatus = ERROR_SUCCESS;
  838. DWORD dwLogType;
  839. WCHAR szQueryName [MAX_PATH]; // Todo: Remove length restriction
  840. DWORD dwNameBufLen = MAX_PATH;
  841. // Validate all properties
  842. // Todo: Ensure that at least one provider, counter, or alert was added.
  843. dwStatus = ValidateProperties (
  844. hkeyLogQueries,
  845. pPropBag,
  846. &dwLogType,
  847. szQueryName,
  848. &dwNameBufLen );
  849. // ValidateProperties() displays messages for all errors
  850. if ( ERROR_SUCCESS == dwStatus ) {
  851. // Write all properties to the registry.
  852. // WriteToRegistry() displays messages for all errors
  853. dwStatus = WriteToRegistry (
  854. hkeyLogQueries,
  855. pPropBag,
  856. szQueryName,
  857. dwLogType );
  858. }
  859. return dwStatus;
  860. }
  861. DWORD _stdcall
  862. ProcessSettingsFile (
  863. LPCTSTR szComputerName,
  864. LPCTSTR szFileName )
  865. {
  866. DWORD dwStatus = ERROR_SUCCESS;
  867. LPTSTR szFirstObject = NULL;
  868. // Open file
  869. dwStatus = LoadSettingsFile ( szFileName, szFirstObject );
  870. if ( ERROR_SUCCESS == dwStatus && NULL != szFirstObject ) {
  871. HKEY hkeyLogQueries = NULL;
  872. dwStatus = ConnectToRegistry (
  873. szComputerName,
  874. hkeyLogQueries );
  875. if ( ERROR_SUCCESS == dwStatus ) {
  876. LPTSTR szCurrentObject = NULL;
  877. LPTSTR szNextObject = NULL;
  878. BOOL bAtLeastOneSysmonObjectRead = FALSE;
  879. assert ( NULL != hkeyLogQueries );
  880. szCurrentObject = szFirstObject;
  881. while ( ERROR_SUCCESS == dwStatus && NULL != szCurrentObject ) {
  882. CPropertyBag PropBag;
  883. dwStatus = PropBag.LoadData ( szCurrentObject, szNextObject );
  884. if ( ERROR_SUCCESS == dwStatus ) {
  885. dwStatus = ProcessSettingsObject (
  886. hkeyLogQueries,
  887. &PropBag );
  888. if ( ERROR_SUCCESS == dwStatus ) {
  889. bAtLeastOneSysmonObjectRead = TRUE;
  890. } else {
  891. if ( LOGMAN_NO_SYSMON_OBJECT != dwStatus ) {
  892. bAtLeastOneSysmonObjectRead = TRUE;
  893. }
  894. // Error messages handled (displayed) within
  895. // ProcessSettingsObject(), so reset dwStatus
  896. dwStatus = ERROR_SUCCESS;
  897. }
  898. } else {
  899. // Handle (display) error message, then reset
  900. // dwStatus to continue.
  901. if ( LOGMAN_NO_SYSMON_OBJECT != dwStatus ) {
  902. DisplayErrorMessage ( dwStatus );
  903. }
  904. dwStatus = ERROR_SUCCESS;
  905. }
  906. szCurrentObject = szNextObject;
  907. }
  908. if ( !bAtLeastOneSysmonObjectRead ) {
  909. dwStatus = LOGMAN_NO_SYSMON_OBJECT;
  910. DisplayErrorMessage ( dwStatus );
  911. }
  912. RegCloseKey ( hkeyLogQueries );
  913. } // else error message displayed by ConnectToRegistry()
  914. } // else error message displayed by LoadSettingsFile()
  915. // Delete data buffer allocated by LoadSettingsFile
  916. if ( NULL != szFirstObject ) {
  917. delete szFirstObject;
  918. }
  919. return dwStatus;
  920. }
  921. DWORD _stdcall
  922. ConnectToQuery (
  923. LPCTSTR szComputerName,
  924. LPCTSTR szQueryName,
  925. HKEY& rhkeyQuery )
  926. {
  927. DWORD dwStatus = ERROR_SUCCESS;
  928. HKEY hkeyQuery = NULL;
  929. HKEY hkeyLogQueries = NULL;
  930. USES_CONVERSION;
  931. dwStatus = ConnectToRegistry (
  932. szComputerName,
  933. hkeyLogQueries );
  934. if ( ERROR_SUCCESS == dwStatus ) {
  935. dwStatus = RegOpenKeyEx (
  936. hkeyLogQueries,
  937. szQueryName,
  938. 0,
  939. KEY_ALL_ACCESS,
  940. &hkeyQuery );
  941. if ( ERROR_SUCCESS != dwStatus ) {
  942. if ( ERROR_ACCESS_DENIED == dwStatus ) {
  943. dwStatus = LOGMAN_REG_ACCESS_DENIED;
  944. DisplayErrorMessage ( dwStatus );
  945. } else if ( ERROR_FILE_NOT_FOUND == dwStatus ) {
  946. dwStatus = LOGMAN_NO_QUERY_CONNECT;
  947. DisplayErrorMessage ( dwStatus, T2W( szQueryName ) );
  948. }
  949. }
  950. }
  951. RegCloseKey ( hkeyLogQueries );
  952. rhkeyQuery = hkeyQuery;
  953. return dwStatus;
  954. }
  955. #pragma warning ( disable : 4706 )
  956. DWORD _stdcall
  957. StartQuery (
  958. LPCTSTR szComputerName,
  959. LPCTSTR szQueryName )
  960. {
  961. DWORD dwStatus = ERROR_SUCCESS;
  962. HKEY hkeyQuery = NULL;
  963. USES_CONVERSION;
  964. // ConnectToQuery displays any errors
  965. dwStatus = ConnectToQuery ( szComputerName, szQueryName, hkeyQuery );
  966. if ( ERROR_SUCCESS == dwStatus ) {
  967. SLQ_TIME_INFO stiData;
  968. DWORD dwRegValue;
  969. BOOL bSetStopToMax;
  970. // Todo: Warn the user if start mode is not manual.
  971. // Set start mode to manual, start time = MIN_TIME_VALUE
  972. memset (&stiData, 0, sizeof(stiData));
  973. stiData.wTimeType = SLQ_TT_TTYPE_START;
  974. stiData.wDataType = SLQ_TT_DTYPE_DATETIME;
  975. stiData.dwAutoMode = SLQ_AUTO_MODE_NONE;
  976. stiData.llDateTime = MIN_TIME_VALUE;
  977. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStartTime, &stiData );
  978. if ( ERROR_SUCCESS == dwStatus ) {
  979. // If stop time mode set to manual, or StopAt with time before Now,
  980. // set the mode to Manual, value to MAX_TIME_VALUE
  981. bSetStopToMax = FALSE;
  982. dwStatus = ReadRegistrySlqTime ( hkeyQuery, cwszRegStopTime, &stiData );
  983. if ( ERROR_SUCCESS == dwStatus ) {
  984. if ( SLQ_AUTO_MODE_NONE == stiData.dwAutoMode ) {
  985. bSetStopToMax = TRUE;
  986. } else if ( SLQ_AUTO_MODE_AT == stiData.dwAutoMode ) {
  987. SYSTEMTIME stLocalTime;
  988. FILETIME ftLocalTime;
  989. LONGLONG llLocalTime;
  990. // get local time
  991. GetLocalTime (&stLocalTime);
  992. SystemTimeToFileTime (&stLocalTime, &ftLocalTime);
  993. llLocalTime = *(LONGLONG*)&ftLocalTime;
  994. if ( llLocalTime >= stiData.llDateTime ) {
  995. bSetStopToMax = TRUE;
  996. }
  997. }
  998. }
  999. if ( ERROR_SUCCESS == dwStatus && bSetStopToMax ) {
  1000. assert( SLQ_TT_DTYPE_DATETIME == stiData.wDataType );
  1001. stiData.dwAutoMode = SLQ_AUTO_MODE_NONE;
  1002. stiData.llDateTime = MAX_TIME_VALUE;
  1003. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStopTime, &stiData );
  1004. }
  1005. }
  1006. // Service needs to distinguish between Running and Start Pending
  1007. // at service startup, so always set state to start pending.
  1008. // Todo: Check to see if running, before executing this.
  1009. if ( ERROR_SUCCESS == dwStatus ) {
  1010. dwRegValue = SLQ_QUERY_START_PENDING;
  1011. dwStatus = WriteRegistryDwordValue (
  1012. hkeyQuery,
  1013. cwszRegCurrentState,
  1014. &dwRegValue );
  1015. }
  1016. // Set LastModified
  1017. if ( ERROR_SUCCESS == dwStatus ) {
  1018. dwStatus = WriteRegistryLastModified ( hkeyQuery );
  1019. }
  1020. // Start the service on the target machine
  1021. if ( ERROR_SUCCESS == dwStatus ) {
  1022. DWORD dwTimeout = 3;
  1023. DWORD dwState = 0;
  1024. dwStatus = Synchronize ( szComputerName );
  1025. while (--dwTimeout && ERROR_SUCCESS == dwStatus ) {
  1026. dwStatus = GetState ( szComputerName, dwState );
  1027. if ( SERVICE_RUNNING == dwState ) {
  1028. break;
  1029. }
  1030. }
  1031. if ( ERROR_SUCCESS == dwStatus && SERVICE_RUNNING != dwState ) {
  1032. dwStatus = LOGMAN_START_TIMED_OUT;
  1033. }
  1034. }
  1035. if ( ERROR_SUCCESS != dwStatus ) {
  1036. if ( LOGMAN_START_TIMED_OUT == dwStatus ) {
  1037. DisplayErrorMessage ( dwStatus, T2W(szQueryName) );
  1038. } else {
  1039. DisplayErrorMessage ( LOGMAN_START_FAILED, T2W(szQueryName) );
  1040. DisplayErrorMessage ( dwStatus );
  1041. }
  1042. }
  1043. }
  1044. if ( NULL != hkeyQuery ) {
  1045. RegCloseKey ( hkeyQuery );
  1046. }
  1047. if ( ERROR_SUCCESS == dwStatus ) {
  1048. DisplayErrorMessage ( LOGMAN_QUERY_START_SUCCESS, T2W(szQueryName) );
  1049. }
  1050. return dwStatus;
  1051. }
  1052. #pragma warning ( default: 4706 )
  1053. #pragma warning ( disable: 4706 )
  1054. DWORD _stdcall
  1055. StopQuery (
  1056. LPCTSTR szComputerName,
  1057. LPCTSTR szQueryName )
  1058. {
  1059. DWORD dwStatus = ERROR_SUCCESS;
  1060. HKEY hkeyQuery = NULL;
  1061. USES_CONVERSION;
  1062. // ConnectToQuery displays any errors
  1063. dwStatus = ConnectToQuery ( szComputerName, szQueryName, hkeyQuery );
  1064. if ( ERROR_SUCCESS == dwStatus ) {
  1065. SLQ_TIME_INFO stiData;
  1066. DWORD dwRestartMode = 0;
  1067. // If query is set to restart on end, clear the restart flag.
  1068. dwStatus = ReadRegistryDwordValue ( hkeyQuery, cwszRegRestart, &dwRestartMode );
  1069. // Todo: Warn user
  1070. if ( ERROR_SUCCESS == dwStatus && SLQ_AUTO_MODE_NONE != dwRestartMode ) {
  1071. dwRestartMode = SLQ_AUTO_MODE_NONE;
  1072. dwStatus = WriteRegistryDwordValue ( hkeyQuery, cwszRegRestart, &dwRestartMode, REG_BINARY );
  1073. }
  1074. // Set stop mode to manual, stop time to MIN_TIME_VALUE
  1075. if ( ERROR_SUCCESS == dwStatus ) {
  1076. memset (&stiData, 0, sizeof(stiData));
  1077. stiData.wTimeType = SLQ_TT_TTYPE_STOP;
  1078. stiData.wDataType = SLQ_TT_DTYPE_DATETIME;
  1079. stiData.dwAutoMode = SLQ_AUTO_MODE_NONE;
  1080. stiData.llDateTime = MIN_TIME_VALUE;
  1081. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStopTime, &stiData );
  1082. }
  1083. // If start time mode set to manual, set the value to MAX_TIME_VALUE
  1084. if ( ERROR_SUCCESS == dwStatus ) {
  1085. dwStatus = ReadRegistrySlqTime ( hkeyQuery, cwszRegStartTime, &stiData );
  1086. if ( ERROR_SUCCESS == dwStatus
  1087. && SLQ_AUTO_MODE_NONE == stiData.dwAutoMode ) {
  1088. assert( SLQ_TT_DTYPE_DATETIME == stiData.wDataType );
  1089. stiData.llDateTime = MAX_TIME_VALUE;
  1090. dwStatus = WriteRegistrySlqTime ( hkeyQuery, cwszRegStartTime, &stiData );
  1091. }
  1092. }
  1093. // Set LastModified
  1094. if ( ERROR_SUCCESS == dwStatus ) {
  1095. dwStatus = WriteRegistryLastModified ( hkeyQuery );
  1096. }
  1097. // Start the service on the target machine
  1098. if ( ERROR_SUCCESS == dwStatus ) {
  1099. DWORD dwTimeout = 3;
  1100. DWORD dwState = 0;
  1101. dwStatus = Synchronize ( szComputerName );
  1102. while (--dwTimeout && ERROR_SUCCESS == dwStatus ) {
  1103. dwStatus = GetState ( szComputerName, dwState );
  1104. if ( SERVICE_STOPPED == dwState ) {
  1105. break;
  1106. }
  1107. }
  1108. if ( ERROR_SUCCESS == dwStatus && SERVICE_STOPPED != dwState ) {
  1109. dwStatus = LOGMAN_STOP_TIMED_OUT;
  1110. }
  1111. }
  1112. if ( ERROR_SUCCESS != dwStatus ) {
  1113. if ( LOGMAN_STOP_TIMED_OUT == dwStatus ) {
  1114. DisplayErrorMessage ( dwStatus, T2W(szQueryName) );
  1115. } else {
  1116. DisplayErrorMessage ( LOGMAN_STOP_FAILED, T2W(szQueryName) );
  1117. DisplayErrorMessage ( dwStatus );
  1118. }
  1119. }
  1120. }
  1121. if ( NULL != hkeyQuery ) {
  1122. RegCloseKey ( hkeyQuery );
  1123. }
  1124. if ( ERROR_SUCCESS == dwStatus ) {
  1125. DisplayErrorMessage ( LOGMAN_QUERY_STOP_SUCCESS, T2W(szQueryName) );
  1126. }
  1127. return dwStatus;
  1128. }
  1129. #pragma warning ( default: 4706 )
  1130. DWORD _stdcall
  1131. GetState (
  1132. LPCTSTR szComputerName,
  1133. DWORD& rdwState )
  1134. {
  1135. DWORD dwStatus = ERROR_SUCCESS;
  1136. SERVICE_STATUS ssData;
  1137. SC_HANDLE hSC;
  1138. SC_HANDLE hLogService;
  1139. rdwState = 0; // Error by default.
  1140. // open SC database
  1141. hSC = OpenSCManager ( szComputerName, NULL, SC_MANAGER_CONNECT);
  1142. if (hSC != NULL) {
  1143. // open service
  1144. hLogService = OpenServiceW (
  1145. hSC,
  1146. cwszLogService,
  1147. SERVICE_INTERROGATE );
  1148. if (hLogService != NULL) {
  1149. if ( ControlService (
  1150. hLogService,
  1151. SERVICE_CONTROL_INTERROGATE,
  1152. &ssData)) {
  1153. rdwState = ssData.dwCurrentState;
  1154. } else {
  1155. dwStatus = GetLastError();
  1156. rdwState = SERVICE_STOPPED;
  1157. // *** error message
  1158. assert (dwStatus != 0);
  1159. }
  1160. CloseServiceHandle (hLogService);
  1161. } else {
  1162. // *** error message
  1163. dwStatus = GetLastError();
  1164. assert (dwStatus != 0);
  1165. }
  1166. CloseServiceHandle (hSC);
  1167. } else {
  1168. // *** error message
  1169. dwStatus = GetLastError();
  1170. assert (dwStatus != 0);
  1171. } // OpenSCManager
  1172. if ( ERROR_SERVICE_NOT_ACTIVE == dwStatus
  1173. || ERROR_SERVICE_REQUEST_TIMEOUT == dwStatus ) {
  1174. rdwState = SERVICE_STOPPED;
  1175. dwStatus = ERROR_SUCCESS;
  1176. }
  1177. return dwStatus;
  1178. }
  1179. #pragma warning ( disable: 4706 )
  1180. DWORD _stdcall
  1181. Synchronize (
  1182. LPCTSTR szComputerName )
  1183. {
  1184. // If the service is running, tell it to synchronize itself,
  1185. // Check the state afterwards to see if it got the message.
  1186. // If stop pending or stopped, wait until the service is
  1187. // stopped and then attempt to start it. The service
  1188. // synchronizes itself from the registry when it is started.
  1189. // Return ERROR_SUCCESS for success, other for failure.
  1190. SC_HANDLE hSC = NULL;
  1191. SC_HANDLE hLogService = NULL;
  1192. SERVICE_STATUS ssData;
  1193. DWORD dwCurrentState;
  1194. DWORD dwTimeout = 25;
  1195. LONG dwStatus = ERROR_SUCCESS;
  1196. dwStatus = GetState ( szComputerName, dwCurrentState );
  1197. if ( ERROR_SUCCESS == dwStatus && 0 != dwCurrentState ) {
  1198. // open SC database
  1199. hSC = OpenSCManager ( szComputerName, NULL, SC_MANAGER_CONNECT);
  1200. if ( NULL != hSC ) {
  1201. // open service
  1202. hLogService = OpenServiceW (
  1203. hSC,
  1204. cwszLogService,
  1205. SERVICE_USER_DEFINED_CONTROL
  1206. | SERVICE_START );
  1207. if ( NULL != hLogService ) {
  1208. if ( ( SERVICE_STOPPED != dwCurrentState )
  1209. && ( SERVICE_STOP_PENDING != dwCurrentState ) ) {
  1210. // Wait 100 milliseconds before synchronizing service,
  1211. // to ensure that registry values are written.
  1212. Sleep ( 100 );
  1213. ControlService (
  1214. hLogService,
  1215. SERVICE_CONTROL_SYNCHRONIZE,
  1216. &ssData);
  1217. dwCurrentState = ssData.dwCurrentState;
  1218. }
  1219. // Make sure that the ControlService call reached the service
  1220. // while it was in run state.
  1221. if ( ( SERVICE_STOPPED == dwCurrentState )
  1222. || ( SERVICE_STOP_PENDING == dwCurrentState ) ) {
  1223. if ( SERVICE_STOP_PENDING == dwCurrentState ) {
  1224. // wait for the service to stop before starting it.
  1225. while ( --dwTimeout && ERROR_SUCCESS == dwStatus ) {
  1226. dwStatus = GetState ( szComputerName, dwCurrentState );
  1227. if ( SERVICE_STOP_PENDING == dwCurrentState ) {
  1228. Sleep(200);
  1229. } else {
  1230. break;
  1231. }
  1232. }
  1233. }
  1234. dwTimeout = 25;
  1235. if ( SERVICE_STOPPED == dwCurrentState ) {
  1236. if ( StartService (hLogService, 0, NULL) ) {
  1237. // wait for the service to start or stop
  1238. // before returning
  1239. while ( --dwTimeout && ERROR_SUCCESS == dwStatus ) {
  1240. dwStatus = GetState ( szComputerName, dwCurrentState );
  1241. if ( SERVICE_START_PENDING == dwCurrentState ) {
  1242. Sleep(200);
  1243. } else {
  1244. break;
  1245. }
  1246. }
  1247. } else {
  1248. dwStatus = GetLastError();
  1249. }
  1250. } else {
  1251. // *** error message
  1252. }
  1253. // *** ensure that dwCurrentState is not stopped?
  1254. }
  1255. }
  1256. CloseServiceHandle ( hLogService );
  1257. } else {
  1258. dwStatus = GetLastError();
  1259. }
  1260. CloseServiceHandle (hSC);
  1261. } else {
  1262. dwStatus = GetLastError();
  1263. }
  1264. // Todo: Update Auto Start service config
  1265. return dwStatus;
  1266. }
  1267. #pragma warning ( default : 4706 )
  1268. int __cdecl
  1269. _tmain (
  1270. INT argc,
  1271. LPTSTR argv[] )
  1272. {
  1273. DWORD dwStatus = 0;
  1274. // Accept user input.
  1275. // The command line arguments are the objects to sample.
  1276. // If no user input, then display help.
  1277. ParseCmd( argc, argv );
  1278. if (Commands[eSettings].bDefined) {
  1279. dwStatus = ProcessSettingsFile (
  1280. Commands[eComputer].strValue,
  1281. Commands[eSettings].strValue );
  1282. // Error messages displayed within ProcessSettingsFile method
  1283. }
  1284. if ( Commands[eStart].bDefined ) {
  1285. dwStatus = StartQuery (
  1286. Commands[eComputer].strValue,
  1287. Commands[eName].strValue
  1288. );
  1289. // Error messages displayed within StartQuery method
  1290. }
  1291. if ( Commands[eStop].bDefined ) {
  1292. dwStatus = StopQuery (
  1293. Commands[eComputer].strValue,
  1294. Commands[eName].strValue
  1295. );
  1296. // Error messages displayed within StopQuery method
  1297. }
  1298. // Error messages displayed within submethods, so reset dwStatus.
  1299. dwStatus = 0;
  1300. FreeCmd();
  1301. return dwStatus;
  1302. }