⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 protocol.c

📁 Vitual Ring Routing 管你知不知道
💻 C
📖 第 1 页 / 共 4 页
字号:
    ZwClose(Key);

    //
    // Update the adapter using the parameters.
    //
    (void) ProtocolControl(PA, &Control);
}

//* ProtocolBindAdapter
//
//  Called by NDIS to tell us about a new adapter.
//
//  Called in a thread context, not at DPC level.
//
void
ProtocolBindAdapter(
    PNDIS_STATUS RetStatus,    // Where to return status of this call.
    NDIS_HANDLE BindContext,   // Handle for calling NdisCompleteBindAdapter.
    PNDIS_STRING AdapterName,  // Name of adapter.
    PVOID SS1,                 // System specific parameter 1.
    PVOID SS2)                 // System specific parameter 2.
{
    //
    // Grovel through the BindContext to get the NDIS protocol handle,
    // and from that get our MiniportAdapter structure.
    // We do this because ProtocolBindAdapter does not give us context.
    //
    NDIS_HANDLE Protocol = NdisProtocolFromBindContext(BindContext);
    MiniportAdapter *VA = (MiniportAdapter *)
        *NdisReservedFieldInProtocol(Protocol);

    UNICODE_STRING GuidName;
    GUID Guid;
    uint BindPrefixLength;

    ProtocolAdapter *PA;
    uint MediaIndex;
    static NDIS_MEDIUM MediaArray[] = { NdisMedium802_3 };
    NDIS_STATUS Status, ErrorStatus;
    uint Filter;
    KIRQL OldIrql;

    UNREFERENCED_PARAMETER(SS1);
    UNREFERENCED_PARAMETER(SS2);

    //
    // Parse past the NDIS binding prefix:
    // We skip the first character (a backslash) and look for a backslash.
    // If we don't find a backslash, RtlGUIDFromString will fail
    // when given a zero-length string.
    //
    BindPrefixLength = 1;
    while (sizeof(WCHAR)*BindPrefixLength < AdapterName->Length) {
        if (((WCHAR *)AdapterName->Buffer)[BindPrefixLength++] == L'\\')
            break;
    }
    BindPrefixLength *= sizeof(WCHAR); // Convert characters to bytes.

    //
    // Convert the NDIS AdapterName to a Guid.
    //
    GuidName.Buffer = (PVOID)((char *)AdapterName->Buffer + BindPrefixLength);
    GuidName.Length = (ushort)(AdapterName->Length - BindPrefixLength);
    GuidName.MaximumLength = (ushort)(AdapterName->MaximumLength - BindPrefixLength);

    if (! NT_SUCCESS(RtlGUIDFromString(&GuidName, &Guid))) {

        KdPrint(("VRR!ProtocolBindAdapter(%.*ls) - bad guid\n",
                 AdapterName->Length / sizeof(WCHAR),
                 AdapterName->Buffer));
        *RetStatus = NDIS_STATUS_FAILURE;
        return;
    }

    PA = (ProtocolAdapter *) ExAllocatePool(NonPagedPool, sizeof *PA);
    if (PA == NULL) {
        *RetStatus = NDIS_STATUS_FAILURE;
        return;
    }

    KdPrint(("VRR!ProtocolBindAdapter(VA %p, Name %.*ls) -> PA %p\n",
             VA,
             AdapterName->Length / sizeof(WCHAR),
             AdapterName->Buffer,
             PA));

    RtlZeroMemory(PA, sizeof *PA);
    PA->VirtualAdapter = VA;
    PA->Index = InterlockedIncrement((PLONG)&VA->NextPhysicalAdapterIndex);
    PA->Guid = Guid;

    NdisAllocatePacketPool(&Status, &PA->PacketPool, PACKET_POOL_SZ, 0);
    if (Status != NDIS_STATUS_SUCCESS) {
        ExFreePool(PA);
        *RetStatus = Status;
        return;
    }

    NdisAllocateBufferPool(&Status, &PA->BufferPool, PACKET_POOL_SZ);
    if (Status != NDIS_STATUS_SUCCESS) {
        NdisFreePacketPool(PA->PacketPool);
        ExFreePool(PA);
        *RetStatus = Status;
        return;
    }

    //
    // Initialize an event in case NdisOpenAdapter completes
    // asynchronously via ProtocolOpenAdapterComplete.
    //
    KeInitializeEvent(&PA->Event, SynchronizationEvent, FALSE);

    //
    // Initialize a mutex used to synchronize attribute retrieval
    // from NDIS.
    //
    ExInitializeFastMutex(&PA->Mutex);

    NdisOpenAdapter(&Status, &ErrorStatus, &PA->Handle,
                    &MediaIndex, MediaArray, sizeof MediaArray / sizeof MediaArray[0],
                    VA->ProtocolHandle, PA, AdapterName,
                    0, NULL);

    //
    // Wait for the open to complete.
    //
    if (Status == NDIS_STATUS_PENDING) {
        (void) KeWaitForSingleObject(&PA->Event, UserRequest, KernelMode,
                                     FALSE, NULL);
        Status = PA->Status;
    }

    //
    // Initialize lock for serializing access to SibInfo. 
    //
    KeInitializeSpinLock(&PA->SibInfoLock);

    if (Status != NDIS_STATUS_SUCCESS) {
        NdisFreeBufferPool(PA->BufferPool);
        NdisFreePacketPool(PA->PacketPool);
        ExFreePool(PA);
        *RetStatus = Status;
        return;
    }

    //
    // Query the maximum frame size.
    // We can only use the adapter if it has a sufficiently large frame,
    // because we need to insert headers.
    //
    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_GEN_MAXIMUM_FRAME_SIZE,
                                   &PA->MaxFrameSize, sizeof PA->MaxFrameSize,
                                   NULL);
    if ((Status != NDIS_STATUS_SUCCESS) ||
        (PA->MaxFrameSize < PROTOCOL_MIN_FRAME_SIZE)) {

        ProtocolCloseAdapter(PA);
        *RetStatus = NDIS_STATUS_FAILURE;
        return;
    }

