Windows内核编程之:注册表操作

注册表项:注册表中的一个项目,类似于目录的概念
注册表子项:类似于目录中的子目录
键名:通过键名可以寻找到相应的键值
键值类别:每个键值存储的时候有不同的类别,可以是整形,字符串等数据
键值:键名下对应存储的数据

1、创建关闭注册表

/************************************************************************
* 函数名称:ZwCreateKey
* 功能描述:打开注册表句柄
* 参数列表:
        KeyHandle:获得的注册表句柄
        DesiredAccess:访问权限,一般设置为KEY_ALL_ACCESS
        ObjectAttributes:OBJECT_ATTRIBUTES数据结构
        TitleIndex:很少用到,一般设置为0
        Class:很少用到,一般设置为NULL
        CreateOptions:创建时的选项,一般设置为REG_OPTION_NON_VOLATILE
        Disposition:返回时创建成功,还是打开成功。返回值是REG_CREATED_NEW_KEY
        或者REG_OPENED_EXISTING_KEY
* 返回值:
*************************************************************************/
NTSTATUS ZwCreateKey(
OUT PHANDLE KeyHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
IN ULONG TitleIndex,
IN PUNICODE_STRING Class OPTIONAL,
IN ULONG CreateOptions,
OUT PULONG Disposition OPTIONAL);
/*
*注意:
*    如果ZwCreateKey指定的项目不存在,则直接创建这个项目
*    并利用Disposition参数返回REG_CREATED_NEW_KEY
*    如果项目已经存在了,Disposition参数返回REG_OPENED_EXISTING_KEY
*/

演示如何使用ZwCreateKey函数打开注册表

//创建或打开某个注册表项目
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;
#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
    MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
    &RegUnicodeString,
    OBJ_CASE_INSENSITIVE, //对大小写敏感
    NULL,
    NULL);

ULONG ulResult;
//创建或打开注册表项目
NTSTATUS ntStatus = ZwCreateKey(&hRegister,
    KEY_ALL_ACCESS,
    &objectAttributes,
    0,
    NULL,
    REG_OPTION_NON_VOLATILE,
    &ulResult);

if( NT_SUCCESS(ntStatus) )
{
    //判断是被新创建,还是已经被创建
    if(ulResult == REG_CREATED_NEW_KEY)
    {
        KdPrint(("The register item is created\n"));
    }
    else if(ulResult == REG_OPENED_EXISTING_KEY)
    {
        KdPrint(("The register item has been created, and now is opened\n"));
    }
}

//创建或打开某注册表项目的子项
UNICODE_STRING subRegUnicodeString;
HANDLE hSubRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&subRegUnicodeString,
    L"SubItem");
OBJECT_ATTRIBUTES subObjectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&subObjectAttributes,
    &subRegUnicodeString,
    OBJ_CASE_INSENSITIVE, //对大小写敏感
    hRegister,
    NULL);

//创建或打开注册表项目
NTSTATUS ntStatus = ZwCreateKey(&hSubRegister,
    KEY_ALL_ACCESS,
    &subObjectAttributes,
    0,
    NULL,
    REG_OPTION_NON_VOLATILE,
    &ulResult);

if( NT_SUCCESS(ntStatus) )
{
    //判断是被新创建,还是已经被创建
    if(ulResult == REG_CREATED_NEW_KEY)
    {
        KdPrint(("The register item is created\n"));
    }
    else if(ulResult == REG_OPENED_EXISTING_KEY)
    {
        KdPrint(("The register item has been created, and now is opened\n"));
    }
}

//关闭注册表句柄
ZwClose(hRegister);
ZwClose(hSubhRegister);

 2、打开注册表

/************************************************************************
* 函数名称:ZwOpenKey
* 功能描述:打开注册表
* 参数列表:
        KeyHandle:返回被打开的句柄
        DesiredAccess:打开的权限,一般设为KEY_ALL_ACCESS
        ObjectAttributes:OBJECT_ATTRIBUTES 数据结构,指示打开的状态
* 返回 值:返回是否打开成功
*************************************************************************/
NTSTATUS ZwOpenKey(
    OUT PHANDLE KeyHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes);
