動作環境
C++ Builder XE4
注意
(追記 2018/11/14)
以下で使用しているZeroMemoryは最適化で吹き飛ぶため、SecureZeroMemory()の使用が推奨されます。
情報
- MACアドレスを取得する by 山本隆 様
- MACアドレスの取得 2 @ たまねぎIT戦士日誌・めも by makky0126 様
情報感謝です。
実装 > v0.1, v0.2
山本様の実装をXE4用インクルードなどに変更しました (ソース内のv0.2コメント参照)。
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TMemo *Memo1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // ユーザー宣言
void __fastcall showMacAddress(void);
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//#include <tchar.h>
//#include <windows.h>
//#include <assert.h>
//#include <stdio.h>
#include "Nb30.h"
//
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------
/*
v0.2
- ZeroMemory()を::ZeroMemory()に変更 (グローバルスコープを明示)
- refactor > 変数名の変更: ローカル変数、ループ変数など
- assert()の使用停止。代わりにearly returnとTMemo出力へ
- インクルードファイルを[C++ Builder XE4]用に変更
v0.1
- 右記からforkした [ http://www.gesource.jp/programming/bcb/83.html ]
Acknowledgement to Takashi YAMAMOTO (山本隆 様)
*/
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
showMacAddress();
}
//---------------------------------------------------------------------------
// MACアドレス関連処理
//
// { MACアドレス取得用構造体
typedef struct {
ADAPTER_STATUS status;
NAME_BUFFER buffer[30];
} ASTAT_t;
// } MACアドレス取得用構造体
void __fastcall TForm1::showMacAddress(void)
{
NCB ancb; // netbios()にて使用
LANA_ENUM lenum; // LANA: LAN Adapterのenum
// NICの数を取得
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBENUM;
ancb.ncb_buffer = (UCHAR*)&lenum;
ancb.ncb_length = sizeof(lenum);
Netbios(&ancb);
//
for(int idx = 0; idx < lenum.length; idx++) { // NICごとの処理
// 1. リセット
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBRESET;
ancb.ncb_lana_num = lenum.lana[idx];
UCHAR retCode = Netbios(&ancb);
//assert(retCode == 0); // >> early returnを代わりに使用
if (retCode != 0) {
Memo1->Lines->Add(L"ERROR: Netbios() failed");
return;
}
// 2. MACアドレスの取得
ASTAT_t adpt; // アダプタ情報取得用バッファ
//
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBASTAT;
ancb.ncb_lana_num = lenum.lana[idx];
strcpy(ancb.ncb_callname, "*");
ancb.ncb_buffer = (UCHAR*)&adpt;
ancb.ncb_length = sizeof(adpt);
retCode = Netbios(&ancb);
//assert(retCode == 0); // >> early returnを代わりに使用
if (retCode != 0) {
Memo1->Lines->Add(L"ERROR: Netbios() failed");
return;
}
// 3. Output to TMemo
String msg = String().sprintf(L"%02X-%02X-%02X-%02X-%02X-%02X",
adpt.status.adapter_address[0],
adpt.status.adapter_address[1],
adpt.status.adapter_address[2],
adpt.status.adapter_address[3],
adpt.status.adapter_address[4],
adpt.status.adapter_address[5]);
Memo1->Lines->Add(msg);
}
}
//---------------------------------------------------------------------------
動作
- ボタンを押すとNICのMACアドレスがMemo1に表示される
- 複数のNICを持つ場合、複数のMACアドレスが表示される
関連
-
NetBIOS関連
-
ZeroMemory()関連
実装 v0.3 > assignMacAddress()の追加
プロダクトコードで使えるようにさらに変更した。
Unit1.h
//---------------------------------------------------------------------------
#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
#include <Vcl.Controls.hpp>
#include <Vcl.StdCtrls.hpp>
#include <Vcl.Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE で管理されるコンポーネント
TMemo *Memo1;
TButton *Button1;
void __fastcall Button1Click(TObject *Sender);
private: // ユーザー宣言
void __fastcall showMacAddress(void);
bool __fastcall assignMacAddress(TStringList *dstPtr);
public: // ユーザー宣言
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
Unit1.cpp
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
//#include <tchar.h>
//#include <windows.h>
//#include <assert.h>
//#include <stdio.h>
#include "Nb30.h"
//
#include <memory>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Memo1->Lines->Clear();
}
//---------------------------------------------------------------------------
/*
v0.3
- assignMacAddress()を追加
- showMacAddress()の処理をこちらに移行
- unique_ptr()使用
v0.2
- ZeroMemory()を::ZeroMemory()に変更 (グローバルスコープを明示)
- refactor > 変数名の変更: ローカル変数、ループ変数など
- assert()の使用停止。代わりにearly returnとTMemo出力へ
- インクルードファイルを[C++ Builder XE4]用に変更
v0.1
- 右記からforkした [ http://www.gesource.jp/programming/bcb/83.html ]
Acknowledgement to Takashi YAMAMOTO (山本隆 様)
*/
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
showMacAddress();
}
//---------------------------------------------------------------------------
// MACアドレス関連処理
//
// { MACアドレス取得用構造体
typedef struct {
ADAPTER_STATUS status;
NAME_BUFFER buffer[30];
} ASTAT_t;
// } MACアドレス取得用構造体
void __fastcall TForm1::showMacAddress(void)
{
std::unique_ptr<TStringList> wrkSL(new TStringList);
assignMacAddress(wrkSL.get());
for(int idx=0; idx < wrkSL->Count; idx++) {
Memo1->Lines->Add(wrkSL->Strings[idx]);
}
}
bool __fastcall TForm1::assignMacAddress(TStringList *dstPtr)
{
if (dstPtr == NULL) {
return false; // error
}
NCB ancb; // netbios()にて使用
LANA_ENUM lenum; // LANA: LAN Adapterのenum
// NICの数を取得
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBENUM;
ancb.ncb_buffer = (UCHAR*)&lenum;
ancb.ncb_length = sizeof(lenum);
Netbios(&ancb);
//
for(int idx = 0; idx < lenum.length; idx++) { // NICごとの処理
// 1. リセット
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBRESET;
ancb.ncb_lana_num = lenum.lana[idx];
UCHAR retCode = Netbios(&ancb);
//assert(retCode == 0); // >> early returnを代わりに使用
if (retCode != 0) {
//Memo1->Lines->Add(L"ERROR: Netbios() failed");
return false;
}
// 2. MACアドレスの取得
ASTAT_t adpt; // アダプタ情報取得用バッファ
//
::ZeroMemory(&ancb, sizeof(ancb));
ancb.ncb_command = NCBASTAT;
ancb.ncb_lana_num = lenum.lana[idx];
strcpy(ancb.ncb_callname, "*");
ancb.ncb_buffer = (UCHAR*)&adpt;
ancb.ncb_length = sizeof(adpt);
retCode = Netbios(&ancb);
//assert(retCode == 0); // >> early returnを代わりに使用
if (retCode != 0) {
//Memo1->Lines->Add(L"ERROR: Netbios() failed");
return false;
}
// 3. Add to list
String msg = String().sprintf(L"%02X-%02X-%02X-%02X-%02X-%02X",
adpt.status.adapter_address[0],
adpt.status.adapter_address[1],
adpt.status.adapter_address[2],
adpt.status.adapter_address[3],
adpt.status.adapter_address[4],
adpt.status.adapter_address[5]);
//Memo1->Lines->Add(msg);
dstPtr->Add(msg);
}
return true;
}
//---------------------------------------------------------------------------