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>
14 _IRQL_requires_max_(APC_LEVEL
)
15 _Acquires_lock_(_Global_critical_region_
)
18 *pExEnterCriticalRegionAndAcquireResourceShared
)(
19 _Inout_
_Requires_lock_not_held_(*_Curr_
) _Acquires_shared_lock_(*_Curr_
)
23 _IRQL_requires_max_(APC_LEVEL
)
24 _Acquires_lock_(_Global_critical_region_
)
27 *pExEnterCriticalRegionAndAcquireResourceExclusive
)(
28 _Inout_
_Requires_lock_not_held_(*_Curr_
) _Acquires_exclusive_lock_(*_Curr_
)
32 _IRQL_requires_max_(APC_LEVEL
)
33 _Acquires_lock_(_Global_critical_region_
)
36 *pExEnterCriticalRegionAndAcquireSharedWaitForExclusive
)(
37 _Inout_
_Requires_lock_not_held_(*_Curr_
) _Acquires_lock_(*_Curr_
)
41 _IRQL_requires_max_(DISPATCH_LEVEL
)
42 _Releases_lock_(_Global_critical_region_
)
45 *pExReleaseResourceAndLeaveCriticalRegion
)(
46 _Inout_
_Requires_lock_held_(*_Curr_
) _Releases_lock_(*_Curr_
)
50 _IRQL_requires_min_(PASSIVE_LEVEL
)
51 _IRQL_requires_max_(DISPATCH_LEVEL
)
54 *pKeAreAllApcsDisabled
)(VOID
);
56 /* TODO: This is getting pretty long, make it somehow easier to read if possible */
58 /* TODO: this is the Windows Server 2003 version! ROS should use this!
59 * This declaration can be removed once ROS headers are corrected */
60 typedef struct _ERESOURCE_2K3
{
61 LIST_ENTRY SystemResourcesList
;
62 POWNER_ENTRY OwnerTable
;
65 volatile PKSEMAPHORE SharedWaiters
;
66 volatile PKEVENT ExclusiveWaiters
;
67 OWNER_ENTRY OwnerThreads
[2];
68 ULONG ContentionCount
;
69 USHORT NumberOfSharedWaiters
;
70 USHORT NumberOfExclusiveWaiters
;
71 _ANONYMOUS_UNION
union {
73 ULONG_PTR CreatorBackTraceIndex
;
76 } ERESOURCE_2K3
, *PERESOURCE_2K3
;
78 #define CheckResourceFields(Res, Reinit) do \
80 ok_eq_pointer((Res)->SystemResourcesList.Flink->Blink, &(Res)->SystemResourcesList); \
81 ok_eq_pointer((Res)->SystemResourcesList.Blink->Flink, &(Res)->SystemResourcesList); \
82 if (!Reinit) ok_eq_pointer((Res)->OwnerTable, NULL); \
83 ok_eq_int((Res)->ActiveCount, 0); \
84 ok_eq_uint((Res)->Flag, 0); \
85 if (!Reinit) ok_eq_pointer((Res)->SharedWaiters, NULL); \
86 if (!Reinit) ok_eq_pointer((Res)->ExclusiveWaiters, NULL); \
87 ok_eq_ulongptr((Res)->OwnerThreads[0].OwnerThread, 0); \
88 ok_eq_ulong((Res)->OwnerThreads[0].TableSize, 0LU); \
89 ok_eq_ulongptr((Res)->OwnerThreads[1].OwnerThread, 0); \
90 ok_eq_ulong((Res)->OwnerThreads[1].TableSize, 0LU); \
91 ok_eq_ulong((Res)->ContentionCount, 0LU); \
92 ok_eq_uint((Res)->NumberOfSharedWaiters, 0); \
93 ok_eq_uint((Res)->NumberOfExclusiveWaiters, 0); \
94 ok_eq_pointer((Res)->Address, NULL); \
95 ok_eq_ulongptr((Res)->SpinLock, 0); \
98 #define CheckResourceStatus(Res, Exclusive, Shared, ExclusiveWaiters, SharedWaiters) do \
101 ok_bool_true(ExIsResourceAcquiredExclusiveLite(Res), "ExIsResourceAcquiredExclusiveLite returned"); \
103 ok_bool_false(ExIsResourceAcquiredExclusiveLite(Res), "ExIsResourceAcquiredExclusiveLite returned"); \
104 ok_eq_ulong(ExIsResourceAcquiredSharedLite(Res), Shared); \
105 ok_eq_ulong(ExGetExclusiveWaiterCount(Res), ExclusiveWaiters); \
106 ok_eq_ulong(ExGetSharedWaiterCount(Res), SharedWaiters); \
111 TestResourceSharedAccess(
116 KeEnterCriticalRegion();
117 ok_bool_true(ExAcquireResourceSharedLite(Res
, FALSE
), "ExAcquireResourceSharedLite returned"); ++Count
;
118 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
120 ok_bool_true(ExAcquireResourceSharedLite(Res
, FALSE
), "ExAcquireResourceSharedLite returned"); ++Count
;
121 ok_bool_true(ExAcquireResourceSharedLite(Res
, TRUE
), "ExAcquireResourceSharedLite returned"); ++Count
;
122 ok_bool_true(ExAcquireSharedStarveExclusive(Res
, FALSE
), "ExAcquireSharedStarveExclusive returned"); ++Count
;
123 ok_bool_true(ExAcquireSharedStarveExclusive(Res
, TRUE
), "ExAcquireSharedStarveExclusive returned"); ++Count
;
124 ok_bool_true(ExAcquireSharedWaitForExclusive(Res
, FALSE
), "ExAcquireSharedWaitForExclusive returned"); ++Count
;
125 ok_bool_true(ExAcquireSharedWaitForExclusive(Res
, TRUE
), "ExAcquireSharedWaitForExclusive returned"); ++Count
;
126 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
128 /* this one fails, TRUE would deadlock */
129 ok_bool_false(ExAcquireResourceExclusiveLite(Res
, FALSE
), "ExAcquireResourceExclusiveLite returned");
130 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
133 if (!KmtIsCheckedBuild
)
134 ExConvertExclusiveToSharedLite(Res
);
135 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
138 ExReleaseResourceLite(Res
);
139 KeLeaveCriticalRegion();
144 TestResourceExclusiveAccess(
149 KeEnterCriticalRegion();
150 ok_bool_true(ExAcquireResourceExclusiveLite(Res
, FALSE
), "ExAcquireResourceExclusiveLite returned"); ++Count
;
152 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
154 ok_bool_true(ExAcquireResourceExclusiveLite(Res
, TRUE
), "ExAcquireResourceExclusiveLite returned"); ++Count
;
155 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
157 ok_bool_true(ExAcquireResourceSharedLite(Res
, FALSE
), "ExAcquireResourceSharedLite returned"); ++Count
;
158 ok_bool_true(ExAcquireResourceSharedLite(Res
, TRUE
), "ExAcquireResourceSharedLite returned"); ++Count
;
159 ok_bool_true(ExAcquireSharedStarveExclusive(Res
, FALSE
), "ExAcquireSharedStarveExclusive returned"); ++Count
;
160 ok_bool_true(ExAcquireSharedStarveExclusive(Res
, TRUE
), "ExAcquireSharedStarveExclusive returned"); ++Count
;
161 ok_bool_true(ExAcquireSharedWaitForExclusive(Res
, FALSE
), "ExAcquireSharedWaitForExclusive returned"); ++Count
;
162 ok_bool_true(ExAcquireSharedWaitForExclusive(Res
, TRUE
), "ExAcquireSharedWaitForExclusive returned"); ++Count
;
163 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
165 ExConvertExclusiveToSharedLite(Res
);
166 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
169 ExReleaseResourceLite(Res
);
170 KeLeaveCriticalRegion();
175 TestResourceUndocumentedShortcuts(
177 IN BOOLEAN AreApcsDisabled
)
182 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
183 if (pKeAreAllApcsDisabled
)
184 ok_eq_uint(pKeAreAllApcsDisabled(), AreApcsDisabled
);
186 if (skip(pExEnterCriticalRegionAndAcquireResourceShared
&&
187 pExEnterCriticalRegionAndAcquireSharedWaitForExclusive
&&
188 pExEnterCriticalRegionAndAcquireResourceExclusive
&&
189 pExReleaseResourceAndLeaveCriticalRegion
, "No shortcuts\n"))
193 /* ExEnterCriticalRegionAndAcquireResourceShared, ExEnterCriticalRegionAndAcquireSharedWaitForExclusive */
195 Ret
= pExEnterCriticalRegionAndAcquireResourceShared(Res
); ++Count
;
196 ok_eq_pointer(Ret
, KeGetCurrentThread()->Win32Thread
);
197 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
198 if (pKeAreAllApcsDisabled
)
199 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
200 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
202 Ret
= pExEnterCriticalRegionAndAcquireResourceShared(Res
); ++Count
;
203 ok_eq_pointer(Ret
, KeGetCurrentThread()->Win32Thread
);
204 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
205 if (pKeAreAllApcsDisabled
)
206 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
207 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
209 pExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res
); ++Count
;
210 ok_eq_pointer(Ret
, KeGetCurrentThread()->Win32Thread
);
211 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
212 if (pKeAreAllApcsDisabled
)
213 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
214 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
218 pExReleaseResourceAndLeaveCriticalRegion(Res
);
219 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
220 if (pKeAreAllApcsDisabled
)
221 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
222 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
225 pExReleaseResourceAndLeaveCriticalRegion(Res
);
226 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
227 if (pKeAreAllApcsDisabled
)
228 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
229 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
231 /* ExEnterCriticalRegionAndAcquireResourceExclusive */
233 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
234 if (pKeAreAllApcsDisabled
)
235 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
236 Ret
= pExEnterCriticalRegionAndAcquireResourceExclusive(Res
); ++Count
;
237 ok_eq_pointer(Ret
, KeGetCurrentThread()->Win32Thread
);
238 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
239 if (pKeAreAllApcsDisabled
)
240 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
241 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
243 Ret
= pExEnterCriticalRegionAndAcquireResourceExclusive(Res
); ++Count
;
244 ok_eq_pointer(Ret
, KeGetCurrentThread()->Win32Thread
);
245 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
246 if (pKeAreAllApcsDisabled
)
247 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
248 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
250 pExReleaseResourceAndLeaveCriticalRegion(Res
); --Count
;
251 ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
252 if (pKeAreAllApcsDisabled
)
253 ok_eq_bool(pKeAreAllApcsDisabled(), AreApcsDisabled
);
254 CheckResourceStatus(Res
, TRUE
, Count
, 0LU, 0LU);
256 pExReleaseResourceAndLeaveCriticalRegion(Res
); --Count
;
257 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
258 if (pKeAreAllApcsDisabled
)
259 ok_eq_uint(pKeAreAllApcsDisabled(), AreApcsDisabled
);
260 CheckResourceStatus(Res
, FALSE
, Count
, 0LU, 0LU);
263 typedef BOOLEAN (NTAPI
*PACQUIRE_FUNCTION
)(PERESOURCE
, BOOLEAN
);
272 PACQUIRE_FUNCTION AcquireResource
;
275 PKSTART_ROUTINE StartRoutine
;
276 } THREAD_DATA
, *PTHREAD_DATA
;
281 AcquireResourceThread(
284 NTSTATUS Status
= STATUS_SUCCESS
;
285 PTHREAD_DATA ThreadData
= Context
;
288 KeEnterCriticalRegion();
289 Ret
= ThreadData
->AcquireResource(ThreadData
->Res
, ThreadData
->Wait
);
290 if (ThreadData
->RetExpected
)
291 ok_bool_true(Ret
, "AcquireResource returned");
293 ok_bool_false(Ret
, "AcquireResource returned");
295 ok_bool_false(KeSetEvent(&ThreadData
->OutEvent
, 0, TRUE
), "KeSetEvent returned");
296 Status
= KeWaitForSingleObject(&ThreadData
->InEvent
, Executive
, KernelMode
, FALSE
, NULL
);
297 ok_eq_hex(Status
, STATUS_SUCCESS
);
300 ExReleaseResource(ThreadData
->Res
);
301 KeLeaveCriticalRegion();
307 PTHREAD_DATA ThreadData
,
309 PACQUIRE_FUNCTION AcquireFunction
,
310 PKSTART_ROUTINE StartRoutine
)
312 ThreadData
->Res
= Res
;
313 KeInitializeEvent(&ThreadData
->InEvent
, NotificationEvent
, FALSE
);
314 KeInitializeEvent(&ThreadData
->OutEvent
, NotificationEvent
, FALSE
);
315 ThreadData
->AcquireResource
= AcquireFunction
;
316 ThreadData
->StartRoutine
= StartRoutine
;
322 PTHREAD_DATA ThreadData
,
324 PACQUIRE_FUNCTION AcquireFunction
)
326 InitThreadDataEx(ThreadData
, Res
, AcquireFunction
, AcquireResourceThread
);
332 PTHREAD_DATA ThreadData
,
333 PLARGE_INTEGER Timeout
,
337 NTSTATUS Status
= STATUS_SUCCESS
;
338 OBJECT_ATTRIBUTES Attributes
;
340 ThreadData
->Wait
= Wait
;
341 ThreadData
->RetExpected
= RetExpected
;
342 InitializeObjectAttributes(&Attributes
, NULL
, OBJ_KERNEL_HANDLE
, NULL
, NULL
);
343 Status
= PsCreateSystemThread(&ThreadData
->Handle
, GENERIC_ALL
, &Attributes
, NULL
, NULL
, ThreadData
->StartRoutine
, ThreadData
);
344 ok_eq_hex(Status
, STATUS_SUCCESS
);
345 Status
= ObReferenceObjectByHandle(ThreadData
->Handle
, SYNCHRONIZE
, *PsThreadType
, KernelMode
, (PVOID
*)&ThreadData
->Thread
, NULL
);
346 ok_eq_hex(Status
, STATUS_SUCCESS
);
348 return KeWaitForSingleObject(&ThreadData
->OutEvent
, Executive
, KernelMode
, FALSE
, Timeout
);
354 PTHREAD_DATA ThreadData
)
356 NTSTATUS Status
= STATUS_SUCCESS
;
358 KeSetEvent(&ThreadData
->InEvent
, 0, TRUE
);
359 Status
= KeWaitForSingleObject(ThreadData
->Thread
, Executive
, KernelMode
, FALSE
, NULL
);
360 ok_eq_hex(Status
, STATUS_SUCCESS
);
362 ObDereferenceObject(ThreadData
->Thread
);
363 Status
= ZwClose(ThreadData
->Handle
);
364 ok_eq_hex(Status
, STATUS_SUCCESS
);
365 KeClearEvent(&ThreadData
->InEvent
);
366 KeClearEvent(&ThreadData
->OutEvent
);
371 TestResourceWithThreads(
374 NTSTATUS Status
= STATUS_SUCCESS
;
375 THREAD_DATA ThreadDataShared
;
376 THREAD_DATA ThreadDataShared2
;
377 THREAD_DATA ThreadDataExclusive
;
378 THREAD_DATA ThreadDataSharedStarve
;
379 THREAD_DATA ThreadDataSharedWait
;
380 LARGE_INTEGER Timeout
;
381 Timeout
.QuadPart
= -10 * 1000 * 10; /* 10 ms */
383 InitThreadData(&ThreadDataShared
, Res
, ExAcquireResourceSharedLite
);
384 InitThreadData(&ThreadDataShared2
, Res
, ExAcquireResourceSharedLite
);
385 InitThreadData(&ThreadDataExclusive
, Res
, ExAcquireResourceExclusiveLite
);
386 InitThreadData(&ThreadDataSharedStarve
, Res
, ExAcquireSharedStarveExclusive
);
387 InitThreadData(&ThreadDataSharedWait
, Res
, ExAcquireSharedWaitForExclusive
);
389 /* have a thread acquire the resource shared */
390 Status
= StartThread(&ThreadDataShared
, NULL
, FALSE
, TRUE
);
391 ok_eq_hex(Status
, STATUS_SUCCESS
);
392 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
393 ok_eq_int(Res
->ActiveCount
, 1);
395 /* a second thread should be able to acquire the resource shared */
396 Status
= StartThread(&ThreadDataShared2
, NULL
, FALSE
, TRUE
);
397 ok_eq_hex(Status
, STATUS_SUCCESS
);
398 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
399 ok_eq_int(Res
->ActiveCount
, 2);
400 FinishThread(&ThreadDataShared2
);
401 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
402 ok_eq_int(Res
->ActiveCount
, 1);
404 /* now have a thread that tries to acquire the resource exclusive -- it should fail */
405 Status
= StartThread(&ThreadDataExclusive
, NULL
, FALSE
, FALSE
);
406 ok_eq_hex(Status
, STATUS_SUCCESS
);
407 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
408 ok_eq_int(Res
->ActiveCount
, 1);
409 FinishThread(&ThreadDataExclusive
);
410 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
411 ok_eq_int(Res
->ActiveCount
, 1);
413 /* as above, but this time it should block */
414 Status
= StartThread(&ThreadDataExclusive
, &Timeout
, TRUE
, TRUE
);
415 ok_eq_hex(Status
, STATUS_TIMEOUT
);
416 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 0LU);
417 ok_eq_int(Res
->ActiveCount
, 1);
419 /* now try another shared one -- it should fail */
420 Status
= StartThread(&ThreadDataShared2
, NULL
, FALSE
, FALSE
);
421 ok_eq_hex(Status
, STATUS_SUCCESS
);
422 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 0LU);
423 ok_eq_int(Res
->ActiveCount
, 1);
424 FinishThread(&ThreadDataShared2
);
426 /* same for ExAcquireSharedWaitForExclusive */
427 Status
= StartThread(&ThreadDataSharedWait
, NULL
, FALSE
, FALSE
);
428 ok_eq_hex(Status
, STATUS_SUCCESS
);
429 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 0LU);
430 ok_eq_int(Res
->ActiveCount
, 1);
431 FinishThread(&ThreadDataSharedWait
);
433 /* ExAcquireSharedStarveExclusive must get access though! */
434 Status
= StartThread(&ThreadDataSharedStarve
, NULL
, TRUE
, TRUE
);
435 ok_eq_hex(Status
, STATUS_SUCCESS
);
436 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 0LU);
437 ok_eq_int(Res
->ActiveCount
, 2);
438 FinishThread(&ThreadDataSharedStarve
);
439 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 0LU);
440 ok_eq_int(Res
->ActiveCount
, 1);
442 /* block another shared one */
443 Status
= StartThread(&ThreadDataShared2
, &Timeout
, TRUE
, TRUE
);
444 ok_eq_hex(Status
, STATUS_TIMEOUT
);
445 CheckResourceStatus(Res
, FALSE
, 0LU, 1LU, 1LU);
446 ok_eq_int(Res
->ActiveCount
, 1);
448 /* finish the very first one */
449 FinishThread(&ThreadDataShared
);
451 /* now the blocked exclusive one should get the resource */
452 Status
= KeWaitForSingleObject(&ThreadDataExclusive
.OutEvent
, Executive
, KernelMode
, FALSE
, NULL
);
453 ok_eq_hex(Status
, STATUS_SUCCESS
);
454 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 1LU);
455 ok_eq_int(Res
->ActiveCount
, 1);
456 ok_eq_uint((Res
->Flag
& ResourceOwnedExclusive
) != 0, 1);
458 FinishThread(&ThreadDataExclusive
);
459 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
461 /* now the blocked shared one should resume */
462 Status
= KeWaitForSingleObject(&ThreadDataShared2
.OutEvent
, Executive
, KernelMode
, FALSE
, NULL
);
463 ok_eq_hex(Status
, STATUS_SUCCESS
);
464 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
465 ok_eq_int(Res
->ActiveCount
, 1);
466 FinishThread(&ThreadDataShared2
);
467 CheckResourceStatus(Res
, FALSE
, 0LU, 0LU, 0LU);
468 ok_eq_int(Res
->ActiveCount
, 0);
477 NTSTATUS Status
= STATUS_SUCCESS
;
478 PTHREAD_DATA ThreadData
= Context
;
481 KeEnterCriticalRegion();
482 Ret
= ThreadData
->AcquireResource(ThreadData
->Res
, ThreadData
->Wait
);
483 if (ThreadData
->RetExpected
)
484 ok_bool_true(Ret
, "AcquireResource returned");
486 ok_bool_false(Ret
, "AcquireResource returned");
487 KeLeaveCriticalRegion();
489 ExReleaseResourceForThreadLite(ThreadData
->Res
, (ULONG_PTR
)ThreadData
->Res
| 3);
491 ok_bool_false(KeSetEvent(&ThreadData
->OutEvent
, 0, TRUE
), "KeSetEvent returned");
492 Status
= KeWaitForSingleObject(&ThreadData
->InEvent
, Executive
, KernelMode
, FALSE
, NULL
);
493 ok_eq_hex(Status
, STATUS_SUCCESS
);
498 TestResourceWithOwner(
502 THREAD_DATA ThreadDataOwner
;
504 InitThreadDataEx(&ThreadDataOwner
, Res
, ExAcquireResourceExclusiveLite
, TestOwnerRes
);
506 KeEnterCriticalRegion();
507 ok_bool_true(ExAcquireResourceExclusiveLite(Res
, FALSE
), "ExAcquireResourceExclusiveLite returned");
508 ExSetResourceOwnerPointer(Res
, (PVOID
)((ULONG_PTR
)Res
| 3));
509 KeLeaveCriticalRegion();
511 Status
= StartThread(&ThreadDataOwner
, NULL
, FALSE
, FALSE
);
512 ok_eq_hex(Status
, STATUS_SUCCESS
);
514 FinishThread(&ThreadDataOwner
);
517 START_TEST(ExResource
)
523 pExEnterCriticalRegionAndAcquireResourceShared
= KmtGetSystemRoutineAddress(L
"ExEnterCriticalRegionAndAcquireResourceShared");
524 pExEnterCriticalRegionAndAcquireSharedWaitForExclusive
= KmtGetSystemRoutineAddress(L
"ExEnterCriticalRegionAndAcquireSharedWaitForExclusive");
525 pExEnterCriticalRegionAndAcquireResourceExclusive
= KmtGetSystemRoutineAddress(L
"ExEnterCriticalRegionAndAcquireResourceExclusive");
526 pExReleaseResourceAndLeaveCriticalRegion
= KmtGetSystemRoutineAddress(L
"ExReleaseResourceAndLeaveCriticalRegion");
527 pKeAreAllApcsDisabled
= KmtGetSystemRoutineAddress(L
"KeAreAllApcsDisabled");
529 if (skip(pKeAreAllApcsDisabled
!= NULL
, "KeAreAllApcsDisabled unavailable\n"))
531 /* We can live without this function here */
534 /* this must be true even with the different structure versions */
535 ASSERT(sizeof(ERESOURCE
) == sizeof(ERESOURCE_2K3
));
537 /* functional tests & internals */
538 Irql
= KeRaiseIrqlToDpcLevel();
539 Status
= ExInitializeResourceLite(&Res
);
540 ok_eq_hex(Status
, STATUS_SUCCESS
);
541 KeLowerIrql(APC_LEVEL
);
543 Status
= ExDeleteResourceLite(&Res
);
544 ok_eq_hex(Status
, STATUS_SUCCESS
);
547 memset(&Res
, 0x55, sizeof Res
);
548 Status
= ExInitializeResourceLite(&Res
);
549 ok_eq_hex(Status
, STATUS_SUCCESS
);
550 CheckResourceFields((PERESOURCE_2K3
)&Res
, FALSE
);
552 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
554 TestResourceSharedAccess(&Res
);
555 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
557 TestResourceExclusiveAccess(&Res
);
558 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
560 TestResourceUndocumentedShortcuts(&Res
, FALSE
);
561 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
562 KeRaiseIrql(APC_LEVEL
, &Irql
);
563 TestResourceUndocumentedShortcuts(&Res
, TRUE
);
565 ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned");
566 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
568 TestResourceWithThreads(&Res
);
570 /* ExReinitializeResourceLite cleans up after us */
571 Status
= ExReinitializeResourceLite(&Res
);
572 ok_eq_hex(Status
, STATUS_SUCCESS
);
573 CheckResourceFields((PERESOURCE_2K3
)&Res
, TRUE
);
574 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
576 TestResourceWithOwner(&Res
);
577 CheckResourceStatus(&Res
, FALSE
, 0LU, 0LU, 0LU);
579 Status
= ExDeleteResourceLite(&Res
);
580 ok_eq_hex(Status
, STATUS_SUCCESS
);
582 /* parameter checks */
583 Status
= STATUS_SUCCESS
;
585 ExInitializeResourceLite(NULL
);
586 } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
) {
587 Status
= _SEH2_GetExceptionCode();
589 ok_eq_hex(Status
, STATUS_ACCESS_VIOLATION
);
592 ExDeleteResourceLite(NULL);
593 Status = ExDeleteResourceLite(&Res);*/