SMBIOSから情報を取得する - ページ 5

 

mt4では問題なし、mt5では問題なし。


 
Vitaly Muzichenko:

mt4では問題なし、mt5では問題なし。

了解です。

関数パラメータは次のとおりです。

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

PVOIDとは 何か調べてみました。

このタイプはなぜかロングと 表記しています。

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);
}
//+------------------------------------------------------------------+

---

エドガー・アフマディエフ さん、ありがとうございました。

 
Vitaly Muzichenko:

最終的なコードは以下の通りです。

---

エドガー・アフマディエフ さん、ありがとうございました。

それを利用する。
数時間でc++とMSのドキュメントでいくつかの例を書き、研究室のフォーラムのメンバーでテストしました。
そんなフラッシュモブ。自分で使う予定はない。
 
Edgar Akhmadeev:

SMBIOSからハードウェア情報(マザーボード、プラットフォーム)を読み取るコードを書きました。もちろんWinAPIを使用します。製品とハードウェアの結合に使用できます。私見ですが、マザーボード以外のものにバインドするのは意味がないと思います。ドライブ、ビデオカードは可変です。

ごあいさつ

50台のマシンについて、わずかな統計情報を収集しました。

UUIDが複数のマシンで同じになる可能性があることが判明し、非常に悔しい 思いをしています。なぜ、そのようなことになるのでしょうか。

しかし、6台のマシンと7台目のマシンでは、"03000200-0400-0500-0006-000700080009 "と一致することが多いのですが、どうでしょう?

Cディスクのパーティション番号も統計を取ってみますが、ユーティリティで簡単に変更されてしまうので、特に縛りとしては不向きです。

 
中国人はお茶目です。
 

このような場合、確実な逃げ道があるとは思えません。50人中7人が一致したことを喜ぶしかない。

マザーボードのUUIDを除けば、他に信頼できるエントリーはありません。その他は、オプション(シリアル番号など)か、フォーマットやWindowsの再インストール、マイナーバージョンアップの際に簡単に交換・変更できるようになっています。

ハードウェアキーと連動していれば別ですが、それはやりすぎです。数千円のソフトにしか通用しない。

 
Edgar Akhmadeev:

このような場合、確実な逃げ道があるとは思えません。50人中7人が一致したことを喜ぶしかない。

マザーボードのUUIDを除けば、他に信頼できるエントリーはありません。その他は、オプション(シリアル番号など)か、フォーマットやWindowsの再インストール、マイナーバージョンアップの際に簡単に交換・変更できるようになっています。

ハードウェアキーと連動していれば別ですが、それはやりすぎです。そんなの何千円もするソフトにしか通用しない。

私の理屈では、サンプルプログラムを撮るとハードを記憶してしまい、それ以上撮れなくなるのです。コーリャが校正刷りを撮ったのなら、他の人は運が悪いということがわかりました。だから、私の喜びはもうおしまい。

Cドライブにバインドするのが唯一の方法だと思う。

 
Vitaly Muzichenko:

私の理屈では、ソフトのサンプルを取ったら鉄分を記憶してしまい、それ以上取れないということです。もしコーリャが裁判を受けたら、私たちの残りはアウトだということがわかったんです。だから、私の喜びはもうおしまい。

もうCドライブにバインドするしか道はないんですね。

他はよくわからない。

 
Vitaly Muzichenko:

私の理屈では、ソフトのサンプルを取ったら鉄分を記憶してしまい、それ以上取れないということです。もしコーリャが裁判を受けたら、私たち以外はアウトだということがわかったんです。だから、私の喜びはもうおしまい。

もうCドライブにバインドするしか道はないんですね。

これは、Cドライブがあり、例えば/dev/sdaでない場合です。