The following code was extracted from my Members.pm module from my 2nd
book (http://www.roth.net/books/handbook/). It gets the user token from
the current or specified process and displays the groups that the token
is a member of.
You can pass in a list of PIDs or don't pass in anything (which will
then use the default process which is the perl.exe running the script).
It is neat to try passing in the PID of a service. :)
use Win32::NetAdmin;
use Win32::API;
print "From the book 'Win32 Perl Scripting: The Administrator's
Handbook' by Dave Roth\n\n";
$VERSION = 1.0;
$PROCESS_QUERY_INFORMATION = 0x0400;
$TOKEN_QUERY = 0x0008;
$iTemp = 1;
$iResult = 1;
%TOKEN = (
user => $iTemp++,
groups => $iTemp++,
privileges => $iTemp++,
owner => $iTemp++,
primarygroup => $iTemp++,
defaultacl => $iTemp++,
source => $iTemp++,
type => $iTemp++,
impersonationlevel => $iTemp++,
statistics => $iTemp++,
restrictedsids => $iTemp++,
);
%TYPE = (
$Win32::NetAdmin::SidTypeUser => 'user',
$Win32::NetAdmin::SidTypeGroup => 'global group',
$Win32::NetAdmin::SidTypeDomain => 'domain',
$Win32::NetAdmin::SidTypeAlias => 'local group',
$Win32::NetAdmin::SidTypeWellKnownGroup => 'system group',
$Win32::NetAdmin::SidTypeDeletedAccount => 'deleted account',
$Win32::NetAdmin::SidTypeInvalid => 'invalid or corrupt
account',
$Win32::NetAdmin::SidTypeUnknown => 'unknown type of
account',
);
$iResult = 0 unless( $OpenProcess = new Win32::API( "kernel32.dll",
"OpenProcess", [I,I,N], N ) );
$iResult = 0 unless( $GetCurrentProcess = new Win32::API(
"kernel32.dll", "GetCurrentProcess", [], N ) );
$iResult = 0 unless( $GetCurrentProcessId = new Win32::API(
"kernel32.dll", "GetCurrentProcessId", [], N ) );
$iResult = 0 unless( $OpenProcessToken = new Win32::API( "advapi32.dll",
"OpenProcessToken", [N,N,P], I ) );
$iResult = 0 unless( $GetTokenInformation = new Win32::API(
"advapi32.dll", "GetTokenInformation", [N,I,P,N,P], I ) );
$iResult = 0 unless( $LookupSid = new Win32::API( "advapi32.dll",
"LookupAccountSid", [P,N,P,P,P,P,P], I ) );
$iResult = 0 unless( $CloseHandle = new Win32::API( "kernel32.dll",
"CloseHandle", [N], I ) );
my @PidList = @ARGV || (undef);
foreach my $Pid ( @PidList )
{
print "PID: $Pid\n";
foreach my $Group ( Get( $Pid ) )
{
print "\t-$Group->{domain}\\$Group->{group}
($TYPE{$Group->{type}})\n";
}
}
sub Get
{
my $Pid;
my @Groups;
my $hProcess;
if( ! defined $Pid )
{
$Pid = $GetCurrentProcessId->Call();
}
$hProcess = $OpenProcess->Call( $PROCESS_QUERY_INFORMATION, 0, $Pid
);
if( $hProcess )
{
my $pHandle = pack( "L", 0 );
if( $OpenProcessToken->Call( $hProcess, $TOKEN_QUERY, $pHandle )
)
{
my $hToken = unpack( "L", $pHandle );
my $pdwBuffer = pack( "L", 0 );
my $pBuffer;
my $dwSize;
# First we need to determine how big of a buffer we need...
$GetTokenInformation->Call( $hToken, $TOKEN{groups}, 0, 0,
$pdwBuffer );
$dwSize = unpack( "L", $pdwBuffer );
$pBuffer = "\x00" x $dwSize;
if( $GetTokenInformation->Call( $hToken, $TOKEN{groups},
$pBuffer, $dwSize, $pdwBuffer ) )
{
my( $GroupCount, $Data ) = unpack( "La*", $pBuffer );
my @Sids;
do
{
my( $pSid, $dwAttributes );
( $pSid, $dwAttributes, $Data ) = unpack( "LLa*",
$Data );
push( @Sids, $pSid );
} while( --$GroupCount && ( 0 < length( $Data ) ) );
foreach my $pSid ( reverse( @Sids ) )
{
my( $StringSize ) = 512;
my( $szGroup, $szDomain ) = ( "\x00" x $StringSize,
"\x00" x $StringSize );
my( $szMachine ) = Win32::NodeName() . "\x00" x 4;
my( $sSidType ) = pack( "s", 0 );
my( $dwNameSize, $dwDomainSize ) = ( pack( "L",
$StringSize ), pack( "L", $StringSize ) );
if( $LookupSid->Call( $szMachine, $pSid, $szGroup,
$dwNameSize, $szDomain, $dwDomainSize, $sSidType ) )
{
TrimString( \$szDomain );
TrimString( \$szGroup );
$SidType = unpack( "s", $sSidType );
push( @Groups, { 'domain' => $szDomain, 'group'
=> $szGroup, 'type' => $SidType } );
}
}
$CloseHandle->Call( $hToken );
}
$CloseHandle->Call( $hToken );
}
$CloseHandle->Call( $hProcess );
}
return( @Groups );
}
sub TrimString
{
my( $StringRef ) = @_;
$$StringRef =~ s/\x00//g;
}
-----Original Message-----
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of
MJG
Sent: Thursday, August 12, 2004 5:32 PM
To: [EMAIL PROTECTED]
Subject: Perl Vs Kix
This is probably more of a question for Activestate....Although I prefer
Perl over doing anything in Kix, there is one thing I can't find about
Perl. Kix has the ability to use the token from a user's Active
Directory Logon. This is useful because it can be used to check a group
membership of a user and so on. Does Perl have this ability or does ADO
and ADSI or even WMI the only way to collect this information?
Thanks
MG
_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs
_______________________________________________
Perl-Win32-Admin mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs