Results 1 to 21 of 21

Thread: [VB6] Read SMBIOS info w/o WMI

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,033

    Lightbulb [VB6] Read SMBIOS info w/o WMI

    Summary

    WMI is a bulky service with a COM-based API that was meant to help computer technicians write administrative maintenance scripts. It isn't meant for application use and if a user stops the service for security reasons relying on it can leave your program high and dry.

    One of the things people often fall back on WMI for is system information, particularly information retrieved from the SMBIOS data block. That's usually just fine, since it seldom makes sense for applications to use such information anyway, so WMI admin scripts usually more than suffice.

    But some people still want to do this, as unreliable as the SMBIOS info is. So here is an approach that bypasses WMI to get the same information.


    The Code

    This is a VB6 collection class SmbiosInformation and a small item class SmbiosItem. It requires no 3rd party libraries and makes use of GetSystemFirmwareTable() in Kernel32.dll to retrieve the raw data. Once retrieved it browses (some would say "parses" but we really aren't) the compound structure for data items.

    It is important to note that this API entrypoint did not become available until Windows Server 2003 SP1 and Windows XP Professional 64-bit SP3. So effectively none of this applies to pre-Vista versions of Windows, all of which are officially unsupported now anyway.


    Limitations, Opportunity

    SmbiosInformation is not exhaustive in its browsing and reporting, returning only a subset of the available information.

    You could choose to add more items, delete items you do not care about, or change the way some data items are reported. For example the "ChassisType" item is currently reported as a Byte value from 0-127 as stored in the raw data block, but you could translate those to friendly String values instead.

    None of this seems very close to "perfect." Depending on the machine you might get various serial number values or you might get an empty String or a String of all 0 characters. You might get "BaseBoardxxxx" items or you might get none of them if the machine doesn't provide them. There is a theoretical way to detect HyperThreading capability, but it fails on some systems, probably because the BIOS is reporting many values according to how it has them set during boot. On some machines the BIOS version comes back as 0.0, which isn't correct.

    Lots of String items come back as "To Be Filled By O.E.M." instead of a useful value, others come back as empty Strings.

    Some kinds of data can be complex. CPUs are reported by socket, and a given machine may have more than one socket and CPU chip, so SmbiosInformation reports those as sub-collections of data, one per socket. There can be multiple Memory Array entries in the raw data, so SmbiosInformation just sums them.


    Helpful References

    I found SMBIOS Demystified helpful but really ended up even more confused. It could have been written far better, but the topic really is confusing so I can't fault the author too much. I'm sure not volunteering to do so!

    But he did provide a link to System Management BIOS where you can download PDFs of different versions of the actual specs. This is critical information if you want to expand on what the provided code does.


    Demo

    I have attached a ZIP archive containing these classes and a simple Project1 program that uses them.

    The demo gets the information, and then reports results two ways:

    • An initial MsgBox presenting a few values retrieved by key (Name).
    • A full dump in a sortable ListView, retrieved by enumeration.


    Name:  sshot.png
Views: 2120
Size:  23.4 KB

    Full Dump


    Useful?

    You be the judge. Results are highly variable from machine to machine that I tested. If it is any comfort, if you can't get it this way you can't get it via WMI either.

    Of course WMI covers lots of other things too - such as letting people get remote access to your machine! It is not a safe thing to have running at all, but Windows itself is becoming more and more dependent on it. Even some of the administrative Control Panel applets need the WMI Service running to work now.
    Attached Files Attached Files
    Last edited by dilettante; Jan 7th, 2015 at 02:47 PM.

  2. #2
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by dilettante View Post
    Useful?
    Yes, higlhy - but code does not run, at least in some systems tested.

    Error 424 in ShowSubSet routine at line
    Code:
        With SBI.Item("CentralProcessors").Value
            SubMsg = "Num CPU sockets = " & CStr(.Count) & vbNewLine 'Error 424 in this line...
    Quickly looked that, and for some reason CentralProcessors value is empty

    Code:
        '<Quick and dirty fix to make code run.>
        If IsEmpty(SBI.Item("CentralProcessors").Value) Then
            SBI.Item("CentralProcessors").Value = 1
        End If
        On Error Resume Next
        '</Quick and dirty fix to make code run.>
    
        With SBI.Item("CentralProcessors").Value 'With - End With sequence does not work at all -> does not list Centralprocessor collection items...
            SubMsg = "Num CPU sockets = " & CStr(.Count) & vbNewLine
    Attached Images Attached Images   
    Last edited by Tech99; Sep 22nd, 2016 at 02:53 PM.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,033

    Re: [VB6] Read SMBIOS info w/o WMI

    Perhaps you missed this comment?

    Code:
    'For IDE testing you should have the Break on Unhandled Errors option
    'set, because the Item property [Get] uses exception handling.
    The way around that is to move the classes into a DLL and compile it separately, but most of the script kiddies around here are afraid of "dependencies."

  4. #4
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    I noticed your comment, error raised when compiled to exe, then looked and run code in IDE.

  5. #5

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,033

    Re: [VB6] Read SMBIOS info w/o WMI

    If you read through FetchAndBrowseSMBiosData() you should see that as long as GetSystemFirmwareTable() does not fail then the CentralProcessors Collection should always get added to the Outer Collection as the very last item.

    So even if there are no (0) entries in CentralProcessors it should still be there, with .Count = 0. The Item just before that should be PhysicalMemoryDevices.

    You seem to be missing those and other Items. I can't see how this is possible no matter what your BIOS provides in the way of data, and I don't see a bug.

    It seems like you must have On Error Resume Next in your calling code or something, masking an exception. Because the only way I can see how CentralProcessors would be missing is if a bug in there someplace threw an exception.

  6. #6
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Since Tech99 had an HP, and my work laptop is an HP, I compiled the code and ran it to see if I had a similar issue, but got an array out of bounds error instead.
    Running in the IDE I finally found the issue (I should have been sleeping instead of debugging though, but couldn't stop).
    Code:
                            Case 3 'System Enclosure or Chassis (Type 3)
                                AddStringValue "ChassisManufacturer", Struct + &H4&
                                'Next item has values such as:
                                '   1 – Other
                                '   2 – Unknown
                                '   3 – Desktop
                                '   4 – Low Profile Desktop
                                '   5 – Pizza Box
                                '   6 – Mini Tower
                                '   7 – Tower
                                '   8 - Portable
                                '   9 - Laptop
                                '  10 - Notebook
                                '... and many more.
                                AddByte "ChassisType", Buffer(Struct + &H5&) And &H7F
                                AddBoolean "ChassisLockPresent", Buffer(Struct + &H5&) And &H80 <> 0
                                AddStringValue "ChassisVersion", Struct + &H6&
                                AddStringValue "ChassisSerialNumber", Struct + &H7&
                                AddStringValue "ChassisAssetTag", Struct + &H8&
                                If SpecVer >= 2007 Then
                                    AddStringValue "ChassisSKU", Struct _
                                                               + &H15& _
                                                               + CLng(Buffer(Struct + &H13&)) * CLng(Buffer(Struct + &H14&))
                                End If
    My major, minor number was 2, 7 so SpecVer = 2007.
    Your code is making the assumption that if the SpecVer is 2007 or greater then the ChassisSKU value exists in the type 3 structure.
    But based on my bios I have to assume that it can exist in the type 3 structure, but doesn't have to.
    The type 3 structure on my machine is 17 bytes &H11 and your code is indexing beyond the data portion of the structure (&H13, &H14) into the first string following the structure and getting a rather large bogus index, so you'll need to check the length value to make sure the ChassisSKU value is present in the structure, before trying to calculate an offset to it.

    p.s. After I added the length test to avoid the bad index calculation, the code worked fine on this machine, didn't see the issue that tech99 had.

    Details extracted from Watches window for Buffer array
    Code:
    Watch : - : Buffer :  : Byte(0 to 1631) : SmbiosInformation
        : Buffer(0) : 0 : Byte : SmbiosInformation 
        : Buffer(1) : 2 : Byte : SmbiosInformation          major 2
        : Buffer(2) : 7 : Byte : SmbiosInformation          minor 7    SpecVer = 2007
        : Buffer(3) : 39 : Byte : SmbiosInformation
        : Buffer(4) : 88 : Byte : SmbiosInformation
        : Buffer(5) : 6 : Byte : SmbiosInformation
    
    shorten text output
    00h    : Buffer(279) : 3         Case 3 'System Enclosure or Chassis (Type 3)
    01h    : Buffer(280) : 17        Length
    02h    : Buffer(281) : 17        Handle (2 bytes)
    03h    : Buffer(282) : 0  
    04h    : Buffer(283) : 1  	 Manufacture
    05h    : Buffer(284) : 10  	 Type
    06h    : Buffer(285) : 0 	 Version
    07h    : Buffer(286) : 2  	 Serial Number
    08h    : Buffer(287) : 3  	 Asset Tag Number
    09h    : Buffer(288) : 3  	 Boot-up State
    0Ah    : Buffer(289) : 3  	 Power Supply State
    0Bh    : Buffer(290) : 1  	 Thermal State
    0Ch    : Buffer(291) : 1  	 Security Status
    0Dh    : Buffer(292) : 0         OEM-defined (4 bytes)
    0Eh    : Buffer(293) : 0  
    0Fh    : Buffer(294) : 0  
    10h    : Buffer(295) : 0  
    11h    : Buffer(296) : 72   'H   String 1 (Manufacture)
    12h    : Buffer(297) : 101  'e
    13h    : Buffer(298) : 119  'w   <= using for n Contained Element Count
    14h    : Buffer(299) : 108  'l   <= using for m Contained Element Record Length
    Last edited by passel; Sep 26th, 2016 at 05:35 AM.

  7. #7
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by dilettante View Post
    If you read through FetchAndBrowseSMBiosData()...
    Yes - sure i looked code, here is the screenshot. Code i have added is displayed here.
    Code:
    AddCollection "CentralProcessors", CentralProcessors
    Works OK, but AddStringValue gets out of bounds error, when ChassisSKU is added.
    Code:
     SmbiosItem.Value = Trim$(Strings(Buffer(StartAt) - 1))
    Struct value is 237, both values in buffer positions are zero

    Yes, the issue is exactly same than what Passel reported. Sorry for the previous false information.
    Attached Images Attached Images    
    Last edited by Tech99; Sep 26th, 2016 at 01:00 PM.

  8. #8
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Perhaps the same cause, but actually slightly different results.
    In my case it was calculating a value to find the SKU String ID and was indexing beyond the end of the Buffer array trying to fetch the String ID.
    In your case, it calculated a value inside the buffer array and got a "String ID" value that wasn't valid and indexed outside the bounds of the Strings array.

    Actually, since you have 22 bytes in your structure, then it seems there should be a SKU string ID, and 5 should be it.
    So, you would expect at least 5 strings (and since that is the last field, then probably only 5 strings) to follow the structure.
    You can see in your Watch Window three strings (two full ones, one only containing a single space, and the first two characters of a third). If you scrolled down you should check to see if there were five strings.
    I'm wondering if the "string" containing only a single space character threw off the stringBlob to string array process.
    Of course, I'm assuming there were actually five strings after the structure.

    So, that means your issue is not the same as mine. I had a truncated type 3 structure (only 17 bytes) so the SKU extraction shouldn't have been attempted, whereas you have a full structure (22 bytes) so have a SKU String ID, but possibly a string processing glitch.

    Take a look at your buffer array starting at (259) and show the range down to where you have two 0 bytes in a row, and see if you have 5 null terminated strings between 259 and where the double nulls are found after that in the buffer array.
    Last edited by passel; Sep 26th, 2016 at 05:20 PM.

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Aside,
    I was wondering about the purpose of this line in the sub below.
    SmbiosItem.Value = GetLong(StartAt)

    It doesn't seem necessary, and I commented it out with no ill effects.
    I'm kinda assuming Sub AddLongValue was the "template" for AddStringValue, and the line was left in by mistake.
    Code:
    Private Sub AddStringValue( _
        ByVal Name As String, _
        ByVal StartAt As Long, _
        Optional ByVal Collection As Collection)
        Dim SmbiosItem As SmbiosItem
        
        If Collection Is Nothing Then Set Collection = Outer
        
        Set SmbiosItem = New SmbiosItem
        SmbiosItem.Name = Name
        SmbiosItem.Value = GetLong(StartAt)                      '<= not needed =======
        If Buffer(StartAt) > 0 Then
            SmbiosItem.Value = Trim$(Strings(Buffer(StartAt) - 1))
        Else
            SmbiosItem.Value = vbNullString
        End If
        Collection.Add SmbiosItem, Name
    End Sub

  10. #10
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Looked with fresh eyes this. Actually value at StartAt postition - 1 so 5-1, four items, and there are those, but gets out of bounds when casting array to variant. Some kind of internal VBA bug?
    Attached Images Attached Images  
    Last edited by Tech99; Sep 27th, 2016 at 12:51 AM.

  11. #11
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    I was on an older cheap Acer laptop (I guess it is noted as NoteBook type in the Bios), which is actually the one I'm on now.
    It has gotten really sluggish as of late, and it has 3GB of memory on board.
    I was thinking I should add more memory and since I knew the dilettante's code displayed maximum amount of memory the board supports, I thought I'd give it a quick run.
    Downloaded the zip from this thread, built the executable, and ran it, but it failed in the ShowSubset Sub with an "Run-time error '5': Invalid procedure call or argument".

    Running in the IDE identified this statement as causing the exception.
    Code:
                    SubMsg = SubMsg _
                           & "CPU socket " & CStr(CpuSocketIndex - 1) & ":" & vbNewLine _
                           & vbTab & "ProcessorSocketDesignation = " _
                                   & CStr(.Item("ProcessorSocketDesignation").Value) & vbNewLine _
                           & vbTab & "ProcessorSocketPopulated = " _
                                   & CStr(.Item("ProcessorSocketPopulated").Value) & vbNewLine _
                           & vbTab & "ProcessorStatus = " _
                                   & CStr(.Item("ProcessorStatus").Value) & vbNewLine _
                           & vbTab & "ProcessorCurrentMHz = " _
                                   & CStr(.Item("ProcessorCurrentMHz").Value) & vbNewLine
                                   SubMsg = SubMsg _
                           & vbTab & "ProcessorCoreCount = " _
                                   & CStr(.Item("ProcessorCoreCount").Value) & vbNewLine _
                           & vbTab & "ProcessorSerialNumber = """ _
                                   & CStr(.Item("ProcessorSerialNumber").Value) & """" & vbNewLine
    Commenting out the concatenations and uncommenting them one by one isolated the problem to this one.
    Code:
                           & vbTab & "ProcessorCoreCount = " _
                                   & CStr(.Item("ProcessorCoreCount").Value) & vbNewLine _
    "ProcessorCourCount" didn't exist in the Collection.
    I looked to see where it was added which is this code in sub FetchAndBrowseSMBiosData
    Code:
    '...
                                    If SpecVer >= 2003 Then
                                        AddStringValue "ProcessorSerialNumber", Struct + &H20&, CentralProcessor
                                        AddStringValue "ProcessorAssetTag", Struct + &H21&, CentralProcessor
                                        AddStringValue "ProcessorPartNumber", Struct + &H22&, CentralProcessor
                                        If SpecVer >= 2005 Then
                                            'When not available these values are &H0:
                                            AddByteValue "ProcessorCoreCount", Struct + &H23&, CentralProcessor
                                            AddByteValue "ProcessorCoreEnabled", Struct + &H24&, CentralProcessor
                                            AddByteValue "ProcessorThreadCount", Struct + &H25&, CentralProcessor
    '...
    This is the only place it is added to the collection, and my SpecVer happens to be 2004 on the machine, so the lines in the >= 2005 block are not executed.

    The comment says "When not available these values are &H0", but doesn't have an else case to add the 0's to the collection.
    I don't know how you want to address this in this case, i.e. to add an else case here, or do a SpecVer test in the ShowSubSet to not show values that weren't added to the collection.

    p.s. I just added an Else block for now.
    Code:
                                    If SpecVer >= 2003 Then
                                        AddStringValue "ProcessorSerialNumber", Struct + &H20&, CentralProcessor
                                        AddStringValue "ProcessorAssetTag", Struct + &H21&, CentralProcessor
                                        AddStringValue "ProcessorPartNumber", Struct + &H22&, CentralProcessor
                                        If SpecVer >= 2005 Then
                                            'When not available these values are &H0:
                                            AddByteValue "ProcessorCoreCount", Struct + &H23&, CentralProcessor
                                            AddByteValue "ProcessorCoreEnabled", Struct + &H24&, CentralProcessor
                                            AddByteValue "ProcessorThreadCount", Struct + &H25&, CentralProcessor
                                            TempInteger = GetInteger(Struct + &H26&)
                                            AddBoolean "Processor64bitCapable", TempInteger And &H4 <> 0, CentralProcessor
                                            AddBoolean "ProcessorMulticore", TempInteger And &H8 <> 0, CentralProcessor
                                            AddBoolean "ProcessorExecuteProtection", TempInteger And &H20 <> 0, CentralProcessor
                                            AddBoolean "ProcessorEnhancedVirtualization", TempInteger And &H40 <> 0, CentralProcessor
                                        Else
                                            AddString "ProcessorCoreCount", "Unspecified", CentralProcessor
                                            AddString "ProcessorCoreEnabled", "Unspecified", CentralProcessor
                                            AddString "ProcessorThreadCount", "Unspecified", CentralProcessor
                                            AddString "Processor64bitCapable", "Unspecified", CentralProcessor
                                            AddString "ProcessorMulticore", "Unspecified", CentralProcessor
                                            AddString "ProcessorExecuteProtection", "Unspecified", CentralProcessor
                                            AddString "ProcessorEnhancedVirtualization", "Unspecified", CentralProcessor
                                        End If
                                    End If
    Last edited by passel; Sep 27th, 2016 at 05:37 AM.

  12. #12

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,033

    Re: [VB6] Read SMBIOS info w/o WMI

    Good finds.

    Yes the extra, silly, pointless looking line in AddStringValue() is probably left over from a refactoring I did early on. It seems like the "template" theory fits. Just delete it.

    The code was never tested (by me) on a commercial machine likely to have ChassisSKU. I'm not sure I ever tested a 2.7+ BIOS at all so the Type 3 code for that item is probably completely untested.

    I think this might be the check required:

    Code:
    If SpecVer >= 2007 Then
        TempLong = &H15& _
                 + CLng(Buffer(Struct + &H13&)) * CLng(Buffer(Struct + &H14&))
        If TempLong + 1 <= Length Then
            AddStringValue "ChassisSKU", Struct + TempLong
        End If
    End If
    There TempLong becomes the location within the Type 3 structure of the base-0 offset to a Byte that holds the "string number" of the ChassisSKU string. Length is a base-1 value for the fixed portion of the struct.

    Does that look right to you?

    However according to the SMBIOS Spec document this should always be there for a 2.7+ BIOS.

    Very annoying not to be able to test this. I don't have any 2.7 BIOS systems at hand.
    Last edited by dilettante; Sep 27th, 2016 at 06:10 AM.

  13. #13
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by Tech99 View Post
    Looked with fresh eyes this. Actually value at StartAt postition - 1 so 5-1, four items, and there are those, but gets out of bounds when casting array to variant. Some kind of internal VBA bug?
    Edit: No it is not a bug in VBA.

    All other calls to AddString function return one array item, but ChasisSKU returns 4, which are unable to cast as non array variant value.

  14. #14
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by Tech99 View Post
    Edit: No it is not a bug in VBA.

    All other calls to AddString function return one array item, but ChasisSKU returns 4, which are unable to cast as non array variant value.
    I'm not sure what you're saying.
    Most every structure is followed by a number of null terminated strings.
    The structure references those strings using a 1 based number, (1,2,3,4...).

    dilettante's code extracts all the strings following the structure into one string, and the splits it into an array of strings (which is 0 based). So, dilettante's code subtracts 1 from the structure's string index (I called it string ID in my earlier posts) to access the strings in the array associated with that structure.
    So, according to the buffer you posted (what we could see of it), the string the SKU was going after would be the 5th string, which would be index 4 in an array (0 to 4) of String.

    Are you saying that you verified there were only four null terminated strings after the structure?

  15. #15
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by passel View Post
    I'm not sure what you're saying.
    Forget my previous post, it was a brain fart - assumption made in a hurry.

    Array is zero indexed so Strings array has 0 to 3 bounds in chassis sku.

  16. #16
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by dilettante View Post
    ...

    The code was never tested (by me) on a commercial machine likely to have ChassisSKU. I'm not sure I ever tested a 2.7+ BIOS at all so the Type 3 code for that item is probably completely untested.

    I think this might be the check required:

    Code:
    If SpecVer >= 2007 Then
        TempLong = &H15& _
                 + CLng(Buffer(Struct + &H13&)) * CLng(Buffer(Struct + &H14&))
        If TempLong + 1 <= Length Then
            AddStringValue "ChassisSKU", Struct + TempLong
        End If
    End If
    There TempLong becomes the location within the Type 3 structure of the base-0 offset to a Byte that holds the "string number" of the ChassisSKU string. Length is a base-1 value for the fixed portion of the struct.

    Does that look right to you?

    However according to the SMBIOS Spec document this should always be there for a 2.7+ BIOS.

    Very annoying not to be able to test this. I don't have any 2.7 BIOS systems at hand.
    Well, all I can say is that my HP from work is 2.7 according to what was extracted (I posted the relevant values from buffer in my post), and the type 3 data shows that the SKU wasn't included (relevant values from buffer also shown in my post).
    I've found that it is hard to count on a fair amount of things being consistent with Windows and Hardware vendor implementations, which is probably the most frustrating part of the job.

    The proposed fix doesn't look right to me, given the fact that the bios information in at least one test case (my work HP) shows that the SKU field might not be there.
    Your fix would prevent it from indexing past the end of buffer if it happened to calculate a bad value that exceeded the length of buffer, but since it is getting values (offset 13h and 14h) that are outside the structure it is possible it might get random values that happen to calculate an offset that is within the bounds of buffer and you would try grab some other random value and use it as an index into your string array which I assume the majority of the time would fail with an out of bounds error on that array.

    The fix, in my opion, would be to read the structure length (the byte after the structure type) and make sure it is 16h or greater (the minimum length of a type 3 structure with SKU should be 16h, which it looks like the case that Tech99 is showing in post #7.

    He mentions the struct value is 237 and we can see from the buffer watch that the type 3 structure ends at 258 (so is 16h in length). The m and n values are 0.
    The number in buffer(258) is 5, which should mean use the 5th string, but he's also showing in Post #10 that apparently only 4 strings were extracted.

    I would have liked to have seen more of the raw buffer array from (259 to wherever the double nulls occur), but since he blotted out the string values in post #10, I'm sure he wouldn't want to display the actual raw byte values for those strings either.
    But if you (Tech90) could show the raw buffer (but blotting out the non-zero bytes you don't want to expose), I would like to verify there are actually only 4 strings, not 5 strings following the structure.

    If there are only 4 strings, then it would seem the SKU field is incorrect so there is a bug in the information.
    If there are actually 5 strings, then that would indicate some condition exist that caused the strings extractor to not work correctly.
    Last edited by passel; Sep 27th, 2016 at 08:25 AM.

  17. #17
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Quote Originally Posted by Tech99 View Post
    Forget my previous post, it was a brain fart - assumption made in a hurry.

    Array is zero indexed so Strings array has 0 to 3 bounds in chassis sku.
    See the last part of my previous post. I would like to verify from the raw values (possibly you'll want to obscured the non-zero bytes to protect sensitive info) that follow the type 3 structure to see if there are really only four strings or whether there are five strings.
    Four would seem to indicate a bug in the bios data (the SKU value is invalid).
    Five would seem to indicate a bug in the strings extraction code (which is hard to see why that would be the case as it is pretty straight forward code).

  18. #18
    Fanatic Member
    Join Date
    Apr 2015
    Location
    Finland
    Posts
    672

    Re: [VB6] Read SMBIOS info w/o WMI

    Thought i included most relevant part of buffer, but here it is a bit more complete. There is double null at 298-299, so clearly only four items, seems to bug in bios data then.
    Attached Images Attached Images  
    Last edited by Tech99; Sep 27th, 2016 at 09:11 AM.

  19. #19
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    I would agree.
    I guess the code will have to add a function or property to get the value (maybe it is already) and trap an out of bound access to the array of strings. Stupid Bios Data...

  20. #20

    Thread Starter
    PowerPoster
    Join Date
    Feb 2006
    Posts
    21,033

    Re: [VB6] Read SMBIOS info w/o WMI

    Well what fun! Clearly we can't rely on a lot so to be thorough a ton of exception handling and bounds checking and such would be required.

    To patch around this case I'm thinking maybe:

    Code:
    If SpecVer >= 2007 Then
        If Length > &H14& Then
            'Contained Element n and m are present:
            TempLong = &H15& _
                     + CLng(Buffer(Struct + &H13&)) * CLng(Buffer(Struct + &H14&))
            If Length > TempLong Then
                'SKU Number string number is present:
                AddStringValue "ChassisSKU", Struct + TempLong
            End If
        End If
    End If
    Supplemented by this change:

    Code:
    Private Sub AddStringValue( _
        ByVal Name As String, _
        ByVal StartAt As Long, _
        Optional ByVal Collection As Collection)
        Dim SmbiosItem As SmbiosItem
        Dim StringIndex As Long
    
        If Collection Is Nothing Then Set Collection = Outer
    
        Set SmbiosItem = New SmbiosItem
        SmbiosItem.Name = Name
        If Buffer(StartAt) > 0 Then
            StringIndex = Buffer(StartAt) - 1
            If StringIndex <= UBound(Strings) Then
                SmbiosItem.Value = Trim$(Strings(StringIndex))
            Else
                'String number was beyond the end of the list of values:
                Exit Sub 'Don't add it at all, not even an empty String value.
            End If
        Else
            SmbiosItem.Value = vbNullString
        End If
        Collection.Add SmbiosItem, Name
    End Sub
    That looks like it should catch some of this.

  21. #21
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    5,984

    Re: [VB6] Read SMBIOS info w/o WMI

    Looks like it to me too.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width