From eff4f2822d570fb7354fee12f1a09fbc0c0bfcc0 Mon Sep 17 00:00:00 2001 From: Valko Laszlo Date: Tue, 16 Jan 2018 07:20:22 +0100 Subject: [PATCH] Added sysinfo module. --- sysinfo.pm | 321 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 321 insertions(+) create mode 100644 sysinfo.pm diff --git a/sysinfo.pm b/sysinfo.pm new file mode 100644 index 0000000..5dc209c --- /dev/null +++ b/sysinfo.pm @@ -0,0 +1,321 @@ +package sysinfo; + +use strict; + +require Exporter; +@sysinfo::ISA = qw(Exporter); +@sysinfo::EXPORT = qw( + read_cpus + get_os_data + get_system_info + get_memory_status + get_wbem_info + get_install_info + get_sysinfo + print_sysinfo +); + +use POSIX qw(strftime); +use Win32; +use Win32::OLE qw(in); +use Win32::API; +use Win32::TieRegistry; + +$Registry->Delimiter('/'); +$Registry->ArrayValues(1); + +use constant wbemFlagReturnImmediately => 0x10; +use constant wbemFlagForwardOnly => 0x20; + +my $PROCESSOR_ARCHITECTURE = { + 0 => 'x86', + 1 => 'MIPS', + 2 => 'Alpha', + 3 => 'PPC', + 5 => 'ARM', + 6 => 'IA64', + 9 => 'x64' +}; + +sub get_value ($) +{ + my ($node) = @_; + + my $value = $$node[0]; + return undef unless defined $value; + my $type = $$node[1]; + if ($type == 4 && $value =~ /^0x[0-9a-f]+$/oi) { + # REG_DWORD + return hex($value); + } + return $value; +} + +sub defines () +{ + Win32::API::Struct->typedef( + SYSTEM_INFO => qw { + WORD wProcessorArchitecture; + WORD wReserved; + DWORD dwPageSize; + UINT_PTR lpMinimumApplicationAddress; + UINT_PTR lpMaximumApplicationAddress; + LPDWORD dwActiveProcessorMask; + DWORD dwNumberOfProcessors; + DWORD dwProcessorType; + DWORD dwAllocationGranularity; + WORD wProcessorLevel; + WORD wProcessorRevision; + } + ); + Win32::API::Struct->typedef( + MEMORYSTATUSEX => qw { + DWORD dwLength; + DWORD MemLoad; + DWORD TotalPhysLo; + DWORD TotalPhysHi; + DWORD AvailPhysLo; + DWORD AvailPhysHi; + DWORD TotalPageFileLo; + DWORD TotalPageFileHi; + DWORD AvailPageFileLo; + DWORD AvailPageFileHi; + DWORD TotalVirtualLo; + DWORD TotalVirtualHi; + DWORD AvailVirtualLo; + DWORD AvailVirtualHi; + DWORD AvailExtendedVirtualLo; + DWORD AvailExtendedVirtualHi; + } + ); + Win32::API->Import('kernel32', 'VOID GetSystemInfo(LPSYSTEM_INFO lpSystemInfo)') || + die "Could not locate kernel32.dll - cannot call GetSystemInfo()\n"; + Win32::API->Import('kernel32', 'BOOL GlobalMemoryStatusEx(LPMEMORYSTATUSEX lpMemoryStatus)') || + die "Could not locate kernel32.dll - cannot call GlobalMemoryStatusEx()\n"; +} + +sub get_system_info () +{ + my $si = Win32::API::Struct->new('SYSTEM_INFO'); + $si->align('0'); + $si->{'wProcessorArchitecture'} = 0; + $si->{'wReserved'} = 0; + $si->{'dwPageSize'} = 0; + $si->{'lpMinimumApplicationAddress'} = 0; + $si->{'lpMaximumApplicationAddress'} = 0; + $si->{'dwActiveProcessorMask'} = 0; + $si->{'dwNumberOfProcessors'} = 0; + $si->{'dwProcessorType'} = 0; + $si->{'dwAllocationGranularity'} = 0; + $si->{'wProcessorLevel'} = 0; + $si->{'wProcessorRevision'} = 0; + GetSystemInfo($si); + my $arch = $si->{'wProcessorArchitecture'}; + if (! defined $arch) { + $arch = 'Unknown'; + } + elsif (! defined $$PROCESSOR_ARCHITECTURE{$arch}) { + $arch = 'Unknown'; + } + else { + $arch = $$PROCESSOR_ARCHITECTURE{$arch}; + } + return { + ProcArch => $arch + }; +} + +sub get_memory_status () +{ + my $ms = Win32::API::Struct->new('MEMORYSTATUSEX'); + $ms->align('auto'); + $ms->{'dwLength'} = $ms->sizeof(); + $ms->{'MemLoad'} = 0; + $ms->{'TotalPhysLo'} = 0; + $ms->{'TotalPhysHi'} = 0; + $ms->{'AvailPhysLo'} = 0; + $ms->{'AvailPhysHi'} = 0; + $ms->{'TotalPageFileLo'} = 0; + $ms->{'TotalPageFileHi'} = 0; + $ms->{'AvailPageFileLo'} = 0; + $ms->{'AvailPageFileHi'} = 0; + $ms->{'TotalVirtualLo'} = 0; + $ms->{'TotalVirtualHi'} = 0; + $ms->{'AvailVirtualLo'} = 0; + $ms->{'AvailVirtualHi'} = 0; + $ms->{'AvailExtendedVirtualLo'} = 0; + $ms->{'AvailExtendedVirtualHi'} = 0; + GlobalMemoryStatusEx($ms); + return undef if $ms->{dwLength} == 0; + my $memory = {}; + if (defined $ms->{'TotalPhysLo'} && defined $ms->{'TotalPhysHi'}) { + $$memory{TotalPhysMB} = $ms->{'TotalPhysHi'} * 4096 + + int(($ms->{'TotalPhysLo'} + 1048575) / 1048576); + } + if (defined $ms->{'TotalPageFileLo'} && defined $ms->{'TotalPageFileHi'}) { + $$memory{TotalPageFileMB} = $ms->{'TotalPageFileHi'} * 4096 + + int(($ms->{'TotalPageFileLo'} + 1048575) / 1048576); + } + return $memory; +} + +sub get_nodename () +{ + return Win32::NodeName(); +} + +sub get_os_data () +{ + my $guid = $Registry->{'HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Cryptography/MachineGuid'}; + die 'Cannot find HKLM\\SOFTWARE\\Microsoft\\Cryptography\\MachineGuid' unless defined $guid; + my $nodename = get_nodename(); + my $domainname = Win32::DomainName(); + my $osdispname = Win32::GetOSDisplayName(); + my $osname = Win32::GetOSName(); + my ($osver, $osmajor, $osminor, $osbuild) = Win32::GetOSVersion(); + my $loginname = Win32::LoginName(); + return { + MachineGuid => get_value($guid), + NodeName => $nodename, + DomainName => $domainname, + LoginName => $loginname, + OSDisplayName => $osdispname, + OSName => $osname, + OSVersion => $osver, + OSMajor => $osmajor, + OSMinor => $osminor, + OSBuild => $osbuild + }; +} + +sub read_cpus () +{ + my $cpus = []; + my $cpu = $Registry->{'HKEY_LOCAL_MACHINE/HARDWARE/Description/System/CentralProcessor'}; + die 'Cannot find HKLM\\HARDWARE\\Description\\System\\CentralProcessor' unless defined $cpu; + foreach my $name ($cpu->SubKeyNames) { + my $sub = $cpu->{$name}; + next unless defined $sub; + my $mhz = get_value($sub->{'~MHz'}); + my $vendor = get_value($sub->{'VendorIdentifier'}); + my $ident = get_value($sub->{'Identifier'}); + my $procname = get_value($sub->{'ProcessorNameString'}); + $procname =~ s/^ +//o; + $procname =~ s/ +$//o; + my $code; + if ($ident =~ /Family (\d+) Model (\d+) Stepping (\d+)/o) { + $code = $1.'.'.$2.'.'.$3; + } + push @$cpus, { + Id => $name, + MHz => $mhz, + Vendor => $vendor, + Identifier => $ident, + Code => $code, + Name => $procname + }; + } + return $cpus; +} + +sub get_wbem_info () +{ + my $nodename = get_nodename(); + my $wmiservice = Win32::OLE->GetObject('winmgmts:\\\\'.$nodename.'\\root\\CIMV2'); + die 'Cannot open WBEM interface' unless defined $wmiservice; + my $list = $wmiservice->ExecQuery('SELECT * FROM Win32_ComputerSystem', 'WQL', wbemFlagReturnImmediately | wbemFlagForwardOnly); + + my $wbem = {}; + foreach my $objitem (in $list) { + $$wbem{PartOfDomain} = $objitem->{'PartOfDomain'}; + $$wbem{Domain} = $objitem->{'Domain'}; + $$wbem{Workgroup} = $objitem->{'Workgroup'}; + $$wbem{Manufacturer} = $objitem->{'Manufacturer'}; + $$wbem{Model} = $objitem->{'Model'}; + } + return $wbem; +} + +sub get_install_info () +{ + my $sw = $Registry->{'HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion'}; + die 'Cannot find HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion' unless defined $sw; + + my $info = {}; + my $installdate = get_value($sw->{'InstallDate'}); + $$info{InstallDateNum} = $installdate; + $$info{InstallTime} = strftime('%Y-%m-%d %H:%M:%S', localtime($installdate)) if defined $installdate; + $$info{ProductId} = get_value($sw->{'ProductId'}); + $$info{ProductName} = get_value($sw->{'ProductName'}); + $$info{InstallationType} = get_value($sw->{'InstallationType'}); + $$info{EditionID} = get_value($sw->{'EditionID'}); + $$info{ReleaseId} = get_value($sw->{'ReleaseId'}); + $$info{CSDVersion} = get_value($sw->{'CSDVersion'}); + $$info{CurrentVersion} = get_value($sw->{'CurrentVersion'}); + return $info; +} + +sub get_sysinfo () +{ + return { + CPU => read_cpus(), + OS => get_os_data(), + System => get_system_info(), + Memory => get_memory_status(), + Install => get_install_info(), + WBEM => get_wbem_info() + }; +} + +sub print_sysinfo () +{ + my $sysinfo = get_sysinfo(); + + my $cpus = $$sysinfo{CPU}; + my $osdata = $$sysinfo{OS}; + my $systeminfo = $$sysinfo{System}; + my $memorystatus = $$sysinfo{Memory}; + my $install = $$sysinfo{Install}; + my $wbem = $$sysinfo{WBEM}; + + print 'NodeName='.$$osdata{NodeName}.', DomainName='.$$osdata{DomainName}.', LoginName='.$$osdata{LoginName}."\n"; + if (defined $$wbem{PartOfDomain}) { + print 'NodeStatus='.($$wbem{PartOfDomain} ? 'Domain' : 'Workgroup'). + ($$wbem{PartOfDomain} ? + (defined $$wbem{Domain} ? ', Domain='.$$wbem{Domain} : '') : + (defined $$wbem{Workgroup} ? ', Workgroup='.$$wbem{Workgroup} : '')). + "\n"; + } + print 'MachineGuid='.$$osdata{MachineGuid}."\n"; + if (defined $$wbem{Manufacturer}) { + print 'Manufacturer='.$$wbem{Manufacturer}; + print ', Model='.$$wbem{Model} if defined $$wbem{Model}; + print "\n"; + } + print 'NumProc='.scalar(@$cpus); + print ' TotalPhys='.$$memorystatus{TotalPhysMB}.' MB' if defined $$memorystatus{TotalPhysMB}; + print ' TotalPageFile='.$$memorystatus{TotalPageFileMB}.' MB' if defined $$memorystatus{TotalPageFileMB}; + print ' CPUArch='.$$systeminfo{ProcArch}."\n"; + print 'OSDisplayName='.$$osdata{OSDisplayName}.', OSName='.$$osdata{OSName}."\n"; + if (defined $$install{ProductName}) { + print 'OSProduct='.$$install{ProductName}; + print ' OSType='.$$install{InstallationType} if defined $$install{InstallationType}; + print ' OSEdition='.$$install{EditionID} if defined $$install{EditionID}; + print ' OSRelease='.$$install{ReleaseId} if defined $$install{ReleaseId}; + print "\n"; + } + print 'OSVersion='.$$install{CurrentVersion}.' ' if defined $$install{CurrentVersion}; + print 'OSMajor='.$$osdata{OSMajor}.' OSMinor='.$$osdata{OSMinor}.' OSBuild='.$$osdata{OSBuild}; + print ' SPVersion='.$$install{CSDVersion} if defined $$install{CSDVersion}; + print "\n"; + print 'ProductId='.$$install{ProductId}; + print ' Installed='.$$install{InstallTime} if defined $$install{InstallTime}; + print "\n"; + foreach my $cpu (@$cpus) { + print $$cpu{Id}.': '.$$cpu{MHz}.' MHz '.$$cpu{Name}.' CPUCode='.$$cpu{Code}."\n"; + } +} + +defines(); + +1;