Author Topic: Postmodern WMI Access  (Read 8321 times)

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Postmodern WMI Access
« on: September 24, 2014, 08:36:00 AM »
Windows Management Instrumentation (WMI), MSDN

If you've ever written an application, and, wanted to determine the installed Windows Operating System Version on the user's computer, you've, no doubt, run into several annoying problems:
  • It's a complete pain in the ass,...and,...
  • It requires an awful lot of tedious code.
    So,...because I'm basically a fearlessly inept programmer, I've written an assembly language application that demonstrates the two current methods of determining the Operating System version: GetVersionEx, which is now OFFICIALLY deprecated,...and, the recommended alternative, accessing the WMI infrastructure to retrieve the appropriate data. WMI is all COM. Either way requires a ridiculous amount of code to return, presumably, accurate information about the Operating System. GetVersionEx works correctly up to Windows Version 8.1,...at which point it still works, but returns the incorrect version information. Windows 8.1 will return version information indicating it is actually Windows 8.0.
    The only difficult aspect of writing this code is prototyping the WMI COM interfaces as MASM-compatible structures. The correct execution of the application rests entirely on this mechanism. And, I had NO concept of how to do this reliably until I stumbled upon an example posted in the MASM Forum by, QWORD. QWORD is a well-known Forum genius, and, I thought it would be appropriate to acknowledge his contributions to the global assembly programmer community, by highjacking his technique and, using it extensively in this program. Thanks, QWORD,...
    I should warn you that there is an vast quantity of bloat infesting this program (and,...I expect numerous death threats for this). The application is a great example of HOW NOT TO WRITE AN ASSEMBLY PROGRAM. You would never deploy code like this in the real world,...it's too cumbersome, too error prone,...and, there are better ways of getting your code to work on someone else's computer without searching WMI first. 
    As always,...all comments are welcome,...except DAVE's GDI Device Context inquiries,...
Zen

adeyblue

  • Member
  • **
  • Posts: 89
    • Airesoft
Re: Postmodern WMI Access
« Reply #1 on: September 24, 2014, 09:16:10 AM »
GetVersionEx, which is now OFFICIALLY deprecated
You can use RtlGetVersion in ntdll.dll as a replacement for GetVersionEx. It's exactly the same function (takes the same two structures, though the MSDN page has them named differently), except it's unicode only and hasn't been, shall we say, neutered, in the same way.

jj2007

  • Member
  • *****
  • Posts: 8619
  • Assembler is fun ;-)
    • MasmBasic
Re: Postmodern WMI Access
« Reply #2 on: September 24, 2014, 11:10:08 AM »
There is also an environment variable called %OS%. From a DOS prompt, type
echo %OS%
and hit Enter.

sinsi

  • Member
  • *****
  • Posts: 1062
Re: Postmodern WMI Access
« Reply #3 on: September 24, 2014, 11:21:32 AM »
C:\Users\tester>echo %OS%
Windows_NT

Useful.
I can walk on water but stagger on beer.

hutch--

  • Administrator
  • Member
  • ******
  • Posts: 5659
  • Mnemonic Driven API Grinder
    • The MASM32 SDK
Re: Postmodern WMI Access
« Reply #4 on: September 24, 2014, 12:42:01 PM »
You do just a little better with VER

Code: [Select]
C:\>ver

Microsoft Windows [Version 6.1.7601]

One thing about Microsoft deprecation, it means that at least the API is stable.  :P
hutch at movsd dot com
http://www.masm32.com    :biggrin:  :biggrin:

jj2007

  • Member
  • *****
  • Posts: 8619
  • Assembler is fun ;-)
    • MasmBasic
Re: Postmodern WMI Access
« Reply #5 on: September 24, 2014, 04:36:01 PM »
Zen,

Access WMI.asm(756) : error A2006: undefined symbol : Fh

@Hutch: see Windows.inc:
ACCESS_DENIED_CALLBACK_ACE_TYPE  equ (0Ah)
ACCESS_ALLOWED_CALLBACK_OBJECT_ACE_TYPE equ (Bh)
ACCESS_DENIED_CALLBACK_OBJECT_ACE_TYPE equ (Ch)
SYSTEM_AUDIT_CALLBACK_ACE_TYPE   equ (Dh)
SYSTEM_ALARM_CALLBACK_ACE_TYPE   equ (Eh)
SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE equ (Fh)
SYSTEM_ALARM_CALLBACK_OBJECT_ACE_TYPE equ (10h)

