Subject Re: Computer serial number
From Marc VdB <dbase@dbase.de>
Date Sun, 21 Apr 2024 18:46:39 +0200
Newsgroups dbase.getting-started
Attachment(s) getbiosdata.cc

Thanks for the data, Mervyn. It shows a hack of a bending of the
specifications but is still conform :-)
And makes my previous code buggy.

Please try the revised version (1.2)

KR

>
> My pleasure.  BIOS.TXT is attached.
>
> Mervyn.



/****************************************************************************
        
        Version 1.0 - Marc VdB        20-04-2024  (get_serial)
        Version 1.1 21-04-2024 (showall)
        Version 1.2 21-04-2024 Bugfix for Mervyns old BIOS :-)
                                                                  (ok, the bug could have appeared in any BIOS)
        
   Class to retrieve Bios data.
        For now, it extracts only the serial number of the Bios (if there is one,
        some of the older Bioses don't have one, in this case ERROR is returned)

   Notes:         The specification of the Bios-Table-Data can be found here:
        https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.3.0.pdf
        
        with the specs, one could add more methods like : get_biosdate() if needed
                                
   Dependencies: None

   Example of use:         set proc to getbiosdata.cc
                     o = new BiosData()
                     cserial = o.get_serial()
                                                        
*****************************************************************************/

Class BiosData

        this.serial = "Not defined"
        this.smblen = 0
        this.smbbuf = " "
        // RSMB = 0x52534D42
        extern CUINT GetSystemFirmwareTable(cuint,cuint,cptr,cuint) kernel32
        
        function get_serial()
        
                local offset,headerlength,strnr,i,startpoint
                offset = 8
                if not this.fillbuffer() ; return "ERROR" ; endif  //couldn't get the data

                /* to be used for testcases
                        f= new file()
                        f.open("bios.txt")
                        x=f.gets()
                        f.close()
                        this.smbbuf=Space(len(x))
                        this.smblen = len(x)/2
                        for i = 0 to len(x)/2-1
                                this.smbbuf.setbyte(i,htoi(substr(x,i*2+1,2)))
                        endfor
                */
                
                // search the first datablock with type 01
                
                do while true
                        if this.smbbuf.getbyte(offset) = 1
                                exit        // we found the datablock with serial number
                        endif
                        headerlength = this.smbbuf.getbyte(offset+1)
                        headerlength = iif(headerlength=0,-2,headerlength)
                        offset = offset + headerlength                
                        
                        // find the next datablock, after the 0x0000
                
                        do while true
                                offset = this.getnull(offset)
                                if offset = 0 ; this.serial = "ERROR" ; return "ERROR" ; endif // no serial
                                // we are looking for a second Null
                                offset++
                                if this.smbbuf.getbyte(offset) = 0
                                        offset++
                                        exit // now offset is pointing to the next datablock and we start over
                                endif
                        enddo
                enddo
                
                // we have the offset of the serialnumber datablock get its headerlength
                
                headerlength = this.smbbuf.getbyte(offset+1)
                
                // and get the nr of the serial string
                
                strnr = this.smbbuf.getbyte(offset+7)
                if strnr = 0 ; this.serial = "ERROR" ; return "ERROR" ; endif // no serial
                
                // jump to the nonformatted data
                
                offset += headerlength
                
                // Now get the offset of the nth string

                for i = 1 to strnr
                        startpoint = offset
                        offset=this.getnull(offset)
                        if offset = 0 ; this.serial = "ERROR" ; return "ERROR" ; endif // no serial
                        offset++
                endfor
                
                // We have the startpoint and the endpoint of the serialnumber

                this.serial = ''
                for i=startpoint to offset-1
                        this.serial += chr(this.smbbuf.getbyte(i))
                endfor
                
                this.smbbuf = " "
                
        return this.serial
        
        function showall(tofile)
                local a,b,c
                if not this.fillbuffer()
                        ? "ERROR"
                        return
                endif  //couldn't get the data
                b= "" ; c =""
                for i = 0 to this.smblen
                        a = this.smbbuf.getbyte(i)
                        c+=itoh(a,2)
                        b+=iif(a>31,chr(a),"#")
                endfor
                if tofile
                        a = new file()
                        a.create("BIOS.TXT","W")
                        a.puts(b)
                        a.puts(c)
                        a.close()
                else
                        ? b ; ? c        
                endif
        return
        
        function getnull(c)                
                do while c<this.smblen        // till the end of the buffer
                        if this.smbbuf.getbyte(c) = 0
                                return c  
                        else
                                c++
                        endif
                enddo
        return 0
        
        function fillbuffer()
                this.smblen = 0        
                // first get the length of the buffer
                this.smblen = GetSystemFirmwareTable(0x52534D42,0,this.smbbuf,this.smblen)
                if this.smblen = 0 ; this.serial = "ERROR" ; return false ; endif                
                // then get the buffer itself                
                this.smbbuf = replicate(chr(0),this.smblen+1)
                this.smblen = GetSystemFirmwareTable(0x52534D42,0,this.smbbuf,this.smblen)
                if this.smblen = 0 ; this.serial = "ERROR" ; return false ; endif
        return true
        
endclass