diff --git a/drivers/network/ndisuio/CMakeLists.txt b/drivers/network/ndisuio/CMakeLists.txt new file mode 100644 index 00000000000..0f257184cda --- /dev/null +++ b/drivers/network/ndisuio/CMakeLists.txt @@ -0,0 +1,22 @@ +add_definitions( + -DNDIS50 + -D_NTDRIVER_) + +spec2def(ndisuio.sys ndisuio.spec) + +list(APPEND SOURCE + main.c + ndisuio.rc + ${CMAKE_CURRENT_BINARY_DIR}/ndisuio.def) + +add_library(ndisuio SHARED ${SOURCE}) + +target_link_libraries(ndisuio + ${PSEH_LIB}) + +set_module_type(ndisuio kernelmodedriver) +add_importlibs(ndisuio ndis ntoskrnl hal) + +add_pch(ndisuio ndisuio.h) + +add_cd_file(TARGET ndisuio DESTINATION reactos/system32/drivers FOR all) diff --git a/drivers/network/ndisuio/createclose.c b/drivers/network/ndisuio/createclose.c new file mode 100644 index 00000000000..23c762b3114 --- /dev/null +++ b/drivers/network/ndisuio/createclose.c @@ -0,0 +1,64 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: createclose.c + * PURPOSE: IRP_MJ_CREATE and IRP_MJ_CLOSE handling + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) + */ + +#include "ndisuio.h" + +#define NDEBUG +#include + +NTSTATUS +NTAPI +NduDispatchCreate(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + ASSERT(DeviceObject == GlobalDeviceObject); + + /* This is associated with an adapter during IOCTL_NDISUIO_OPEN_(WRITE_)DEVICE */ + IrpSp->FileObject->FsContext = NULL; + IrpSp->FileObject->FsContext2 = NULL; + + /* Completed successfully */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = FILE_OPENED; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Return success */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +NduDispatchClose(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; + PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2; + KIRQL OldIrql; + + ASSERT(DeviceObject == GlobalDeviceObject); + + /* Check if this handle was ever associated with an adapter */ + if (AdapterContext != NULL) + { + ASSERT(OpenEntry != NULL); + + /* Call the our helper */ + DereferenceAdapterContextWithOpenEntry(AdapterContext, OpenEntry); + } + + /* Completed */ + Irp->IoStatus.Status = STATUS_SUCCESS; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + /* Return success */ + return STATUS_SUCCESS; +} \ No newline at end of file diff --git a/drivers/network/ndisuio/ioctl.c b/drivers/network/ndisuio/ioctl.c new file mode 100644 index 00000000000..25fb18be2fc --- /dev/null +++ b/drivers/network/ndisuio/ioctl.c @@ -0,0 +1,247 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: ioctl.c + * PURPOSE: IOCTL handling + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) + */ + +#include "ndisuio.h" + +#define NDEBUG +#include + +NTSTATUS +SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; + PNDISUIO_SET_OID SetOidRequest; + NDIS_REQUEST NdisRequest; + ULONG RequestLength; + NDIS_STATUS Status; + + Irp->IoStatus.Information = 0; + + SetOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID)) + { + /* Setup the NDIS request */ + NdisRequest.RequestType = NdisRequestSetInformation; + NdisRequest.Oid = SetOidRequest->Oid; + NdisRequest.InformationBuffer = SetOidRequest->Data; + NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID); + + /* Dispatch the request */ + NdisRequest(&Status, + AdapterContext->BindingHandle, + &NdisRequest); + + /* Wait for the request */ + if (Status == NDIS_STATUS_PENDING) + { + KeWaitForSingleObject(&AdapterContext->AsyncEvent, + Executive, + KernelMode, + FALSE, + NULL); + Status = AdapterContext->AsyncStatus; + } + + /* Return the bytes read */ + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesRead; + } + else + { + /* Bad parameters */ + Status = STATUS_INVALID_PARAMETER; + } + + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +NTSTATUS +QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext; + PNDISUIO_QUERY_OID QueryOidRequest; + NDIS_REQUEST NdisRequest; + ULONG RequestLength; + NDIS_STATUS Status; + + Irp->IoStatus.Information = 0; + + QueryOidRequest = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID)) + { + /* Setup the NDIS request */ + NdisRequest.RequestType = NdisRequestQueryInformation; + NdisRequest.Oid = QueryOidRequest->Oid; + NdisRequest.InformationBuffer = QueryOidRequest->Data; + NdisRequest.InformationBufferLength = RequestLength - sizeof(NDIS_OID); + + /* Dispatch the request */ + NdisRequest(&Status, + AdapterContext->BindingHandle, + &NdisRequest); + + /* Wait for the request */ + if (Status == NDIS_STATUS_PENDING) + { + KeWaitForSingleObject(&AdapterContext->AsyncEvent, + Executive, + KernelMode, + FALSE, + NULL); + Status = AdapterContext->AsyncStatus; + } + + /* Return the bytes written */ + if (NT_SUCCESS(Status)) Irp->IoStatus.Information = NdisRequest.BytesWritten; + } + else + { + /* Bad parameters */ + Status = STATUS_INVALID_PARAMETER; + } + + Irp->IoStatus.Status = Status; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +NTSTATUS +OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + PFILE_OBJECT FileObject = IrpSp->FileObject; + UNICODE_STRING DeviceName; + ULONG NameLength; + NTSTATUS Status; + PNDISUIO_ADAPTER_CONTEXT AdapterContext; + PNDISUIO_OPEN_ENTRY OpenEntry; + + NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength; + if (NameLength != 0) + { + DeviceName.MaximumLength = DeviceName.Length = NameLength; + DeviceName.Buffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + + /* Check if this already has a context */ + AdapterContext = FindAdapterContextByName(&DeviceName); + if (AdapterContext == NULL) + { + /* Create a new context */ + Status = BindAdapterByName(&DeviceName, &AdapterContext); + } + else + { + /* Reference the existing context */ + ReferenceAdapterContext(AdapterContext, FALSE); + Status = STATUS_SUCCESS; + } + + /* Check that the bind succeeded */ + if (NT_SUCCESS(Status)) + { + OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry)); + if (OpenEntry) + { + /* Set the file object pointer */ + OpenEntry->FileObject = FileObject; + + /* Associate this FO with the adapter */ + FileObject->FsContext = AdapterContext; + FileObject->FsContext2 = OpenEntry; + + /* Add it to the adapter's list */ + ExInterlockedInsertTailList(&AdapterContext->OpenEntryList, + &OpenEntry->ListEntry, + &AdapterContext->Spinlock); + + /* Success */ + Status = STATUS_SUCCESS; + } + else + { + /* Remove the reference we added */ + DereferenceAdapterContext(AdapterContext, NULL); + + Status = STATUS_NO_MEMORY; + } + } + } + else + { + Status = STATUS_INVALID_PARAMETER; + } + + Irp->IoStatus.Status = Status; + Irp->IoStatus.Information = 0; + + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return Status; +} + +NTSTATUS +OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp) +{ + /* FIXME: Handle this correctly */ + return OpenDeviceReadWrite(Irp, IrpSp); +} + +NTSTATUS +NTAPI +NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp); + + ASSERT(DeviceObject == GlobalDeviceObject); + + /* Handle open IOCTLs first */ + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_NDISUIO_OPEN_DEVICE: + return OpenDeviceReadWrite(Irp, IrpSp); + + case IOCTL_NDISUIO_OPEN_WRITE_DEVICE: + return OpenDeviceWrite(Irp, IrpSp); + + default: + /* Fail if this file object has no adapter associated */ + if (IrpSp->FileObject->FsContext == NULL) + { + Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + + return STATUS_INVALID_PARAMETER; + } + + /* Now handle other IOCTLs */ + switch (IrpSp->Parameters.DeviceIoControl.IoControlCode) + { + case IOCTL_NDISUIO_QUERY_OID_VALUE: + return QueryAdapterOid(Irp, IrpSp); + + case IOCTL_NDISUIO_SET_OID_VALUE: + return SetAdapterOid(Irp, IrpSp); + + default: + DPRINT1("Unimplemented\n"); + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + break; + } + break; + } +} diff --git a/drivers/network/ndisuio/main.c b/drivers/network/ndisuio/main.c new file mode 100644 index 00000000000..f30ee5eb998 --- /dev/null +++ b/drivers/network/ndisuio/main.c @@ -0,0 +1,88 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: main.c + * PURPOSE: Driver entry point and protocol initialization + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) + */ + +#include "ndisuio.h" + +#define NDEBUG +#include + +PDEVICE_OBJECT GlobalDeviceObject; +NDIS_HANDLE GlobalProtocolHandle; + +VOID NTAPI NduUnload(PDRIVER_OBJECT DriverObject) +{ + IoDeleteDevice(GlobalDeviceObject); + + DPRINT("NDISUIO: Unloaded\n"); +} + +NTSTATUS +NTAPI +DriverEntry(PDRIVER_OBJECT DriverObject, + PUNICODE_STRING RegistryPath) +{ + NTSTATUS Status; + NDIS_PROTOCOL_CHARACTERISTICS Chars; + + /* Setup dispatch functions */ + DriverObject->MajorFunction[IRP_MJ_CREATE] = NduDispatchCreate; + DriverObject->MajorFunction[IRP_MJ_CLOSE] = NduDispatchClose; + DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NduDispatchDeviceControl; + DriverObject->MajorFunction[IRP_MJ_READ] = NduDispatchRead; + DriverObject->MajorFunction[IRP_MJ_WRITE] = NduDispatchWrite; + DriverObject->DriverUnload = NduUnload; + + /* Create the NDISUIO device object */ + Status = IoCreateDevice(DriverObject, + 0, + NULL, // FIXME + NDISUIO_DEVICE_NAME, + FILE_DEVICE_SECURE_OPEN, + FALSE, + &GlobalDeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create device object with status 0x%x\n", Status); + return Status; + } + + /* Register the protocol with NDIS */ + RtlZeroMemory(&Chars, sizeof(Chars)); + Chars.MajorNdisVersion = NDIS_MAJOR_VERSION; + Chars.MinorNdisVersion = NDIS_MINOR_VERSION; + Chars.OpenAdapterCompleteHandler = NduOpenAdapterComplete; + Chars.CloseAdapterCompleteHandler = NduCloseAdapterComplete; + Chars.SendCompleteHandler = NduSendComplete; + Chars.TransferDataCompleteHandler = NduTransferDataComplete; + Chars.ResetCompleteHandler = NduResetComplete; + Chars.RequestCompleteHandler = NduRequestComplete; + Chars.ReceiveHandler = NduReceive; + Chars.ReceiveComplete = NduReceiveComplete; + Chars.StatusHandler = NduStatus; + Chars.StatusCompleteHandler = NduStatusComplete; + Chars.Name = NULL; //FIXME + Chars.ReceivePacketHandler = NULL; //NduReceivePacket + Chars.BindAdapterHandler = NduBindAdapter; + Chars.UnbindAdapterHandler = NduUnbindAdapter; + Chars.PnPEventHandler = NduPnPEvent; + + NdisRegisterProtocol(&Status, + &GlobalProtocolHandle, + &Chars, + sizeof(Chars)); + if (Status != NDIS_STATUS_SUCCESS) + { + DPRINT1("Failed to register protocol with status 0x%x\n", Status); + IoDeleteDevice(GlobalDeviceObject); + return Status; + } + + DPRINT("NDISUIO: Loaded\n"); + + return STATUS_SUCCESS; +} diff --git a/drivers/network/ndisuio/misc.c b/drivers/network/ndisuio/misc.c new file mode 100644 index 00000000000..e23432375c5 --- /dev/null +++ b/drivers/network/ndisuio/misc.c @@ -0,0 +1,113 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: misc.c + * PURPOSE: Helper functions + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) + */ + +#include "ndisuio.h" + +#define NDEBUG +#include + +PNDISUIO_ADAPTER_CONTEXT +FindAdapterContextByName(PNDIS_STRING DeviceName) +{ + KIRQL OldIrql; + PLIST_ENTRY CurrentEntry; + PNDISUIO_ADAPTER_CONTEXT AdapterContext; + + KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql); + CurrentEntry = GlobalAdapterList.Flink; + while (CurrentEntry != &GlobalAdapterList) + { + AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry); + + /* Check if the device name matches */ + if (RtlEqualUnicodeString(&AdapterContext->DeviceName, DeviceName, TRUE)) + { + KeAcquireSpinLockAtDpcLevel(&AdapterContext->Spinlock); + + /* Check that it's not being destroyed */ + if (AdapterContext->OpenCount > 0) + { + KeReleaseSpinLockFromDpcLevel(&AdapterContext->Spinlock); + KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql); + return AdapterContext; + } + else + { + KeReleaseSpinLockFromDpcLevel(&Adaptercontext->Spinlock); + } + } + + CurrentEntry = CurrentEntry->Flink; + } + KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql); + + return NULL; +} + +VOID +ReferenceAdapterContext(PNDISUIO_ADAPTER_CONTEXT AdapterContext, BOOLEAN Locked) +{ + KIRQL OldIrql; + + /* Lock if needed */ + if (!Locked) + { + KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql); + } + + /* Increment the open count */ + AdapterContext->OpenCount++; + + /* Unlock if needed */ + if (!Locked) + { + KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql); + } +} + +VOID +DereferenceAdapterContextWithOpenEntry(PNDISUIO_ADAPTER_CONTEXT AdapterContext, + PNDISUIO_OPEN_ENTRY OpenEntry) +{ + KIRQL OldIrql; + + /* Lock the adapter context */ + KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql); + + /* Decrement the open count */ + AdapterContext->OpenCount--; + + /* Cleanup the open entry if we were given one */ + if (OpenEntry != NULL) + { + /* Remove the open entry */ + RemoveEntryList(&OpenEntry->ListEntry); + + /* Invalidate the FO */ + OpenEntry->FileObject->FsContext = NULL; + OpenEntry->FileObject->FsContext2 = NULL; + + /* Free the open entry */ + ExFreePool(OpenEntry); + } + + /* See if this binding can be destroyed */ + if (AdapterContext->OpenCount == 0) + { + /* Unlock the context */ + KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql); + + /* Destroy the adapter context */ + UnbindAdapterByContext(AdapterContext); + } + else + { + /* Still more references on it */ + KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql); + } +} diff --git a/drivers/network/ndisuio/ndisuio.h b/drivers/network/ndisuio/ndisuio.h new file mode 100644 index 00000000000..6c3ca505974 --- /dev/null +++ b/drivers/network/ndisuio/ndisuio.h @@ -0,0 +1,55 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: ndisuio.h + * PURPOSE: NDISUIO definitions + */ +#ifndef __NDISUIO_H +#define __NDISUIO_H + +#include +#include +//#include +#include +#include + +struct _NDISUIO_ADAPTER_CONTEXT +{ + /* Asynchronous completion */ + NDIS_STATUS AsyncStatus; + KEVENT AsyncEvent; + + /* NDIS binding information */ + NDIS_HANDLE BindingHandle; + + /* Reference count information */ + ULONG OpenCount; + LIST_ENTRY OpenEntryList; + + /* Receive packet list */ + LIST_ENTRY PacketList; + + /* Cancel read */ + BOOLEAN CancelRead; + + /* Global list entry */ + LIST_ENTRY ListEntry; + + /* Spin lock */ + KSPIN_LOCK Spinlock; +} NDISUIO_ADAPTER_CONTEXT, *PNDISUIO_ADAPTER_CONTEXT; + +struct _NDISUIO_OPEN_ENTRY +{ + /* File object */ + PFILE_OBJECT FileObject; + + /* List entry */ + LIST_ENTRY ListEntry; +} NDISUIO_OPEN_ENTRY, *PNDISUIO_OPEN_ENTRY; + +/* NDIS version info */ +#define NDIS_MAJOR_VERISON 5 +#define NDIS_MINOR_VERSION 0 + +#endif /* __NDISUIO_H */ diff --git a/drivers/network/ndisuio/ndisuio.rbuild b/drivers/network/ndisuio/ndisuio.rbuild new file mode 100644 index 00000000000..e5ace2f6d9f --- /dev/null +++ b/drivers/network/ndisuio/ndisuio.rbuild @@ -0,0 +1,14 @@ + + + + . + + + ndis + pseh + ntoskrnl + hal + ndisuio.h + main.c + ndisuio.rc + diff --git a/drivers/network/ndisuio/ndisuio.rc b/drivers/network/ndisuio/ndisuio.rc new file mode 100644 index 00000000000..bf0e8f4c7ae --- /dev/null +++ b/drivers/network/ndisuio/ndisuio.rc @@ -0,0 +1,5 @@ +#define REACTOS_VERSION_DLL +#define REACTOS_STR_FILE_DESCRIPTION "NDIS User-Mode I/O Protocol Driver\0" +#define REACTOS_STR_INTERNAL_NAME "ndisuio\0" +#define REACTOS_STR_ORIGINAL_FILENAME "ndisuio.sys\0" +#include diff --git a/drivers/network/ndisuio/protocol.c b/drivers/network/ndisuio/protocol.c new file mode 100644 index 00000000000..a50c83ee8fb --- /dev/null +++ b/drivers/network/ndisuio/protocol.c @@ -0,0 +1,278 @@ +/* + * 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 + +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; + + /* 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); + + /* Remove the adapter context from the global list */ + KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql); + RemoveEntryList(&AdapterContext->ListEntry); + KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql); + + /* 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 = 1; + + /* 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) +{ + /* We don't bind like this */ + *Status = NDIS_STATUS_SUCCESS; +} + +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); +} + diff --git a/drivers/network/ndisuio/readwrite.c b/drivers/network/ndisuio/readwrite.c new file mode 100644 index 00000000000..a37872bd045 --- /dev/null +++ b/drivers/network/ndisuio/readwrite.c @@ -0,0 +1,40 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NDIS User I/O driver + * FILE: readwrite.c + * PURPOSE: Handles IRP_MJ_READ and IRP_MJ_WRITE + * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org) + */ + +#include "ndisuio.h" + +#define NDEBUG +#include + +VOID +NTAPI +NduDispatchRead(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + ASSERT(DeviceObject == GlobalDeviceObject); + + /* FIXME: Not implemented */ + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + + return STATUS_NOT_IMPLEMENTED; +} + +VOID +NTAPI +NduDispatchWrite(PDEVICE_OBJECT DeviceObject, + PIRP Irp) +{ + ASSERT(DeviceObject == GlobalDeviceObject); + + /* FIXME: Not implemented */ + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + Irp->IoStatus.Information = 0; + + return STATUS_NOT_IMPLEMENTED; +} \ No newline at end of file