Hi,
I am trying to get BiosVersion by using WMI. I have found example code at http://www.masm32.com/board/index.php?topic=6550.msg48779#msg48779 However because returned value is string array I can't print it easily. I don't want to write workaround code. So I am wondering what is the structure of string array? After I run my code I get below buffer at ecx register.

00233070  01 00 80 01 04 00 00 00 00 00 00 00 38 69 22 00  ........8i".
00233080  01 00 00 00 00 00 00 00 AB AB AB AB AB AB AB AB  .......
00233090  00 00 00 00 00 00 00 00 C0 5D DA 33 F3 2C 00 18  ........]3,.
002330A0  14 00 00 00 48 00 50 00 51 00 4F 00 45 00 4D 00  ...H.P.Q.O.E.M.
002330B0  20 00 2D 00 20 00 31 00 00 00 AD BA 0D F0 AD BA  .-. .1....
002330C0  AB AB AB AB AB AB AB AB 00 00 00 00 00 00 00 00  ........
002330D0  25 58 D9 D0 FC 2C 00 00 C4 00 21 00 30 2D 23 00  %X,...!.0-#.


Here is the code I use.
.586
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE

INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\ole32.inc
INCLUDE \masm32\include\msvcrt.inc
;INCLUDE \masm32\include\gel32.inc

INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\ole32.lib
INCLUDELIB \masm32\lib\msvcrt.lib
;INCLUDELIB \masm32\lib\gel32.lib

INCLUDE c:\masm32\macros\ucmacros.asm

; located in ObjIdl.h

EOAC_NONE  EQU 0

; located in RpcDce.h

RPC_C_AUTHN_LEVEL_DEFAULT  EQU 0
RPC_C_IMP_LEVEL_DEFAULT    EQU 0

RPC_C_IMP_LEVEL_IMPERSONATE EQU 3

GUID2 STRUC
    dd1 DWORD ?
    dw1 WORD ?
    dw2 WORD ?
    db1 BYTE ?
    db2 BYTE ?
    db3 BYTE ?
    db4 BYTE ?
    db5 BYTE ?
    db6 BYTE ?
    db7 BYTE ?
    db8 BYTE ?
GUID2 ENDS

IWbemLocator STRUCT
    lpVtbl DWORD  ?
IWbemLocator ENDS

IWbemLocatorVtbl STRUCT
    QueryInterface DWORD  ?
    AddRef        DWORD  ?
    Release        DWORD  ?
    ConnectServer  DWORD  ?
IWbemLocatorVtbl ENDS

IWbemServices STRUCT
    lpVtbl DWORD  ?
IWbemServices ENDS

IWbemServicesVtbl STRUCT
    QueryInterface            DWORD  ?
    AddRef                    DWORD  ?
    Release                    DWORD  ?
    OpenNamespace              DWORD  ?
    CancelAsyncCall            DWORD  ?
    QueryObjectSink            DWORD  ?
    GetObject                  DWORD  ?
    GetObjectAsync            DWORD  ?
    PutClass                  DWORD  ?
    PutClassAsync              DWORD  ?
    DeleteClass                DWORD  ?
    DeleteClassAsync          DWORD  ?
    CreateClassEnum            DWORD  ?
    CreateClassEnumAsync      DWORD  ?
    PutInstance                DWORD  ?
    PutInstanceAsync          DWORD  ?
    DeleteInstance            DWORD  ?
    DeleteInstanceAsync        DWORD  ?
    CreateInstanceEnum        DWORD  ?
    CreateInstanceEnumAsync    DWORD  ?
    ExecQuery                  DWORD  ?
    ExecQueryAsync            DWORD  ?
    ExecNotificationQuery      DWORD  ?
    ExecNotificationQueryAsync DWORD  ?
    ExecMethod                DWORD  ?
    ExecMethodAsync            DWORD  ?
IWbemServicesVtbl ENDS

IEnumWbemClassObject STRUCT
    lpVtbl          DWORD  ?
IEnumWbemClassObject ENDS

IEnumWbemClassObjectVtbl STRUCT
    QueryInterface DWORD  ?
    AddRef        DWORD  ?
    Release        DWORD  ?
    Reset          DWORD  ?
    Next          DWORD  ?
    NextAsync      DWORD  ?
    Clone          DWORD  ?
    Skip          DWORD  ?
