Jump to content

Recommended Posts

Posted

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

Posted (edited)

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
Posted (edited)

@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
Posted (edited)

@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
Posted (edited)

@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
Posted (edited)
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
  • 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
×
×
  • Create New...