Jump to content

WINAPI GetLogicalProcessorInformation


powerbass4
 Share

Recommended Posts

Hi, I need the help of some "C++ Pros" of you....

The "WINAPI GetLogicalProcessorInformation" function does not exists in the AutoIt Includes, so I decided to build it on my own ....no success so far.
I adapted easy functions, but this one seems to be odd and unfamiliar.

I hope somebody can help me.... and after that this function should be added to the Includes (WinAPISys.au3).

 

BOOL WINAPI GetLogicalProcessorInformation(
  _Out_   PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,
  _Inout_ PDWORD                                ReturnLength
);

https://msdn.microsoft.com/en-us/library/windows/desktop/ms683194(v=vs.85).aspx

 

typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
  ULONG_PTR                      ProcessorMask;
  LOGICAL_PROCESSOR_RELATIONSHIP Relationship;
  union {
    struct {
      BYTE Flags;
    } ProcessorCore;
    struct {
      DWORD NodeNumber;
    } NumaNode;
    CACHE_DESCRIPTOR Cache;
    ULONGLONG        Reserved[2];
  };
} SYSTEM_LOGICAL_PROCESSOR_INFORMATION, *PSYSTEM_LOGICAL_PROCESSOR_INFORMATION;

https://msdn.microsoft.com/en-us/library/windows/desktop/ms686694(v=vs.85).aspx

Link to comment
Share on other sites

maybe there is a better way to "translate" the union

#include <Array.au3>
#include <WinAPI.au3>
#include <array.au3>

#AutoIt3Wrapper_UseX64=n

;variablen zuordnen
Enum $RelationProcessorCore, _
        $RelationNumaNode, _
        $RelationCache, _
        $RelationProcessorPackage, _
        $RelationGroup, _
        $RelationAll


Global $processorCoreCount = 0, _
        $logicalProcessorCount = 0, _
        $processorPackageCount = 0, _
        $numaNodeCount = 0, _
        $L1CacheCount = 0, _
        $L2CacheCount = 0, _
        $L3CacheCount = 0, _
        $L1CacheSize = 0, _
        $L2CacheSize = 0, _
        $L3CacheSize = 0




