📄 io.c
字号:
//
// Open our configuration information in the registry.
//
Status = IoOpenDeviceRegistryKey(VA->PhysicalDeviceObject,
PLUGPLAY_REGKEY_DRIVER,
GENERIC_READ,
&KeyHandle);
if (! NT_SUCCESS(Status)) {
KdPrint(("IoCmd: IoOpenDeviceRegistryKey()=%x\n", Status));
ExecResult = VRR_COMMAND_ERROR;
} else {
VirtualAddress Address;
//
// Clear the individual/group bit and
// the local/universal bit:
//
RtlCopyMemory(Address,&Command->ArgAddress,sizeof(VirtualAddress));
IEEE_802_ADDR_CLEAR_GROUP(Address);
IEEE_802_ADDR_CLEAR_LOCAL(Address);
//
// Write the new address to the registry.
//
Status = SetRegNetworkAddress(KeyHandle, L"NetworkAddress", Address);
if (! NT_SUCCESS(Status)) {
KdPrint(("IoCmd: SetRegNetworkAddress()=%x\n", Status));
ExecResult = VRR_COMMAND_ERROR;
}
else {
ExecResult = VRR_COMMAND_SUCCESS;
Status = STATUS_SUCCESS;
}
}
ZwClose(KeyHandle);
}
else if (Command->OpCode == VRR_COMMAND_ATHMSRC) {
ProtocolAdapter *PA;
ProtocolAdapter *AthMsrcPA[MAX_ATHMSRC_PA] = {NULL, NULL};
uint CountPA = 0;
uint i;
MSRC_OID_Command AthCommand;
AthCommand.OpCode = Command->Arg1;
AthCommand.Arg = Command->Arg2;
RtlCopyMemory(&AthCommand.MACAddr,Command->ArgAddress,sizeof(VirtualAddress));
//
// Find PA that SupportsQuerySibTable.
// We are only interested in the first MAX_ATHMSRC_PA of these.
//
KeAcquireSpinLock(&VA->Lock, &OldIrql);
for (PA = VA->PhysicalAdapters; PA != NULL && CountPA < MAX_ATHMSRC_PA; PA = PA->Next)
if (PA->SupportsQuerySibTable == TRUE)
AthMsrcPA[CountPA++] = PA;
KeReleaseSpinLock(&VA->Lock, OldIrql);
//
// Send command to each of the chosen PA.
//
ExecResult = VRR_COMMAND_SUCCESS;
for (i = 0; i < CountPA; i++) {
Status = ProtocolRequestHelper(AthMsrcPA[i],
NdisRequestSetInformation,
OID_MSRC_COMMAND,
&AthCommand, sizeof(AthCommand),
NULL);
PrintfNdisStatus(__FUNCTION__ " ExecCmd(OID_MSRC_COMMAND):",Status,FALSE);
if (Status != NDIS_STATUS_SUCCESS)
ExecResult = VRR_COMMAND_ERROR;
}
}
else if (Command->OpCode == VRR_COMMAND_SEND_PROBE) {
NeighborCacheEntry *NCE;
ProtocolAdapter *PA;
NDIS_PACKET *Probe = NULL;
ExecResult = VRR_COMMAND_SUCCESS;
KeAcquireSpinLock(&VA->NC.Lock, &OldIrql);
if ((NCE=FindNCE(&VA->NC,Command->ArgAddress,
VRR_IFID_UNSPECIFIED,
VRR_IFID_UNSPECIFIED,
VRR_NCE_STATE_ANY)) == NULL) {
ExecResult = VRR_COMMAND_BAD_ARG;
}
else if ((NCE->Flags & VRR_NCE_FLAG_SIB_OID) == 0) {
ExecResult = VRR_COMMAND_ERROR;
}
else if ((PA=FindPhysicalAdapterFromIndex(VA,NCE->LocIF)) == NULL) {
ExecResult = VRR_COMMAND_ERROR;
}
else if (PktPairCreateProbePacket(VA,&NCE->AdjOut,0,&Probe,0,TRUE,
METRIC_TYPE_INVALID) != NDIS_STATUS_SUCCESS) {
ExecResult = VRR_COMMAND_ERROR;
}
KeReleaseSpinLock(&VA->NC.Lock, OldIrql);
if (ExecResult == VRR_COMMAND_SUCCESS && Probe != NULL) {
if (PC(Probe)->PA == NULL)
PktPairSendProbeComplete(VA, Probe, NDIS_STATUS_FAILURE);
else
ProtocolTransmit(PC(Probe)->PA, Probe);
}
}
else if (Command->OpCode == VRR_COMMAND_INIT_EVSET) {
if (VA->JoiningOnHold == 0)
ExecResult = VRR_COMMAND_ERROR; // Too late.
else if (Command->Arg1 < VRR_MAX_VSET_SIZE) {
RtlCopyMemory(VA->ExpectedVSet[Command->Arg1],Command->ArgAddress,sizeof(VirtualAddress));
VA->AddErrorVSet[Command->Arg1] = 0;
ExecResult = VRR_COMMAND_SUCCESS;
VA->TestExpectedVSet = TRUE;
}
}
else if (Command->OpCode == VRR_COMMAND_SR_DIRECT) {
ProbeListEntry *PLE;
VirtualAddress *Target;
if (Command->Arg1 > 2) {
VrrKdPrint("IoCmd: illegal arg n>2 to VRR_COMMAND_SR_DIRECT", NULL, NULL);
Status = STATUS_INVALID_PARAMETER_1;
goto Return;
}
if (IsUnspecified(Command->ArgAddress)) {
VrrKdPrint("IoCmd: reject unspecified address as SR VA->Address", NULL, NULL);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
if (IsIEEEGroupAddress(Command->ArgAddress)) {
VrrKdPrint("IoCmd: reject broadcast address as SR VA->Address", NULL, NULL);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
if (Command->Arg1 == 0)
Target = &Command->ArgAddress;
else if (Command->Arg1 == 1)
Target = &VA->AddressDec;
else if (Command->Arg1 == 2)
Target = &VA->AddressInc;
KeAcquireSpinLock(&VA->NT.Lock, &OldIrql);
if (FindPLE(&VA->PL,*Target) == NULL)
if ((PLE=FindOrCreatePLE(VA,*Target))!=NULL) {
VrrTrace(VA,2,"IoCmd=SendSR",NULL,NULL,*Target,NULL,0,"Arg1",Command->Arg1);
if (Command->Arg1 == 1) {
PLE->SRDirection = VRR_SR_DIRECT_LHS;
InterlockedIncrement(&VA->CountGenSRleft);
}
else if (Command->Arg1 == 2) {
PLE->SRDirection = VRR_SR_DIRECT_RHS;
InterlockedIncrement(&VA->CountGenSRright);
}
if (PLE->SRDirection != 0)
PLE->SRcAntiRoute = AddressListAdd(NULL,VA->Address);
PLE->Timeout = KeQueryInterruptTime() - 1;
}
KeReleaseSpinLock(&VA->NT.Lock, OldIrql);
ExecResult = VRR_COMMAND_SUCCESS;
}
else if (Command->OpCode == VRR_COMMAND_BC_JITMIN) {
if (Command->Arg2 <= VA->BroadcastJitterMaxMs) {
InterlockedExchange(&VA->BroadcastJitterMinMs, Command->Arg2);
ExecResult = VRR_COMMAND_SUCCESS;
}
else
ExecResult = VRR_COMMAND_BAD_ARG;
}
else if (Command->OpCode == VRR_COMMAND_BC_JITMAX) {
if (Command->Arg2 >= VA->BroadcastJitterMinMs) {
InterlockedExchange(&VA->BroadcastJitterMaxMs, Command->Arg2);
ExecResult = VRR_COMMAND_SUCCESS;
}
else
ExecResult = VRR_COMMAND_BAD_ARG;
}
else if (Command->OpCode == VRR_COMMAND_SEND_BC) {
BroadcastList *BL = &VA->BL;
BroadcastListEntry *BLE;
if (Command->Arg2 > 0 && Command->Arg2 <= VA->MediumMaxFrameLen) {
uchar *Buffer = NULL;
if ((Buffer=ExAllocatePool(NonPagedPool,Command->Arg2)) != NULL) {
VirtualAddress BcastAddress = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
RtlFillMemory(Buffer,Command->Arg2,'V');
UpdateBroadcastList(VA,VA->Address,
InterlockedIncrement(&VrrGlobal.NextFrameSeqNo),
0,VA->Address,BcastAddress,
TRUE,Buffer,Command->Arg2);
ExFreePool(Buffer);
ExecResult = VRR_COMMAND_SUCCESS;
}
}
else {
ExecResult = VRR_COMMAND_BAD_ARG;
}
}
else {
ExecResult = ExecCommand(VA,Command->OpCode,Command->Arg1);
}
if (ExecResult == VRR_COMMAND_SUCCESS)
Status = STATUS_SUCCESS;
else if (ExecResult == VRR_COMMAND_BAD_OPCODE)
Status = STATUS_INVALID_PARAMETER_2;
else if (ExecResult == VRR_COMMAND_BAD_ARG)
Status = STATUS_INVALID_PARAMETER_3;
else if (ExecResult == VRR_COMMAND_ERROR)
Status = STATUS_UNSUCCESSFUL;
else if (ExecResult == VRR_COMMAND_NOT_READY)
Status = STATUS_DEVICE_OFF_LINE;
Return:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
//* IoVrrGlobalState
//
// Dump struct VrrGlobalState to user.
//
NTSTATUS
IoVrrGlobalState(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
VrrGlobalState *GlobalIn;
VrrGlobalState *GlobalOut;
NTSTATUS Status;
PAGED_CODE();
Irp->IoStatus.Information = 0;
if (IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof *GlobalOut ||
IrpSp->Parameters.DeviceIoControl.OutputBufferLength != sizeof *GlobalOut) {
Status = STATUS_INVALID_PARAMETER;
goto Return;
}
//
// Note that the Query and Info->Query structures overlap!
//
GlobalIn = (VrrGlobalState *) Irp->AssociatedIrp.SystemBuffer;
GlobalOut = (VrrGlobalState *) Irp->AssociatedIrp.SystemBuffer;
RtlCopyMemory(GlobalOut, &VrrGlobal, sizeof *GlobalOut);
Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof *GlobalOut;
Return:
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
//* IoQueryTearDownCacheEntry
//
// Handles queries for information about a node table entry.
//
NTSTATUS
IoQueryTearDownCacheEntry(
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpSp)
{
VRR_QUERY_TDOWN_CACHE_ENTRY *Query;
VRR_INFO_TDOWN_CACHE_ENTRY *Info;
MiniportAdapter *VA = NULL;
TearDownCacheEntry *TDCE;
KIRQL OldIrql;
NTSTATUS Status;
PAGED_CODE();
Irp->IoStatus.Information = 0;
if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength != sizeof *Query) ||
(IrpSp->Parameters.DeviceIoControl.OutputBufferLength < sizeof *Info)) {
Status = STATUS_INVALID_PARAMETER;
goto Return;
}
//
// Note that the Query and Info->Query structures overlap!
//
Query = (VRR_QUERY_TDOWN_CACHE_ENTRY *) Irp->AssociatedIrp.SystemBuffer;
Info = (VRR_INFO_TDOWN_CACHE_ENTRY *) Irp->AssociatedIrp.SystemBuffer;
//
// Return information about the specified virtual adapter.
//
VA = FindVirtualAdapterFromQuery(&Query->VA);
if (VA == NULL) {
Status = STATUS_INVALID_PARAMETER_1;
goto Return;
}
if (IsUnspecified(Query->Address)) {
//
// Return the address and PathId of the first TDCE.
//
KeAcquireSpinLock(&VA->TDC.Lock, &OldIrql);
if (VA->TDC.FirstTDCE != SentinelTDCE(&VA->TDC)) {
RtlCopyMemory(Info->Query.Address,
VA->TDC.FirstTDCE->Address,
sizeof(VirtualAddress));
Info->Query.PathId = VA->TDC.FirstTDCE->PathId;
RtlCopyMemory(Info->Query.ReportedBy,
VA->TDC.FirstTDCE->ReportedBy,
sizeof(VirtualAddress));
// Ensure enough here to uniquely identify the entry.
}
KeReleaseSpinLock(&VA->TDC.Lock, OldIrql);
Irp->IoStatus.Information = sizeof Info->Query;
}
else {
//
// Find the specified TDCE.
//
KeAcquireSpinLock(&VA->TDC.Lock, &OldIrql);
for (TDCE = VA->TDC.FirstTDCE; ; TDCE = TDCE->Next) {
if (TDCE == SentinelTDCE(&VA->TDC)) {
KeReleaseSpinLock(&VA->TDC.Lock, OldIrql);
Status = STATUS_INVALID_PARAMETER_2;
goto Return;
}
if (VirtualAddressEqual(Query->Address, TDCE->Address))
if (Query->PathId == TDCE->PathId)
if (VirtualAddressEqual(Query->ReportedBy, TDCE->ReportedBy))
break;
}
//
// Return miscellaneous information about the TDCE.
//
RtlCopyMemory(Info->Address, TDCE->Address, sizeof(VirtualAddress));
Info->PathId = TDCE->PathId;
Info->Timeout = TIMEOUT_TO_MS(TDCE->Timeout);
RtlCopyMemory(Info->ReportedBy, TDCE->ReportedBy, sizeof(VirtualAddress));
//
// Return address of the next TDCE (or zero).
// Again, ensure enough for uniqueness of next query.
//
if (TDCE->Next == SentinelTDCE(&VA->TDC)) {
RtlZeroMemory(Info->Query.Address, sizeof(VirtualAddress));
}
else {
RtlCopyMemory(Info->Query.Address,
TDCE->Next->Address,
sizeof(VirtualAddress));
Info->Query.PathId = TDCE->Next->PathId;
RtlCopyMemory(Info->Query.ReportedBy,
TDCE->Next->ReportedBy,
sizeof(VirtualAddress));
}
KeReleaseSpinLock(&VA->TDC.Lock, OldIrql);
Irp->IoStatus.Information = sizeof *Info;
}
Status = STATUS_SUCCESS;
Return:
#if 0
if (VA != NULL)
ReleaseVA(VA);
#endif
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, I
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -