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
/*
 * PROJECT:         ReactOS API Tests
 * LICENSE:         GPLv2+ - See COPYING in the top level directory
 * PURPOSE:         Test for NtDeleteKey
 */

#include "precomp.h"

static
NTSTATUS
CreateRegistryKeyHandle(PHANDLE KeyHandle,
                      ACCESS_MASK AccessMask,
                      PWCHAR RegistryPath)
{
    UNICODE_STRING KeyName;
    OBJECT_ATTRIBUTES Attributes;

    RtlInitUnicodeString(&KeyName, RegistryPath);
    InitializeObjectAttributes(&Attributes,
                               &KeyName,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);

    return NtCreateKey(KeyHandle, AccessMask, &Attributes, 0, NULL, REG_OPTION_VOLATILE, 0);
}

START_TEST(NtDeleteKey)
{
    NTSTATUS Status;
    HANDLE ParentKey, ChildKey, PetKey;
    WCHAR Buffer[sizeof("\\Registry\\Machine\\Software\\RosTests\\Child\\Pet") + 5];
    ULONG i;

    /* Create a registry key */
    Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Create a children registry key */
    Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child");
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Try deleting the parent one */
    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_CANNOT_DELETE);

    /* See what happens with Child one */
    Status = NtDeleteKey(ChildKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Retry with parent one */
    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* re-retry */
    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Close everything */
    NtClose(ChildKey);
    NtClose(ParentKey);

    /* Same, but this time close the child handle before trying to delete the parent */
    /* Create a registry key */
    Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Create a children registry key */
    Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ, L"\\Registry\\Machine\\Software\\RosTests\\Child");
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Close the Child */
    NtClose(ChildKey);

    /* Try deleting the parent one */
    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_CANNOT_DELETE);

    /* See what happens with Child one */
    Status = CreateRegistryKeyHandle(&ChildKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child");
    ok_ntstatus(Status, STATUS_SUCCESS);
    Status = NtDeleteKey(ChildKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Retry with parent one */
    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Close everything */
    NtClose(ChildKey);
    NtClose(ParentKey);

    /* Stress test key creation */
    Status = CreateRegistryKeyHandle(&ParentKey, KEY_READ | DELETE, L"\\Registry\\Machine\\Software\\RosTests");

    for (i = 0; i <= 9999; i++) {
        swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d", i);
        Status = CreateRegistryKeyHandle(&ChildKey, KEY_READ, Buffer);<--- Status is assigned
        NtClose(ChildKey);

        swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d\\Pet", i);
        Status = CreateRegistryKeyHandle(&PetKey, KEY_READ, Buffer);<--- Status is overwritten
        NtClose(PetKey);
    }
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Test hive rerooting */
    Status = CreateRegistryKeyHandle(&PetKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child5000\\Pet");
    ok_ntstatus(Status, STATUS_SUCCESS);
    Status = NtDeleteKey(PetKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    NtClose(PetKey);

    Status = CreateRegistryKeyHandle(&ChildKey, DELETE, L"\\Registry\\Machine\\Software\\RosTests\\Child5000");
    ok_ntstatus(Status, STATUS_SUCCESS);
    Status = NtDeleteKey(ChildKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Test mass key deletion */
    for (i = 0; i <= 9999; i++) {
        if (i != 5000) {
            swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d\\Pet", i);
            CreateRegistryKeyHandle(&PetKey, DELETE, Buffer);
            Status = NtDeleteKey(PetKey);<--- Status is assigned
            NtClose(PetKey);

            swprintf(Buffer, L"\\Registry\\Machine\\Software\\RosTests\\Child%04d", i);
            CreateRegistryKeyHandle(&ChildKey, DELETE, Buffer);
            Status = NtDeleteKey(ChildKey);<--- Status is overwritten
            NtClose(ChildKey);
        }
    }
    ok_ntstatus(Status, STATUS_SUCCESS);

    Status = NtDeleteKey(ParentKey);
    ok_ntstatus(Status, STATUS_SUCCESS);

    /* Close ParentKey */
    NtClose(ParentKey);
}