Monday: 00-23
Tuesday: 00-23
Wednesday: 00-23
Thursday: 00-23
Friday: 00-23
Saturday: 00-23
if( ApiLink( 'kernel32.dll',
'DWORD GetTimeZoneInformation( PVOID pTZInfo )' ) )
{
my $pTZInfo = NewString( 200 );
my $Result = GetTimeZoneInformation( $pTZInfo );
if( 0 == $Result || 2 == $Result )
{
$TZOffset = unpack( "l", $pTZInfo ) / 60;
}
}
# Determine which hours on what days of the week this user has
# permission to logon
my $DayIndex = 0;
my $BinaryHours = $Value;
my $HourString = unpack( "b*", $BinaryHours );
$Value = "";
# We need to offset the logon hours string by the number
# of hours we are either before or after GMT.
if( 0 > $TZOffset )
{
$TZOffset *= -1;
$HourString =~ s/^(.*)(.{$TZOffset})$/$2$1/;
}
else
{
$HourString =~ s/^(.{$TZOffset})(.*)$/$2$1/;
}
# hours the user is allowed to log on.
foreach my $Day ( $HourString =~ /.{24}/g )
{
my @Hours;
my $Display = "";
my $Index = 0;
$Day .= "0";
foreach my $HourValue ( split( "", $Day ) )
{
if( $HourValue )
{
if( "" eq $Display )
{
$Display = sprintf( "%02d", $Index );
}
}
else
{
if( "" ne $Display )
{
if( $Display < $Index - 1 )
{
$Display .= sprintf( "-%02d", $Index - 1 );
}
push( @Hours, $Display );
$Display = "";
}
}
$Index++;
}
$Value .= sprintf( "%- 50s", "$WEEKDAYS[$DayIndex++]: "
. join( ",", @Hours ) ), "\n";
}
}
-----Original Message-----
From: DePriest, Jason R. [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, December 24, 2002 1:23 PM
To: 'Steven Manross'; Perl-Win32-Admin ([EMAIL PROTECTED])
Subject: RE: Win32::AdminMisc - user flag USER_LOGON_HOURSThanks, Steven.
That helped me pull the data out to be a reasonable value (i.e. 21-bytes instead of 1-byte). I had glanced at the pack/unpack functions but didn't actually try to use them.
However, I am trying to use the UserGetMiscAttributes module instead of the UserSetMiscAttributes module.
From your example, I think I'll still have to create a huge switch statement to get the 1's and 0's into text strings.-----Original Message-----
From: Steven Manross [mailto:[EMAIL PROTECTED]]
Sent: Tuesday, December 24, 2002 3:04 PM
To: 'DePriest, Jason R.'; Perl-Win32-Admin ([EMAIL PROTECTED])
Subject: RE: Win32::AdminMisc - user flag USER_LOGON_HOURS
I don't know why but contrary to Dave's belief, I had to set this up
this way to make it work, where the first line is the last few hours on
Sunday and then the next lines are Monday, Tuesday, etc...%Logon_Hours = ('special' =>
[(1,0,0,0,0,0,0,
0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,
0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,
)],
'normal' =>
[(1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
)],
);
my $packed_hours = pack ( 'b*' ,
join('',@{$Logon_Hours{$hours_identifier}}) ) ;
if (Win32::AdminMisc::UserSetMiscAttributes ($pdc, $username,
USER_LOGON_HOURS =>
$packed_hours )) {
print " Succeeded setting Logon Hours for $username!\n";
} else {
print " Failed setting Logon Hours for $username!\nERROR:
",Win32::GetLastError(),"\n";
}Steven
-----Original Message-----
From: DePriest, Jason R. [ mailto:[EMAIL PROTECTED]]
Sent: Tuesday, December 24, 2002 1:55 PM
To: Perl-Win32-Admin ([EMAIL PROTECTED])
Subject: Win32::AdminMisc - user flag USER_LOGON_HOURS
Dave Roth's documentation and website say this value points to a 21-byte
(168-bit) binary string in which each bit represents one hour of the
week.Has anyone bothered to parse this flag out into english? The only way I
can think of is to write a pseudo-switch statement with a 168 'if'
statements that push the results into an array.Plus, if I 'ord' the value from the flag (and no restrictions are set),
I get 255 and not 2E+167.
Thank you!
Jason R DePriest
# DumpAccount.pl # Example 2.2: # ---------------------------------------- # From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth # Published by New Riders Publishing. # ISBN # 1-57870-215-1 # print "From the book 'Win32 Perl Scripting: The Administrator's Handbook' by Dave Roth\n\n";
use Win32; use Getopt::Long; use Win32::NetAdmin; use Win32::AdminMisc; use Win32::API::Prototype; %FLAGS = ( eval UF_TEMP_DUPLICATE_ACCOUNT => "UF_TEMP_DUPLICATE_ACCOUNT", eval UF_NORMAL_ACCOUNT => "UF_NORMAL_ACCOUNT", eval UF_INTERDOMAIN_TRUST_ACCOUNT => "UF_INTERDOMAIN_TRUST_ACCOUNT", eval UF_WORKSTATION_TRUST_ACCOUNT => "UF_WORKSTATION_TRUST_ACCOUNT", eval UF_SERVER_TRUST_ACCOUNT => "UF_SERVER_TRUST_ACCOUNT", eval UF_DONT_EXPIRE_PASSWD => "UF_DONT_EXPIRE_PASSWD", eval UF_SETTABLE_BITS => "UF_SETTABLE_BITS", eval UF_SCRIPT => "UF_SCRIPT", eval UF_ACCOUNTDISABLE => "UF_ACCOUNTDISABLE", eval UF_HOMEDIR_REQUIRED => "UF_HOMEDIR_REQUIRED", eval UF_LOCKOUT => "UF_LOCKOUT", eval UF_PASSWD_NOTREQD => "UF_PASSWD_NOTREQD", eval UF_PASSWD_CANT_CHANGE => "UF_PASSWD_CANT_CHANGE", ); %AUTH_FLAGS = ( eval AF_OP_PRINT => "AF_OP_PRINT", eval AF_OP_COMM => "AF_OP_COMM", eval AF_OP_SERVER => "AF_OP_SERVER", eval AF_OP_ACCOUNTS => "AF_OP_ACCOUNTS", ); %PRIVILEGES = ( eval USER_PRIV_GUEST => "USER_PRIV_GUEST", eval USER_PRIV_USER => "USER_PRIV_USER", eval USER_PRIV_ADMIN => "USER_PRIV_ADMIN", ); @WEEKDAYS = qw( Sunday Monday Tuesday Wednesday Thursday Friday Saturday ); # Vicious hack to get the time zone if( ApiLink( 'kernel32.dll', 'DWORD GetTimeZoneInformation( PVOID pTZInfo )' ) ) { my $pTZInfo = NewString( 200 ); my $Result = GetTimeZoneInformation( $pTZInfo ); if( 0 == $Result || 2 == $Result ) { $TZOffset = unpack( "l", $pTZInfo ) / 60; } } Configure( \%Config ); if( $Config{help} ) { Syntax(); exit(); } if( "" ne $Config{domain} ) { # Find the primary domain controller for the specified domain. $Config{machine} = ""; Win32::NetAdmin::GetDomainController( '', $Config{domain}, $Config{machine} ); } elsif( "" eq $Config{machine} ) { # Find the primary domain controller for the current domain. $Config{machine} = ""; Win32::NetAdmin::GetDomainController( '', Win32::DomainName(), $Config{machine} ); } # Expand any user account wildcards foreach my $Account ( @{$Config{accounts}} ) { if( $Account =~ /\*$/ ) { my( $Prefix ) = ( $Account =~ /^(.*)\*$/ ); my @Users; Win32::AdminMisc::GetUsers( $Config{machine}, $Prefix, \@Users ); push( @AccountList, @Users ); } else { push( @AccountList, $Account ); } } $~ = Attributes; foreach my $Account ( sort( @AccountList ) ) { my %Info; print "Displaying $Config{machine}\\$Account:\n"; if( Win32::AdminMisc::UserGetMiscAttributes( $Config{machine}, $Account, \%Info ) ) { foreach $Key ( sort( keys( %Info ) ) ) { $Value = $Info{$Key}; ( $DisplayKey ) = ( ( lc $Key ) =~ /^.*?_(.*)/i ); $DisplayKey =~ s/_/ /g; if( $Key =~ /_age/i ) { # Break apart the C timestamp into years, days, # hours and minutes # There are 31536000 seconds in a year... # There are 86400 seconds in a day... # There are 3600 seconds in an hour... # And of course 60 seconds in a minute. my $Time = $Info{$Key}; my $Years = int( $Time / 31536000 ); my $Days = int( ( $Time % 31536000 ) / 86400 ); my $Hours = int( ( ( $Time % 31536000 ) % 86400 ) / 3600 ); my $Minutes = int( ( ( ( $Time % 31536000 ) % 86400 ) % 3600 ) / 60 ); $Value = sprintf( "%01d Years %02d Days %02d Hours %02d Minutes", $Years, $Days, $Hours, $Minutes ); } elsif( $Key =~ /LAST/i || $Key =~ /ACCT_EXPIRES/i ) { if( 1 > $Value ) { $Value = "No date specified"; } else { $Value = scalar localtime( $Info{$Key} ); } } elsif( $Key =~ /AUTH_FLAGS/i ) { # Break apart the flags attribute into individual flag strings $Value = DecodeBits( $Value, \%AUTH_FLAGS ); } elsif( $Key =~ /FLAGS/i ) { # Break apart the flags attribute into individual flag strings $Value = DecodeBits( $Value, \%FLAGS ); } elsif( $Key =~ /PASSWORD$/i ) { $Value = "<Unknown>"; } elsif( $Key =~ /PRIV$/i ) { $Value = $PRIVILEGES{$Value}; } elsif( $Key =~ /MAX_STORAGE$/i ) { if( -1 == $Value ) { $Value = "Unlimited storage"; } else { # Format the number to include commas as in 123,456,789 while( $Value =~ s/^(-?\d+)(\d{3})/$1,$2/ ){}; $Value .= " bytes"; } } elsif( $Key =~ /LOGON_HOURS/i ) { # Determine which hours on what days of the week this user has # permission to logon my $DayIndex = 0; my $BinaryHours = $Value; my $HourString = unpack( "b*", $BinaryHours ); $Value = ""; # We need to offset the logon hours string by the number # of hours we are either before or after GMT. if( 0 > $TZOffset ) { $TZOffset *= -1; $HourString =~ s/^(.*)(.{$TZOffset})$/$2$1/; } else { $HourString =~ s/^(.{$TZOffset})(.*)$/$2$1/; } # Now walk through each day and determine what # hours the user is allowed to log on. foreach my $Day ( $HourString =~ /.{24}/g ) { my @Hours; my $Display = ""; my $Index = 0; $Day .= "0"; foreach my $HourValue ( split( "", $Day ) ) { if( $HourValue ) { if( "" eq $Display ) { $Display = sprintf( "%02d", $Index ); } } else { if( "" ne $Display ) { if( $Display < $Index - 1 ) { $Display .= sprintf( "-%02d", $Index - 1 ); } push( @Hours, $Display ); $Display = ""; } } $Index++; } $Value .= sprintf( "%- 50s", "$WEEKDAYS[$DayIndex++]: " . join( ",", @Hours ) ), "\n"; } } write; } } else { print "failure: "; print Win32::FormatMessage( Win32::AdminMisc::GetError() ); } print "\n"; } sub DecodeBits { my( $Bits, $FlagList ) = @_; my $Result = ""; foreach my $Flag ( keys( %{$FlagList} ) ) { # Add spaces so that the format breaks lines (formats will not # break lines on carriage returns) $Result .= $FlagList->{$Flag} . " " x 40 . "\n" if( $Bits & $Flag ); } return( $Result ); } 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 ) = ( Win32::GetLongPathName( $0 ) =~ /([^\\\/]*?)$/ ); my( $Line ) = "-" x length( $Script ); print <<EOT; $Script $Line Displays an account's configuration. Syntax: perl $Script [-d Domain | -m Machine] Account [Account2 ...] -m Machine..Specify a machine where the user account lives. -d Domain...Specify a domain where the user account lives. 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. If no domain or machine is specified then the current domain is used. EOT } format Attributes = @<<<<<<<<<<<<<<<< ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< "$DisplayKey:", $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value ~ ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Value .