/*
*注意:
*    如果ZwOpenKey指定的项不存在,不会创建这个项目
*    而是返回一个错误状态
*/

演示如何使用ZwOpenKey打开注册表项目

#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
                     MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                           &RegUnicodeString,
                           OBJ_CASE_INSENSITIVE, //对大小写敏感
                           NULL,
                           NULL);

//打开注册表
NTSTATUS ntStatus = ZwOpenKey(&hRegister,
                              KEY_ALL_ACCESS,
                              &objectAttributes);
//判断操作是否成功
if( NT_SUCCESS(ntStatus) )
{
    KdPrint(("Open register successfully\n"));
}

//关闭句柄
ZwClose(hRegister);

3、添加、修改注册表键值

键值的分类

分类                    描述
REG_BINARY            键值用二进制存储
REG_SZ                键值用宽字符串,字符串以\0的结尾
REG_EXPAND_SZ         键值用宽字符串,字符串以\0的结尾,该字符串是扩展的字符
REG_MULTI_SZ          键值存储多个字符串,每个字符串以\0隔开
REG_DWORD             键值用4字节整形存储
REG_QWORD             键值用8字节存储
/************************************************************************
* 函数名称:ZwSetValueKey
* 功能描述:在添加和修改注册表键值的时候,要分类进行添加和修改
* 参数列表:
        KeyHandle:注册表句柄
        ValueName:要新建或者修改的键名
        TitleIndex:很少用,一般设为0
        Type:在表中选择一种类型
        Data:键值数据
        DataSize:记录键值数据的大小
* 返回 值:返回新建或者修改的结果
*************************************************************************/
NTSTATUS ZwSetValueKey(
    IN HANDLE KeyHandle,
    IN PUNICODE_STRING ValueName,
    IN ULONG TitleIndex OPTIONAL,
    IN ULONG Type,
    IN PVOID Data,
    IN ULONG DataSize);

/*
*注意:
*    使用ZwSetValueKey函数的时候,
*    如果指定的键名不存在,则直接创建。
*    如果指定的键名已存在,则对已有键值进行修改
*/

演示如何修改和设置键值

#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
                     MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                           &RegUnicodeString,
                           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;
//初始化ValueName
RtlInitUnicodeString(&ValueName, L"REG_DWORD value");

//设置REG_DWORD 子键
ULONG ulValue = 1000;
ZwSetValueKey(
    hRegister,
    &ValueName,
    0,
    REG_DWORD,
    &ulValue,
    sizeof(ulValue));

//初始化ValueName
RtlInitUnicodeString(&ValueName, L"REG_SZ value");
WCHAR* strValue = L"hello world";

//设置REG_SZ 子键
ZwSetValueKey(
    hRegister,
    &ValueName,
    0,
    REG_SZ,
    &strValue,
    wcslen(strValue) * 2 + 2);

//初始化ValueName
RtlInitUnicodeString(&ValueName, L"REG_BINARY value");
UCHAR buffer[10];
RtlFillMemory(buffer, sizeof(buffer), 0XFF);

//设置REG_BINARY 子键
ZwSetValueKey(
    hRegister,
    &ValueName,
    0,
    REG_BINARY,
    buffer,
    sizeof(buffer));

//关闭句柄
ZwClose(hRegister);

4、查询注册表

/************************************************************************
* 函数名称:ZwQueryValueKey
* 功能描述:对注册表的项进行查询,从而获取注册表的键值
* 参数列表:
        KeyHandle:打开的注册表句柄
        ValueName:要查询的键名
        KeyValueInformationClass:根据KeyValueInformation的不同选择不同的查询类别
        KeyValueInformation:选择一种查询类别
            KeyValueBasicInformation:查询基本信息
            KeyValueFullformation:查询全部信息
            KeyValuePartialInformation:查询部分信息
            每种查询类型会有对应的一种数据结构获得查询结果
        Length:要查数据的长度
        ResultLength:实际查询数据的长度
* 返回值:表示查询数据是否成功
*************************************************************************/
NTSTATUS ZwQueryValueKey(
    IN HANDLE KeyHandle,
    IN PUNICODE_STRING ValueName,
    IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
    OUT PVOID KeyValueInformation,
    IN ULONG Length,
    OUT PULONG ResultLength);