#if ENABLE_MSRC_SIB_OID
    //
    // Check whether adapter's driver supports OID_MSRC_QUERY_SIB_TABLE.
    //
    {
        uint BytesNeeded = 0;
        Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                       OID_GEN_SUPPORTED_LIST,
                                       NULL, 0,
                                       &BytesNeeded);
        if (Status == NDIS_STATUS_INVALID_LENGTH || Status == NDIS_STATUS_BUFFER_TOO_SHORT) {
            char *Buff = ExAllocatePool(NonPagedPool, BytesNeeded);

            Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                       OID_GEN_SUPPORTED_LIST,
                                       Buff, BytesNeeded,
                                       NULL);
            if (Status != NDIS_STATUS_SUCCESS) {
                KdPrint(("VRR!ProtocolBindAdapter: Query MSRC_OID Status=0x%x\n", Status));
            }
            else {
                //
                // Look for OID_MSRC_QUERY_SIB_TABLE in the list of supported OIDs.
                //
                uint i;
                uint *p = (uint *)Buff;
                //KdPrint(("Adapter OID_GEN_SUPPORTED_LIST follows\n"));
                BytesNeeded >>= 2;
                for (i = 0; i < BytesNeeded; i++) {
                    //KdPrint(("        %08x\n",*p));
                    if (*p == OID_MSRC_QUERY_SIB_TABLE) {
                        VrrKdPrint("    PA supports OID_MSRC_QUERY_SIB_TABLE",NULL,NULL);
                        PA->SupportsQuerySibTable = TRUE;
                    }
                    p++;
                }
            }
            ExFreePool(Buff);
        }
    }
