〜 システム 〜
レジストリにサブキーを作成 (要ADVAPI32.DLL)

レジストリとは何たるかの説明は他所を見てもらえればわかるかと思うので簡単に説明します。
ウィンドウズ3.1以前の「アプリケーションを含むシステムの設定情報」の保存先であった
個々のINIファイルに代わる一元管理が可能なデータベースのことです。
現在でもINIファイルに設定情報を保存するアプリケーションは良くありますが、
レジストリではなくINIファイルばかりだと、バラバラの位置に保存できることで問題が出ました。
大量のINIファイルから目的の情報を検索する時間然り、
他のファイルと同じく、簡単に触れる位置にあることで、誤削除や誤編集をしてしまう点然り。
そこでウィンドウズ95およびNTはレジストリ機能が大幅に拡張されたことに伴い、
根底となるシステム情報の多くはこのレジストリに保存されるようになりました。
不慣れなユーザーが触ることのない離れた場所で保存することで誤操作は減るでしょうし、
INIファイルを使わずレジストリに保存されていることがわかっているのなら、
関係のないファイル数が膨大に増えようとも設定データはファイル数には依存せず、
レジストリを検索させても、そう時間は掛かりません。目視での確認なら時間は掛かるでしょうが…。
ただ、メリットがある反面、デメリットも当然あります。
レジストリに保存している場合、エクスプローラ上から選択削除させるだけでは完全には消えません。
システムの根幹となるならまだしも、ちょっとしたツールやゲーム程度なら
レジストリに保存されることを嫌うユーザーが多いのも実情なので、
自作のツールを公開する際は、少しだけ気をつけるようにしましょう。

さて、レジストリに新しくサブキーを追加するにはAPI関数RegCreateKeyExを使用します。
第1引数には「レジストリエディタ(regedit.exe)を見たことある人は承知の通りの5種類存在する」
以下のメインキーのうちのいずれかを指定します。

HKEY_CLASSES_ROOT(=0x80000000)」  拡張子や関連付け等のファイルそのものに関するキー。通称「HKCR」。 「HKEY_CURRENT_USER(=0x80000001)」  字の如く、現在のログインユーザーに関するキー。通称「HKCU」。 「HKEY_LOCAL_MACHINE(=0x80000002)」  全ユーザー共通のシステム全体の設定に関するキー。通称「HKLM」。 「HKEY_USERS(=0x80000003)」  ウィンドウズの初期情報とユーザー毎の設定に関するキー。通称「HKU」。 「HKEY_CURRENT_CONFIG(=0x80000005)」  現在のシステム設定に関するキー。通称「HKCC」。

0x80000004が飛んでいますが、ソレは「4という数字が縁起悪い数字だから」とかそんな理由ではなく、 下記のように存在はするのですが、上記の5種類とは違って実際のレジストリではないのです。

HKEY_PERFORMANCE_DATA(=0x80000004)」  ウィンドウズ2000等のNT系のみに存在する現在のステータス等の各種情報。 「HKEY_DYN_DATA(=0x80000006)」  ウィンドウズ95や98等の9X系のみに存在する現在のステータス等の各種情報。

