Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS NDIS User I/O driver * FILE: protocol.c * PURPOSE: Protocol stuff * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) */
#include "ndisuio.h"
#define NDEBUG#include <debug.h>
VOIDNTAPINduOpenAdapterComplete(NDIS_HANDLE ProtocolBindingContext, NDIS_STATUS Status, NDIS_STATUS OpenStatus){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter open completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
VOIDNTAPINduCloseAdapterComplete(NDIS_HANDLE ProtocolBindingContext, NDIS_STATUS Status){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter close completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
NDIS_STATUSNTAPINduNetPnPEvent(NDIS_HANDLE ProtocolBindingContext, PNET_PNP_EVENT NetPnPEvent){ PNDIS_DEVICE_POWER_STATE PowerState;
DPRINT("NetPnPEvent\n");
switch (NetPnPEvent->NetEvent) { case NetEventQueryRemoveDevice: /* Nothing to do */ DPRINT1("NetPnPEvent: QueryRemoveDevice\n"); return NDIS_STATUS_SUCCESS;
case NetEventSetPower: ASSERT(NetPnPEvent->BufferLength >= sizeof(*PowerState));
PowerState = NetPnPEvent->Buffer; switch (*PowerState) { case NdisDeviceStateD0: DPRINT1("NetPnPEvent: SetPower D0\n"); return NDIS_STATUS_SUCCESS;
default: DPRINT1("NetPnPEvent: SetPower state %d not supported\n", *PowerState); return NDIS_STATUS_FAILURE; }
case NetEventQueryPower: DPRINT1("NetPnPEvent: QueryPower\n"); return NDIS_STATUS_SUCCESS;
case NetEventCancelRemoveDevice: DPRINT1("NetPnPEvent: CancelRemoveDevice\n"); return NDIS_STATUS_SUCCESS;
case NetEventReconfigure: DPRINT1("NetPnPEvent: Reconfigure\n"); return NDIS_STATUS_SUCCESS;
case NetEventBindList: DPRINT1("NetPnPEvent: BindList\n"); return NDIS_STATUS_SUCCESS;
case NetEventBindsComplete: DPRINT("NetPnPEvent: BindsComplete\n"); return NDIS_STATUS_SUCCESS;
case NetEventPnPCapabilities: DPRINT1("NetPnPEvent: PnPCapabilities\n"); return NDIS_STATUS_SUCCESS;
default: DPRINT1("NetPnPEvent unimplemented for net event 0x%x\n", NetPnPEvent->NetEvent); return NDIS_STATUS_FAILURE; }}
VOIDNTAPINduSendComplete(NDIS_HANDLE ProtocolBindingContext, PNDIS_PACKET Packet, NDIS_STATUS Status){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter send completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
VOIDNTAPINduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext, PNDIS_PACKET Packet, NDIS_STATUS Status, UINT BytesTransferred){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter transfer completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
VOIDNTAPINduResetComplete(NDIS_HANDLE ProtocolBindingContext, NDIS_STATUS Status){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter reset completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
VOIDNTAPINduRequestComplete(NDIS_HANDLE ProtocolBindingContext, PNDIS_REQUEST NdisRequest, NDIS_STATUS Status){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext;
DPRINT("Asynchronous adapter request completed\n");
/* Store the final status and signal the event */ AdapterContext->AsyncStatus = Status; KeSetEvent(&AdapterContext->AsyncEvent, IO_NO_INCREMENT, FALSE);}
NDIS_STATUSNTAPINduReceive(NDIS_HANDLE ProtocolBindingContext, NDIS_HANDLE MacReceiveContext, PVOID HeaderBuffer, UINT HeaderBufferSize, PVOID LookAheadBuffer, UINT LookaheadBufferSize, UINT PacketSize){ PNDISUIO_ADAPTER_CONTEXT AdapterContext = ProtocolBindingContext; PNDISUIO_PACKET_ENTRY PacketEntry; PVOID PacketBuffer; PNDIS_PACKET Packet; NDIS_STATUS Status; UINT BytesTransferred;
DPRINT("Received a %d byte packet\n", PacketSize);
/* Discard if nobody is waiting for it */ if (AdapterContext->OpenCount == 0) return NDIS_STATUS_NOT_ACCEPTED;
/* Allocate a buffer to hold the packet data and header */ PacketBuffer = ExAllocatePool(NonPagedPool, PacketSize + HeaderBufferSize); if (!PacketBuffer) return NDIS_STATUS_NOT_ACCEPTED;
/* Allocate the packet descriptor and buffer */ Packet = CreatePacketFromPoolBuffer(AdapterContext, (PUCHAR)PacketBuffer + HeaderBufferSize, PacketSize); if (!Packet) { ExFreePool(PacketBuffer); return NDIS_STATUS_NOT_ACCEPTED; }
/* Transfer the packet data into our data buffer */ if (LookaheadBufferSize == PacketSize) { NdisCopyLookaheadData((PVOID)((PUCHAR)PacketBuffer + HeaderBufferSize), LookAheadBuffer, PacketSize, AdapterContext->MacOptions); BytesTransferred = PacketSize; } else { NdisTransferData(&Status, AdapterContext->BindingHandle, MacReceiveContext, 0, PacketSize, Packet, &BytesTransferred); if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; } if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to transfer data with status 0x%x\n", Status); CleanupAndFreePacket(Packet, FALSE); ExFreePool(PacketBuffer); return NDIS_STATUS_NOT_ACCEPTED; } }
/* Copy the header data */ RtlCopyMemory(PacketBuffer, HeaderBuffer, HeaderBufferSize);
/* Free the packet descriptor and buffers but not the pool because we still need it */ CleanupAndFreePacket(Packet, FALSE);
/* Allocate a packet entry from pool */ PacketEntry = ExAllocatePool(NonPagedPool, sizeof(NDISUIO_PACKET_ENTRY) + BytesTransferred + HeaderBufferSize - 1); if (!PacketEntry) { ExFreePool(PacketBuffer); return NDIS_STATUS_RESOURCES; }
/* Initialize the packet entry and copy in packet data */ PacketEntry->PacketLength = BytesTransferred + HeaderBufferSize; RtlCopyMemory(PacketEntry->PacketData, PacketBuffer, PacketEntry->PacketLength);
/* Free the old buffer */ ExFreePool(PacketBuffer);
/* Insert the packet on the adapter's packet list */ ExInterlockedInsertTailList(&AdapterContext->PacketList, &PacketEntry->ListEntry, &AdapterContext->Spinlock);
/* Signal the read event */ KeSetEvent(&AdapterContext->PacketReadEvent, IO_NETWORK_INCREMENT, FALSE);
return NDIS_STATUS_SUCCESS;}
VOIDNTAPINduReceiveComplete(NDIS_HANDLE ProtocolBindingContext){ /* No op */}
VOIDNTAPINduStatus(NDIS_HANDLE ProtocolBindingContext, NDIS_STATUS GeneralStatus, PVOID StatusBuffer, UINT StatusBufferSize){ /* FIXME: Implement status tracking */}
VOIDNTAPINduStatusComplete(NDIS_HANDLE ProtocolBindingContext){ /* FIXME: Implement status tracking */}
staticNDIS_STATUSUnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext){ KIRQL OldIrql; PLIST_ENTRY CurrentEntry; PNDISUIO_OPEN_ENTRY OpenEntry; PNDISUIO_PACKET_ENTRY PacketEntry; NDIS_STATUS Status;
DPRINT("Unbinding adapter %wZ\n", &AdapterContext->DeviceName);
/* FIXME: We don't do anything with outstanding reads */
/* Remove the adapter context from the global list */ KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql); RemoveEntryList(&AdapterContext->ListEntry); KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
/* Free the device name string */ RtlFreeUnicodeString(&AdapterContext->DeviceName);
/* Invalidate all handles to this adapter */ CurrentEntry = AdapterContext->OpenEntryList.Flink; while (CurrentEntry != &AdapterContext->OpenEntryList) { OpenEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_OPEN_ENTRY, ListEntry);
/* Make sure the entry is sane */ ASSERT(OpenEntry->FileObject);
/* Remove the adapter context pointer */ ASSERT(AdapterContext == OpenEntry->FileObject->FsContext); OpenEntry->FileObject->FsContext = NULL; AdapterContext->OpenCount--;
/* Remove the open entry pointer */ ASSERT(OpenEntry == OpenEntry->FileObject->FsContext2); OpenEntry->FileObject->FsContext2 = NULL;
/* Move to the next entry */ CurrentEntry = CurrentEntry->Flink;
/* Free the open entry */ ExFreePool(OpenEntry); }
/* If this fails, we have a refcount mismatch somewhere */ ASSERT(AdapterContext->OpenCount == 0);
/* Free all pending packet entries */ CurrentEntry = AdapterContext->PacketList.Flink; while (CurrentEntry != &AdapterContext->PacketList) { PacketEntry = CONTAINING_RECORD(CurrentEntry, NDISUIO_PACKET_ENTRY, ListEntry);
/* Move to the next entry */ CurrentEntry = CurrentEntry->Flink;
/* Free the packet entry */ ExFreePool(PacketEntry); }
/* Send the close request */ NdisCloseAdapter(&Status, AdapterContext->BindingHandle);
/* Wait for a pending close */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; }
/* Free the context */ ExFreePool(AdapterContext);
return Status;}
staticNDIS_STATUSBindAdapterByName(PNDIS_STRING DeviceName){ NDIS_STATUS OpenErrorStatus; PNDISUIO_ADAPTER_CONTEXT AdapterContext; NDIS_MEDIUM SupportedMedia[1] = {NdisMedium802_3}; UINT SelectedMedium; NDIS_STATUS Status; NDIS_REQUEST Request;
/* Allocate the adapter context */ AdapterContext = ExAllocatePool(NonPagedPool, sizeof(*AdapterContext)); if (!AdapterContext) { return NDIS_STATUS_RESOURCES; }
/* Set up the adapter context */ RtlZeroMemory(AdapterContext, sizeof(*AdapterContext)); KeInitializeEvent(&AdapterContext->AsyncEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&AdapterContext->PacketReadEvent, SynchronizationEvent, FALSE); KeInitializeSpinLock(&AdapterContext->Spinlock); InitializeListHead(&AdapterContext->PacketList); InitializeListHead(&AdapterContext->OpenEntryList); AdapterContext->OpenCount = 0;
AdapterContext->DeviceName.Length = AdapterContext->DeviceName.MaximumLength = DeviceName->Length; AdapterContext->DeviceName.Buffer = ExAllocatePool(NonPagedPool, DeviceName->Length); if (!AdapterContext->DeviceName.Buffer) { ExFreePool(AdapterContext); return NDIS_STATUS_RESOURCES; }
/* Copy the device name into the adapter context */ RtlCopyMemory(AdapterContext->DeviceName.Buffer, DeviceName->Buffer, DeviceName->Length);
DPRINT("Binding adapter %wZ\n", &AdapterContext->DeviceName);
/* Create the buffer pool */ NdisAllocateBufferPool(&Status, &AdapterContext->BufferPoolHandle, 50); if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to allocate buffer pool with status 0x%x\n", Status); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; }
/* Create the packet pool */ NdisAllocatePacketPool(&Status, &AdapterContext->PacketPoolHandle, 25, PROTOCOL_RESERVED_SIZE_IN_PACKET); if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to allocate packet pool with status 0x%x\n", Status); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; }
/* Send the open request */ NdisOpenAdapter(&Status, &OpenErrorStatus, &AdapterContext->BindingHandle, &SelectedMedium, SupportedMedia, 1, GlobalProtocolHandle, AdapterContext, DeviceName, 0, NULL);
/* Wait for a pending open */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; }
/* Check the final status */ if (Status != NDIS_STATUS_SUCCESS) { DPRINT1("Failed to open adapter for bind with status 0x%x\n", Status); NdisFreePacketPool(AdapterContext->PacketPoolHandle); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; }
/* Get the MAC options */ Request.RequestType = NdisRequestQueryInformation; Request.DATA.QUERY_INFORMATION.Oid = OID_GEN_MAC_OPTIONS; Request.DATA.QUERY_INFORMATION.InformationBuffer = &AdapterContext->MacOptions; Request.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(ULONG); NdisRequest(&Status, AdapterContext->BindingHandle, &Request);
/* Wait for a pending request */ if (Status == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); Status = AdapterContext->AsyncStatus; }
/* Check the final status */ if (Status != NDIS_STATUS_SUCCESS) { NDIS_STATUS CloseStatus;
DPRINT1("Failed to get MAC options with status 0x%x\n", Status);
NdisCloseAdapter(&CloseStatus, AdapterContext->BindingHandle); if (CloseStatus == NDIS_STATUS_PENDING) { KeWaitForSingleObject(&AdapterContext->AsyncEvent, Executive, KernelMode, FALSE, NULL); }
NdisFreePacketPool(AdapterContext->PacketPoolHandle); NdisFreeBufferPool(AdapterContext->BufferPoolHandle); RtlFreeUnicodeString(&AdapterContext->DeviceName); ExFreePool(AdapterContext); return Status; }
/* Add the adapter context to the global list */ ExInterlockedInsertTailList(&GlobalAdapterList, &AdapterContext->ListEntry, &GlobalAdapterListLock);
return STATUS_SUCCESS;}
VOIDNTAPINduBindAdapter(PNDIS_STATUS Status, NDIS_HANDLE BindContext, PNDIS_STRING DeviceName, PVOID SystemSpecific1, PVOID SystemSpecific2){ /* Use our helper function to create a context for this adapter */ *Status = BindAdapterByName(DeviceName);}
VOIDNTAPINduUnbindAdapter(PNDIS_STATUS Status, NDIS_HANDLE ProtocolBindingContext, NDIS_HANDLE UnbindContext){ /* This is forced unbind. UnbindAdapterByContext() will take care of * invalidating file handles pointer to this adapter for us */ *Status = UnbindAdapterByContext(ProtocolBindingContext);}