static NTSTATUS NTAPI NotificationCallback( _In_ PVOID NotificationStructure, _Inout_opt_ PVOID Context) { PDEVICE_INTERFACE_CHANGE_NOTIFICATION Notification = NotificationStructure; NTSTATUS Status; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE Handle; ok_irql(PASSIVE_LEVEL); ok_eq_pointer(Context, &NotificationContext); ok_eq_uint(Notification->Version, 1); ok_eq_uint(Notification->Size, sizeof(*Notification)); /* symbolic link must exist */ trace("Interface change: %wZ\n", Notification->SymbolicLinkName); InitializeObjectAttributes(&ObjectAttributes, Notification->SymbolicLinkName, OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenSymbolicLinkObject(&Handle, GENERIC_READ, &ObjectAttributes); ok_eq_hex(Status, STATUS_SUCCESS); if (!skip(NT_SUCCESS(Status), "No symbolic link\n")) { Status = ObCloseHandle(Handle, KernelMode); ok_eq_hex(Status, STATUS_SUCCESS); } return STATUS_SUCCESS; }
static VOID NTAPI DpcHandler( IN PRKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2) { PKPRCB Prcb = KeGetCurrentPrcb(); ok_irql(DISPATCH_LEVEL); InterlockedIncrement(&DpcCount); ok(DeferredContext == Dpc, "DeferredContext = %p, Dpc = %p, expected equal\n", DeferredContext, Dpc); ok_eq_pointer(SystemArgument1, (PVOID)0xabc123); ok_eq_pointer(SystemArgument2, (PVOID)0x5678); /* KDPC object contents */ ok_eq_uint(Dpc->Type, DpcObject); ok_eq_uint(Dpc->Importance, DpcImportance); ok_eq_uint(Dpc->Number, 0); ok(Dpc->DpcListEntry.Blink != NULL, "\n"); ok(Dpc->DpcListEntry.Blink != &Dpc->DpcListEntry, "\n"); if (!skip(Dpc->DpcListEntry.Blink != NULL, "DpcListEntry.Blink == NULL\n")) ok_eq_pointer(Dpc->DpcListEntry.Flink, Dpc->DpcListEntry.Blink->Flink); ok(Dpc->DpcListEntry.Flink != NULL, "\n"); ok(Dpc->DpcListEntry.Flink != &Dpc->DpcListEntry, "\n"); if (!skip(Dpc->DpcListEntry.Flink != NULL, "DpcListEntry.Flink == NULL\n")) ok_eq_pointer(Dpc->DpcListEntry.Blink, Dpc->DpcListEntry.Flink->Blink); ok_eq_pointer(Dpc->DeferredRoutine, DpcHandler); ok_eq_pointer(Dpc->DeferredContext, DeferredContext); ok_eq_pointer(Dpc->SystemArgument1, SystemArgument1); ok_eq_pointer(Dpc->SystemArgument2, SystemArgument2); ok_eq_pointer(Dpc->DpcData, NULL); ok_eq_uint(Prcb->DpcRoutineActive, 1); /* this DPC is not in the list anymore, but it was at the head! */ ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Flink, Dpc->DpcListEntry.Flink); ok_eq_pointer(Prcb->DpcData[DPC_NORMAL].DpcListHead.Blink, Dpc->DpcListEntry.Blink); }
static VOID TestEventFunctional( IN PKEVENT Event, IN EVENT_TYPE Type, IN KIRQL OriginalIrql) { LONG State; PKTHREAD Thread = KeGetCurrentThread(); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); memset(Event, 0x55, sizeof *Event); KeInitializeEvent(Event, Type, TRUE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); Event->Header.SignalState = 0x12345678L; CheckEvent(Event, Type, 0x12345678L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KePulseEvent(Event, 0, FALSE); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x12345678L); Event->Header.SignalState = 0x12345678L; KeClearEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0L); State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 1L); Event->Header.SignalState = 0x23456789L; State = KeSetEvent(Event, 0, FALSE); CheckEvent(Event, Type, 1L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x23456789L); Event->Header.SignalState = 0x3456789AL; State = KeResetEvent(Event); CheckEvent(Event, Type, 0L, FALSE, OriginalIrql, (PVOID *)NULL, 0); ok_eq_long(State, 0x3456789AL); /* Irql is raised to DISPATCH_LEVEL here, which kills checked build, * a spinlock is acquired and never released, which kills MP build */ if ((OriginalIrql <= DISPATCH_LEVEL || !KmtIsCheckedBuild) && !KmtIsMultiProcessorBuild) { Event->Header.SignalState = 0x456789ABL; State = KeSetEvent(Event, 0, TRUE); CheckEvent(Event, Type, 1L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x456789ABL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); Event->Header.SignalState = 0x56789ABCL; State = KePulseEvent(Event, 0, TRUE); CheckEvent(Event, Type, 0L, TRUE, DISPATCH_LEVEL, (PVOID *)NULL, 0); ok_eq_long(State, 0x56789ABCL); ok_eq_uint(Thread->WaitIrql, OriginalIrql); /* repair the "damage" */ Thread->WaitNext = FALSE; KmtSetIrql(OriginalIrql); } ok_irql(OriginalIrql); KmtSetIrql(OriginalIrql); }
static VOID TestQueryLink( _In_ HANDLE LinkHandle, _In_ PCUNICODE_STRING ExpectedTarget) { NTSTATUS Status; WCHAR QueriedTargetBuffer[32]; UNICODE_STRING QueriedTarget; ULONG ResultLength; PULONG pResultLength; ULONG i; for (i = 0; i < 2; i++) { if (i == 0) { pResultLength = &ResultLength; } else { pResultLength = NULL; } /* Query with NULL Buffer just gives us the length */ RtlInitEmptyUnicodeString(&QueriedTarget, NULL, 0); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.MaximumLength, 0); ok_eq_pointer(QueriedTarget.Buffer, NULL); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); /* Query with Length-1 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length - 1); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length - 1); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); /* Query with Length buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); if (pResultLength && QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) { ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with Length+1 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length + 1); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + 1); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); if (pResultLength && QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) { ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with Length+2 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length + sizeof(WCHAR)); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + sizeof(WCHAR)); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); if (pResultLength) { if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with full-sized buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, sizeof(QueriedTargetBuffer)); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok_eq_uint(QueriedTarget.MaximumLength, sizeof(QueriedTargetBuffer)); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); if (pResultLength) { if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } } }
static VOID TestDriverObject( IN PDRIVER_OBJECT DriverObject, IN PCUNICODE_STRING RegistryPath OPTIONAL, IN DRIVER_STATUS DriverStatus) { BOOLEAN CheckThisDispatchRoutine; PVOID FirstMajorFunc; int i; UNICODE_STRING HardwareDatabase = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\HARDWARE\\DESCRIPTION\\SYSTEM"); UNICODE_STRING RegPath = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\ControlSet001\\Services\\Kmtest-IoDeviceObject"); UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"\\Driver\\Kmtest-IoDeviceObject"); UNICODE_STRING ServiceKeyName = RTL_CONSTANT_STRING(L"Kmtest-IoDeviceObject"); BOOLEAN Equal; ok(DriverObject->Size == sizeof(DRIVER_OBJECT), "Size does not match, got %x\n",DriverObject->Size); ok(DriverObject->Type == 4, "Type does not match 4. got %d\n", DriverObject->Type); if (DriverStatus == DriverStatusEntry) { ok(DriverObject->DeviceObject == NULL, "Expected DeviceObject pointer to be 0, got %p\n", DriverObject->DeviceObject); ok (DriverObject->Flags == DRVO_LEGACY_DRIVER, "Expected Flags to be DRVO_LEGACY_DRIVER, got %lu\n", DriverObject->Flags); ok(DriverObject->DriverStart < (PVOID)TestEntry, "DriverStart is %p, expected < %p\n", DriverObject->DriverStart, (PVOID)TestEntry); ok(DriverObject->DriverSize > 0x2000, "DriverSize 0x%lx\n", DriverObject->DriverSize); ok_eq_pointer(DriverObject->DriverExtension, (PDRIVER_EXTENSION)(DriverObject + 1)); ok_eq_pointer(DriverObject->DriverExtension->DriverObject, DriverObject); ok_eq_pointer(DriverObject->DriverExtension->AddDevice, NULL); ok_eq_ulong(DriverObject->DriverExtension->Count, 0UL); Equal = RtlEqualUnicodeString(RegistryPath, &RegPath, FALSE); ok(Equal, "RegistryPath is '%wZ'\n", RegistryPath); ok((ULONG_PTR)RegistryPath % PAGE_SIZE == 0, "RegistryPath %p not page-aligned\n", RegistryPath); ok_eq_pointer(RegistryPath->Buffer, (PWCHAR)(RegistryPath + 1)); ok_eq_uint(RegistryPath->MaximumLength, RegistryPath->Length); Equal = RtlEqualUnicodeString(&DriverObject->DriverExtension->ServiceKeyName, &ServiceKeyName, FALSE); ok(Equal, "ServiceKeyName is '%wZ'\n", &DriverObject->DriverExtension->ServiceKeyName); ok_eq_tag(KmtGetPoolTag(DriverObject->DriverExtension->ServiceKeyName.Buffer), ' oI'); ok_eq_uint((KmtGetPoolType(DriverObject->DriverExtension->ServiceKeyName.Buffer) - 1) & BASE_POOL_TYPE_MASK, NonPagedPool); ok_eq_uint(DriverObject->DriverExtension->ServiceKeyName.MaximumLength, DriverObject->DriverExtension->ServiceKeyName.Length + sizeof(UNICODE_NULL)); ok_eq_uint(DriverObject->DriverExtension->ServiceKeyName.Buffer[DriverObject->DriverExtension->ServiceKeyName.Length / sizeof(WCHAR)], UNICODE_NULL); Equal = RtlEqualUnicodeString(&DriverObject->DriverName, &DriverName, FALSE); ok(Equal, "DriverName is '%wZ'\n", &DriverObject->DriverName); ok_eq_tag(KmtGetPoolTag(DriverObject->DriverName.Buffer), ' oI'); ok_eq_uint((KmtGetPoolType(DriverObject->DriverName.Buffer) - 1) & BASE_POOL_TYPE_MASK, PagedPool); ok_eq_uint(DriverObject->DriverName.MaximumLength, DriverObject->DriverName.Length); // TODO: show that both string and buffer are constants inside ntos Equal = RtlEqualUnicodeString(DriverObject->HardwareDatabase, &HardwareDatabase, FALSE); ok(Equal, "HardwareDatabase is '%wZ'\n", DriverObject->HardwareDatabase); ok_eq_uint(DriverObject->HardwareDatabase->MaximumLength, DriverObject->HardwareDatabase->Length + sizeof(UNICODE_NULL)); ok_eq_uint(DriverObject->HardwareDatabase->Buffer[DriverObject->HardwareDatabase->Length / sizeof(WCHAR)], UNICODE_NULL); ok(DriverObject->DriverInit == DriverEntry, "DriverInit is %p, expected %p\n", (PVOID)DriverObject->DriverInit, (PVOID)DriverEntry); } else if (DriverStatus == DriverStatusIrp) { ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null\n"); ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED), "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED, got %lu\n", DriverObject->Flags); } else if (DriverStatus == DriverStatusUnload) { ok(DriverObject->DeviceObject != NULL, "Expected DeviceObject pointer to non null\n"); ok (DriverObject->Flags == (DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED), "Expected Flags to be DRVO_LEGACY_DRIVER | DRVO_INITIALIZED | DRVO_UNLOAD_INVOKED, got %lu\n", DriverObject->Flags); } else ASSERT(FALSE); /* Select a routine that was not changed */ FirstMajorFunc = DriverObject->MajorFunction[1]; ok(FirstMajorFunc != 0, "Expected MajorFunction[1] to be non NULL\n"); if (!skip(FirstMajorFunc != NULL, "First major function not set!\n")) { for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { if (DriverStatus > 0) CheckThisDispatchRoutine = (i > 3) && (i != 14); else CheckThisDispatchRoutine = TRUE; if (CheckThisDispatchRoutine) { ok(DriverObject->MajorFunction[i] == FirstMajorFunc, "Expected MajorFunction[%d] to match %p\n", i, FirstMajorFunc); } } } }
static VOID TestResourceWithThreads( IN PERESOURCE Res) { NTSTATUS Status = STATUS_SUCCESS; THREAD_DATA ThreadDataShared; THREAD_DATA ThreadDataShared2; THREAD_DATA ThreadDataExclusive; THREAD_DATA ThreadDataSharedStarve; THREAD_DATA ThreadDataSharedWait; LARGE_INTEGER Timeout; Timeout.QuadPart = -10 * 1000 * 10; /* 10 ms */ InitThreadData(&ThreadDataShared, Res, ExAcquireResourceSharedLite); InitThreadData(&ThreadDataShared2, Res, ExAcquireResourceSharedLite); InitThreadData(&ThreadDataExclusive, Res, ExAcquireResourceExclusiveLite); InitThreadData(&ThreadDataSharedStarve, Res, ExAcquireSharedStarveExclusive); InitThreadData(&ThreadDataSharedWait, Res, ExAcquireSharedWaitForExclusive); /* have a thread acquire the resource shared */ Status = StartThread(&ThreadDataShared, NULL, FALSE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* a second thread should be able to acquire the resource shared */ Status = StartThread(&ThreadDataShared2, NULL, FALSE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 2); FinishThread(&ThreadDataShared2); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* now have a thread that tries to acquire the resource exclusive -- it should fail */ Status = StartThread(&ThreadDataExclusive, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataExclusive); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* as above, but this time it should block */ Status = StartThread(&ThreadDataExclusive, &Timeout, TRUE, TRUE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* now try another shared one -- it should fail */ Status = StartThread(&ThreadDataShared2, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataShared2); /* same for ExAcquireSharedWaitForExclusive */ Status = StartThread(&ThreadDataSharedWait, NULL, FALSE, FALSE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataSharedWait); /* ExAcquireSharedStarveExclusive must get access though! */ Status = StartThread(&ThreadDataSharedStarve, NULL, TRUE, TRUE); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 2); FinishThread(&ThreadDataSharedStarve); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 0LU); ok_eq_int(Res->ActiveCount, 1); /* block another shared one */ Status = StartThread(&ThreadDataShared2, &Timeout, TRUE, TRUE); ok_eq_hex(Status, STATUS_TIMEOUT); CheckResourceStatus(Res, FALSE, 0LU, 1LU, 1LU); ok_eq_int(Res->ActiveCount, 1); /* finish the very first one */ FinishThread(&ThreadDataShared); /* now the blocked exclusive one should get the resource */ Status = KeWaitForSingleObject(&ThreadDataExclusive.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 1LU); ok_eq_int(Res->ActiveCount, 1); ok_eq_uint((Res->Flag & ResourceOwnedExclusive) != 0, 1); FinishThread(&ThreadDataExclusive); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); /* now the blocked shared one should resume */ Status = KeWaitForSingleObject(&ThreadDataShared2.OutEvent, Executive, KernelMode, FALSE, NULL); ok_eq_hex(Status, STATUS_SUCCESS); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 1); FinishThread(&ThreadDataShared2); CheckResourceStatus(Res, FALSE, 0LU, 0LU, 0LU); ok_eq_int(Res->ActiveCount, 0); }
static VOID TestResourceUndocumentedShortcuts( IN PERESOURCE Res, IN BOOLEAN AreApcsDisabled) { PVOID Ret; LONG Count = 0; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled); /* ExEnterCriticalRegionAndAcquireResourceShared, ExEnterCriticalRegionAndAcquireSharedWaitForExclusive */ Count = 0; Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); Ret = ExEnterCriticalRegionAndAcquireResourceShared(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); ExEnterCriticalRegionAndAcquireSharedWaitForExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); while (Count-- > 1) { ExReleaseResourceAndLeaveCriticalRegion(Res); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); } ExReleaseResourceAndLeaveCriticalRegion(Res); ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); /* ExEnterCriticalRegionAndAcquireResourceExclusive */ Count = 0; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); Ret = ExEnterCriticalRegionAndAcquireResourceExclusive(Res); ++Count; ok_eq_pointer(Ret, KeGetCurrentThread()->Win32Thread); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); ExReleaseResourceAndLeaveCriticalRegion(Res); --Count; ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_bool(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, TRUE, Count, 0LU, 0LU); ExReleaseResourceAndLeaveCriticalRegion(Res); --Count; ok_bool_false(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ok_eq_uint(KeAreAllApcsDisabled(), AreApcsDisabled); CheckResourceStatus(Res, FALSE, Count, 0LU, 0LU); }