Query BIOS serial number: Difference between revisions

From NSIS Wiki
Jump to navigationJump to search
(Created page with "The following code demonstrates the usage of the Windows Management Instrumentation (WMI) only via the System plugin. The sample code displays the BIOS serial number in a mes...")
 
(Variant might be 64-bit number, must allocate a large enough struct)
Line 77: Line 77:
             ; Variant
             ; Variant
             ; (unsigned short vt, WORD wReserved1, WORD wReserved2, WORD wReserved3, BSTR bstrVal)
             ; (unsigned short vt, WORD wReserved1, WORD wReserved2, WORD wReserved3, BSTR bstrVal)
             System::Call "*(i 0, i 0, i 0) p.r7"
             System::Call "*(i 0, i 0, &i8 0) p.r7"
             ${If} $7 != 0
             ${If} $7 != 0
                 ; Call IWbemClassObject->Get
                 ; Call IWbemClassObject->Get
Line 85: Line 85:
                 ${Else}  
                 ${Else}  
                   ; Check type of variant
                   ; Check type of variant
                   System::Call "*$7(i .r1)"
                   System::Call "*$7(&i2 .r1)"
                  IntOp $1 $1 & 0xFFFF
                   ${If} $1 == ${VT_BSTR}
                   ${If} $1 == ${VT_BSTR}
                       ; Access bstrVal from Variant
                       ; Access bstrVal from Variant

Revision as of 16:44, 23 August 2016

The following code demonstrates the usage of the Windows Management Instrumentation (WMI) only via the System plugin.

The sample code displays the BIOS serial number in a message box.

The script makes use of features available in NSIS 3.0 or newer such as the Target directive and use of p for pointer in System::Call statements.

Script

OutFile "bios_serial.exe"
Target x86-unicode
 
!include "LogicLib.nsh"
 
!define CLSCTX_INPROC_SERVER 1
!define CLSID_WbemLocator {4590f811-1d3a-11d0-891f-00aa004b2e24}
!define IID_IWbemLocator {dc12a687-737f-11cf-884d-00aa004b2e24}
 
!define RPC_C_AUTHN_LEVEL_DEFAULT    0
!define RPC_C_IMP_LEVEL_IMPERSONATE  3
 
!define EOAC_NONE                    0
 
!define WBEM_FLAG_FORWARD_ONLY       0x20
!define WBEM_FLAG_RETURN_IMMEDIATELY 0x10
!define WBEM_INFINITE                0xffffffff
 
!define VT_BSTR                      8
 
Function bios_serial
  ; Save registers
  Push $1
  Push $2
  Push $3
  Push $4
  Push $5
  Push $6
  Push $7
 
  ; Initialization of COM is done via OleInitialize in NSIS installer code
  ; Set general COM security level
  System::Call "ole32::CoInitializeSecurity( \
        p 0, i -1, p 0, p 0, i ${RPC_C_AUTHN_LEVEL_DEFAULT}, \
        i ${RPC_C_IMP_LEVEL_IMPERSONATE}, p 0, i ${EOAC_NONE}, p 0) p.r1"
  ${If} $1 != 0
     StrCpy $0 "failed to initialize security: $1"
     Goto bios_serial_end
  ${EndIf}
 
  ; Create IWbemLocator interface
  System::Call "ole32::CoCreateInstance( \
        g '${CLSID_WbemLocator}', p 0, \
        i ${CLSCTX_INPROC_SERVER}, \
        g '${IID_IWbemLocator}', *p .r2) i.r1"
  ${If} $1 != 0
     StrCpy $0 "failed to create IWebmLocator object: $1"
     Goto bios_serial_end
  ${EndIf}
 
  ; Call IWbemLocator->ConnectServer
  System::Call "$2->3(w 'ROOT\CIMV2', p 0, p 0, i 0, p 0, i 0, i 0, *p .r3) p.r1"
 
  ${If} $1 != 0
     StrCpy $0 "failed to connect: $1"
  ${Else}
     ; Call IWbemServices->ExecQuery 
     System::Call "$3->20(w 'WQL', w 'Select SerialNumber from Win32_BIOS', \
        ${WBEM_FLAG_FORWARD_ONLY} | ${WBEM_FLAG_RETURN_IMMEDIATELY}, \
        p 0, *p .r4) p.r1"
     ${If} $1 != 0
         StrCpy $0 "failed to query: $1 $3"
     ${Else}
         ; Call IEnumWbemClassObject->Next
         System::Call "$4->4(i ${WBEM_INFINITE}, i 1, *p .r5, *p .r6) p.r1"
         ${If} $6 != 0
             ; Variant
             ; (unsigned short vt, WORD wReserved1, WORD wReserved2, WORD wReserved3, BSTR bstrVal)
             System::Call "*(i 0, i 0, &i8 0) p.r7"
             ${If} $7 != 0
                ; Call IWbemClassObject->Get
                System::Call "$5->4(w 'SerialNumber', i 0, p r7, i 0, i 0) p.r1"
                ${If} $1 != 0
                   StrCpy $0 "failed to get: $1"
                ${Else} 
                   ; Check type of variant
                   System::Call "*$7(&i2 .r1)"
                   ${If} $1 == ${VT_BSTR}
                      ; Access bstrVal from Variant
                      System::Call "*$7(i, i, w .r0)"
                   ${Else}
                      StrCpy $0 "failed to access data: wrong type [$1]"
                   ${EndIf}
                   System::Call "ole32::VariantClear(p r7)"
                ${EndIf}
                ; Deallocate memory of variant
                System::Free $7
             ${Else}
                StrCpy $0 "failed to allocate memory for variant"
             ${EndIf}
             ; Call IWbemClassObject->Release
             System::Call "$5->2()"
         ${Else}
             StrCpy $0 "failed to iterate [$6] $1"
         ${EndIf}
         ; Call IEnumWbemClassObject->Release
         System::Call "$4->2()"
     ${EndIf}
 
     ; Call IWbemService->Release
     System::Call "$3->2()"
  ${EndIf}
 
  ; Call IWbemLocator->Release
  System::Call "$2->2()"
 
bios_serial_end:
  ; Restore registers
  Pop $7
  Pop $6
  Pop $5
  Pop $4
  Pop $3
  Pop $2
  Pop $1
FunctionEnd
 
Function .onInit
  InitPluginsDir
  Call bios_serial
  MessageBox MB_OK "Bios Serial Number=$0"
  Quit
FunctionEnd
 
Section 
SectionEnd

Links

  • This forum thread contains the original but due to PHP prettifying messed up version of this script.
  • This MSDN link describes the Win32_BIOS WMI class used in this script.