Search code examples
cmasm

In MASM, how to access the longValue member within the PDH_FMT_COUNTERVALUE struct?


Working on a project to get the current CPU load.
I'm having difficulty accessing the longvalue in this struct: (sizeof is 16 bytes)

   PDH_FMT_COUNTERVALUE STRUCT 8
                   CStatus                        DWORD ?
                   UNION                         
                   longValue                      DWORD ?
                   doubleValue                    QWORD ?
                   largeValue                     QWORD ?
                   pAnsiStringValue               QWORD ?
                   pWideStringValue               QWORD ?
                   ENDS                          
   PDH_FMT_COUNTERVALUE ENDS

Initially, I tried using this MASM code but the CPU usage was always 0.
(I think it was looking at the member padding after the first 4 bytes for CStatus)

              LOCAL           value:PDH_FMT_COUNTERVALUE
              ...
              LEA             R9,value
              MOV             EAX,DWORD PTR [R9+PDH_FMT_COUNTERVALUE.longValue]
              MOV             cput,RAX

However, by adding 4, it correctly finds the longvalue:

              LOCAL           value:PDH_FMT_COUNTERVALUE
              ...
              LEA             R9,value
              MOV             EAX,DWORD PTR [R9+PDH_FMT_COUNTERVALUE.longValue+4] ;; <-- +4 added here
              MOV             cput,RAX

Notice the following offset resolves to +8 overall

PDH_FMT_COUNTERVALUE.longValue+4 ;; dword ptr [r9+8]

For comparison, the MSVC compiler generates the correct +8 offset:
(It dereferences a byte, even though it's defined as a DWORD)

cput = value.longValue;
movzx       eax,byte ptr [value+8h]  
mov         byte ptr [cput],al  

Question

This code looks hackish [R9+PDH_FMT_COUNTERVALUE.longValue+4], so is there a more legit method to refer to the longvalue member directly in MASM?

EDIT

Possible solution, manually padding the struct allows access to the longValue.

   PDH_FMT_COUNTERVALUE STRUCT 8
                   CStatus                        DWORD ?
                   padding                        BYTE 4 DUP (?)
                   UNION                         
                   longValue                      DWORD ?
                   doubleValue                    QWORD ?
                   largeValue                     QWORD ?
                   pAnsiStringValue               QWORD ?
                   pWideStringValue               QWORD ?
                   ENDS                          
   PDH_FMT_COUNTERVALUE ENDS

Solution

  • Unfortunately I'm not aware of a cleaner solution than this, but this should work:

    COUNTERVALUE UNION                    
        longValue                      DWORD ?
        doubleValue                    QWORD ?
        largeValue                     QWORD ?
        pAnsiStringValue               QWORD ?
        pWideStringValue               QWORD ?
    COUNTERVALUE ENDS                          
    
    PDH_FMT_COUNTERVALUE STRUCT 8
        CStatus                        DWORD ?
        COUNTERVALUE                   <>
    PDH_FMT_COUNTERVALUE ENDS