ページ 11

レジストリ操作について教えてください

Posted: 2013年10月02日(水) 16:41
by K.S
VC++2010
C言語
Win32API

ユーザー情報を登録するのにレジストリを使用したいと思っています。
ログイン用ダイアログのコールバック関数で

switch(msg)
{
case WM_INITDIALOG:
RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Software\\ソフト名"),0,KEY_ALL_ACCESS,&hkey);
name = "login_mail";
RegQueryValueEx(hkey,name,NULL,&dwType,(LPBYTE)(LPCTSTR)&data,&dwSize);
if(data)
{
strcpy(szBuf_mail,(LPCSTR)&data);
SetDlgItemText(hwnd,MAIL,(LPSTR)szBuf_mail);
}
省略

このように書き、ログイン用ダイアログ作成と同時にレジストリに登録情報があるかを見に行き、
情報が存在すればログインフォームのエディトボックスに投入されるようにしています。

次にログインフォームですが、

case WM_COMMAND:
switch(LOWORD(wp))
{
case ID_LOGIN://ログインボタン
GetDlgItemText(hwnd,ID_MAIL,(LPSTR)szBuf_mail,(int)sizeof(szBuf_mail));

RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Software\\ソフト名"),0,KEY_ALL_ACCESS,&hkey);

name = "login_mail";
RegSetValueEx(hkey,name,0,REG_SZ,(LPCSTR)szBuf_mail,(int)sizeof(szBuf_mail));

login_flag = LOGIN();
break;
}

レジストリに既に情報が登録されてようが、されてまいがレジストリに新しく情報登録させるようにしています。


1.レジストリに手動で書き込みしたあとにログイン用ダイアログを開くとフォームのエディトボックスに自動で登録情報が投入されます。
2.レジストリに書き込みがされてない状態でログイン用ダイアログを開くとフォームのエディトボックスには投入されていません。
3.フォームに自動投入されたり、手動で新しく入力してログインボタンを押すとレジストリに登録情報が書き込まれます。
4.レジストリにソフトで書き込みをしたあとにログイン用ダイアログを開くとエラーも何も出ずにソフトが終了してしまします。

質問はこの4番の部分の原因と対策を教えてほしいです。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 18:34
by softya(ソフト屋)
codeタグをご利用下さい。ソースコードが見やすくなります。
http://dixq.net/board/board.html#k10
プレビューで表示を確認していただくとミスをする危険が減ります。

気になるのは、RegOpenKeyExなどの戻り値を確認していないのでエラーになっているのでは?と疑っています。
あとレジストリキーもない新規だとレジストリに書き込みが出来ていない気がするんですが、本当に出来ていますでしょうか?

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 19:54
by K.S
softya(ソフト屋) さんが書きました:codeタグをご利用下さい。ソースコードが見やすくなります。
http://dixq.net/board/board.html#k10
プレビューで表示を確認していただくとミスをする危険が減ります。

気になるのは、RegOpenKeyExなどの戻り値を確認していないのでエラーになっているのでは?と疑っています。
あとレジストリキーもない新規だとレジストリに書き込みが出来ていない気がするんですが、本当に出来ていますでしょうか?
ご指摘ありがとうございます。

レジストリキーはその前の段階で作成しています。
書き込みはレジストリエディタで書き込まれているのを確認済みです。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 21:25
by みけCAT
変数dataの型は何ですか?
&がついているのが怪しい気がします。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 21:51
by softya(ソフト屋)
ステップ実行とかはされていますか? どこで抜けてしまうか確認できると思うのですが。
あと、どうしても分からなければ出来るだけ簡単な再現コードを作ってみて下さい。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 21:52
by K.S
みけCAT さんが書きました:変数dataの型は何ですか?
&がついているのが怪しい気がします。
DWORDになっています。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 21:54
by みけCAT
IDがID_MAILであるコントロール(おそらくメールの入力欄?)に半角2文字だけ入力し、テストしてみてください。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 21:55
by softya(ソフト屋)
K.S さんが書きました:
みけCAT さんが書きました:変数dataの型は何ですか?
&がついているのが怪しい気がします。
DWORDになっています。
文字列をDWORDで受けていると言うことですか?

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:01
by K.S
みけCAT さんが書きました:IDがID_MAILであるコントロール(おそらくメールの入力欄?)に半角2文字だけ入力し、テストしてみてください。
aaaと入力すると期待する結果が得られました。
しかし、自分のメールアドレス(30文字程度)を入力するとエラーも出ずに消えてしまいました。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:03
by みけCAT
K.S さんが書きました:aaaと入力すると期待する結果が得られました。
しかし、自分のメールアドレス(30文字程度)を入力するとエラーも出ずに消えてしまいました。
予想通りの結果です。
DWORD型は4バイトのことが多いので、どう考えてもバッファが足りません。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:04
by みけCAT
RegQueryValueExを呼ぶ前に、dwSizeに代入している値はいくつですか?もしくは、どういう値を代入していますか?(~関数の戻り値など)

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:05
by K.S
softya(ソフト屋) さんが書きました:
K.S さんが書きました:
みけCAT さんが書きました:変数dataの型は何ですか?
&がついているのが怪しい気がします。
DWORDになっています。
文字列をDWORDで受けていると言うことですか?
すみません。
別の関数内のdataを見てました。
正しくはLPSTR型です。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:07
by K.S
みけCAT さんが書きました:RegQueryValueExを呼ぶ前に、dwSizeに代入している値はいくつですか?もしくは、どういう値を代入していますか?(~関数の戻り値など)
関数の戻り値にはしていません。
最初に
DWORD dwType;
としてるだけです。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:09
by みけCAT
K.S さんが書きました:すみません。
別の関数内のdataを見てました。
正しくはLPSTR型です。
ポインタは、32ビットの環境なら4バイト、64ビットの環境なら8バイトのことが多いと思います。
バッファ不足には変わりありません。
K.S さんが書きました:関数の戻り値にはしていません。
最初に
DWORD dwType;
としてるだけです。
未初期化ですね。
一度RegQueryValueEx関数の仕様を見てみてください。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:16
by softya(ソフト屋)
K.S さんが書きました:
softya(ソフト屋) さんが書きました: 文字列をDWORDで受けていると言うことですか?
すみません。
別の関数内のdataを見てました。
正しくはLPSTR型です。
変数名だけで間違いがおきて危険なので、型を表す名前にしたほうが良いですね。
RegQueryValueEx(hkey,name,NULL,&dwType,(LPBYTE)(LPCTSTR)&data,&dwSize);
だとdataがLPSTRだと&dataでポインタのポインタって事になりますので、キャストが強引でかつ&いらないです。
つまり引数の書き方が間違っていて大変危険です。
(LPBYTE)data
で通りませんか?

それとdataがLPSTRだそうですが、ポインタ値は代入済みですか?
ポインタ値が正しい値で、かつ呪文な文字列を受ける大きさの領域のポインタ値じゃないとメモリ破壊をすることになります。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:37
by K.S
ちょっと気になったのですが、
メールの取得のすぐあとに同じような書き方でパスワードの取得もしています。

コード:

	switch(msg)
	{
		case WM_INITDIALOG:
			RegOpenKeyEx(HKEY_CURRENT_USER,TEXT("Software\\ソフト名"),0,KEY_ALL_ACCESS,&hkey);

			name = "login_mail";
			RegQueryValueEx(hkey,name,NULL,&dwType,(LPBYTE)(LPCTSTR)&data,&dwSize);

			if(data)
			{
				strcpy(szBuf_mail,(LPCSTR)&data);
				SetDlgItemText(hwnd,MAIL,(LPSTR)szBuf_mail);
			}

			name = "login_passwd";
			RegQueryValueEx(hkey,name,NULL,&dwType,(LPBYTE)(LPCTSTR)&data,&dwSize);

			if(data)
			{
				strcpy(szBuf_pass,(LPCSTR)&data);
				SetDlgItemText(hwnd,ID_PASS,(LPSTR)szBuf_pass);
			}

			RegCloseKey(hkey);
書き方はまったく一緒なのですが、メールの取得(ここで言う9~13行目)までをコメントアウトさせるとアプリケーションの終了はなく、
パスワードのエディトボックスの方に値が投入されます。
これはパスワードの長さに関係なく文字列が1文字でも30文字でもエラーにはなりません。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:42
by softya(ソフト屋)
K.S さんが書きました:ちょっと気になったのですが、
メールの取得のすぐあとに同じような書き方でパスワードの取得もしています。

書き方はまったく一緒なのですが、メールの取得(ここで言う9~13行目)までをコメントアウトさせるとアプリケーションの終了はなく、
パスワードのエディトボックスの方に値が投入されます。
これはパスワードの長さに関係なく文字列が1文字でも30文字でもエラーにはなりません。
たまたま動くことも有るので、それは何の保証にもなりません。
確かなことは、必要なバッファを必要なサイズだけ用意してなかったら、どんな動作をするかは保証できないということです。

【補足】あとC言語の文法を正しく使ってないと、も付け加えておきます。ポインタは色々と危険なのです。

Re: レジストリ操作について教えてください

Posted: 2013年10月02日(水) 22:46
by みけCAT
投入された値は本当にレジストリに書き込まれているパスワードですか?
PasswordEyeで調べることができます。