This will check for 6,6a, or hotfixes, and install hotfixes that are needed.
Hotfixes should be in a directory called 'hotfixes' in the same dir as the
script, and named after the Q article (i.e. Q248399.exe) The MD5
checksumming is disabled, too. Pretty much incomplete, but maybe useful.

Without any warranty, Its a few months out of date; someone took over and
integrated it into out NMS framework.  

######################################################
# Hotfix Auditing and Installation Tool
# Chris Bell    [EMAIL PROTECTED]
my $vernum=".77";       my $verdate="2.10.01";
######################################################
use Win32::EventLog;
use Win32::EventLog::Message;
use Win32::TieRegistry qw(KEY_READ);
use File::Copy;
#use Digest::MD5;

&Usage if not @ARGV;

ARG: while (@ARGV) {
  my $arg=shift;
  $arg=~s/\-//;
  if ($arg=~/^l$/i) {
    $slist=shift;
    next ARG;
  }
  if ($arg=~/^s$/i) {
    $svr=shift;
    push @slist, $svr;
    next ARG;
  }
  elsif ($arg=~/^i$/i) {
    print "Fix Mode Enabled.\n";
    $fix=1;
    next ARG;
  }
  elsif ($arg=~/^m$/i) {
    print "Show Missing Hotfixes Enabled.\n";
    $showmissing=1;
    next ARG;
  }
  elsif ($arg=~/^fd$/i) {
    print "File Check (Date/Size) Enabled.\n";
    $checkfiles=1;
    $checkdate=1;
    next ARG;
  }
  elsif ($arg=~/^fm$/i) {
    print "File Check (MD5 Checksum) Enabled.\n";
    $checkfiles=1;
    $checkmd5=1;
    next ARG;
  }
  elsif ($arg=~/^tw$/i) {
    print "Web Server Scan Mode Enabled.\n";
    $web=1;
    next ARG;
  }
  elsif ($arg=~/^td$/i) {
    print "Domain Controller Scan Mode Enabled.\n";
    $dc=1;
    next ARG;
  }
  elsif ($arg=~/^ts$/i) {
    print "SQL Server Scan Mode Enabled.\n";
    $sql=1;
    next ARG;
  }
  elsif ($arg=~/^c$/i) {
    print "Continuous Mode Enabled.\n";
    $continue=1;
    next ARG;
  }
  elsif ($arg=~/^6a$/i) {
    print "sp6a Check Mode Enabled.\n";
    $sp6acheck=1;
    next ARG;
  }
  elsif ($arg=~/^q$/i) {
    print "Quiet Mode Enabled.\n";
    $quiet=1;
    next ARG;
  }
  elsif ($arg=~/^f$/i) {
    $logtofile=1;       
    $logfile=shift;
    print "Logging to file $logfile.\n";
    next ARG;
  }
    
  elsif ($arg=~/^(h|help)$/i) {
    &Usage;
  }
  else {
    print "Invalid option: $arg\n";
    &Usage;
  }
}

if (defined $slist) {
  if (not -e $slist) {
    print "Serverlist not found: $slist\n";
    &Usage;
  }
  else {
    open (SLIST,"<$slist") or die "Could not open server list ($slist): $!";
    @slist=<SLIST>;
    close SLIST;
  }
}

if (not defined @slist) {
  print "No Server list or single server defined: $slist\n\n";
  &Usage;
}

my @hotfixes=();
if ($dc) {
  @hotfixes=(
  "Q243649",
  "Q243835",
  "Q244599",    #"Q238934",  # crypt32.dll is replaced by Q263305
  "Q246045",
  "Q246467",
  "Q247869",    #"Q245148",  # Winlogon is replaced by Q264684
  "Q248183",
  "Q248399",
  "Q249108",
  "Q249973",
  "Q257870",
  "Q259622",
  "Q259728",
  "Q262694",
  "Q263305",
  "Q264684",
  "Q266433",
  "Q269049",
  "Q269239",
  "Q271652",
  "Q274835",
  "Q275567",    # NEW "Q279336" #,"Q265714"
  );    
}
else {
  @hotfixes=(
  "Q243649",
  "Q243835",
  "Q244599",    #"Q238934",  # crypt32.dll is replaced by Q263305
  "Q246045",
  "Q246467",
  "Q247869",    #"Q245148",  # Winlogon is replaced by Q264684
  "Q248183",
  "Q248399",
  "Q249108",
  "Q249973",
  "Q257870",
  "Q259622",
  "Q259728",
  "Q260205",
  "Q262694",
  "Q263305",
  "Q264684",
  "Q266433",
  "Q269049",
  "Q269239",
  "Q271652",
  "Q274835",
  "Q275567",    # NEW "Q279336" #,"Q265714"
  );

}

