mirror of
https://github.com/reactos/reactos.git
synced 2024-11-19 05:22:59 +00:00
93d3b91947
- Fix a race condition during adapter context destruction - Add missing IRP completion in IRP_MJ_READ and IRP_MJ_WRITE handlers - Create an adapter context in response to PnP events svn path=/branches/wlan-bringup/; revision=54816
278 lines
7.8 KiB
C
278 lines
7.8 KiB
C
/*
|
|
* 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>
|
|
|
|
PNDIS_MEDIUM SupportedMedia = {NdisMedium802_3};
|
|
|
|
VOID
|
|
NTAPI
|
|
NduOpenAdapterComplete(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);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduCloseAdapterComplete(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);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduSendComplete(NDIS_HANDLE ProtocolBindingContext,
|
|
PNDIS_PACKET Packet,
|
|
NDIS_STATUS Status)
|
|
{
|
|
/* FIXME: Implement send/receive */
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduTransferDataComplete(NDIS_HANDLE ProtocolBindingContext,
|
|
PNDIS_PACKET Packet,
|
|
NDIS_STATUS Status,
|
|
UINT BytesTransferred)
|
|
{
|
|
/* FIXME: Implement send/receive */
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduResetComplete(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);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduRequestComplete(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_STATUS
|
|
NTAPI
|
|
NduReceive(NDIS_HANDLE ProtocolBindingContext,
|
|
NDIS_HANDLE MacReceiveContext,
|
|
PVOID HeaderBuffer,
|
|
UINT HeaderBufferSize,
|
|
PVOID LookAheadBuffer,
|
|
UINT LookaheadBufferSize,
|
|
UINT PacketSize)
|
|
{
|
|
/* FIXME: Implement send/receive */
|
|
return NDIS_STATUS_NOT_ACCEPTED;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduReceiveComplete(NDIS_HANDLE ProtocolBindingContext)
|
|
{
|
|
/* No op */
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduStatus(NDIS_HANDLE ProtocolBindingContext,
|
|
NDIS_STATUS GeneralStatus,
|
|
PVOID StatusBuffer,
|
|
UINT StatusBufferSize)
|
|
{
|
|
/* FIXME: Implement status tracking */
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduStatusComplete(NDIS_HANDLE ProtocolBindingContext)
|
|
{
|
|
/* FIXME: Implement status tracking */
|
|
}
|
|
|
|
NDIS_STATUS
|
|
UnbindAdapterByContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext)
|
|
{
|
|
KIRQL OldIrql;
|
|
PLIST_ENTRY CurrentOpenEntry;
|
|
PNDISUIO_OPEN_ENTRY OpenEntry;
|
|
|
|
/* Remove the adapter context from the global list */
|
|
KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
|
|
RemoveEntryList(&AdapterContext->ListEntry);
|
|
KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
|
|
|
|
/* Invalidate all handles to this adapter */
|
|
CurrentOpenEntry = AdapterContext->OpenEntryList.Flink;
|
|
while (CurrentOpenEntry != &AdapterContext->OpenEntryList)
|
|
{
|
|
OpenEntry = CONTAINING_RECORD(CurrentOpenEntry, 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 */
|
|
CurrentOpenEntry = CurrentOpenEntry->Flink;
|
|
|
|
/* Free the open entry */
|
|
ExFreePool(OpenEntry);
|
|
}
|
|
|
|
/* If this fails, we have a refcount mismatch somewhere */
|
|
ASSERT(AdapterContext->OpenCount == 0);
|
|
|
|
/* 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);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
BindAdapterByName(PNDIS_STRING DeviceName, PNDISUIO_ADAPTER_CONTEXT *Context)
|
|
{
|
|
NDIS_STATUS OpenErrorStatus;
|
|
PNDISUIO_ADAPTER_CONTEXT AdapterContext;
|
|
UINT SelectedMedium;
|
|
NDIS_STATUS Status;
|
|
|
|
/* 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);
|
|
KeInitializeSpinLock(&AdapterContext->Spinlock);
|
|
InitializeListHead(&AdapterContext->PacketList);
|
|
InitializeListHead(&AdapterContext->OpenEntryList);
|
|
AdapterContext->OpenCount = 0;
|
|
|
|
/* Send the open request */
|
|
NdisOpenAdapter(&Status,
|
|
&OpenErrorStatus,
|
|
&AdapterContext->BindingHandle,
|
|
&SelectedMedium,
|
|
SupportedMedia,
|
|
sizeof(SupportedMedia),
|
|
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);
|
|
ExFreePool(AdapterContext);
|
|
return;
|
|
}
|
|
|
|
/* Add the adapter context to the global list */
|
|
ExInterlockedInsertTailList(&GlobalAdapterList,
|
|
&AdapterContext->ListEntry,
|
|
&GlobalAdapterListLock);
|
|
|
|
/* Return the context */
|
|
*Context = AdapterContext;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduBindAdapter(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);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
NduUnbindAdapter(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);
|
|
}
|
|
|