Retrieving information from SMBIOS - page 5

 

Problem in mt4, works fine in mt5


 
Vitaly Muzichenko:

Problem in mt4, works fine in mt5

Got it.

The function parameter reads

uint    GetSystemFirmwareTable(uint firmware_table_provider_signature,uint firmware_table_id,PVOID firmware_table_buffer,uint buffer_size);

I checked what PVOID is.

I have marked this type as long for some reason.

I changed it touchar and it works

 

The final code is as follows

//+------------------------------------------------------------------+
//|                                                      ProjectName |
//|                                      Copyright 2020, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property version   "1.0"
#property strict
#property copyright "(c)2021 Edgar Akhmadeev"
#property link      "https://www.mql5.com/en/users/dali"
// 2021.03.23

#import "kernel32.dll"
uint GetSystemFirmwareTable(uint firmware_table_provider_signature,uint firmware_table_id,uchar firmware_table_buffer,uint buffer_size);
uint GetSystemFirmwareTable(uint firmware_table_provider_signature,uint firmware_table_id,uchar &firmware_table_buffer[],uint buffer_size);
#import

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
union UUID16 {
   uchar b[16];
};
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class SMBIOS
{
private:
   static UUID16     uuid;

public:
   static string     Read();
};
static UUID16  SMBIOS::uuid;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
static string SMBIOS::Read()
{
   const uint SMBIOS_signature = ('R' << 24) + ('S' << 16) + ('M' << 8) + 'B';
// Query size of SMBIOS info.
   uint size = GetSystemFirmwareTable(SMBIOS_signature, 0, NULL, 0);
// Allocate memory for SMBIOS info
   uchar data[];
   if (ArrayResize(data, size) <= 0)
      return NULL;
// Retrieve the SMBIOS table
   uint written = GetSystemFirmwareTable(SMBIOS_signature, 0, data, size);
   if (written != size)
      return NULL;
   uint idx = 0;
   idx += 8;
// Process the SMBIOS info
   string sUUID;
   while (idx < size) {
      uchar type = data[idx];
      uchar len = data[idx + 1];
      if (len < 4)
         break;
      if (type == 1 && len >= 25) {
         idx += 8;   // offset to UUID
         // check if there is a valid UUID (not all 0x00 or all 0xff)
         bool all_zero = true, all_one = true;
         for (int i = 0; i < 16 && (all_zero || all_one); i++) {
            if (data[idx + i] != 0x00)
               all_zero = false;
            if (data[idx + i] != 0xFF)
               all_one = false;
         }
         if (!all_zero && !all_one) {
            uint idx2 = 0;
            // As off version 2.6 of the SMBIOS specification, the first 3 fields of the UUID are supposed to be encoded on little-endian. (para 7.2.1)
            sUUID  = StringFormat("%02x", uuid.b[idx2++] = data[idx + 3]);
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 2]);
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 1]);
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 0]);
            sUUID += "-";
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 5]);
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 4]);
            sUUID += "-";
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 7]);
            sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + 6]);
            sUUID += "-";
            for (int i = 8; i < 10; i++)
               sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + i]);
            sUUID += "-";
            for (int i = 10; i < 16; i++)
               sUUID += StringFormat("%02x", uuid.b[idx2++] = data[idx + i]);
         }
         return sUUID;
      } else
         idx += len;    // Skip formatted area
      do {
         int i = 0;
         while (idx + i < size && data[idx + i] != 0)
            ++i;
         idx += i + 1;
      } while (data[idx] != 0);
      ++idx;
   }
   return sUUID;
}

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
{
   string uuid = SMBIOS::Read();
   if (uuid == NULL) {
      Print("Error reading SMBIOS data!");
      return;
   }
   Print("UUID: ", uuid);
}
//+------------------------------------------------------------------+

---

@Edgar Akhmadeev, thank you very much!

 
Vitaly Muzichenko:

The final code is as follows

---

@Edgar Akhmadeev, thank you very much!

Take advantage of it.
Wrote a couple of examples in c++ and MS documentation in a few hours, tested it on the lab forum members.
Such a flash mob. Not planning to use them myself.
 
Edgar Akhmadeev:

Written code to read hardware information (motherboard and platform) from SMBIOS. WinAPI is used, of course. Can be used to bind products to hardware. In my opinion, it makes no sense to bind to anything other than the motherboard. Drives, video cards are variable.

Greetings!

Gathered some scant statistics on ~50 machines.

Turns out thatthe UUID can be the same on several machines, which is very frustrating. Why is this the case?

That said, more often than not, namely on 6 machines and my 7th, the number matches "03000200-0400-0500-0006-000700080009"

I'll try to gather statistics about the C disk partition number as well, although it's easily changed by utilities, so it's particularly unsuitable as a binding.

 
The Chinese are mischievous.
 

I don't see a reliable way out in such a case. We can only be glad that 7 out of 50 match.

Apart from the motherboard UUID, there are no other reliable entries. The others are either optional (e.g. serial number) or easily swapped out or changed when formatting, reinstalling the Windows or a minor upgrade.

Unless linked to a hardware key, but that is too much. Only good for software worth thousands of dollars.

 
Edgar Akhmadeev:

I don't see a reliable way out in such a case. We can only be glad that 7 out of 50 match.

Apart from the motherboard UUID, there are no other reliable entries. The others are either optional (e.g. serial number) or easily swapped out or changed when formatting, reinstalling the Windows or a minor upgrade.

Unless linked to a hardware key, but that is too much. That's only good for thousands of dollars worth of software.

My logic is this: if you took a sample program, it remembers the hardware and you can't take any more. Now it turns out that if Kolya took a proof copy, the rest of us are out of luck. So my joy is over.

The only way out now I can see is to bind to the C drive

 
Vitaly Muzichenko:

My logic is as follows: if you took a software sample, it remembers the iron and you can't take any more. Now it turns out that if Kolya took the trial, then the rest of us are out. So my joy is over.

I see the only way out now is to bind to the C drive.

I don't understand about the others.

 
Vitaly Muzichenko:

My logic is as follows: if you took a software sample, it remembers the iron and you can't take any more. Now it turns out that if Kolya took the trial, then the rest of us are out. So my joy is over.

I see the only way out now is to bind to the C drive.

This is if there is a C drive and not, for example, /dev/sda