#  DisplayADSIObject.pl
#  Example 9.5:
#  ----------------------------------------
#  From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth
#  Published by New Riders Publishing.
#  ISBN # 1-57870-215-1
#
#  This script displays an ADSI path's object.  It also allows for filtering
#  and impersontation
#
print "From the book 'Win32 Perl Scripting: The Administrator's Handbook' by Dave Roth\n\n";


use Getopt::Long;
use Win32;
use Win32::OLE qw( in );
use Win32::OLE::Const 'Active DS Type Library';

$Config{path} = "WinNT://" . Win32::DomainName();
Configure( \%Config );
if( $Config{help} )
{
  Syntax();
  exit;
}
if( $AD = GetADSIObject( \%Config ) )
{
  my $iCount = 0;
  my $Schema = Win32::OLE->GetObject( $AD->{Schema} );

  # The schema object's Container property shows if we are a container.
  if( $Schema->{Container} )
  {
    if( scalar @{$Config{filter}} )
    {
      # Apply a filter
      $AD->{Filter} = $Config{filter} ;
    }
    print "This '$AD->{ADsPath}' $AD->{Class} object contains ";
    print "the following objects:\n";
    foreach my $Object ( in( $AD ) )
    {
      print ++$iCount . ") $Object->{Name} ($Object->{Class})\n";
    }
  }
  else
  {
    print "The '$AD->{ADsPath}' is a $AD->{Class} object.\n";
  }
}

sub GetADSIObject
{
  my( $Config ) = @_;
  my $ADSIObject;
  my $ADsPath = $Config->{path};

  if( defined $Config->{user} )
  {
    my( $ADProvider, $Path ) = ( $ADsPath =~ m#^([^/]*)(.*)# );
    
    if( my $AD = Win32::OLE->GetObject( $ADProvider ) )
    {
      if( ! ( $ADSIObject = $AD->OpenDSObject( $ADsPath, 
                           $Config->{user}, 
                           $Config->{password}, 
                           ADS_SECURE_AUTHENTICATION
                           | ADS_USE_ENCRYPTION 
                           | ADS_READONLY_SERVER ) ) )
      {
        print "Error:\n" . Win32::OLE->LastError();
      }
    }
  }
  else
  {
    $ADSIObject = Win32::OLE->GetObject( $ADsPath );
  }
  return( $ADSIObject );
}

sub Configure
{
  my( $Config ) = @_;
  my $Result;
  Getopt::Long::Configure( "prefix_pattern=(-|\/)" );
  $Result = GetOptions( $Config,
                        qw(
                          user|u=s
                          password|p=s
                          filter|f=s@
                          help|?|h
                        ) );
  $Config{path} = shift @ARGV if( scalar @ARGV );
  $Config{help} = 1 if( ! $Result );
  return();              
}

sub Syntax
{
  my( $Script ) = ( Win32::GetLongPathName( $0 ) =~ /([^\\]*?)$/ );
  my $Whitespace = " " x length( $Script );
  print<< "EOT";

Syntax:
  $Script [-f filter] [-u User] [-p Password] [ADSI Path] 
    -f Filter.......Name of an ADSI class to filter.  If any filters
                    are specified then only objects that are of the
                    specified filter types will be displayed.
                    This switch can be specified multiple times. 
    -u User.........Name of a user account to impersonate.
    -p Password.....Password of the specified user.
    ADSI Path.......This is the ADSI path to use.
                    Default is WinNT://DOMAIN
EOT
}