#endif

    //
    // Query the adapter address.
    //
    Status = ProtocolRequestHelper(PA, NdisRequestQueryInformation,
                                   OID_802_3_CURRENT_ADDRESS,
                                   &PA->Address, sizeof PA->Address,
                                   NULL);
    if (Status != NDIS_STATUS_SUCCESS) {

        ProtocolCloseAdapter(PA);
        *RetStatus = NDIS_STATUS_FAILURE;
        return;
    }

    //
    // Initialize from the registry.
    //
    ProtocolInitAdapter(PA);

    //
    // Query the adapter bandwidth and channel,
    // if they were not configured from the registry.
    //
    ProtocolQueryRadioConfiguration(PA);

    //
    // Add the new physical adapter to our list.
    //
    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    PA->Prev = &VA->PhysicalAdapters;
    PA->Next = VA->PhysicalAdapters;
    if (VA->PhysicalAdapters != NULL)
        VA->PhysicalAdapters->Prev = &PA->Next;
    VA->PhysicalAdapters = PA;
    KeReleaseSpinLock(&VA->Lock, OldIrql);

    //
    // Set the receive filter so that we start receiving frames.
    // We want promiscuous mode but not all adapters support it.
    //
    Filter = NDIS_PACKET_TYPE_PROMISCUOUS;
    Status = ProtocolRequestHelper(PA, NdisRequestSetInformation,
                                   OID_GEN_CURRENT_PACKET_FILTER,
                                   &Filter, sizeof Filter, NULL);
    if (Status == NDIS_STATUS_SUCCESS) {
        //
        // We got promiscuous mode.
        //
        PA->Promiscuous = TRUE;
    }
    else {
        VRRASSERT(PA->Promiscuous == FALSE);

        Filter = (NDIS_PACKET_TYPE_BROADCAST |
                  NDIS_PACKET_TYPE_DIRECTED |
                  NDIS_PACKET_TYPE_MULTICAST);
        Status = ProtocolRequestHelper(PA, NdisRequestSetInformation,
                                       OID_GEN_CURRENT_PACKET_FILTER,
                                       &Filter, sizeof Filter, NULL);
        if (Status != NDIS_STATUS_SUCCESS)
            KdPrint(("VRR!ProtocolRequestHelper(PA %p, PF) -> %x\n",
                     PA, Status));
    }


    //
    // If this is the first physical adapter, indicate that
    // that our miniport is now connected.
    //
    if (PA->Next == NULL)
        MiniportIndicateStatusConnected(VA);

    *RetStatus = NDIS_STATUS_SUCCESS;
}

//* ProtocolUnbindAdapter
//
//  Called by NDIS when we need to unbind from an adapter.
//
void
ProtocolUnbindAdapter(
    PNDIS_STATUS RetStatus,       // Where to return status from this call.
    NDIS_HANDLE Handle,           // Context we gave NDIS earlier.
    NDIS_HANDLE UnbindContext)    // Context for completing this request.
{
    ProtocolAdapter *PA = (ProtocolAdapter *)Handle;
    MiniportAdapter *VA = PA->VirtualAdapter;
    KIRQL OldIrql;

    UNREFERENCED_PARAMETER(UnbindContext);

    KdPrint(("VRR!ProtocolUnbindAdapter(VA %p PA %p)\n", VA, PA));

    //
    // Remove the adapter from our list.
    //
    KeAcquireSpinLock(&VA->Lock, &OldIrql);
    if (PA->Next != NULL)
        PA->Next->Prev = PA->Prev;
    *PA->Prev = PA->Next;
    KeReleaseSpinLock(&VA->Lock, OldIrql);

    //
    // If this was the last physical adapter, indicate that
    // our miniport is no longer connected to a physical adapter.
    //
    // NB: We have a race with ProtocolBindAdapter and could
    // indicate disconnected after it indicates connected.
    //
    if (VA->PhysicalAdapters == NULL)
        MiniportIndicateStatusDisconnected(VA);

    ProtocolCloseAdapter(PA);
    *RetStatus = NDIS_STATUS_SUCCESS;
}

