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
START_TEST(RtlHandle)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