论坛风格切换切换到宽版
  • 2512阅读
  • 0回复

深入了解注册表 [复制链接]

上一主题 下一主题
离线海豚
 

发帖
15476
金钱
465513
威望
0
贡献值
1
只看楼主 正序阅读 使用道具 0 发表于: 2007-12-28
1.注册表数据类型 
注册表是一个数据库,它的结构类似于逻辑磁盘驱动器。注册表包含了键(key),类似于磁盘的目录;键值(value),对应磁盘中的文件,键值储存数据(data)。键可以包含子键(subkey)或者键值。最高级别的键是根键,只有根键不是子键。

键和键值都借用了文件系统的命名习惯。例如,保存在键名为 trade ,键值的名字为 mark ,可以通过 trade\mark 唯一确定这个键值。如果键有未命名的键值,两个注册表编辑器的应用程序,Regedit和Regedt32,分别有不同的显示,Regedit显示为:(Default),Regedt32显示为:<No Name>。

键值储存的数据类型可以是Table 5-1列出的11种类型中的一个。注册表键值主要的类型是: REG_DWORD, REG_BINARY, 和 REG_SZ。 REG_DWORD 储存数字或布尔值;REG_BINARY 储存超过32位的数字或者是原始数据,如加密密码;REG_SZ 储存 Unicode 编码的字符串,如名字、文件名、路径和类型等。

图1注册表数据类型