第2引数はサブキー名(を格納した変数のポインタ)を指定します。 注意点として、ウィンドウズ9X系では無視されますがNT系だとエラーになるので、 から始まる名称は付けない様にしてください。 第3引数は将来のために予約されたものであり、0を指定してください。 第4引数はサブキーに割り当てられるクラスの文字列(を格納した変数のポインタ)を指定しますが、 現時点では定義されてないので0を指定してください。 第5引数は以下のオプションのうちのいずれかを指定しますが、普通に使うには既定の値で問題ないでしょう。
REG_OPTION_NON_VOLATILE0x0000既定で指定される再起動しても保持されたままのフラグ。
REG_OPTION_VOLATILE0x0001NT系では再起動すると設定情報は失われ、9X系は保持されたままのフラグ。
REG_OPTION_BACKUP_RESTORE0x00049X系は無視され、NT系は第6パラメータ(後述)のキーのバックアップまたは
復元に必要なアクセス要求とともにキーをオープンするフラグ。
第6引数はキーに割り当てるべきセキュリティアクセス権を示すアクセスマスクの組み合わせを指定しますが、 通常はKEY_ALL_ACCESS(=0x000F003F)を指定します。
KEY_QUERY_VALUE0x0001サブキーデータの問い合わせを許可。
KEY_SET_VALUE0x0002サブキーデータの設定を許可。
KEY_CREATE_SUB_KEY0x0004サブキーの作成を許可。
KEY_ENUMERATE_SUB_KEYS0x0008サブキーの列挙を許可。
KEY_NOTIFY0x0010変更の通知を許可。
KEY_CREATE_LINK0x0020シンボリックリンクの作成を許可。
KEY_WRITE0x00020006STANDARD_RIGHTS_WRITE + KEY_CREATE_SUB_KEY + KEY_SET_VALUE
KEY_READ
KEY_EXECUTE
0x00020019STANDARD_RIGHTS_READ + KEY_QUERY_VALUE +
KEY_ENUMERATE_SUB_KEYS + KEY_NOTIFY
KEY_ALL_ACCESS0x000F003FSTANDARD_RIGHTS_REQUIRED + KEY_QUERY_VALUE + KEY_ENUMERATE_SUB_KEYS +
KEY_NOTIFY + KEY_CREATE_SUB_KEY + KEY_CREATE_LINK + KEY_SET_VALUE
第7引数はセキュリティ属性を格納したSECURITY_ATTRIBUTES構造体のアドレスを指定しますが、 特別なことをしない時は0で良い…とあります。 第8引数は当API関数によって作成または開かれたサブキーのハンドルを受け取る変数を指定します。 当API関数を使用した際、既に存在していた場合は二重には作られず開かれるだけですが、 第9引数は作成・オープンのいずれなのかを示す値を受け取る変数を指定します。0なら受け取りません。
REG_CREATED_NEW_KEY0x0001新しくサブキーが作成された。
REG_OPENED_EXISTING_KEY0x0002既に存在しているサブキーを開いた。
パラメータ数は多いのですが、以上で新しくサブキーを作成することが出来ます。 作り終われば、データのセット、キーの確認をする前にキーを一旦解放してあげましょう。 レジストリキーをクローズするAPI関数はRegCloseKeyです。 指定するのは、むろん言うまでもなく、上記の作成またはオープンしたキーです。 冒頭で書いたように重要なシステム情報はレジストリに保存されているので、 仮にレジストリが壊れてしまったら、OSを再インストールするハメになるかもしれませんので、 取り扱いにはくれぐれも慎重にする必要があります。 下記サンプルモジュールでは、statにAPI関数の実行結果の情報が返り、 定義命令・関数に渡す数値型変数に取得したサブキーのハンドルが入ります。 尚、statはAPI関数失敗時には0、キー作成に成功すれば1、キーを開いただけなら2となります。

gethkey キー文字列
キー文字列 定義済キー文字列を指定するとメインキーの定義値を返し、
以下の数値文字列を指定すれば定義済キー文字列を返す。
"0"HKEY_CLASSES_ROOT
"1"HKEY_CURRENT_USER
"2"HKEY_LOCAL_MACHINE
"3"HKEY_USERS
"4"HKEY_PERFORMANCE_DATA
"5"HKEY_CURRENT_CONFIG
"6"HKEY_DYN_DATA

regcreatekey 受取変数, キー文字列, アクセスマスク
受取変数作成したキーハンドルの受取先変数を指定する。
尚、作成に失敗したら0、作成成功なら1、作成済で開いただけなら2がstatに代入される。
キー文字列作成するキーのパス(メインキー+サブキー)を指定する。
アクセスマスク以下に示す作成キーのセキュリティ権を指定する。
0x0001サブキーデータの問い合わせを許可
0x0002サブキーデータの問い合わせを許可
0x0004サブキーの作成を許可
0x0008サブキーの列挙を許可
0x0010変更の通知を許可
0x0020シンボリックリンクの作成を許可
0x00020006読込系の処理を許可
0x00020019書込系の処理を許可
0x000F003F全ての処理を許可

regclose キーハンドル
キーハンドル使い終わって解放する、または設定し終えて更新するキーハンドルを指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
	ll_libload advapi, "advapi32.dll"
	ll_getproc RegCreateKeyEx, "RegCreateKeyExA", advapi
	ll_getproc RegCloseKey, "RegCloseKey", advapi

#module
#deffunc gethkey str
	mref string, 32
	sdim s, 22, 7
	mref stt, 64
	mref rstr, 65
	s.0 = "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS"
	s.4 = "HKEY_PERFORMANCE_DATA", "HKEY_CURRENT_CONFIG", "HKEY_DYN_DATA"
	strmid rstr, string, 0, 1
	if rstr ! "H" {
		i = 0 + rstr
		rstr = s.i
		return
	}
	instr i, string, "\\"
	if i ! -1 : strmid rstr, string, 0, i : else : rstr = string
	stt = 0
	repeat 7
		if s.cnt = rstr {
			stt = 0x80000000 + cnt
			instr i.0, string, "\\"
			strlen i.1, string
			strmid rstr, string, i + 1, i.1 - i.0 - 1
			break
		}
	loop
	return

#deffunc regcreatekey val, str, int
	mref hkey, 16 : mref path, 33 : mref sa, 2
	mref stt, 64
	gethkey path
	if stat = 0 : return
	path = refstr
	prm = stat, 0, 0, 0, 0, (sa = 0) * 0x000F003F + sa
	ll_getptr path : ll_ret prm.1
	ll_getptr hkey : ll_ret prm.7
	ll_getptr i.1  : ll_ret prm.8
	ll_callfunc prm, 9, RegCreateKeyEx@
	ll_ret prm
	if prm : stt = 0 : else : stt = i.1
	return