$dll = DllOpen("kernel32.dll")
ConsoleWrite('- Debug(' & @ScriptLineNumber & ') : $dll = ' & $dll & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
ConsoleWrite('- : $dll = ' & $dll & @CRLF)               ;### Debug Console

;adresse holen
$procaddress = DllCall($dll, "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "GetLogicalProcessorInformation")
ConsoleWrite('- : $ret = ' & $procaddress[0] & @CRLF)    ;### Debug Console

;Funktion callen, um buffer größe zu erhalten
$return_length = 0
$ret = DllCallAddress("uint", $procaddress[0], "dword", 0, "uint*", $return_length)
;~ ConsoleWrite('- : $ret = ' & $ret & @CRLF ) ;### Debug Console
$return_length = $ret[2]
;~ ConsoleWrite('- : $return_length = ' & $return_length & @CRLF ) ;### Debug Console
;~ _arraydisplay($ret)


$struct_bytes = DllStructCreate("byte [" & $return_length & "]")
$ptr = DllStructGetPtr($struct_bytes)
;~ ConsoleWrite('- : $ptr = ' & $ptr & @CRLF ) ;### Debug Console


;Funktion callen, um bufferpointer  zu übergeben und buffer zu füllen
$ret = DllCallAddress("uint", $procaddress[0], "ptr", $ptr, "uint*", $return_length)
;~ ConsoleWrite('- : $ret = ' & $ret[0] & @CRLF ) ;### Debug Console
;~ _arraydisplay($ret)

;zeig´s mir baby!!!
$ret = DllStructGetData($struct_bytes, 1)
ConsoleWrite('- : $ret = ' & ($ret) & @CRLF)             ;### Debug Console
For $i = 3 To $return_length * 2 Step 48
    $a = StringMid($ret, $i, 48)
    ConsoleWrite("    " & $a & @CRLF)
Next


ConsoleWrite(@CRLF & @CRLF & "+ Ergebnisse:" & @CRLF & @CRLF)

;zuordnen

For $i = 0 To $return_length - 24 Step 24

    $a = StringMid($ret, 3 + $i * 2, 48)
    ConsoleWrite($a & @CRLF)

;~ ;PLPI = PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
    $struct_PLPI = DllStructCreate("dword ProcessorMask;" & _
            "dword Relationship;" & _
            "byte [16];", $ptr + $i)

    ;die "union" nachbasteln....alle
    $struct_Processorcore = DllStructCreate("byte Flags", DllStructGetPtr($struct_PLPI) + 8)

    $struct_NumaNode = DllStructCreate("dword NodeNumber", DllStructGetPtr($struct_PLPI) + 8)

    $struct_CACHE_DESCRIPTOR = DllStructCreate("byte Level;" & _
            "byte Associativity;" & _
            "word Linesize;" & _
            "dword Size;" & _
            "dword Type", DllStructGetPtr($struct_PLPI) + 8)



;~     $structsize = DllStructGetSize($struct_PLPI)
;~     ConsoleWrite('- : $structsize = ' & $structsize & @CRLF ) ;### Debug Console




    ;Daten auslesen
    $ProcessorMask = DllStructGetData($struct_PLPI, "ProcessorMask")
    ConsoleWrite('> $ProcessorMask = ' & $ProcessorMask & @CRLF)
    $Relationship = DllStructGetData($struct_PLPI, "Relationship")
    ConsoleWrite('> $Relationship  = ' & $Relationship)


    $Relationship = Int(DllStructGetData($struct_PLPI, "Relationship"))

    Switch $Relationship

        Case $RelationProcessorCore                      ;0 es werden Prozessor daten abgefragt
            ConsoleWrite("  ProcessorCore" & @CRLF)
            $ProcessorCore = DllStructGetData($struct_Processorcore, "Flags")
            ConsoleWrite('- : $ProcessorCore = ' & $ProcessorCore & @CRLF) ;### Debug Console

            $processorCoreCount += 1

            $logicalProcessorCount += CountSetBits($ProcessorMask)

        Case $RelationNumaNode
            ConsoleWrite("  NumaNode" & @CRLF)
            $NodeNumber = DllStructGetData($struct_NumaNode, "NodeNumber")
            ConsoleWrite('- : $NodeNumber = ' & $NodeNumber & @CRLF) ;### Debug Console

            $numaNodeCount += 1

        Case $RelationCache
            ConsoleWrite("  RelationCache" & @CRLF)
            $Level = DllStructGetData($struct_CACHE_DESCRIPTOR, "Level")
            ConsoleWrite('- : $Level = ' & $Level & @CRLF) ;### Debug Console
            $Associativity = DllStructGetData($struct_CACHE_DESCRIPTOR, "Associativity")
            ConsoleWrite('- : $Associativity = ' & $Associativity & @CRLF) ;### Debug Console
            $Linesize = DllStructGetData($struct_CACHE_DESCRIPTOR, "Linesize")
            ConsoleWrite('- : $Linesize = ' & $Linesize & @CRLF) ;### Debug Console
            $Size = DllStructGetData($struct_CACHE_DESCRIPTOR, "Size")
            ConsoleWrite('- : $Size = ' & $Size & @CRLF) ;### Debug Console
            $Type = DllStructGetData($struct_CACHE_DESCRIPTOR, "Type")
            ConsoleWrite('- : $Type = ' & $Type & @CRLF) ;### Debug Console

            Switch $Level
                Case 1
                    $L1CacheCount += 1
                    $L1CacheSize += $Size
                Case 2
                    $L2CacheCount += 1
                    $L2CacheSize += $Size
                Case 3
                    $L3CacheCount += 1
                    $L3CacheSize += $Size
            EndSwitch




        Case $RelationProcessorPackage
            ConsoleWrite("  ProcessorPackage" & @CRLF)
            $processorPackageCount += 1

        Case $RelationGroup
            ConsoleWrite("  Group" & @CRLF)



    EndSwitch






    ConsoleWrite(@CRLF & @CRLF)

Next



$returnstring = "GetLogicalProcessorInformation:" & @CRLF & @CRLF & _
        StringFormat("Number %-30s = %u", "Processorcores", $processorCoreCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "NumaNodes", $numaNodeCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "logicalProcessorCount", $logicalProcessorCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "processorPackageCount", $processorPackageCount) & @CRLF & _
        StringFormat("Number %-30s = %u/%u/%u", "Level1/2/3-Caches", $L1CacheCount, $L2CacheCount, $L3CacheCount) & @CRLF & _
        StringFormat("Number %-30s = %u/%u/%u", "L1/L2/L3 cache sizes (kB)", $L1CacheSize / 1024, $L2CacheSize / 1024, $L3CacheSize / 1024) & @CRLF & _
        ""

ConsoleWrite($returnstring & @CRLF)

MsgBox(0, "GetLogicalProcessorInformation", $returnstring)



Func CountSetBits($uint)                                 ;zählt gesetzte bits
    $anz = 0
    For $i = 0 To 31
        If BitAND(2 ^ $i, $uint) Then $anz += 1
    Next
    Return $anz
EndFunc                                                  ;==>CountSetBits

 

Edited by AndyG
Link to comment
Share on other sites

@AndyG: Hi! Please, can you be so kind to explain me these two issues:

Quote
For $i = 0 To $return_length - 48 Step 24

 

Why do you exclude last 48 bytes?

Quote
$a = StringMid($ret, 3 + $i * 2, 48)

 

Why do you exclude first 3 bytes and $i is multiplied by 2?

 

Edited by j0kky
Link to comment
Share on other sites

@j0kky,

Because I can not program (only "read" a little bit) C(++)-code, i had to examine those "UNION"-stuff.

The "showing" of the bytes in several "lines" helped me to understand the structure, so i converted the bytes to chars to have a better "view" into the data!

The SYSTEM_LOGICAL_PROCESSOR_INFORMATION - struct has a lenght of 24bytes. In HEX-representation, the length is 48 chars....the length of the entire string is 2 (chars/bytes) for the "0x" and X*48(chars/bytes). The data starts at the third character, the first 2 are the "0x".

Imagine, that the 24Byte-SYSTEM_LOGICAL_PROCESSOR_INFORMATION - struct is a "Window"  to show only 24Bytes in the memory from all the bytes given back from the GetLogicalProcessorInformation-Function-call.

The start-address for every "24-bytes-Window" is the pointer to the memory plus 24 Bytes....

If you reach the end, the last "24-bytes-Window" is the region/area 24 bytes in front of the last byte....in HEX-reperesentation 48 chars. The last "address" for stringmid() to show the next(last) 48 chars is (endaddress-48).

I hope that i could clarify a little bit and that my explanations were useful. If not, ask again and surely someone with a much better phrasing/mode of expression than me will help you!

 

[OT]What should I do without google translate:>[OT]

 

code for 32/64Bit

#include <Array.au3>
#include <WinAPI.au3>


#AutoIt3Wrapper_UseX64=y                                 ;für 32/64Bit

;variablen zuordnen
Enum $RelationProcessorCore, _
        $RelationNumaNode, _
        $RelationCache, _
        $RelationProcessorPackage, _
        $RelationGroup, _
        $RelationAll


Global $processorCoreCount = 0, _
        $logicalProcessorCount = 0, _
        $processorPackageCount = 0, _
        $numaNodeCount = 0, _
        $L1CacheCount = 0, _
        $L2CacheCount = 0, _
        $L3CacheCount = 0, _
        $L1CacheSize = 0, _
        $L2CacheSize = 0, _
        $L3CacheSize = 0


If @AutoItX64 Then
    $32_64 = 32
    $sSize = 16
Else
    $32_64 = 24
    $sSize = 8
EndIf



$dll = DllOpen("kernel32.dll")
;~ ConsoleWrite('- Debug(' & @ScriptLineNumber & ') : $dll = ' & $dll & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
;~ ConsoleWrite('- : $dll = ' & $dll & @CRLF)               ;### Debug Console

;adresse holen
$procaddress = DllCall($dll, "ptr", "GetProcAddress", "ptr", _WinAPI_GetModuleHandle("kernel32.dll"), "str", "GetLogicalProcessorInformation")
;~ ConsoleWrite('- : $ret = ' & $procaddress[0] & @CRLF)    ;### Debug Console

;Funktion callen, um buffer größe zu erhalten
$return_length = 0
$ret = DllCallAddress("uint", $procaddress[0], "dword", 0, "uint*", $return_length)
;~ ConsoleWrite('- : $ret = ' & $ret & @CRLF ) ;### Debug Console
$return_length = $ret[2]
;~ ConsoleWrite('- : $return_length = ' & $return_length & @CRLF ) ;### Debug Console
;~ _ArrayDisplay($ret)


$struct_bytes = DllStructCreate("byte [" & $return_length & "]")
$ptr = DllStructGetPtr($struct_bytes)
;~ ConsoleWrite('- : $ptr = ' & $ptr & @CRLF ) ;### Debug Console


;Funktion callen, um bufferpointer  zu übergeben und buffer zu füllen
$ret = DllCallAddress("uint", $procaddress[0], "ptr", $ptr, "uint*", $return_length)
;~ ConsoleWrite('- : $ret = ' & $ret[0] & @CRLF ) ;### Debug Console
;~ _arraydisplay($ret)

;zeig´s mir baby!!!
$ret = DllStructGetData($struct_bytes, 1)
ConsoleWrite('- : $ret = ' & ($ret) & @CRLF)             ;### Debug Console
For $i = 3 To $return_length * 2 Step $32_64 * 2
    $a = StringMid($ret, $i, $32_64 * 2)
    ConsoleWrite("    " & $a & @CRLF)
Next


ConsoleWrite(@CRLF & @CRLF & "+ Ergebnisse:" & @CRLF & @CRLF)

;zuordnen

For $i = 0 To $return_length - $32_64 Step $32_64

    $a = StringMid($ret, 3 + $i * 2, $32_64 * 2)
    ConsoleWrite($a & @CRLF)

;~ ;PLPI = PSYSTEM_LOGICAL_PROCESSOR_INFORMATION
    $struct_PLPI = DllStructCreate("uint_ptr ProcessorMask;" & _
            "uint_ptr Relationship;" & _
            "byte [" & $32_64 - 16 & "]", $ptr + $i)

    ;die "union" nachbasteln....alle
    $struct_Processorcore = DllStructCreate("byte Flags", DllStructGetPtr($struct_PLPI) + $sSize)

    $struct_NumaNode = DllStructCreate("dword NodeNumber", DllStructGetPtr($struct_PLPI) + $sSize)

    $struct_CACHE_DESCRIPTOR = DllStructCreate("byte Level;" & _
            "byte Associativity;" & _
            "word Linesize;" & _
            "dword Size;" & _
            "dword Type", DllStructGetPtr($struct_PLPI) + $sSize)



;~     $structsize = DllStructGetSize($struct_PLPI)
;~     ConsoleWrite('- : $structsize = ' & $structsize & @CRLF ) ;### Debug Console




    ;Daten auslesen
    $ProcessorMask = DllStructGetData($struct_PLPI, "ProcessorMask")
    ConsoleWrite('> $ProcessorMask = ' & $ProcessorMask & @CRLF)
    $Relationship = DllStructGetData($struct_PLPI, "Relationship")
    ConsoleWrite('> $Relationship  = ' & $Relationship)


    $Relationship = Int(DllStructGetData($struct_PLPI, "Relationship"))

    Switch $Relationship

        Case $RelationProcessorCore                      ;0 es werden Prozessor daten abgefragt
            ConsoleWrite("  ProcessorCore" & @CRLF)
            $ProcessorCore = DllStructGetData($struct_Processorcore, "Flags")
            ConsoleWrite('- : $ProcessorCore = ' & $ProcessorCore & @CRLF) ;### Debug Console

            $processorCoreCount += 1

            $logicalProcessorCount += CountSetBits($ProcessorMask)

        Case $RelationNumaNode
            ConsoleWrite("  NumaNode" & @CRLF)
            $NodeNumber = DllStructGetData($struct_NumaNode, "NodeNumber")
            ConsoleWrite('- : $NodeNumber = ' & $NodeNumber & @CRLF) ;### Debug Console

            $numaNodeCount += 1

        Case $RelationCache
            ConsoleWrite("  RelationCache" & @CRLF)
            $Level = DllStructGetData($struct_CACHE_DESCRIPTOR, "Level")
            ConsoleWrite('- : $Level = ' & $Level & @CRLF) ;### Debug Console
            $Associativity = DllStructGetData($struct_CACHE_DESCRIPTOR, "Associativity")
            ConsoleWrite('- : $Associativity = ' & $Associativity & @CRLF) ;### Debug Console
            $Linesize = DllStructGetData($struct_CACHE_DESCRIPTOR, "Linesize")
            ConsoleWrite('- : $Linesize = ' & $Linesize & @CRLF) ;### Debug Console
            $Size = DllStructGetData($struct_CACHE_DESCRIPTOR, "Size")
            ConsoleWrite('- : $Size = ' & $Size & @CRLF) ;### Debug Console
            $Type = DllStructGetData($struct_CACHE_DESCRIPTOR, "Type")
            ConsoleWrite('- : $Type = ' & $Type & @CRLF) ;### Debug Console

            Switch $Level
                Case 1
                    $L1CacheCount += 1
                    $L1CacheSize += $Size
                Case 2
                    $L2CacheCount += 1
                    $L2CacheSize += $Size
                Case 3
                    $L3CacheCount += 1
                    $L3CacheSize += $Size
            EndSwitch




        Case $RelationProcessorPackage
            ConsoleWrite("  ProcessorPackage" & @CRLF)
            $processorPackageCount += 1

        Case $RelationGroup
            ConsoleWrite("  Group" & @CRLF)



    EndSwitch






    ConsoleWrite(@CRLF & @CRLF)

Next



$returnstring = "GetLogicalProcessorInformation: " & 32 * (1 + @AutoItX64) & "Bit" & @CRLF & @CRLF & _
        StringFormat("Number %-30s = %u", "Processorcores", $processorCoreCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "NumaNodes", $numaNodeCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "logicalProcessorCount", $logicalProcessorCount) & @CRLF & _
        StringFormat("Number %-30s = %u", "processorPackageCount", $processorPackageCount) & @CRLF & _
        StringFormat("Number %-30s = %u/%u/%u", "Level1/2/3-Caches", $L1CacheCount, $L2CacheCount, $L3CacheCount) & @CRLF & _
        StringFormat("Number %-30s = %u/%u/%u", "L1/L2/L3 cache sizes (kB)", $L1CacheSize / 1024, $L2CacheSize / 1024, $L3CacheSize / 1024) & @CRLF & _
        ""

ConsoleWrite($returnstring & @CRLF)

MsgBox(0, "GetLogicalProcessorInformation", $returnstring)



Func CountSetBits($uint)                                 ;zählt gesetzte bits
    $anz = 0
    For $i = 0 To 31
        If BitAND(2 ^ $i, $uint) Then $anz += 1
    Next
    Return $anz
EndFunc                                                  ;==>CountSetBits

 

 

 

Edited by AndyG
Link to comment
Share on other sites

You have been extremely clear, my mistake was not to consider what DllStructGetData does to binary data (it multiplies by 2 the final lenght and adds 2 characters "0x" at the start) :D

Thank you very much!

Link to comment
Share on other sites

@Andy G: On second thought I'm quite sure in first script it should be:

For $i = 0 To $return_length - 24 Step 24

In fact, in my system, if you exclude 48 bytes instead of 24, you don't count a NumaNode!

Edited by j0kky
Link to comment
Share on other sites

We helped each other :)

Maybe next days I'll post my version of GetLogicalProcessorInformation wrapper, I don't know if GetProcAddress involvement is really necessary!

Link to comment
Share on other sites

2 hours ago, j0kky said:

I don't know if GetProcAddress involvement is really necessary!

No, it´s not!

"Stolen" from chesstiger´s not fully working try :bye::

$hDll = DllOpen("Kernel32.dll")
    $tBufferSize = DllStructCreate("dword size;")
    DllCall($hDll, "bool", "GetLogicalProcessorInformation", "struct*", 0, "DWORD_PTR", DllStructGetPtr($tBufferSize, "size"))
    $hMem = _MemGlobalAlloc($tBufferSize.size, $GPTR) ;Nötig, da sonst nach Verlassen der Funktion der Speicherbereich freigegeben wird...
    $tBuffer = DllStructCreate("byte[" & $tBufferSize.size & "]", $hMem)
    DllCall($hDll, "bool", "GetLogicalProcessorInformation", "struct*", DllStructGetPtr($tBuffer), "DWORD_PTR", DllStructGetPtr($tBufferSize, "size"))

this and the use of something like an OO-Style (to get the content of the structs by their name like $buffer.item ) should lead to a good result. Have fun!

Edited by AndyG
Link to comment
Share on other sites

  • 2 weeks later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...