#use strict; use English; use warnings; use vars qw($opt_d $opt_v); use Getopt::Std; use Win32::OLE; use Win32::PerfLib; use Win32::API; use Win32::Process::Info; my %counter; my %r_counter; my $TOKEN_QUERY; my $TOKEN_ADJUST_PRIVILEGES; my $SE_PRIVILEGE_ENABLED; my $PROCESS_TERMINATE; my $SE_DEBUG_NAME; my $GetCurrentProcess; my $OpenProcessToken; my $LookupPrivilegeValue; my $AdjustTokenPrivileges; my $OpenProcess; my $TerminateProcess; my $CloseHandle; my $myserver = "xxxxxxx"; my $mydatabase = "mail/xxxxxxx.nsf"; # Define a directory to store the results my $dir = 'D:/PerlTestFolder/Notes'; # Define a list of "Normal" folders to skip my @badlist = ('_Archiving', 'Archiving\\Age of Documents', 'Discussion Threads', 'Events'); # Auto-print carriage returns $OUTPUT_RECORD_SEPARATOR = "\n"; # Open the email database in Lotus Notes my $notes = Win32::OLE->new('Notes.NotesSession', 'Quit') or die "Can't open Lotus Notes"; my $database = $notes->GetDatabase($myserver,$mydatabase); $database->OpenMail; # Verify the server connection print "Connected to ", $database->{Title}, " on ", $database->{Server}if $opt_v; # Loop over all of the folders foreach my $viewname (GetViews($database)) { # Get the object for this View print "Checking folder $viewname..."; my $view = $database->GetView($viewname); # Create a subdirectory to store the messages in $viewname =~ tr/()$//d; $viewname =~ s(\\)(.)g; chdir ($dir); # Get the first document in the folder my $num = 1; my $doc = $view->GetFirstDocument; next unless $doc; GetInfo($num, $dir, $doc); # Get the remaining documents in the folder while ($doc = $view->GetNextDocument($doc)) { $num++; GetInfo($num, $dir, $doc); } } #kill_process("notes2.exe"); sub GetInfo { my ($num, $path, $doc) = @_; my $subject = $doc->{Subject}->[0]; #Debug helper #print "Processing message $subject"; if ($subject =~ m/ISCD Notification/){ if ($subject =~ m/ISCD Notification Start/) { parseemail($num, $path, $doc, "Start", "", $subject); } elsif ($subject =~ m/ISCD Notification Stop/) { my $nid = ""; $nid = substr $subject, 22; parseemail($num, $path, $doc, "Stop", $nid, $subject); } } } sub GetViews { my ($database) = @_; my @views = (); # Loop through all of the views in this database my $array_ref = $database->{Views}; foreach my $view (@$array_ref) { my $name = $view->{Name}; # We only want folders if it's the Inbox # or a normal folder name with no parentheses if (($name eq '($Inbox)')){ # --Change to read only inbox-- #To read all folders, line above should be "if (($name eq '($Inbox)') or ($name !~ /\(.+\)/)) {" # Add the folder name to the @views list # if it's not in the @badlist push(@views, $name) unless (grep { $name eq $_ } @badlist); } if (($name eq '($Inbox)') or ($name !~ /\(.+\)/)) { } } return @views; } sub parseemail{ my ($num, $path, $doc, $type, $nid, $subject) = @_; my $body = $doc->{Body}; my $service = ""; my $org = ""; my $geo = ""; my $dur = ""; my $text = ""; my @lines = split /\n/, $body; foreach my $line (@lines) { if ($line =~ m/Service:/){ $service = substr $line, 8; $service =~ s/^\s+//; $service =~ s/\s+$//; } if ($line =~ m/Organization:/){ $org = substr $line, 13; $org =~ s/^\s+//; $org =~ s/\s+$//; } if ($line =~ m/Geography:/){ $geo = substr $line, 10; $geo =~ s/^\s+//; $geo =~ s/\s+$//; } if ($line =~ m/Duration:/){ $dur = substr $line, 9; $dur =~ s/^\s+//; $dur =~ s/\s+$//; } if ($line =~ m/Text:/){ $text = substr $line, 5; $text =~ s/^\s+//; $text =~ s/\s+$//; } } print "\"$type\",\"$nid\",\"$service\",\"$org\",\"$geo\",\"$dur\",\"$text\""; # Write the contents of the message to a file my $filename = "ISCD_Notification_$num.txt"; open (TEXTFILE, ">$path/$filename") or die "Can't create $path $filename: $!"; print TEXTFILE "\"$type\",\"$nid\",\"$service\",\"$org\",\"$geo\",\"$dur\",\"$text\""; close TEXTFILE; } sub kill_process { my $process = shift; my $result = 0; my $pid = getpid($process); if ($pid){ if (kill_pid($pid)){ print "Process=Successfully killed $process\n"; } else{ print "Process=Cannot kill $process\n"; } } else{ print "Process=$process not found\n"; } } sub getpid { my $process = shift; my $server = $ENV{COMPUTERNAME}; my $pid; Win32::PerfLib::GetCounterNames($server, \%counter); %r_counter = map { $counter{$_} => $_ } keys %counter; my $process_obj = $r_counter{Process}; my $process_id = $r_counter{'ID Process'}; my $perflib = new Win32::PerfLib($server) || return 0; my $proc_ref = {}; $perflib->GetObjectList($process_obj, $proc_ref); $perflib->Close(); my $instance_ref = $proc_ref->{Objects}->{$process_obj}->{Instances}; foreach my $p (sort keys %{$instance_ref}){ my $counter_ref = $instance_ref->{$p}->{Counters}; foreach my $i (keys %{$counter_ref}){ if($counter_ref->{$i}->{CounterNameTitleIndex} == $process_id && $instance_ref->{$p}->{Name} eq $process){ $pid = $counter_ref->{$i}->{Counter}; last; } } } #try again using a different approach WMI unless ($pid){ if (my $pi = Win32::Process::Info->new($server)){ my $processes = $pi->GetProcInfo(); my $number = @$processes; foreach (@$processes){ if ($_->{Name} =~ /$process/i){ $pid = $_->{ProcessId}; } } } } $pid?return $pid:return 0; } sub pidalive { my $pid = shift; my $server = $ENV{COMPUTERNAME}; Win32::PerfLib::GetCounterNames($server, \%counter); %r_counter = map { $counter{$_} => $_ } keys %counter; my $process_obj = $r_counter{Process}; my $process_id = $r_counter{'ID Process'}; my $perflib = new Win32::PerfLib($server) || return 0; my $proc_ref = {}; $perflib->GetObjectList($process_obj, $proc_ref); $perflib->Close(); my $instance_ref = $proc_ref->{Objects}->{$process_obj}->{Instances}; foreach my $p (sort keys %{$instance_ref}){ my $counter_ref = $instance_ref->{$p}->{Counters}; foreach my $i (keys %{$counter_ref}){ if ($counter_ref->{$i}->{Counter} == $pid){ return $pid; } } } return 0; } sub kill { my $process = shift; my $pid = getpid($process); if ($pid){ Configure(); my $iResult = ForceKill( $pid ); return 1 if( $iResult ); } return 0; } sub kill_pid { my $pid = shift; Configure(); my $iResult = ForceKill( $pid ); return 1 if( $iResult ); return 0; } sub ForceKill { my( $Pid ) = @_; my $iResult = 0; my $phToken = pack( "L", 0 ); # Fetch the process's token if($OpenProcessToken->Call($GetCurrentProcess->Call(), $TOKEN_ADJUST_PRIVILEGES | $TOKEN_QUERY, $phToken )){ my $hToken = unpack( "L", $phToken ); # Set the debug privilege on the token if( SetPrivilege( $hToken, $SE_DEBUG_NAME, 1 ) ){ # Now that we have debug privileges on the process # open the process so we can mess with it. my $hProcess = $OpenProcess->Call( $PROCESS_TERMINATE, 0, $Pid ); if( $hProcess ){ # We no longer need the debug privilege since we have opened # the process so remove the privilege. SetPrivilege( $hToken, $SE_DEBUG_NAME, 0 ); # Let's termiante the process $iResult = $TerminateProcess->Call( $hProcess, 0 ); $CloseHandle->Call( $hProcess ); } } $CloseHandle->Call( $hToken ); } return $iResult; } sub SetPrivilege { my( $hToken, $pszPriv, $bSetFlag ) = @_; my $pLuid = pack( "Ll", 0, 0 ); my $iResult; # Lookup the LIUD of the privilege if( $LookupPrivilegeValue->Call( "\x00\x00", $pszPriv, $pLuid ) ){ # Unpack the LUID my $pPrivStruct = pack( "LLlL", 1, unpack( "Ll", $pLuid ), ( ( $bSetFlag )? $SE_PRIVILEGE_ENABLED : 0 ) ); # Now modify the process's token to set the required privilege $iResult = ( 0 != $AdjustTokenPrivileges->Call( $hToken, 0, $pPrivStruct, length( $pPrivStruct ), 0, 0 ) ); } return $iResult; } sub Configure { $TOKEN_QUERY = 0x0008; $TOKEN_ADJUST_PRIVILEGES = 0x0020; $SE_PRIVILEGE_ENABLED = 0x02; $PROCESS_TERMINATE = 0x0001; $SE_DEBUG_NAME = "SeDebugPrivilege"; # Prepare to use some specialized Win32 API calls $GetCurrentProcess = new Win32::API( 'Kernel32.dll', 'GetCurrentProcess', [], N ) || die; $OpenProcessToken = new Win32::API( 'AdvApi32.dll', 'OpenProcessToken', [N,N,P], I ) || die; $LookupPrivilegeValue = new Win32::API( 'AdvApi32.dll', 'LookupPrivilegeValue', [P,P,P], I ) || die; $AdjustTokenPrivileges = new Win32::API( 'AdvApi32.dll', 'AdjustTokenPrivileges', [N,I,P,N,P,P], I ) || die; $OpenProcess = new Win32::API( 'Kernel32.dll', 'OpenProcess', [N,I,N], N ) || die; $TerminateProcess = new Win32::API( 'Kernel32.dll', 'TerminateProcess', [N,I], I ) || die; $CloseHandle = new Win32::API( 'Kernel32.dll', 'CloseHandle', [N], I ) || die; }