/*++ Copyright (c) 1990 Microsoft Corporation Module Name: ELTEST.C Abstract: Test Routines for the EventLog. THINGS I WANT THIS TO DO... AddReg - Creates A Registry Entry. eltest addreg application mytest mf= eltest.dll cat= CreateMessageFile WriteEvent ReadLog If LogFile isn't one of the popular ones, then it could be a backup logfile. GetNumEvents GetOldest Clear Backup LOOPTESTS.... I should be able to run this test like mprtest such that it doesn't leave the test process until told. This way we can register an event source, then if we call WriteEvent without a specified EventSource, it will use the stored source. Calling RegisterEventSource twice without calling DeRegisterSource would be an error. (Or better yet, I could keep a table of sources and handles). RegisterEventSource DeRegisterSource PROTOTYPES FOR FUNCTION.... BOOL CloseEventLog ( HANDLE hEventLog ) BOOL DeregisterEventSource ( HANDLE hEventLog ) BOOL NotifyChangeEventLog( HANDLE hEventLog, HANDLE hEvent ) BOOL GetNumberOfEventLogRecords ( HANDLE hEventLog, PDWORD NumberOfRecords ) BOOL GetOldestEventLogRecord ( HANDLE hEventLog, PDWORD OldestRecord ) BOOL ClearEventLogW ( HANDLE hEventLog, LPCWSTR BackupFileName ) BOOL BackupEventLogW ( HANDLE hEventLog, LPCWSTR BackupFileName ) HANDLE OpenEventLogW ( LPCWSTR UNCServerName, LPCWSTR ModuleName ) HANDLE RegisterEventSourceW ( LPCWSTR UNCServerName, LPCWSTR ModuleName ) HANDLE OpenBackupEventLogW ( LPCWSTR UNCServerName, LPCWSTR FileName ) BOOL ReadEventLogW ( HANDLE hEventLog, DWORD dwReadFlags, DWORD dwRecordOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, DWORD *pnBytesRead, DWORD *pnMinNumberOfBytesNeeded ) BOOL ReportEventW ( HANDLE hEventLog, WORD wType, WORD wCategory OPTIONAL, DWORD dwEventID, PSID lpUserSid OPTIONAL, WORD wNumStrings, DWORD dwDataSize, LPCWSTR *lpStrings OPTIONAL, LPVOID lpRawData OPTIONAL ) Author: Dan Lafferty (danl) 09-March-1994 Environment: User Mode - Win32 Revision History: 09-Mar-1994 danl created --*/ // // INCLUDES // #define UNICODE 1 #include // DbgPrint prototype #include // DbgPrint prototype #include // needed for winbase.h #include // atoi #include // printf #include // getch #include // strcmp #include // win32 typedefs #include // Unicode #include // FORMAT_LPTSTR //------------------ // DEFINES //------------------ #define APPLICATION_LOG "Application" #define SYSTEM_LOG "System" #define SECURITY_LOG "Security" #define REG_APPLICATION_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\" #define REG_SYSTEM_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\System\\" #define REG_SECURITY_KEY "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Security\\" #define EVENT_SOURCE_NAME "tevent" #define MSG_DLL "%SystemRoot%\\System32\\tevent.dll" #define VALUE_EVENT_MF TEXT("EventMessageFile") #define VALUE_CATEGORY_MF TEXT("CategoryMessageFile") #define VALUE_PARAMETER_MF TEXT("ParameterMessageFile") #define VALUE_TYPES_SUPPORTED TEXT("TypesSupported") #define VALUE_CATEGORY_COUNT TEXT("CategoryCount") #define TYPES_SUPPORTED (EVENTLOG_ERROR_TYPE | \ EVENTLOG_WARNING_TYPE | \ EVENTLOG_INFORMATION_TYPE) //---------------------- // GLOBALS //---------------------- LPTSTR ApplLogRegName=TEXT(REG_APPLICATION_KEY); LPTSTR SysLogRegName =TEXT(REG_SYSTEM_KEY); LPTSTR SecLogRegName =TEXT(REG_SECURITY_KEY); LPTSTR ApplLogName = TEXT(APPLICATION_LOG); LPTSTR SysLogName = TEXT(SYSTEM_LOG); LPTSTR SecLogName = TEXT(SECURITY_LOG); //---------------------- // FUNCTION PROTOTYPES //---------------------- VOID AddRegUsage(VOID); DWORD AddSourceToRegistry( IN LPTSTR ServerName, IN LPTSTR LogName, IN LPTSTR EventSourceName, IN LPTSTR *argv, IN DWORD argc ); BOOL ConvertToUnicode( OUT LPWSTR *UnicodeOut, IN LPSTR AnsiIn ); DWORD DelSourceInRegistry( IN LPTSTR ServerName, IN LPTSTR LogName, IN LPTSTR EventSourceName ); VOID DisplayStatus ( IN LPTSTR ServiceName, IN LPTSTR DisplayName, IN LPSERVICE_STATUS ServiceStatus ); BOOL MakeArgsUnicode ( DWORD argc, PCHAR argv[] ); BOOL ProcessArgs ( LPTSTR ServerName, DWORD argc, LPTSTR argv[] ); VOID Usage( VOID); VOID ConfigUsage(VOID); VOID CreateUsage(VOID); VOID QueryUsage(VOID); LONG wtol( IN LPWSTR string ); VOID UserInputLoop( LPTSTR ServerName ); DWORD ReadLogFile( LPTSTR ServerName, LPTSTR LogName, IN LPTSTR *argv, IN DWORD argc ); VOID ReadLogUsage(VOID); VOID DisplayRecord( PEVENTLOGRECORD pElRecord, BOOL PrintTheHeader ); /****************************************************************************/ VOID __cdecl main ( DWORD argc, PCHAR argvAnsi[] ) /*++ Routine Description: Allows manual testing of the EVENTLOG API. eltest Arguments: Return Value: --*/ { UCHAR i; DWORD j; DWORD argIndex; LPTSTR pServerName=NULL; LPTSTR *argv; if (argc <2) { Usage(); return; } // // Make the arguments unicode if necessary. // #ifdef UNICODE if (!MakeArgsUnicode(argc, argvAnsi)) { return; } #endif argv = (LPTSTR *)argvAnsi; argIndex = 1; if (STRNCMP (argv[1], TEXT("\\\\"), 2) == 0) { pServerName = argv[1]; argIndex = 2; // skip over servername. } // // Check to see if we are to run in Loop Mode, or in single function // mode. In Loop Mode, we go into a loop, and ask the user for // input until the user decides to quit. // // Process Arguments: // // INDEX 0 1 2 3 // EL // if (STRICMP (argv[argIndex], TEXT("Loop")) == 0) { UserInputLoop(pServerName); } else { ProcessArgs(pServerName, argc-argIndex, &(argv[argIndex])); } #ifdef UNICODE // // Free up the unicode strings if there are any // for(j=0; j 0) { //-------------------------------------- // put the string in argv/argc format. //-------------------------------------- buffer[1]+=2; // make this an end offset argc=0; for (i=2,j=0; idwServiceType); switch(ServiceStatus->dwServiceType){ case SERVICE_WIN32_OWN_PROCESS: printf("WIN32_OWN_PROCESS \n"); break; case SERVICE_WIN32_SHARE_PROCESS: printf("WIN32_SHARE_PROCESS \n"); break; case SERVICE_WIN32: printf("WIN32 \n"); break; case SERVICE_ADAPTER: printf("ADAPTER \n"); break; case SERVICE_KERNEL_DRIVER: printf("KERNEL_DRIVER \n"); break; case SERVICE_FILE_SYSTEM_DRIVER: printf("FILE_SYSTEM_DRIVER \n"); break; case SERVICE_DRIVER: printf("DRIVER \n"); break; default: printf(" ERROR \n"); } printf(" STATE : %lx ", ServiceStatus->dwCurrentState); switch(ServiceStatus->dwCurrentState){ case SERVICE_STOPPED: printf("STOPPED "); break; case SERVICE_START_PENDING: printf("START_PENDING "); break; case SERVICE_STOP_PENDING: printf("STOP_PENDING "); break; case SERVICE_RUNNING: printf("RUNNING "); break; case SERVICE_CONTINUE_PENDING: printf("CONTINUE_PENDING "); break; case SERVICE_PAUSE_PENDING: printf("PAUSE_PENDING "); break; case SERVICE_PAUSED: printf("PAUSED "); break; default: printf(" ERROR "); } // // Print Controls Accepted Information // if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_STOP) { printf("\n (STOPPABLE,"); } else { printf("\n (NOT_STOPPABLE,"); } if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_PAUSE_CONTINUE) { printf("PAUSABLE,"); } else { printf("NOT_PAUSABLE,"); } if (ServiceStatus->dwControlsAccepted & SERVICE_ACCEPT_SHUTDOWN) { printf("ACCEPTS_SHUTDOWN)\n"); } else { printf("IGNORES_SHUTDOWN)\n"); } // // Print Exit Code // printf(" WIN32_EXIT_CODE : %d\t(0x%lx)\n", ServiceStatus->dwWin32ExitCode, ServiceStatus->dwWin32ExitCode); printf(" SERVICE_EXIT_CODE : %d\t(0x%lx)\n", ServiceStatus->dwServiceSpecificExitCode, ServiceStatus->dwServiceSpecificExitCode ); // // Print CheckPoint & WaitHint Information // printf(" CHECKPOINT : 0x%lx\n", ServiceStatus->dwCheckPoint); printf(" WAIT_HINT : 0x%lx\n", ServiceStatus->dwWaitHint ); return; } VOID Usage( VOID) { printf("DESCRIPTION:\n"); printf("\tEL is a command line program used for testing the eventlog \n"); printf("USAGE:\n"); printf("\tEL [Function] \n\n"); printf("\tThe option has the form \"\\\\ServerName\"\n"); printf("\tFurther help on Functions can be obtained by typing: \"el [Function]\"\n"); printf("\tFunctions:\n" "\t AddReg-----------Creates a registry entry for an event source.\n" "\t DelReg-----------Deletes a registry entry.\n" "\t WriteEvent-------Writes an event.\n" "\t ReadLog----------Reads from the logfile.\n" "\t GetNumEvents-----Gets the number of events in the specified log.\n" "\t GetOldest--------Gets the record number for the oldest record" "\t in the log\n" "\t ClearLog---------Clears the specified Log.\n" "\t Backup-----------Copies the specified log to a new file.\n" "\t RegisterSource---Registers a name for the event source.\n" "\t The handle is stored internally.\n" "\t DeRegisterSource-Closes handle opened with RegSource.\n" "\t NotifyChange-----A thread is created which gets notified of EL changes.\n"); printf("\n"); } VOID AddRegUsage(VOID) { printf("\nAdds a subkey under one of the logfiles listed in the registry.\n"); printf("SYNTAX: \n eltest addreg logfile ...\n"); printf("ADDREG OPTIONS:\n"); printf("NOTE: The option name includes the equal sign.\n"); printf(" MsgFile= Name of Event Message File\n" " CatFile= Name of Category Message File\n" " ParamFile= Name of Parameter Message File\n" " CatCount= Category Count\n" " Type= \n"); printf("EXAMPLE:\n eltest addreg application myapp MsgFile= MyMsgs.dll" " Type= error Type= warning\n"); } VOID ConfigUsage(VOID) { printf("Modifies a service entry in the registry and Service Database.\n"); printf("SYNTAX: \nsc config ...\n"); printf("CONFIG OPTIONS:\n"); printf("NOTE: The option name includes the equal sign.\n" " type= \n" " start= \n" " error= \n" " binPath= \n" " group= \n" " tag= \n" " depend= \n" " obj= \n" " DisplayName= \n" " password= \n"); } VOID CreateUsage(VOID) { printf("Creates a service entry in the registry and Service Database.\n"); printf("SYNTAX: \nsc create ...\n"); printf("CREATE OPTIONS:\n"); printf("NOTE: The option name includes the equal sign.\n" " type= \n" " start= \n" " error= \n" " binPath= \n" " group= \n" " tag= \n" " depend= \n" " obj= \n" " DisplayName= \n" " password= \n"); } VOID ReadLogUsage(VOID) { printf("\nReads a logfile and dumps the contents.\n"); printf("SYNTAX: \n eltest readlog logfile ...\n"); printf("READLOG OPTIONS:\n"); printf("NOTE: The option name includes the equal sign.\n"); printf(" ReadFlag= (default = fwd) \n" " RecordNum= record number where read should start (default=0)\n" " BufSize= size of the buffer (default = 10000)\n"); printf("EXAMPLE:\n eltest addreg application myapp MsgFile= MyMsgs.dll" " Type= error Type= warning\n"); } DWORD AddSourceToRegistry( IN LPTSTR ServerName, IN LPTSTR LogName, IN LPTSTR EventSourceName, IN LPTSTR *argv, IN DWORD argc ) /*++ Routine Description: This function writes to the registry all the information to register this application as an event source. Arguments: Return Value: --*/ { TCHAR tempName[MAX_PATH]; HKEY hKey; DWORD dwStatus=NO_ERROR; HKEY hRegistry=HKEY_LOCAL_MACHINE; LPTSTR EventMessageFile=NULL; LPTSTR CategoryMessageFile=NULL; LPTSTR ParameterMessageFile=NULL; DWORD dwTypes=0; DWORD dwCategoryCount=0; DWORD i; // // Look at the LogName, and generate the appropriate registry key // path for that log. // if (STRICMP(LogName, ApplLogName) == 0) { STRCPY(tempName, ApplLogRegName); } else if (STRICMP(LogName, SysLogName) == 0) { STRCPY(tempName, SysLogRegName); } else if (STRICMP(LogName, SecLogName) == 0) { STRCPY(tempName, SecLogRegName); } else { printf("AddSourceToRegistry: Invalid LogName\n"); return(ERROR_INVALID_PARAMETER); } STRCAT(tempName, EventSourceName); // // Get Variable Arguments // for (i=0; iLength); } } switch(GetLastError()) { case ERROR_INSUFFICIENT_BUFFER: // // Increase the size of the buffer and try again // if (numBytesReqd > BufSize) { LocalFree(pElBuffer); BufSize = numBytesReqd; pElBuffer = LocalAlloc(LPTR, BufSize); if (!pElBuffer) { printf("ReadLogFile: LocalAlloc Failed %d\n",GetLastError()); } goto TryAgain; } else { printf("ReadLogFile #1: THIS SHOULD NEVER HAPPEN\n"); } break; case ERROR_EVENTLOG_FILE_CHANGED: // // The current read position for this handle has been overwritten. // Reopen the file and print a message to the effect that some // records may have been missed. // printf("ReadLogFile: Current Read position has been overwritten\n"); hEventLog = OpenEventLog(ServerName,LogName); if (hEventLog == NULL) { printf("OpenEventLog failed %d\n",GetLastError()); goto CleanExit; } goto TryAgain; case ERROR_HANDLE_EOF: printf("EOF\n"); break; default: printf("UnknownError: %d\n",GetLastError()); break; } } CleanExit: if (pElBuffer != NULL) { LocalFree(pElBuffer); } if (hEventLog != NULL) { CloseEventLog(hEventLog); } return(0); } VOID DisplayRecord( PEVENTLOGRECORD pElRecord, BOOL PrintTheHeader ) /*++ Routine Description: Arguments: Return Value: --*/ { if (PrintTheHeader) { printf("RecNum/tTimeGen/tWriteTime/tEventID/tType/tNumStr/tCat/n"); } printf("%d/t%d/t%d/t%d/t%d/t%d/t%d\n", pElRecord->RecordNumber, pElRecord->TimeGenerated, pElRecord->TimeWritten, pElRecord->EventID, pElRecord->EventType, pElRecord->NumStrings, pElRecord->EventCategory); } LONG wtol( IN LPWSTR string ) { LONG value = 0; while((*string != L'\0') && (*string >= L'0') && ( *string <= L'9')) { value = value * 10 + (*string - L'0'); string++; } return(value); }