IEnumWbemClassObjectVtbl ENDS

IWbemClassObject STRUCT
    lpVtbl DWORD  ?
IWbemClassObject ENDS

IWbemClassObjectVtbl STRUCT
    QueryInterface          DWORD  ?
    AddRef                  DWORD  ?
    Release                DWORD  ?
    GetQualifierSet        DWORD  ?
    Get                    DWORD  ?
    Put                    DWORD  ?
    Delete                  DWORD  ?
    GetNames                DWORD  ?
    BeginEnumeration        DWORD  ?
    Next                    DWORD  ?
    EndEnumeration          DWORD  ?
    GetPropertyQualifierSet DWORD  ?
    GetObjectText          DWORD  ?
    SpawnDerivedClass      DWORD  ?
    SpawnInstance          DWORD  ?
    CompareTo              DWORD  ?
    GetPropertyOrigin      DWORD  ?
    InheritsFrom            DWORD  ?
    GetMethod              DWORD  ?
    PutMethod              DWORD  ?
    DeleteMethod            DWORD  ?
    BeginMethodEnumeration  DWORD  ?
    NextMethod              DWORD  ?
    EndMethodEnumeration    DWORD  ?
    GetMethodQualifierSet  DWORD  ?
    GetMethodOrigin        DWORD  ?
IWbemClassObjectVtbl ENDS

.CONST
 
    wszSelect  WORD "S","E","L","E","C","T"," ","*"," ","F","R","O","M"," ",0  ; the WSTR macro can't handle the asterisk
    wszCrLf    WORD 13,10,0
     
    WSTR        wszClass,    "Win32_BIOS"    ;<<< Set class here
    WSTR        wszProperty, "BIOSVersion"  ;<<< Set property here
 
    WSTR        wszNameSpace, "root\cimv2"
    WSTR        wszQueryLanguage, "WQL"
 
    WSTR        wszMsg, "Bios Version: %s"
 
WaitKeyW proto :PTR WORD
.DATA

    ; located in WbemCli.h
 
    WBEM_FLAG_CONNECT_USE_MAX_WAIT  EQU    80h
    WBEM_FLAG_FORWARD_ONLY          EQU    20h
    WBEM_INFINITE                  EQU    -1
    WBEM_E_INVALID_QUERY            EQU    80041017h
    WBEM_E_INVALID_QUERY_TYPE      EQU    80041018h
 
    IID_IWbemLocator                GUID2  <0dc12a687h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
 
    IID_IEnumWbemClassObject        GUID2  <027947e1h,0d731h,011ceh,0a3h,057h,000h,000h,000h,000h,000h,001h>
 
    IID_IWbemClassObject            GUID2  <0dc12a681h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
 
    ; located in WbemProv.h
 
    CLSID_WbemAdministrativeLocator GUID2  <0cb8555cch,09128h,011d1h,0adh,09bh,000h,0c0h,04fh,0d8h,0fdh,0ffh>
 
    locator    IWbemLocator            <>
    service    IWbemServices          <>
    enumerator  IEnumWbemClassObject    <>
    processor  IWbemClassObject        <>
 
    retCount    DWORD  ?
 
    var_val    DWORD  ?
                DWORD  ?
                DWORD  ?
             
    pwszResult  PWORD  ?           
             
    wszQuery  WORD 256 dup(?)             