After inserting this, it assembles fine:

        ASSUME ecx: NOTHING
        SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE equ (0Fh)
        .IF bl==SYSTEM_AUDIT_CALLBACK_OBJECT_ACE_TYPE    ;    (0Fh)

P.S.: Jotti says 6 out of 22 found "Gen:Variant.Kazy.156456" - how did you produce this???

http://virusscan.jotti.org/en-gb/scanresult/43c57c2b3dfe4ba62b3dbf90995434c6983459c0
« Last Edit: September 24, 2014, 08:04:45 PM by jj2007 »

ToutEnMasm

  • Member
  • *****
  • Posts: 1190
    • EditMasm
Re: Postmodern WMI Access
« Reply #6 on: September 24, 2014, 07:22:59 PM »
The NTDDI_... is the more easy to work with.
Need the list of NTDDI_ constantes in sdkddkver.h (sdk)
For all the system,you need a test
Quote
;################################################################
GetVersion PROC
         Local  retour:DWORD
   mov retour,0 ;defaut failed
   mov osvi.dwOSVersionInfoSize,sizeof SDKOSVERSIONINFOEX
   invoke GetVersionEx,addr osvi
   .if eax == FALSE
      mov osvi.dwOSVersionInfoSize,sizeof OSVERSIONINFO
      invoke GetVersionEx,addr osvi
   .endif
   mov retour,eax

FindeGetVersion:
   mov eax,retour
   ret
GetVersion endp

;return the NTDDI version in eax
;return the
;################################################################
SdkDdkVersion PROC                     ;return the NTDDI_ .. version
         Local  retour:DWORD
   mov retour,0
   invoke GetVersion
   .if eax != 0
      mov edx,osvi.dwMajorVersion
      shl edx,8      ;* 100h
      add edx,osvi.dwMinorVersion      
      shl edx,16      ;* 100h
      movzx eax,osvi.wServicePackMajor
      shl eax,8         ;* 10h
      add edx,eax
      mov retour,edx      
   .endif

FindeSdkDdkVersion:
   mov eax,retour
   ret
SdkDdkVersion endp

;################################################################

Quote
;
; NTDDI version constants
;
NTDDI_WIN2K   equ   < 005000000h>
NTDDI_WIN2KSP1   equ   < 005000100h>
NTDDI_WIN2KSP2   equ   < 005000200h>
NTDDI_WIN2KSP3   equ   < 005000300h>
NTDDI_WIN2KSP4   equ   < 005000400h>
NTDDI_WINXP   equ   < 005010000h>
NTDDI_WINXPSP1   equ   < 005010100h>
NTDDI_WINXPSP2   equ   < 005010200h>
NTDDI_WINXPSP3   equ   < 005010300h>
NTDDI_WINXPSP4   equ   < 005010400h>
NTDDI_WS03   equ   < 005020000h>
NTDDI_WS03SP1   equ   < 005020100h>
NTDDI_WS03SP2   equ   < 005020200h>
NTDDI_WS03SP3   equ   < 005020300h>
NTDDI_WS03SP4   equ   < 005020400h>
NTDDI_WIN6   equ   < 006000000h>
NTDDI_WIN6SP1   equ   < 006000100h>
NTDDI_WIN6SP2   equ   < 006000200h>
NTDDI_WIN6SP3   equ   < 006000300h>
NTDDI_WIN6SP4   equ   < 006000400h>
NTDDI_VISTA   equ   < NTDDI_WIN6>
NTDDI_VISTASP1   equ   < NTDDI_WIN6SP1>
NTDDI_VISTASP2   equ   < NTDDI_WIN6SP2>
NTDDI_VISTASP3   equ   < NTDDI_WIN6SP3>
NTDDI_VISTASP4   equ   < NTDDI_WIN6SP4>
NTDDI_LONGHORN   equ   < NTDDI_VISTA>
NTDDI_WS08   equ   < NTDDI_WIN6SP1>
NTDDI_WS08SP2   equ   < NTDDI_WIN6SP2>
NTDDI_WS08SP3   equ   < NTDDI_WIN6SP3>
NTDDI_WS08SP4   equ   < NTDDI_WIN6SP4>
NTDDI_WIN7   equ   < 006010000h>
NTDDI_WIN8   equ   < 006020000h>
NTDDI_WINBLUE   equ   < 006030000h>
;
Fa is a musical note to play with CL

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Postmodern WMI Access
« Reply #7 on: September 25, 2014, 04:08:37 AM »
Thanks, everyone for the information. All of your comments had info that I was completely unaware of. Thanks, ADEYBLUE...I wasn't even aware the RtlGetVersion routine even existed. :dazzled:

