#! perl -w

# ######################################################################### #
#
# FILE				: Eventlog.pl
#
# PURPOSE			: Enables an administrator to view and manage event
#					  log settings.
#
# LAST MODIFIED		: 30th August 2000.
# LAST MODIFIED By	: A.V. Kiran Kumar
#
# AUTHOR			: Basil Dias.
#
# ######################################################################### #

use strict; # Turn on script syntax checking
use Cwd;
BEGIN
{
	if( &IsWmiModuleInstalled() )
	{
		require W2RK::WMI; import W2RK::WMI; # WMI library
	}
	else
	{
		print STDERR "ERROR: Wmi.pm is required to run the script.\n       Copy Wmi.pm from the Resource Kit directory to /Perl/site/lib/W2RK.\n";
		exit( 0 );
	}

	sub IsWmiModuleInstalled
	{
		foreach ( @INC )
		{
			my $dir = $_."/W2RK/Wmi.pm";
			if( -e $dir )
			{
				require W2RK::WMI; import W2RK::WMI; # WMI library
				return 1;
			}
		}
		return 0;
	}
}


use constant ASNEDDED	=> 0;		#setbehavior value of 0.
use constant NEVER		=> -1;		#setbehavior value of -1.
use constant DEFBEHAVE	=> 7;		#Default behavior of 7 days.
use constant DEFMAXLOG	=> 524288;	#Defauklt maxlogsize of 512KB(512 * 1024).
use constant WBEMFLAG	=> 131072;	#Flag required for Put_ method
									#(WBEM_FLAG_USE_AMENDED_QUALIFIERS).
use constant WBEMPRIVILEGEBACKUP => 16;
use constant WBEMPRIVILEGESECURITY => 7;

# Usage messages
use constant USAGE_MAIN =>      "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -?\" for usage information.\n";
use constant USAGE_BACKUP =>    "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -backup -?\" for usage information.\n";
use constant USAGE_CHANGE =>    "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -change -?\" for usage information.\n";
use constant USAGE_CLEAR =>     "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -clear -?\" for usage information.\n";
use constant USAGE_EXPORT =>     "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -export -?\" for usage information.\n";
use constant USAGE_QUERY =>     "The syntax of the command is incorrect.\n".
                                "Type \"EventLog.pl -query -?\" for usage information.\n";

# Error messages
use constant ERROR_FMT_INVALIDOPTION => "ERROR: Invalid value '%s' for the %s option.\n";	# Error Code 7
use constant ERROR_FMT_LOG => "ERROR: Unable to clear '%s' log.\n";	# Error Code 254
use constant ERROR_FMT_MATCHES => "ERROR: '%s' log not found.\n";	# Error Code 3
use constant ERROR_FMT_INSTANCE => "ERROR: Unable to get the %s information.\n"; # Error Code 19
use constant ERROR_FMT_NOEVENTS => "ERROR: There are no events in '%s' Log.\n"; # Error Code 30
use constant ERROR_FMT_BACKUPLOG => "ERROR: Unable to backup '%s' log. File/Directory '%s' already exists.\n";	# Error Code 254
use constant ERROR_FMT_BACKUP => "ERROR: Unable to backup '%s' log. Could not create file '%s'.\n";	# Error Code 254
use constant ERROR_FMT_CHANGE => "ERROR: Unable to change '%s' log settings.\n";	# Error Code 254
use constant ERROR_FMT_CHANGESKIP => "SKIPPING: Current value of '%s' log is same. Property not set.\n";	# Error Code 100
use constant ERROR_FMT_EXPORT => "ERROR: Unable to export '%s' log. File\/Directory '%s' already exists.\n";	# Error Code 254
use constant ERROR_FMT_EXPORTFAIL => "ERROR: Unable to export '%s' log. Cannot create file '%s'.\n";	# Error Code 254
use constant ERROR_FILE => "ERROR: Option file requires an argument.\n";	# Error Code 8
use constant ERROR_NOFILE_WILDCARD => "ERROR: The -file parameter is not valid when the wildcard(*) argument is used.\n"; # Error No 7

# Success Messages
use constant MSG_FMT_LOG	=>	"SUCCESS: '%s' log cleared.\n";
use constant MSG_FMT_BACKUP	=>	"SUCCESS: '%s' log exported to file '%s'.\n";
use constant MSG_FMT_CHANGE	=>	"SUCCESS: '%s' log settings changed.\n";
use constant MSG_FMT_CHANGEINFO	=> "INFO: The '%s' log will be reduced in size. The new setting will not take effect until you clear the log. Do you want to continue(Y/N): ";

my $errorlevel = 0;
my (@lognames, @filenames)= ();

