@@ -10,9 +10,11 @@ use windows::{
1010 core:: PSTR , Win32 :: System :: Power :: GetSystemPowerStatus ,
1111 Win32 :: System :: Power :: SYSTEM_POWER_STATUS ,
1212 Win32 :: System :: SystemInformation :: GetComputerNameExA ,
13+ Win32 :: System :: SystemInformation :: GetLogicalProcessorInformation ,
1314 Win32 :: System :: SystemInformation :: GetTickCount64 ,
1415 Win32 :: System :: SystemInformation :: GlobalMemoryStatusEx ,
1516 Win32 :: System :: SystemInformation :: MEMORYSTATUSEX ,
17+ Win32 :: System :: SystemInformation :: RelationProcessorCore ,
1618 Win32 :: System :: WindowsProgramming :: GetUserNameA ,
1719} ;
1820
@@ -295,11 +297,76 @@ impl GeneralReadout for WindowsGeneralReadout {
295297 }
296298
297299 fn cpu_physical_cores ( & self ) -> Result < usize , ReadoutError > {
298- Err ( ReadoutError :: NotImplemented )
300+ // Source: https://github.com/seanmonstar/num_cpus/blob/master/src/lib.rs#L129
301+ #[ allow( non_camel_case_types, dead_code) ]
302+ struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
303+ mask : usize ,
304+ relationship : u32 ,
305+ _unused : [ u64 ; 2 ]
306+ }
307+
308+ // The required size of the buffer, in bytes
309+ let mut needed_size = 0 ;
310+
311+ // Get the required size of the buffer
312+ unsafe {
313+ GetLogicalProcessorInformation ( std:: ptr:: null_mut ( ) , & mut needed_size) ;
314+ }
315+
316+ let struct_size = std:: mem:: size_of :: < SYSTEM_LOGICAL_PROCESSOR_INFORMATION > ( ) as u32 ;
317+
318+ // Could be 0, or some other bogus size
319+ if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
320+ return Err ( ReadoutError :: Other (
321+ "Call to \" GetLogicalProcessorInformation\" returned an invalid size." . to_string ( )
322+ ) ) ;
323+ }
324+
325+ let count = needed_size / struct_size;
326+
327+ // Allocate some memory where we will store the processor info
328+ let mut buf = Vec :: with_capacity ( count as usize ) ;
329+
330+ let result;
331+
332+ // Populate the buffer with processor information
333+ unsafe {
334+ result = GetLogicalProcessorInformation ( buf. as_mut_ptr ( ) , & mut needed_size) ;
335+ }
336+
337+ // If failed for some reason
338+ if result. as_bool ( ) == false {
339+ return Err ( ReadoutError :: Other (
340+ "Call to \" GetLogicalProcessorInformation\" failed." . to_string ( )
341+ ) ) ?;
342+ }
343+
344+ // Number of logical processor entries
345+ let count = needed_size / struct_size;
346+
347+ unsafe {
348+ buf. set_len ( count as usize ) ;
349+ }
350+
351+ let phys_proc_count = buf. iter ( )
352+ // Only interested in processor packages (physical processors.)
353+ . filter ( |proc_info| proc_info. Relationship == RelationProcessorCore )
354+ . count ( ) ;
355+
356+ return if phys_proc_count == 0 {
357+ Err ( ReadoutError :: Other (
358+ "No physical processor cores found." . to_string ( )
359+ ) ) ?
360+ } else {
361+ Ok ( phys_proc_count)
362+ }
299363 }
300364
301365 fn cpu_cores ( & self ) -> Result < usize , ReadoutError > {
302- Err ( ReadoutError :: NotImplemented )
366+ // Open the registry key containing the CPUs information.
367+ let cpu_info = RegKey :: predef ( HKEY_LOCAL_MACHINE ) . open_subkey ( "HARDWARE\\ DESCRIPTION\\ System\\ CentralProcessor" ) ?;
368+ // Count the number of subkeys, which is the number of CPU logical processors.
369+ Ok ( cpu_info. enum_keys ( ) . count ( ) )
303370 }
304371
305372 fn uptime ( & self ) -> Result < usize , ReadoutError > {
0 commit comments