974e689f5d1d8e1589124ed0f106a27c0bd70511
[reactos.git] / kmtests / ntos_ex / ExResource.c
1 /*
2 * PROJECT: ReactOS kernel-mode tests
3 * LICENSE: GPLv2+ - See COPYING in the top level directory
4 * PURPOSE: Kernel-Mode Test Suite Executive Resource test
5 * PROGRAMMER: Thomas Faber <thfabba@gmx.de>
6 */
7
8 #include <ntddk.h>
9 #include <ntifs.h>
10 #include <ndk/extypes.h>
11 #include <kmt_test.h>
12 #include <pseh/pseh2.h>
13
14 //#define NDEBUG
15 #include <debug.h>
16
17 /* TODO: This is getting pretty long, make it somehow easier to read if possible */
18
19 /* TODO: this is the Windows Server 2003 version! ROS should use this!
20 * This declaration can be removed once ROS headers are corrected */
21 typedef struct _ERESOURCE_2K3 {
22 LIST_ENTRY SystemResourcesList;
23 POWNER_ENTRY OwnerTable;
24 SHORT ActiveCount;
25 USHORT Flag;
26 volatile PKSEMAPHORE SharedWaiters;
27 volatile PKEVENT ExclusiveWaiters;
28 OWNER_ENTRY OwnerThreads[2];
29 ULONG ContentionCount;
30 USHORT NumberOfSharedWaiters;
31 USHORT NumberOfExclusiveWaiters;
32 #if defined(_WIN64)
33 PVOID Reserved2; /* TODO: not sure if this should be in here for 2k3 */
34 #endif
35 _ANONYMOUS_UNION union {
36 PVOID Address;
37 ULONG_PTR CreatorBackTraceIndex;
38 } DUMMYUNIONNAME;
39 KSPIN_LOCK SpinLock;
40 } ERESOURCE_2K3, *PERESOURCE_2K3;
41
42 #define CheckResourceFields(Res, Reinit) do \
43 { \
44 ok_eq_pointer((Res)->SystemResourcesList.Flink->Blink, &(Res)->SystemResourcesList); \
45 ok_eq_pointer((Res)->SystemResourcesList.Blink->Flink, &(Res)->SystemResourcesList); \
46 if (!Reinit) ok_eq_pointer((Res)->OwnerTable, NULL); \
47 ok_eq_int((Res)->ActiveCount, 0); \
48 ok_eq_uint((Res)->Flag, 0); \
49 if (!Reinit) ok_eq_pointer((Res)->SharedWaiters, NULL); \
50 if (!Reinit) ok_eq_pointer((Res)->ExclusiveWaiters, NULL); \
51 ok_eq_pointer((PVOID)(Res)->OwnerThreads[0].OwnerThread, NULL); \
52 ok_eq_ulong((Res)->OwnerThreads[0].TableSize, 0LU); \
53 ok_eq_pointer((PVOID)(Res)->OwnerThreads[1].OwnerThread, NULL); \
54 ok_eq_ulong((Res)->OwnerThreads[1].TableSize, 0LU); \
55 ok_eq_ulong((Res)->ContentionCount, 0LU); \
56 ok_eq_uint((Res)->NumberOfSharedWaiters, 0); \
57 ok_eq_uint((Res)->NumberOfExclusiveWaiters, 0); \
58 /* ok_eq_pointer((Res)->Reserved2, NULL); */ \
59 ok_eq_pointer((Res)->Address, NULL); \
60 ok_eq_pointer((PVOID)(Res)->SpinLock, NULL); \
61 } while (0)
62
63 #define CheckResourceStatus(Res, Exclusive, Shared, ExclusiveWaiters, SharedWaiters) do \
64 { \
65 if (Exclusive) \
66 ok_bool_true(ExIsResourceAcquiredExclusiveLite(Res), "ExIsResourceAcquiredExclusiveLite returned"); \
67 else \
68 ok_bool_false(ExIsResourceAcquiredExclusiveLite(Res), "ExIsResourceAcquiredExclusiveLite returned"); \
69 ok_eq_ulong(ExIsResourceAcquiredSharedLite(Res), Shared); \
70 ok_eq_ulong(ExGetExclusiveWaiterCount(Res), ExclusiveWaiters); \
71 ok_eq_ulong(ExGetSharedWaiterCount(Res), SharedWaiters); \
72 } while (0)
73
74 static
75 VOID
76 TestResourceSharedAccess(
77 IN PERESOURCE Res)
78 {
79 LONG Count = 0;
80
81 KeEnterCriticalRegion();
82 ok_bool_true(ExAcquireResourceSharedLite(Res, FALSE), "ExAcquireResourceSharedLite returned"); ++Count;
83 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
84
85 ok_bool_true(ExAcquireResourceSharedLite(Res, FALSE), "ExAcquireResourceSharedLite returned"); ++Count;
86 ok_bool_true(ExAcquireResourceSharedLite(Res, TRUE), "ExAcquireResourceSharedLite returned"); ++Count;
87 ok_bool_true(ExAcquireSharedStarveExclusive(Res, FALSE), "ExAcquireSharedStarveExclusive returned"); ++Count;
88 ok_bool_true(ExAcquireSharedStarveExclusive(Res, TRUE), "ExAcquireSharedStarveExclusive returned"); ++Count;
89 ok_bool_true(ExAcquireSharedWaitForExclusive(Res, FALSE), "ExAcquireSharedWaitForExclusive returned"); ++Count;
90 ok_bool_true(ExAcquireSharedWaitForExclusive(Res, TRUE), "ExAcquireSharedWaitForExclusive returned"); ++Count;
91 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
92
93 /* this one fails, TRUE would deadlock */
94 ok_bool_false(ExAcquireResourceExclusiveLite(Res, FALSE), "ExAcquireResourceExclusiveLite returned");
95 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
96
97 /* this must not crash or deadlock (but can assert) */
98 ExConvertExclusiveToSharedLite(Res);
99 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
100
101 while (Count--)
102 ExReleaseResourceLite(Res);
103 KeLeaveCriticalRegion();
104 }
105
106 static
107 VOID
108 TestResourceExclusiveAccess(
109 IN PERESOURCE Res)
110 {
111 LONG Count = 0;
112
113 KeEnterCriticalRegion();
114 ok_bool_true(ExAcquireResourceExclusiveLite(Res, FALSE), "ExAcquireResourceExclusiveLite returned"); ++Count;
115
116 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
117
118 ok_bool_true(ExAcquireResourceExclusiveLite(Res, TRUE), "ExAcquireResourceExclusiveLite returned"); ++Count;
119 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
120
121 ok_bool_true(ExAcquireResourceSharedLite(Res, FALSE), "ExAcquireResourceSharedLite returned"); ++Count;
122 ok_bool_true(ExAcquireResourceSharedLite(Res, TRUE), "ExAcquireResourceSharedLite returned"); ++Count;
123 ok_bool_true(ExAcquireSharedStarveExclusive(Res, FALSE), "ExAcquireSharedStarveExclusive returned"); ++Count;
124 ok_bool_true(ExAcquireSharedStarveExclusive(Res, TRUE), "ExAcquireSharedStarveExclusive returned"); ++Count;
125 ok_bool_true(ExAcquireSharedWaitForExclusive(Res, FALSE), "ExAcquireSharedWaitForExclusive returned"); ++Count;
126 ok_bool_true(ExAcquireSharedWaitForExclusive(Res, TRUE), "ExAcquireSharedWaitForExclusive returned"); ++Count;
127 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
128
129 ExConvertExclusiveToSharedLite(Res);
130 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
131
132 while (Count--)
133 ExReleaseResourceLite(Res);
134 KeLeaveCriticalRegion();
135 }
136
137 static
138 VOID
139 TestResourceUndocumentedShortcuts(
140 IN PERESOURCE Res,
141 IN BOOLEAN AreApcsDisabled)
142 {
143 PVOID Ret;
144 LONG Count = 0;
145
146 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
147 ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled);
148
149 /* ExEnterCriticalRegionAndAcquireResourceShared, ExEnterCriticalRegionAndAcquireSharedWaitForExclusive */
150 Count = 0;
151 Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count;
152 ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
153 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
154 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
155 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
156
157 Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count;
158 ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
159 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
160 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
161 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
162
163 ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res); ++Count;
164 ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
165 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
166 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
167 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
168
169 while (Count-- > 1)
170 {
171 ExReleaseResourceAndLeaveCriticalRegion(Res);
172 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
173 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
174 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
175 }
176
177 ExReleaseResourceAndLeaveCriticalRegion(Res);
178 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
179 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
180 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
181
182 /* ExEnterCriticalRegionAndAcquireResourceExclusive */
183 Count = 0;
184 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
185 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
186 Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count;
187 ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
188 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
189 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
190 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
191
192 Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count;
193 ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread);
194 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
195 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
196 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
197
198 ExReleaseResourceAndLeaveCriticalRegion(Res); --Count;
199 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
200 ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled);
201 CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU);
202
203 ExReleaseResourceAndLeaveCriticalRegion(Res); --Count;
204 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
205 ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled);
206 CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU);
207 }
208
209 typedef BOOLEAN (NTAPI *PACQUIRE_FUNCTION)(PERESOURCE, BOOLEAN);
210
211 typedef struct
212 {
213 HANDLE Handle;
214 PKTHREAD Thread;
215 PERESOURCE Res;
216 KEVENT InEvent;
217 KEVENT OutEvent;
218 PACQUIRE_FUNCTION AcquireResource;
219 BOOLEAN Wait;
220 BOOLEAN RetExpected;
221 } THREAD_DATA, *PTHREAD_DATA;
222
223 static
224 VOID
225 NTAPI
226 AcquireResourceThread(
227 PVOID Context)
228 {
229 NTSTATUS Status = STATUS_SUCCESS;
230 PTHREAD_DATA ThreadData = Context;
231 BOOLEAN Ret;
232
233 KeEnterCriticalRegion();
234 Ret = ThreadData->AcquireResource(ThreadData->Res, ThreadData->Wait);
235 if (ThreadData->RetExpected)
236 ok_bool_true(Ret, "AcquireResource returned");
237 else
238 ok_bool_false(Ret, "AcquireResource returned");
239
240 ok_bool_false(KeSetEvent(&ThreadData->OutEvent, 0, TRUE), "KeSetEvent returned");
241 Status = KeWaitForSingleObject(&ThreadData->InEvent, Executive, KernelMode, FALSE, NULL);
242 ok_eq_hex(Status, STATUS_SUCCESS);
243
244 if (Ret)
245 ExReleaseResource(ThreadData->Res);
246 KeLeaveCriticalRegion();
247 }
248
249 static
250 VOID
251 InitThreadData(
252 PTHREAD_DATA ThreadData,
253 PERESOURCE Res,
254 PACQUIRE_FUNCTION AcquireFunction)
255 {
256 ThreadData->Res = Res;
257 KeInitializeEvent(&ThreadData->InEvent, NotificationEvent, FALSE);
258 KeInitializeEvent(&ThreadData->OutEvent, NotificationEvent, FALSE);
259 ThreadData->AcquireResource = AcquireFunction;
260 }
261
262 static
263 NTSTATUS
264 StartThread(
265 PTHREAD_DATA ThreadData,
266 PLARGE_INTEGER Timeout,
267 BOOLEAN Wait,
268 BOOLEAN RetExpected)
269 {
270 NTSTATUS Status = STATUS_SUCCESS;
271 OBJECT_ATTRIBUTES Attributes;
272
273 ThreadData->Wait = Wait;
274 ThreadData->RetExpected = RetExpected;
275 InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
276 Status = PsCreateSystemThread(&ThreadData->Handle, GENERIC_ALL, &Attributes, NULL, NULL, AcquireResourceThread, ThreadData);
277 ok_eq_hex(Status, STATUS_SUCCESS);
278 Status = ObReferenceObjectByHandle(ThreadData->Handle, SYNCHRONIZE, PsThreadType, KernelMode, (PVOID *)&ThreadData->Thread, NULL);
279 ok_eq_hex(Status, STATUS_SUCCESS);
280
281 return KeWaitForSingleObject(&ThreadData->OutEvent, Executive, KernelMode, FALSE, Timeout);
282 }
283
284 static
285 VOID
286 FinishThread(
287 PTHREAD_DATA ThreadData)
288 {
289 NTSTATUS Status = STATUS_SUCCESS;
290
291 KeSetEvent(&ThreadData->InEvent, 0, TRUE);
292 Status = KeWaitForSingleObject(ThreadData->Thread, Executive, KernelMode, FALSE, NULL);
293 ok_eq_hex(Status, STATUS_SUCCESS);
294
295 ObDereferenceObject(ThreadData->Thread);
296 Status = ZwClose(ThreadData->Handle);
297 ok_eq_hex(Status, STATUS_SUCCESS);
298 KeClearEvent(&ThreadData->InEvent);
299 KeClearEvent(&ThreadData->OutEvent);
300 }
301
302 static
303 VOID
304 TestResourceWithThreads(
305 IN PERESOURCE Res)
306 {
307 NTSTATUS Status = STATUS_SUCCESS;
308 THREAD_DATA ThreadDataShared;
309 THREAD_DATA ThreadDataShared2;
310 THREAD_DATA ThreadDataExclusive;
311 THREAD_DATA ThreadDataSharedStarve;
312 THREAD_DATA ThreadDataSharedWait;
313 LARGE_INTEGER Timeout;
314 Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */
315
316 InitThreadData(&ThreadDataShared, Res, ExAcquireResourceSharedLite);
317 InitThreadData(&ThreadDataShared2, Res, ExAcquireResourceSharedLite);
318 InitThreadData(&ThreadDataExclusive, Res, ExAcquireResourceExclusiveLite);
319 InitThreadData(&ThreadDataSharedStarve, Res, ExAcquireSharedStarveExclusive);
320 InitThreadData(&ThreadDataSharedWait, Res, ExAcquireSharedWaitForExclusive);
321
322 /* have a thread acquire the resource shared */
323 Status = StartThread(&ThreadDataShared, NULL, FALSE, TRUE);
324 ok_eq_hex(Status, STATUS_SUCCESS);
325 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
326 ok_eq_int(Res->ActiveCount, 1);
327
328 /* a second thread should be able to acquire the resource shared */
329 Status = StartThread(&ThreadDataShared2, NULL, FALSE, TRUE);
330 ok_eq_hex(Status, STATUS_SUCCESS);
331 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
332 ok_eq_int(Res->ActiveCount, 2);
333 FinishThread(&ThreadDataShared2);
334 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
335 ok_eq_int(Res->ActiveCount, 1);
336
337 /* now have a thread that tries to acquire the resource exclusive -- it should fail */
338 Status = StartThread(&ThreadDataExclusive, NULL, FALSE, FALSE);
339 ok_eq_hex(Status, STATUS_SUCCESS);
340 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
341 ok_eq_int(Res->ActiveCount, 1);
342 FinishThread(&ThreadDataExclusive);
343 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
344 ok_eq_int(Res->ActiveCount, 1);
345
346 /* as above, but this time it should block */
347 Status = StartThread(&ThreadDataExclusive, &Timeout, TRUE, TRUE);
348 ok_eq_hex(Status, STATUS_TIMEOUT);
349 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU);
350 ok_eq_int(Res->ActiveCount, 1);
351
352 /* now try another shared one -- it should fail */
353 Status = StartThread(&ThreadDataShared2, NULL, FALSE, FALSE);
354 ok_eq_hex(Status, STATUS_SUCCESS);
355 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU);
356 ok_eq_int(Res->ActiveCount, 1);
357 FinishThread(&ThreadDataShared2);
358
359 /* same for ExAcquireSharedWaitForExclusive */
360 Status = StartThread(&ThreadDataSharedWait, NULL, FALSE, FALSE);
361 ok_eq_hex(Status, STATUS_SUCCESS);
362 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU);
363 ok_eq_int(Res->ActiveCount, 1);
364 FinishThread(&ThreadDataSharedWait);
365
366 /* ExAcquireSharedStarveExclusive must get access though! */
367 Status = StartThread(&ThreadDataSharedStarve, NULL, TRUE, TRUE);
368 ok_eq_hex(Status, STATUS_SUCCESS);
369 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU);
370 ok_eq_int(Res->ActiveCount, 2);
371 FinishThread(&ThreadDataSharedStarve);
372 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU);
373 ok_eq_int(Res->ActiveCount, 1);
374
375 /* block another shared one */
376 Status = StartThread(&ThreadDataShared2, &Timeout, TRUE, TRUE);
377 ok_eq_hex(Status, STATUS_TIMEOUT);
378 CheckResourceStatus(Res, FALSE, 0LU, 1LU, 1LU);
379 ok_eq_int(Res->ActiveCount, 1);
380
381 /* finish the very first one */
382 FinishThread(&ThreadDataShared);
383
384 /* now the blocked exclusive one should get the resource */
385 Status = KeWaitForSingleObject(&ThreadDataExclusive.OutEvent, Executive, KernelMode, FALSE, NULL);
386 ok_eq_hex(Status, STATUS_SUCCESS);
387 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 1LU);
388 ok_eq_int(Res->ActiveCount, 1);
389 ok_eq_uint((Res->Flag & ResourceOwnedExclusive) != 0, 1);
390
391 FinishThread(&ThreadDataExclusive);
392 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
393
394 /* now the blocked shared one should resume */
395 Status = KeWaitForSingleObject(&ThreadDataShared2.OutEvent, Executive, KernelMode, FALSE, NULL);
396 ok_eq_hex(Status, STATUS_SUCCESS);
397 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
398 ok_eq_int(Res->ActiveCount, 1);
399 FinishThread(&ThreadDataShared2);
400 CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU);
401 ok_eq_int(Res->ActiveCount, 0);
402 }
403
404 START_TEST(ExResource)
405 {
406 NTSTATUS Status;
407 ERESOURCE Res;
408 KIRQL Irql;
409
410 /* this must be true even with the different structure versions */
411 ASSERT(sizeof(ERESOURCE) == sizeof(ERESOURCE_2K3));
412
413 /* functional tests & internals */
414 Irql = KeRaiseIrqlToDpcLevel();
415 Status = ExInitializeResourceLite(&Res);
416 ok_eq_hex(Status, STATUS_SUCCESS);
417 KeLowerIrql(APC_LEVEL);
418
419 Status = ExDeleteResourceLite(&Res);
420 ok_eq_hex(Status, STATUS_SUCCESS);
421 KeLowerIrql(Irql);
422
423 memset(&Res, 0x55, sizeof Res);
424 Status = ExInitializeResourceLite(&Res);
425 ok_eq_hex(Status, STATUS_SUCCESS);
426 CheckResourceFields((PERESOURCE_2K3)&Res, FALSE);
427
428 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
429
430 TestResourceSharedAccess(&Res);
431 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
432
433 TestResourceExclusiveAccess(&Res);
434 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
435
436 TestResourceUndocumentedShortcuts(&Res, FALSE);
437 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
438 KeRaiseIrql(APC_LEVEL, &Irql);
439 TestResourceUndocumentedShortcuts(&Res, TRUE);
440 KeLowerIrql(Irql);
441 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
442 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
443
444 TestResourceWithThreads(&Res);
445
446 /* ExReinitializeResourceLite cleans up after us */
447 Status = ExReinitializeResourceLite(&Res);
448 ok_eq_hex(Status, STATUS_SUCCESS);
449 CheckResourceFields((PERESOURCE_2K3)&Res, TRUE);
450 CheckResourceStatus(&Res, FALSE, 0LU, 0LU, 0LU);
451
452 Status = ExDeleteResourceLite(&Res);
453 ok_eq_hex(Status, STATUS_SUCCESS);
454
455 /* parameter checks */
456 Status = STATUS_SUCCESS;
457 _SEH2_TRY {
458 ExInitializeResourceLite(NULL);
459 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) {
460 Status = _SEH2_GetExceptionCode();
461 } _SEH2_END;
462 ok_eq_hex(Status, STATUS_ACCESS_VIOLATION);
463
464 /* these bugcheck
465 ExDeleteResourceLite(NULL);
466 Status = ExDeleteResourceLite(&Res);*/
467 }