/* 
   Pierre A. Humblet
   May 2007
   Program to prints Windows application log entries.
   Derived from http://msdn2.microsoft.com/en-us/library/aa363676.aspx
*/

#include <windows.h>
#include <stdio.h>
#include <time.h>
#include <string.h>

#define BUFFER_SIZE 0x7ffff     // Max as of XP2 / Windows Server 2003

int main(int argc, char * argv[])
{
  HANDLE h;
  EVENTLOGRECORD *pevlr; 
  BYTE bBuffer[BUFFER_SIZE]; 
  DWORD dwRead, dwNeeded, dwThisRecord; 

  if (argc > 1)
   {
	printf("Usage: cronevents\n"
		"Function: prints cron and crontab Windows event log entries on stdout.\n"
		"Return value: 0 on success, 1 the if application log cannot be opened.\n");
	exit(1);
   } 

  // Open the Application event log. 
 
  h = OpenEventLog( NULL,    // use local computer
					"Application");   // source name
  if (h == NULL) 
    {
	  printf("Could not open the Application event log.\n"); 
	  exit(1);
    }
 
  pevlr = (EVENTLOGRECORD *) &bBuffer; 
 
  // Get the record number of the oldest event log record.

  GetOldestEventLogRecord(h, &dwThisRecord);

  // Opening the event log positions the file pointer for this 
  // handle at the beginning of the log. Read the event log records 
  // sequentially until the last record has been read. 
 
  while (ReadEventLog(h,                // event log handle 
					  EVENTLOG_FORWARDS_READ |  // reads forward 
					  EVENTLOG_SEQUENTIAL_READ, // sequential read 
					  0,            // ignored for sequential reads 
					  pevlr,        // pointer to buffer 
					  BUFFER_SIZE,  // size of buffer 
					  &dwRead,      // number of bytes read 
					  &dwNeeded))   // bytes in next record 
    {
	  while (dwRead > 0) 
        { 
		  SID_NAME_USE use;
		  DWORD sizeName, sizeDomain;
		  char name[100], domain[100];
		  struct tm tm;

		  /* All Cygwin entries have EventID == 0, NumStrings == 1, DataLength == 0.
		   Look for "cron" in the source string. */
		  if (pevlr->EventID != 0
			  || pevlr->NumStrings != 1
			  || pevlr->DataLength != 0
			  || !strstr((LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD)),
						 "cron")) 
			goto skip;

		  time_t timeGenerated = (time_t) pevlr->TimeGenerated;		  
		  localtime_r(&timeGenerated, &tm);
		  printf("%02d/%02d/%02d %02d:%02d:%02d ", 
				 1900 + tm.tm_year, 1 + tm.tm_mon, 
				 tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);

		  sizeName = sizeof(name);
		  sizeDomain = sizeof(domain);
		  if (LookupAccountSid(NULL, 
							   (PSID) ((LPBYTE) pevlr + pevlr->UserSidOffset),
							   name,
							   &sizeName,
							   NULL,
							   &sizeDomain,
							   &use))
			printf("[%s] ", name);

		  /* Printing the source is redundant, it is in the string
			 printf("%s ", 
			 (LPSTR) ((LPBYTE) pevlr + sizeof(EVENTLOGRECORD))); 
		  */

		  printf("%s\n", 
				 (LPSTR) ((LPBYTE) pevlr + pevlr->StringOffset));

		skip:
		  dwRead -= pevlr->Length; 
		  pevlr = (EVENTLOGRECORD *) 
			((LPBYTE) pevlr + pevlr->Length); 
        } 
 
	  pevlr = (EVENTLOGRECORD *) &bBuffer; 
    } 
 
  CloseEventLog(h);
  exit(0);
}