print "Checking against " . scalar @hotfixes . " hotfixes in the list.\n";

my %fileinfo=(
  "drivers\\afd.sys" => ["11/16/1999","66,448","4hUDCnxC26R8TOgiwTJtrQ"],
  "drivers\\beep.sys" => ["10/29/1999","4,112","0vCoe9l9Y8xd9s/+CuG+AQ"],
  #"bone.dll" => ["10/30/2000","10,000","E6Gf/s8Z03eGt0facNmSLw"],
  #"browser.dll" => ["10/30/2000","18,192","qgrn+4emj04+Rtee9iftiw"],
  "cmd.exe" => ["04/19/2000","208,144","mhV4eiD7xmE5kOSFKlnuFg"],
  "crypt32.dll" => ["01/20/2000","371,472","2RpIOQpjYDpZT6aah15urg"],
  "drivers\\floppy.sys" => ["10/29/1999","18,928","8Di9GjxvBBl8jtC5pZph1A"],
  "inetsrv\\infocomm.dll" =>
["04/24/2000","185,760","llK0gGz3iVsrUi8a7o5vog"],
  #"ipx.dll" => ["10/30/2000","42,768","wmShAtfUe3aQTC0MCygg0A"],
  "jet500.dll" => ["10/13/1999","458,512","3qcYAzV2ZBzywr1BoRNxYQ"],
  "kernel32.dll" => ["08/30/2000","375,056","3JugoBmuJv6tXRCuVPpgsg"],
  #"lmmon.dll" => ["11/03/1999","12,560","NgZZer1YSkPFrLkd1NJN5Q"],
  "localmon.dll" => ["11/03/1999","18,704","/S6jxiQd8OuwL0cv39wFsA"],
  "localspl.dll" => ["11/03/1999","140,560","m5WM7UnIIKVqZPq0cOmD9A"],
  #"lpdsvc.dll" => ["03/28/2000","23,312","RGbWbPtwigQseuERmbmmSw"],
  #"lprhelp.dll" => ["11/03/1999","13,072","yMHVdqWY6XUY5kDFES0qEw"],
  #"lprmon.dll" => ["11/03/1999","21,776","5wSBSivaVPXlKCpZAX2waA"],
  "lsasrv.dll" => ["12/06/1999","155,408","MjSVyNg2Y6tW3Jy5LuTOig"],
  "msaudite.dll" => ["09/26/2000","19,216","7ieAGB2ZIEYbe+tRUyGElg"],
  "msgina.dll" => ["07/25/2000","124,176","0Nlx7S1T6ydcSAtdxlFVHg"],
  #"ncp.dll" => ["10/30/2000","203,536","Yw20wOwJk98cMDg2sK+tqA"],
  #"netbios.dll" => ["10/30/2000","21,280","4pDbABFGIZsj2cNKiwX6Yg"],
  "drivers\\netbt.sys" => ["09/29/2000","124,688","sTeoZKeeYwd6hZj3SFNapg"],
  "drivers\\netdtect.sys" =>
["10/29/1999","8,368","vIHEh5Mnx4np1N1mg1SiBw"],
  #"nmapi.dll" => ["10/30/2000","63,968","RCxQoi0Yt6HQyUdiaom6UQ"],
  #"nntp.dll" => ["10/30/2000","20,752","hrc281UASKLC4X1aInsF6w"],
  #"ntkrnlmp.exe" => ["09/26/2000","956,352","O2GZ8DEnOVPB8xBOA5DT2A"],
  "ntoskrnl.exe" => ["09/26/2000","935,936","TfDZ7o8ZzAli9zi6ilkh4Q"],
  "drivers\\null.sys" => ["10/29/1999","2,800","ZwQUWQQFLfvUbF4jNFH2sg"],
  "drivers\\parallel.sys" =>
["11/09/1999","14,960","zhUtBAQCevLuwggA2CjROg"],
  "drivers\\parport.sys" =>
["10/29/1999","10,064","wohzLpXkrD6PD9zrsT9Inw"],
  #"ppp.dll" => ["10/30/2000","63,760","YRcr8HXQbtKFu2Sd6vxEOg"],
  "rdisk.exe" => ["01/02/2000","68,368","D5HW8s4j6b/EKuKFrohq+A"],
  #"rdr.sys" => ["05/19/2000","265,712","d2mJkTX+1mvViw9k1tC5rQ"],
  #"regacl40.exe" => ["06/23/2000","42,256","8wJNrTqwV6SIqyLgPsz7Gg"],
  "riched20.dll" => ["12/23/1999","268,560","BTxeAYlR1sSxeOfgIpz6EA"],
  "riched32.dll" => ["12/23/1999","173,328","DRAnvqhwXYifeJdYSJWbcw"],
  "rpcrt4.dll" => ["06/02/2000","343,312","XY5SyZwIcOvSnjuZ3ntWg"],
  "samsrv.dll" => ["12/06/1999","174,352","xyK06DcbaqEWJdWTqHwnbQ"],
  "drivers\\scsiport.sys" =>
["10/29/1999","35,440","peXtzI7APayCmDmBxttSaQ"],
  "shell32.dll" => ["06/07/2000","1,280,784","4J0VA3co+kZX5aRkbanooQ"],
  #"smb.dll" => ["10/30/2000","168,208","E1+r5Q81ayOmsnBSBG6STw"],
  "smss.exe" => ["09/11/2000","40,208","rRUhd4brDLM5ifX0bNbUdw"],
  #"snmp.dll" => ["10/30/2000","16,656","N4La5cL24FULkGKtFycniw"],
  "spoolss.dll" => ["11/03/1999","48,400","xGKaJK4/yxZKiegLCFfw4w"],
  "spoolss.exe" => ["11/03/1999","39,184","RXe+V+3aZGrnR2BihtsEcw"],
  "srvsvc.dll" => ["11/22/1999","99,600","jmw26sqFCPAP/ai4YptuoQ"],
  "inetsrv\\ssinc.dll" => ["04/24/2000","38,256","jNpOn6CMeE5CAkyfcXFAAw"],
  "inetsrv\\sspifilt.dll" =>
["04/24/2000","25,360","OytDpczwkr0ebbOwmUwU9A"],
  "tcpcfg.dll" => ["06/23/2000","161,040","X5Qb62bc28LL0Rfj9Sb/YA"],
  #"tcpip.dll" => ["10/30/2000","186,128","I1dh8nNnYq6OqB+K/fBnqg"],
  "drivers\\tcpip.sys" => ["04/27/2000","174,512","Gpoi5MvyM+k0NRRf43tT0w"],
  #"tds.dll" => ["10/30/2000","112,912","QZZerZ+bg1x6kDplaq5xMg"],
  #"trail.dll" => ["10/30/2000","21,264","o79Cgm6LoKag+VkE6mAPqw"],
  "userinit.exe" => ["07/25/2000","26,896","+nR7prb+91HbUJvC7YKYrw"],
  #"vines.dll" => ["10/30/2000","26,896","UTZV5BuQ7AGlBtr1Q53FXw"],
  "inetsrv\\w3svc.dll" => ["04/24/2000","228,496","vxJvai9V1lbDhlqaxMg2tg"],
  "win32spl.dll" => ["11/03/1999","80,144","2TGf6il7YwqsHZkr9A458g"],
  "winlogon.exe" => ["06/05/2000","192,784","mgg1dRCo728txrpaqm2EPg"],
  "wshtcpip.dll" => ["10/29/1999","18,704","OcaCgxu0XorJpJgt6VWhA"]
);