#deffunc regclose int
	mref hkey, 0
	ll_callfunc hkey, 1, RegCloseKey@
	return
#global

	sdim list, 132
	sdim sub, 256
	dim key, 2
	repeat 7
		if cnt : list += "\n"
		gethkey "" + cnt
		list += refstr
	loop
	index = 1
	sub = "software\\hspbc"
	objsize 250, 20
	pos  10, 10 : mes "メインキー"
	pos 120, 10 : combox index, , list
	pos  10, 40 : mes "サブキー"
	pos 120, 40 : input sub, 250
	pos 120, 70 : button "キーを作成する", *create
	notesel list
	stop

*create
	noteget main, index
	path = main + "\\" + sub
	// サブキーを作成
	regcreatekey key, path
	if stat {
		if stat = 1 {
			dialog "作成に成功しました", , "作成キー:" + key
		} else {
			dialog "キーは既に存在しています", , "オープンキー:" + key
		}
		regclose key // サブキーを閉じる
	} else {
		dialog "[" + path + "]の作成に失敗しました", 1
	}
	stop

定義済情報 = gethkey(キー文字列)
定義済情報定義済情報の受取先を指定する。
キー文字列 定義済キー文字列を指定するとメインキーの定義値を返し、
以下の数値文字列を指定すれば定義済キー文字列を返す。
"0"HKEY_CLASSES_ROOT
"1"HKEY_CURRENT_USER
"2"HKEY_LOCAL_MACHINE
"3"HKEY_USERS
"4"HKEY_PERFORMANCE_DATA
"5"HKEY_CURRENT_CONFIG
"6"HKEY_DYN_DATA

regcreatekey 受取変数, キー文字列, アクセスマスク
受取変数作成したキーハンドルの受取先変数を指定する。
尚、作成に失敗したら0、作成成功なら1、作成済で開いただけなら2がstatに代入される。
キー文字列作成するキーのパス(メインキー+サブキー)を指定する。
アクセスマスク以下に示す作成キーのセキュリティ権を指定する。
0x0001サブキーデータの問い合わせを許可
0x0002サブキーデータの問い合わせを許可
0x0004サブキーの作成を許可
0x0008サブキーの列挙を許可
0x0010変更の通知を許可
0x0020シンボリックリンクの作成を許可
0x00020006読込系の処理を許可
0x00020019書込系の処理を許可
0x000F003F全ての処理を許可

regclose キーハンドル
キーハンドル使い終わって解放する、または設定し終えて更新するキーハンドルを指定する。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#uselib "advapi32.dll"
#cfunc global RegCreateKeyEx "RegCreateKeyExA" int, sptr, int, int, int, int, int, var, var
#func  global regclose "RegCloseKey" int

#module
#defcfunc gethkey str string, local i, local s
	mref rstr, 65
	s.0 = "HKEY_CLASSES_ROOT", "HKEY_CURRENT_USER", "HKEY_LOCAL_MACHINE", "HKEY_USERS"
	s.4 = "HKEY_PERFORMANCE_DATA", "HKEY_CURRENT_CONFIG", "HKEY_DYN_DATA"
	rstr = string
	if strmid(rstr, 0, 1) ! "H" : return s(int(rstr)) // コード指定ならメインキー名を返す
	if instr(rstr, , "\\") ! -1 : rstr = strmid(rstr, 0, instr(rstr, , "\\"))
	foreach s
		if s.cnt = rstr {
			i = 0x80000000 + cnt
			rstr = string
			rstr = strmid(rstr, instr(rstr, , "\\") + 1, strlen(rstr) - instr(rstr, , "\\") - 1)
			break
		}
	loop
	return i // キー指定ならハンドルを返す

#deffunc regcreatekey var hkey, var path, int sa, local i
	if RegCreateKeyEx(int(gethkey(path)), refstr, , , , (sa = 0) * 0x000F003F + sa, 0, hkey, i.1) {
		return 0 // ハンドルが無効
	} else {
		return i.1 // 1:作成成功 2:オープンのみ
	}
#global

	sdim list, 132
	sdim sub, 256
	dim key, 2
	repeat 7
		if cnt : list += "\n"
		list += gethkey(str(cnt))
	loop
	index = 1
	sub = "software\\hspbc"
	objsize 200, 20
	pos  10, 10 : mes "メインキー"
	pos 120, 10 : combox index, , list
	pos  10, 40 : mes "サブキー"
	pos 120, 40 : input sub, 250
	pos 120, 70 : button gosub "キーを作成する", *create
	notesel list
	stop

*create
	noteget main, index
	path = main + "\\" + sub
	// サブキーを作成
	regcreatekey key, path
	if stat {
		if stat = 1 {
			dialog "作成に成功しました", , "作成キー:" + key
		} else {
			dialog "キーは既に存在しています", , "オープンキー:" + key
		}
		regclose key // サブキーを閉じる
	} else {
		dialog "[" + path + "]の作成に失敗しました", 1
	}
	return