IoConnectInterruptEx() Fail

I am trying to register an MSI interrupt handling routine with wdm.
However, calling the IoConnectInterruptEx() function causes a BSOD (PNP_DETECTED_FATAL_ERROR).

May I know what am I doing wrong?
I wrote the code like this:

StartDevice(
PDEVICE_OBJECT fdo,
PCM_PARTIAL_RESOURCE_LIST ResourceListRaw,
PCM_PARTIAL_RESOURCE_LIST ResourceList
)
{
U32 vector;
KIRQL IrqL;
KAFFINITY affinity;
KINTERRUPT_MODE mode;
DEVICE_EXTENSION* pdx;
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceRaw;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource;

 ....

pdx = fdo->DeviceExtension;
for (i = 0; i < ResourceListRaw->Count; ++i, ++Resource, ++ResourceRaw)
{
    KdPrint(("              Resource %02d\n", i));
    switch (ResourceRaw->Type)
    {
        case CmResourceTypeInterrupt:

        if (ResourceRaw->Flags & CM_RESOURCE_INTERRUPT_MESSAGE)
        {
            MSIIntPresent = TRUE;
            IrqL = (KIRQL)Resource->u.MessageInterrupt.Translated.Level;
            vector = Resource->u.MessageInterrupt.Translated.Vector;
            affinity = Resource->u.MessageInterrupt.Translated.Affinity;
            ShareVector = (BOOLEAN)(Resource->ShareDisposition == CmResourceShareShared);
            KdPrint(("                Type    : Message Interrupt\n"
                "                Vector    : (Translated = 0x%02x)\n"
                "                IRQL    : (Translated = 0x%02x)\n",
                "                ShareVector    : (Translated = 0x%02x)\n",
                vector, IrqL, ShareVector));
        }
        ...
    }
}
if (MSIIntPresent)
{
    IO_CONNECT_INTERRUPT_PARAMETERS params;
    RtlZeroMemory(&params, sizeof(IO_CONNECT_INTERRUPT_PARAMETERS));
    KdPrint(("MSIIntPresent\n"));
    KdPrint(("Vector=%d IrqL=%d affinity=%d ShareVector=%d,\n", vector, IrqL, affinity, ShareVector));
    params.Version = CONNECT_FULLY_SPECIFIED;
    params.FullySpecified.PhysicalDeviceObject = pdx->pPhysicalDeviceObject;
    params.FullySpecified.InterruptObject = &pdx->pInterruptObject;
    params.FullySpecified.ServiceRoutine = OnInterrupt;
    params.FullySpecified.ServiceContext = fdo;
    params.FullySpecified.SpinLock = NULL;
    params.FullySpecified.Vector = vector;
    params.FullySpecified.Irql = IrqL;
    params.FullySpecified.SynchronizeIrql = IrqL; 
    params.FullySpecified.InterruptMode = mode;
    params.FullySpecified.ShareVector = ShareVector;
    params.FullySpecified.ProcessorEnableMask = affinity;
    params.FullySpecified.FloatingSave = FALSE; 
    status = IoConnectInterruptEx(&params);
    if (!NT_SUCCESS(status))
    {
        KdPrint((DBG_NAME "ERROR - IoConnectInterrupt() failed, status = 0x%08x\n", status));
        if (status == STATUS_NOT_SUPPORTED)
        {
            KdPrint(("STATUS_NOT_SUPPORTED\n"));
        }
        pdx->pInterruptObject = NULL;
    }
    else
    {
        KdPrint((DBG_NAME "Connected to interrupt vector\n"));
    }  
}

}

Is there something wrong with specifying PhysicalDeviceObject or ServiceContext?

I’ve read the documentation provided by microsoft, but I don’t quite understand.
( https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/using-the-connect-fully-specified-version-of-ioconnectinterruptex )
Any advice would be appreciated.

My advice would be to not use WDM, but rather use KMDF.

Peter

1 Like