Detecting OS Version Using WMI

Share your advanced PureBasic knowledge/code with the community.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Detecting OS Version Using WMI

Post by RASHAD »

;Using WMI works for at least 80% of the cases
;Let us use the OS resources if it is wrong so MS did that
;For detecting if the OS is 32 bit or 64 bit there is a professional way by Rescator
;but I decided to code somthing simple but different so the User have more than one option to use
;Between lines there are many small tips to use

;Tested on XP , Vista ,Windows 7 32/64 and it works (I hope)

;Boys please do not make it a scandal

Code: Select all

#COINIT_MULTITHREAD=0 
#RPC_C_AUTHN_LEVEL_CONNECT=2 
#RPC_C_IMP_LEVEL_IDENTIFY=2 
#EOAC_NONE=0 
#RPC_C_AUTHN_WINNT=10 
#RPC_C_AUTHZ_NONE=0 
#RPC_C_AUTHN_LEVEL_CALL=3 
#RPC_C_IMP_LEVEL_IMPERSONATE=3 
#CLSCTX_INPROC_SERVER=1 
#wbemFlagReturnImmediately=16 
#wbemFlagForwardOnly=32 
#IFlags = #wbemFlagReturnImmediately + #wbemFlagForwardOnly 
#WBEM_INFINITE=$FFFFFFFF 
#WMISeparator="," 


Procedure.l ansi2uni(ansi.s) 
  size.l=MultiByteToWideChar_(#CP_ACP,0,ansi,-1,0,0) 
  Dim unicode.w(size) 
  MultiByteToWideChar_(#CP_ACP, 0, ansi, Len(ansi), unicode(), size) 
  ProcedureReturn SysAllocString_(@unicode()) 
EndProcedure 

Procedure uni2ansi(uni) 
  Shared WMIResult.s 
  WMIResult.s = "" 
  mem=uni 
  While PeekW (mem) 
    WMIResult=WMIResult+Chr(PeekW(mem)) 
    mem=mem+2 
  Wend 
  ProcedureReturn @WMIResult 
EndProcedure 

ProcedureDLL.s WMI(WMICommand.s) 
  CoInitializeEx_(0,#COINIT_MULTITHREAD) 
  hres=CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT,#RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0) 
  If hres <> 0: MessageRequester("ERROR", "unable to call CoInitializeSecurity", #MB_OK): Goto cleanup: EndIf 
  hres=CoCreateInstance_(?CLSID_WbemLocator,0,#CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc.IWbemLocator) 
  If hres <> 0: MessageRequester("ERROR", "unable to call CoCreateInstance", #MB_OK): Goto cleanup: EndIf 
  hres=loc\ConnectServer(ansi2uni("root\cimv2"),0,0,0,0,0,0,@svc.IWbemServices) 
  If hres <> 0: MessageRequester("ERROR", "unable to call IWbemLocator::ConnectServer", #MB_OK): Goto cleanup: EndIf 
  hres=svc\QueryInterface(?IID_IUnknown,@pUnk.IUnknown) 
  hres=CoSetProxyBlanket_(svc,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE) 
  If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf 
  hres=CoSetProxyBlanket_(pUnk,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE) 
  If hres <> 0: MessageRequester("ERROR", "unable to call CoSetProxyBlanket", #MB_OK): Goto cleanup: EndIf 
  pUnk\Release()
  
  k=CountString(WMICommand,#WMISeparator) 
  Dim wmitxt$(k) 
  For i=0 To k 
    wmitxt$(i) = StringField(WMICommand,i+1,#WMISeparator) 
  Next
   
  
  hres=svc\ExecQuery(ansi2uni("WQL"),ansi2uni(wmitxt$(0)), #IFlags,0,@pEnumerator.IEnumWbemClassObject) 
  If hres <> 0: MessageRequester("ERROR", "unable to call IWbemServices::ExecQuery", #MB_OK): Goto cleanup: EndIf 
  hres=pEnumerator\reset() 
  Repeat 
  hres=pEnumerator\Next(#WBEM_INFINITE, 1, @pclsObj.IWbemClassObject, @uReturn) 
  For i=1 To k 
    mem=AllocateMemory(1000) 
    hres=pclsObj\get(ansi2uni(wmitxt$(i)), 0, mem, 0, 0) 
    Type=PeekW(mem) 
    Select Type 
      Case 8 
        val.s=PeekS(uni2ansi(PeekL(mem+8))) 
      Case 3 
        val.s=Str(PeekL(mem+8)) 
      Default 
        val.s="" 
    EndSelect 
    If uReturn <> 0: wmi$=wmi$+wmitxt$(i)+" = "+val+Chr(10)+Chr(13): EndIf 
    FreeMemory(mem) 
  Next 
Until uReturn = 0 

cleanup: 
svc\Release() 
loc\Release() 
pEnumerator\Release() 
pclsObj\Release() 
CoUninitialize_() 

ProcedureReturn wmi$ 
EndProcedure 


DataSection 
CLSID_IEnumWbemClassObject: 
Data.l $1B1CAD8C 
Data.w $2DAB, $11D2 
Data.b $B6, $04, $00, $10, $4B, $70, $3E, $FD 

IID_IEnumWbemClassObject: 
Data.l $7C857801 
Data.w $7381, $11CF 
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24 

CLSID_WbemLocator: 
Data.l $4590F811 
Data.w $1D3A, $11D0 
Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24 

IID_IWbemLocator: 
Data.l $DC12A687 
Data.w $737F, $11CF 
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24 

IID_IUnknown: 
Data.l $00000000 
Data.w $0000, $0000 
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
EndDataSection 


Procedure.s Between(string.s, LString.s, RString.s) 
  Protected Between.s, LIndex.l, RIndex.l 
  
  LIndex = FindString(string, LString, 0) 
  RIndex = FindString(string, RString, 0) 
  
  If LIndex And RIndex 
    LIndex  + Len(LString) 
    Between = Mid(string, LIndex, RIndex-LIndex) 
  EndIf 
  
  ProcedureReturn Between 
EndProcedure

Procedure.s GetWindowsDirectory()
  Path.s=Space(500)
  GetWindowsDirectory_(@Path,500)
  ProcedureReturn Path
EndProcedure  

Text$ = WMI("Select * FROM Win32_OperatingSystem,Name")
Text$ = Between(Text$,"Name = ","|")

If FileSize(GetWindowsDirectory()+"\SysWOW64") = -2
Text$ = Text$ + ",64 bit"
Else
Text$ = Text$ + ",32 bit"
EndIf

MessageRequester("OS Version",Text$)
have a good day
RASHAD
rsts
Addict
Addict
Posts: 2736
Joined: Wed Aug 24, 2005 8:39 am
Location: Southwest OH - USA

Post by rsts »

Works fine for

---------------------------
OS Version
---------------------------
Microsoft Windows 7 Home Premium ,64 bit
---------------------------
OK
---------------------------
User avatar
Tomi
Enthusiast
Enthusiast
Posts: 270
Joined: Wed Sep 03, 2008 9:29 am

Post by Tomi »

XP 32 detected
Thanks RASHAD
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Nice, thank you :)

Only works though as long as the WMI service is not disabled on the computer, which a lot of people do now a days even though its not necessary.
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4954
Joined: Sun Apr 12, 2009 6:27 am

Post by RASHAD »

@rsts
You are as usual
Thanks man

@Tomi
Thank you

@SFSxOI
Thank you
That is why I said 80% success
Post Reply