2017-08-10 82 views
0

我有一個總線驅動程序,爲自定義以太網卡的每個物理端口創建一個PDO。我也有安裝在每個PDO上的NDIS微型端口驅動程序。如何從NDIS Miniport調用KMDF WDF接口?

總線驅動程序基於靜態Toaster示例。 NDIS微型端口基於經過修改以匹配硬件的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定義的接口? 謝謝

回答

0

從您的驅動程序的NDIS方面,你可以撥打NdisMGetDeviceProperty獲得單個微型端口的FDO。從那裏,以通常的方式撥打IoCallDriver(或IoSynchronousCallDriver保存幾行代碼)以發出IRP_MN_QUERY_INTERFACE

您需要確保在MiniportHalt完成之前取消引用總線接口。

0

這是我工作的代碼。

// *********************************** 
    // 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);