Quote from: HUTCH
One thing about Microsoft deprecation, it means that at least the API is stable.
FUNNY,...and, yet,...so true,...

JOCHEN,
It's weird, I rewrote and recompiled that program many times, and the compiler only caught one of those errors (forgetting the leading zero, before a hex value starting with a letter).
But, the more serious problem is the virus scan. I'm mystified. You have the source code,...where is the virus ???
The question: how did you produce this ???,...
I wrote the source in the Hutch's Quick Editor, and compiled it with the MASM compiler (ml.exe, Microsoft Macro Assembler version 6.14.8444, included with the MASM32 Package). I've never heard of Jotti before,...is it reliable ???

...And,...TOUTENMASM,...Thanks, I've never run across the  NTDDI version constants before,...had no idea even what they were,...
Here is a blog post from Raymond Chen: Why Are The Generic Version Numbers Called NTDDI?, Dec 2008
Zen

Vortex

  • Member
  • *****
  • Posts: 1821
Re: Postmodern WMI Access
« Reply #8 on: September 25, 2014, 04:43:55 AM »
You can check the registry to determine the OS version :

Code: [Select]
.386
.model flat,stdcall
option casemap:none

include     \masm32\include\windows.inc
include     \masm32\include\kernel32.inc
include     \masm32\include\user32.inc
include     \masm32\include\masm32.inc
include     \masm32\include\advapi32.inc
include     \masm32\include\msvcrt.inc

includelib  \masm32\lib\kernel32.lib
includelib  \masm32\lib\user32.lib
includelib  \masm32\lib\masm32.lib
includelib  \masm32\lib\advapi32.lib
includelib  \masm32\lib\msvcrt.lib

.data

subkey      db 'SOFTWARE\Microsoft\Windows NT\CurrentVersion',0
ValName     db 'ProductName',0
buffsize    dd 32

.data?

hKey        dd ?
buffer      db 32 dup(?)

.code

start:

    invoke  RegOpenKeyEx,HKEY_LOCAL_MACHINE,ADDR subkey,0,\
            KEY_ALL_ACCESS,ADDR hKey

    invoke  RegQueryValueEx,hKey,ADDR ValName,0,\
            0,ADDR buffer,ADDR buffsize

    invoke  StdOut,ADDR buffer
   
    invoke  RegCloseKey,hKey
    invoke  ExitProcess,0

END start

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Postmodern WMI Access
« Reply #9 on: September 25, 2014, 04:46:46 AM »
VORTEX,
Yeah,...thanks, good stuff. I'd forgotten about the registry. This key exists with the correct value for all versions of Windows (I assume it does) ???
Zen

Gunther

  • Member
  • *****
  • Posts: 3585
  • Forgive your enemies, but never forget their names
Re: Postmodern WMI Access
« Reply #10 on: September 25, 2014, 04:47:26 AM »
Hi Erol,

You can check the registry to determine the OS version :

interesting code. Can I use it for later?

Gunther
Get your facts first, and then you can distort them.

dedndave

  • Member
  • *****
  • Posts: 8806
  • Still using Abacus 2.0
    • DednDave
Re: Postmodern WMI Access
« Reply #11 on: September 25, 2014, 05:01:24 AM »
Erol has the right idea
in fact, some details may only be discovered by reading the registry

http://www.masmforum.com/board/index.php?topic=11963.0
http://www.masmforum.com/archive2012/6537_OSinfo23.zip

EDIT: using the registry should solve the 8.0/8.1 issue although, i haven't tested it

dedndave

  • Member
  • *****
  • Posts: 8806
  • Still using Abacus 2.0
    • DednDave
Re: Postmodern WMI Access
« Reply #12 on: September 25, 2014, 05:04:27 AM »
in reference to the post by adeyblue, "officially depricated" doesn't really mean a lot   :biggrin:

