1

我有一个总线驱动程序,它为自定义以太网卡的每个物理端口创建一个 PDO。我还有一个安装在每个 PDO 上的 NDIS 微型端口驱动程序。

Bus Driver 基于静态 Toaster 示例。NDIS Miniport 基于 Netvmini 修改以匹配硬件。

ToasterInterface.InterfaceHeader.InterfaceReference =
    WdfDeviceInterfaceReferenceNoOp;
ToasterInterface.InterfaceHeader.InterfaceDereference =
    WdfDeviceInterfaceDereferenceNoOp;

ToasterInterface.GetCrispinessLevel  = Bus_GetCrispinessLevel;
ToasterInterface.SetCrispinessLevel  = Bus_SetCrispinessLevel;
ToasterInterface.IsSafetyLockEnabled = Bus_IsSafetyLockEnabled;

WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
                                (PINTERFACE) &ToasterInterface,
                                &GUID_TOASTER_INTERFACE_STANDARD,
                                NULL);

状态 = WdfDeviceAddQueryInterface(hChild, &qiConfig);

如何从 NDIS 驱动程序调用 KMDF WDF 定义的接口?谢谢

4

2 回答 2

1

从驱动程序的 NDIS 端,您可以调用NdisMGetDeviceProperty以获取单个微型端口的 FDO。从那里,以通常的方式调用IoCallDriver(或IoSynchronousCallDriver保存几行代码)发出IRP_MN_QUERY_INTERFACE.

您需要确保在 MiniportHalt 完成之前取消对总线接口的引用。

于 2017-08-15T01:26:54.147 回答
1

这是对我有用的代码。

    // ***********************************
    // Inside Header (Both Drivers, Shared)
    // ***********************************

    typedef
    NTSTATUS
    (*PMY_BUS_INTERFACE_TEST) (
        _In_ PINTERFACE InterfaceHeader,
        _In_ PVOID pDataIn,
        _In_ size_t szDataInSize
        );

    typedef struct _MY_BUS_INTERFACE {
        INTERFACE InterfaceHeader;
        PMY_BUS_INTERFACE_TEST InterfaceTest;
    } MY_BUS_INTERFACE, *PMY_BUS_INTERFACE;

    #define MY_BUS_INTERFACE_VERSION 1
    DEFINE_GUID(GUID_MY_BUS_INTERFACE, 0x12345678, 0x1234, 0x1234, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);


    // ***********************************
    // pdo.c: inside Bus_CreatePdo
    // ***********************************


    //
    // Test Interface
    //
    MY_BUS_INTERFACE arincInterface;
    RtlZeroMemory(&arincInterface, sizeof(MY_BUS_INTERFACE));
    arincInterface.InterfaceHeader.Size = sizeof(MY_BUS_INTERFACE);
    arincInterface.InterfaceHeader.Version = MY_BUS_INTERFACE_VERSION;
    arincInterface.InterfaceHeader.Context = (PVOID)hChild;
    arincInterface.InterfaceHeader.InterfaceReference = WdfDeviceInterfaceReferenceNoOp;
    arincInterface.InterfaceHeader.InterfaceDereference = WdfDeviceInterfaceDereferenceNoOp;

    arincInterface.InterfaceTest = Bus_InterfaceTest;

    WDF_QUERY_INTERFACE_CONFIG qic;
    WDF_QUERY_INTERFACE_CONFIG_INIT(&qic,
        (PINTERFACE)&arincInterface,
        &GUID_MY_BUS_INTERFACE,
        NULL);


    // ***********************************
    // Inside pdo.c
    // ***********************************

    NTSTATUS
    Bus_InterfaceTest(
        _In_ PINTERFACE InterfaceHeader,
        _In_ PVOID pDataIn,
        _In_ size_t szDataInSize
    )
    {
        NTSTATUS status = STATUS_SUCCESS;

        UNREFERENCED_PARAMETER(InterfaceHeader);
        UNREFERENCED_PARAMETER(pDataIn);
        UNREFERENCED_PARAMETER(szDataInSize);

        KdPrint(("Bus_InterfaceTest: pDataIn [%p] [%llu] \n", pDataIn, szDataInSize));

        status = -678;

        return status;
    }



    // ***********************************
    // Inside Miniport Driver
    // ***********************************

    //
    // Query Interface Setup
    //
    MY_BUS_INTERFACE myBusInterface;
    PMY_BUS_INTERFACE pMyBusInterface = &myBusInterface;

    //
    // Initialize an event to block on
    //
    KEVENT event;
    KeInitializeEvent(&event, SynchronizationEvent, FALSE);

    //
    // Build an irp
    //
    IO_STATUS_BLOCK     ioStatus;

    PIRP irp = IoBuildSynchronousFsdRequest(
        IRP_MJ_PNP,
        Adapter->NextDeviceObject,
        NULL,
        0,
        NULL,
        &event,
        &ioStatus
    );

    if (!irp) {
        pMyBusInterface = NULL;
        Status = STATUS_INSUFFICIENT_RESOURCES;
        break;
    }

    irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
    irp->IoStatus.Information = 0;

    //
    // Get the irp stack location
    //
    PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(irp);

    //
    // Use QUERY_INTERFACE to get the address of the direct-call
    // ACPI interfaces.
    //
    irpSp->MajorFunction = IRP_MJ_PNP;
    irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
    irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID)&GUID_MY_BUS_INTERFACE;
    irpSp->Parameters.QueryInterface.Version = MY_BUS_INTERFACE_VERSION;
    irpSp->Parameters.QueryInterface.Size = sizeof(MY_BUS_INTERFACE);
    irpSp->Parameters.QueryInterface.Interface = (PINTERFACE)pMyBusInterface;
    irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;

    //
    // send the request down
    //
    NTSTATUS status = IoCallDriver(Adapter->NextDeviceObject, irp);
    if (status == STATUS_PENDING) {
        KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
        status = ioStatus.Status;
    }
    else if (!NT_SUCCESS(status))
    {
        KdPrint(("IoCallDriver was not pending or success \n"));
        break;
    }

    //
    // test interface
    //
    char testData[260] = "TEST";
    NTSTATUS interfaceTestStatus = (*myBusInterface.InterfaceTest)(
        (PINTERFACE)pMyBusInterface,
        (PVOID)testData,
        strlen(testData)
        );
    if (interfaceTestStatus == -678)
    {
        KdPrint(("************************************** \n"));
        KdPrint(("***     InterfaceTest SUCCESS      *** \n"));
        KdPrint(("************************************** \n"));

        status = STATUS_SUCCESS;
    }
    else {
        KdPrint(("************************************** \n"));
        KdPrint(("***     InterfaceTest FAILURE      *** \n"));
        KdPrint(("************************************** \n"));
        status = STATUS_UNSUCCESSFUL;
        (*myBusInterface.InterfaceHeader.InterfaceDereference)(myBusInterface.InterfaceHeader.Context);
        break;
    }

    //
    // Dereference Interface
    //
    (*myBusInterface.InterfaceHeader.InterfaceDereference)(myBusInterface.InterfaceHeader.Context);
于 2017-08-16T13:05:19.890 回答