/************************************************************************
*1、KeyValuePartialInformation可以查询键值的数据,
*    它对应的查询数据结构是KEY_VALUE_PARTIAL_INFORMATION
*************************************************************************/
typedef struct KEY_VALUE_PARTIAL_INFORMATION{
    ULONG TitleIndex;
    ULONG Type;//数据的类型,查询键值的分类
    ULONG DataLength;//数据的长度
    UCHAR Data[1]; //数据指针,这里是变长的数据
}KEY_VALUE_PARTIAL_INFORMATION, *PKEY_VALUE_PARTIAL_INFORMATION;

/*
*注意:KEY_VALUE_PARTIAL_INFORMATION的数据结构长度不固定
*    所以首先要确定这个长度
*    一般使用ZwQueryValueKey分为4个步骤:
*1、用ZwQueryValueKey获取这个数据结构的长度
*2、分配入册长度的内存,用来查询
*3、再次调用ZwQueryValueKey,获取键值
*4、回收内存
*/

查询注册表的示例代码

#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
                     MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                           &RegUnicodeString,
                           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;
//初始化ValueName
RtlInitUnicodeString(&ValueName, L"REG_DWORD value");

//读取REG_DWORD子键
ULONG ulSize;
ntStatus = ZwQueryValueKey(hRegister,
                           &ValueName,
                           KeyValuePartialInformation,
                           NULL,
                           0,
                           &ulSize);

if(ntStatus == STATUS_OBJECT_NAME_NOT_FOUND || ulSize == 0)
{
    ZwClose(hRegister);
    KdPrint("The item is not exist\n");
    return;
}

PKEY_VALUE_PARTIAL_INFORMATION pvpi = 
    (PKEY_VALUE_PARTIAL_INFORMATION)
    ExAllocatePool(PagedPool, ulSize);

//查询注册表
ntStatus = ZwQueryValueKey(hRegister,
                           &ValueName,
                           KeyValuePartialInformation,
                           pvpi,
                           ulSize,
                           &ulSize);

if(!NT_SUCCESS(ntStatus))
{
    ZwClose(hRegister);
    KdPrint(("Read register ERROR\n"));
    return;
}

//判断是否REG_DWORD类型
if(pvpi->Type == REG_DWORD && pvpi->DataLength == sizeof(ULONG))
{
    PULONG pulValue = (PULONG)pvpi->Data;
    KdPrint(("The value:%d\n", *pulValue));
}

ExFreePool(pvpi);

//初始化ValueName
RtlInitUnicodeString(&ValueName, L"REG_SZ value");
//读取REG_SZ子键
ntStatus = ZwQueryValueKey(hRegister,
                           &ValueName,
                           KeyValuePartialInformation,
                           NULL,
                           0,
                           &ulSize);
if(ntStatus == STATUS_OBJECT_NAME_NOT_FOUND || ulSize == 0)
{
    ZwClose(hRegister);
    KdPrint("The item is not exist\n");
    return;
}

pvpi = 
    (PKEY_VALUE_PARTIAL_INFORMATION)
    ExAllocatePool(PagedPool, ulSize);

//查询注册表
ntStatus = ZwQueryValueKey(hRegister,
                           &ValueName,
                           KeyValuePartialInformation,
                           pvpi,
                           ulSize,
                           &ulSize);

if(!NT_SUCCESS(ntStatus))
{
    ZwClose(hRegister);
    KdPrint(("Read register ERROR\n"));
    return;
}

if(pvpi->Type == REG_SZ)
{
    KdPrint(("The value:%S\n", pvpi->Data));
}

//关闭句柄
ZwClose(hRegister);

 5、枚举子项