i am willing to bet that the function will still be supported in windows 9

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Postmodern WMI Access
« Reply #13 on: September 25, 2014, 05:10:58 AM »
DAVE !!
I was completely OBLIVIOUS to this thread. THANKS !
...So,...in addition to being a world-renowned expert on GDI Device Contexts,...you are also an expert on Operating System versions ???
Zen

jj2007

  • Member
  • *****
  • Posts: 8619
  • Assembler is fun ;-)
    • MasmBasic
Re: Postmodern WMI Access
« Reply #14 on: September 25, 2014, 05:13:58 AM »
It's weird, I rewrote and recompiled that program many times, and the compiler only caught one of those errors (forgetting the leading zero, before a hex value starting with a letter).
You probably modified Windows.inc and forgot about it. The equate MUST trigger an assembly error. Compare your windows.inc date to the other inc files.

Quote
But, the more serious problem is the virus scan. I'm mystified. You have the source code,...where is the virus ???
The question: how did you produce this ???,...
I wrote the source in the Hutch's Quick Editor, and compiled it with the MASM compiler (ml.exe, Microsoft Macro Assembler version 6.14.8444, included with the MASM32 Package). I've never heard of Jotti before,...is it reliable ???

Jotti is reliable, they use the major AV engines. Which means that something in your code triggers a warning based on heuristic analysis. Your invokes look clean...
Code: [Select]
invoke [esi].IEnumWbemClassObject.Next, ptrEnmWbmClsObjOS, WBEM_INFINITE, 1, ADDR ptrCrtInsOpSystm, ADDR ulNumRetCrtIns
invoke [esi].IEnumWbemClassObject.Next, ptrIEnmProcesrWbm, WBEM_INFINITE, 1, ADDR ppProcesorObj, ADDR ulProcesrRetd
invoke [esi].IEnumWbemClassObject.Next, ptrIEnmWbmOprtSystm, WBEM_INFINITE, 1, ADDR ppOprtngSystmObj, ADDR ulOSRetnd   
invoke [esi].IEnumWbemClassObject.Release, ptrIEnmProcesrWbm
invoke [esi].IEnumWbemClassObject.Release, ptrIEnmWbmOprtSystm
invoke [esi].IWbemClassObject.Get, dwOutBndParmsSD, dwBstrPropSD, 0, ADDR VarPropSD, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrCptnProp, 0, ADDR VarOSCptnProp, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrMinSrvPckVer, 0, ADDR VarSerPckMinr, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrNumProces, 0, ADDR VarNumProces, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOprSysName, 0, ADDR VarOSNamePrp, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOSArchPrp, 0, ADDR VarOSArchtcrPrp, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOSBuldType, 0, ADDR VarOSBuildTyp, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOSManfctr, 0, ADDR VarOSManfctr, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOSType, 0, ADDR VarOSType, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrOSVersion, 0, ADDR VarOSVersion, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrPrdctType, 0, ADDR VarPrdctType, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppOprtngSystmObj, BstrSrvPckMajrVer, 0, ADDR VarMajrSerPck, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrClckSpdPrcr, 0, ADDR VarPrcClkSpd, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrL2CacheSz, 0, ADDR VarL2CacheSz, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrMaxClckSpd, 0, ADDR VarMaxClkSpd, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrPrcrArchtcr, 0, ADDR VarPrcrArch, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrPrcrDatWdth, 0, ADDR VarDtWdthPrc, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrPrcrType, 0, ADDR VarProcrType, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrPrcsrCption, 0, ADDR VarPrcCption, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrPrcsrManfactr, 0, ADDR VarManfctrPrc, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrProcesrName, 0, ADDR VarNamProcesr, NULL, NULL
invoke [esi].IWbemClassObject.Get, ppProcesorObj, BstrVrsionPrcsr, 0, ADDR VarVersnPrc, NULL, NULL
invoke [esi].IWbemClassObject.GetMethod, dwClassSysSec, dwBstrSetSD, 0, ADDR dwWbmClsGetMethd, NULL
invoke [esi].IWbemClassObject.Put, dwSpawnInstnc, dwBstrPutSD, 0, ADDR WMISecDesVar, 0
invoke [esi].IWbemClassObject.Release, dwClassSysSec
invoke [esi].IWbemClassObject.Release, dwOutBndParmsSD
invoke [esi].IWbemClassObject.Release, dwSpawnInstnc
invoke [esi].IWbemClassObject.Release, dwWbmClsGetMethd
invoke [esi].IWbemClassObject.Release, ppOprtngSystmObj
invoke [esi].IWbemClassObject.Release, ppProcesorObj
invoke [esi].IWbemClassObject.SpawnInstance, dwWbmClsGetMethd, 0, ADDR dwSpawnInstnc
invoke [esi].IWbemLocator.ConnectServer, dwptrWbemLocator, bstrNameSpace, 0, 0, 0, 0, 0, 0, ADDR ptrIWbemServices    ;    This works correctly   
invoke [esi].IWbemLocator.Release, dwptrWbemLocator    ;   
invoke [esi].IWbemServices.CreateInstanceEnum, ptrIWbemServices, BstrOprtngSystm, lFlgsEnumOpSystm, NULL, ADDR ptrEnmWbmClsObjOS
invoke [esi].IWbemServices.ExecMethod, ptrIWbemServices, dwBstrSysSecClss, dwBstrGetSDMethd, 0, NULL, NULL, ADDR dwOutBndParmsSD, NULL
invoke [esi].IWbemServices.ExecMethod, ptrIWbemServices, dwBstrSysSecClss, dwBstrSetSD, 0, NULL, dwSpawnInstnc, NULL, NULL
invoke [esi].IWbemServices.ExecQuery, ptrIWbemServices, bstrWQL, bstrQryOprtngSystm, lFlgsOprtngSystm, NULL, ADDR ptrIEnmWbmOprtSystm   
invoke [esi].IWbemServices.ExecQuery, ptrIWbemServices, bstrWQL, bstrQryProcesr, lFlgsProcessor, NULL, ADDR ptrIEnmProcesrWbm   
invoke [esi].IWbemServices.GetObject, ptrIWbemServices, dwBstrSysSecrty, 0, NULL, ADDR dwClassSysSec, NULL
invoke [esi].IWbemServices.Release, ptrIWbemServices    ;   
invoke AddAccessAllowedAce, dwptrAcsCntList, ACL_REVISION, dwAccessMsk, ADDR UserCpySid
invoke ChckOperSysVersn    ;   
invoke ChckUsrSecurty    ;   
invoke CloseHandle, hLogFile
invoke CloseHandle, hLogFile
invoke CloseHandle, hPrevsLogFil    ;    This handle must be closed first, or DeleteFile fails.   
invoke CoCreateInstance, ADDR CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, ADDR IID_IWbemLocator, ADDR dwptrWbemLocator
invoke CoInitializeEx, NULL, COINIT_MULTITHREADED   
invoke CoInitializeSecurity, NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL
invoke ConvertSecurityDescriptorToStringSecurityDescriptor, dwptrSectyDescrp, SDDL_REVISION_1, DACL_SECURITY_INFORMATION, \
invoke CoQueryProxyBlanket, ptrIWbemServices, ADDR dwCurAuthntcnSrvc, ADDR dwPrxyAuthztnSrvc, ADDR dwPrncplNamOleChr, \
invoke CoSetProxyBlanket, ptrIEnmWbmOprtSystm, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_NONE, COLE_DEFAULT_PRINCIPAL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_L
invoke CoSetProxyBlanket, ptrIWbemServices, RPC_C_AUTHN_DEFAULT, RPC_C_AUTHZ_NONE, COLE_DEFAULT_PRINCIPAL, dwCurAuthntcnLvl, \
invoke CoUninitialize    ;    Must be called on this thread   
invoke CreateDirectory, lpDataDir, NULL
invoke CreateFile, lpLogInfo, 0C0000000h, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL   
invoke CreateFile, lpLogInfo, 0C0000000h, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL   
invoke CreateFile, lpLogInfo, 0C0000000h, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL   
invoke CreateFontIndirect, dwPtrFont   
invoke CreateWindowEx, ExtStyle, ADDR ClassName, ADDR AppName, WndStyle, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hIn
invoke DefWindowProc, hMainWnd, uMsg, wParam, lParam 
invoke DeleteDC, hTestDC   
invoke DeleteFile, dwPtrLogFil   
invoke DispatchMessage, ADDR msg
invoke DsplyWMICmplt    ;   Displays message on window at completion of TestWMIData.   
invoke DwtoA, dwAceFlags, ADDR AceFlagsval
invoke DwtoA, dwAceTypeNum, ADDR NumDesAceType   
invoke DwtoA, dwCountACEs, ADDR NumACLEntries   
invoke DwtoA, dwDesgndACENum, ADDR ACENumber   
invoke DwtoA, dwErIEnmOprtgSystm, ADDR RtnValCrtInsEnOS
invoke DwtoA, dwErrAddAcsAled, ADDR NumErrAddAllow
invoke DwtoA, dwErrCoQryPrxBln, ADDR ComErrNumQryProx   
invoke DwtoA, dwIdntClntAuthntcn, ADDR AuthIdentyProx   
invoke DwtoA, dwL2CacheSize, ADDR StrL2CacheSiz
invoke DwtoA, dwLenSecrtyDescrp, ADDR NumBytsSecDescrpt   
invoke DwtoA, dwLenStrCnvScDes, ADDR NumLenSecDesStr
invoke DwtoA, dwLenStrWrtnWide, ADDR LenWrttn   
invoke DwtoA, dwMaxClokSpd, ADDR StrMaxClkSped
invoke DwtoA, dwMinVrSrvcPck, ADDR StrSerPckMinVr
invoke DwtoA, dwOSNumProces, ADDR StrOSNumProcess
invoke DwtoA, dwOSstmCrtInsErr, ADDR ErNumCrtInstOS
invoke DwtoA, dwProxyCapblts, ADDR AuthIdentyProx   
invoke DwtoA, dwPrscrClkSpd, ADDR StrPrcrClkSped
invoke DwtoA, dwPrscrDtWdth, ADDR StrPrcrDtWdth
invoke DwtoA, dwptrACE, ADDR AddrAcePointr
invoke DwtoA, dwSizeBytesACE, ADDR AceSizeBytes   
invoke DwtoA, dwStasProcsrEnm, ADDR ProcsrErrCdNext
invoke DwtoA, dwStatsOSEnum, ADDR OSErrCodeNext
invoke DwtoA, dwVerMajSrvcPck, ADDR StrMajrVerSerPck
invoke DwtoA, ebx, ADDR TimeDate   
invoke DwtoA, ecx, ADDR TimeYear   
invoke DwtoA, ulNumRetCrtIns, ADDR ErNumCrtInstOS
invoke DwtoA, ulOSRetnd, ADDR RtrndObjsNum
invoke DwtoA, ulProcesrRetd, ADDR ProcsrRtdObjNum
invoke ExitProcess, eax
invoke GetAce, dwptrAcsCntList, dwNumItrtnsACE, ADDR dwptrACE
invoke GetAclInformation, dwptrAcsCntList, ADDR AclSizeInfo, SIZEOF ACL_SIZE_INFORMATION, AclSizeInformation
invoke GetCommandLine
invoke GetCurrentDirectory, 256, ADDR CurrentDirectory   
invoke GetDC, hTestWndw   
invoke GetLastError
invoke GetLastError
invoke GetMessage, ADDR msg, NULL, 0, 0
invoke GetModuleHandle, NULL
invoke GetSecurityDescriptorDacl, dwptrSectyDescrp, ADDR bDaclPresent, ADDR dwptrAcsCntList, ADDR bDACLDefaulted
invoke GetSecurityDescriptorLength, dwptrSectyDescrp
invoke GetSecurityDescriptorLength, dwptrSectyDescrp
INVOKE GetStockObject, 0    ;    WHITE_BRUSH       
invoke GetSystemTime, ADDR CurDateTime   
invoke IsValidSecurityDescriptor, dwptrSectyDescrp
invoke IsValidSecurityDescriptor, dwptrSectyDescrp
invoke LoadCursor, NULL, IDC_ARROW
invoke LoadIcon, NULL, IDI_WINICON
invoke memcpy, dwptrArrData, dwptrSectyDescrp, lLenSecDesrpt
invoke PostQuitMessage, NULL   
invoke RegisterClassEx, ADDR wc
invoke RtlZeroMemory, ADDR AceFlagsval, 16
invoke RtlZeroMemory, ADDR ACENumber, 16
invoke RtlZeroMemory, ADDR AcePtrSizeMsk, 256
invoke RtlZeroMemory, ADDR AceSizeBytes, 16
invoke RtlZeroMemory, ADDR AddrAcePointr, 32
invoke RtlZeroMemory, ADDR AuthIdentyProx, 32
invoke RtlZeroMemory, ADDR AuthIdentyProx, 32
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR AuthntcnImprsnInfo, 256
invoke RtlZeroMemory, ADDR BuildTypePropOS, 64
invoke RtlZeroMemory, ADDR ComErrNumQryProx, 16
invoke RtlZeroMemory, ADDR CoQryPrincplName, 128
invoke RtlZeroMemory, ADDR ErMesQryProxBlnkt, 128
invoke RtlZeroMemory, ADDR ErNumCrtInstOS, 16
invoke RtlZeroMemory, ADDR ErNumCrtInstOS, 16
invoke RtlZeroMemory, ADDR ErNumCrtInstOS, 16
invoke RtlZeroMemory, ADDR MajVernSrvcPck, 64
invoke RtlZeroMemory, ADDR MinrVerSrvcPck, 64
invoke RtlZeroMemory, ADDR NumACLEntries, 16
invoke RtlZeroMemory, ADDR NumBytsSecDescrpt, 16
invoke RtlZeroMemory, ADDR NumDesAceType, 16
invoke RtlZeroMemory, ADDR NumErrAddAllow, 16
invoke RtlZeroMemory, ADDR NumLenSecDesStr, 16
invoke RtlZeroMemory, ADDR NumOSObjsRtrnd, 128
invoke RtlZeroMemory, ADDR NumProcsrObjRtnd, 128
invoke RtlZeroMemory, ADDR OprSystmType, 32
invoke RtlZeroMemory, ADDR OSCrtInstncEnum, 128
invoke RtlZeroMemory, ADDR OSCrtInstncEnum, 128
invoke RtlZeroMemory, ADDR OSErrCodeNext, 32
invoke RtlZeroMemory, ADDR OSManufctrPrp, 64
invoke RtlZeroMemory, ADDR OSNumbrProceses, 64
invoke RtlZeroMemory, ADDR OSRprtWbemNxtEr, 128
invoke RtlZeroMemory, ADDR PrdctTypeOpStm, 64
invoke RtlZeroMemory, ADDR PrntDaclstrng, 256
invoke RtlZeroMemory, ADDR ProcsrErrCdNext, 32
invoke RtlZeroMemory, ADDR ProcsrRtdObjNum, 16
invoke RtlZeroMemory, ADDR ProcsrWbemNxtErr, 128
invoke RtlZeroMemory, ADDR ReprtACEProperts, 256
invoke RtlZeroMemory, ADDR ReprtLenSecDes, 128
invoke RtlZeroMemory, ADDR ReprtSizeAclList, 128
invoke RtlZeroMemory, ADDR ReptProcsrType, 128
invoke RtlZeroMemory, ADDR RprtCptnPropWinOS, 128
invoke RtlZeroMemory, ADDR RprtErrAddAce, 128
invoke RtlZeroMemory, ADDR RptBuildTypProp, 128
invoke RtlZeroMemory, ADDR RptL2CacheSiz, 128
invoke RtlZeroMemory, ADDR RptManfacturProcsr, 128
invoke RtlZeroMemory, ADDR RptMaxClckSped, 128
invoke RtlZeroMemory, ADDR RptMinSrvcPckVer, 128
invoke RtlZeroMemory, ADDR RptNamPrpProcesr, 256
invoke RtlZeroMemory, ADDR RptOSArchProp, 128
invoke RtlZeroMemory, ADDR RptOSManfctrPrp, 128
invoke RtlZeroMemory, ADDR RptOSNumProcess, 128
invoke RtlZeroMemory, ADDR RptOSProdctType, 128
invoke RtlZeroMemory, ADDR RptOSPropName, 192
invoke RtlZeroMemory, ADDR RptOSType, 128
invoke RtlZeroMemory, ADDR RptOSVersnProp, 128
invoke RtlZeroMemory, ADDR RptPrcrDatWdth, 128
invoke RtlZeroMemory, ADDR RptPrcsrArchtcr, 128
invoke RtlZeroMemory, ADDR RptPrcsrCaption, 192
invoke RtlZeroMemory, ADDR RptPrcsrClckSpd, 128
invoke RtlZeroMemory, ADDR RptProcsrVerson, 128
invoke RtlZeroMemory, ADDR RptSrvcPckMajrVer, 128
invoke RtlZeroMemory, ADDR RtnEnmNxtCrtInst, 128
invoke RtlZeroMemory, ADDR RtnEnmNxtCrtInst, 128
invoke RtlZeroMemory, ADDR RtnEnmNxtCrtInst, 128
invoke RtlZeroMemory, ADDR RtnValCrtInsEnOS, 16
invoke RtlZeroMemory, ADDR RtrndObjsNum, 16
invoke RtlZeroMemory, ADDR SizeWMISecDscrptr, 128
invoke RtlZeroMemory, ADDR StrACEType, 64
invoke RtlZeroMemory, ADDR StrCaptionProcsr, 64
invoke RtlZeroMemory, ADDR StrCptnPropOpSstm, 64
invoke RtlZeroMemory, ADDR StrDatWdthPrcr, 64
invoke RtlZeroMemory, ADDR StrL2CacheSiz, 32
invoke RtlZeroMemory, ADDR StrL2CacheSize, 64
invoke RtlZeroMemory, ADDR StrMajrVerSerPck, 16
invoke RtlZeroMemory, ADDR StrManufctrOS, 64
invoke RtlZeroMemory, ADDR StrManufctrProcsr, 64
invoke RtlZeroMemory, ADDR StrMaxClckSpeed, 64
invoke RtlZeroMemory, ADDR StrMaxClkSped, 32
invoke RtlZeroMemory, ADDR StrNamPrpProcesr, 128
invoke RtlZeroMemory, ADDR StrOSArchProp, 32
invoke RtlZeroMemory, ADDR StrOSBldTyp, 64
invoke RtlZeroMemory, ADDR StrOSName, 128
invoke RtlZeroMemory, ADDR StrOSNumProcess, 32
invoke RtlZeroMemory, ADDR StrOSVersion, 64
invoke RtlZeroMemory, ADDR StrPrcrArchtctr, 64
invoke RtlZeroMemory, ADDR StrPrcrClkSped, 32
invoke RtlZeroMemory, ADDR StrPrcrDtWdth, 32
invoke RtlZeroMemory, ADDR StrPrcsrCaption, 96
invoke RtlZeroMemory, ADDR StrPrcsrClckSped, 64
invoke RtlZeroMemory, ADDR StrPrcsrVersion, 64
invoke RtlZeroMemory, ADDR StrProcsrManfctr, 64
invoke RtlZeroMemory, ADDR StrProcsrType, 64
invoke RtlZeroMemory, ADDR StrSerPckMinVr, 16
invoke RtlZeroMemory, ADDR StrVersionProcsr, 64
invoke RtlZeroMemory, ADDR VersionPropOS, 32
invoke RtlZeroMemory, ADDR WbemNamProcesor, 32
invoke RtlZeroMemory, ADDR WbmNamOprtngSys , 32
invoke SafeArrayAccessData, dwptrSafeArry, ADDR dwptrArrData
invoke SafeArrayAccessData, dwptrSafeArry, ADDR dwptrSectyDescrp    ;    dwptrSectyDescrp is a pointer to a pointer to a Security Descriptor.   
invoke SafeArrayCreate, VT_UI1, 1 , ADDR SafeArrBnd
invoke SafeArrayUnaccessData, dwptrSafeArry
invoke SafeArrayUnaccessData, dwptrSafeArry
invoke SelectObject, hTestDC, hMesFont
invoke SetFilePointer, hLogFile, 0, NULL, FILE_BEGIN
invoke SetFilePointer, hLogFile, 0, NULL, FILE_CURRENT
invoke SetFilePointer, hLogFile, 0, NULL, FILE_CURRENT
invoke SetFilePointer, hLogFile, dwLogFilePtr, NULL, FILE_CURRENT
invoke SetUpLogFile    ;    This creates new directory, creates Log File, and writes preliminary information to it.   
invoke ShowWindow, hMainWnd, SW_SHOWNORMAL    ;    The application should specify SW_SHOWNORMAL the first time ShowWindow is called.   
invoke TestWMIData    ;    testing new WMI procedure to access Network Adapter information.       
invoke TextOut, hTestDC, 32, 64, ADDR szWMITstCmplt, dwLenTxtOut   
invoke TranslateMessage, ADDR msg
invoke UpdateWindow, hMainWnd
invoke UpdateWindow, hTestWndw   
invoke VariantInit, ADDR WMISecDesVar

... although, of course, I have no idea what ConvertSecurityDescriptorToStringSecurityDescriptor does ::)