use Net::Ping;
use Win32::Registry;
my $Host;
my $Subnet = shift @ARGV || ?192.168.1?; A
my $Host_Min = shift @ARGV || 0;
my $Host_Max = shift @ARGV || 255;
# Изменить массив @VALID_SHARES, указав в нем список B
# допустимых на машине нулевых ресурсов сеанса.
my @VALID_SHARES = qw(
  DFS$
  CHEYUPD$
  CHEYALERT$
  COMCFG
);
my $Ping_Timeout = 2;
my $PingObject = Net::Ping->new( ?icmp?, $Ping_Timeout ) || die; C
my $LogFile = $0; D
$LogFile =~ s/.[^.]*$/.log/;
if( open( LOG, ?> $LogFile? ) )
{
  my $BackupHandle = select( LOG );
  $| = 1;
  select( $BackupHandle );
}
# Отыскать все сетевые узлы. E
foreach my $Host ( $Host_Min .. $Host_Max )
{
  my $IP = ?$Subnet.$Host?;
  print ?Checking $IP...?;
  if( $PingObject->ping( $IP ) )
  {
    # В сети обнаружен узел; приступаем к обработке.
    print ?found?;
    ProcessHost( $IP );
  }
  else
  {
    print ?no node found.?;
  }
  print ?
?;
}
close( LOG ) if( fileno LOG );

sub ProcessHost
{
  my $Host = shift @_;
  my( $Root,  $MachineName, $MachineSpeed, $UserName,
    $NullSessionShares );

  # Попытка соединения с удаленной машиной.
  if( $HKEY_LOCAL_MACHINE->Connect( $Host, $Root ) )
  {
    my $Key;
     # Определить имя компьютера.
    if( $Root->Open( ?SYSTEMCurrentControlSetControlComputerName
      ComputerName?, $Key ) )
    {
      my $Type;
      $Key->QueryValueEx( ?ComputerName?, $Type, $MachineName );
      print ? \$MachineName ?;
      $Key->Close();
    }

    # Определить последнего зарегистрировавшегося пользователя.
    if( $Root->Open( ?SOFTWAREMicrosoftWindows NTCurrentVersion
      Winlogon?, $Key ) )
    {
      my $Type;
      $Key->QueryValueEx( ?DefaultUserName?, $Type, $UserName);
      print ? (Last User: $UserName) ?;
      $Key->Close();
    }

    # Определить приблизительную скорость процессора.
    if( $Root->Open( ?HARDWAREDESCRIPTIONSystem
      CentralProcessor?, $Key ) )
    {
      my $Type;
      $Key->QueryValueEx( ?~MHz?, $Type, $MachineSpeed );
      print ? (approx. $MachineSpeed MHz) ?;
      $Key->Close();
    }

    # Попытка открыть указанный раздел реестра.
    if( $Root->Open( ?SYSTEMCurrentControlSetServiceslanmanserver
      parameters?, $Key ) )
    {
       my $Type;
       if( $Key->QueryValueEx( ?NullSessionShares?, $Type, F
        $NullSessionShares ) )
      {
        my( @AllowedList, @DeniedList );
        foreach my $ShareName ( split( //, $NullSessionShares ) ) G
        {
          if( IsShareAllowed( $ShareName ) ) H
          {
            push( @AllowedList, $ShareName );
          }
          else
          {
            push( @DeniedList, $ShareName );
          }
        }
        # Если обнаружены неразрешенные ресурсы,
        # выполняем необходимые операции.
        if( scalar @DeniedList )
        {
          print ?
	Null shares not allowed:
		?? .
            join( ??
		??, @DeniedList ) . ??
?;
          # Удаление символа комментария из следующей строки приведет
            # к изменению реестра. Поэтому прежде, чем удалять символ
            # комментария, следует тщательно все продумать.
          # $Key->SetValueEx( ?NullSessionShares?, 0, REG_MULTI_SZ,
          # join( ??, @AllowedList ) );
        }
      }
      $Key->Close();
    }
    $Root->Close();
  }
  else
  {
    print ? Registry service is not enabled.?; I
  }
  printf( LOG ?%s	%s	%s	%s	%s
?,
          $Host,
          $UserName,
          $MachineName,
          $MachineSpeed,
          $NullSessionShares ) if( fileno LOG );
}

sub IsShareAllowed
{
  my( $ShareName ) = @_;
  foreach my $ValidShare ( @VALID_SHARES )
  {
    return( 1 ) if( lc $ValidShare eq lc $ShareName );
  }
  return( 0 );
}