/************************************************************************
* 函数名称:ZwQueryKey
* 功能描述:获得某注册表项究竟有多少个子项
* 参数列表:
        KeyHandle:获得的注册表句柄
        KeyInformationClass:查询的类别,一般选择KeyFullInformation
        KeyInformation:查询的数据指针。
            如果KeyInformationClass是KeyFullInformation
            则该指针指向一个KEY_FULL_INFORMATION的数据结构
        Length:数据长度
        ResultLength:返回的数据长度
* 返回值:查询是否成功
*************************************************************************/
NTSTATUS ZwQueryKey(
    IN HANDLE KeyHandle,
    IN KEY_INFORMATION_CLASS KeyInformationClass,
    OUT PVOID KeyInformation,
    IN ULONG Length,
    OUT PULONG ResultLength
);
/*
*备注:
*    1、使用ZwQueryKey时,可以将参数KeyInformationClass指定为KeyFullInformation
* 这样参数KeyInformation就对应一个KEY_FULL_INFORMATION数据结构,该数据结构中的
* SubKeys指明了项中有多少个子项
*    2、KEY_FULL_INFORMATION数据结构的大小是变长的,所有要调用两次ZwQueryKey。
* 第一次获取KEY_FULL_INFORMATION数据的长度,第二次真正获取KEY_FULL_INFORMATION
* 数据
*/
/************************************************************************
* 函数名称:ZwEnumerateKey
* 功能描述:针对第几个子项获取该子项的具体信息
* 参数列表:
        KeyHandle:获得的注册表句柄
        Index:很好用到,一般为0
        KeyInformationClass:查询的类别,一般选择KeyFullInformation
        KeyInformation:该子项的信息
        Length:子项信息的长度
        ResultLength:返回子键信息的长度
* 返回值:查询是否成功
*************************************************************************/
NTSTATUS ZwEnumerateKey(
    IN HANDLE KeyHandle, 
    IN ULONG Index, 
    IN KEY_INFORMATION_CLASS KeyInformationClass, 
    OUT PVOID KeyInformation,
    IN ULONG Length,
    OUT PULONG ResultLength
);
/*
*备注:
*    1、使用ZwEnumerateKey时,可以将参数KeyInformationClass指定为
* KeybasicInformation
* 这样参数KeyInformation就对应一个KEY_BASIC_INFORMATION数据结构
*    2、KEY_BASIC_INFORMATION数据结构的大小是变长的,所有要调用两次
* ZwEnumerateKey。第一次获取KEY_BASIC_INFORMATION数据的长度,第二
* 次真正获取KEY_BASIC_INFORMATION数据
*/

如何枚举子项

#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
    MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
    &RegUnicodeString,
    OBJ_CASE_INSENSITIVE, //对大小写敏感
    NULL,
    NULL);

//打开注册表
NTSTATUS ntStatus = ZwOpenKey(&hRegister,
    KEY_ALL_ACCESS,
    &objectAttributes);

if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Open register successfully\n"));
}

ULONG ulSize;
//第一次调用ZwQueryKey,为了获取KEY_FULL_INFORMATION数据的长度
ZwQueryKey(hRegister,
    KeyFullInformation,
    NULL,
    0,
    &ulSize);

PKEY_FULL_INFORMATION pfi = 
    (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);

//第二次调用ZwQueryKey,为了获取KEY_FULL_INFORMATION数据
ZwQueryKey(hRegister,
    KeyFullInformation,
    pfi,
    ulSize,
    &ulSize);

for(ULONG i = 0; I < pfi->SubKeys; i++)
{
    //第一次调用ZwEnumerateKey,为了获取KEY_BASIC_INFORMATION数据的长度
    ZwEnumerateKey(hRegister,
        i,
        KeyBasicInformation,
        NULL,
        0,
        &ulSize);

    PKEY_BASIC_INFORMATION pbi = 
        (PKEY_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);

    //第二次调用ZwEnumerateKey,为了获取KEY_BASIC_INFORMATION数据
    ZwEnumerateKey(hRegister,
        i,
        KeyBasicInformation,
        pbi,
        ulSize,
        &ulSize);

    UNICODE_STRING uniKeyName;
    uniKeyName.Length =
    uniKeyName.MaximumLength =
    (USHORT)pbi->NameLength;
    uniKeyName.Buffer = pbi->Name;
    KdPrint(("The %d sub item name:%wZ\n", i, &uniKeyName));
    //回收内存
    ExFreePool(pbi);
}