//* ProtocolPnPEvent
//
//  Called by NDIS for plug'n'play and power-management events.
//
//  Called in a thread context, not at DPC level.
//
NDIS_STATUS
ProtocolPnPEvent(
    NDIS_HANDLE Handle,   // Binding handle.
    PNET_PNP_EVENT NetPnPEvent)
{
    static char *NetEvents[] = {
        "set power",
        "query power",
        "query remove",
        "cancel remove",
        "reconfigure",
        "bind list",
        "binds complete",
        "pnp capabilities",
    };
    ProtocolAdapter *PA = (ProtocolAdapter *)Handle;

    KdPrint(("VRR!ProtocolPnPEvent(PA %p Event %s)\n", PA,
             (NetPnPEvent->NetEvent < sizeof NetEvents / sizeof NetEvents[0]) ?
             NetEvents[NetPnPEvent->NetEvent] : "unknown"));

    if (NetPnPEvent->NetEvent == NetEventSetPower) {
        NET_DEVICE_POWER_STATE PowerState;

        //
        // Get the power state of the interface.
        //
        VRRASSERT(NetPnPEvent->BufferLength >= sizeof PowerState);
        PowerState = * (NET_DEVICE_POWER_STATE *) NetPnPEvent->Buffer;

        if (PowerState == NetDeviceStateD0) {
            //
            // The device woke up.
            //
            ProtocolQueryRadioConfiguration(PA);
        }
    }

    return NDIS_STATUS_SUCCESS;
}

//* ProtocolInit
//
//  Registers an VRR transport with NDIS.
//
NDIS_STATUS
ProtocolInit(
    IN const WCHAR *Name,
    IN MiniportAdapter *VA)
{
    NDIS_PROTOCOL_CHARACTERISTICS PC;
    NDIS_STATUS Status;

    RtlZeroMemory(&PC, sizeof PC);
    RtlInitUnicodeString(&PC.Name, Name);
    PC.MajorNdisVersion = NDIS_PROTOCOL_MAJOR_VERSION;
    PC.MinorNdisVersion = NDIS_PROTOCOL_MINOR_VERSION;
    PC.OpenAdapterCompleteHandler = ProtocolOpenAdapterComplete;
    PC.CloseAdapterCompleteHandler = ProtocolCloseAdapterComplete;
    PC.SendCompleteHandler = ProtocolTransmitComplete;
    PC.TransferDataCompleteHandler = ProtocolTransferDataComplete;
    PC.ResetCompleteHandler = ProtocolResetComplete;
    PC.RequestCompleteHandler = ProtocolRequestComplete;
    PC.ReceiveHandler = ProtocolReceive;
    PC.ReceiveCompleteHandler = ProtocolReceiveComplete;
    PC.StatusHandler = ProtocolStatus;
    PC.StatusCompleteHandler = ProtocolStatusComplete;
    PC.ReceivePacketHandler = ProtocolReceivePacket;
    PC.BindAdapterHandler = ProtocolBindAdapter;
    PC.UnbindAdapterHandler = ProtocolUnbindAdapter;
    PC.PnPEventHandler = ProtocolPnPEvent;

    NdisRegisterProtocol(&Status, &VA->ProtocolHandle, &PC, sizeof PC);
    KdPrint(("VRR!NdisRegisterProtocol(VA %p) -> %x\n", VA, Status));
    if (Status != NDIS_STATUS_SUCCESS)
        return Status;

    //
    // Modify the NDIS protocol structure to point
    // to our MiniportAdapter structure. We need this because
    // ProtocolBindAdapter does not supply us with a context.
    //
    *NdisReservedFieldInProtocol(VA->ProtocolHandle) = VA;

    return NDIS_STATUS_SUCCESS;
}

//* ProtocolCleanup
//
//  Uninitializes an VRR transport module.
//  Closes any remaining adapters.
//
void
ProtocolCleanup(MiniportAdapter *VA)
{
    NDIS_STATUS Status;

    //
    // NDIS will call ProtocolUnbindAdapter for each adapter,
    // so we are left with no physical adapters.
    //
    NdisDeregisterProtocol(&Status, VA->ProtocolHandle);
    KdPrint(("VRR!NdisDeregisterProtocol(VA %p) -> %x\n", VA, Status));
    VRRASSERT(VA->PhysicalAdapters == NULL);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -