〜 システム 〜
メモリ管理をカスタマイズ (要ADVAPI32.DLL)

MicroSoftの「Tweak UI」や、「窓の手」、「いじくるツール」等…
ウィンドウズ標準の機能では変更できない箇所を操作して環境を改善するツールが存在します。
ソレらの機能はレジストリ内のデータを新規に作成したり、既存の値を変更したりすることで実現しており、
似たような機能を実現するツールの作成や、ツールを導入するまでもなく一部のみをチューニングしたい時に
下記サンプルの要領で操作することでHSPからでも操作可能です。
今回は、メモリ管理「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management」内の
シャットダウン時に仮想メモリを解放する設定「ClearPageFileAtShutdown」、
重要なDLLをメインメモリに置く設定「DisablePagingExecutive」、
ファイルキャッシュサイズの変更「IoPageLockLimit」、
非ページプールサイズの最適化「NonPagedPoolSize」、
2次キャッシュの最適化「SecondLevelDataCache」を操作しています。
各項目がどういう役割をしていて、どのような値が適切なのかは各自検索・検証の上で行ってください。

尚、紹介項目は極一部であり、様々な設定項目があるので、興味がある方はいろいろ探してみてください。
上記項目はXP環境での話であり、OSによって存在しないか機能しない可能性が十分ありますし、
機能する場合であっても、設定することでパソコン自体が壊れてしまう可能性があります。
当然ですが、如何なる問題が発生しようとも当方は責任を負いませんので、
実行はバックアップをした上、自己責任でやるようにしてください。
変更直後は大抵変化が見られないと思いますが、パソコンを再起動させれば設定が有効になります。
全然変化しないからといって無茶な設定をしたままパソコンを終了させてしまい、
次回パソコンを使う際にとんでもないことになってしまわないように注意してください。

レジストリ操作モジュールはコチラコチラで紹介している汎用Tipsを使用しています。
モジュールの詳細については上記の汎用Tipsを紹介しているリンク先のテキストを参照してください。
	

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

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

regsetnum 項目名, データ, キーハンドル, タイプフラグ
項目名 値の名前文字列を指定する。
尚、設定成功すれば0、失敗すればエラーコードがstatに代入される。
データ設定するデータを入れた数値定数または数値型変数を指定する。
キーハンドルregopenkey命令で取得した対象キーのハンドルを指定する。
タイプフラグデータの型を下記から指定する。尚、省略すると通常の数値(=4)となる。
1NULLで終わる文字列
2展開前の環境変数への参照が入った文字列
3バイナリーデータ
432ビット数値(リトルエンディアン形式)
532ビット数値(ビッグエンディアン形式)
6Unicodeシンボリックリンク
7NULLで終わる複数行文字列
8デバイスドライバのリソースリスト
1164ビット数値(リトルエンディアン形式)

regdelvalue キーハンドル, 項目名
キーハンドルregopenkey命令で取得した削除対象キーのハンドルを指定する。
項目名 値の名前文字列を指定する。
尚、削除成功すれば0、失敗すればエラーコードがstatに代入される。

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	ll_libload advapi, "advapi32.dll"
	ll_getproc RegOpenKeyEx, "RegOpenKeyExA", advapi
	ll_getproc RegQueryValueEx, "RegQueryValueExA", advapi
	ll_getproc RegSetValueEx, "RegSetValueExA", advapi
	ll_getproc RegDeleteValue, "RegDeleteValueA", 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 regopenkey val, str, int
	mref hkey, 16 : mref path, 33 : mref sa, 3
	mref stt, 64
	gethkey path
	if stat = 0 : return
	path = refstr
	prm = stat, 0, 0, (sa = 0) * 0x000F003F + sa
	ll_getptr path : ll_ret prm.1
	ll_getptr hkey : ll_ret prm.4
	ll_callfunc prm, 5, RegOpenKeyEx@
	ll_ret prm : stt = prm
	return

#deffunc reggetvalue val, str ,int, int
	mref data, 24 : mref name, 33 : mref hkey, 2 : mref type, 3
	mref stt, 64
	prm = hkey
	i.1 = 256
	ll_getptr name : ll_ret prm.1
	ll_getptr i    : ll_ret prm.3
	ll_getptr data : ll_ret prm.4
	ll_getptr i.1  : ll_ret prm.5
	ll_callfunc prm, 6, RegQueryValueEx@
	ll_ret prm : stt = prm
	if i >= 4 & (i <= 6) | (i = 11) | (type ! 0) : mref data, 16 // 強制的に数値型に変換
	if type : data = i
	return

