#  UnLock.pl
#  Example 2.6:
#  ----------------------------------------
#  From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth
#  Published by New Riders Publishing.
#  ISBN # 1-57870-215-1
#
#  This script will unlock an account that has entered a locked state. This
#  typically occurs when a user attempts to logon using an invalid password
#  too many times.
#
#
print "From the book 'Win32 Perl Scripting: The Administrator's Handbook' by Dave Roth\n\n";


use Getopt::Long;
use Win32::NetAdmin;
use Win32::AdminMisc;
    
Configure( \%Config );
if( $Config{help} )
{
  Syntax();
  exit();
}

if( "" ne $Config{domain} )
{
  # Must first assign some value to the machine key otherwise
  # GetDomainController() will fail.
  $Config{machine} = "";
  Win32::NetAdmin::GetDomainController( '', 
                                        $Config{domain}, 
                                        $Config{machine} );
}
else
{
  if( "" eq $Config{machine} )
  {
    # Must first assign some value to the machine key otherwise
    # GetDomainController() will fail.
    $Config{machine} = "";
    Win32::NetAdmin::GetDomainController( '', 
                                          Win32::DomainName(), 
                                          $Config{machine} );
  }
}

foreach my $Account ( @{$Config{accounts}} )
{
  if( $Account =~ /\*$/ )
  {
    my( $Prefix ) = ( $Account =~ /^(.*)\*$/ );
    my @Users;
    Win32::AdminMisc::GetUsers( $Config{machine}, $Prefix, \@Users );
    map
    {
      $AccountList{lc $_} = 1;
    } ( @Users );
  }
  else
  {
    $AccountList{lc $Account} = 1;
  }
}

# Notice that we use a hash (%AccountList) to track the users we 
# are working on. This is a simple hack to prevent us from 
# processing the same user more than once (if the user passed
# in the same account name multiple times).
foreach my $Account ( keys( %AccountList ) )
{
  my %Attrib;
  print "$Config{machine}\\$Account ... ";
  if( Win32::AdminMisc::UserGetMiscAttributes( $Config{machine}, 
                                               $Account, 
                                               \%Attrib ) )
  {
    my $Flags = $Attrib{USER_FLAGS};
    if( $Flags & UF_LOCKOUT )
    {
      $Flags &= ~UF_LOCKOUT;
      if( Win32::AdminMisc::UserGetMiscAttributes( $Config{machine}, 
                                                   $Account, 
                                                   USER_FLAGS => $Flags ) )
      {
        print "success.";
      }
      else
      {
        print "failed: " . Error();
      }
    }
    else
    {
      print "not locked out.";
    }
  }
  else
  {
    print "can not query account: " . Error();
  }
  print "\n";
}

sub Error
{
    return( Win32::FormatMessage( Win32::AdminMisc::GetError() ) );
}

sub Configure
{
  my( $Config ) = @_;
  
  Getopt::Long::Configure( "prefix_pattern=(-|\/)" );
  $Result = GetOptions( $Config, 
                         qw(
                             machine|m=s
                             domain|d=s
                             help|?
                         )
                     );
  
  $Config->{help} = 1 if( ! $Result );
  if( "" ne $Config->{machine} )
  {
    $Config->{machine} = "\\\\$Config->{machine}";
    $Config->{machine} =~ s/^(\\\\)+/\\\\/;
  }
  push( @{$Config->{accounts}}, @ARGV );
  $Config->{help} = 1 if( ! scalar @{$Config->{accounts}} );
}

sub Syntax
{
    my( $Script ) = ( $0 =~ /([^\\\/]*?)$/ );
    my( $Line ) = "-" x length( $Script );

    print <<EOT;

$Script
$Line
Unlocks a locked account.

Syntax:
    perl $Script [-m Machine | -d Domain] Account [Account2 ...]
        -m Machine..Specify a machine the accounts live on.
        -d Domain...Specify the domain the accounts live in.
        Account.....The name of the account (the userid).
                    This account can end with a * char to indicate
                    all accounts that begin with the specified string.
EOT
}
