📄 protocol.c
字号:
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 + -