winupd/sysinfo.pm

322 lines
9.2 KiB
Perl

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;