環境…Win2000 VC6.0SP5
現在、外付けHDDのデバイス情報とドライブレターの取得を行いたいのですが、
上手く行く方法がありません。
試した方法は、
・レジストリの「MountedDevices」を参照する。
結果…HDD以外の情報は取得できるが、HDDは不可。
・CreateFile関数の第1引数に「\\\\.\\x」(xはドライブレター)でハンドルを取得。
結果…HDD以外のハンドルは取得できるが、HDDは不可。
そして、現在CreateFile関数の第1引数に「\\\\.\\PHYSICALDRIVEx」
(xはドライブナンバー)から情報を取得する方法を試しています。
現時点では、ちょっとあやしい感じがします。
何か良い方法をご存知の方は、おりませんでしょうか?
以下のようなソースで
-----------------------------------------------------------------
STORAGE_PROPERTY_QUERY sPQ = { StorageDeviceProperty, PropertyStandardQuery };
STORAGE_DEVICE_DESCRIPTOR sdid;
flg = DeviceIoControl(
hDevice,//各ドライブのハンドル
IOCTL_STORAGE_QUERY_PROPERTY,
&sPQ,
sizeof(sPQ),
&sdid,
sizeof(sdid),
&dwRet,
NULL);
CloseHandle( hDevice );
-----------------------------------------------------------------
この様な出力結果になりました。
(内臓HDDの結果)
sdid {
Version 0x00000028
Size 0x00000084
DeviceType 0x00 ''
DeviceTypeModifier0x00 ''
RemovableMedia 0x00 ''
CommandQueueing 0x00 ''
VendorIdOffset 0x00000000
ProductIdOffset 0x00000000
ProductRevisionOffset 0x00000000
SerialNumberOffset 0x00000000
BusType BusTypeAta
RawPropertiesLength 0x00000000
RawDeviceProperties 0x0012f9e0 "
}
ベンダーIDやドライブレターなどは、得られないようです。
あまりにもネット上に情報が少ない為、質問させて頂きます。
以下のような処理手順なのですが、ベンダーのデータが取得できません。
悪いところを指摘してくれませんでしょうか?
-------------------------------------------------
char strGetDeviceName[] = \\\\.\\PHYSICALDRIVE0;
BOOL flg;
DWORD dwRet;
// HDDのデバイスハンドルを取得
HANDLE hDevice;
hDevice = ::CreateFile(
strGetDeviceName,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hDevice == INVALID_HANDLE_VALUE)
return;
// ベンダー値を取得
STORAGE_PREDICT_FAILURE sdid;
ZeroMemory( &sdid, sizeof (sdid) );
flg = DeviceIoControl(
hDevice,// 事前に取得したHDDのハンドル
IOCTL_STORAGE_PREDICT_FAILURE,
NULL,
0,
&sdid,
sizeof(sdid),
&dwRet,
NULL);
//sdidの中に値が入ってこない。
-------------------------------------------------
気が付いたことだけ
ドライブレターは
GetLogicalDrives() または
GetLogicalDriveStrings()
で求めたほうがよいではないでしょうか?
CreateFile関数の第1引数に「\\\\.\\x」(xはドライブレター)でハンドルを取得。
結果…HDD以外のハンドルは取得できるが、HDDは不可。
•フロッピーディスクや、ハードディスクのパーティションを開く場合、dwShareMode パラメー
タで FILE_SHARE_WRITE フラグを指定しなければなりません。
FILE_SHARE_READ なので失敗しているとおもいます。
上の方のやつについて
DDK入れてないんで詳細わからず、試すこともできないんだけど
microsoft.comの英語からすると少なくとも出力バッファは
STORAGE_DEVICE_DESCRIPTORより大きくないとだめっぽいけど
flgやdwRetの結果はどうなってます?
char aaa[10000];
STORAGE_DEVICE_DESCRIPTOR* psdid = (STORAGE_DEVICE_DESCRIPTOR*)aaa;
flg = DeviceIoControl(
hDevice,
IOCTL_STORAGE_QUERY_PROPERTY,
&sPQ,
sizeof(sPQ),
psdid,
sizeof(aaa),
&dwRet,
NULL);
うまくいったら
puts(&aaa[psdid->VendorIdOffset]);
ってことじゃないかな
もうひとつ
CreateFile関数の第1引数は「\\\\.\\x」ではなく
「\\\\.\\x:」でないとエラーになります。
>汎さん
ご指摘ありがとうございます。
おっしゃる通り、「FILE_SHARE_WRITE」を追加したことでハンドルの取得に成功しました。
これで、ドライブレターの取得に関しては解決しました。(きっと…)
ありがとうございます。
HDDのハンドルを取得するソース部分
----------------------------------------------------------
char strGetDeviceName[] = \\\\.\\A:;
char strDriveLetter = 'A';
int posDriveLetter = 4;
HANDLE hDevice;
for (int i = 0; i < 26; i++){
strGetDeviceName[ posDriveLetter ] = strDriveLetter + i;
hDevice = ::CreateFile(
strGetDeviceName,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
}
----------------------------------------------------------
>kuさん
ご指摘された通り、事前に大きめのサイズのバッファのポインタり」オておくことで
以下の値が得られました。
ありがとうございます。
ソース
--------------------------------------------
BYTE buf[ 2048 ];
STORAGE_PROPERTY_QUERY sPQ = { StorageDeviceProperty,
PropertyStandardQuery, NULL };
STORAGE_DEVICE_DESCRIPTOR* sdd = (STORAGE_DEVICE_DESCRIPTOR*)buf;
ZeroMemory( sdd, sizeof (buf) );
flg = DeviceIoControl(
hDevice,// 上記で取得したHDDのハンドル
IOCTL_STORAGE_QUERY_PROPERTY,
&sPQ,
sizeof(sPQ),
sdd,
sizeof(buf),
&dwRet,
NULL);
--------------------------------------------
取得した値
sdd 0x0012f65c
Version 40
Size 132
DeviceType 0 ''
DeviceTypeModifier0 ''
RemovableMedia 0 ''
CommandQueueing 0 ''
VendorIdOffset 0
ProductIdOffset 76
ProductRevisionOffset 86
SerialNumberOffset 96
BusType BusTypeAta
RawPropertiesLength 36
RawDeviceProperties 0x0012f680 "
ここの各オフセット値が「STORAGE_PREDICT_FAILURE」構造体内の
「VendorSpecific」のオフセットに当ると見ました。
そこで、「IOCTL_STORAGE_PREDICT_FAILURE」コマンドで
ベンダー値を取得する事を試みました。
--------------------------------------------
BYTE buf2
STORAGE_PREDICT_FAILURE* spf = (STORAGE_PREDICT_FAILURE*)buf2;
ZeroMemory( spf, sizeof (buf2) );
flg = DeviceIoControl(
hDevice,
IOCTL_STORAGE_PREDICT_FAILURE,
NULL,
0,
spf,
sizeof(buf2),
&dwRet,
NULL);
--------------------------------------------
が、取得できる値とオフセットの場所が全然合いません。
(HDDはシーゲイト製40GBです。)
spf
VendorSpecific 0x0012ee5c "
[0] 0 ''
[1] 0 ''
[2] 0 ''
[3] 0 ''
[4] 0 ''
[5] 0 ''
[6] 0 ''
[7] 0 ''
[8] 0 ''
[9] 0 ''
[10] 0 ''
[11] 0 ''
[12] 76 'L'
[13] 0 ''
[14] 0 ''
[15] 0 ''
[16] 86 'V'
[17] 0 ''
[18] 0 ''
[19] 0 ''
[20] 96 '~'
[21] 0 ''
[22] 0 ''
[23] 0 ''
[24] 3 ''
[25] 0 ''
[26] 0 ''
[27] 0 ''
[28] 36 '$'
[29] 0 ''
[30] 0 ''
[31] 0 ''
[32] 0 ''
[33] 0 ''
[34] 0 ''
[35] 0 ''
[36] 0 ''
[37] 0 ''
[38] 0 ''
[39] 0 ''
[40] 0 ''
[41] 0 ''
[42] 0 ''
[43] 0 ''
[44] 83 'S'
[45] 84 'T'
[46] 51 '3'
[47] 52 '4'
[48] 48 '0'
[49] 56 '8'
[50] 49 '1'
[51] 48 '0'
[52] 65 'A'
[53] 32 ' '
[54] 32 ' '
[55] 32 ' '
[56] 32 ' '
[57] 32 ' '
[58] 32 ' '
[59] 32 ' '
[60] 32 ' '
[61] 32 ' '
[62] 32 ' '
[63] 32 ' '
[64] 32 ' '
[65] 32 ' '
[66] 32 ' '
[67] 32 ' '
[68] 51 '3'
[69] 46 '.'
[70] 51 '3'
[71] 57 '9'
[72] 83 'S'
[73] 84 'T'
[74] 51 '3'
[75] 52 '4'
[76] 48 '0'
[77] 56 '8'
[78] 49 '1'
[79] 48 '0'
[80] 65 'A'
[81] 0 ''
[82] 51 '3'
[83] 46 '.'
[84] 51 '3'
[85] 57 '9'
[86] 0 ''
[87] 32 ' '
[88] 32 ' '
[89] 32 ' '
[90] 0 ''
[91] 0 ''
…長いので省略
上記のオフセット値はどこのオフセットり」キのか分からなくなってしまいました。
ベンダー値を取得する他の方法でもあるのでしょうか…。
すみません。
出来たと思ったのですが、USBドライブの場合、
「IOCTL_STORAGE_PREDICT_FAILURE」
コマンドではベンダ値を取得出来ませんでした。
HDDのハンドルを利用した、別な方法を探します。
何度も書き込んで申し訳ありません。
補足として、
「IOCTL_STORAGE_QUERY_PROPERTY」
コマンドでは、値が取得出来ています。
取得したUSBHDDの値
sdd 0x0012f65c
Version 40
Size 103
DeviceType 0 ''
DeviceTypeModifier 0 ''
RemovableMedia 0 ''
CommandQueueing 0 ''
VendorIdOffset 72
ProductIdOffset 81
ProductRevisionOffset 98
SerialNumberOffset 0
BusType BusTypeUsb
僕がレスしているので他の方が遠慮しているだけかもしれませんが
このまま解答してくださる方がおられないように感じます
他の方の質問の内容に答えている内にあるページを発見しました
下記のページはDDKに関する掲示板があります(職人フォーラムという項目です)
マルチポストは嫌われますので、こちらでの経緯と質問を書いて投稿してはいかがでしょうか?
http://www.ouk.co.jp/ogawa/
毎回本当にありがとうございます。
早速書き込んで見ます。
一生懸命 API レベルで取り組まれているようですが、WMI(Windows Management
Instruments)を使うのでは駄目でしょうか?
実際に試していませんが、「デバイスマネージャ」に表示されているくらいの情報は最
低限取得できるはずです。
渋木宏明(ひどり)さん。
アドバイスありがとうございます。
WMI調べて見たいと思います。
しかし、デバイスマネージャ上の情報からや、エクスプローラのプロパティからでさえ、
HDDとドライブレターの繋がりを知る事は出来ないので、難しいかもしれないですね。
CD/DVDの制御でよくここを参考にさせてもらっています.
http://www.geocities.co.jp/Hollywood/4205/doc/spti.html
R7038XXさんの疑問はHDDだから参考にならないかも
しれませんが.