.CODE

  main:
 
    INVOKE CoInitializeEx, NULL, COINIT_MULTITHREADED
 
    INVOKE CoInitializeSecurity, NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
     
    INVOKE CoCreateInstance, ADDR CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, ADDR IID_IWbemLocator, ADDR locator

    INVOKE lstrcatW, ADDR wszQuery, ADDR wszSelect
    INVOKE lstrcatW, ADDR wszQuery, ADDR wszClass
 
    mov esi, locator
    lodsd
    push    OFFSET service
    push    NULL
    push    NULL
    push    WBEM_FLAG_CONNECT_USE_MAX_WAIT
    push    NULL
    push    NULL
    push    NULL
    push    OFFSET wszNameSpace
    push    DWORD PTR
    call    DWORD PTR

    mov esi, service
    lodsd
    push    OFFSET enumerator
    push    NULL
    push    WBEM_FLAG_FORWARD_ONLY
    push    OFFSET wszQuery
    push    OFFSET wszQueryLanguage
    push    DWORD PTR
    call    DWORD PTR

    mov esi, enumerator
    lodsd
    push    OFFSET retCount
    push    OFFSET processor
    push    TRUE
    push    WBEM_INFINITE
    push    DWORD PTR
    call    DWORD PTR
 
    mov esi, processor
    lodsd
    push    NULL
    push    NULL
    push    OFFSET var_val
    push    0
    push    OFFSET wszProperty
    push    DWORD PTR
    call    DWORD PTR
 
    mov esi,
    mov edi,
    mov ecx,
 
    mov pwszResult, ecx
 
    INVOKE crt_wprintf, ADDR wszCrLf
    INVOKE crt_wprintf, ADDR wszMsg, pwszResult
    INVOKE crt_wprintf, ADDR wszCrLf

    INVOKE CoUninitialize
 
    INVOKE WaitKeyW, uni$("Press any key to exit ...")
 
    INVOKE ExitProcess, 0

WaitKeyW PROC pwszPrompt:PTR WORD
    .DATA
        IFNDEF wszCrLf
            wszCrLf WORD 13,10,0
        ENDIF
    .CODE 
    .IF pwszPrompt == NULL
        INVOKE crt_wprintf, ADDR wszCrLf
        INVOKE crt_wprintf, uni$("Press any key to continue ... ")
    .ELSE
        INVOKE crt_wprintf, ADDR wszCrLf
        INVOKE crt_wprintf, pwszPrompt
    .ENDIF 
    INVOKE crt__getch
    .IF (eax == 0) || (eax == 0E0h)
        INVOKE crt__getch
    .ENDIF
    INVOKE crt_wprintf, ADDR wszCrLf
    ret
WaitKeyW ENDP
;======================================================
 
END main


Here is the original vbs script that works.

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery( _
    "SELECT * FROM Win32_BIOS",,48)
For Each objItem in colItems
    If isNull(objItem.BIOSVersion) Then
        Wscript.Echo "BIOSVersion: Sorry. Unable to find that information."
    Else
        Wscript.Echo "BIOSVersion: " & Join(objItem.BIOSVersion, ",")
    End If
Next
WScript.Quit
Posted on 2009-09-19 07:12:06 by LaptoniC
Thanks to one of masm32forum members, I have managed to fix it. Here is the working code.

.586
.MODEL FLAT,STDCALL
OPTION CASEMAP:NONE

INCLUDE \masm32\include\windows.inc
INCLUDE \masm32\include\kernel32.inc
INCLUDE \masm32\include\ole32.inc
INCLUDE \masm32\include\msvcrt.inc
;INCLUDE \masm32\include\gel32.inc

INCLUDELIB \masm32\lib\kernel32.lib
INCLUDELIB \masm32\lib\ole32.lib
INCLUDELIB \masm32\lib\msvcrt.lib
;INCLUDELIB \masm32\lib\gel32.lib

INCLUDE c:\masm32\macros\ucmacros.asm

; located in ObjIdl.h

EOAC_NONE  EQU 0

; located in RpcDce.h

RPC_C_AUTHN_LEVEL_DEFAULT  EQU 0
RPC_C_IMP_LEVEL_DEFAULT    EQU 0

RPC_C_IMP_LEVEL_IMPERSONATE EQU 3

GUID2 STRUC
    dd1 DWORD ?
    dw1 WORD ?
    dw2 WORD ?
    db1 BYTE ?
    db2 BYTE ?
    db3 BYTE ?
    db4 BYTE ?
    db5 BYTE ?
    db6 BYTE ?
    db7 BYTE ?
    db8 BYTE ?
GUID2 ENDS

IWbemLocator STRUCT
    lpVtbl DWORD  ?
IWbemLocator ENDS

IWbemLocatorVtbl STRUCT
    QueryInterface DWORD  ?
    AddRef        DWORD  ?
    Release        DWORD  ?
    ConnectServer  DWORD  ?
IWbemLocatorVtbl ENDS

IWbemServices STRUCT
    lpVtbl DWORD  ?
IWbemServices ENDS

