1package FusionInventory::Agent::Task::Inventory::Win32::CPU; 2 3use strict; 4use warnings; 5 6use parent 'FusionInventory::Agent::Task::Inventory::Module'; 7 8use English qw(-no_match_vars); 9use Win32; 10 11use FusionInventory::Agent::Tools; 12use FusionInventory::Agent::Tools::Win32; 13use FusionInventory::Agent::Tools::Generic; 14 15sub isEnabled { 16 my (%params) = @_; 17 return 0 if $params{no_category}->{cpu}; 18 return 1; 19} 20 21sub isEnabledForRemote { 22 my (%params) = @_; 23 return 0 if $params{no_category}->{cpu}; 24 return 1; 25} 26 27sub doInventory { 28 my (%params) = @_; 29 30 my $inventory = $params{inventory}; 31 32 my @cpus = _getCPUs(%params); 33 34 foreach my $cpu (@cpus) { 35 $inventory->addEntry( 36 section => 'CPUS', 37 entry => $cpu 38 ); 39 } 40 41 if (any { $_->{NAME} =~ /QEMU/i } @cpus) { 42 $inventory->setHardware ({ 43 VMSYSTEM => 'QEMU' 44 }); 45 } 46} 47 48sub _getCPUs { 49 my (%params) = @_; 50 51 my $remotewmi = $params{inventory}->getRemote(); 52 53 my @dmidecodeInfos = $remotewmi || Win32::GetOSName() eq 'Win2003' ? 54 () : getCpusFromDmidecode(); 55 56 # the CPU description in WMI is false, we use the registry instead 57 my $registryInfos = getRegistryKey( 58 path => "HKEY_LOCAL_MACHINE/Hardware/Description/System/CentralProcessor", 59 wmiopts => { # Only used for remote WMI optimization 60 values => [ qw/Identifier ProcessorNameString VendorIdentifier/ ] 61 } 62 ); 63 64 my $cpuId = 0; 65 my @cpus; 66 67 foreach my $object (getWMIObjects( 68 class => 'Win32_Processor', 69 properties => [ qw/ 70 NumberOfCores NumberOfLogicalProcessors ProcessorId MaxClockSpeed 71 SerialNumber Name Description Manufacturer 72 / ] 73 )) { 74 75 my $dmidecodeInfo = $dmidecodeInfos[$cpuId]; 76 my $registryInfo = $registryInfos->{"$cpuId/"}; 77 78 # Compute WMI threads for this CPU if not available in dmidecode, this is the case on win2003r2 with 932370 hotfix applied (see #2894) 79 my $wmi_threads = !$dmidecodeInfo->{THREAD} && $object->{NumberOfCores} ? $object->{NumberOfLogicalProcessors}/$object->{NumberOfCores} : undef; 80 81 # Split CPUID from its value inside registry 82 my @splitted_identifier = split(/ |\n/, $registryInfo->{'/Identifier'} || $object->{Manufacturer}); 83 84 my $cpu = { 85 CORE => $dmidecodeInfo->{CORE} || $object->{NumberOfCores}, 86 THREAD => $dmidecodeInfo->{THREAD} || $wmi_threads, 87 DESCRIPTION => $registryInfo->{'/Identifier'} || $object->{Description}, 88 NAME => trimWhitespace($registryInfo->{'/ProcessorNameString'} || $object->{Name}), 89 MANUFACTURER => getCanonicalManufacturer($registryInfo->{'/VendorIdentifier'} || $object->{Manufacturer}), 90 SERIAL => $dmidecodeInfo->{SERIAL} || $object->{SerialNumber}, 91 SPEED => $dmidecodeInfo->{SPEED} || $object->{MaxClockSpeed}, 92 FAMILYNUMBER => $splitted_identifier[2], 93 MODEL => $splitted_identifier[4], 94 STEPPING => $splitted_identifier[6], 95 ID => $dmidecodeInfo->{ID} || $object->{ProcessorId} 96 }; 97 98 # Some information are missing on Win2000 99 if (!$cpu->{NAME} && !$remotewmi) { 100 $cpu->{NAME} = $ENV{PROCESSOR_IDENTIFIER}; 101 if ($cpu->{NAME} =~ s/,\s(\S+)$//) { 102 $cpu->{MANUFACTURER} = $1; 103 } 104 } 105 106 if ($cpu->{SERIAL}) { 107 $cpu->{SERIAL} =~ s/\s//g; 108 } 109 110 if (!$cpu->{SPEED} && $cpu->{NAME} =~ /([\d\.]+)s*(GHZ)/i) { 111 $cpu->{SPEED} = { 112 ghz => 1000, 113 mhz => 1, 114 }->{lc($2)} * $1; 115 } 116 117 # Support CORECOUNT total available cores 118 $cpu->{CORECOUNT} = $dmidecodeInfo->{CORECOUNT} 119 if ($dmidecodeInfo->{CORECOUNT}); 120 121 push @cpus, $cpu; 122 123 $cpuId++; 124 } 125 126 return @cpus; 127} 128 1291; 130