if (($continue) and ($fix)) {
  ErrPrint("You cannot fix and continue. That will make lots of jobs. Try
again.","ERROR",4);     
}

START:;

SERVER: for my $server (@slist) {
  chomp $server;
  
  system("title HFCheck - Checking $server");

  my $count=0;
  my $ping=`ping $server -n 2`;
  &ErrPrint("Connect Failed",$server,3,1,$quiet) unless ($ping=~/Reply
from/);

  if ($sp6acheck) {
    if (not my
$hfkey=$Registry->Connect($server,"LMachine\\Software\\Microsoft\\Windows
NT\\CurrentVersion\\Hotfix\\Q246009",{Access=>KEY_READ})) {
      &ErrPrint("sp6a Not Installed",$server,1);
    }
    next SERVER if ($sp6acheck);
  }

  HOTFIX: for my $hotfix (@hotfixes) {
    if (my
$hfkey=$Registry->Connect($server,"LMachine\\Software\\Microsoft\\Windows
NT\\CurrentVersion\\Hotfix\\$hotfix",{Access=>KEY_READ})) {
      my $hfinstalled=$hfkey->GetValue("Installed");
      $hfinstalled=~s/^0x0000000//;
      if (not $hfinstalled) {
        LogPrint("$hotfix,$hfinstalled",$server);
        $$server{$hotfix}++;
      }
      else {
        $count++;
      }
    }
    else {
      if ($showmissing) {
        LogPrint("Needs $hotfix",$server,1);
        &GenerateEvent("Hotfix",$server,$hotfix);
      }
      &CopyHotFix($server,$hotfix) or &ErrPrint("Could not copy
$hotfix",$server,2);
      $$server{$hotfix}++;
    }
  }

  my $hfcount=scalar @hotfixes;
  if ($count != $hfcount) {
    if (($count eq '22') and ($dc) and ($$server{'Q260205'})) {
      LogPrint("OK",$server,1) if (not $quiet);         
    }
    else {
      LogPrint("ERROR: Hotfix count $count/$hfcount",$server,1);
    }
  }
  else {
    LogPrint("OK",$server,1) if (not $quiet);
  }
  if ($checkfiles) {
    for my $file (sort keys %fileinfo) {
      my $remfile="\\\\$server\\admin\$\\system32\\$file";
      if (-e $remfile) {
        if ($checkdate) {
          my $filedir=`dir $remfile `;
          if
($filedir=~/(\d{2}\/\d{2}\/\d{4})\s+(\d{2}:\d{2}(a|p))\s+(\d+\,\d+\,*\d*)\s+
((\w|\d)+\.(\w|\d)+)/) {
            $filedate=$1;
            $filesize=$4;
            #LogPrint("$remfile,$filedate,$filesize",$server,1);
          }
          else {
            ErrPrint("Could not get file info, regex mismatch:
$filedir",$server);
          }
          if ($filedate eq $fileinfo{$file}[0]) {
            #LogPrint("$file date matches",$server,1);
            if ($filesize eq $fileinfo{$file}[1]) {
              #LogPrint("$file size matches",$server,1);
            }
            else {
              LogPrint("$file != $fileinfo{$file}[1]
($filesize)",$server,1);
 
if(copy("files\\$file","\\\\$server\\admin\$\\system32\\$file"))
{&LogPrint("Copied $file",$server,1)}
              else {
 
if(copy("files\\$file","\\\\$server\\admin\$\\hotfixes\\$file"))
{&LogPrint("Copied $file to temp",$server,1)}
                else {&ErrPrint("Could not copy $file to temp",$server)}
              }

            }
          }
          else {
            LogPrint("$file != $fileinfo{$file}[0] ($filedate)",$server,1);
            if(copy("files\\$file","\\\\$server\\admin\$\\system32\\$file"))
{&LogPrint("Copied $file",$server,1)}
            else {
 
if(copy("files\\$file","\\\\$server\\admin\$\\hotfixes\\$file")) {
                &LogPrint("Copied $file to temp",$server,1);
                if (not -e "\\\\$server\\admin\$\\hotfixes\\inuse.exe") {
                  if
(copy("files\\inuse.exe","\\\\$server\\admin\$\\hotfixes\\inuse.exe")) {
                    &LogPrint("Copied inuse.exe to temp",$server,1);

                  }
                  else {&ErrPrint("Could not copy inuse.exe to
temp",$server)}
                }
              }
              else {&ErrPrint("Could not copy $file to temp",$server)}
            }
          }
        }
        elsif ($checkmd5) {
          my $filecontents;
          {
            open FH, $remfile;
            local $/=undef;
            binmode(FH);
            $filecontents=<FH>;
          }
          $checksum=Digest::MD5::md5_base64($filecontents);
          if ($checksum eq $fileinfo{$file}[2]) {
            LogPrint("checksum match for $file",$server,1);
          }
          else {
            LogPrint("checksum MISMATCH for $file: $checksum",$server,1);
 
#if(copy("hotfixes\\files\\$file","\\\\$server\\admin\$\\system32\\$file"))
{&LogPrint("Copied $file",$server,1)}
            #else {&ErrPrint("Could not copy $file",$server)}
          }
        }
        else {ErrPrint("Checkfile enabled but no type.. should never
happen",$server,2)}
      }
      else {
        LogPrint("Could not find $file",$server);
      }
    }
  }
  &InstallHotFix($server) if $fix;
}
if ($continue) {
  print "\n";
  goto START;
}

sub CopyHotFix {
  my $server=shift;
  my $hotfix=shift;
 
  if (not -e "\\\\$server\\c\$\\boot.ini") {
    &ErrPrint("Could not connect to share: $^E",$server,3,1);
  }
  if (not -e "\\\\$server\\admin\$\\hotfixes") {
    if (not mkdir("\\\\$server\\admin\$\\hotfixes",755)) {
      &ErrPrint("Could not make hotfix directory: $^E",$server,3);
    }
  }
  $hotfix=$hotfix . "i.exe";
  if (not -e "\\\\$server\\admin\$\\hotfixes\\$hotfix") {
    if (-e "hotfixes\\$hotfix") {
      copy("hotfixes\\$hotfix","\\\\$server\\admin\$\\hotfixes\\$hotfix") or
&ErrPrint("Could not copy $hotfix",$server,2);
      &LogPrint("Copied $hotfix",$server);
    }
    else {&ErrPrint("Could not find local hotfix $hotfix",$server,2)}
  }
  return 1;
}

sub InstallHotFix {
  my $server=shift;

  my $switch=0;

  if (-e "hotfix.cmd") {
    unlink "hotfix.cmd" or &ErrPrint("Could not unlink hotfix batch file:
$!",$server,3);
  }
  for my $hotfix (sort keys %$server) {
    if ($$server{$hotfix}) {
      #LogPrint("Needs $hotfix",$server,1);
      open(HF,">>hotfix$server.cmd") or &ErrPrint("Could not open hotfix
batch file: $!",$server,3);
      print HF "\%SYSTEMROOT\%\\hotfixes\\" . $hotfix . "i.exe -z -q -m\n";
      close HF;
      $switch=1;
      #die "check the batch";
    }
  }

  if (-e "hotfix.cmd") {
    copy("hotfix.cmd","\\\\$server\\admin\$\\hotfixes\\hotfix.cmd") or
&ErrPrint("Could not copy hotfix.cmd",$server,2);
    &LogPrint("Copied hotfix.cmd",$server);
    unlink "hotfix.cmd" or &ErrPrint("Could not unlink hotfix batch file:
$!",$server,3);
  }
  if ($switch) {
    my $timeat=&GetTime($server);
    my $atjobstr="at \\\\$server $timeat cmd /c
\^\%SYSTEMROOT\^\%\\hotfixes\\hotfix.cmd";
    LogPrint($atjobstr,$server);
    my $atjob=`$atjobstr`;
    if ($atjob=~/Added/) {LogPrint("atjob set at $timeat",$server,1)}
    else {print "failed\n"}
  }
}

sub GetTime {
  my $server=shift;

  my $timerem=`net time \\\\$server 2>&1`;
  if ($timerem=~/Current time at \\\\$server is \d+\/\d+\/\d+ ((\d+):(\d+))
(AM|PM)/) {
    $hour=$2;
    $min=$3;
    $ampm=$4;
  }

  $min++;
  $min++;

  if (($ampm eq 'PM') and ($hour < 12)) {$hour+=12;}

  if ($min > 59) {
    $min-=60;
    $hour++;
  }
  if ($hour > 23) {$hour-=24}

  if (length($min)==1) {$min="0".$min}

  my $attime="$hour:$min";

  return $attime;
}

sub GetDomain {
  my $server=shift;
  my $netdom=`netdom query \\\\$server 2>&1`;
  if ($netdom=~/is a (member|domain controller) of (.*)\./) {
    $domain=$2;
  }
  else {print "Could not determine domain for $server\n"}
  return $domain;
}

sub ErrPrint {
  my $msg=shift;
  my $server=shift;
  my $errlvl=shift;
  my $quieterr=shift;

  if ($logtofile) {
   open (LOG, ">>$logfile") or die "Could not open $logfile for writing:
$!";
    print LOG "$server: $msg\n" unless $quieterr;
    close LOG;
  }
  print "$server: $msg\n" unless $quieterr;

  if ($errlvl==2) {
    next HOTFIX;
  }
  elsif ($errlvl==3) {
    next SERVER;
  }
  elsif ($errlvl==4) {
    exit(0);    
  }
 
}

sub GenerateEvent {
  my $msg=shift;
  my $server=shift;
  my $hf=shift;
  
  LogPrint("Generating an event for $server",$server);
 
  Win32::EventLog::Message::RegisterSource( 'System', 'HotFix
Checker',$server );

  $event = Win32::EventLog->new( 'HotFix Checker',$server ) or
&ErrPrint("Could not post error to event log",$server,2);

  $event->Report( 
    {
       EventID     => 70000,
       Strings     => "*** An important hotfix is missing from the server
($hf). *** Please install the hotfix as soon as possible. ***",
       EventType   => EVENTLOG_ERROR_TYPE,
    }
  );
}


sub LogPrint {
  my $msg=shift;
  my $server=shift;
  my $verby;

  if ($logtofile) {
    open (LOG, ">>$logfile") or die "Could not open $logfile for writing:
$!";
    print LOG "$server: $msg\n";
    close LOG;
  }
  print "$server: $msg\n";
}

sub Usage {
  print <<EOF;  
HFCheck version $vernum modified $verdate

Usage: hfcheck.pl <-l or -s> <options>

-l      Serverlist with on server per line
-s      Single Server (bare servername w/o the \\\\)
-fd     Checks file dates and sizes for hotfix files
-i      Installs any hotfixes that are not present
-td     Domain Controller Mode (doesn't do the IIS fixes
-tw     Web Server Mode (default)
-m      Show the actual missing hotfixes instead of the x/x
-c      Continuous Mode (for looping querys to see install progress
-q      Quiet Mode
-h      This crap

Without any options, hfcheck access the registry of the systems
in the list (specified by -l) and checks for installed hotfixes. By
adding the -fd option, hfcheck will compare file size/dates of all
related hotfix files (that are applicable).

The -i option automatically installs any required hotfixes not seen in the
registry.

Email bugs to cbell\@interland.com
EOF

  exit(0);
}



> -----Original Message-----
> From: David Rigaudiere [mailto:[EMAIL PROTECTED]]
> Sent: Friday, September 28, 2001 8:18 AM
> To: [EMAIL PROTECTED];
> [EMAIL PROTECTED]
> Subject: Re: Querying Service Pack
> 
> 
> > Has anyone found a way to tell if a server has SP6 or SP6a on it?
> 
> You could check the content of the following key.
> 
> [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows 
> NT\CurrentVersion\CSDVersion]
> 
> 
> Regards
> David
> 
> --
> David "Sniper" Rigaudiere
> http://paris.mongueurs.net               The Paris Perl Mongers
> http://www.perlmonks.org                 Join the Monastery
> http://sourceforge.net/projects/ncms     NCMS project manager
> 
> 
> 
> _______________________________________________
> Perl-Win32-Admin mailing list
> [EMAIL PROTECTED]
> http://listserv.ActiveState.com/mailman/listinfo/perl-win32-admin
> 
_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
http://listserv.ActiveState.com/mailman/listinfo/perl-win32-admin

Reply via email to