IWbemServicesVtbl STRUCT
    QueryInterface            DWORD  ?
    AddRef                    DWORD  ?
    Release                    DWORD  ?
    OpenNamespace              DWORD  ?
    CancelAsyncCall            DWORD  ?
    QueryObjectSink            DWORD  ?
    GetObject                  DWORD  ?
    GetObjectAsync            DWORD  ?
    PutClass                  DWORD  ?
    PutClassAsync              DWORD  ?
    DeleteClass                DWORD  ?
    DeleteClassAsync          DWORD  ?
    CreateClassEnum            DWORD  ?
    CreateClassEnumAsync      DWORD  ?
    PutInstance                DWORD  ?
    PutInstanceAsync          DWORD  ?
    DeleteInstance            DWORD  ?
    DeleteInstanceAsync        DWORD  ?
    CreateInstanceEnum        DWORD  ?
    CreateInstanceEnumAsync    DWORD  ?
    ExecQuery                  DWORD  ?
    ExecQueryAsync            DWORD  ?
    ExecNotificationQuery      DWORD  ?
    ExecNotificationQueryAsync DWORD  ?
    ExecMethod                DWORD  ?
    ExecMethodAsync            DWORD  ?
IWbemServicesVtbl ENDS

IEnumWbemClassObject STRUCT
    lpVtbl          DWORD  ?
IEnumWbemClassObject ENDS

IEnumWbemClassObjectVtbl STRUCT
    QueryInterface DWORD  ?
    AddRef        DWORD  ?
    Release        DWORD  ?
    Reset          DWORD  ?
    Next          DWORD  ?
    NextAsync      DWORD  ?
    Clone          DWORD  ?
    Skip          DWORD  ?
IEnumWbemClassObjectVtbl ENDS

IWbemClassObject STRUCT
    lpVtbl DWORD  ?
IWbemClassObject ENDS

IWbemClassObjectVtbl STRUCT
    QueryInterface          DWORD  ?
    AddRef                  DWORD  ?
    Release                DWORD  ?
    GetQualifierSet        DWORD  ?
    Get                    DWORD  ?
    Put                    DWORD  ?
    Delete                  DWORD  ?
    GetNames                DWORD  ?
    BeginEnumeration        DWORD  ?
    Next                    DWORD  ?
    EndEnumeration          DWORD  ?
    GetPropertyQualifierSet DWORD  ?
    GetObjectText          DWORD  ?
    SpawnDerivedClass      DWORD  ?
    SpawnInstance          DWORD  ?
    CompareTo              DWORD  ?
    GetPropertyOrigin      DWORD  ?
    InheritsFrom            DWORD  ?
    GetMethod              DWORD  ?
    PutMethod              DWORD  ?
    DeleteMethod            DWORD  ?
    BeginMethodEnumeration  DWORD  ?
    NextMethod              DWORD  ?
    EndMethodEnumeration    DWORD  ?
    GetMethodQualifierSet  DWORD  ?
    GetMethodOrigin        DWORD  ?
IWbemClassObjectVtbl ENDS

SAFEARRAYBOUND struct
cElements dd ?
lLbound dd ?
SAFEARRAYBOUND ends
 
SAFEARRAY    struct
cDims dw ?
fFeatures dw ?
cbElements dd ?
cLocks dd ?
pvData dd ?
rgsabound SAFEARRAYBOUND <>
SAFEARRAY ends

.CONST
 
    wszSelect  WORD "S","E","L","E","C","T"," ","*"," ","F","R","O","M"," ",0  ; the WSTR macro can't handle the asterisk
    wszCrLf    WORD 13,10,0


    WSTR        wszClass,    "Win32_BIOS"    ;<<< Set class here
    WSTR        wszProperty, "BIOSVersion"  ;<<< Set property here

    WSTR        wszNameSpace, "root\cimv2"
    WSTR        wszQueryLanguage, "WQL"
 
    WSTR        wszMsg, "Serial Number %i: %s"
 
