📄 ndisbind.c
字号:
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;
NDIS_MEDIUM MediumArray[1] = {NdisMedium802_3};
UINT SelectedMediumIndex;
PNDISPROT_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
{
//
// Check if we already have a binding to this device.
//
pTmpOpenContext = ndisprotLookupDevice(pBindingInfo, BindingInfoLength);
if (pTmpOpenContext != NULL)
{
DEBUGP(DL_WARN,
("CreateBinding: Binding to device %ws already exists on open %p\n",
pTmpOpenContext->DeviceName.Buffer, pTmpOpenContext));
NPROT_DEREF_OPEN(pTmpOpenContext); // temp ref added by Lookup
Status = NDIS_STATUS_FAILURE;
break;
}
NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
//
// Check if this open context is already bound/binding/closing.
//
if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_IDLE) ||
NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED))
{
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
Status = NDIS_STATUS_NOT_ACCEPTED;
//
// Make sure we don't abort this binding on failure cleanup.
//
fDoNotDisturb = TRUE;
break;
}
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING);
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
//
// Copy in the device name. Add room for a NULL terminator.
//
NPROT_ALLOC_MEM(pOpenContext->DeviceName.Buffer, BindingInfoLength + sizeof(WCHAR));
if (pOpenContext->DeviceName.Buffer == NULL)
{
DEBUGP(DL_WARN, ("CreateBinding: failed to alloc device name buf (%d bytes)\n",
BindingInfoLength + sizeof(WCHAR)));
Status = NDIS_STATUS_RESOURCES;
break;
}
NPROT_COPY_MEM(pOpenContext->DeviceName.Buffer, pBindingInfo, BindingInfoLength);
*(PWCHAR)((PUCHAR)pOpenContext->DeviceName.Buffer + BindingInfoLength) = L'\0';
NdisInitUnicodeString(&pOpenContext->DeviceName, pOpenContext->DeviceName.Buffer);
//
// Allocate packet pools.
//
NdisAllocatePacketPoolEx(
&Status,
&pOpenContext->SendPacketPool,
MIN_SEND_PACKET_POOL_SIZE,
MAX_SEND_PACKET_POOL_SIZE - MIN_SEND_PACKET_POOL_SIZE,
sizeof(NPROT_SEND_PACKET_RSVD));
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
" send packet pool: %x\n", Status));
break;
}
NdisAllocatePacketPoolEx(
&Status,
&pOpenContext->RecvPacketPool,
MIN_RECV_PACKET_POOL_SIZE,
MAX_RECV_PACKET_POOL_SIZE - MIN_RECV_PACKET_POOL_SIZE,
sizeof(NPROT_RECV_PACKET_RSVD));
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
" recv packet pool: %x\n", Status));
break;
}
//
// Buffer pool for receives.
//
NdisAllocateBufferPool(
&Status,
&pOpenContext->RecvBufferPool,
MAX_RECV_PACKET_POOL_SIZE);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
" recv buffer pool: %x\n", Status));
break;
}
//
// If we are running on Win9X, allocate a buffer pool for sends
// as well, since we can't simply cast MDLs to NDIS_BUFFERs.
//
if (pOpenContext->bRunningOnWin9x)
{
NdisAllocateBufferPool(
&Status,
&pOpenContext->SendBufferPool,
MAX_SEND_PACKET_POOL_SIZE);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
" send buffer pool: %x\n", Status));
break;
}
}
//
// Assume that the device is powered up.
//
pOpenContext->PowerState = NetDeviceStateD0;
//
// Open the adapter.
//
NPROT_INIT_EVENT(&pOpenContext->BindEvent);
NdisOpenAdapter(
&Status,
&OpenErrorCode,
&pOpenContext->BindingHandle,
&SelectedMediumIndex,
&MediumArray[0],
sizeof(MediumArray) / sizeof(NDIS_MEDIUM),
Globals.NdisProtocolHandle,
(NDIS_HANDLE)pOpenContext,
&pOpenContext->DeviceName,
0,
NULL);
if (Status == NDIS_STATUS_PENDING)
{
NPROT_WAIT_EVENT(&pOpenContext->BindEvent, 0);
Status = pOpenContext->BindStatus;
}
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: NdisOpenAdapter (%ws) failed: %x\n",
pOpenContext->DeviceName.Buffer, Status));
break;
}
//
// Note down the fact that we have successfully bound.
// We don't update the state on the open just yet - this
// is to prevent other threads from shutting down the binding.
//
fOpenComplete = TRUE;
//
// Get the friendly name for the adapter. It is not fatal for this
// to fail.
//
(VOID)NdisQueryAdapterInstanceName(
&pOpenContext->DeviceDescr,
pOpenContext->BindingHandle
);
//
// Get Current address
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestQueryInformation,
OID_802_3_CURRENT_ADDRESS,
&pOpenContext->CurrentAddress[0],
NPROT_MAC_ADDR_LEN,
&BytesProcessed
);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: qry current address failed: %x\n",
Status));
break;
}
//
// Get MAC options.
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestQueryInformation,
OID_GEN_MAC_OPTIONS,
&pOpenContext->MacOptions,
sizeof(pOpenContext->MacOptions),
&BytesProcessed
);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: qry MAC options failed: %x\n",
Status));
break;
}
//
// Get the max frame size.
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestQueryInformation,
OID_GEN_MAXIMUM_FRAME_SIZE,
&pOpenContext->MaxFrameSize,
sizeof(pOpenContext->MaxFrameSize),
&BytesProcessed
);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: qry max frame failed: %x\n",
Status));
break;
}
//
// Get the media connect status.
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestQueryInformation,
OID_GEN_MEDIA_CONNECT_STATUS,
&GenericUlong,
sizeof(GenericUlong),
&BytesProcessed
);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("CreateBinding: qry media connect status failed: %x\n",
Status));
break;
}
if (GenericUlong == NdisMediaStateConnected)
{
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_MEDIA_FLAGS, NUIOO_MEDIA_CONNECTED);
}
else
{
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_MEDIA_FLAGS, NUIOO_MEDIA_DISCONNECTED);
}
//
// Mark this open. Also check if we received an Unbind while
// we were setting this up.
//
NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE);
//
// Did an unbind happen in the meantime?
//
if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED))
{
Status = NDIS_STATUS_FAILURE;
}
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
}
while (FALSE);
if ((Status != NDIS_STATUS_SUCCESS) && !fDoNotDisturb)
{
NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
//
// Check if we had actually finished opening the adapter.
//
if (fOpenComplete)
{
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE);
}
else if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING))
{
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_FAILED);
}
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
ndisprotShutdownBinding(pOpenContext);
}
DEBUGP(DL_INFO, ("CreateBinding: OpenContext %p, Status %x\n",
pOpenContext, Status));
return (Status);
}
VOID
ndisprotShutdownBinding(
IN PNDISPROT_OPEN_CONTEXT pOpenContext
)
/*++
Routine Description:
Utility function to shut down the NDIS binding, if one exists, on
the specified open. This is written to be called from:
ndisprotCreateBinding - on failure
NdisProtUnbindAdapter
We handle the case where a binding is in the process of being set up.
This precaution is not needed if this routine is only called from
the context of our UnbindAdapter handler, but they are here in case
we initiate unbinding from elsewhere (e.g. on processing a user command).
NOTE: this blocks and finishes synchronously.
Arguments:
pOpenContext - pointer to open context block
Return Value:
None
--*/
{
NDIS_STATUS Status;
BOOLEAN DoCloseBinding = FALSE;
do
{
NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING))
{
//
// We are still in the process of setting up this binding.
//
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
break;
}
if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
{
NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_CLOSING);
DoCloseBinding = TRUE;
}
NPROT_RELEASE_LOCK(&pOpenContext->Lock);
if (DoCloseBinding)
{
ULONG PacketFilter = 0;
ULONG BytesRead = 0;
//
// Set Packet filter to 0 before closing the binding
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestSetInformation,
OID_GEN_CURRENT_PACKET_FILTER,
&PacketFilter,
sizeof(PacketFilter),
&BytesRead);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("ShutDownBinding: set packet filter failed: %x\n", Status));
}
//
// Set multicast list to null before closing the binding
//
Status = ndisprotDoRequest(
pOpenContext,
NdisRequestSetInformation,
OID_802_3_MULTICAST_LIST,
NULL,
0,
&BytesRead);
if (Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(DL_WARN, ("ShutDownBinding: set multicast list failed: %x\n", Status));
}
//
// Cancel pending control irp for status indication.
//
ndisServiceIndicateStatusIrp(pOpenContext,
0,
NULL,
0,
TRUE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -