始めまして。
R7038XXと申します。
現在、レジストリ値からドライブの種類の取得を行おうとしています。
以下のような手順で取得しているのですが、レジストリの値が取得出来ません。
CRegKey* cRegKey = new CRegKey; // レジストリクラスの生成
DWORD dwSize = 256;
LPTSTR regData = new char[ dwSize ]; // レジストリサイズ分領域を確保
//レジストリの読み出し
cRegKey->Open( HKEY_LOCAL_MACHINE, SYSTEM\\MountedDevices);//, KEY_READ );
char strDriveLetter[] = A;
char strKeyName[] = \\DosDevices\\ ;
int posDriveLetter = sizeof( strKeyName ) - 2;
// ドライブレターの数だけ繰り返す
for (int i = 0; i < 26; i ++){
strKeyName[ posDriveLetter ] = (char)((int)strDriveLetter[0] + i);
ZeroMemory( regData, dwSize );
cRegKey->QueryValue( regData, strKeyName, &dwSize ); // レジ
ストリから取得
// この「regData」にレジストリの値が代入されるはずだが、値が入らない。
if (memcmp( regData, \\??\\ , 4) != 0){
continue;
}
}
レジストリフィールドの指定は間違っていると、強制エラーで終了するので
間違ってはいません。
原因が分かる方はおりますでしょうか?
該当するレジストリ項目を見ると、
\DosDevices\A:
のように末尾にコロンがついていますよ。
Win98SEにはそのようなレジストリキーは無いので判りませんがとりあえず、
cRegKey->QueryValue( regData, strKeyName, &dwSize );
の後、dwSizeの中身は書き換わりますが、それに関しては問題ないのでしょうか??
また、戻り値で成功しているか確認してみてはどうでしょう?
> if (memcmp( regData, \\??\\ , 4) != 0){
> continue;
> }
これは、スキップしたいのでしょうけど、
全体で26回しか回らないので、すべてのドライブ情報は取れないのではないですか?
みなさん、ありがとうございます。
>JBOYさん
>> if (memcmp( regData, \\??\\ , 4) != 0){
>> continue;
>> }
この部分はテスト段階の部分ですので、無視してください。
大変紛らわしくて、申し訳ありません。
しかし、A~Zまでだと、26回で丁度ではないのでしょうか?
>dairygoodsさん
ご指摘の通りでした。
訂正しました。
>瀬戸っぷ
訂正後、エラーの種類が
ERROR_MORE_DATA
なので、データの指定幅が狭いと言うことは分かりました。
そこで以下のように修正したのですが、データ幅の違いから、
エラーダイアログによって強制終了するようになりました。
----------------------------------------------------------------------------
// レジストリを読み出す
CRegKey* cRegKey = new CRegKey; // レジストリクラスの生成
DWORD dwSize = 161;
LPTSTR regData = new char[ dwSize + 2 ]; // レジストリサイズ分領域を確保
try{
//レジストリの読み出し
cRegKey->Open( HKEY_LOCAL_MACHINE, SYSTEM\\MountedDevices, KEY_READ );
}catch(...){
delete cRegKey;
return -1;
}
LONG ret;
char strDriveLetter[] = A;
char strKeyName[] = \\DosDevices\\ :;
int posDriveLetter = sizeof( strKeyName ) - 3;
// ドライブレターの数だけ繰り返す
for (int i = 0; i < 26; i ++){
strKeyName[ posDriveLetter ] = (char)((int)strDriveLetter[0] + i);
ZeroMemory( regData, dwSize + 2 );
ret = cRegKey->QueryValue( regData, (LPCTSTR)strKeyName, &dwSize );
// レジストリから取得
if (ret != ERROR_SUCCESS){
continue;
}
}
----------------------------------------------------------------------------
取得するレジストリの値によって、dwSizeを変化させる必要があると思うのですが、
「CRegKey」クラスには指定したレジストリフィールドのデータサイズを取得
するようなメソッドがありません。
取得するサイズは丁度のサイズを指定しなければ、強制終了ダイアログが出るような
感じなのですが、どのように解決するとよろしいのでしょうか?
MFCは使用していないのですが……
通常のSDKの場合と大差ないと思います。
というコトで…
ZeroMemory( regData, dwSize );
の前にdwSizeの値を再設定すれば問題ないハズです。
用意されたバッファサイズが受け取り用より大きい分には問題ないハズですから。
最初のバッファ確保時に
new char[MAX_PATH];
等でMAX_PATH分確保し(私だとだとchar szBuf[MAX_PATH]と取りますが)、
dwSize = MAX_PATH;
として再設定します。
MAX_PATHでバッファサイズが足りない場合は、改めて大きめに確保しますが。
SDKの場合は、RegQueryInfoKey()にて、最大サイズが取得できるようですが…
(使用したコトはないです)
regedit等でレジストリの内容を確認しました?
R7038XXさんが参照しようとしているレジストリはREG_BINARYとなっていませんでしたか?
また
LONG QueryValue(DWORD&, LPCTSTR);
LONG QueryValue(LPTSTR, LPCTSTR, DWORD*);
は、上は数値用、下は文字列用と書いてあり
それ以外の場合は、使わない方が良いかもしれません
MFCのソースを見たところ、事実上問題ないとは思いますし、
たぶん取得できている値とバイト数には問題ないと思いますが
(いずれ実装方法が変更になったらだめな可能性もあります)
デバッグの実行ではエラーがでて面倒なのでWin32APIを使った方が良いと思います
ありがとうございます。
>瀬戸っぷさん
レジストリデータ以上のサイズを指定しても問題ありませんか。
>kuさん
ひょっとして、MFC版はバイナリのレジストリデータを読めないと言うことですか。
> 取得するサイズは丁度のサイズを指定しなければ、強制終了ダイアログが出るような
> 感じなのですが、どのように解決するとよろしいのでしょうか?
違います、多めに取っておく分には問題ありません
1.Win32APIのRegQueryValueExの戻り値がERROR_SUCCESSでなかった場合
2.REG_SZかREG_MULTI_SZかREG_EXPAND_SZ以外のデータタイプの場合
この2つのパターンでエラーがおきます
今回のものはREG_BINARYなので、そのため2が引っかかりエラーとなっています
> 取得するサイズは丁度のサイズを指定しなければ、強制終了ダイアログが出るような
この辺を推測するには、自分でできる限りの情報を集めた方が良いと思います
今回の場合は
1.取得するレジストリをregedit等で調べる
2.使用する関数の仕様を調べる
3.MFCのソースを1stepずつ実行し具体的に何が原因でエラーとなっているか調べる
> レジストリデータ以上のサイズを指定しても問題ありませんか。
問題ないです
> ひょっとして、MFC版はバイナリのレジストリデータを読めないと言うことですか。
僕が持っているVC6.0のMFCのソースを見たところ、このバージョンでは実は読めている
というのが答えですが、たぶんWIN32APIを直接呼ぶのが良いだろうと思います
サイズの取得は、「cRegKey->QueryValue(regData,NULL,&dwSize)」で可能かと。
QueryValue()をループで使う場合には、
下記のようにQueryValue()を使う前に毎回dwSizeにバッファサイズを
設定しないといけません
理由は、QueryValue()を呼ぶとregDataにレジストリのデータを取得できるわけですが
そのデータサイズがdwSizeに入るからです
これは正常にデータの取得ができた場合で、
バッファが小さかった場合はERROR_MORE_DATAが戻り値で
データのサイズがdwSizeに入ります
for (int i = 0; i < 26; i ++){
strKeyName[ posDriveLetter ] = (char)((int)strDriveLetter[0] + i);
DWORD dwSize = 163;
ZeroMemory( regData, dwSize );
ret = cRegKey->QueryValue( regData, (LPCTSTR)strKeyName, &dwSize );
色々とありがとうございます。
>NEG(ねぐ)さん
同じフィールドの種類のデータ幅は同じなんですね。
>kuさん
それで、「ERROR_MORE_DATA」ばかりになったわけですか。
でも、もうWIN32の方に書き換えてしまいました。
すみません。
が、ここでなぜかCドライブがHDDなのにその値が出てくれません。
フロッピーとCDROMのドライブは取得で来ているのですが、
以下のソースでは
---------------------------------------------------------------
DWORD dwType;
DWORD dwLen = MAX_PATH;
char regData[ MAX_PATH ]; // レジストリサイズ分領域を確保
char strRegData[ MAX_PATH ]; // レジストリサイズ分領域を確保
HKEY hKey;
LONG ret;
char strDriveLetter[] = A;
char strKeyName[] = \\DosDevices\\ :;
int posDriveLetter = sizeof( strKeyName ) - 3;
// キーのオープン
ret = RegOpenKeyEx( HKEY_LOCAL_MACHINE, SYSTEM\\MountedDevices, 0,
KEY_READ, &hKey);
if (ret != ERROR_SUCCESS)
return;
// ドライブレターの数だけ繰り返す
for (int i = 0; i < 26; i ++){
strKeyName[ posDriveLetter ] = (char)((int)strDriveLetter[0] + i);
// サイズの取得
ret = RegQueryValueEx( hKey, strKeyName, 0, &dwType, NULL, &dwLen);
if (ret != ERROR_SUCCESS){
continue;
}
dwLen = MAX_PATH;
::ZeroMemory( regData, MAX_PATH );//dwSize + 2 );
// Valueの取得
ret = RegQueryValueEx( hKey, strKeyName, 0, &dwType,
(LPBYTE)regData, &dwLen );
if (ret != ERROR_SUCCESS){
continue;
}
::ZeroMemory( strRegData, MAX_PATH );
// UNICODEから変換する
::WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)regData, -1,
(LPSTR)strRegData, MAX_PATH, 0, 0 );
}
---------------------------------------------------------------
以上で、UNICODEからchar型として読めるように変換したデータが以下のように
なります
現在のPCの構成は
Aドライブ-フロッピー
Cドライブ-HDD
Dドライブ-CDROM
です。
・Aドライブを調べた結果
strRegData 0x0012fc64
\??\FDC#GENERIC_FLOPPY_DRIVE#1&349da29&0&0#{53f5630d-b6bf-11d0-94f2-
00a0c91efb8b}
・Cドライブを調べた結果
strRegData 0x0012fc64 ???
・Dドライブを調べた結果
strRegData 0x0012fc64
\??\IDE#CdRomE-IDE_CD-
ROM_48X#AKU____________________T3A_____#4&13b4afd&0&0.0.0#{53f5630d-b6bf-11d0-
94f2-00a0c91efb8b}
このレジストリ部分には、HDD以外の情報が書き込まれているのですか?
ついでに、外付けCD-RWを追加した時の結果です。
Eドライブ-外付けCD-RW
strRegData 0x0012fc64 \??
\USBSTOR#CdRom&Ven_PHILIPS&Prod_401248_CDRW&Rev_1.0D#000000043413&0#{53f5630d-
b6bf-11d0-94f2-00a0c91efb8b}
http://webclub.kcom.ne.jp/ma/takabin/bcb_code_driveletter.html
内容については全く知らないのですが、ここは役に立ちますか?
レジストリ見てみましたが、R7038XXさんと同じ感じです
OSはWin2000です
HDDについてはUNICODEっぽくないような感じです
>kuさん
実は、ここはすでに目を通しています。
ボーランド系なので、使用する関数などが少し違いますが、
レジストリの取得する場所は一緒になっています。
どうも、このサンプルでもHDDを探しているという部分は無く、
IDE・SCSI・USBそれぞれを調べてはいるのですが、私の結果や
ソース内の記述から、CD-ROMドライブを調べるサンプルだと思われます。