#  98_Processes.pl
#  Example: 7.16a
#  ----------------------------------------
#  From "Win32 Perl Scripting: Administrators Handbook" by Dave Roth
#  Published by New Riders Publishing.
#  ISBN # 1-57870-215-1
#
#  This script demonstrates how to procure the process list on a Windows 95
#  or Windows 98 machine.

use Win32::API;

$TH32CS_SNAPPROCESS = 0x00000002;
$TH32CS_SNAPMODULE  = 0x00000008;
$szExeFileSize = 260 * ( 1 + Win32::API::IsUnicode() );
%STRUCT = (
    processentry32  =>  "L3LL3lLA$szExeFileSize"
);

$Snapshot = new Win32::API( 'kernel32.dll', 'CreateToolhelp32Snapshot', [N,N], N ) || die;
$CloseHandle = new Win32::API( 'kernel32.dll', 'CloseHandle', [N], I ) || die;
$Process32First = new Win32::API( 'kernel32.dll', 'Process32First', [N,P], I ) || die;
$Process32Next = new Win32::API( 'kernel32.dll', 'Process32Next', [N,P], I ) || die;

$~ = PROCESS_HEADER;
write();

if( $hSnapshot = $Snapshot->Call( $TH32CS_SNAPPROCESS, 0 ) )
{
    my $Process = pack( $STRUCT{processentry32} );
    my $Size = length( $Process );
    $Process = pack( $STRUCT{processentry32}, $Size );

    if( $Process32First->Call( $hSnapshot, $Process ) )
    {
        $~ = PROCESS_INFO;
        do
        {
            my( @ProcData ) = unpack( $STRUCT{processentry32}, $Process );
            my $iIndex = 0;
            $Proc = {};
            $Proc->{size}                   = $ProcData[$iIndex++];
            $Proc->{usage}                  = $ProcData[$iIndex++];
            $Proc->{'ID Process'}           = $ProcData[$iIndex++];
            $Proc->{hid}                    = $ProcData[$iIndex++];
            $Proc->{mid}                    = $ProcData[$iIndex++];
            $Proc->{'Thread Count'}         = $ProcData[$iIndex++];
            $Proc->{'Creating Process ID'}  = $ProcData[$iIndex++];
            $Proc->{prioritybase}           = $ProcData[$iIndex++];
            $Proc->{flags}                  = $ProcData[$iIndex++];
            $Proc->{Name}                   = FixString( $ProcData[$iIndex++] );
            write;
            $Process = pack( $STRUCT{processentry32}, $Size );
        }
        while( $Process32Next->Call( $hSnapshot, $Process ) );
    }
    $CloseHandle->Call( $hSnapshot );
}

sub FixString
{
    my( $String ) = @_;
    $String =~ s/\x00//gs;
    return( $String );
}

format PROCESS_HEADER =
@||| @||||| @|||||||||||||||| @||||||
PID, Parent, "Process Name", "Threads"
---- ------ ----------------- -------
.

format PROCESS_INFO =
@||| @||||| @<<<<<<<<<<<<<<<< @>>>>>>
$Proc->{'ID Process'}, $Proc->{'Creating Process ID'}, $Proc->{Name}, $Proc->{'Thread Count'}
.
