1 /*
2  * PROJECT:     ReactOS API tests
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Tests for the NtQueryOpenSubKeys API
5  * COPYRIGHT:   Copyright 2023 George Bișoc <george.bisoc@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 START_TEST(NtQueryOpenSubKeys)
11 {
12     NTSTATUS Status;
13     OBJECT_ATTRIBUTES ObjectAttributes;
14     ULONG Subkeys;
15     UNICODE_STRING RegistryKey = RTL_CONSTANT_STRING(L"\\Registry");
16     UNICODE_STRING SystemKey = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM");
17     UNICODE_STRING SoftwareKey = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SOFTWARE");
18     UNICODE_STRING DefaultUserKey = RTL_CONSTANT_STRING(L"\\Registry\\User\\.DEFAULT");
19 
20     /* We give no object attributes and no return variable */
21     Status = NtQueryOpenSubKeys(NULL, NULL);
22     ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
23 
24     /* Build a key path to the main registry tree */
25     InitializeObjectAttributes(&ObjectAttributes,
26                                &RegistryKey,
27                                OBJ_CASE_INSENSITIVE,
28                                NULL,
29                                NULL);
30 
31     /* We give object attributes but no return variable */
32     Status = NtQueryOpenSubKeys(&ObjectAttributes, NULL);
33     ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
34 
35     /*
36      * We give no object attributes but return variable.
37      *
38      * NOTE: Windows 10 and Server 2003 return different kinds of status
39      * codes. In Server 2003 it returns STATUS_ACCESS_VIOLATION because
40      * this function implements more probe checks against the object
41      * attributes parameter (namely the path name of the object) so it
42      * fails earlier. In Windows 10 instead the function only probes the
43      * memory address of the object attributes so that it resides in the boundary
44      * of the UM memory range so the function lets this NULL parameter
45      * slide through until ObOpenObjectByName hits this parameter as being
46      * NULL and returns STATUS_INVALID_PARAMETER. Currently ReactOS follows
47      * the behavior of Windows 10.
48      */
49     Status = NtQueryOpenSubKeys(NULL, &Subkeys);
50     ok(Status == STATUS_ACCESS_VIOLATION || Status == STATUS_INVALID_PARAMETER,
51        "STATUS_ACCESS_VIOLATION or STATUS_INVALID_PARAMETER expected, got 0x%lx\n", Status);
52 
53     /* Garbage return variable, this function doesn't check for alignment */
54     Status = NtQueryOpenSubKeys(&ObjectAttributes, (PVOID)1);
55     ok_ntstatus(Status, STATUS_ACCESS_VIOLATION);
56 
57     /* Return the open subkeys of this key now */
58     Status = NtQueryOpenSubKeys(&ObjectAttributes, &Subkeys);
59     ok_ntstatus(Status, STATUS_SUCCESS);
60 
61     trace("\\Registry has %lu opened subkeys\n", Subkeys);
62 
63     /* Build a key path to the SYSTEM key */
64     InitializeObjectAttributes(&ObjectAttributes,
65                                &SystemKey,
66                                OBJ_CASE_INSENSITIVE,
67                                NULL,
68                                NULL);
69 
70     /* Return the open subkeys of this key now */
71     Status = NtQueryOpenSubKeys(&ObjectAttributes, &Subkeys);
72     ok_ntstatus(Status, STATUS_SUCCESS);
73 
74     trace("\\Registry\\Machine\\SYSTEM has %lu opened subkeys\n", Subkeys);
75 
76     /* Build a key path to the SYSTEM key */
77     InitializeObjectAttributes(&ObjectAttributes,
78                                &SoftwareKey,
79                                OBJ_CASE_INSENSITIVE,
80                                NULL,
81                                NULL);
82 
83     /* Return the open subkeys of this key now */
84     Status = NtQueryOpenSubKeys(&ObjectAttributes, &Subkeys);
85     ok_ntstatus(Status, STATUS_SUCCESS);
86 
87     trace("\\Registry\\Machine\\SOFTWARE has %lu opened subkeys\n", Subkeys);
88 
89     /* Build a key path to the default user key */
90     InitializeObjectAttributes(&ObjectAttributes,
91                                &DefaultUserKey,
92                                OBJ_CASE_INSENSITIVE,
93                                NULL,
94                                NULL);
95 
96     /* Return the open subkeys of this key now */
97     Status = NtQueryOpenSubKeys(&ObjectAttributes, &Subkeys);
98     ok_ntstatus(Status, STATUS_SUCCESS);
99 
100     trace("\\Registry\\User\\.DEFAULT has %lu opened subkeys\n", Subkeys);
101 }
102