• ベストアンサー

GetAdapterInfoによりマックアドレスを取得したい。

はじめまして、sandayu999と申します。 ネットワークアダプタの情報を取得するために GetAdapterInfo関数を使用しているのですが 返り値がエラーとなってしまいます。 環境はWindowsXPでCコンパイラは borlandのbcc32.exeを使用しております。 コンパイルは正常に行えました。 [mac.c] --------------------------------------- IP_ADAPTER_INFO adapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); //サイズ取得 print("%d\n",GetAdaptersInfo( &adapterInfo, &aiSize )); 出力してみたところ、値が87(ERROR_INVALID_PARAMETER) となってしまいました。 どのような対処をしたら良いのかわからない状態です、どなたかアドバイスをよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.3

PIP_ADAPTER_INFO padapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize); printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize )); free(padapterInfo); でどうでしょう? 質問文のソースではアダプタが1つの時にしか正常に動作しないような気がします。

sandayu999
質問者

補足

hofuhofuさん、taka_tetsuさん返信ありがとうございます。 >taka_tetsuさん >書かれているコード、質問に書かれた部分で全部ですか? すみません、一部しか記述しておりませんでした。 全体は下記になります(多少みずらくなってます) ----------------- #include <windows.h> #include <iphlpapi.h> #include <stdio.h> void main(void){ IP_ADAPTER_INFO adapterInfo; DWORD aiSize, i; GetAdaptersInfo(NULL,&aiSize); if( GetAdaptersInfo( &adapterInfo, &aiSize ) != ERROR_SUCCESS ) { printf( "GetAdapterInfo呼び出し失敗\n" ); return; } fprintf( stdout,"MACアドレス = [" ); for( i = 0; i < adapterInfo.AddressLength; i++ ) { fprintf( stdout, "%.2X", (int)adapterInfo.Address[i] ); if( i == ( adapterInfo.AddressLength - 1 ) ) fputs( "]\n", stdout ); else fputs( "-", stdout ); } } そこで、hofuhofuさんのご指摘通りに行ってみたところ、 ----------------- PIP_ADAPTER_INFO padapterInfo; DWORD aiSize; GetAdaptersInfo(NULL,&aiSize); padapterInfo=(PIP_ADAPTER_INFO)malloc(aiSize); printf("%d\n",GetAdaptersInfo( padapterInfo, &aiSize )); free(padapterInfo); にて成功の0が出力されました。 これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを 確保しているという解釈でよいでしょうか? (IP_ADAPTER_INFOだと、一つ分しか確保できていなかった) そこで、プログラムを下記のように直してみました。 ----------------- #include <windows.h> #include <iphlpapi.h> #include <stdio.h> void main(void){ PIP_ADAPTER_INFO padapterInfo; DWORD aiSize, i; GetAdaptersInfo(NULL,&aiSize); if( GetAdaptersInfo( padapterInfo, &aiSize ) != ERROR_SUCCESS ) { printf( "GetAdapterInfo呼び出し失敗\n" ); return; } while( padapterInfo ) { fprintf( stdout,"MACアドレス = [" ); for( i = 0; i < padapterInfo->AddressLength; i++ ) { fprintf( stdout, "%.2X", (int)padapterInfo->Address[i] ); if( i == ( padapterInfo->AddressLength - 1 ) ) fputs( "]\n", stdout ); else fputs( "-", stdout ); } padapterInfo = padapterInfo->Next; } free(padapterInfo); } [結果] ----------------- MACアドレス = [00-xx-xx-xx-xx-xx] MACアドレス = [00-xx-xx-xx-xx-xx] MACアドレス = [00-xx-xx-xx-xx-xx] と無事MACアドレスが出力されました。 雑誌にはもともとのソースでもNIC1枚分の情報は出力 されるとあったのですが、現在の方法 での処理のほうが正しいようです。 それと、MSDNのサンプルでは http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iphlp/iphlp/ip_adapter_info.asp でIP_ADAPTER_INFOのサンプルを見てみたのですが、 こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか? 通常は、hohuhohuさんの書かれるとおり、最後にFREE を入れるべきですよね?

その他の回答 (5)

  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.6

ちょっと修正です。 aiSizeを初期化もせずにつかっているのがまずいです。 本来この手法はOutBufLenに0を指定して、強制的にERROR_BUFFER_OVERFLOWを起こし必要な領域のサイズを得ようというもののようです(このときpAdapterInfoは問題にならないのでNULLを入れている)。 MSDNのサンプルソースではアダプタが複数あった場合にのみ発生したERROR_BUFFER_OVERFLOWを処理しているのに対し、最初からERROR_BUFFER_OVERFLOWを前提にしてプログラムを組んでいるという違いがあります。 ただpAdapterInfoにNULLを指定した場合にもOutBufLenの値に関係なくERROR_BUFFER_OVERFLOWが発生し、OutBufLenに必要な領域のサイズが帰ってきているようです。 今回のケースではこの現象により正常に動いているように見えていたわけですが、MSDNにはERROR_BUFFER_OVERFLOWの発生条件としてOutBufLenが小さすぎること以外書かれていないので、この現象に依存したプログラムは避けるべきだと思います。

sandayu999
質問者

お礼

hohuhohuさん返信有難うございます。 なるほど、確かに自分のソースは最初からERROR_BUFFER_OVERFLOWをさせて取得しています。 (初期化もせずに) MSDNのソースに直した形での取得方法にしようと 思います。

  • hofuhofu
  • ベストアンサー率70% (336/476)
回答No.5

> これはIP_ADAPTER_INFOのポインタ型のPIP_ADAPTER_INFOを使用することでNIC分のメモリを > 確保しているという解釈でよいでしょうか? MSDNを見る限りそういうことだろうと判断して回答しました。 説明文を読むと十分な領域さえ確保されていれば、サイズはどのような値でもいいようです。 BYTE buf[5120]; DWORD aiSize=5120; GetAdaptersInfo((PIP_ADAPTER_INFO)buf,&aiSize); でもほとんどの環境で正常に動作すると思います。 それより改めて見直してみて気になったのは、 GetAdaptersInfo(NULL,&aiSize); //サイズ取得 ですね。 確かに必要な容量がaiSizeに帰ってきていますが、この挙動自体はMSDNに記載されていないようです。 If this size is insufficient to hold the adapter information, GetAdaptersInfo fills in this variable with the required size, and returns an error code of ERROR_BUFFER_OVERFLOW とはありますが、これはpOutBufLenで指定された値が必要な容量未満だったときですし。 この方法でサイズ取得するのはよく行われているようですが、記載が無い以上避けておいたほうがいいように思います。

sandayu999
質問者

補足

hofuhofuさん、返信ありがとうございます。 >それより改めて見直してみて気になったのは、 >GetAdaptersInfo(NULL,&aiSize); //サイズ取得 >ですね。 >確かに必要な容量がaiSizeに帰ってきていますが、 >この挙動自体はMSDNに記載されていないようです。 MSDNのサンプルを見てみたのですが、 pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) ); ulOutBufLen = sizeof(IP_ADAPTER_INFO); if (GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) != ERROR_SUCCESS) { GlobalFree (pAdapterInfo); pAdapterInfo = (IP_ADAPTER_INFO *) malloc (ulOutBufLen); } この記述をみると、最初は、 IP_ADAPTER_INFO一つ分で確保しに行ってますが、 そのとき、if文で GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) をして、失敗だったらulOutBufLenを使用して 再度所得しなおしているので、MSDN上いちおう 問題ないのではないでしょうか?

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>こちらはFREE関数を使ってメモリを最後に開放していないのですが、これはサンプルだから省略されたということでしょうか? >通常は、hohuhohuさんの書かれるとおり、最後にFREE を入れるべきですよね? 当たり前のことですが、free()を呼ぶのはその領域が不要になったとき。 MSDNのサンプル、関数にはなってないですよね。 取得したMACアドレス、printfで表示するだけでしたらすぐにfreeしてもいいですけど、他にも使うんでしたら解放しちゃまずいですよね。

sandayu999
質問者

お礼

taka_tetsuさん返信ありがとうございます。 >当たり前のことですが、free()を呼ぶのはその領域 >が不要になったとき。 >MSDNのサンプル、関数にはなってないですよね。 >取得したMACアドレス、printfで表示するだけでし >たらすぐにfreeしてもいいですけど、他にも使うん >でしたら解放しちゃまずいですよね。 なるほど、確かに関数になっていませんでした。 プログラムも理解することができました。 ありがとうございました。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.2

>実際、自分のプログラム(雑誌に載っていたサンプル) >だとなぜエラーなのか原因がわからなかったのです。 書かれているコード、質問に書かれた部分で全部ですか? 使用してる変数の宣言からAPIの呼び出しまでの間を全部書いていただければどこがおかしいか確認できると思いますけど。 >ERROR_INVALID_PARAMETERについても英語で説明 >はありますが、、いまいち対処法をみいだすことが >できなくて。 ERROR_INVALID_PARAMETERは、「パラメータが間違ってます」ってだけなんで、使い方が違うとしか言いようが無いです。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1
sandayu999
質問者

お礼

taka_tetsuさん、返信ありがとうございます。 実は、自分も調べていて紹介していただいたURL にはいったのですが、 実際、自分のプログラム(雑誌に載っていたサンプル) だとなぜエラーなのか原因がわからなかったのです。 ERROR_INVALID_PARAMETERについても英語で説明 はありますが、、いまいち対処法をみいだすことが できなくて。 他にも、色々と調べてはみたのですが、 ERROR_INVALID_PARAMETER が出力されてしまっている状態です。

関連するQ&A