#deffunc regsetnum str, int, int, int
	mref name, 32 : mref data, 1 : mref hkey, 2 : mref type, 3
	mref stt, 64
	if type = 3 {
		s = "" + data
		strlen i, s
	} else {
		if type = 11 : i = 8 : else : i = 4
	}
	prm = hkey, 0, 0, (type = 0) * 4 + type, 0, i
	ll_getptr name : ll_ret prm.1
	ll_getptr data : ll_ret prm.4
	ll_callfunc prm, 6, RegSetValueEx@
	ll_ret prm : stt = prm
	return

#deffunc regdelvalue int, str
	mref hkey, 0 : mref name, 33
	mref stt, 64
	prm = hkey
	ll_getptr name : ll_ret prm.1
	ll_callfunc prm, 2, RegDeleteValue@
	ll_ret prm : stt = prm
	return

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

#define deffile "RegDefSet.bak" // バックアップファイル名
#define num     5               // 設定項目総数

	onexit *exit
	sdim value, 24, num
	sdim path, 128
	value = "ClearPageFileAtShutdown", "DisablePagingExecutive", "IoPageLockLimit", "NonPagedPoolSize", "SecondLevelDataCache"
	dim dat, num
	notesel bk
	objsize 250, 25
	gethkey "2"
	path = refstr + "\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
	regopenkey key, path
	gosub *reload
	exist deffile
	if strsize = -1 : gosub *backup
	stop

*backup
	repeat num
		if dat.cnt ! -1 : noteadd value.cnt + "=" + dat.cnt
	loop
	notesave deffile
	dialog "元の設定を「" + deffile + "」に保存しました"
	return

*init
	exist deffile
	if strsize = -1 {
		dialog "バックアップファイルが見つかりません", 1
		return
	}
	dialog "元の設定に戻しますか?", 2
	if stat = 7 : return
	noteload deffile
	repeat num
		instr i, bk, value.cnt
		strlen i.1, value.cnt
		if i = -1 {
			regdelvalue key, value.cnt // 元々存在しなかった場合は削除
		} else {
			getstr tmp, bk, i + i.1 + 1, '\n'
			regsetnum value.cnt, 0 + tmp, key // 元の値に書換
		}
	loop
	notfound = 0
	gosub *reload
	stop

*clear
	gosub *reload
	stop

*reload
	redraw 0
	color 255, 255, 255 : boxf : color
	clrobj
	pos  10, 10 : mes "対象キー(参考表示)"
	pos 180, 10 : input path, 450, 20
	if key {
		pos 10,  60 : button "設定初期化(バックアップ読込)", *init
		pos 10,  90 : chkbox "項目が存在しない場合は作成", notfound
		pos 10, 120 : button "設定クリア(レジストリ再読込)", *clear
		pos 10, 150 : button "設定更新", *set
		repeat num
			reggetvalue tmp, value.cnt, key
			pos 10, cnt * 30 + 180 : mes value.cnt
			if stat = 0 | notfound = 1 {
				if stat ! 0 : dat.cnt = 0 : else : dat.cnt = 0 + tmp
				pos 210, cnt * 30 + 180 : input dat.cnt, 50, 20
			} else {
				pos 210, cnt * 30 + 180 : mes "存在しません"
				dat.cnt = -1
			}
		loop
		pos 10, 350 : mes "※存在しない項目は作成チェックを付けて設定クリアをしてください"
	} else {
		pos 10, 60 : mes "キー自体が存在しない場合は更新できません"
	}
	redraw 1
	return

*set
	if key {
		dialog "上記の設定に変更します。\nよろしいですか?", 2
		if stat = 6 {
			repeat num
				reggetvalue tmp, value.cnt, key
				if stat = 0 | notfound = 1 {
					regsetnum value.cnt, dat.cnt, key // 更新
				}
			loop
		}
	}
	stop

*exit
	if key : regclose key

定義済情報 = 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

エラーコード = regopenkey(受取変数, キー文字列, アクセスマスク)
エラーコードオープン成功(=0)したか失敗(=エラーコード)したかの状態受取先を指定する。
受取変数開く対象のキーハンドル受取先変数を指定する。
キー文字列オープンするキーのパス(メインキー+サブキー)を指定する。
アクセスマスク以下に示すキーのセキュリティ権を指定する。
0x0001サブキーデータの問い合わせを許可
0x0002サブキーデータの問い合わせを許可
0x0004サブキーの作成を許可
0x0008サブキーの列挙を許可
0x0010変更の通知を許可
0x0020シンボリックリンクの作成を許可
0x00020006読込系の処理を許可
0x00020019書込系の処理を許可
0x000F003F全ての処理を許可

regsetvalue キーハンドル, 項目名, データ, タイプフラグ
キーハンドル regopenkey命令で取得した対象キーのハンドルを指定する。
尚、設定に成功(=0)したか失敗(=エラーコード)したかの状態がstatに返る。
項目名値の名前文字列を指定する。
データ設定するデータを入れた変数を指定する。
タイプフラグデータの型を下記から指定する。尚、省略すると通常の文字列(=1)となる。
1NULLで終わる文字列
2展開前の環境変数への参照が入った文字列
3バイナリーデータ
432ビット数値(リトルエンディアン形式)
532ビット数値(ビッグエンディアン形式)
6Unicodeシンボリックリンク
7NULLで終わる複数行文字列
8デバイスドライバのリソースリスト
1164ビット数値(リトルエンディアン形式)

