WIN32汇编语言教程:第15章 注册表和INI文件 · 15.3 对注册表的操作(7)
3. 查询键属性
在枚举子键和键值项的时候往往会遇到这样一个问题:注册表函数对键值数据的长度并没有限制,在预留缓冲区的时候如果申请太大的内存比较浪费,申请太小的内存则无法枚举成功,对于返回的子键名称和键值项名称也是如此。那么,究竟该留多大的缓冲区呢?其实在枚举之前可以先用RegQueryInfoKey函数查看一下键的统计信息。
RegQueryInfoKey函数返回的信息有:一个键下面子键的数量、键值项的数量、子键名称和键值名称字符串的最大长度及键值数据的最大长度等。根据这些信息,就能方便地申请足够大的缓冲区来保证枚举成功。函数还能返回创建子键时指定的类名和最后一次写入子键的时间等信息。
RegQueryInfoKey函数的用法是:
invoke RegQueryInfoKey,hKey,lpClass,lpcbClass,lpReserved,\
lpcSubKeys,lpcbMaxSubKeyLen,lpcbMaxClassLen,\
lpcValues,lpcbMaxValueNameLen,lpcbMaxValueLen,\
lpcbSecurityDescriptor,lpftLastWriteTime
函数的参数比较多,但并不复杂,各参数的含义是:
● hKey—指定要获取信息的键句柄,键的打开方式中必须包括KEY_QUERY_VALUE。
● lpClass——指向一个缓冲区,用来返回创建键时指定的Class字符串。
● lpcbClass——指向一个双字变量,调用函数时变量中必须放入lpClass指定的缓冲区的长度,函数返回时在这里放入返回到缓冲区中的字符串长度。
● lpReserved——保留参数,必须设置为0。
● lpcSubKeys——指向一个双字,用来返回键中的子键数量。
● lpcbMaxSubKeyLen——指向一个双字,用来返回所有子键中最长的名称字符串长度,返回的长度不包括字符串结尾的0字符。
● lpcbMaxClassLen——指向一个双字,用来返回所有子键中最长的Class字符串长度,返回的长度不包括字符串结尾的0字符。
● lpcValues——指向一个双字,用来返回键下面的键值项数量。
● lpcbMaxValueNameLen——指向一个双字,用来返回所有键值项中最长的名称字符串长度,返回的长度不包括字符串结尾的0字符。
● lpcbMaxValueLen——指向一个双字,用来返回所有键值数据的最大长度。
● lpcbSecurityDescriptor——指向一个双字,用来返回安全描述符的长度。
● lpftLastWriteTime——指向一个FILETIME结构,用来返回最后一次修改键的时间。
可以看到,除hKey外其他的参数都是指针,指向用来返回数据的变量或结构,如果不需要返回某种信息的话,可以将对应的指针参数设置为NULL。另外,所有返回的最长名称字符串长度中都不包括结尾的0字符。
除了前面介绍的函数外,系统中还存在一些不常用的注册表函数,比如可以用RegLoadKey和RegReplaceKey 函数从指定的文件中恢复注册表的子键信息,也可以通过RegSaveKey函数将键信息保存到指定的文件中。另外,可以通过RegConnectRegistry等函数操作远程注册表。对于这些函数,本节就不详细介绍了。
15.3.5 注册表应用举例
曾经有一段时间,注册表修改和优化的工具层出不穷,如魔法兔子、侠客系统修改器和Windows优化大师等都是这方面的典型软件。看了前面的注册表函数后,读者现在一定知道,编写这些软件的大部分时间是花在界面设计和收集注册表的说明资料上,在这些工作的背后,使用的就是这么几个注册表函数。
本节用几个简单的例子来演示一些涉及注册表操作的常见应用,读者在收集到足够的注册表说明资料后,参考这些例子就可以写出类似的应用程序来。
1. 设置开机自动运行
Windows在启动并执行登录操作后,会将HKEY_LOCAL_MACHINE\ Software\Microsoft\ Windows\CurrentVersion\Run子键下的所有键值项枚举一遍,并将所有REG_SZ类型的键值数据字符串当做一个文件名自动执行,所以在这个子键下设置一个键值项,让它的键值数据是某个文件名字符串(也可以是数据文件名,Windows会自动打开关联的可执行文件),就可以让这个文件在Windows启动后自动运行。
Windows只关心键值数据,并不关心键值名称,所以在设置的时候只要保证键值名称是惟一的就可以了。下面的_SetAutoRun子程序就可以用来将程序设置为自动运行:
.const
szKeyAutoRun db 'Software\Microsoft\Windows\CurrentVersion\Run',0
szValueAutoRun db 'AutoRun Test',0 ;在不同程序中使用时修改此字符串!
.code
... ...
;####################################################################
_SetAutoRun proc _dwFlag
local @szFileName[MAX_PATH]:byte
.if _ dwFlag
invoke GetModuleFileName,NULL,addr @szFileName,MAX_PATH
inc eax
invoke _RegSetValue,addr szKeyAutoRun,addr szValueAutoRun,\
addr @szFileName,REG_SZ,eax
.else
invoke _RegDelValue, addr szKeyAutoRun,addr szValueAutoRun
.endif
ret
_SetAutoRun endp
;####################################################################
当用TRUE参数调用_SetAutoRun子程序时,程序将被设置为自动运行,这时子程序先用GetModuleFileName函数获取当前执行文件的文件名,然后用 .const段中定义的szValueAutoRun字符串当做键值项的名称,用文件名当做键值数据在Run键下设置一个键值项。当用FALSE参数调用的时候,程序将取消自动运行,这时子程序仅简单地将前面设置的键值项删除而已。
2. 设置文件关联
如果将一个数据文件与一个可执行文件关联,那么就可以通过双击数据文件来直接执行可执行文件,比如双击以txt为扩展名的文本文件,系统就会自动执行Notepad.exe文件来编辑它,这就是因为txt文件是与Notepad.exe文件关联的。
文件关联是在注册表的HKEY_CLASSES_ROOT根键中设置的。要为某种扩展名设置关联,需要在HKEY_CLASSES_ROOT根键下设置两个子键,第一个子键的名称是“.扩展名”(和数据文件的扩展名相对应),这个子键需要设置默认值,默认值的数据为HKEY_CLASSES_ROOT根键下另一个子键的名称,在这个子键下可以继续设置与这种数据文件关联的可执行文件名。
如果关联的操作方式是“打开”,那么在第二个子键中,可以继续创建“shell\open\ command”子键,并把command子键的默认值设为可执行文件名,这样双击数据文件,就会执行这个可执行文件;如果关联的操作方式是“打印”,那么可以在第二个子键中继续创建“shell\print\command”子键,同样将command子键的默认值设为执行打印操作的可执行文件名。当然,也可以只设置“open”操作的关联。经过这两个步骤,文件关联就设置好了。
以“*.test”数据文件为例,要在HKEY_CLASSES_ROOT根键下创建一个“.test”子键,把它的默认值设置为“testfile”,然后再创建一个“testfile\shell\open\command”子键,并把command键的默认值设置为指定的可执行文件名。
下面这段代码就是将“*.test”数据文件与当前可执行文件关联的子程序,调用_SetExt子程序就可以完成这个功能:
.const
szKeyEnter db 'testfile',0
szKeyExt1 db '.test',0
szKeyExt2 db 'testfile\shell\open\command',0
szParam db ' "%1"',0
.data
... ...
;####################################################################
_SetExt proc
local @hKey
local @szFileName[MAX_PATH]:byte
invoke RegCreateKey,HKEY_CLASSES_ROOT,addr szKeyExt1,addr @hKey
.if eax == ERROR_SUCCESS
invoke RegSetValueEx,@hKey,NULL,NULL,\
REG_SZ,addr szKeyEnter,sizeof szKeyEnter
invoke RegCloseKey,@hKey
.endif
invoke RegCreateKey,HKEY_CLASSES_ROOT,addr szKeyExt2,addr @hKey
.if eax == ERROR_SUCCESS
invoke GetModuleFileName,NULL,addr @szFileName,MAX_PATH
上页:第15章 注册表和INI文件 · 15.3 对注册表的操作(6) 下页:第15章 注册表和INI文件 · 15.3 对注册表的操作(8)