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