MAIN:
{
	my ($backup, $change, $clear, $export, $query, $help, $server, $user, $password);
	my ($maxsize, $behavior, $format ,$restore, $verbose, $log);

	my $wmi = W2RK::WMI->new;
	$SIG{__WARN__} = sub { die @_; };
	$wmi->ProcessOptions(
				"backup"	=> \$backup,
				"change"	=> \$change,
				"clear"		=> \$clear,
				"export"	=> \$export,
				"query"		=> \$query,
				"format=s"	=> \$format,
				"file=s"	=> \@filenames,
				"setmaxsize=s"	=> \$maxsize,
				"setbehavior=s"	=> \$behavior,
				"restore"	=> \$restore,
				"verbose"	=> \$verbose,
				"s=s"       => \$server,
				"u=s"       => \$user,
				"p=s"       => \$password,
				"h|?"		=> \$help);

	SWITCH:
	{
		if ( defined $backup && !defined $change && !defined $clear && !defined $export && !defined $query )
		{
			&BackupUsage() if( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password );

			fail USAGE_BACKUP, 8 if ( defined $help && ( defined $format || defined @filenames ||
				@ARGV > 0 || defined $maxsize || defined $behavior || defined $restore ||
				defined $verbose || defined $server || defined $user || defined $password ) );

			fail USAGE_BACKUP, 8 if ( ( defined $user && !defined $server ) || ( defined $password &&
				( !defined $user || !defined $server ) ) );

			fail USAGE_BACKUP, 8 if( @ARGV == 0 || defined $maxsize || defined $behavior || defined $restore || defined $verbose );
			@lognames = @ARGV;

			eval
			{
				$wmi->{server} = $server if( defined $server );
				$wmi->{username} = $user if( defined $user );
				$wmi->{password} = $password if( defined $password );
				$wmi->Connect();
			};
			fail $@, 9 if($@);

			# Set the privileges.
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGESECURITY);
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGEBACKUP);

			if(defined $format)
			{
				fail sprintf( ERROR_FMT_INVALIDOPTION, $format, "format" ), 7
					if( $format !~ /^EVT$|^TXT$|^CSV$/i );
				$format = 'normal' if($format =~ /^TXT$/i);
				$format = lc($format);
			}
			else
			{
				$format = 'evt';
			}

			if( &CheckWildcard( \@lognames ) )
			{
				fail( ERROR_NOFILE_WILDCARD, 7 ) if( @filenames );
			}

			&BackupLog($wmi, \@lognames, \@filenames, $format);
			last SWITCH;
		}
		if ( !defined $backup && defined $change && !defined $clear && !defined $export && !defined $query )
		{
			&ChangeUsage() if( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password );

			fail USAGE_CHANGE, 8 if ( defined $help && ( defined $format || defined @filenames ||
				@ARGV > 0 || defined $maxsize || defined $behavior || defined $restore ||
				defined $verbose || defined $server || defined $user || defined $password ) );

			fail USAGE_CHANGE, 8 if ( ( defined $user && !defined $server ) || ( defined $password &&
				( !defined $user || !defined $server ) ) );

			eval
			{
				$wmi->{server} = $server if( defined $server );
				$wmi->{username} = $user if( defined $user );
				$wmi->{password} = $password if( defined $password );
				$wmi->Connect();
			};
			fail $@, 9 if($@);

			# Set the privileges.
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGESECURITY);
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGEBACKUP);

			fail USAGE_CHANGE, 8 if( @ARGV == 0 || @filenames || $verbose || $format );
			fail USAGE_CHANGE, 8 if( !defined $maxsize && !defined $behavior && !defined $restore );

			fail sprintf( ERROR_FMT_INVALIDOPTION, $maxsize, "setmaxsize" ), 7
				if( defined $maxsize && ( $maxsize !~ /^\d+$/ || $maxsize < 1 || $maxsize > 4194240 ) );

			@lognames = @ARGV;

			if(defined $behavior)
			{
				if($behavior =~ /^NEVER$/i)
				{
					$behavior = NEVER;
				}
				elsif($behavior =~ /^ASNEEDED$/i)
				{
					$behavior = ASNEDDED;
				}
				elsif($behavior =~ /^OLDERTHAN\d+$/i)
				{
					$behavior = substr( $behavior,9 );
					fail sprintf( ERROR_FMT_INVALIDOPTION, $behavior, "setbehavior" ), 7
						if ($behavior < 0 && $behavior > 366);
				}
				else
				{
					fail sprintf( ERROR_FMT_INVALIDOPTION, $behavior, "setbehavior" ), 7;
				}
			}
			&ChangeLog($wmi, \@lognames, $maxsize, $behavior, $restore);
			last SWITCH;
		}
		if ( !defined $backup&& !defined $change && defined $clear && !defined $export && !defined $query )
		{
			&ClearUsage() if( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password );

			fail USAGE_CLEAR, 8 if ( defined $help && ( defined $format || defined @filenames ||
				@ARGV > 0 || defined $maxsize || defined $behavior || defined $restore ||
				defined $verbose || defined $server || defined $user || defined $password ) );

			fail USAGE_CLEAR, 8 if ( ( defined $user && !defined $server ) || ( defined $password &&
				( !defined $user || !defined $server ) ) );

			eval
			{
				$wmi->{server} = $server if( defined $server );
				$wmi->{username} = $user if( defined $user );
				$wmi->{password} = $password if( defined $password );
				$wmi->Connect();
			};
			fail $@, 9 if($@);

			# Set the privileges.
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGESECURITY);
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGEBACKUP);

			fail USAGE_CLEAR, 8 if( @ARGV == 0 || $maxsize || $behavior || @filenames || $verbose || defined $format );
			@lognames = @ARGV;

			&ClearLog($wmi, \@lognames);
			last SWITCH;
		}
		if( !defined $backup&& !defined $change && !defined $clear && defined $export && !defined $query )
		{
			&ExportUsage() if( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password );

			fail USAGE_EXPORT, 8 if ( defined $help && ( defined $format || defined @filenames ||
				@ARGV > 0 || defined $maxsize || defined $behavior || defined $restore ||
				defined $verbose || defined $server || defined $user || defined $password ) );

			fail USAGE_EXPORT, 8 if ( ( defined $user && !defined $server ) || ( defined $password &&
				( !defined $user || !defined $server ) ) );

			eval
			{
				$wmi->{server} = $server if( defined $server );
				$wmi->{username} = $user if( defined $user );
				$wmi->{password} = $password if( defined $password );
				$wmi->Connect();
			};
			fail $@, 9 if($@);

			# Set the privileges.
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGESECURITY);
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGEBACKUP);

			if(defined $format)
			{
				fail sprintf( ERROR_FMT_INVALIDOPTION, $format, "format" ), 7 if ( $format !~ /^TXT$|^CSV$/i );
				$format = 'normal' if($format =~ /^TXT$/i);
				$format = lc($format);
			}
			else
			{
				$format = 'normal';
			}
			@lognames = @ARGV;
			fail USAGE_EXPORT, 8 if( @lognames == 0 || defined $maxsize || defined $behavior || $verbose );

			if( &CheckWildcardExport( \@lognames ) )
			{
				fail( ERROR_NOFILE_WILDCARD, 7 ) if( @filenames );
			}

			&ExportLog($wmi, \@lognames, \@filenames, $format);
			last SWITCH;
		}
		if ( !defined $backup&& !defined $change && !defined $clear && !defined $export && defined $query )
		{
			&QueryUsage() if( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password );

			fail USAGE_QUERY, 8 if ( defined $help && ( defined $format || defined @filenames ||
				@ARGV > 0 || defined $maxsize || defined $behavior || defined $restore ||
				defined $verbose || defined $server || defined $user || defined $password ) );

			fail USAGE_QUERY, 8 if ( ( defined $user && !defined $server ) || ( defined $password &&
				( !defined $user || !defined $server ) ) );

			eval
			{
				$wmi->{server} = $server if( defined $server );
				$wmi->{username} = $user if( defined $user );
				$wmi->{password} = $password if( defined $password );
				$wmi->Connect();
			};
			fail $@, 9 if($@);

			# Set the privileges.
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGESECURITY);
			$wmi->services->{Security_}->{Privileges}->Add(WBEMPRIVILEGEBACKUP);

			if(defined $format)
			{
				fail sprintf( ERROR_FMT_INVALIDOPTION, $format, "format" ), 7 if( $format !~ /^TABLE$|^LIST$|^CSV$/i );
				$format = 'normal' if($format =~ /^TABLE$/i);
				$format = lc($format);
			}
			else
			{
				$format = 'normal';
			}
			@lognames = @ARGV;
			fail USAGE_QUERY, 8 if( @lognames == 0 || defined $maxsize || defined $behavior || @filenames );
			&QueryLog($wmi, \@lognames, \@filenames, $format, $verbose);
			last SWITCH;
		}
		&usage() if ( defined $help && !defined $format && !defined @filenames && @ARGV == 0 &&
				!defined $maxsize && !defined $behavior && !defined $restore && !defined $verbose &&
				!defined $server && !defined $user && !defined $password && !defined $backup &&
				!defined $change && !defined $clear && !defined $export && !defined $query );
		fail USAGE_MAIN, 8;
	} #end of SWITCH

	exit(0);  #end of main
} # End of Main

