📄 ndisbind.c
字号:
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
ndisbind.c
Abstract:
NDIS protocol entry points and utility routines to handle binding
and unbinding from adapters.
Environment:
Kernel mode only.
Revision History:
arvindm 4/5/2000 Created
--*/
#include "precomp.h"
#define __FILENUMBER 'DNIB'
VOID
NdisuioBindAdapter(
OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING pDeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
/*++
Routine Description:
Protocol Bind Handler entry point called when NDIS wants us
to bind to an adapter. We go ahead and set up a binding.
An OPEN_CONTEXT structure is allocated to keep state about
this binding.
Arguments:
pStatus - place to return bind status
BindContext - handle to use with NdisCompleteBindAdapter
DeviceName - adapter to bind to
SystemSpecific1 - used to access protocol-specific registry
key for this binding
SystemSpecific2 - unused
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
NDIS_STATUS Status, ConfigStatus;
NDIS_HANDLE ConfigHandle;
do
{
//
// Allocate our context for this open.
//
NUIO_ALLOC_MEM(pOpenContext, sizeof(NDISUIO_OPEN_CONTEXT));
if (pOpenContext == NULL)
{
Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Initialize it.
//
NUIO_ZERO_MEM(pOpenContext, sizeof(NDISUIO_OPEN_CONTEXT));
NUIO_SET_SIGNATURE(pOpenContext, oc);
NUIO_INIT_LOCK(&pOpenContext->Lock);
NUIO_INIT_LIST_HEAD(&pOpenContext->PendedReads);
NUIO_INIT_LIST_HEAD(&pOpenContext->PendedWrites);
NUIO_INIT_LIST_HEAD(&pOpenContext->RecvPktQueue);
NUIO_INIT_EVENT(&pOpenContext->PoweredUpEvent);
//
// Start off by assuming that the device below is powered up.
//
NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
//
// Determine the platform we are running on.
//
pOpenContext->bRunningOnWin9x = TRUE;
NdisOpenProtocolConfiguration(
&ConfigStatus,
&ConfigHandle,
(PNDIS_STRING)SystemSpecific1);
if (ConfigStatus == NDIS_STATUS_SUCCESS)
{
PNDIS_CONFIGURATION_PARAMETER pParameter;
NDIS_STRING VersionKey = NDIS_STRING_CONST("Environment");
NdisReadConfiguration(
&ConfigStatus,
&pParameter,
ConfigHandle,
&VersionKey,
NdisParameterInteger);
if ((ConfigStatus == NDIS_STATUS_SUCCESS) &&
((pParameter->ParameterType == NdisParameterInteger) ||
(pParameter->ParameterType == NdisParameterHexInteger)))
{
pOpenContext->bRunningOnWin9x =
(pParameter->ParameterData.IntegerData == NdisEnvironmentWindows);
}
NdisCloseConfiguration(ConfigHandle);
}
NUIO_REF_OPEN(pOpenContext); // Bind
//
// Add it to the global list.
//
NUIO_ACQUIRE_LOCK(&Globals.GlobalLock);
NUIO_INSERT_TAIL_LIST(&Globals.OpenList,
&pOpenContext->Link);
NUIO_RELEASE_LOCK(&Globals.GlobalLock);
//
// Set up the NDIS binding.
//
Status = ndisuioCreateBinding(
pOpenContext,
(PUCHAR)pDeviceName->Buffer,
pDeviceName->Length);
if (Status != NDIS_STATUS_SUCCESS)
{
break;
}
}
while (FALSE);
*pStatus = Status;
return;
}
VOID
NdisuioOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorCode
)
/*++
Routine Description:
Completion routine called by NDIS if our call to NdisOpenAdapter
pends. Wake up the thread that called NdisOpenAdapter.
Arguments:
ProtocolBindingContext - pointer to open context structure
Status - status of the open
OpenErrorCode - if unsuccessful, additional information
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
pOpenContext->BindStatus = Status;
NUIO_SIGNAL_EVENT(&pOpenContext->BindEvent);
}
VOID
NdisuioUnbindAdapter(
OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
/*++
Routine Description:
NDIS calls this when it wants us to close the binding to an adapter.
Arguments:
pStatus - place to return status of Unbind
ProtocolBindingContext - pointer to open context structure
UnbindContext - to use in NdisCompleteUnbindAdapter if we return pending
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
//
// Mark this open as having seen an Unbind.
//
NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
NUIO_SET_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED);
//
// In case we had threads blocked for the device below to be powered
// up, wake them up.
//
NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
NUIO_RELEASE_LOCK(&pOpenContext->Lock);
ndisuioShutdownBinding(pOpenContext);
*pStatus = NDIS_STATUS_SUCCESS;
return;
}
VOID
NdisuioCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Called by NDIS to complete a pended call to NdisCloseAdapter.
We wake up the thread waiting for this completion.
Arguments:
ProtocolBindingContext - pointer to open context structure
Status - Completion status of NdisCloseAdapter
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
pOpenContext->BindStatus = Status;
NUIO_SIGNAL_EVENT(&pOpenContext->BindEvent);
}
NDIS_STATUS
NdisuioPnPEventHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Called by NDIS to notify us of a PNP event. The most significant
one for us is power state change.
Arguments:
ProtocolBindingContext - pointer to open context structure
this is NULL for global reconfig events.
pNetPnPEvent - pointer to the PNP event
Return Value:
Our processing status for the PNP event.
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
NDIS_STATUS Status;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
switch (pNetPnPEvent->NetEvent)
{
case NetEventSetPower:
NUIO_STRUCT_ASSERT(pOpenContext, oc);
pOpenContext->PowerState = *(PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
if (pOpenContext->PowerState > NetDeviceStateD0)
{
//
// The device below is transitioning to a low power state.
// Block any threads attempting to query the device while
// in this state.
//
NUIO_INIT_EVENT(&pOpenContext->PoweredUpEvent);
//
// Wait for any I/O in progress to complete.
//
ndisuioWaitForPendingIO(pOpenContext, FALSE);
//
// Return any receives that we had queued up.
//
ndisuioFlushReceiveQueue(pOpenContext);
DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower to %d\n",
pOpenContext, pOpenContext->PowerState));
}
else
{
//
// The device below is powered up.
//
DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower ON: %d\n",
pOpenContext, pOpenContext->PowerState));
NUIO_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
}
Status = NDIS_STATUS_SUCCESS;
break;
case NetEventQueryPower:
Status = NDIS_STATUS_SUCCESS;
break;
case NetEventBindsComplete:
NUIO_SIGNAL_EVENT(&Globals.BindsComplete);
Status = NDIS_STATUS_SUCCESS;
break;
case NetEventQueryRemoveDevice:
case NetEventCancelRemoveDevice:
case NetEventReconfigure:
case NetEventBindList:
case NetEventPnPCapabilities:
Status = NDIS_STATUS_SUCCESS;
break;
default:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
DEBUGP(DL_INFO, ("PnPEvent: Open %p, Event %d, Status %x\n",
pOpenContext, pNetPnPEvent->NetEvent, Status));
return (Status);
}
VOID
NdisuioProtocolUnloadHandler(
VOID
)
/*++
Routine Description:
NDIS calls this on a usermode request to uninstall us.
Arguments:
None
Return Value:
None
--*/
{
ndisuioDoProtocolUnload();
}
NDIS_STATUS
ndisuioCreateBinding(
IN PNDISUIO_OPEN_CONTEXT pOpenContext,
IN PUCHAR pBindingInfo,
IN ULONG BindingInfoLength
)
/*++
Routine Description:
Utility function to create an NDIS binding to the indicated device,
if no such binding exists.
Here is where we also allocate additional resources (e.g. packet pool)
for the binding.
Things to take care of:
1. Is another thread doing this (or has finished binding) already?
2. Is the binding being closed at this time?
3. NDIS calls our Unbind handler while we are doing this.
These precautions are not needed if this routine is only called from
the context of our BindAdapter handler, but they are here in case
we initiate binding from elsewhere (e.g. on processing a user command).
NOTE: this function blocks and finishes synchronously.
Arguments:
pOpenContext - pointer to open context block
pBindingInfo - pointer to unicode device name string
BindingInfoLength - length in bytes of the above.
Return Value:
NDIS_STATUS_SUCCESS if a binding was successfully set up.
NDIS_STATUS_XXX error code on any failure.
--*/
{
NDIS_STATUS Status;
NDIS_STATUS OpenErrorCode;
UNICODE_STRING DeviceName;
PLIST_ENTRY pEnt;
NDIS_MEDIUM MediumArray[1] = {NdisMedium802_3};
UINT SelectedMediumIndex;
PNDISUIO_OPEN_CONTEXT pTmpOpenContext;
BOOLEAN fDoNotDisturb = FALSE;
BOOLEAN fOpenComplete = FALSE;
ULONG BytesProcessed;
ULONG GenericUlong = 0;
DEBUGP(DL_LOUD, ("CreateBinding: open %p/%x, device [%ws]\n",
pOpenContext, pOpenContext->Flags, pBindingInfo));
Status = NDIS_STATUS_SUCCESS;
do
{
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -