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.

1532 lines
40 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. ELTEST.C
  5. Abstract:
  6. Test Routines for the EventLog.
  7. THINGS I WANT THIS TO DO...
  8. AddReg <ServerName> <logname> <EntryName> <EventMessageFile>
  9. <CategoryMessageFile> <CategoryCount> <ParameterMessageFile>
  10. <TypesSupported> - Creates A Registry Entry.
  11. eltest addreg application mytest mf= eltest.dll cat=
  12. CreateMessageFile <??? Is this possible ???>
  13. WriteEvent <ServerName> <EventSource> <Type> <Category> <EventId> <UserSid?>
  14. <NumStrings> <Strings> <RawData>
  15. ReadLog <Server> <LogFile> <ReadFlags> <RecordOffset> <bufSize>
  16. If LogFile isn't one of the popular ones, then it could be a backup
  17. logfile.
  18. GetNumEvents <Server> <LogFile>
  19. GetOldest <Server> <LogFile>
  20. Clear <Server> <LogFile>
  21. Backup <Server> <LogFile> <BackupFile>
  22. LOOPTESTS....
  23. I should be able to run this test like mprtest such that it doesn't leave
  24. the test process until told. This way we can register an event source,
  25. then if we call WriteEvent without a specified EventSource, it will use
  26. the stored source. Calling RegisterEventSource twice without calling
  27. DeRegisterSource would be an error. (Or better yet, I could keep a table
  28. of sources and handles).
  29. RegisterEventSource <EventSource>
  30. DeRegisterSource <EventSource>
  31. PROTOTYPES FOR FUNCTION....
  32. BOOL
  33. CloseEventLog (
  34. HANDLE hEventLog
  35. )
  36. BOOL
  37. DeregisterEventSource (
  38. HANDLE hEventLog
  39. )
  40. BOOL
  41. NotifyChangeEventLog(
  42. HANDLE hEventLog,
  43. HANDLE hEvent
  44. )
  45. BOOL
  46. GetNumberOfEventLogRecords (
  47. HANDLE hEventLog,
  48. PDWORD NumberOfRecords
  49. )
  50. BOOL
  51. GetOldestEventLogRecord (
  52. HANDLE hEventLog,
  53. PDWORD OldestRecord
  54. )
  55. BOOL
  56. ClearEventLogW (
  57. HANDLE hEventLog,
  58. LPCWSTR BackupFileName
  59. )
  60. BOOL
  61. BackupEventLogW (
  62. HANDLE hEventLog,
  63. LPCWSTR BackupFileName
  64. )
  65. HANDLE
  66. OpenEventLogW (
  67. LPCWSTR UNCServerName,
  68. LPCWSTR ModuleName
  69. )
  70. HANDLE
  71. RegisterEventSourceW (
  72. LPCWSTR UNCServerName,
  73. LPCWSTR ModuleName
  74. )
  75. HANDLE
  76. OpenBackupEventLogW (
  77. LPCWSTR UNCServerName,
  78. LPCWSTR FileName
  79. )
  80. BOOL
  81. ReadEventLogW (
  82. HANDLE hEventLog,
  83. DWORD dwReadFlags,
  84. DWORD dwRecordOffset,
  85. LPVOID lpBuffer,
  86. DWORD nNumberOfBytesToRead,
  87. DWORD *pnBytesRead,
  88. DWORD *pnMinNumberOfBytesNeeded
  89. )
  90. BOOL
  91. ReportEventW (
  92. HANDLE hEventLog,
  93. WORD wType,
  94. WORD wCategory OPTIONAL,
  95. DWORD dwEventID,
  96. PSID lpUserSid OPTIONAL,
  97. WORD wNumStrings,
  98. DWORD dwDataSize,
  99. LPCWSTR *lpStrings OPTIONAL,
  100. LPVOID lpRawData OPTIONAL
  101. )
  102. Author:
  103. Dan Lafferty (danl) 09-March-1994
  104. Environment:
  105. User Mode - Win32
  106. Revision History:
  107. 09-Mar-1994 danl
  108. created
  109. --*/
  110. //
  111. // INCLUDES
  112. //
  113. #define UNICODE 1
  114. #include <nt.h> // DbgPrint prototype
  115. #include <ntrtl.h> // DbgPrint prototype
  116. #include <nturtl.h> // needed for winbase.h
  117. #include <stdlib.h> // atoi
  118. #include <stdio.h> // printf
  119. #include <conio.h> // getch
  120. #include <string.h> // strcmp
  121. #include <windows.h> // win32 typedefs
  122. #include <tstr.h> // Unicode
  123. #include <debugfmt.h> // FORMAT_LPTSTR
  124. //------------------
  125. // DEFINES
  126. //------------------
  127. #define APPLICATION_LOG "Application"
  128. #define SYSTEM_LOG "System"
  129. #define SECURITY_LOG "Security"
  130. #define REG_APPLICATION_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\"
  131. #define REG_SYSTEM_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\"
  132. #define REG_SECURITY_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security\\"
  133. #define EVENT_SOURCE_NAME "tevent"
  134. #define MSG_DLL "%SystemRoot%\\System32\\tevent.dll"
  135. #define VALUE_EVENT_MF TEXT("EventMessageFile")
  136. #define VALUE_CATEGORY_MF TEXT("CategoryMessageFile")
  137. #define VALUE_PARAMETER_MF TEXT("ParameterMessageFile")
  138. #define VALUE_TYPES_SUPPORTED TEXT("TypesSupported")
  139. #define VALUE_CATEGORY_COUNT TEXT("CategoryCount")
  140. #define TYPES_SUPPORTED (EVENTLOG_ERROR_TYPE | \
  141. EVENTLOG_WARNING_TYPE | \
  142. EVENTLOG_INFORMATION_TYPE)
  143. //----------------------
  144. // GLOBALS
  145. //----------------------
  146. LPTSTR ApplLogRegName=TEXT(REG_APPLICATION_KEY);
  147. LPTSTR SysLogRegName =TEXT(REG_SYSTEM_KEY);
  148. LPTSTR SecLogRegName =TEXT(REG_SECURITY_KEY);
  149. LPTSTR ApplLogName = TEXT(APPLICATION_LOG);
  150. LPTSTR SysLogName = TEXT(SYSTEM_LOG);
  151. LPTSTR SecLogName = TEXT(SECURITY_LOG);
  152. //----------------------
  153. // FUNCTION PROTOTYPES
  154. //----------------------
  155. VOID
  156. AddRegUsage(VOID);
  157. DWORD
  158. AddSourceToRegistry(
  159. IN LPTSTR ServerName,
  160. IN LPTSTR LogName,
  161. IN LPTSTR EventSourceName,
  162. IN LPTSTR *argv,
  163. IN DWORD argc
  164. );
  165. BOOL
  166. ConvertToUnicode(
  167. OUT LPWSTR *UnicodeOut,
  168. IN LPSTR AnsiIn
  169. );
  170. DWORD
  171. DelSourceInRegistry(
  172. IN LPTSTR ServerName,
  173. IN LPTSTR LogName,
  174. IN LPTSTR EventSourceName
  175. );
  176. VOID
  177. DisplayStatus (
  178. IN LPTSTR ServiceName,
  179. IN LPTSTR DisplayName,
  180. IN LPSERVICE_STATUS ServiceStatus
  181. );
  182. BOOL
  183. MakeArgsUnicode (
  184. DWORD argc,
  185. PCHAR argv[]
  186. );
  187. BOOL
  188. ProcessArgs (
  189. LPTSTR ServerName,
  190. DWORD argc,
  191. LPTSTR argv[]
  192. );
  193. VOID
  194. Usage(
  195. VOID);
  196. VOID
  197. ConfigUsage(VOID);
  198. VOID
  199. CreateUsage(VOID);
  200. VOID
  201. QueryUsage(VOID);
  202. LONG
  203. wtol(
  204. IN LPWSTR string
  205. );
  206. VOID
  207. UserInputLoop(
  208. LPTSTR ServerName
  209. );
  210. DWORD
  211. ReadLogFile(
  212. LPTSTR ServerName,
  213. LPTSTR LogName,
  214. IN LPTSTR *argv,
  215. IN DWORD argc
  216. );
  217. VOID
  218. ReadLogUsage(VOID);
  219. VOID
  220. DisplayRecord(
  221. PEVENTLOGRECORD pElRecord,
  222. BOOL PrintTheHeader
  223. );
  224. /****************************************************************************/
  225. VOID __cdecl
  226. main (
  227. DWORD argc,
  228. PCHAR argvAnsi[]
  229. )
  230. /*++
  231. Routine Description:
  232. Allows manual testing of the EVENTLOG API.
  233. eltest
  234. Arguments:
  235. Return Value:
  236. --*/
  237. {
  238. UCHAR i;
  239. DWORD j;
  240. DWORD argIndex;
  241. LPTSTR pServerName=NULL;
  242. LPTSTR *argv;
  243. if (argc <2) {
  244. Usage();
  245. return;
  246. }
  247. //
  248. // Make the arguments unicode if necessary.
  249. //
  250. #ifdef UNICODE
  251. if (!MakeArgsUnicode(argc, argvAnsi)) {
  252. return;
  253. }
  254. #endif
  255. argv = (LPTSTR *)argvAnsi;
  256. argIndex = 1;
  257. if (STRNCMP (argv[1], TEXT("\\\\"), 2) == 0) {
  258. pServerName = argv[1];
  259. argIndex = 2; // skip over servername.
  260. }
  261. //
  262. // Check to see if we are to run in Loop Mode, or in single function
  263. // mode. In Loop Mode, we go into a loop, and ask the user for
  264. // input until the user decides to quit.
  265. //
  266. // Process Arguments:
  267. //
  268. // INDEX 0 1 2 3
  269. // EL <ServerName> <Function> <FunctionOptions...>
  270. //
  271. if (STRICMP (argv[argIndex], TEXT("Loop")) == 0) {
  272. UserInputLoop(pServerName);
  273. }
  274. else {
  275. ProcessArgs(pServerName, argc-argIndex, &(argv[argIndex]));
  276. }
  277. #ifdef UNICODE
  278. //
  279. // Free up the unicode strings if there are any
  280. //
  281. for(j=0; j<argc; j++) {
  282. LocalFree(argv[j]);
  283. }
  284. #endif
  285. return;
  286. }
  287. VOID
  288. UserInputLoop(
  289. LPTSTR ServerName
  290. )
  291. /*++
  292. Routine Description:
  293. This function sits in a loop, gathering input from the user, and
  294. processing that input until the user indicates that it should stop.
  295. The following user commands indicate that we should stop:
  296. done
  297. exit
  298. stop
  299. quit
  300. Arguments:
  301. Return Value:
  302. --*/
  303. {
  304. UCHAR i;
  305. DWORD j;
  306. LPTSTR *argv;
  307. UCHAR buffer[255];
  308. LPSTR argvA[20];
  309. DWORD argc=0;
  310. BOOL KeepGoing;
  311. do {
  312. //------------------------------
  313. // Get input from the user
  314. //------------------------------
  315. buffer[0] = 90-2;
  316. printf("\nwaiting for instructions... \n");
  317. _cgets(buffer);
  318. if (buffer[1] > 0) {
  319. //--------------------------------------
  320. // put the string in argv/argc format.
  321. //--------------------------------------
  322. buffer[1]+=2; // make this an end offset
  323. argc=0;
  324. for (i=2,j=0; i<buffer[1]; i++,j++) {
  325. argc++;
  326. argvA[j] = &(buffer[i]);
  327. while ((buffer[i] != ' ') && (buffer[i] != '\0')) {
  328. i++;
  329. }
  330. buffer[i] = '\0';
  331. }
  332. //------------------------------------------
  333. // Make the arguments unicode if necessary.
  334. //------------------------------------------
  335. #ifdef UNICODE
  336. if (!MakeArgsUnicode(argc, argvA)) {
  337. return;
  338. }
  339. #endif
  340. //-----------------------------------------------
  341. // If the first argument doesn't indicate that
  342. // we should stop, then process the arguments.
  343. //-----------------------------------------------
  344. argv = (LPTSTR *)argvA;
  345. if((STRICMP (argv[0], TEXT("done")) == 0) ||
  346. (STRICMP (argv[0], TEXT("stop")) == 0) ||
  347. (STRICMP (argv[0], TEXT("exit")) == 0) ||
  348. (STRICMP (argv[0], TEXT("quit")) == 0)) {
  349. KeepGoing = FALSE;
  350. }
  351. else {
  352. KeepGoing = ProcessArgs(ServerName, argc, argv);
  353. }
  354. #ifdef UNICODE
  355. //-----------------------------------------------
  356. // Free up the unicode strings if there are any
  357. //-----------------------------------------------
  358. for(j=0; j<argc; j++) {
  359. LocalFree(argv[j]);
  360. }
  361. #endif
  362. }
  363. } while (KeepGoing);
  364. return;
  365. }
  366. /****************************************************************************/
  367. BOOL
  368. ProcessArgs (
  369. LPTSTR ServerName,
  370. DWORD argc,
  371. LPTSTR argv[]
  372. )
  373. /*++
  374. Routine Description:
  375. Arguments:
  376. Return Value:
  377. --*/
  378. {
  379. DWORD status;
  380. DWORD specialFlag = FALSE;
  381. DWORD argIndex; // index to unchecked portion of arglist.
  382. argIndex = 0;
  383. //
  384. // If we are adding a registry entry, the get a handle to it.
  385. // Otherwise, get a handle to the LogFile.
  386. //
  387. //-----------------------
  388. // AddSourceToRegistry
  389. //-----------------------
  390. if (STRICMP (argv[argIndex], TEXT("AddReg")) == 0 ) {
  391. //
  392. // Must have at least "AddReg logname EntryName"
  393. //
  394. if (argc < (argIndex + 3)) {
  395. AddRegUsage();
  396. goto CleanExit;
  397. }
  398. status = AddSourceToRegistry(
  399. ServerName,
  400. argv[argIndex+1], // LogName
  401. argv[argIndex+2], // SourceName
  402. &argv[argIndex+1],
  403. argc-(argIndex+2)
  404. );
  405. }
  406. //-----------------------
  407. // DeleteFromRegistry
  408. //-----------------------
  409. else if (STRICMP (argv[argIndex], TEXT("DelReg")) == 0) {
  410. //
  411. // Must have at least "DelReg logname EntryName"
  412. //
  413. if (argc < (argIndex + 3)) {
  414. goto CleanExit;
  415. }
  416. status = DelSourceInRegistry(
  417. ServerName,
  418. argv[argIndex+1], // LogName
  419. argv[argIndex+2] // SourceName
  420. );
  421. }
  422. //-----------------------
  423. // WriteEvent
  424. //-----------------------
  425. else if (STRICMP (argv[argIndex], TEXT("WriteEvent")) == 0) {
  426. printf("In WriteEvent\n");
  427. if (ServerName != NULL) {
  428. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  429. }
  430. }
  431. //-----------------------
  432. // ReadLog
  433. //-----------------------
  434. else if (STRICMP (argv[argIndex], TEXT("ReadLog")) == 0) {
  435. printf("In ReadLog\n");
  436. if (ServerName != NULL) {
  437. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  438. }
  439. //
  440. // Must have at least "ReadLog logname"
  441. //
  442. if (argc < (argIndex + 2)) {
  443. ReadLogUsage();
  444. goto CleanExit;
  445. }
  446. status = ReadLogFile(
  447. ServerName, // ServerName
  448. argv[argIndex+1], // LogName
  449. &argv[argIndex+1], // argv
  450. argc-(argIndex+1)); // argc
  451. }
  452. //-----------------------
  453. // GetNumEvents
  454. //-----------------------
  455. else if (STRICMP (argv[argIndex], TEXT("GetNumEvents")) == 0) {
  456. printf("in GetNumEvents\n");
  457. if (ServerName != NULL) {
  458. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  459. }
  460. }
  461. //-----------------------
  462. // GetOldest
  463. //-----------------------
  464. else if (STRICMP (argv[argIndex], TEXT("GetOldest")) == 0) {
  465. printf("in GetOldest\n");
  466. if (ServerName != NULL) {
  467. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  468. }
  469. }
  470. //-----------------------
  471. // ClearLog
  472. //-----------------------
  473. else if (STRICMP (argv[argIndex], TEXT("ClearLog")) == 0) {
  474. printf("in ClearLog\n");
  475. if (ServerName != NULL) {
  476. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  477. }
  478. }
  479. //-----------------------
  480. // Backup
  481. //-----------------------
  482. else if (STRICMP (argv[argIndex], TEXT("Backup")) == 0) {
  483. printf("in Backup\n");
  484. if (ServerName != NULL) {
  485. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  486. }
  487. }
  488. //-----------------------
  489. // RegisterSource
  490. //-----------------------
  491. else if (STRICMP (argv[argIndex], TEXT("RegisterSource")) == 0) {
  492. printf("in RegisterSource\n");
  493. if (ServerName != NULL) {
  494. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  495. }
  496. }
  497. //-----------------------
  498. // DeRegisterSource
  499. //-----------------------
  500. else if (STRICMP (argv[argIndex], TEXT("DeRegisterSource")) == 0) {
  501. printf("in DeRegisterSource\n");
  502. if (ServerName != NULL) {
  503. printf("ServerName = "FORMAT_LPTSTR"\n",ServerName);
  504. }
  505. }
  506. //****************
  507. // Exit Program
  508. //****************
  509. else if (STRICMP (argv[0], TEXT("Exit")) == 0) {
  510. //
  511. // THIS SHOULD CLOSE HANDLES.
  512. //
  513. return(FALSE);
  514. }
  515. else {
  516. printf("Bad argument\n");
  517. Usage();
  518. }
  519. CleanExit:
  520. return(TRUE);
  521. }
  522. BOOL
  523. MakeArgsUnicode (
  524. DWORD argc,
  525. PCHAR argv[]
  526. )
  527. /*++
  528. Routine Description:
  529. Arguments:
  530. Return Value:
  531. Note:
  532. --*/
  533. {
  534. DWORD i;
  535. //
  536. // ScConvertToUnicode allocates storage for each string.
  537. // We will rely on process termination to free the memory.
  538. //
  539. for(i=0; i<argc; i++) {
  540. if(!ConvertToUnicode( (LPWSTR *)&(argv[i]), argv[i])) {
  541. printf("Couldn't convert argv[%d] to unicode\n",i);
  542. return(FALSE);
  543. }
  544. }
  545. return(TRUE);
  546. }
  547. BOOL
  548. ConvertToUnicode(
  549. OUT LPWSTR *UnicodeOut,
  550. IN LPSTR AnsiIn
  551. )
  552. /*++
  553. Routine Description:
  554. This function translates an AnsiString into a Unicode string.
  555. A new string buffer is created by this function. If the call to
  556. this function is successful, the caller must take responsibility for
  557. the unicode string buffer that was allocated by this function.
  558. The allocated buffer should be free'd with a call to LocalFree.
  559. NOTE: This function allocates memory for the Unicode String.
  560. Arguments:
  561. AnsiIn - This is a pointer to an ansi string that is to be converted.
  562. UnicodeOut - This is a pointer to a location where the pointer to the
  563. unicode string is to be placed.
  564. Return Value:
  565. TRUE - The conversion was successful.
  566. FALSE - The conversion was unsuccessful. In this case a buffer for
  567. the unicode string was not allocated.
  568. --*/
  569. {
  570. NTSTATUS ntStatus;
  571. DWORD bufSize;
  572. UNICODE_STRING unicodeString;
  573. ANSI_STRING ansiString;
  574. //
  575. // Allocate a buffer for the unicode string.
  576. //
  577. bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
  578. *UnicodeOut = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, (UINT)bufSize);
  579. if (*UnicodeOut == NULL) {
  580. printf("ScConvertToUnicode:LocalAlloc Failure %ld\n",GetLastError());
  581. return(FALSE);
  582. }
  583. //
  584. // Initialize the string structures
  585. //
  586. RtlInitAnsiString( &ansiString, AnsiIn);
  587. unicodeString.Buffer = *UnicodeOut;
  588. unicodeString.MaximumLength = (USHORT)bufSize;
  589. unicodeString.Length = 0;
  590. //
  591. // Call the conversion function.
  592. //
  593. ntStatus = RtlAnsiStringToUnicodeString (
  594. &unicodeString, // Destination
  595. &ansiString, // Source
  596. (BOOLEAN)FALSE); // Allocate the destination
  597. if (!NT_SUCCESS(ntStatus)) {
  598. printf("ScConvertToUnicode:RtlAnsiStringToUnicodeString Failure %lx\n",
  599. ntStatus);
  600. return(FALSE);
  601. }
  602. //
  603. // Fill in the pointer location with the unicode string buffer pointer.
  604. //
  605. *UnicodeOut = unicodeString.Buffer;
  606. return(TRUE);
  607. }
  608. /****************************************************************************/
  609. VOID
  610. DisplayStatus (
  611. IN LPTSTR ServiceName,
  612. IN LPTSTR DisplayName,
  613. IN LPSERVICE_STATUS ServiceStatus
  614. )
  615. /*++
  616. Routine Description:
  617. Displays the service name and the service status.
  618. |
  619. |SERVICE_NAME: messenger
  620. |DISPLAY_NAME: messenger
  621. | TYPE : WIN32
  622. | STATE : ACTIVE,STOPPABLE, PAUSABLE, ACCEPTS_SHUTDOWN
  623. | EXIT_CODE : 0xC002001
  624. | CHECKPOINT : 0x00000001
  625. | WAIT_HINT : 0x00003f21
  626. |
  627. Arguments:
  628. ServiceName - This is a pointer to a string containing the name of
  629. the service.
  630. DisplayName - This is a pointer to a string containing the display
  631. name for the service.
  632. ServiceStatus - This is a pointer to a SERVICE_STATUS structure from
  633. which information is to be displayed.
  634. Return Value:
  635. none.
  636. --*/
  637. {
  638. printf("\nSERVICE_NAME: "FORMAT_LPTSTR"\n", ServiceName);
  639. if (DisplayName != NULL) {
  640. printf("DISPLAY_NAME: "FORMAT_LPTSTR"\n", DisplayName);
  641. }
  642. printf(" TYPE : %lx ", ServiceStatus->dwServiceType);
  643. switch(ServiceStatus->dwServiceType){
  644. case SERVICE_WIN32_OWN_PROCESS:
  645. printf("WIN32_OWN_PROCESS \n");
  646. break;
  647. case SERVICE_WIN32_SHARE_PROCESS:
  648. printf("WIN32_SHARE_PROCESS \n");
  649. break;
  650. case SERVICE_WIN32:
  651. printf("WIN32 \n");
  652. break;
  653. case SERVICE_ADAPTER:
  654. printf("ADAPTER \n");
  655. break;
  656. case SERVICE_KERNEL_DRIVER:
  657. printf("KERNEL_DRIVER \n");
  658. break;
  659. case SERVICE_FILE_SYSTEM_DRIVER:
  660. printf("FILE_SYSTEM_DRIVER \n");
  661. break;
  662. case SERVICE_DRIVER:
  663. printf("DRIVER \n");
  664. break;
  665. default:
  666. printf(" ERROR \n");
  667. }
  668. printf(" STATE : %lx ", ServiceStatus->dwCurrentState);
  669. switch(ServiceStatus->dwCurrentState){
  670. case SERVICE_STOPPED:
  671. printf("STOPPED ");
  672. break;
  673. case SERVICE_START_PENDING:
  674. printf("START_PENDING ");
  675. break;
  676. case SERVICE_STOP_PENDING:
  677. printf("STOP_PENDING ");
  678. break;
  679. case SERVICE_RUNNING:
  680. printf("RUNNING ");
  681. break;
  682. case SERVICE_CONTINUE_PENDING:
  683. printf("CONTINUE_PENDING ");
  684. break;
  685. case SERVICE_PAUSE_PENDING:
  686. printf("PAUSE_PENDING ");
  687. break;
  688. case SERVICE_PAUSED:
  689. printf("PAUSED ");
  690. break;
  691. default:
  692. printf(" ERROR ");
  693. }
  694. //
  695. // Print Controls Accepted Information
  696. //
  697. if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP) {
  698. printf("\n (STOPPABLE,");
  699. }
  700. else {
  701. printf("\n (NOT_STOPPABLE,");
  702. }
  703. if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) {
  704. printf("PAUSABLE,");
  705. }
  706. else {
  707. printf("NOT_PAUSABLE,");
  708. }
  709. if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) {
  710. printf("ACCEPTS_SHUTDOWN)\n");
  711. }
  712. else {
  713. printf("IGNORES_SHUTDOWN)\n");
  714. }
  715. //
  716. // Print Exit Code
  717. //
  718. printf(" WIN32_EXIT_CODE : %d\t(0x%lx)\n",
  719. ServiceStatus->dwWin32ExitCode,
  720. ServiceStatus->dwWin32ExitCode);
  721. printf(" SERVICE_EXIT_CODE : %d\t(0x%lx)\n",
  722. ServiceStatus->dwServiceSpecificExitCode,
  723. ServiceStatus->dwServiceSpecificExitCode );
  724. //
  725. // Print CheckPoint & WaitHint Information
  726. //
  727. printf(" CHECKPOINT : 0x%lx\n", ServiceStatus->dwCheckPoint);
  728. printf(" WAIT_HINT : 0x%lx\n", ServiceStatus->dwWaitHint );
  729. return;
  730. }
  731. VOID
  732. Usage(
  733. VOID)
  734. {
  735. printf("DESCRIPTION:\n");
  736. printf("\tEL is a command line program used for testing the eventlog \n");
  737. printf("USAGE:\n");
  738. printf("\tEL <ServerName> [Function] <FunctionOptions...> \n\n");
  739. printf("\tThe option <server> has the form \"\\\\ServerName\"\n");
  740. printf("\tFurther help on Functions can be obtained by typing: \"el [Function]\"\n");
  741. printf("\tFunctions:\n"
  742. "\t AddReg-----------Creates a registry entry for an event source.\n"
  743. "\t DelReg-----------Deletes a registry entry.\n"
  744. "\t WriteEvent-------Writes an event.\n"
  745. "\t ReadLog----------Reads from the logfile.\n"
  746. "\t GetNumEvents-----Gets the number of events in the specified log.\n"
  747. "\t GetOldest--------Gets the record number for the oldest record"
  748. "\t in the log\n"
  749. "\t ClearLog---------Clears the specified Log.\n"
  750. "\t Backup-----------Copies the specified log to a new file.\n"
  751. "\t RegisterSource---Registers a name for the event source.\n"
  752. "\t The handle is stored internally.\n"
  753. "\t DeRegisterSource-Closes handle opened with RegSource.\n"
  754. "\t NotifyChange-----A thread is created which gets notified of EL changes.\n");
  755. printf("\n");
  756. }
  757. VOID
  758. AddRegUsage(VOID)
  759. {
  760. printf("\nAdds a subkey under one of the logfiles listed in the registry.\n");
  761. printf("SYNTAX: \n eltest addreg <ServerName> logfile <SubKeyName> <option1> <option2>...\n");
  762. printf("ADDREG OPTIONS:\n");
  763. printf("NOTE: The option name includes the equal sign.\n");
  764. printf(" MsgFile= Name of Event Message File\n"
  765. " CatFile= Name of Category Message File\n"
  766. " ParamFile= Name of Parameter Message File\n"
  767. " CatCount= Category Count\n"
  768. " Type= <error|warning|information|AuditSuccess|AuditFailure|All>\n");
  769. printf("EXAMPLE:\n eltest addreg application myapp MsgFile= MyMsgs.dll"
  770. " Type= error Type= warning\n");
  771. }
  772. VOID
  773. ConfigUsage(VOID)
  774. {
  775. printf("Modifies a service entry in the registry and Service Database.\n");
  776. printf("SYNTAX: \nsc config <service> <option1> <option2>...\n");
  777. printf("CONFIG OPTIONS:\n");
  778. printf("NOTE: The option name includes the equal sign.\n"
  779. " type= <own|share|kernel|filesys|rec|adapt|error>\n"
  780. " start= <boot|system|auto|demand|disabled|error>\n"
  781. " error= <normal|severe|critical|error|ignore>\n"
  782. " binPath= <BinaryPathName>\n"
  783. " group= <LoadOrderGroup>\n"
  784. " tag= <yes|no>\n"
  785. " depend= <Dependencies(space seperated)>\n"
  786. " obj= <AccountName|ObjectName>\n"
  787. " DisplayName= <display name>\n"
  788. " password= <password> \n");
  789. }
  790. VOID
  791. CreateUsage(VOID)
  792. {
  793. printf("Creates a service entry in the registry and Service Database.\n");
  794. printf("SYNTAX: \nsc create <service> <option1> <option2>...\n");
  795. printf("CREATE OPTIONS:\n");
  796. printf("NOTE: The option name includes the equal sign.\n"
  797. " type= <own|share|kernel|filesys|rec|error>\n"
  798. " start= <boot|system|auto|demand|disabled|error>\n"
  799. " error= <normal|severe|critical|error|ignore>\n"
  800. " binPath= <BinaryPathName>\n"
  801. " group= <LoadOrderGroup>\n"
  802. " tag= <yes|no>\n"
  803. " depend= <Dependencies(space seperated)>\n"
  804. " obj= <AccountName|ObjectName>\n"
  805. " DisplayName= <display name>\n"
  806. " password= <password> \n");
  807. }
  808. VOID
  809. ReadLogUsage(VOID)
  810. {
  811. printf("\nReads a logfile and dumps the contents.\n");
  812. printf("SYNTAX: \n eltest readlog <ServerName> logfile <option1> <option2>...\n");
  813. printf("READLOG OPTIONS:\n");
  814. printf("NOTE: The option name includes the equal sign.\n");
  815. printf(" ReadFlag= <fwd|back|seek|seq> (default = fwd) \n"
  816. " RecordNum= record number where read should start (default=0)\n"
  817. " BufSize= size of the buffer (default = 10000)\n");
  818. printf("EXAMPLE:\n eltest addreg application myapp MsgFile= MyMsgs.dll"
  819. " Type= error Type= warning\n");
  820. }
  821. DWORD
  822. AddSourceToRegistry(
  823. IN LPTSTR ServerName,
  824. IN LPTSTR LogName,
  825. IN LPTSTR EventSourceName,
  826. IN LPTSTR *argv,
  827. IN DWORD argc
  828. )
  829. /*++
  830. Routine Description:
  831. This function writes to the registry all the information to register
  832. this application as an event source.
  833. Arguments:
  834. Return Value:
  835. --*/
  836. {
  837. TCHAR tempName[MAX_PATH];
  838. HKEY hKey;
  839. DWORD dwStatus=NO_ERROR;
  840. HKEY hRegistry=HKEY_LOCAL_MACHINE;
  841. LPTSTR EventMessageFile=NULL;
  842. LPTSTR CategoryMessageFile=NULL;
  843. LPTSTR ParameterMessageFile=NULL;
  844. DWORD dwTypes=0;
  845. DWORD dwCategoryCount=0;
  846. DWORD i;
  847. //
  848. // Look at the LogName, and generate the appropriate registry key
  849. // path for that log.
  850. //
  851. if (STRICMP(LogName, ApplLogName) == 0) {
  852. STRCPY(tempName, ApplLogRegName);
  853. }
  854. else if (STRICMP(LogName, SysLogName) == 0) {
  855. STRCPY(tempName, SysLogRegName);
  856. }
  857. else if (STRICMP(LogName, SecLogName) == 0) {
  858. STRCPY(tempName, SecLogRegName);
  859. }
  860. else {
  861. printf("AddSourceToRegistry: Invalid LogName\n");
  862. return(ERROR_INVALID_PARAMETER);
  863. }
  864. STRCAT(tempName, EventSourceName);
  865. //
  866. // Get Variable Arguments
  867. //
  868. for (i=0; i<argc ;i++ ) {
  869. if (STRICMP(argv[i], TEXT("EventMsgFile=")) == 0) {
  870. EventMessageFile = argv[i+1];
  871. i++;
  872. }
  873. if (STRICMP(argv[i], TEXT("CategoryMsgFile=")) == 0) {
  874. CategoryMessageFile = argv[i+1];
  875. i++;
  876. }
  877. if (STRICMP(argv[i], TEXT("ParameterMsgFile=")) == 0) {
  878. ParameterMessageFile = argv[i+1];
  879. i++;
  880. }
  881. if (STRICMP(argv[i], TEXT("Type=")) == 0) {
  882. //--------------------------------------------------------
  883. // We want to allow for several arguments of type= in the
  884. // same line. These should cause the different arguments
  885. // to be or'd together.
  886. //--------------------------------------------------------
  887. if (STRICMP(argv[i+1],TEXT("error")) == 0) {
  888. dwTypes |= EVENTLOG_ERROR_TYPE;
  889. }
  890. if (STRICMP(argv[i+1],TEXT("warning")) == 0) {
  891. dwTypes |= EVENTLOG_WARNING_TYPE;
  892. }
  893. if (STRICMP(argv[i+1],TEXT("information")) == 0) {
  894. dwTypes |= EVENTLOG_INFORMATION_TYPE;
  895. }
  896. if (STRICMP(argv[i+1],TEXT("AuditSuccess")) == 0) {
  897. dwTypes |= EVENTLOG_AUDIT_SUCCESS;
  898. }
  899. if (STRICMP(argv[i+1],TEXT("AuditFailure")) == 0) {
  900. dwTypes |= EVENTLOG_AUDIT_FAILURE;
  901. }
  902. if (STRICMP(argv[i+1],TEXT("All")) == 0) {
  903. dwTypes |= (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
  904. EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS |
  905. EVENTLOG_AUDIT_FAILURE);
  906. }
  907. else {
  908. printf("Invalid Type\n");
  909. AddRegUsage();
  910. return(ERROR_INVALID_PARAMETER);
  911. }
  912. i++;
  913. }
  914. if (STRICMP(argv[i], TEXT("CategoryCount=")) == 0) {
  915. dwCategoryCount = ATOL(argv[i+1]);
  916. i++;
  917. }
  918. }
  919. //
  920. // Connect to the registry on the correct machine.
  921. //
  922. printf("Connect to Registry\n");
  923. dwStatus = RegConnectRegistry(ServerName, HKEY_LOCAL_MACHINE, &hRegistry);
  924. if (dwStatus != NO_ERROR) {
  925. printf("RegConnectRegistry Failed %d\n",GetLastError());
  926. return(dwStatus);
  927. }
  928. //
  929. // Create the new key for this source
  930. //
  931. printf("Create Key\n");
  932. dwStatus = RegCreateKey(hRegistry, tempName, &hKey);
  933. if (dwStatus != ERROR_SUCCESS) {
  934. printf("Couldn't create Source Key in registry %d\n",dwStatus);
  935. return(dwStatus);
  936. }
  937. if (EventMessageFile != NULL) {
  938. printf("Set EventMessageFile\n");
  939. dwStatus = RegSetValueEx(
  940. hKey,
  941. VALUE_EVENT_MF,
  942. 0,
  943. REG_EXPAND_SZ,
  944. (LPBYTE)EventMessageFile,
  945. STRLEN(EventMessageFile) + sizeof(TCHAR));
  946. if (dwStatus != ERROR_SUCCESS) {
  947. printf("RegSetValue (messageFile) failed %d\n",GetLastError());
  948. goto CleanExit;
  949. }
  950. }
  951. //
  952. // Set the Category Message File
  953. //
  954. if (CategoryMessageFile != NULL) {
  955. printf("Set Category Message File\n");
  956. dwStatus = RegSetValueEx(
  957. hKey,
  958. VALUE_CATEGORY_MF,
  959. 0,
  960. REG_EXPAND_SZ,
  961. (LPBYTE)CategoryMessageFile,
  962. STRLEN(CategoryMessageFile) + sizeof(TCHAR));
  963. if (dwStatus != ERROR_SUCCESS) {
  964. printf("RegSetValue (category mf) failed %d\n",GetLastError());
  965. goto CleanExit;
  966. }
  967. }
  968. //
  969. // Set the Parameter Message File
  970. //
  971. if (ParameterMessageFile != NULL) {
  972. printf("Set Parameter Message File\n");
  973. dwStatus = RegSetValueEx(
  974. hKey,
  975. VALUE_PARAMETER_MF,
  976. 0,
  977. REG_EXPAND_SZ,
  978. (LPBYTE)ParameterMessageFile,
  979. STRLEN(ParameterMessageFile) + sizeof(TCHAR));
  980. if (dwStatus != ERROR_SUCCESS) {
  981. printf("RegSetValue (Parameter mf) failed %d\n",GetLastError());
  982. goto CleanExit;
  983. }
  984. }
  985. //
  986. // Set the Types Supported
  987. //
  988. if (dwTypes != 0) {
  989. printf("Set Types Supported\n");
  990. dwStatus = RegSetValueEx(
  991. hKey,
  992. VALUE_TYPES_SUPPORTED,
  993. 0,
  994. REG_DWORD,
  995. (LPBYTE) &dwTypes,
  996. sizeof(DWORD));
  997. if (dwStatus != ERROR_SUCCESS) {
  998. printf("RegSetValue (TypesSupported) failed %d\n",GetLastError());
  999. goto CleanExit;
  1000. }
  1001. }
  1002. //
  1003. // Set the Category Count
  1004. //
  1005. if (dwCategoryCount != 0) {
  1006. printf("Set CategoryCount\n");
  1007. dwStatus = RegSetValueEx(
  1008. hKey,
  1009. VALUE_CATEGORY_COUNT,
  1010. 0,
  1011. REG_DWORD,
  1012. (LPBYTE) &dwCategoryCount,
  1013. sizeof(DWORD));
  1014. if (dwStatus != ERROR_SUCCESS) {
  1015. printf("RegSetValue (CategoryCount) failed %d\n",GetLastError());
  1016. goto CleanExit;
  1017. }
  1018. }
  1019. dwStatus = NO_ERROR;
  1020. CleanExit:
  1021. RegCloseKey(hKey);
  1022. RegCloseKey(hRegistry);
  1023. return(dwStatus);
  1024. }
  1025. DWORD
  1026. DelSourceInRegistry(
  1027. IN LPTSTR ServerName,
  1028. IN LPTSTR LogName,
  1029. IN LPTSTR EventSourceName
  1030. )
  1031. /*++
  1032. Routine Description:
  1033. This function writes to the registry all the information to register
  1034. this application as an event source.
  1035. Arguments:
  1036. Return Value:
  1037. --*/
  1038. {
  1039. LPTSTR tempName;
  1040. HKEY hParentKey;
  1041. BOOL status=FALSE;
  1042. DWORD dwStatus;
  1043. HKEY hRegistry=HKEY_LOCAL_MACHINE;
  1044. //
  1045. // Look at the LogName, and generate the appropriate registry key
  1046. // path for that log.
  1047. //
  1048. if (STRICMP(LogName, ApplLogName) == 0) {
  1049. tempName = ApplLogRegName;
  1050. }
  1051. else if (STRICMP(LogName, SysLogName) == 0) {
  1052. tempName = SysLogRegName;
  1053. }
  1054. else if (STRICMP(LogName, SecLogName) == 0) {
  1055. tempName = SecLogRegName;
  1056. }
  1057. else {
  1058. printf("AddSourceToRegistry: Invalid LogName\n");
  1059. return(ERROR_INVALID_PARAMETER);
  1060. }
  1061. //
  1062. // Connect to the registry on the correct machine.
  1063. //
  1064. dwStatus = RegConnectRegistry(ServerName, HKEY_LOCAL_MACHINE, &hRegistry);
  1065. if (dwStatus != NO_ERROR) {
  1066. printf("RegConnectRegistry Failed %d\n",GetLastError());
  1067. return(status);
  1068. }
  1069. //
  1070. // Open the Parent Key of the key we want to delete.
  1071. //
  1072. dwStatus = RegOpenKeyEx(
  1073. hRegistry,
  1074. tempName,
  1075. 0,
  1076. KEY_ALL_ACCESS,
  1077. &hParentKey);
  1078. if (dwStatus != ERROR_SUCCESS) {
  1079. printf("Couldn't open Parent of key to be deleted. %d\n",dwStatus);
  1080. goto CleanExit;
  1081. }
  1082. //
  1083. // Delete the subkey.
  1084. //
  1085. dwStatus = RegDeleteKey(hParentKey, EventSourceName);
  1086. if (dwStatus != ERROR_SUCCESS) {
  1087. printf("Couldn't delete "FORMAT_LPTSTR" key from registry %d\n",
  1088. EventSourceName, dwStatus);
  1089. }
  1090. RegCloseKey(hParentKey);
  1091. CleanExit:
  1092. RegCloseKey(hRegistry);
  1093. return(status);
  1094. }
  1095. DWORD
  1096. ReadLogFile(
  1097. LPTSTR ServerName,
  1098. LPTSTR LogName,
  1099. IN LPTSTR *argv,
  1100. IN DWORD argc
  1101. )
  1102. /*++
  1103. Routine Description:
  1104. Arguments:
  1105. Return Value:
  1106. --*/
  1107. {
  1108. DWORD dwReadFlag = EVENTLOG_FORWARDS_READ;
  1109. DWORD dwRecordNum = 0;
  1110. DWORD BufSize = 10000;
  1111. DWORD numBytesRead;
  1112. DWORD numBytesReqd;
  1113. LPVOID pElBuffer = NULL;
  1114. PEVENTLOGRECORD pElRecord;
  1115. BOOL PrintTheHeader;
  1116. DWORD i;
  1117. HANDLE hEventLog=NULL;
  1118. //
  1119. // Get Variable Arguments
  1120. //
  1121. for (i=0; i<argc ;i++ ) {
  1122. if (STRICMP(argv[i], TEXT("ReadFlag=")) == 0) {
  1123. if (STRICMP(argv[i+1],TEXT("fwd")) == 0) {
  1124. dwReadFlag |= EVENTLOG_FORWARDS_READ;
  1125. }
  1126. if (STRICMP(argv[i+1],TEXT("back")) == 0) {
  1127. dwReadFlag |= EVENTLOG_BACKWARDS_READ;
  1128. }
  1129. if (STRICMP(argv[i+1],TEXT("seek")) == 0) {
  1130. dwReadFlag |= EVENTLOG_SEEK_READ;
  1131. }
  1132. if (STRICMP(argv[i+1],TEXT("seq")) == 0) {
  1133. dwReadFlag |= EVENTLOG_SEQUENTIAL_READ;
  1134. }
  1135. i++;
  1136. }
  1137. if (STRICMP(argv[i], TEXT("RecordNum=")) == 0) {
  1138. dwRecordNum = ATOL(argv[i+1]);
  1139. i++;
  1140. }
  1141. if (STRICMP(argv[i], TEXT("BufSize=")) == 0) {
  1142. BufSize = ATOL(argv[i+1]);
  1143. i++;
  1144. }
  1145. hEventLog = OpenEventLog(ServerName,LogName);
  1146. if (hEventLog == NULL) {
  1147. printf("OpenEventLog failed %d\n",GetLastError());
  1148. return(0);
  1149. }
  1150. pElBuffer = LocalAlloc(LPTR, BufSize);
  1151. if (pElBuffer == NULL) {
  1152. printf("ReadLogFile: LocalAlloc Failed %d\n",GetLastError());
  1153. goto CleanExit;
  1154. }
  1155. //---------------------------------------------------------
  1156. // Read and Display the contents of the eventlog
  1157. //---------------------------------------------------------
  1158. PrintTheHeader = TRUE;
  1159. TryAgain:
  1160. while(ReadEventLog(
  1161. hEventLog,
  1162. dwReadFlag,
  1163. dwRecordNum,
  1164. pElBuffer,
  1165. BufSize,
  1166. &numBytesRead,
  1167. &numBytesReqd)) {
  1168. pElRecord = (PEVENTLOGRECORD) pElBuffer;
  1169. while ((PBYTE) pElRecord < (PBYTE) pElBuffer + numBytesRead) {
  1170. //
  1171. // Print the record to the display
  1172. //
  1173. DisplayRecord(pElRecord,PrintTheHeader);
  1174. PrintTheHeader = FALSE;
  1175. //
  1176. // Move to the next event in the buffer
  1177. //
  1178. pElRecord = (PEVENTLOGRECORD)((PBYTE) pElRecord +
  1179. pElRecord->Length);
  1180. }
  1181. }
  1182. switch(GetLastError()) {
  1183. case ERROR_INSUFFICIENT_BUFFER:
  1184. //
  1185. // Increase the size of the buffer and try again
  1186. //
  1187. if (numBytesReqd > BufSize) {
  1188. LocalFree(pElBuffer);
  1189. BufSize = numBytesReqd;
  1190. pElBuffer = LocalAlloc(LPTR, BufSize);
  1191. if (!pElBuffer) {
  1192. printf("ReadLogFile: LocalAlloc Failed %d\n",GetLastError());
  1193. }
  1194. goto TryAgain;
  1195. }
  1196. else {
  1197. printf("ReadLogFile #1: THIS SHOULD NEVER HAPPEN\n");
  1198. }
  1199. break;
  1200. case ERROR_EVENTLOG_FILE_CHANGED:
  1201. //
  1202. // The current read position for this handle has been overwritten.
  1203. // Reopen the file and print a message to the effect that some
  1204. // records may have been missed.
  1205. //
  1206. printf("ReadLogFile: Current Read position has been overwritten\n");
  1207. hEventLog = OpenEventLog(ServerName,LogName);
  1208. if (hEventLog == NULL) {
  1209. printf("OpenEventLog failed %d\n",GetLastError());
  1210. goto CleanExit;
  1211. }
  1212. goto TryAgain;
  1213. case ERROR_HANDLE_EOF:
  1214. printf("EOF\n");
  1215. break;
  1216. default:
  1217. printf("UnknownError: %d\n",GetLastError());
  1218. break;
  1219. }
  1220. }
  1221. CleanExit:
  1222. if (pElBuffer != NULL) {
  1223. LocalFree(pElBuffer);
  1224. }
  1225. if (hEventLog != NULL) {
  1226. CloseEventLog(hEventLog);
  1227. }
  1228. return(0);
  1229. }
  1230. VOID
  1231. DisplayRecord(
  1232. PEVENTLOGRECORD pElRecord,
  1233. BOOL PrintTheHeader
  1234. )
  1235. /*++
  1236. Routine Description:
  1237. Arguments:
  1238. Return Value:
  1239. --*/
  1240. {
  1241. if (PrintTheHeader) {
  1242. printf("RecNum/tTimeGen/tWriteTime/tEventID/tType/tNumStr/tCat/n");
  1243. }
  1244. printf("%d/t%d/t%d/t%d/t%d/t%d/t%d\n",
  1245. pElRecord->RecordNumber,
  1246. pElRecord->TimeGenerated,
  1247. pElRecord->TimeWritten,
  1248. pElRecord->EventID,
  1249. pElRecord->EventType,
  1250. pElRecord->NumStrings,
  1251. pElRecord->EventCategory);
  1252. }
  1253. LONG
  1254. wtol(
  1255. IN LPWSTR string
  1256. )
  1257. {
  1258. LONG value = 0;
  1259. while((*string != L'\0') &&
  1260. (*string >= L'0') &&
  1261. ( *string <= L'9')) {
  1262. value = value * 10 + (*string - L'0');
  1263. string++;
  1264. }
  1265. return(value);
  1266. }