打开注册表的句柄后,就可以对该项进行设置和修改了。注册表是以二元形式存储的,即“键名”和“键值”。通过键名设置键值,而键值可以划分几个类,如下表所示。
表1 键值的分类
在添加和修改注册表键值的时候,要分类进行添加和修改,DDK提供了 ZwSetValueKey 函数来完成这个任务,其函数声明是:
NTSTATUS ZwSetValueKey(IN HANDLE KeyHandle,IN PUNICODE_STRING ValueName,IN ULONG TitleIndex,IN ULONG Type,IN PVOID Data,IN ULONG DataSize);
// KeyHandle: 注册表句柄
// ValueName:要新建或者修改的键名
// TitleIndex: 很少用,一般设为0
// Type: 在表1中选择一种类型
// Data: 记录键值数据
// DataSize: 记录键值数据的大小
// 返回值: 返回新建或者修改的结果
使用 ZwSetValueKey 函数的时候,如果指定的键名不存在,则直接创建,如果指定键名已经存在。则对已有键值进行修改。当新建或者修改键值的时候,根据表1不同的类别,Data指向不同的数据结构,并且用DataSize指明数据大小。例如,REG_DWORD类型,对应的数据大小就是4,REG_QWORD数据类型,数据大小就是8,如果是REG_SZ,数据长度是字符串长度的二倍加上两个字节。下面的代码演示了如何修改和设置键值。
UNICODE_STRING RegUnicodeStr;HANDLE hRegister;// 初始化 UNICODE_STRING 字符串RtlInitUnicodeString(&RegUnicodeStr,MY_REG_SOFTWARE_KEY_NAME);OBJECT_ATTRIBUTES objectAttributes;// 初始化objectAttributesInitializeObjectAttributes(&objectAttributes,&RegUnicodeStr,OBJ_CASE_INSENSITIVE, // 对大小写敏感NULL,NULL);// 打开注册表项NTSTATUS ntStatus = ZwOpenKey(&hRegister,KEY_ALL_ACCESS, &objectAttributes);// 判断操作是否成功if (NT_SUCCESS(ntStatus)){KdPrint(("Open register successfully. \n"));}UNICODE_STRING ValueName;// 初始化 ValueNameRtlInitUnicodeString(&ValueName,L"REG_DWORD value");// 设置 REG_DWORD 子健ULONG ulValue = 1000;ZwSetValueKey(hRegister,&ValueName,0,REG_DWORD,&ulValue,sizeof(ulValue));// 初始化 ValueNameRtlInitUnicodeString(&ValueName, L"REG_SZ value");WCHAR* strValue = L"Hello world";// 设置 REG_SZ 子健ZwSetValueKey(hRegister,&ValueName,0,REG_SZ,strValue,wcslen(strValue) * 2 + 2);// 初始化 ValueNameRtlInitUnicodeString(&ValueName, L"REG_BINARY value");UCHAR buffer[10];RtlFillMemory(buffer, sizeof(buffer), 0xFF);// 设置REG_MULTI_SZ 子健ZwSetValueKey(hRegister,&ValueName,0,REG_BINARY,buffer,sizeof(buffer));// 关闭句柄ZwClose(hRegister);