WaitKeyW proto :PTR WORD
.DATA

    ; located in WbemCli.h
 
    WBEM_FLAG_CONNECT_USE_MAX_WAIT  EQU    80h
    WBEM_FLAG_FORWARD_ONLY          EQU    20h
    WBEM_INFINITE                  EQU    -1
    WBEM_E_INVALID_QUERY            EQU    80041017h
    WBEM_E_INVALID_QUERY_TYPE      EQU    80041018h
 
    IID_IWbemLocator                GUID2  <0dc12a687h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
 
    IID_IEnumWbemClassObject        GUID2  <027947e1h,0d731h,011ceh,0a3h,057h,000h,000h,000h,000h,000h,001h>
 
    IID_IWbemClassObject            GUID2  <0dc12a681h,0737fh,011cfh,088h,04dh,000h,0aah,000h,04bh,02eh,024h>
 
    ; located in WbemProv.h
 
    CLSID_WbemAdministrativeLocator GUID2  <0cb8555cch,09128h,011d1h,0adh,09bh,000h,0c0h,04fh,0d8h,0fdh,0ffh>
 
    locator    IWbemLocator            <>
    service    IWbemServices          <>
    enumerator  IEnumWbemClassObject    <>
    processor  IWbemClassObject        <>
 
    retCount    DWORD  ?
 
    var_val    DWORD  ?
                DWORD  ?
                DWORD  ?
                DWORD  ?


    pwszResult  PWORD  ?           
             
    wszQuery  WORD 256 dup(?)             

.CODE

  main:
 
    INVOKE CoInitializeEx, NULL, COINIT_MULTITHREADED
 
    INVOKE CoInitializeSecurity, NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
     
    INVOKE CoCreateInstance, ADDR CLSID_WbemAdministrativeLocator, NULL, CLSCTX_INPROC_SERVER, ADDR IID_IWbemLocator, ADDR locator

    INVOKE lstrcatW, ADDR wszQuery, ADDR wszSelect
    INVOKE lstrcatW, ADDR wszQuery, ADDR wszClass
 
    mov esi, locator
    lodsd
    push    OFFSET service
    push    NULL
    push    NULL
    push    WBEM_FLAG_CONNECT_USE_MAX_WAIT
    push    NULL
    push    NULL
    push    NULL
    push    OFFSET wszNameSpace
    push    DWORD PTR
    call    DWORD PTR

    mov esi, service
    lodsd
    push    OFFSET enumerator
    push    NULL
    push    WBEM_FLAG_FORWARD_ONLY
    push    OFFSET wszQuery
    push    OFFSET wszQueryLanguage
    push    DWORD PTR
    call    DWORD PTR

    mov esi, enumerator
    lodsd
    push    OFFSET retCount
    push    OFFSET processor
    push    TRUE
    push    WBEM_INFINITE
    push    DWORD PTR
    call    DWORD PTR
 
    mov esi, processor
    lodsd
    push    NULL
    push    NULL
    push    OFFSET var_val
    push    0
    push    OFFSET wszProperty
    push    DWORD PTR
    call    DWORD PTR
 
    mov esi,
    mov edi,
    mov ecx,
 
    mov pwszResult, ecx

mov esi,.SAFEARRAY.pvData
mov edi,.SAFEARRAY.rgsabound.cElements

    INVOKE crt_wprintf, ADDR wszCrLf
 
 

 
.while edi
  mov ecx,
  INVOKE crt_wprintf, ADDR wszMsg, edi,ecx
  INVOKE crt_wprintf, ADDR wszCrLf
dec edi
  add esi,4
.endw



    INVOKE crt_wprintf, ADDR wszCrLf

    INVOKE CoUninitialize
 
    INVOKE WaitKeyW, uni$("Press any key to exit ...")
 
    INVOKE ExitProcess, 0

WaitKeyW PROC pwszPrompt:PTR WORD
    .DATA
        IFNDEF wszCrLf
            wszCrLf WORD 13,10,0
        ENDIF
    .CODE 
    .IF pwszPrompt == NULL
        INVOKE crt_wprintf, ADDR wszCrLf
        INVOKE crt_wprintf, uni$("Press any key to continue ... ")
    .ELSE
        INVOKE crt_wprintf, ADDR wszCrLf
        INVOKE crt_wprintf, pwszPrompt
    .ENDIF 
    INVOKE crt__getch
    .IF (eax == 0) || (eax == 0E0h)
        INVOKE crt__getch
    .ENDIF
    INVOKE crt_wprintf, ADDR wszCrLf
    ret
WaitKeyW ENDP
;======================================================
 
END main
Posted on 2009-09-19 20:03:34 by LaptoniC