regdelvalue キーハンドル, 項目名
キーハンドルregopenkey命令で取得した削除対象キーのハンドルを指定する。
項目名 値の名前文字列を指定する。
尚、削除成功すれば0、失敗すればエラーコードがstatに代入される。

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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#uselib "advapi32.dll"
#cfunc global RegOpenKeyEx "RegOpenKeyExA" int, sptr, int, int, var
#cfunc global RegQueryValueEx "RegQueryValueExA" int, sptr, int, var, var, var
#func  global RegSetValueEx "RegSetValueExA" int, sptr, int, int, var, int
#func  global regdelvalue "RegDeleteValueA" int, sptr
#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

#defcfunc regopenkey var hkey, var path, int sa, local s
	return RegOpenKeyEx(int(gethkey(path)), refstr, , (sa = 0) * 0x000F003F + sa, hkey)

#defcfunc reggetvalue var data, int hkey, str name, int type, local i
	i = 256
	i.1 = RegQueryValueEx(hkey, name, , i.2, data, i)
	if type : data = i.2
	return i.1

#deffunc regsetvalue int hkey, str name, var data, int type, local i
	if type = 0 | type = 1 | type = 2 | type = 6 | type = 7 | type = 8 : data = str(data) : i = strlen(data) + 1
	if type = 4 | type = 5 : data = int(data) : i = 4
	if type = 3 : i = strlen(str(data))
	if type = 11 : i = 8
	RegSetValueEx hkey, name, , (type = 0) * 1 + type, data, i
	return
#global

#define deffile "RegDefSet.bak" // バックアップファイル名

	onexit *exit
	value = "ClearPageFileAtShutdown", "DisablePagingExecutive", "IoPageLockLimit", "NonPagedPoolSize", "SecondLevelDataCache"
	dim dat, length(value)
	notesel bk
	objsize 250, 20
	path = gethkey("2") + "\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"
	dummy = regopenkey(key, path)
	gosub *reload
	exist deffile
	if strsize = -1 : gosub *backup
	stop

*backup
	foreach value
		if dat.cnt ! -1 : noteadd value.cnt + "=" + dat.cnt
	loop
	notesave deffile
	dialog "元の設定を「" + deffile + "」に保存しました"
	return

*init
	exist deffile
	if strsize = -1 {
		dialog "バックアップファイルが見つかりません", 1
		return
	}
	dialog "元の設定に戻しますか?", 2
	if stat = 7 : return
	noteload deffile
	foreach value
		if instr(bk, , value.cnt) = -1 {
			regdelvalue key, value.cnt // 元々存在しなかった場合は削除
		} else {
			getstr tmp, bk, instr(bk, , value.cnt) + strlen(value.cnt) + 1, '\n'
			regsetvalue key, value.cnt, tmp, 4 // 元の値に書換
		}
	loop
	notfound = 0
	gosub *reload
	return

*reload
	redraw 0
	syscolor 15 : boxf : color
	clrobj
	pos  10, 10 : mes "対象キー(参考表示)"
	pos 180, 10 : input path, 450, 20
	if key {
		pos 10,  60 : button gosub "設定初期化(バックアップ読込)", *init
		pos 10,  90 : chkbox "項目が存在しない場合は新規作成", notfound
		pos 10, 120 : button gosub "設定クリア(レジストリ再読込)", *reload
		pos 10, 150 : button gosub "設定更新", *set
		foreach value
			pos 10, cnt * 30 + 180 : mes value.cnt
			if reggetvalue(dat.cnt, key, value.cnt) = 0 | notfound = 1 {
				if reggetvalue(dat.cnt, key, value.cnt) ! 0 : dat.cnt = 0
				pos 210, cnt * 30 + 180 : input dat.cnt, 50, 20
			} else {
				pos 210, cnt * 30 + 180 : mes "存在しません"
				dat.cnt = -1
			}
		loop
		pos 10, 350 : mes "※存在しない項目は新規作成チェックを付けて設定クリアをしてください"
	} else {
		pos 10, 60 : mes "キー自体が存在しない場合は更新できません"
	}
	redraw 1
	return

*set
	if key = 0 : return
	dialog "上記の設定に変更します。\nよろしいですか?", 2
	if stat = 6 {
		foreach value
			if reggetvalue(dummy, key, value.cnt) = 0 | notfound = 1 {
				regsetvalue key, value.cnt, dat.cnt, 4 // 更新
			}
		loop
	}
	return

*exit
	if key : regclose key
	end