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