Получение информации из SMBIOS - страница 5

 

Проблема в мт4, в мт5 работает отменно


 
Vitaly Muzichenko:

Проблема в мт4, в мт5 работает отменно

Разобрался.

В параметре функции указано 

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

Посмотрел, что такое PVOID

Почему-то этот тип обозначили long

Сменил на uchar и всё заработало

 

Итоговый код получился вот таким

//+------------------------------------------------------------------+
//|                                                      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, огромное спасибо!

 
Vitaly Muzichenko:

Итоговый код получился вот таким

---

@Edgar Akhmadeev, огромное спасибо!

Пользуйтесь.
Написал по паре примеров на c++ и документации MS за несколько часов, испытал на лабораторных форумчанах.
Флэшмоб такой. Сам-то не планирую применять.
 
Edgar Akhmadeev:

Написал код для чтения информации о железе (материнская плата и платформа) из SMBIOS. Используется, естественно, WinAPI. Может быть использован для привязки продуктов к железу. На мой взгляд, привязывать к чему-либо другому, кроме материнской платы, смысла нет. Диски, видеокарты - переменная величина.

Приветствую!

Собрал некоторую скудную статистику ~50 машин.

Оказалось, что UUID может быть у нескольких машин одинаковый, что сильно печалит. Почему так?

При этом, чаще всего, а именно на 6-ти машинах и моя 7-я, совпадает номер "03000200-0400-0500-0006-000700080009"

Попробую собрать статистику и о номере раздела диска С, хотя он легко меняется утилитами, поэтому в качестве привязки особо непригоден. 

 
Китайцы шалят. 
 

Не вижу надёжного выхода в таком случае. Остаётся только радоваться, что из 50 совпадают 7.

Кроме UUID материнки нет других надёжных привязок. Остальные либо опциональны (напр. серийный номер), либо легко подменяются, либо изменяются при форматировании, переустановке винды или лёгком апгрейде.

Разве что привязать к аппаратному ключу, но это уже слишком. Сойдёт только для софта в тысячи долларов.

 
Edgar Akhmadeev:

Не вижу надёжного выхода в таком случае. Остаётся только радоваться, что из 50 совпадают 7.

Кроме UUID материнки нет других надёжных привязок. Остальные либо опциональны (напр. серийный номер), либо легко подменяются, либо изменяются при форматировании, переустановке винды или лёгком апгрейде.

Разве что привязать к аппаратному ключу, но это уже слишком. Сойдёт только для софта в тысячи долларов.

У меня логика такая: если брали пробник программы, то запоминает железо и больше взять нельзя. Сейчас получается, если Коля взял пробник, то остальные в пролёте. Так что радость на этом окончилась.

Выход сейчас вижу один, делать привязку в диску С

 
Vitaly Muzichenko:

У меня логика такая: если брали пробник программы, то запоминает железо и больше взять нельзя. Сейчас получается, если Коля взял пробник, то остальные в пролёте. Так что радость на этом окончилась.

Выход сейчас вижу один, делать привязку в диску С

Не понял про остальных.

 
Vitaly Muzichenko:

У меня логика такая: если брали пробник программы, то запоминает железо и больше взять нельзя. Сейчас получается, если Коля взял пробник, то остальные в пролёте. Так что радость на этом окончилась.

Выход сейчас вижу один, делать привязку в диску С

Это если есть диск C, а не, например, /dev/sda

Причина обращения: