KeWaitForSingleObject failed on AMD64

I have a drive that uses a worker thread (based on src\input\vserial sample). The driver runs fine on an XP 32bit computer, but bug check on a AMD64 dual in EvtDeviceContextCleanup. I just load then unload the driver so the execution path just went through the functions below.

NTSTATUS MyTestEvtDeviceAdd(IN WDFDRIVER Driver, PWDFDEVICE_INIT DeviceInit)
{

// Initialize the work queue semaphore
KeInitializeSemaphore(&pDevContext->IrpQueueSem, 0, MAXLONG);
// Reset the termination flag
pDevContext->bTerminateThread = FALSE;

InitializeObjectAttributes(&objAttrs, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &objAttrs, (HANDLE)0, NULL, WorkerThreadMain, pDevContext);

// Obtain pointer and close thread
ObReferenceObjectByHandle(hThread, THREAD_ALL_ACCESS, NULL, KernelMode, (PVOID*)&pDevContext->pThreadObj, NULL);
ZwClose(hThread);

}

VOID WorkerThreadMain(IN PVOID pContext)
{

while(TRUE)
{

KeWaitForSingleObject(&pDevContext->IrpQueueSem, Executive, KernelMode, FALSE, NULL);

// Exit when termination flag is set
if(pDevContext->bTerminateThread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
return;
}

// Do its things here

}
}

VOID MyTestEvtDeviceContextCleanup(IN WDFDEVICE Device)
{

if(pDevContext->pThreadObj)
{
// Set the termination flag
pDevContext->bTerminateThread = TRUE;
// Wake worker thread up so it can handle the termination
KeReleaseSemaphore(&(pDevContext->IrpQueueSem), 0, 1, TRUE);
// Wait for the thread to terminate
status = KeWaitForSingleObject(&(pDevContext->pThreadObj), Executive, KernelMode, FALSE, NULL);
ObDereferenceObject(&(pDevContext->pThreadObj));
}

}

I compared the value of pDevContext->pThreadObj at creation time and crash time, and they are the same. Below is output from !analyze -v

*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************

IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 0000000100060000, memory referenced
Arg2: 000000000000000c, IRQL
Arg3: 0000000000000001, value 0 = read operation, 1 = write operation
Arg4: fffff8000105b554, address which referenced memory

Debugging Details:

*** No owner thread found for resource fffff800013e6ae0
*** No owner thread found for resource fffff800013e6ae0

WRITE_ADDRESS: 0000000100060000

CURRENT_IRQL: c

FAULTING_IP:
nt!KeWaitForSingleObject+404
fffff800`0105b554 4c8928 mov qword ptr [rax],r13

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0xA

PROCESS_NAME: System

TRAP_FRAME: fffffadfc8e8ca60 – (.trap fffffadfc8e8ca60)
NOTE: The trap frame does not contain all registers.
Some register values may be zeroed.
rax=0000000100060000 rbx=0000000000000000 rcx=fffffadfcda95fb8
rdx=fffff78000000014 rsi=0000000000000008 rdi=fffffadfcd5144f0
rip=fffff8000105b554 rsp=fffffadfc8e8cbf0 rbp=fffffadfcdd52bd0
r8=0000000000000000 r9=0000000000000000 r10=fffff78000000008
r11=0000000000000000 r12=0000000000000000 r13=0000000000000000
r14=0000000000000000 r15=0000000000000000
iopl=0 nv up ei pl zr na po nc
nt!KeWaitForSingleObject+0x404:
fffff800`0105b554 4c8928 mov qword ptr [rax],r13 ds:0004:0000=???
Resetting default scope

LOCK_ADDRESS: fffff800013e6be0 – (!locks fffff800013e6be0)

Resource @ nt!IopDeviceTreeLock (0xfffff800013e6be0) Shared 1 owning threads
Threads: fffffadfcdd52bd0-01<*>
1 total locks, 1 locks currently held

PNP_TRIAGE:
Lock address : 0xfffff800013e6be0
Thread Count : 1
Thread address: 0xfffffadfcdd52bd0
Thread wait : 0x10611d8a

LAST_CONTROL_TRANSFER: from fffff8000105c0c7 to fffff8000119c2c0

STACK_TEXT:
fffffadfc8e8c1e8 fffff8000105c0c7 : 000000000000000a fffffadfcdd52bd0 0000000100060000 0000000000000001 : nt!DbgBreakPointWithStatus
fffffadfc8e8c1f0 fffff8000105d3d0 : fffff80000000003 000000000000000a 0000000100060000 000000000000000c : nt!KiBugCheckDebugBreak+0x17
fffffadfc8e8c260 fffff80001193144 : 000000000000000a 0000000100060000 000000000000000c 0000000000000001 : nt!KeBugCheck2+0x6a0
fffffadfc8e8c8a0 fffff800011a21b4 : 000000000000000a 0000000100060000 000000000000000c 0000000000000001 : nt!KeBugCheckEx+0x104
fffffadfc8e8c8e0 fffff800011a1147 : 0000000000000001 0000000100060000 0000000000000000 fffffadfc8e8ca60 : nt!KiBugCheckDispatch+0x74
fffffadfc8e8ca60 fffff8000105b554 : 0000e5fb00000000 0000000000000008 0000000000000004 fffffadfcda95f00 : nt!KiPageFault+0x207
fffffadfc8e8cbf0 fffffadfc8b459c9 : fffffadfcda95fb0 fffffadf00000000 0000000000000000 0000000000000000 : nt!KeWaitForSingleObject+0x404
fffffadfc8e8cc80 fffffadfc5f12f6d : 000005203256a438 00000000a079654b 0000000000000001 0000000000000000 : MyTestDev!MyTestEvtDeviceContextCleanup+0x179 [c:\projects\kwdftest\mytestdev.c @ 915]
fffffadfc8e8ccd0 fffffadfc5f15d2f : fffffadfcda95bc0 fffffadfcda95bc0 fffffadfcda95be0 fffffadfcd514530 : Wdf01000!FxObject::CallCleanup+0x75
fffffadfc8e8cd00 fffffadfc5f14f9b : fffffadfcda95bc0 fffffadf00000005 fffffadf45457000 0000000000000101 : Wdf01000!FxObject::DisposeChildrenWorker+0x457
fffffadfc8e8ce80 fffffadfc5f153be : fffffadfcda95bc0 fffffadfc5f13700 fffffadfcd6e9001 0000000000000002 : Wdf01000!FxObject::PerformDisposingDisposeChildrenLocked+0x1d3
fffffadfc8e8cf90 fffffadfc5f1450e : fffffadfcda95bc0 fffffadfcda95b00 fffffadfcda95b01 0000000000000000 : Wdf01000!FxObject::PerformEarlyDisposeWorkerAndUnlock+0x23e
fffffadfc8e8d060 fffffadfc5f54a56 : fffffadfcda95bc0 fffffadfcd5dcb80 0000000000000124 0000000000000000 : Wdf01000!FxObject::EarlyDispose+0x226
fffffadfc8e8d130 fffffadfc5f5243f : fffffadfcd5dcb80 fffffadfcd5dcb80 0000000000000124 fffffadfcd5dcb80 : Wdf01000!FxPkgPnp::PnpEventRemovedCommonCode+0x2d2
fffffadfc8e8d1b0 fffffadfc5f53855 : fffffadfcd5dcb80 0000052000000004 fffffadf00000015 fffffadfc5f816d0 : Wdf01000!FxPkgFdo::PnpEventFdoRemovedOverload+0x17
fffffadfc8e8d1e0 fffffadfc5f53058 : fffffadfcd5dcb80 fffffadf00000117 fffffadfcd5dcb80 000005203256a400 : Wdf01000!FxPkgPnp::PnpEnterNewState+0x385
fffffadfc8e8d2b0 fffffadfc5f52d90 : fffffadfcd5dcb80 fffffadfc8e8d430 0000000000000000 fffffadf00000000 : Wdf01000!FxPkgPnp::PnpProcessEventInner+0x154
fffffadfc8e8d3a0 fffffadfc5f45b2f : fffffadfcd5dcb80 fffffadf00000200 0000000000000000 fffffadfc5f8c1a8 : Wdf01000!FxPkgPnp::PnpProcessEvent+0x4fc
fffffadfc8e8d480 fffffadfc5f433a3 : fffffadfcd5dcb80 fffffadfc8e8d5b0 0000000000000000 000005203256a438 : Wdf01000!FxPkgPnp::_PnpRemoveDevice+0xe7
fffffadfc8e8d530 fffffadfc5f1ad8f : fffffadfcd5dcb80 fffffadfcd684cf0 fffffadfcd684cf0 fffffadfcdbf2630 : Wdf01000!FxPkgPnp::Dispatch+0x79b
fffffadfc8e8d600 fffffadfc5f1acc2 : fffffadfcd5db070 fffffadfcd684cf0 fffffadfcd5db070 fffff80001000000 : Wdf01000!FxDevice::Dispatch+0xb7
fffffadfc8e8d630 fffff800014e6442 : fffffadfcd5db070 fffffadfcd684cf0 fffffadfc8e8d758 00000000ffffffff : Wdf01000!FxDevice::DispatchWithLock+0x82
fffffadfc8e8d670 fffff800014e6a1f : fffffadfcdbf2870 fffffadfc8e8d758 0000000000000000 0000000000000000 : nt!IopSynchronousCall+0x2b2
fffffadfc8e8d710 fffff8000104fe47 : fffffadfcdbf2870 fffff80000000002 fffffadfcdbf2870 0000000000000000 : nt!IopRemoveDevice+0x1cf
fffffadfc8e8d7f0 fffff800014e9b4e : fffffadfcdbf2630 fffff80000000015 fffffa8000357930 0000000000000002 : nt!IopRemoveLockedDeviceNode+0x667
fffffadfc8e8d890 fffff800014f37bf : fffffadfcdbf2870 fffffa8000357930 0000000000000002 fffff80001007201 : nt!IopDeleteLockedDeviceNodes+0x29e
fffffadfc8e8d910 fffff800014f0a10 : fffffadfc8e8da70 fffff80001632210 fffffadfc8e8da90 8101010101010100 : nt!PiProcessQueryRemoveAndEject+0x188f
fffffadfc8e8da40 fffff80001185cb4 : fffffadfcd9d5d40 fffffadf00000001 0000000000000000 0000000000000000 : nt!PiWalkDeviceList+0x790
fffffadfc8e8dce0 fffff8000157059e : 0000000000000001 0000000000000000 0000000000000000 0000000000000000 : nt!ExpWorkerThread+0x194
fffffadfc8e8dd70 fffff8000119be76 : fffff80001185b20 0000000000000001 fffff80001570560 0000000000000000 : nt!PspSystemThreadStartup+0x3e
fffffadfc8e8ddd0 0000000000000000 : 0000000000000000 0000000000000000 0000000000000000 0000000000000000 : nt!KiStartSystemThread+0x16

STACK_COMMAND: kb

FOLLOWUP_IP:
MyTestDev!MyTestEvtDeviceContextCleanup+179 [c:\projects\kwdftest\mytestdev.c @ 915]
fffffadf`c8b459c9 89442438 mov dword ptr [rsp+38h],eax

FAULTING_SOURCE_CODE:
911: TRUE); // Must call WaitForXxx right after this
912:
913: // Wait for the thread to terminate
914: status = KeWaitForSingleObject(&(pDevContext->pThreadObj), // Ptr to thread

915: Executive, // Reason for wait
916: KernelMode, // wait mode
917: FALSE, // Alertable?
918: NULL); // ptr to timeout value. Null = indefinetely
919:
920: ObDereferenceObject(&(pDevContext->pThreadObj));

SYMBOL_STACK_INDEX: 7

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: MyTestDev

IMAGE_NAME: MyTestDev.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 498b4647

SYMBOL_NAME: MyTestDev!MyTestEvtDeviceContextCleanup+179

FAILURE_BUCKET_ID: X64_0xA_W_MyTestDev!MyTestEvtDeviceContextCleanup+179

BUCKET_ID: X64_0xA_W_MyTestDev!MyTestEvtDeviceContextCleanup+179

Followup: MachineOwner

As the system provides storage for thread objects, the expression
&(pDevContext->ThreadObj) is invalid pointer indirection.

//Daniel

wrote in message news:xxxxx@ntdev…
> status = KeWaitForSingleObject(&(pDevContext->pThreadObj),
> Executive, KernelMode, FALSE, NULL);
> ObDereferenceObject(&(pDevContext->pThreadObj));
> }

Thanks. I must have looked at the line right above (KeReleaseSemaphore(&(pDevContext->IrpQueueSem),…) and applied the same “logic” two the next two function calls.