//回收内存
ExFreePool(pfi);
//关闭句柄
ZwClose(hRegister);

6、枚举子键

/*
*备注:
*    1、枚举子键是通过ZwQueryKey和ZwEnumerateValueKey
* 两个函数的配合完成的
*    2、ZwEnumerateValueKey函数的使用和ZwEnumerateKey
* 函数的使用类似
*/

演示枚举子键

#define  MY_REG_SOFTWARE_KEY_NAME L"\\Registry\\Machine\\Software\\Itao"
UNICODE_STRING RegUnicodeString;
HANDLE hRegister;

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
    MY_REG_SOFTWARE_KEY_NAME);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
    &RegUnicodeString,
    OBJ_CASE_INSENSITIVE, //对大小写敏感
    NULL,
    NULL);

//打开注册表
NTSTATUS ntStatus = ZwOpenKey(&hRegister,
    KEY_ALL_ACCESS,
    &objectAttributes);

if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Open register successfully\n"));
}

ULONG ulSize;
//第一次调用ZwQueryKey,为了获取KEY_FULL_INFORMATION数据的长度
ZwQueryKey(hRegister,
    KeyFullInformation,
    NULL,
    0,
    &ulSize);

PKEY_FULL_INFORMATION pfi = 
    (PKEY_FULL_INFORMATION)ExAllocatePool(PagedPool, ulSize);

//第二次调用ZwQueryKey,为了获取KEY_FULL_INFORMATION数据
ZwQueryKey(hRegister,
    KeyFullInformation,
    pfi,
    ulSize,
    &ulSize);

for(ULONG i = 0; i < pfi->Values; i++)
{
    //枚举注册表
    ZwEnumerateValueKey(hRegister,
        i,
        KeyValueBasicInformation,
        NULL,
        0,
        &ulSize);

    PKEY_VALUE_BASIC_INFORMATION pvbi = 
        (PKEY_VALUE_BASIC_INFORMATION)ExAllocatePool(PagedPool, ulSize);

    //枚举注册表
    ZwEnumerateValueKey(hRegister,
        i,
        KeyValueBasicInformation,
        pvbi,
        ulSize,
        &ulSize);

    UNICODE_STRING uniKeyName;
    uniKeyName.Length =
    uniKeyName.MaximumLength =
    (USHORT)pvbi->NameLength;
    uniKeyName->Buffer = pvbi->Name;
    KdPrint(("The %d sub value name:%wZ\n", i, &uniKeyName));

    if(pvbi->Type == REG_SZ)
        KdPrint(("The Sub value type:REG_SZ\n"));
    else if(pvbi->Type == REG_MULTI_SZ)
        KdPrint(("The Sub value type:REG_MULTI_SZ\n"));
    else if(pvbi->Type == REG_DWORD)
        KdPrint(("The Sub value type:REG_DWORD\n"));
    else if(pvbi->Type == REG_BINARY)
        KdPrint(("The Sub value type:REG_BINARY\n"));

    //回收内存
    ExFreePool(pbi);
}

//回收内存
ExFreePool(pfi);
//关闭句柄
ZwClose(hRegister);

 7、删除子项

/************************************************************************
* 函数名称:ZwDeleteKey
* 功能描述:删除子项
* 参数列表:
        KeyHandle:打开的文件句柄
* 返回值:是否删除成功
*************************************************************************/
NTSTATUS ZwDeleteKey(
    IN HANDLE KeyHandle
    );

/*
*注意:
*    该函数只能删除没有子项的项目
*    如果项中还有子项,则不能删除
*    需要先将该项中的所有子项全部删除后,再删除该项
*/

演示如何在驱动程序中删除子项

