[NDISUIO]
authorCameron Gutman <aicommander@gmail.com>
Tue, 3 Jan 2012 18:12:29 +0000 (18:12 +0000)
committerCameron Gutman <aicommander@gmail.com>
Tue, 3 Jan 2012 18:12:29 +0000 (18:12 +0000)
- Handle IOCTL_NDISUIO_OPEN_WRITE_DEVICE and IOCTL_NDISUIO_OPEN_DEVICE properly with regard to current open handles
- Check that we have read permissions (opened by IOCTL_NDISUIO_OPEN_DEVICE) before allowing queries or reads

svn path=/branches/wlan-bringup/; revision=54819

drivers/network/ndisuio/ioctl.c
drivers/network/ndisuio/ndisuio.h
drivers/network/ndisuio/readwrite.c

index df3a638..8555e5c 100644 (file)
@@ -174,8 +174,19 @@ OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
         {
             /* Reference the adapter context */
             KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
-            ReferenceAdapterContext(AdapterContext);
-            Status = STATUS_SUCCESS;
+            if (AdapterContext->OpenCount != 0)
+            {
+                /* An open for read-write is exclusive,
+                 * so we can't have any other open handles */
+                KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
+                Status = STATUS_INVALID_PARAMETER;
+            }
+            else
+            {
+                /* Add a reference */
+                ReferenceAdapterContext(AdapterContext);
+                Status = STATUS_SUCCESS;
+            }
         }
         else
         {
@@ -191,6 +202,9 @@ OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
             {
                 /* Set the file object pointer */
                 OpenEntry->FileObject = FileObject;
+                
+                /* Set the permissions */
+                OpenEntry->WriteOnly = FALSE;
 
                 /* Associate this FO with the adapter */
                 FileObject->FsContext = AdapterContext;
@@ -230,8 +244,80 @@ OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
 NTSTATUS
 OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
 {
-    /* FIXME: Handle this correctly */
-    return OpenDeviceReadWrite(Irp, IrpSp);
+    PFILE_OBJECT FileObject = IrpSp->FileObject;
+    UNICODE_STRING DeviceName;
+    ULONG NameLength;
+    NTSTATUS Status;
+    PNDISUIO_ADAPTER_CONTEXT AdapterContext;
+    PNDISUIO_OPEN_ENTRY OpenEntry;
+    KIRQL OldIrql;
+    
+    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)
+        {
+            /* Reference the adapter context */
+            KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
+            ReferenceAdapterContext(AdapterContext);
+            Status = STATUS_SUCCESS;
+        }
+        else
+        {
+            /* Invalid device name */
+            Status = STATUS_INVALID_PARAMETER;
+        }
+        
+        /* 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;
+                
+                /* Set permissions */
+                OpenEntry->WriteOnly = TRUE;
+                
+                /* Add it to the adapter's list */
+                InsertTailList(&AdapterContext->OpenEntryList,
+                               &OpenEntry->ListEntry);
+                
+                /* Success */
+                KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
+                Status = STATUS_SUCCESS;
+            }
+            else
+            {
+                /* Remove the reference we added */
+                KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
+                DereferenceAdapterContext(AdapterContext, NULL);
+                Status = STATUS_NO_MEMORY;
+            }
+        }
+    }
+    else
+    {
+        /* Invalid device name */
+        Status = STATUS_INVALID_PARAMETER;
+    }
+    
+    Irp->IoStatus.Status = Status;
+    Irp->IoStatus.Information = 0;
+    
+    IoCompleteRequest(Irp, IO_NO_INCREMENT);
+    
+    return Status;
 }
 
 NTSTATUS
@@ -240,6 +326,7 @@ NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
                          PIRP Irp)
 {
     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
+    PNDISUIO_OPEN_ENTRY OpenEntry;
     
     ASSERT(DeviceObject == GlobalDeviceObject);
 
@@ -263,24 +350,39 @@ NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
                 return STATUS_INVALID_PARAMETER;
             }
 
-            /* Now handle other IOCTLs */
+            /* Now handle write IOCTLs */
             switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
             {
-                case IOCTL_CANCEL_READ:
-                    return CancelPacketRead(Irp, IrpSp);
-
-                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;
+                    /* Check that we have read permissions */
+                    OpenEntry = IrpSp->FileObject->FsContext2;
+                    if (OpenEntry->WriteOnly)
+                    {
+                        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+                        Irp->IoStatus.Information = 0;
+                        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                        
+                        return STATUS_INVALID_PARAMETER;
+                    }
+
+                    switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
+                    {
+                        case IOCTL_CANCEL_READ:
+                            return CancelPacketRead(Irp, IrpSp);
+                        
+                        case IOCTL_NDISUIO_QUERY_OID_VALUE:
+                            return QueryAdapterOid(Irp, IrpSp);
+                        
+                        default:
+                            DPRINT1("Unimplemented\n");
+                            Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
+                            Irp->IoStatus.Information = 0;
+                            IoCompleteRequest(Irp, IO_NO_INCREMENT);
+                            break;
+                    }
             }
             break;
     }
index f4a83d1..43e9179 100644 (file)
@@ -42,10 +42,25 @@ struct _NDISUIO_OPEN_ENTRY
     /* File object */
     PFILE_OBJECT FileObject;
     
+    /* Tracks how this adapter was opened (write-only or read-write) */
+    BOOLEAN WriteOnly;
+    
     /* List entry */
     LIST_ENTRY ListEntry;
 } NDISUIO_OPEN_ENTRY, *PNDISUIO_OPEN_ENTRY;
 
+struct _NDISUIO_PACKET_ENTRY
+{
+    /* Length of data at the end of the struct */
+    ULONG PacketLength;
+    
+    /* Entry on the packet list */
+    LIST_ENTRY ListEntry;
+
+    /* Packet data */
+    UCHAR PacketData[1];
+} NDISUIO_PACKET_ENTRY, *PNDISUIO_PACKET_ENTRY;
+
 /* NDIS version info */
 #define NDIS_MAJOR_VERISON 5
 #define NDIS_MINOR_VERSION 0
index 4e1f0e9..61bfc51 100644 (file)
@@ -18,6 +18,7 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject,
 {
     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
     PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
+    PNDISUIO_OPEN_ENTRY OpenEntry = IrpSp->FileObject->FsContext2;
     KIRQL OldIrql;
     NTSTATUS Status;
     PLIST_ENTRY ListEntry;
@@ -26,6 +27,15 @@ NduDispatchRead(PDEVICE_OBJECT DeviceObject,
 
     ASSERT(DeviceObject == GlobalDeviceObject);
 
+    if (OpenEntry->WriteOnly)
+    {
+        Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+        Irp->IoStatus.Information = 0;
+        IoCompleteRequest(Irp, IO_NO_INCREMENT);
+        
+        return STATUS_INVALID_PARAMETER;
+    }
+
     while (TRUE)
     {
         KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);