# ######################################################################### #
#
# PURPOSE	: Checks for valid lognames as entered through
#		  command line with -log option and clears log entries
#		  if -clear option is specified.
#
# INPUTS	: $rlogs - Reference to lognames array.
#		  $instances - Instances of Win32_NTEventLogFile.
#
# RETURN VALUE	: Array @newnames containing lognames.
#
# ######################################################################### #
sub CheckLog
{
	my @newlogs = ();
	my ($dumy, $flag);
	my ($lognames, $instances, $clear) = @_;

	for(my $index = 0;$index < @$lognames; $index++)
	{
		$flag = 0;
		$dumy = $$lognames[$index];
		$dumy  =~ s/\*+/\*/g;	$dumy =~ s/\[/\\\[/g;
		$dumy =~ s/\(/\\\(/g;	$dumy =~ s/\)/\\\)/g;
		$dumy =~ s/\$/\\\$/g;	$dumy =~ s/\|/\\\|/g;
		$dumy =~ s/\+/\\\+/g;	$dumy =~ s/\./\\./g;
		$dumy =~ s/\^/\\^/g;	$dumy =~ s/\?/\\?/g;	
		$dumy  =~ s/\*/.\*/g;
		for my $instance (in $instances )
		{
			if($instance->{LogfileName} =~ /^$dumy$/i)
			{
				$flag = 1;
				push(@newlogs,$instance->{LogfileName});
				if( defined $clear )
				{
					$instance->ClearEventlog();
					if(Win32::OLE->LastError == 0)
					{
						printf STDOUT ( MSG_FMT_LOG, $instance->{LogfileName} );
					}
					else
					{
						printf STDERR ( ERROR_FMT_LOG, $instance->{LogfileName} );
						$errorlevel = 254;
					}
				}
			}
		}
		if( !$flag )
		{
			printf STDERR ( ERROR_FMT_MATCHES, $$lognames[$index] );
			$errorlevel = 3;
		}
	}
	exit($errorlevel) if(@newlogs == 0);
	@$lognames = ();
	push(@$lognames, @newlogs);
}

# ######################################################################### #
#
# PURPOSE	: Executes the WMI query for retrieving data from
#		  the WMI object connected to.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $query - Query string.
#
# RETURN VALUE	: Array returned by CollectionToTable.
#		  Null if no events are present in the log.
#
# ######################################################################### #
sub ExecQuery
{
	my ($wmi, $query) = @_;
	my $collections;
	eval { $collections = $wmi->ExecQuery($query); };
	fail sprintf( ERROR_FMT_INSTANCE, "Event Log" ), 19 if( $@ );

	if($collections->{Count} == 0)
	{
		my $templog = substr($query,rindex($query,"=")+1);
		$templog =~ s/[\s|\"]*//g;
		printf STDERR ( ERROR_FMT_NOEVENTS, "$templog");
		$errorlevel = 30;
		return;
	}
	else
	{
		return $wmi->CollectionToTable($collections);
	}
}

# ######################################################################### #
#
# PURPOSE	: Backs up the eventlog in the specified format.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $rlogs - Reference to array of lognames.
#		  $rfiles - Reference to array of filenames.
#		  $format - Format string.
#		  $form - Format type.
#
# RETURN VALUE	: None.
#
# ######################################################################### #
sub BackupLog
{
	my ($wmi, $lognames, $filenames, $format) = @_;
	my $instances;
	eval{ $instances = $wmi->InstancesOf("Win32_NTEventLogFile"); };
	fail sprintf( ERROR_FMT_INSTANCE, "Event Log" ), 19 if($@);
	&CheckLog($lognames, $instances);
	my $backupfile;
	if($format eq 'evt')
	{
		for my $instance (in $instances )
		{
			for(my $indx=0; $indx < @$lognames; $indx++)
			{
				if($$lognames[$indx] =~ /^$instance->{LogfileName}$/i)
				{
					$backupfile = (defined $$filenames[$indx]) ? $$filenames[$indx] : "$$lognames[$indx].evt";
					if( -e $backupfile)
					{
						printf STDERR ( ERROR_FMT_BACKUPLOG, $$lognames[$indx], $backupfile );
						$errorlevel = 254;
						next;
					}
					if(index($backupfile, "\\") == -1)
					{
						my $temp = cwd;
						$temp =~ s/\//\\/g;
						$backupfile = "$temp\\$backupfile";
					}
					$instance->BackupEventLog($backupfile);
					if(Win32::OLE->LastError == 0 && ( -f $backupfile))
					{
						printf STDOUT ( MSG_FMT_BACKUP, "$$lognames[$indx]", "$backupfile" );
					}
					else
					{
						$instance->Copy($backupfile);
						if(Win32::OLE->LastError == 0 && ( -f $backupfile))
						{
							printf STDOUT ( MSG_FMT_BACKUP, "$$lognames[$indx]", "$backupfile" );
						}
						else
						{
							printf STDERR ( ERROR_FMT_BACKUP, "$$lognames[$indx]", "$backupfile" ) if( !( -f $backupfile ) );
							$errorlevel = 254;
						}
					}
					last;
				}
			}
		}
	}
	else
	{
		my $ext = ($format eq 'normal') ? ".txt" : ".csv";
		for(my $indx=0; $indx < @$lognames; $indx++)
		{
			$backupfile = (defined $$filenames[$indx]) ? $$filenames[$indx] : $$lognames[$indx].$ext;
			if( -e $backupfile)
			{
				printf STDERR ( ERROR_FMT_BACKUPLOG, "$$lognames[$indx]", "$backupfile" );
				$errorlevel = 254;
				next;
			}

			my $query = "SELECT * from Win32_NTLogEvent WHERE Logfile = \"$$lognames[$indx]\"";
			my @table = ExecQuery($wmi, $query) or next;
			my @fields =( TimeGenerated   => { Align => 'left' ,
					Formatter => sub { ConvertToOurDateTimeFormat($_[0],1) } },
				TimeWritten   => { Align => 'left',
					Formatter => sub { ConvertToOurDateTimeFormat($_[0],2) } },
				SourceName => {  Align => 'left',
					Formatter => sub{ FormatEntry($_[0]) } },
				Type => { Align => 'left',
					Formatter => sub{ FormatEntry($_[0]) } },
				CategoryString => { Align => 'left',
					Formatter => sub{ FormatEntry($_[0]) } },
				EventCode => {  Align => 'left',
					Formatter => sub{ FormatEntry($_[0]) } },
				User => { Align => 'left',
					Formatter => sub{ FormatUserName($_[0]) } },
 				ComputerName => { Align => 'left',
					Formatter => sub{ FormatEntry($_[0]) } },
				Message=> {  Align => 'left' ,
					Formatter => sub{ FormatEntry($_[0]) } });

			unless(open(LOG,">$backupfile"))
			{
				printf STDERR ( ERROR_FMT_BACKUP, "$$lognames[$indx]", "$backupfile" );
				$errorlevel = 254;
				next;
			}

			select(LOG) and $wmi->ShowTable(\@table, {Format => $format,
							Sort => 'TimeGenerated',
							NoHeader => 1 },
					@fields	);
			close(LOG); select(STDOUT);
			printf STDOUT ( MSG_FMT_BACKUP, "$$lognames[$indx]", "$backupfile" );
		}
	}
	exit($errorlevel);
}

# ######################################################################### #
#
# PURPOSE	: Changes the log settings for the specified eventlog file.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $rlogs - Reference to array of lognames.
#		  $maxsize - Maximum size of the log.
#		  $behavior - behavior setting to be applied on the log.
#		  $restore - Flag value for -restore option.
#
# RETURN VALUE	: None.
#
# ######################################################################### #
sub ChangeLog
{
	my ($wmi, $lognames, $maxsize, $behavior, $restore) = @_;
	my $flag = 0;
	my $instances;
	eval{ $instances = $wmi->InstancesOf("Win32_NTEventLogFile"); };
	fail sprintf( ERROR_FMT_INSTANCE, "Event Log" ), 19 if($@);

	&CheckLog($lognames, $instances);

	for my $instance (in $instances )
	{
		$flag = 0;
		for my $logname ( @$lognames )
		{
			if($logname =~ /^$instance->{LogfileName}$/i) 
			{
				if(defined $restore)
				{
					if( $instance->{MaxFileSize} != DEFMAXLOG)
					{
						$instance->{MaxFileSize} = DEFMAXLOG;
						$flag++;
					}
					if($instance->{OverwriteOutDated} != DEFBEHAVE)
					{
						$instance->{OverwriteOutDated} = DEFBEHAVE;
						$flag++;
					}
				}
				else
				{
					if( defined $maxsize)
					{
						my $rem = $maxsize%64;
						my $tempmaxsize = $maxsize;
						if($rem)
						{
							$tempmaxsize -= $rem;
							$tempmaxsize +=64 if($rem > 31);
						}
						$tempmaxsize = 64 unless($tempmaxsize);
						$tempmaxsize *= 1024;
						if($instance->{MaxFileSize} != $tempmaxsize)
						{
							if($instance->{MaxFileSize} > $tempmaxsize)
							{
								printf STDOUT ( MSG_FMT_CHANGEINFO, "$logname" );
								RESPONSE: my $response = <STDIN>;
								exit(254) if ( $response =~ /n/i );
								if( $response !~ /y/i )
								{
									printf STDOUT "\nInvalid input. Enter (Y/N) : ";
									goto RESPONSE;
								}
							}
							$instance->{MaxFileSize} = $tempmaxsize;
							$flag++;
						}
					}
					if( defined $behavior && $instance->{OverwriteOutDated} != $behavior )
					{
						$instance->{OverwriteOutDated} = $behavior ;
						$flag++;
					}
				}
				if($flag)
				{
					$instance->Put_(WBEMFLAG);
					if ( Win32::OLE->LastError )
					{
						printf STDERR ( ERROR_FMT_CHANGE, "$logname" );
						$errorlevel = 254;
					}
					else
					{
						printf STDOUT ( MSG_FMT_CHANGE, "$logname" );
					}
				}
				else
				{
					printf STDERR ( ERROR_FMT_CHANGESKIP, "$logname" );
					$errorlevel = 100;
				}
			}
		} # inner for.
	} # outer for.
	exit( $errorlevel);
}

# ######################################################################### #
#
# PURPOSE	: Clears up the log entries for the specified log.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $rlogs - Reference to array of lognames.
#
# RETURN VALUE	: None.
#
# ######################################################################### #
sub ClearLog
{
	my ($wmi, $lognames) = @_;
	fail USAGE_CLEAR, 8 unless(defined @$lognames);
	my $instances;
	eval{ $instances = $wmi->InstancesOf("Win32_NTEventLogFile"); };
	fail sprintf( ERROR_FMT_INSTANCE, "event log" ), 19 if($@);
	&CheckLog($lognames, $instances, 1);
	exit($errorlevel);
}

# ######################################################################### #
#
# PURPOSE	: Exports the log entries to a file in the format
#		  specified.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $rlogs - Reference to array of lognames.
#		  $rfiles - Reference to array of filenames.
#		  $format - Format string.
#		  $form - Form type.
#
# RETURN VALUE	: None.
#
# ######################################################################### #
sub ExportLog
{
	my ($wmi, $lognames, $filenames, $format) = @_;
	my ($exportfile, $query);
	my (@table, @fields) = ();

	my $instances;
	eval{ $instances = $wmi->InstancesOf("Win32_NTEventLogFile"); };
	fail sprintf( ERROR_FMT_INSTANCE, "event log" ), 19 if($@);

	&CheckLog($lognames, $instances);
	my $ext = ($format eq 'normal') ? ".txt" : ".csv";
	for(my $indx=0; $indx < @$lognames; $indx++)
	{
		$exportfile = (defined $$filenames[$indx]) ? $$filenames[$indx] : $$lognames[$indx].$ext;
		if( -e $exportfile)
		{
			printf STDERR ( ERROR_FMT_EXPORT, "$$lognames[$indx]", "$exportfile" );
			$errorlevel = 254;
			next;
		}

		$query = "SELECT * from Win32_NTLogEvent WHERE Logfile = \"$$lognames[$indx]\"";
		@table = ExecQuery($wmi, $query) or next;
		@fields =(Type => { Name => 'Type', Align => 'left',
			 Formatter => sub{ FormatEntry($_[0]) }},
		TimeGenerated   => { Name    => 'Date', Align => 'left',
			Formatter => sub{ ConvertToOurDateTimeFormat($_[0],1) } },
		TimeWritten   => { Name    => ' Time', Align => 'left',
			Formatter => sub { ConvertToOurDateTimeFormat($_[0],2) } },
		SourceName => { Name => 'Source', Align => 'left',
			Formatter => sub{ FormatEntry($_[0]) } },
		CategoryString => { Name => 'Category', Align => 'left', 
			Formatter => sub{FormatEntry($_[0]) } },
		EventCode => { Name => 'Event', Align => 'left',
			Formatter => sub{ FormatEntry($_[0]) } },
		User => { Name => 'User', Align => 'left', 
			Formatter => sub{ FormatUserName($_[0]) } },
		ComputerName => { Name => 'Computer', Align => 'left',
			Formatter => sub{ FormatEntry($_[0]) } } );

		unless( open(LOG,">$exportfile") )
		{
			printf STDERR ( ERROR_FMT_EXPORTFAIL, "$$lognames[$indx]", "$exportfile" );
			$errorlevel = 254;
			next;
		}
		select(LOG) and $wmi->ShowTable(\@table, {Format => $format,
				Sort => 'TimeGenerated',
				HeaderDashes => 0 },
				@fields	) ;

		close(LOG); select(STDOUT);
		printf STDOUT ( MSG_FMT_BACKUP, "$$lognames[$indx]", "$exportfile" );
	}
	exit($errorlevel);
}

# ######################################################################### #
#
# PURPOSE	: Queries the specified eventlog and displays
#		  data in the format specified.
#
# INPUTS	: $wmi - The reference to the WMI interface object.
#		  $rlogs - Reference to array of lognames.
#		  $rfiles - Reference to array of filenames.
#		  $format - Format string.
#		  $format - Format type.
#		  $verbose - Flag value set for -verbose option.
#
# RETURN VALUE	: None.
#
# ######################################################################### #
sub QueryLog
{
	my ($wmi, $lognames, $filenames, $format,$verbose)  = @_;

	my $instances;
	eval{ $instances = $wmi->InstancesOf("Win32_NTEventLogFile"); };
	fail sprintf( ERROR_FMT_INSTANCE, "event log" ) if($@);

	&CheckLog($lognames, $instances);
	my $query = "SELECT * from Win32_NTEventLogFile WHERE";
	for my $logname ( @$lognames )
	{
		$query = $query . " LogfileName = \"$logname\" OR";
	}
	substr($query, -2, 2) = "";		#remove the last extra "OR"
	my @table = ExecQuery($wmi, $query) or next;

	my @fields = ( LogfileName => { Name => 'Display Name',  Align => 'left',
			Formatter => sub { sprintf("%s Log", $_[0]) } },
		FileSize => { Name => 'Size', Align => 'left',
			Formatter => sub { sprintf("%dKB", $_[0] / 1024) } },
		CreationDate => { Align => 'left', Hide => ($verbose ? 0 : 1 ),
			Formatter => sub { ConvertToOurDateTimeFormat($_[0],1) } },
		LastModified => { Align => 'left', Hide => ($verbose ? 0 : 1),
			Formatter => sub { ConvertToOurDateTimeFormat($_[0],1) } },
		LastAccessed => { Align => 'left', Hide => ($verbose ? 0 : 1) ,
			Formatter => sub { ConvertToOurDateTimeFormat($_[0],1) } },
		MaxFileSize  =>  { Name => "MaxLogSize", Align => 'left',
			Hide => ($verbose ? 0 : 1),
			Formatter => sub { sprintf("%dKB", $_[0] / 1024) } },
		OverwriteOutDated => { Name => "LogBehavior", Align => 'left',
			Hide => ($verbose ? 0 : 1), 
			Formatter => sub { &FormatBehavior($_[0]) } },
		NumberOfRecords => { Name => '# Event ', Align => 'left',
			Formatter => sub{ FormatEntry($_[0]) } },
		Description => { Name => 'Description', Align => 'left',
			Formatter => sub{ FormatEntry($_[0]) } } );

	$wmi->ShowTable(\@table, {Format => $format,
				Sort  => 'LogfileName',
				HeaderDashes => 1 },
			@fields	);
	exit($errorlevel);
}

# ######################################################################### #
#
# PURPOSE	: convert the date from the  wmi format 
#		  yyyymmddHHMMSS.mmmmmmsUUU ( yyyy - 4 digit year,
#		  mm - month, dd-month day, HH-hour, MM-minute, SS-seconds,
#		  mmmmmmm - micro secs, s -sign (+ or -) UUU - time zone )
#		  to the readable format mm/dd/yy:hh:mm:ss.
#
# INPUTS	: $DateTime - DateTime in the format mm/dd/yy:hh:mm
#		  $DT - Flag value specifying the format of the return value.
#			0 - mm/dd/yy hh:mm:ss
#			1 - mm/dd/yy
#			2 - hh:mm:ss
#
# RETURN VALUE	: $WmiDateTime in the format as specified by the $DT flag.
#
# ######################################################################### #
sub ConvertToOurDateTimeFormat
{
	my $DateTime;
	my ($WmiDateTime, $DT) = @_;
	if( $DT =~ /^1$|^0$/i)
	{
		$DateTime .= (defined substr($WmiDateTime,4,2) ? substr($WmiDateTime,4,2) : "--");
		$DateTime .= "\/" . (defined substr($WmiDateTime,6,2) ? substr($WmiDateTime,6,2) : "--");
		$DateTime .= "\/" . (defined substr($WmiDateTime,0,4) ? substr($WmiDateTime,0,4) : "--");
	}
	if( $DT =~ /^2$|^0$/i)
	{
		$DateTime .= " " . (defined substr($WmiDateTime,8,2) ? substr($WmiDateTime,8,2) : "--");
		$DateTime .= ":" . (defined substr($WmiDateTime,10,2) ? substr($WmiDateTime,10,2) : "--");
		$DateTime .= ":" . (defined substr($WmiDateTime,12,2) ? substr($WmiDateTime,12,2) : "--");
	}
	return $DateTime;
}


# ######################################################################### #
#
# PURPOSE	: To check if the wildcard * is used in the backup  command 
#
# INPUTS	: The user name entry.
#
# RETURN VALUE	: 1 if '*' exists else 0 
#
# ######################################################################### #
sub CheckWildcard
{
	my( $lognames ) = @_;

	my %LogHash;
	foreach ( @$lognames )
	{
		if ($_ =~ /\*/) 
		{
			return 1;
		}
		next if( exists( $LogHash{ $_ } ) );
		$LogHash{ $_ } = 1;
		push( @$lognames , $_ );
	}
	return 0;
}

# ######################################################################### #
#
# PURPOSE	: To check if the wildcard * is used in the export  command 
#
# INPUTS	: The user name entry.
#
# RETURN VALUE	: 1 if '*' exists else 0 
#
# ######################################################################### #
sub CheckWildcardExport
{
	my( $lognames ) = @_;

	my %LogHash;
	foreach ( @$lognames )
	{
		if ($_ =~ /\*/) 
		{

			return 1;
		}
		next if( exists( $LogHash{ $_ } ) );
		$LogHash{ $_ } = 1;
	}
	return 0;
}


# ######################################################################### #
#
# PURPOSE	: This formats the user name in a readable format.
#
# INPUTS	: The user name entry.
#
# RETURN VALUE	: $user - in a readable format.
#
# ######################################################################### #
sub FormatUserName
{
	my $user;
	my $WmiUser = $_[0];
	chomp($WmiUser);
	my $rindex = rindex($WmiUser,"\\");

	$user = ($rindex < 0) ? $WmiUser : substr($WmiUser,$rindex+1);
	$user = FormatEntry($user);
	return $user;
}

# ######################################################################### #
#
# PURPOSE	: Replaces the WmiEntry string with N/A wherever unavailable.
#
# INPUTS	: $WmiEntry -The Wmi entry string.
#
# RETURN VALUE	: $WmiEntry - in a readable format.
#
# ######################################################################### #
sub FormatEntry
{
	my $WmiEntry = $_[0]||"";
	$WmiEntry =~ s/\r\n/ /g;
	return ($WmiEntry ne "") ? ucfirst($WmiEntry) : "N\/A";
}

# ######################################################################### #
#
# PURPOSE	: Format the behavior value to the standard format.
#
# INPUTS	: $value - Behavior value.
#
# RETURN VALUE	: Behavior string.
#
# ######################################################################### #

sub FormatBehavior
{
	my $value = $_[0];
	if($value eq '')
	{
		return "N\/A";
	}
	elsif($value eq '0')
	{
		return "OVERWRITE EVENTS AS NEEDED";
	}
	elsif($value eq '-1')
	{
		return "NEVER OVERWRITE EVENTS";
	}
	else
	{
		return "OVERWRITE EVENTS OLDER THAN $value DAYS";
	}
}

# ######################################################################### #
#
# PURPOSE	: Prints usage to STDOUT and exits.
#
# ######################################################################### #
sub usage
{
print <<EOF;

EventLog.pl -Operation [arguments]

Description:
    Enables an administrator to view and manage event log settings.

Operation List:
    -backup     Backup one or more event logs.
    -change     Change one or more settings in a defined event log.
    -clear      Clear/Erase all events in a defined event log.
    -export     Export one or more event logs to a text file.
    -query      Query the properties/settings for one or more event logs.

For Detailed Usage:
    EventLog.pl -backup -?
    EventLog.pl -change -?
    EventLog.pl -clear  -?
    EventLog.pl -export -?
    EventLog.pl -query  -?

EOF
	exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -backup option to STDOUT and exits.
#
# ######################################################################### #
sub BackupUsage
{
print <<EOF;

EventLog.pl -backup [-s machine [-u user [-p password]]]
            [-format format]
            [-file filename]
            logname...

Description:
    Backup one or more event logs in a variety of formats.

Parameter List:
    -s           machine        Specifies the remote system to connect to.

    -u           user           Specifies the user name(user context)
                                to run the scripts commands under.

    -p           password       Specifies user password.

    -format      format         Specifies the backup format to use.
                                Valid formats are: EVT, TXT, CSV.

    -file        filename       Specifies the filename(s) to use for
                                backing up the log(s) to.

    default                     Specifies the log(s) to backup.

Examples:
    EventLog.pl -backup *
    EventLog.pl -backup Application -format CSV
    EventLog.pl -backup System Security -file SysEvt.txt -file SecEvt.txt
    EventLog.pl -backup System Security Application -file SysEvt.txt
                -file SecEvt.txt -file appEvt.txt

EOF
    exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -change option to STDOUT and exits.
#
# ######################################################################### #
sub ChangeUsage
{
print <<EOF;

EventLog.pl -change [-s machine [-u user [-p password]]]
            [-setmaxsize maxsize]
            [-setbehavior behavior]
            -restore
            logname...

Description:
    Change one or more settings in a defined event log.

Parameter List:
    -s           machine        Specifies the remote system to connect to.

    -u           user           Specifies the user name(user context)
                                to run the scripts commands under.

    -p           password       Specifies user password.

    -setmaxsize  maxsize        Specifies new Max Log Size(in KB).
                                Maxsize needs to be a 64KB increment.
                                Valid range is 1 - 4194240.

    -setbehavior behavior       Specifies new Max Log Behavior.
                                Valid Behaviors are : NEVER, ASNEEDED
                                or OLDERTHANX(1-365).

    -restore                    Restore a log's settings to its default
                                values. This overrides the -setmaxsize
                                and -setbehavior options.

    default                     Specifies the log(s) to change.

Examples:
    EventLog.pl -change -restore S*
    EventLog.pl -change -setmaxsize 512 -setbehavior OLDERTHAN15 System
    EventLog.pl -change -setmaxsize 1024 -restore Application

EOF
	exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -clear option to STDOUT and exits.
#
# ######################################################################### #
sub ClearUsage
{
print <<EOF;

EventLog.pl -clear [-s machine [-u user [-p password]]]
            logname...

Description:
    Clear/Erase all events in a defined event log.

Parameter List:
    -s        machine        Specifies the remote system to connect to.

    -u        user           Specifies the user name(user context)
                             to run the scripts commands under.

    -p        password       Specifies user password.

    default                  Specifies the log(s) to clear.

Examples:
    EventLog.pl -clear S*
    EventLog.pl -clear Application

EOF
	exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -export option to STDOUT and exits.
#
# ######################################################################### #
sub ExportUsage
{
print <<EOF;

EventLog.pl -export [-s machine [-u user [-p password]]]
            [-format format]
            [-file filename]
            logname...

Description:
    Export one or more event logs to a text file.

Parameter List:
    -s        machine        Specifies the remote system to connect to.

    -u        user           Specifies the user name(user context)
                             to run the scripts commands under.

    -p        password       Specifies user password.

    -format   format         Specifies the export format to use.
                             Valid formats are: TXT and CSV.

    -file     filename       Specifies the filename(s) to use for
                             exporting the log(s) to.

    default                  Specifies the log(s) to export.

Examples:
    EventLog.pl -export System
    EventLog.pl -export * -s server -u user -p password
    EventLog.pl -export Security -format CSV -file seclog.csv
    EventLog.pl -export Security Application -format CSV -file seclog.csv 
                -file applog.csv
    EventLog.pl -export Security Application System -format CSV 
                -file seclog.csv -file applog.csv -file syslog.csv

EOF
	exit(0);
}

# ######################################################################### #
#
# PURPOSE	: Prints usage for -query option to STDOUT and exits.
#
# ######################################################################### #
sub QueryUsage
{
print <<EOF;

EventLog.pl -query [-s machine [-u user [-p password]]]
            [-verbose]
            [-format format]
            logname...

Description:
    Query and display the properties/settings for one or more event logs.

Parameter List:
    -s        machine        Specifies the remote system to connect to.

    -u        user           Specifies the user name(user context)
                             to run the scripts commands under.

    -p        password       Specifies user password.

    -verbose                 Specifies to show detailed properties for
                             given event log.

    -format   format         Specifies the output format to use.
                             Valid formats are: TABLE, LIST, CSV.

    default                  Specifies the log(s) to query for.

Examples:
    EventLog.pl -query System -s machine -u user -p password
    EventLog.pl -query System -verbose
    EventLog.pl -query * -format CSV

EOF
	exit(0);
}