REG_LINK 类型比较特别,因为它可以让一个键值透明地指向另一个键或者键值。当通过链接跨过注册表时,路径搜索会在链接的目标继续。例如,如果 \Root1\Link 有一个 REG_LINK 类型的键值 \Root2\RegKey ,而且 RegKey 包含键值 RegValue ,两个路径可以确定 RegValue :\Root1\Lin[k\RegValue 或者 \Root2\RegKey\RegValue。Windows NT显著地使用注册表链接,注册表6个根键中的3个链接到其余3个没有链接的根键。链接并不保存,它们必须在每次重启动之后动态创建 。

2.注册表逻辑结构 
可以通过注册表储存的数据画出它的组织图。根键不能增加或者删除,总共有6个根键,储存以下信息:见图2
为什么根键的名字以“H”开头?因为根键的名字代表了Win32访问键的句柄。 HKLM 是 HKEY_LOCAL_MACHINE 的缩写。



图3列出了素有根键以及它们的缩写。下面将详细介绍每一个根键的内容和目的。

HKEY_USERS 
HKU包含了系统上每个装载用户的配置和在登记数据库的用户类,同时还包含了一个名为HKU\.DEFAULT的子键,链接到缺省的工作站配置。
HKEY_CLASSES_ROOT 
HKCR包含了两个类型的信息:文件扩展名相关信息和COM类登记信息。每个登记了的文件扩展名都有一个键,大部分键包含一个REG_SZ类型的键值,指向HKCR下另外一个键,该键包含扩展名代表的那类文件的相关信息。例如,HKCR\.xls指向微软Excel文件类信息的另外一个键,如HKCU\Excel.Sheet.8。HKCR下另外的键包含了登记在系统上的COM对象的详细配置信息。
HKEY_CLASSES_ROOT的数据有两个来源:
每一个用户类登记信息在HKCU\SOFTWARE\Classes,对应硬盘文件\Documents and Settings\username\Local Settings\Application Data\Microsoft\Windows\Usrclass.dat。
登记信息系统范围的类在HKLM\SOFTWARE\Classes。
增加每个用户类登记信息是Windows NT的一个新特点,将用户的登记信息与系统范围分开,因此分开的配置文件可以包含用户定制信息。它同时还关闭了一个安全漏洞:微软Windows NT 4,没有权限的用户可以修改或删除HKEY_CLASSES_ROOT下的键,因此影响系统上应用程序的操作。Windows NT,没有权限的用户和应用程序可以读系统范围的数据,但只可以修改它们私有的数据。
HKEY_LOCAL_MACHINE 
HKLM是一个根键,它包含所有系统范围的配置的子键:HARDWARE, SAM, SECURITY, SOFTWARE, 和 SYSTEM。
HKLM\HARDWARE 子键提供了系统的硬件的描述和所有硬件的设备到驱动程序的映射。设备管理器工具可以察看到注册表硬件信息,它只是简单地通过 HARDWARE 键读出键值即可。
HKLM\SAM 子键保存了本地帐号和组信息,如用户密码、组定义和与域(域,是指在一台或多台相关联的主机控制下的网络资源。)相关的信息。Windows NT服务器系统作为域控制器,在Active Directory 中储存了帐号和组,Active Directory 是一个储存域范围的设置和信息的数据库。另外,SAM键包含的安全描述信息在缺省时,被配置成甚至管理者帐号都不能访问,但可以修改成管理者可读。但因为数据并未整理成官方文档,而且密码加密是单方向映射,即不可以从密码的已加密方式来确定密码,所以从中看不出什么信息。
HKLM\SECURITY 子键储存了系统范围的安全策略和用户权限分配。 HKLM\SAM 链接到 SECURITY 的子键 HKLM\SECURITY\SAM 。缺省时,不可以察看 HKLM\SECURITY 或者 HKLM\SAM\SAM的内容,因为那些键的安全性设置成只允许系统帐号访问。
HKLM\SOFTWARE 子键是Windows 储存引导系统时不需要的系统范围的配置信息,也是第三方应用程序储存他们的系统范围的设置,如应用程序的文件和目录的路径,授权和有效期信息。
HKLM\SYSTEM 子键包含了引导系统时需要的系统范围的配置信息,如装载哪些设备驱动程序和启动哪些服务。因为这些信息是启动系统的关键,因此Windows 拷贝了这些信息中的一部分放在这个键下,称为“上一次好的控制集”。如果配置修改了当前控制集,管理者可以选择前一个工作控制集,以防止系统启动。
HKEY_CURRENT_CONFIG 
HKEY_CURRENT_CONFIG只是链接到储存当前硬件配置的HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\Current。硬件配置允许管理者为各种基本系统驱动程序配置设置,尽管一次次引导,潜在的配置可能改变了,但应用程序总可以通过这个键引用当前活动的配置。
HKEY_PERFORMANCE_DATA 
注册表是Windows 访问性能计数器的值的一种机制,计数器的值可以是操作系统组件或者是服务器应用程序。通过注册表访问性能计数器的一个好处就是使远程性能监控更加自由,因为通过普通的注册表API,很容易就可以远程访问注册表。
可以直接通过打开一个特殊的名为HKEY_PERFORMANCE_DATA的键访问注册表性能计数器信息,查询其中的值。在注册表编辑器上不能看到这个键,要看到这个键,只有通过编程,调用Win32注册表函数,如RegQueryValueEx。性能信息实际上并不储存在注册表,注册表函数通过这个键从性能数据提供者处搜寻信息。也可以通过使用PDH(Performance Data Helper)的Pdh.dll提供的函数,访问性能计数器信息。
图4显示了关于访问性能计数器信息的组件

3. 注册表内部
这个部分将讲述执行体子系统中实现注册表的配置管理器是如何组织注册表的磁盘文件,当应用程序和其他操作系统组件读和修改注册表键和键值时,配置管理器如何管理注册表。同时还将讨论配置管理器使用什么机制,尽量确保注册表总是处在一个可修复的状态,甚至当注册表正在修改时,系统崩溃。
注册表文件(Hives)
在磁盘上,注册表不是简单的一个大文件,而是一个集合,由称为“注册表文件(hive)”的分散的文件组成。每个注册表文件包含一个注册表树,有一个键作为树的根或者说是起点,子键及其键值都在根下。你可能会认为注册表编辑器显示的根键与注册表文件中的根键相对应,但其实并不是这样。图5列出了注册表文件和它们在磁盘上的文件名。除了用户配置外,所有注册表文件的路径名都被编进配置管理器。当配置管理器装载注册表文件(包括系统配置文件)时,将每个注册表文件的路径记录在子键HKLM\SYSTEM\CurrentControlSet\Control\hivelist下,当注册表文件卸载时,路径被删除。配置管理器创建根键,并将这些注册表文件链接一起,构造出注册表编辑器所显示的注册表结构。



s上图列出的一些注册表文件是易失性的,没有相关的磁盘文件。易失性是指断电时数据丢失而不可再恢复,系统完全在内存里创建和管理这些注册表文件,因此这些注册表文件是临时的,系统在每次引导时创建。易失性注册表文件的一个例子是HKLM\HARDWARE,储存关于物理设备的信息和设备分配到的资源。每次系统引导时都进行资源分配和检测硬件,所以不将这些数据保存在磁盘上是合理的。
有一个特殊的键类型是符号链接类型,使配置管理器可以链接注册表文件,组织注册表。一个符号链接是一个键改变方向,指向配置管理器的另外一个键。例如,HKLM\SAM是一个链接类型的键,链接到SAM注册表文件的根。
注册表文件结构
配置管理器将一个注册表文件逻辑上分成称为“块”的分配单位,很象文件系统将磁盘分成“蔟”。块的大小定义成4096byte(4K),当有新数据使注册表文件需要扩大时,注册表文件通常以块为粒度增加。注册表文件的第一块是“基块”,基块包含了关于注册表文件的全局信息,当中包括:

签名(regf),表示这个文件是一个注册表文件;
升级序列号;
对注册表文件最后写操作的时间戳;
格式版本号;
校验;
注册表文件的内部文件名,如\Device\HarddiskVolume\WINNT\CONFIG\SAM。

当我们描述数据是如何写到一个注册表文件时,我们将阐明升级序列号和时间戳的重要性。注册表文件文件格式号码指定了注册表文件中的数据格式。从WIndows NT 3.51到Windows NT 4,注册表文件格式有所改变,因此如果尝试在Windows NT较早的版本,装载Windows NT 4或者Windows 2000的注册表文件,会失败。
Windows 组织注册表数据,在注册表文件保存的单位称为“单元(cell)”,一个单元可以保存键,数值,安全描述子,子键的列表,或者键值的列表。在单元数据的开始,有一个字段描述了数据的类型。图6详细描述了每个单元数据类型。单元的头有一个字段,说明单元的大小。当一个单元加入到注册表文件,注册表文件必须扩大到可以包含这个单元。系统创建一个分配单位称为“箱柜(bin)”。一个箱柜是新单元的大小,向上取整到下一个块的边界。在单元的最后到箱柜最后之间的空闲空间,可以分配另外的单元。箱柜有一个头,包含签名(hbin),有一个字段,记录箱柜在注册表文件中的位移以及箱柜的大小。

通过使用箱柜(bin),而不是单元(cell),来跟踪注册表的活动部分,Windows NT简化了一些管理。例如,系统分配和释放箱柜,比起单元来说,不需要那么频繁,可以让配置管理器更有效地管理内存。当配置管理器将一个注册表文件读到内存,它可以选择只读那些包含单元的箱柜,也就是活动箱柜,而忽略空的箱柜。当系统在一个注册表文件中增加和删除单元,空的箱柜会散布在活动箱柜间,这类似于当系统在磁盘上创建和删除文件时发生的磁盘碎片。当一个箱柜成为空,配置管理器将这个空的箱柜与临近的空箱柜联合成一个大的连续的空箱柜。配置管理器还联合临近的删除掉的单元形成一个大的空闲单元。配置管理器从不压缩一个注册表文件,你可以通过 Win32 的值RegSaveKey 和RegReplaceKey 函数压缩注册表,Windows 的 Backup 应用程序也是使用这两个函数。
创建结构注册表文件结构的连接被称为“单元索引号(cell index)”。单元索引号是单元在注册表文件中的位移,单元索引号象一个指针,从一个单元指向另一个单元。配置管理器转换成相对注册表文件的开始的位移。正如Table 5-5中描述的,键类型的单元有一个字段说明它的父键的单元索引号;子键列表类型的单元包含一系列子键的单元索引号。因此,如果想寻找,例如,子键 A 的键单元, A 的父键是 B ,你必须先通过键 B 的子键列表单元索引号寻找包含键 B 的子键列表单元,然后通过子键列表单元中的单元索引号,寻找键 B 的每一个子键,再查看子键的名字是否与你想找的键 A 匹配。
单元、箱柜和块三者很容易被混淆,所以用一个简单的注册表文件布局的例子,帮助你分清它们的不同。图7中显示的简单的注册表文件有一个基块和两个箱柜。第一个箱柜是空的,第二个箱柜包含了若干个单元。注册表文件只有两个键,一个是根键Root,另一个是Root的子键Sub Key。Root有两个键值,Val1 和 Val2。一个子键列表类型的单元定位出根键的子键,一个键值列表类型的单元定位出根键的键值。第二个箱柜中空的单元是空闲空间。图中没有显示这两个键的安全单元,一个注册表文件中也可能会有安全描述子类型的单元。

Internal structure of a registry hive
图8显示了磁盘探测程序(Dskprobe.exe)查看 SYSTEM 注册表文件的第一个箱柜。注意到在图的右上方是箱柜的签名hbin,箱柜签名的下面是键单元的签名nk。因为x86计算机储存数据的方法,因此签名看起来是反的。这个单元是SYSTEM注册表文件的根单元,配置管理器内部将它命名为$$$PROTO.HIV,所以,在nk签名后可以看到名字。
为了优化寻找键值和子键,配置管理器将子键列表单元按字母顺序排列,在子键队列中寻找一个子键,可以进行二元的操作。也就是,先在队列的中间寻找,如果正在寻找的子键的名字在中间子键的前面,配置管理器知道子键在子键队列的前半部,否则,在子键队列的后半部。这个划分过程一直进行到配置管理器找到子键或者找不到匹配的。键值列表单元虽然没有排序,但是新键值通常加在序列的尾部。

单元映射
当访问注册表发生时,配置管理器并不是每一次都访问注册表文件在磁盘上的映像文件,相反,Windows NT在内核的地址空间,保留每个注册表文件的一个版本。当一个注册表文件初始化时,配置管理器确定注册表文件的大小,从内核的分页池分配足够的内存保存它,然后将注册表文件读到内存。因为所有的装载的注册表文件都被读到分页池,所以注册表数据是分页池的最大使用者。

如果注册表文件从不增大,配置管理器就可以把内存中的注册表文件当做一个文件,对它进行所有的管理操作。给出一个单元索引号,配置管理器可以通过简单地将单元索引号相加,计算出单元在内存中的位置,其实就是以内存中的注册表文件映像为基准,在注册表文件中的位移。在系统引导初期,这个过程正是Ntldr对 SYSTEM 注册表文件进行的操作:Ntldr将整个SYSTEM注册表文件读到内存,作为一个只读的注册表文件,以内存中的注册表文件为基准,将单元索引号相加,定位出单元。当增加新的键和键值时,注册表文件需要增大,这意味着系统必须分配分页池的内存去储存新的包含增加的键和键值的箱柜。这样一来,内存分页池中保留注册表数据的内存就没有必要是连续的。

为了处理在内存中储存注册表文件数据的非连续的内存缓冲区,配置管理器采用了一个策略,类似于Windows NT内存管理器将虚拟内存地址映射到物理内存地址。配置管理器采用了一个两级的设计,如图9示,输入一个单元索引号,也就是注册表文件的位移,返回的输出中包括内存中单元索引号所在的块的地址以及单元所在箱柜的内存地址。箱柜可以包含一个或一个以上的块,而注册表文件的增长是以箱柜为单位,因此,Windows NT总是用一个连续的内存缓冲区代表一个箱柜,换句话说,一个箱柜中的所有块在分页池的相同部分。

为了实现映射,配置管理器将一个单元索引号分成3个字段,与内存管理器将虚拟地址分成字段一样。WIndows NT将单元索引号的第一个字段作为单元映射目录的索引号,单元映射目录有1024个入口,每一个入口指向一个单元映射表,每个单元映射表有512个映射入口,映射表中的入口由单元索引号的第二个字段指定,这个入口定位单元所在箱柜和块的内存地址。在映射过程的最后一步,配置管理器将单元索引号最后一个字段作为在先前已确定好的块中的位移,精确地定位出单元在内存中的位置。当一个注册表文件初始化时,配置管理器动态创建映射表,分配一个映射入口给注册表文件中的每一个块,当注册表文件改变大小时,从单元映射目录中增加或删除表。

注册表名字空间和操作
配置管理器通过定义一个“键对象(key object)”的对象类型去统一注册表的名字空间与内核普通的名字空间。配置管理器插入一个名为 Registry 的键对象到Windows NT名字空间的根,作为注册表的入口。Regedit以HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet的形式显示键的名字,但Win32子系统将这样的名字转成对象名字空间的形式,如\Registry\Machine\System\CurrentControlSet。当Windows NT对象管理器分析这个名字时,如果遇到键对象的名字以Registry开头的,就将名字的剩余部分传递给配置管理器。配置管理器继续分析这个名字,在内部的注册表文件树中寻找期望的键或键值。在描述一个典型的注册表操作的控制流程前,需要讨论键对象和键控制块。当应用程序打开或者创建一个注册表键,对象管理器给应用程序一个句柄来引用这个键,与键对象对应的句柄,是配置管理器在对象管理器的帮助下分配的。通过对象管理器的对象支持,配置管理器可以利用对象管理器提供的关于安全和引用计数的功能。

每一个打开的注册表键,配置管理器还分配一个键控制块,储存键的完整的路径名,包括控制块所指的键节点的单元索引号,还包括一个当最后的键句柄关闭时,配置管理器是否需要删除控制块所指的键单元的标志。Windows NT将所有的键控制块组成一个以字母为顺序的二元树,以便可以通过名字快速搜索存在的键控制块。一个键对象指向它对应的键控制块,所以,如果有两个应用程序同时打开相同的注册表键,每一个应用程序将收到一个键对象,而且两个键对象将指向一个共同的键控制块。

当应用程序打开一个存在的注册表键,应用程序首先调用一个注册表API,并在这个注册表API中指定键的名字,该API调用对象管理器的名字分析例程。对象管理器在名字空间遇到配置管理器的注册表键对象时,将路径名传递给配置管理器。配置管理器通过在内存中的注册表文件数据结构,在键和子键中搜索,寻找指定的键。如果配置管理器找到键单元,配置管理器寻找键控制块,确定该键是否被同样的或者是另外的应用程序打开。为了优化,搜索例程总是从最近的一个已经打开的控制块的祖先开始。例如,如果有一个应用程序打开了\Registry\Machine\Key1\Subkey2,\Registry\Machine已经打开,分析例程将\Registry\Machine注册表控制块作为起点。如果键没有被打开,配制管理器分配一个新的键控制块,并插入到控制块树中。然后,配制管理器分配一个键对象指向键控制块,最后将控制返回给对象管理器,由它返回一个句柄给应用程序。

当应用程序创建一个新的注册表键,配置管理器首先找新键的父键单元,然后在新键所在的注册表文件中的空闲单元的队列中搜索一个足够大的空闲单元,作为新键的单元,如果找不到,配置管理器分配一个新的箱柜,将它作为一个单元,并将箱柜剩余的空闲空间放到空闲单元队列中。新键单元填入其相关信息,包括键的名字,配置管理器将新创建的键加到父键的子键列表单元中。最后,将父键的单元索引号储存到新创建的子键的键单元中。

配置管理器通过键控制块的引用计数器确定什么时候删除键控制块。如果在一个键控制块中,所有的指向同一个键的句柄都关闭了,引用计数器就变成0,这标志着这个键控制块已经没有必要存在了。如果有应用程序调用删除键的API设置了删除标志,配置管理器可以从注册表文件中删除相关的键,因为已经没有应用程序打开这个键。

稳定的存储
为了确保一个非挥发性的注册表文件,也就是有磁盘文件对应的注册表文件,总是在一个可恢复的状态,配置管理器使用了注册表文件的日志文件。每一个非挥发性的注册表文件有一个相关的注册表文件的日志文件,是一个隐含文件,有相同的基名和和一个.log的扩展名。例如,在 \Winnt\System32\Config 目录下,如果选择了显示隐含文件和文件夹的选项,就可以看到System.log,Sam.log,和其他.log文件。当一个注册表文件初始化时,配置管理器分配一个位数组,每一位代表注册表文件中一个512Byte部分,或者说是代表注册表文件的1个扇区。这个数组称为脏扇区数组,数组中一个打开(on)的bit意味着系统修改了内存中的注册表文件相应的扇区,必须将修改了的扇区写回注册表文件;一个关闭(off)位意味着对应的扇区与内存中的注册表文件内容相同,都是最新的。

当创建一个新的键或键值,或者修改一个已存在的键或键值,配置管理器在脏扇区数组记录下注册表文件修改了的扇区,然后调度一个懒惰写程序,也称为注册表文件同步操作,在发送请求同步注册表文件5秒后,懒惰写程序的系统线程被唤醒,将内存中所有注册表文件的脏扇区写到磁盘上。这样一来,所有发生在同步请求与同步操作之间的注册表修改在同一时间被刷新。当一个注册表文件同步发生后,下一个同步将发生在5秒后。

如果懒惰写程序只是简单地将所有注册表文件的脏扇区写到注册表文件,如果在写过程系统崩溃,注册表文件就会处在一个不一致状态,而且不可恢复址。为了防止此类事件发生,懒惰写程序首先将注册表文件的脏扇区数组和所有脏扇区备份到注册表文件的记录文件,如果需要的话,扩大记录文件的大小。然后更新注册表文件中基块的序列号,再将脏扇区写到注册表文件。当懒惰写程序完成后,再更新基块中的序列号。这样,当写注册表文件其间,如果系统崩溃,下次引导时,配置管理器将注意到两个注册表文件中的基块的序列号不匹配,配置管理器将用注册表文件的记录文件更新注册表文件的脏扇区。这样,注册表文件可以保持最新和一致性。

为了进一步保护关键的SYSTEM注册表文件的完整性,配置管理器还维护了一个SYSTEM注册表文件的镜像在磁盘上。如果察看在\Winnt\System32\Config目录下的非隐含文件,可以看到三个文件有相同的基名System,分别是System, System.alt, 和 System.sav。System.alt是注册表文件的预备文件,每当同步刷新脏扇区到SYSTEM注册表文件时,同时也更新了System.alt。当系统引导时,如果配置管理器检测到SYSTEM注册表文件被破坏了,就尝试装载注册表文件的预备文件。如果原来的注册表文件虽然被破坏,但还可以使用,配置管理器就用预备文件更新原来的SYSTEM注册表文件。

当Windows NT完成安装时,System.sav是SYSTEM注册表文件的一个拷贝。这个拷贝通常只是在最后的情况下使用,将计算机的配置恢复到最初的状态。

注册表优化
配置管理器只作了少量的显著的性能优化。事实上每个注册表键都有一个安全描述子保护对键的访问,如果在注册表文件中为每个键储存一个唯一的安全描述子拷贝是非常低效的,因为整个注册表的子树经常都使用相同的安全设置。当系统要对一个键实施安全性,配置管理器首先检查键的父键所相关的安全描述子,然后再检查父键所有的子键,如果这些键的安全描述子都匹配系统要给该键实施的安全描述子,配置管理器就只是简单地共享已存在的安全描述子,通过引用计数器跟踪有多少个键共享相同的安全描述子。

配置管理器还优化注册表文件中储存键和键值的名字的方法。尽管注册表是完全兼容Unicode编码,使用Unicode编码指定所有的名字,但如果一个名字只包含ASCII字符,配置管理器就用ASCII的方式在注册表文件中储存这个名字。当配置管理器读这个名字时,例如在进行名字搜索时,它在内存中将这个名字转成Unicode方式。用ASCII方式储存名字可以大大减少注册表文件的大小。

为了降低内存的使用,键控制块并不储存完整的键注册表路径名,而只引用键的名字。例如,指向\Registry\System\Control的键控制块,只使用名字Control,而不是完整的路径。为了进一步优化内存的使用,配置管理器使用键名控制块储存键名,所有键控制块如果有相同的键名,将共享相同的键名控制块。为了优化性能,配置管理器以哈西表的方式储存键控制块的名字以便快速搜索。

为了可以快速访问键控制块,配置管理器在缓冲区中储存经常被访问的键控制块,缓冲区被设置成哈西表的方式。当配置管理器需要寻找一个键控制块时,它首先检查缓冲区。最后,配置管理器还有另外一个缓冲区—延迟关闭表,储存应用程序关闭的键控制块。所以,应用程序可以迅速地再打开一个它最近关闭的键。配置管理器向延迟关闭表中增加最近的关闭的控制块时,删除最旧的键控制块。

解读注册表文件 
如图10示,注册表文件包含以下类型的块:

头块 regf
基块 hbin
键块 nk
键值块 vk
哈希子键列表块 lf
非哈希子键列表块 li
中间键块 ri
每个块有相应的ID,如头块是 regf ,基块是 hbin等。这些ID用于识别注册表文件以及在定位各个块时是否正确。注册表文件是一个树状结构。头块(regf)大小是4096Byte,从注册表文件向下位移4096,就是基块(hbin),基块(hbin)是根键,即键块(nk)的开始,键块(nk)中包含:

1.键值块(vk)的数目及其位移;
2.子键列表块的数目及位移.
通过两个循环,可以遍历上述的块。第一个循环是循环键值块(vk),键值块(vk)中包含了键值的名字及数据的位移。第二个循环是子键列表,子键列表块有三种类型,分别是哈希子键列表块(lf)、非哈希子键列表块(li)和中间键块(ri)。哈希子键列表块(lf)和非哈希子键列表块(li)中都包含了键块(nk)的位移,不同的是,哈希子键列表块中有4个Byte储存了键值块(nk)的名字,但不是完整的名字,按照字母顺序排列,可以方便查找。哈希子键列表块(lf)、非哈希子键列表块(li)指向的键块(nk)可能直接指向键值块(vk),但也可能是子键列表块,这就需要进一步的递归循环,直到最后找到键值(vk)块为止。中间键块(ri)指向的是非哈希子键列表块(li),再由非哈希子键列表块(li)指向键块(nk),循环过程最后都是以键值块(vk)为结束。
注意:
根据MSDN资料,键 CurrentControlSet ,要根据键 select 的值,决定它是 ControlSet001 ,还是 ControlSet002 。如 select 的值是02,CurrentControlSet 其实就是 ControlSet002 。
如果数据的大小比较小,可以直接放在键值块(vk),而不用通过位移,放在其他地方。

好了 结尾了 希望能对大家对注册表的操作有所帮助

评价一下你浏览此帖子的感受

精彩

感动

搞笑

开心

愤怒

无聊

灌水
我爱潜水!
快速回复
限100 字节
 
上一个 下一个