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