UNICODE_STRING RegUnicodeString;
HANDLE hRegister;
#define MY_REG_SOFTWARE_KEY_NAME1 L"Registry\\Machine\\Software\\Itao\\SubItem"

//初始化UNICODE_STRING字符串
RtlInitUnicodeString(&RegUnicodeString,
                     MY_REG_SOFTWARE_KEY_NAME1);

OBJECT_ATTRIBUTES objectAttributes;
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
                    &RegUnicodeString,
                    OBJ_CASE_INSENSITIVE, //对大小写敏感
                    NULL,
                    NULL);

//打开注册表
NTSTATUS ntStatus = ZwOpenKey(&hRegister,
                              KEY_ALL_ACCESS,
                              &objectAttributes);

//判断操作是否成功
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Open register successfully\n"));
}

//删除注册表键
ntStatus = ZwDeleteKey(hRegister);
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("DELETE the item successfully\n"));
}
else if(ntStatus == STATUS_ACCESS_DENIED)
{
    KdPrint(("STATUS_ACCESS_DENIED\n"));
}
else if(ntStatus == STATUS_INVALID_HANDLE)
{
    KdPrint(("STATUS_INVALID_HANDLE\n"));
}
else
{
    KdPrint(("Maybe the item has sub item to delete\n"));
}
//关闭句柄
ZwClose(hRegister);

8、其他

/*
*        RtlXX关于注册表的操作
*    分类                                描述
*RtlCreateRegistryKey                 创建注册表
*RtlCheckRegistryKey                  查看某注册表项是否存在
*RtlWriteRegistryValue                写注册表
*RtlDeleteRegistryValue               删除注册表的子键
*/

演示如何在驱动程序中使用这些函数

//创建子项
NTSTATUS ntStatus = RtlCreateRegistryKey(
            RTL_REGISTRY_SERVUCES, 
            L"HelloDDK\\Itao");
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Create the item successfully\n"));
}

//检测某项是否存在
ntStatus = RtlCheckRegistryKey(
    RTL_REGISTRY_SERVUCES, 
    L"HelloDDK\\Itao");
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("The item is exist\n"));
}

//写入REG_DWORD的数据
ULONG value1 = 100;
ntStatus = RtlWriteRegistryValue(
    RTL_REGISTRY_SERVUCES, 
    L"HelloDDK\\Itao",
    L"DWORD_Value",
    REG_DWORD,
    &value1,
    sizeof(value1));
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Write thw DWORD value successfully\n"));
}

//写注册表
PWCHAR szString = L"Hello DDK";
ntStatus = RtlWriteRegistryValue(
    RTL_REGISTRY_SERVUCES, 
    L"HelloDDK\\Itao",
    L"SZ_Value",
    REG_SZ,
    szString,
    wcslen(szStrubg) * 2 + 2);
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Write thw REG_SZ value successfully\n"));
}

//初始化变量
RTL_QUERY_REGISTRY_TABLE paramTable[2];
RtlZeroMemory(paramTable, sizeof(paramTable));

ULONG defaultData = 0;
ULONG uQueryValue;
paramTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
paramTable[0].Name = L"DWORD_Value";
paramTable[0].EntryContext = &uQueryValue;
paramTable[0].DefaultType = REG_DWORD;
paramTable[0].DefaultData = &defaultData;
paramTable[0].DefaultLenth = sizeof(ULONG);

//查询REG_DWORD的数据
ntStatus = RtlQueryRegistryValue(
    RTL_REGISTRY_SERVUCES, 
    L"HelloDDK\\Itao",
    NULL,
    NULL);
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Query the item successfully\n"));
    KdPrint(("The item is :%d\n", uQueryValue));
}

//删除子键
ntStatus = RtlDeleteRegistryValue(
    RTL_REGISTRY_SERVUCES, 
    L"DWORD_Value");
if(NT_SUCCESS(ntStatus))
{
    KdPrint(("Delete the value successfully\n"));
}
原文地址:https://www.cnblogs.com/qintangtao/p/3083825.html