1 /*
2  * PROJECT:         ReactOS API tests
3  * LICENSE:         LGPLv2.1+ - See COPYING.LIB in the top level directory
4  * PURPOSE:         Test for Rtl handle tables
5  * PROGRAMMER:      Thomas Faber <thomas.faber@reactos.org>
6  */
7 
8 #include "precomp.h"
9 
10 typedef struct _TEST_HANDLE_ENTRY
11 {
12     RTL_HANDLE_TABLE_ENTRY HandleEntry;
13     ULONG Data;
14 } TEST_HANDLE_ENTRY, *PTEST_HANDLE_ENTRY;
15 
16 START_TEST(RtlHandle)
17 {
18     const ULONG MaxHandles = 2048;
19     RTL_HANDLE_TABLE HandleTable;
20     PUCHAR HandleBase;
21     PRTL_HANDLE_TABLE_ENTRY HandleEntry;
22     PTEST_HANDLE_ENTRY TestEntry;
23     PTEST_HANDLE_ENTRY TestEntry2;
24     ULONG Index;
25     BOOLEAN Valid;
26     ULONG i;
27 
28     /* Initialize handle table */
29     RtlFillMemory(&HandleTable, sizeof(HandleTable), 0x55);
30     RtlInitializeHandleTable(MaxHandles, sizeof(TEST_HANDLE_ENTRY), &HandleTable);
31     ok(HandleTable.MaximumNumberOfHandles == MaxHandles, "MaximumNumberOfHandles = %lu\n", HandleTable.MaximumNumberOfHandles);
32     ok(HandleTable.SizeOfHandleTableEntry == sizeof(TEST_HANDLE_ENTRY),
33        "SizeOfHandleTableEntry = %lu\n", HandleTable.SizeOfHandleTableEntry);
34     ok(HandleTable.Reserved[0] == 0, "Reserved[0] = 0x%lx\n", HandleTable.Reserved[0]);
35     ok(HandleTable.Reserved[1] == 0, "Reserved[1] = 0x%lx\n", HandleTable.Reserved[1]);
36     ok(HandleTable.CommittedHandles == NULL, "CommittedHandles = %p\n", HandleTable.CommittedHandles);
37     ok(HandleTable.UnCommittedHandles == NULL, "UnCommittedHandles = %p\n", HandleTable.UnCommittedHandles);
38     ok(HandleTable.MaxReservedHandles == NULL, "MaxReservedHandles = %p\n", HandleTable.MaxReservedHandles);
39     ok(HandleTable.FreeHandles == NULL, "FreeHandles = %p\n", HandleTable.FreeHandles);
40 
41     /* Allocate a handle, now we have a committed page */
42     HandleEntry = RtlAllocateHandle(&HandleTable, &Index);
43 
44     ok(HandleTable.CommittedHandles != NULL, "CommittedHandles = %p\n", HandleTable.CommittedHandles);
45     HandleBase = (PUCHAR)HandleTable.CommittedHandles;
46 
47     trace("CommittedHandles = %p\n", HandleBase);
48     ok((PUCHAR)HandleTable.UnCommittedHandles == HandleBase + PAGE_SIZE, "UnCommittedHandles = %p\n", HandleTable.UnCommittedHandles);
49     ok((PUCHAR)HandleTable.MaxReservedHandles == HandleBase + MaxHandles * sizeof(TEST_HANDLE_ENTRY), "MaxReservedHandles = %p\n", HandleTable.MaxReservedHandles);
50     ok((PUCHAR)HandleTable.FreeHandles == HandleBase + sizeof(TEST_HANDLE_ENTRY), "FreeHandles = %p\n", HandleTable.FreeHandles);
51 
52     ok((PUCHAR)HandleEntry == HandleBase, "HandleEntry = %p\n", HandleEntry);
53     ok(Index == 0, "Index = %lu\n", Index);
54 
55     ok(HandleEntry->Flags == 0, "Flags = 0x%lx\n", HandleEntry->Flags);
56 
57     TestEntry = (PTEST_HANDLE_ENTRY)HandleEntry;
58     ok(TestEntry->Data == 0, "Data = %lu\n", TestEntry->Data);
59     TestEntry->Data = 0x87654321;
60 
61     /* Handle is not recognized as valid unless we set the valid flag */
62     Valid = RtlIsValidHandle(&HandleTable, &TestEntry->HandleEntry);
63     ok(Valid == FALSE, "Valid = %u\n", Valid);
64     HandleEntry = InvalidPointer;
65     Valid = RtlIsValidIndexHandle(&HandleTable, 0, &HandleEntry);
66     ok(Valid == FALSE, "Valid = %u\n", Valid);
67     ok(HandleEntry == InvalidPointer, "HandleEntry = %p\n", HandleEntry);
68 
69     TestEntry->HandleEntry.Flags = RTL_HANDLE_VALID;
70     Valid = RtlIsValidHandle(&HandleTable, &TestEntry->HandleEntry);
71     ok(Valid == TRUE, "Valid = %u\n", Valid);
72     HandleEntry = InvalidPointer;
73     Valid = RtlIsValidIndexHandle(&HandleTable, 0, &HandleEntry);
74     ok(Valid == TRUE, "Valid = %u\n", Valid);
75     ok(HandleEntry == &TestEntry->HandleEntry, "HandleEntry = %p\n", HandleEntry);
76 
77     /* Allocate a second handle */
78     HandleEntry = RtlAllocateHandle(&HandleTable, &Index);
79 
80     ok((PUCHAR)HandleTable.CommittedHandles == HandleBase, "CommittedHandles = %p\n", HandleTable.CommittedHandles);
81     ok((PUCHAR)HandleTable.UnCommittedHandles == HandleBase + PAGE_SIZE, "UnCommittedHandles = %p\n", HandleTable.UnCommittedHandles);
82     ok((PUCHAR)HandleTable.MaxReservedHandles == HandleBase + MaxHandles * sizeof(TEST_HANDLE_ENTRY), "MaxReservedHandles = %p\n", HandleTable.MaxReservedHandles);
83     ok((PUCHAR)HandleTable.FreeHandles == HandleBase + 2 * sizeof(TEST_HANDLE_ENTRY), "FreeHandles = %p\n", HandleTable.FreeHandles);
84 
85     ok((PUCHAR)HandleEntry == HandleBase + sizeof(TEST_HANDLE_ENTRY), "HandleEntry = %p\n", HandleEntry);
86     ok(Index == 1, "Index = %lu\n", Index);
87 
88     TestEntry2 = (PTEST_HANDLE_ENTRY)HandleEntry;
89     ok(TestEntry2->Data == 0, "Data = %lu\n", TestEntry2->Data);
90     TestEntry2->Data = 0x87604321;
91 
92     TestEntry2->HandleEntry.Flags = RTL_HANDLE_VALID;
93     Valid = RtlIsValidHandle(&HandleTable, &TestEntry2->HandleEntry);
94     ok(Valid == TRUE, "Valid = %u\n", Valid);
95     HandleEntry = NULL;
96     Valid = RtlIsValidIndexHandle(&HandleTable, 1, &HandleEntry);
97     ok(Valid == TRUE, "Valid = %u\n", Valid);
98     ok(HandleEntry == &TestEntry2->HandleEntry, "HandleEntry = %p\n", HandleEntry);
99 
100     /* Free the first and allocate another */
101     Valid = RtlFreeHandle(&HandleTable, &TestEntry->HandleEntry);
102     ok(Valid == TRUE, "Valid = %u\n", Valid);
103 
104     HandleEntry = RtlAllocateHandle(&HandleTable, &Index);
105     ok((PUCHAR)HandleEntry == HandleBase, "HandleEntry = %p\n", HandleEntry);
106     ok(Index == 0, "Index = %lu\n", Index);
107     ok(HandleEntry->Flags == 0, "Flags = 0x%lx\n", HandleEntry->Flags);
108 
109     TestEntry = (PTEST_HANDLE_ENTRY)HandleEntry;
110     ok(TestEntry->Data == 0, "Data = %lu\n", TestEntry->Data);
111     TestEntry->Data = 0x87650321;
112 
113     Valid = RtlFreeHandle(&HandleTable, &TestEntry2->HandleEntry);
114     ok(Valid == TRUE, "Valid = %u\n", Valid);
115     TestEntry->HandleEntry.Flags = RTL_HANDLE_VALID;
116     Valid = RtlFreeHandle(&HandleTable, &TestEntry->HandleEntry);
117     ok(Valid == TRUE, "Valid = %u\n", Valid);
118 
119     ok((PUCHAR)HandleTable.FreeHandles == HandleBase, "FreeHandles = %p\n", HandleTable.FreeHandles);
120 
121     /* Allocate all possible handles */
122     for (i = 0; i < MaxHandles; i++)
123     {
124         const ULONG EntriesPerPage = PAGE_SIZE / sizeof(TEST_HANDLE_ENTRY);
125 
126         HandleEntry = RtlAllocateHandle(&HandleTable, &Index);
127         ok(Index == i, "[%lu] Index = %lu\n", i, Index);
128         ok((PUCHAR)HandleEntry == HandleBase + i * sizeof(TEST_HANDLE_ENTRY),
129            "[%lu] HandleEntry = %p\n", i, HandleEntry);
130 
131         ok((PUCHAR)HandleTable.CommittedHandles == HandleBase, "[%lu] CommittedHandles = %p\n", i, HandleTable.CommittedHandles);
132         ok((PUCHAR)HandleTable.UnCommittedHandles == HandleBase + PAGE_SIZE * (i / EntriesPerPage + 1) , "[%lu] UnCommittedHandles = %p\n", i, HandleTable.UnCommittedHandles);
133         ok((PUCHAR)HandleTable.MaxReservedHandles == HandleBase + MaxHandles * sizeof(TEST_HANDLE_ENTRY), "[%lu] MaxReservedHandles = %p\n", i, HandleTable.MaxReservedHandles);
134         if ((i + 1) % EntriesPerPage == 0)
135         {
136             ok(HandleTable.FreeHandles == NULL, "[%lu] FreeHandles = %p\n", i, HandleTable.FreeHandles);
137         }
138         else
139         {
140             ok((PUCHAR)HandleTable.FreeHandles == HandleBase + (i + 1) * sizeof(TEST_HANDLE_ENTRY), "[%lu] FreeHandles = %p\n", i, HandleTable.FreeHandles);
141         }
142 
143         TestEntry = (PTEST_HANDLE_ENTRY)HandleEntry;
144         ok(TestEntry->Data == 0, "[%lu] Data = 0x%lx\n", i, TestEntry->Data);
145         TestEntry->Data = (i << 16) + (i + 1);
146 
147         Valid = RtlIsValidHandle(&HandleTable, &TestEntry->HandleEntry);
148         ok(Valid == FALSE, "[%lu] Valid = %u\n", i, Valid);
149         HandleEntry = InvalidPointer;
150         Valid = RtlIsValidIndexHandle(&HandleTable, i, &HandleEntry);
151         ok(Valid == FALSE, "[%lu] Valid = %u\n", i, Valid);
152         ok(HandleEntry == InvalidPointer, "[%lu] HandleEntry = %p\n", i, HandleEntry);
153     }
154 
155     /* Try one more */
156     Index = 0x55555555;
157     HandleEntry = RtlAllocateHandle(&HandleTable, &Index);
158     ok(HandleEntry == NULL, "HandleEntry = %p\n", HandleEntry);
159     ok(Index == 0x55555555, "Index = 0x%lx\n", Index);
160 
161     /* Free them all */
162     for (i = 0; i < MaxHandles; i++)
163     {
164         TestEntry = (PTEST_HANDLE_ENTRY)HandleBase + i;
165 
166         ok(TestEntry->Data == (i << 16) + (i + 1), "[%lu] Data = %lu\n", i, TestEntry->Data);
167 
168         TestEntry->HandleEntry.Flags = RTL_HANDLE_VALID;
169 
170         Valid = RtlIsValidHandle(&HandleTable, &TestEntry->HandleEntry);
171         ok(Valid == TRUE, "[%lu] Valid = %u\n", i, Valid);
172         HandleEntry = InvalidPointer;
173         Valid = RtlIsValidIndexHandle(&HandleTable, i, &HandleEntry);
174         ok(Valid == TRUE, "[%lu] Valid = %u\n", i, Valid);
175         ok(HandleEntry == &TestEntry->HandleEntry, "[%lu] HandleEntry = %p\n", i, HandleEntry);
176 
177         Valid = RtlFreeHandle(&HandleTable, &TestEntry->HandleEntry);
178         ok(Valid == TRUE, "[%lu] Valid = %u\n", i, Valid);
179 
180         Valid = RtlIsValidHandle(&HandleTable, &TestEntry->HandleEntry);
181         ok(Valid == FALSE, "[%lu] Valid = %u\n", i, Valid);
182         HandleEntry = InvalidPointer;
183         Valid = RtlIsValidIndexHandle(&HandleTable, i, &HandleEntry);
184         ok(Valid == FALSE, "[%lu] Valid = %u\n", i, Valid);
185         ok(HandleEntry == InvalidPointer, "[%lu] HandleEntry = %p\n", i, HandleEntry);
186     }
187 
188     /* Check the memory commit once again */
189     ok((PUCHAR)HandleTable.CommittedHandles == HandleBase, "[%lu] CommittedHandles = %p\n", i, HandleTable.CommittedHandles);
190     ok((PUCHAR)HandleTable.UnCommittedHandles == HandleBase + MaxHandles * sizeof(TEST_HANDLE_ENTRY), "[%lu] UnCommittedHandles = %p\n", i, HandleTable.UnCommittedHandles);
191     ok((PUCHAR)HandleTable.MaxReservedHandles == HandleBase + MaxHandles * sizeof(TEST_HANDLE_ENTRY), "[%lu] MaxReservedHandles = %p\n", i, HandleTable.MaxReservedHandles);
192     ok((PUCHAR)HandleTable.FreeHandles == HandleBase + (i - 1) * sizeof(TEST_HANDLE_ENTRY), "[%lu] FreeHandles = %p\n", i, HandleTable.FreeHandles);
193 
194     /* Finally, destroy the table */
195     RtlDestroyHandleTable(&HandleTable);
196     ok((PUCHAR)HandleTable.CommittedHandles == HandleBase, "CommittedHandles = %p\n", HandleTable.CommittedHandles);
197 }
198