📄 ndisbind.c
字号:
NUIO_FREE_MEM(pOpenContext->DeviceName.Buffer);
pOpenContext->DeviceName.Buffer = NULL;
pOpenContext->DeviceName.Length =
pOpenContext->DeviceName.MaximumLength = 0;
}
if (pOpenContext->DeviceDescr.Buffer != NULL)
{
//
// this would have been allocated by NdisQueryAdpaterInstanceName.
//
NdisFreeMemory(pOpenContext->DeviceDescr.Buffer, 0, 0);
pOpenContext->DeviceDescr.Buffer = NULL;
}
}
VOID
ndisuioWaitForPendingIO(
IN PNDISUIO_OPEN_CONTEXT pOpenContext,
IN BOOLEAN DoCancelReads
)
/*++
Routine Description:
Utility function to wait for all outstanding I/O to complete
on an open context. It is assumed that the open context
won't go away while we are in this routine.
Arguments:
pOpenContext - pointer to open context structure
DoCancelReads - do we wait for pending reads to go away (and cancel them)?
Return Value:
None
--*/
{
NDIS_STATUS Status;
ULONG LoopCount;
ULONG PendingCount;
#ifdef NDIS51
//
// Wait for any pending sends or requests on the binding to complete.
//
for (LoopCount = 0; LoopCount < 60; LoopCount++)
{
Status = NdisQueryPendingIOCount(
pOpenContext->BindingHandle,
&PendingCount);
if ((Status != NDIS_STATUS_SUCCESS) ||
(PendingCount == 0))
{
break;
}
DEBUGP(DL_INFO, ("WaitForPendingIO: Open %p, %d pending I/O at NDIS\n",
pOpenContext, PendingCount));
NUIO_SLEEP(2);
}
NUIO_ASSERT(LoopCount < 60);
#endif // NDIS51
//
// Make sure any threads trying to send have finished.
//
for (LoopCount = 0; LoopCount < 60; LoopCount++)
{
if (pOpenContext->PendedSendCount == 0)
{
break;
}
DEBUGP(DL_WARN, ("WaitForPendingIO: Open %p, %d pended sends\n",
pOpenContext, pOpenContext->PendedSendCount));
NUIO_SLEEP(1);
}
NUIO_ASSERT(LoopCount < 60);
if (DoCancelReads)
{
//
// Wait for any pended reads to complete/cancel.
//
while (pOpenContext->PendedReadCount != 0)
{
DEBUGP(DL_INFO, ("WaitForPendingIO: Open %p, %d pended reads\n",
pOpenContext, pOpenContext->PendedReadCount));
//
// Cancel any pending reads.
//
ndisuioCancelPendingReads(pOpenContext);
NUIO_SLEEP(1);
}
}
}
VOID
ndisuioDoProtocolUnload(
VOID
)
/*++
Routine Description:
Utility routine to handle unload from the NDIS protocol side.
Arguments:
None
Return Value:
None
--*/
{
NDIS_HANDLE ProtocolHandle;
NDIS_STATUS Status;
DEBUGP(DL_INFO, ("ProtocolUnload: ProtocolHandle %lx\n",
Globals.NdisProtocolHandle));
if (Globals.NdisProtocolHandle != NULL)
{
ProtocolHandle = Globals.NdisProtocolHandle;
Globals.NdisProtocolHandle = NULL;
NdisDeregisterProtocol(
&Status,
ProtocolHandle
);
}
}
NDIS_STATUS
ndisuioDoRequest(
IN PNDISUIO_OPEN_CONTEXT pOpenContext,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN UINT InformationBufferLength,
OUT PUINT pBytesProcessed
)
/*++
Routine Description:
Utility routine that forms and sends an NDIS_REQUEST to the
miniport, waits for it to complete, and returns status
to the caller.
NOTE: this assumes that the calling routine ensures validity
of the binding handle until this returns.
Arguments:
pOpenContext - pointer to our open context
RequestType - NdisRequest[Set|Query]Information
Oid - the object being set/queried
InformationBuffer - data for the request
InformationBufferLength - length of the above
pBytesProcessed - place to return bytes read/written
Return Value:
Status of the set/query request
--*/
{
NDISUIO_REQUEST ReqContext;
PNDIS_REQUEST pNdisRequest = &ReqContext.Request;
NDIS_STATUS Status;
NUIO_INIT_EVENT(&ReqContext.ReqEvent);
pNdisRequest->RequestType = RequestType;
switch (RequestType)
{
case NdisRequestQueryInformation:
pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
InformationBuffer;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
case NdisRequestSetInformation:
pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer =
InformationBuffer;
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
InformationBufferLength;
break;
default:
NUIO_ASSERT(FALSE);
break;
}
NdisRequest(&Status,
pOpenContext->BindingHandle,
pNdisRequest);
if (Status == NDIS_STATUS_PENDING)
{
NUIO_WAIT_EVENT(&ReqContext.ReqEvent, 0);
Status = ReqContext.Status;
}
if (Status == NDIS_STATUS_SUCCESS)
{
*pBytesProcessed = (RequestType == NdisRequestQueryInformation)?
pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten:
pNdisRequest->DATA.SET_INFORMATION.BytesRead;
}
return (Status);
}
NDIS_STATUS
ndisuioValidateOpenAndDoRequest(
IN PNDISUIO_OPEN_CONTEXT pOpenContext,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID InformationBuffer,
IN UINT InformationBufferLength,
OUT PUINT pBytesProcessed,
IN BOOLEAN bWaitForPowerOn
)
/*++
Routine Description:
Utility routine to prevalidate and reference an open context
before calling ndisuioDoRequest. This routine makes sure
we have a valid binding.
Arguments:
pOpenContext - pointer to our open context
RequestType - NdisRequest[Set|Query]Information
Oid - the object being set/queried
InformationBuffer - data for the request
InformationBufferLength - length of the above
pBytesProcessed - place to return bytes read/written
bWaitForPowerOn - Wait for the device to be powered on if it isn't already.
Return Value:
Status of the set/query request
--*/
{
NDIS_STATUS Status;
do
{
if (pOpenContext == NULL)
{
DEBUGP(DL_WARN, ("ValidateOpenAndDoRequest: request on unassociated file object!\n"));
Status = NDIS_STATUS_INVALID_DATA;
break;
}
NUIO_STRUCT_ASSERT(pOpenContext, oc);
NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
//
// Proceed only if we have a binding.
//
if (!NUIO_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
{
NUIO_RELEASE_LOCK(&pOpenContext->Lock);
Status = NDIS_STATUS_INVALID_DATA;
break;
}
NUIO_ASSERT(pOpenContext->BindingHandle != NULL);
//
// Make sure that the binding does not go away until we
// are finished with the request.
//
NdisInterlockedIncrement(&pOpenContext->PendedSendCount);
NUIO_RELEASE_LOCK(&pOpenContext->Lock);
if (bWaitForPowerOn)
{
//
// Wait for the device below to be powered up.
// We don't wait indefinitely here - this is to avoid
// a PROCESS_HAS_LOCKED_PAGES bugcheck that could happen
// if the calling process terminates, and this IRP doesn't
// complete within a reasonable time. An alternative would
// be to explicitly handle cancellation of this IRP.
//
NUIO_WAIT_EVENT(&pOpenContext->PoweredUpEvent, 4500);
}
Status = ndisuioDoRequest(
pOpenContext,
RequestType,
Oid,
InformationBuffer,
InformationBufferLength,
pBytesProcessed);
//
// Let go of the binding.
//
NdisInterlockedDecrement(&pOpenContext->PendedSendCount);
break;
}
while (FALSE);
DEBUGP(DL_LOUD, ("ValidateOpenAndDoReq: Open %p/%x, OID %x, Status %x\n",
pOpenContext, pOpenContext->Flags, Oid, Status));
return (Status);
}
VOID
NdisuioResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
NDIS entry point indicating that a protocol initiated reset
has completed. Since we never call NdisReset(), this should
never be called.
Arguments:
ProtocolBindingContext - pointer to open context
Status - status of reset completion
Return Value:
None
--*/
{
ASSERT(FALSE);
return;
}
VOID
NdisuioRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST pNdisRequest,
IN NDIS_STATUS Status
)
/*++
Routine Description:
NDIS entry point indicating completion of a pended NDIS_REQUEST.
Arguments:
ProtocolBindingContext - pointer to open context
pNdisRequest - pointer to NDIS request
Status - status of reset completion
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
PNDISUIO_REQUEST pReqContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
//
// Get at the request context.
//
pReqContext = CONTAINING_RECORD(pNdisRequest, NDISUIO_REQUEST, Request);
//
// Save away the completion status.
//
pReqContext->Status = Status;
//
// Wake up the thread blocked for this request to complete.
//
NUIO_SIGNAL_EVENT(&pReqContext->ReqEvent);
}
VOID
NdisuioStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS GeneralStatus,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
/*++
Routine Description:
Protocol entry point called by NDIS to indicate a change
in status at the miniport.
We make note of reset and media connect status indications.
Arguments:
ProtocolBindingContext - pointer to open context
GeneralStatus - status code
StatusBuffer - status-specific additional information
StatusBufferSize - size of the above
Return Value:
None
--*/
{
PNDISUIO_OPEN_CONTEXT pOpenContext;
pOpenContext = (PNDISUIO_OPEN_CONTEXT)ProtocolBindingContext;
NUIO_STRUCT_ASSERT(pOpenContext, oc);
DEBUGP(DL_INFO, ("Status: Open %p, Status %x\n",
pOpenContext, GeneralStatus));
NUIO_ACQUIRE_LOCK(&pOpenContext->Lock);
do
{
if (pOpenContext->PowerState != NetDeviceStateD0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -