none
DeviceIoControl関数の戻り値 RRS feed

  • 質問

  • 下手なグラマです。

    VC++の内容ではないのですがHP等のサンプルを見ながらHDDのモデル名等の情報を

    取得しようといろいろやってますがうまくいきません。

    IOCTL_STORAGE_QUERY_PROPERTYの設定でDeviceIoControl関数を実行すると

    戻り値がfalseになっています。IOCTL_STORAGE_PREDICT_FAILUREではtrueが返っています。
    OSはWin2000、コンパイラはBCB5を使用しています。
    とりあえずPlatformSDKとDDKはダウンロードして必要なheaderだけをカレントへ
    コピーしています。PSDK等のincludeフォルダーをBCBの統合環境設定に入れると
    うまくいきません。(重複するせいか...)もっといい方法がありそうなのですが...
    とりあえずDeviceIoControl関数がtrueになるようにしたいです。
    どなたかよいアドバイスをお願いいたします。


    bool Test1(void)
    {
      DWORD dwLen;
      BYTE* pcbData;
      HANDLE hDrive;
      DWORD dwRet = 0;
      bool ret;

     

      STORAGE_PROPERTY_QUERY  sQuery;
      sQuery.PropertyId = StorageDeviceProperty;
      sQuery.QueryType = PropertyStandardQuery;
      sQuery.AdditionalParameters[0] = NULL;

      hDrive = CreateFile("\\\\.\\C:",

                  GENERIC_READ,

                  FILE_SHARE_READ | FILE_SHARE_WRITE,

                  NULL,

                  OPEN_EXISTING,

                  FILE_ATTRIBUTE_NORMAL,

                  NULL);

      if(hDrive == INVALID_HANDLE_VALUE)
         return false;

      dwLen = 2048;  //十分な領域確保

      pcbData = new BYTE[dwLen];
      if(pcbData == NULL)
      {
         ::CloseHandle(hDrive);
         return false;
      }

      ZeroMemory(pcbData,dwLen);

      ret = :Big SmileeviceIoControl( hDrive,

                     IOCTL_STORAGE_QUERY_PROPERTY,

                     &sQuery,

                     sizeof(STORAGE_PROPERTY_QUERY),

                     pcbData,

                     dwLen,

                     &dwRet,

                     NULL);
      if(ret == false)                  //  <---- ここ
                Form1->Label1->Caption = "false";
      else
                Form1->Label1->Caption = "true";

      ::CloseHandle(hDrive);
    }

    2008年2月12日 15:05

回答

  •  下手なグラマ さんからの引用

    上記を取り出して再度行って見ましたが駄目でした。

    一部ファイルや一部の定義のみソースにコピーするといった操作は正しい結果を得られないことがあります。

    BCBのインクルードパス、ライブラリパスにPlatform SDK(Windows SDK)やDDKを優先して検索するように設定すべきです。

     

    使っているマクロが別のヘッダーで定義されていたりすると、新しいSDKでは中身が違うと言うこともあり得ますので。

     

    但し、VCLの定義内容によっては新しいSDKで通らないこともあり得ます。

    #そもそも、BCBってlibの形式違うんでしたっけ?

     

    追記

    最初に書いてありましたね。見落としましていて、すみません。

    VCでいうMFCも、Windows SDK等の新しいバージョンではコンパイルが通らないこともありますので、インクルード順や環境の影響は十分あり得ます。

     

    他に考えられる、試行してみること

    ・マクロ定数はVCで得られた値をそのまま数値で定義する。

     別のマクロ、CTL_CODE等は使わない形にする。

    ・pack(アライメント、パッキング)の数値は合っていますか?

     VCでのsizeofとBCBでのsizeofの数値は同じ?

     

    他に気になる点

    ・DeviceIOControlのBOOL型と、bool型は異なりますし、falseと比較するのも本来は正しくない気がします。

    2008年2月15日 15:40
    モデレータ
  • マクロを使わない、sizeofを比較してみるというのは、VC(正常動作)とBCB(異常動作)の引数が本当に同じかという確認の事かと思います。

    <私の環境のVCの場合>

    int value = IOCTL_STORAGE_QUERY_PROPERTY; // ←0x002d1400でした

    int size = sizeof(STORAGE_PROPERTY_QUERY);  // ←12でした

     

    次にDeviceIoControlの引数でIOCTL_STORAGE_QUERY_PROPERTYを0x002d1400に

    STORAGE_PROPERTY_QUERYを12に置換してビルド→実行で(当然ですが)正常動作することを確認しました。

     

    後はBCBで同様の確認をしてみて、値がVCと同じかどうか、もし異なっていたらVCの値をそのまま渡すと正常動作になるのか、といった辺りを試されると良いと思います。
    2008年2月17日 11:37

すべての返信

  • 私の環境(Vista)で実行したところCreateFileの引数が "\\\\.\\C:" ではINVALID_HANDLE_VALUEが返ってきましたが

    2nd HDDの "\\\\.\\D:" を指定したところDeviceIoControlの結果もtrueで返ってきました。

     

    DeviceIoControlの後でGetLastErrorの値を調べたら解決のヒントが得られるのではないでしょうか

     

    2008年2月14日 12:36
  • C.Johnさん。ありがとうございます。VC++のフォーラムなので少し恐縮してます。

    CreateFileの引数を各ドライブに変更してGetLastErrorの値を確認してみました。

     

    \\.\A: -> ファンクションが間違っています。0
    \\.\C: -> パラメータが間違っています。,
    \\.\D: -> パラメータが間違っています。,
    \\.\F: -> パラメータが間違っています。,
    \\.\G: -> パラメータが間違っています。,
    \\.\H: -> パラメータが間違っています。,

    C,DがHDD、F,Gがドライブ、HがUSBドライブです。パラメータが違うと出てますが

    どこかで見たサンプルと同じにしています。DeviceIoControl関数がパラメータを

    受け付けない言うことは何かのDLL等が古いのかなとも感じてます。

    DLL等がOSもWin2kですがコンパイラもBCB5でちょっと古いのが気になりますが

    BCB6でも同じでした。もし何かありましたらお願いいたします。

    2008年2月14日 13:48
  • パラメータが間違っているとすると「PlatformSDKとDDKはダウンロードして必要なheaderだけをカレントへ
    コピーしています。」という作業でおかしな定義(定数や構造体)を読み込んでしまっているのではないでしょうか?

     

    // 参考までに

    Visual C++ 2005 Express Edition + PlatformSDKでビルドした実行ファイルをWin2000上で動作させたところ、DeviceIoControlの結果はtrueでした。

    Win2000上にインストールしてあるVC6ではwinioctl.hが古く、STORAGE_PROPERTY_QUERYが定義されていないためビルド不可でした。

    2008年2月14日 14:58
  • C.johnさん。ありがとうございます。

    ご提案頂き、ヘッダーファイルはBCBでいうメインのvcl.hのひとつのみにして

    DDK(03/06/19の日付)のntddstor.hから

     

    構造体:STORAGE_DEVICE_DESCRIPTOR、STORAGE_PROPERTY_QUERY

    共用体:STORAGE_BUS_TYPE、STORAGE_PROPERTY_ID、STORAGE_QUERY_TYPE

    あと

    #define CTL_CODE( DeviceType, Function, Method, Access ) (                 \
        ((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
    )


    #define IOCTL_STORAGE_QUERY_PROPERTY   CTL_CODE(0x2D, 0x0500, 0, 0)

    // IOCTL_STORAGE_BASE -> 0x2D

    //  METHOD_BUFFERED       -> 0

    //  FILE_ANY_ACCESS         ->  0


    上記を取り出して再度行って見ましたが駄目でした。

    C.JohnさんのWin2000上にインストールしてあるVC6で起きている事が似ている感じのように

    思います。私もC.Johnさんと同じようにVisual C++ 2005 Express Edition + PlatformSDKで

    ビルドした実行ファイルをWin2000上で動作させたところ、C:~H:までDeviceIoControlの結果は

    trueでした。やはりBCBが古いのかな...。何か関係しているファイル等をを入れ替えて動作出来れば

    いいんですが...。

    2008年2月15日 13:42
  •  下手なグラマ さんからの引用

    上記を取り出して再度行って見ましたが駄目でした。

    一部ファイルや一部の定義のみソースにコピーするといった操作は正しい結果を得られないことがあります。

    BCBのインクルードパス、ライブラリパスにPlatform SDK(Windows SDK)やDDKを優先して検索するように設定すべきです。

     

    使っているマクロが別のヘッダーで定義されていたりすると、新しいSDKでは中身が違うと言うこともあり得ますので。

     

    但し、VCLの定義内容によっては新しいSDKで通らないこともあり得ます。

    #そもそも、BCBってlibの形式違うんでしたっけ?

     

    追記

    最初に書いてありましたね。見落としましていて、すみません。

    VCでいうMFCも、Windows SDK等の新しいバージョンではコンパイルが通らないこともありますので、インクルード順や環境の影響は十分あり得ます。

     

    他に考えられる、試行してみること

    ・マクロ定数はVCで得られた値をそのまま数値で定義する。

     別のマクロ、CTL_CODE等は使わない形にする。

    ・pack(アライメント、パッキング)の数値は合っていますか?

     VCでのsizeofとBCBでのsizeofの数値は同じ?

     

    他に気になる点

    ・DeviceIOControlのBOOL型と、bool型は異なりますし、falseと比較するのも本来は正しくない気がします。

    2008年2月15日 15:40
    モデレータ
  • Azuleanさん。ありがとうございます。

    おっしゃる通りBCBのLibはOMFフォーマットだったと思います。COFFフォーマットからの変換ソフト(COFF2OMF)が

    ありますがまだ使用してません。(かなりのファイル数があります)

    >・マクロ定数はVCで得られた値をそのまま数値で定義する。

    > 別のマクロ、CTL_CODE等は使わない形にする。

    別のマクロは使っていないと思っていますがCTL_CODEはどうやって代用出来るか調べてみます。

    >・pack(アライメント、パッキング)の数値は合っていますか?

    > VCでのsizeofとBCBでのsizeofの数値は同じ?

    packという言葉を初めて知りました。 sizeofは調べてみます。

    やはりこのあたりの話になるとBCB関連のフォーラムに書くべきなんでしょうね...。すいません。

    初めに参考にしたHPは下記です。

    http://www.usefullcode.net/2007/02/if.html

    http://d.hatena.ne.jp/kaorun55/20080210

    2008年2月17日 8:46
  • マクロを使わない、sizeofを比較してみるというのは、VC(正常動作)とBCB(異常動作)の引数が本当に同じかという確認の事かと思います。

    <私の環境のVCの場合>

    int value = IOCTL_STORAGE_QUERY_PROPERTY; // ←0x002d1400でした

    int size = sizeof(STORAGE_PROPERTY_QUERY);  // ←12でした

     

    次にDeviceIoControlの引数でIOCTL_STORAGE_QUERY_PROPERTYを0x002d1400に

    STORAGE_PROPERTY_QUERYを12に置換してビルド→実行で(当然ですが)正常動作することを確認しました。

     

    後はBCBで同様の確認をしてみて、値がVCと同じかどうか、もし異なっていたらVCの値をそのまま渡すと正常動作になるのか、といった辺りを試されると良いと思います。
    2008年2月17日 11:37
  • C.Johnさん。ありがとうございます。

    >int value = IOCTL_STORAGE_QUERY_PROPERTY; // ←0x002d1400でした

    >int size = sizeof(STORAGE_PROPERTY_QUERY);  // ←12でした

    これはBCB5も同じでした。

     

    >次にDeviceIoControlの引数でIOCTL_STORAGE_QUERY_PROPERTYを0x002d1400に

    >STORAGE_PROPERTY_QUERYを12に置換してビルド→実行で(当然ですが)正常動作することを確認しました。

    引数置換も行ってみましたが同じでした。DeviceIoControl関数を実装しているDLLに何かあるんでしょうか....。

    ちょっと手詰まり感があります。orz

    2008年2月20日 14:58
  • C.Johnさん。Azuleanさん。

    >int size = sizeof(STORAGE_PROPERTY_QUERY);  // ←3でした

    すいません。ただダイレクトにIOCTL_STORAGE_QUERY_PROPERTYとsizeof(STORAGE_PROPERTY_QUERY)を

    置き換えるだけでは駄目みたいです。その後、BCB関連のフォーラムを見つけていろいろ教えて頂きました。

     

    unsigned char inbuffer[1024] = { 0 };
    STORAGE_PROPERTY_QUERY *sPQ = (STORAGE_PROPERTY_QUERY *)inbuffer;
    sPQ->PropertyId = StorageDeviceProperty;
    sPQ->QueryType = PropertyStandardQuery;

    ret = :Big SmileeviceIoControl( hDevice, IOCTL_STORAGE_QUERY_PROPERTY, sPQ, 12, sdd, sizeof(buffer), &dwRet, 0 );

    BCBではこのようになるそうです。C.Johnさん、Azuleanさんにはいろいろきっかけを教えて頂きありがとう御座いました。
    2008年2月25日 14:27
  • こんにちは。中川俊輔 です。

     

    Azuleanさん、C.Johnさん、大変参考になる回答ありがとうございます。

     

    下手なグラマさん、解決方法を投稿していただき、ありがとうございます。

    問題解決の参考になった回答のようでしたので、

    勝手ながらAzuleanさん、C.Johnさんの回答へ回答済みチェックをつけさせていただきました。

     

    問題解決につながる回答があった場合は、なるべく回答済みボタンを押してチェックを付けてください。

    下手なグラマさんはチェックを解除することもできますので、ご確認ください。

     

    それでは!

     

    2008年3月3日 8:57