ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

ioctl.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS NDIS User I/O driver
00004  * FILE:        ioctl.c
00005  * PURPOSE:     IOCTL handling
00006  * PROGRAMMERS: Cameron Gutman (cameron.gutman@reactos.org)
00007  */
00008 
00009 #include "ndisuio.h"
00010 
00011 //#define NDEBUG
00012 #include <debug.h>
00013 
00014 static
00015 NTSTATUS
00016 WaitForBind(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00017 {
00018     /* I've seen several code samples that use this IOCTL but there's
00019      * no official documentation on it. I'm just implementing it as a no-op
00020      * right now because I don't see any reason we need it. We handle an open
00021      * and bind just fine with IRP_MJ_CREATE and IOCTL_NDISUIO_OPEN_DEVICE */
00022     DPRINT("Wait for bind complete\n");
00023     
00024     Irp->IoStatus.Status = STATUS_SUCCESS;
00025     Irp->IoStatus.Information = 0;
00026     
00027     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00028     
00029     return STATUS_SUCCESS;
00030 }
00031 
00032 static
00033 NTSTATUS
00034 QueryBinding(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00035 {
00036     PNDISUIO_ADAPTER_CONTEXT AdapterContext = NULL;
00037     PNDISUIO_QUERY_BINDING QueryBinding = Irp->AssociatedIrp.SystemBuffer;
00038     ULONG BindingLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00039     NTSTATUS Status;
00040     PLIST_ENTRY CurrentEntry;
00041     KIRQL OldIrql;
00042     ULONG i;
00043     ULONG BytesCopied = 0;
00044 
00045     if (QueryBinding && BindingLength >= sizeof(NDISUIO_QUERY_BINDING))
00046     {
00047         KeAcquireSpinLock(&GlobalAdapterListLock, &OldIrql);
00048         i = 0;
00049         CurrentEntry = GlobalAdapterList.Flink;
00050         while (CurrentEntry != &GlobalAdapterList)
00051         {
00052             if (i == QueryBinding->BindingIndex)
00053             {
00054                 AdapterContext = CONTAINING_RECORD(CurrentEntry, NDISUIO_ADAPTER_CONTEXT, ListEntry);
00055                 break;
00056             }
00057             i++;
00058             CurrentEntry = CurrentEntry->Flink;
00059         }
00060         KeReleaseSpinLock(&GlobalAdapterListLock, OldIrql);
00061         if (AdapterContext)
00062         {
00063             DPRINT("Query binding for index %d is adapter %wZ\n", i, &AdapterContext->DeviceName);
00064             BytesCopied = sizeof(NDISUIO_QUERY_BINDING);
00065             if (AdapterContext->DeviceName.Length <= BindingLength - BytesCopied)
00066             {
00067                 QueryBinding->DeviceNameOffset = BytesCopied;
00068                 QueryBinding->DeviceNameLength = AdapterContext->DeviceName.Length;
00069                 RtlCopyMemory((PUCHAR)QueryBinding + QueryBinding->DeviceNameOffset,
00070                               AdapterContext->DeviceName.Buffer,
00071                               QueryBinding->DeviceNameLength);
00072                 BytesCopied += AdapterContext->DeviceName.Length;
00073 
00074                 /* FIXME: Copy description too */
00075                 QueryBinding->DeviceDescrOffset = BytesCopied;
00076                 QueryBinding->DeviceDescrLength = 0;
00077                 
00078                 /* Successful */
00079                 Status = STATUS_SUCCESS;
00080             }
00081             else
00082             {
00083                 /* Not enough buffer space */
00084                 Status = STATUS_BUFFER_TOO_SMALL;
00085             }
00086         }
00087         else
00088         {
00089             /* Invalid index */
00090             Status = STATUS_NO_MORE_ENTRIES;
00091         }
00092     }
00093     else
00094     {
00095         /* Invalid parameters */
00096         Status = STATUS_INVALID_PARAMETER;
00097     }
00098     
00099     Irp->IoStatus.Status = Status;
00100     Irp->IoStatus.Information = BytesCopied;
00101     
00102     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00103     
00104     return Status;
00105 }
00106 
00107 #if 0
00108 static
00109 NTSTATUS
00110 CancelPacketRead(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00111 {
00112     PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
00113     PNDISUIO_PACKET_ENTRY PacketEntry;
00114     NTSTATUS Status;
00115     
00116     /* Indicate a 0-byte packet on the queue so one read returns 0 */
00117     PacketEntry = ExAllocatePool(PagedPool, sizeof(NDISUIO_PACKET_ENTRY));
00118     if (PacketEntry)
00119     {
00120         PacketEntry->PacketLength = 0;
00121         
00122         ExInterlockedInsertHeadList(&AdapterContext->PacketList,
00123                                     &PacketEntry->ListEntry,
00124                                     &AdapterContext->Spinlock);
00125         
00126         KeSetEvent(&AdapterContext->PacketReadEvent, IO_NO_INCREMENT, FALSE);
00127         
00128         Status = STATUS_SUCCESS;
00129     }
00130     else
00131     {
00132         Status = STATUS_NO_MEMORY;
00133     }
00134     
00135     Irp->IoStatus.Status = Status;
00136     Irp->IoStatus.Information = 0;
00137     
00138     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00139     
00140     return Status;
00141 }
00142 #endif
00143 
00144 static
00145 NTSTATUS
00146 SetAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00147 {
00148     PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
00149     PNDISUIO_SET_OID SetOidRequest;
00150     NDIS_REQUEST Request;
00151     ULONG RequestLength;
00152     NDIS_STATUS Status;
00153     
00154     Irp->IoStatus.Information = 0;
00155     
00156     SetOidRequest = Irp->AssociatedIrp.SystemBuffer;
00157     RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00158     if (SetOidRequest && RequestLength >= sizeof(NDIS_OID))
00159     {
00160         /* Setup the NDIS request */
00161         Request.RequestType = NdisRequestSetInformation;
00162         Request.DATA.SET_INFORMATION.Oid = SetOidRequest->Oid;
00163         Request.DATA.SET_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
00164         if (Request.DATA.SET_INFORMATION.InformationBufferLength != 0)
00165         {
00166             Request.DATA.SET_INFORMATION.InformationBuffer = SetOidRequest->Data;
00167         }
00168         else
00169         {
00170             Request.DATA.SET_INFORMATION.InformationBuffer = NULL;
00171         }
00172         Request.DATA.SET_INFORMATION.BytesRead = 0;
00173 
00174         DPRINT("Setting OID 0x%x on adapter %wZ\n", SetOidRequest->Oid, &AdapterContext->DeviceName);
00175 
00176         /* Dispatch the request */
00177         NdisRequest(&Status,
00178                     AdapterContext->BindingHandle,
00179                     &Request);
00180 
00181         /* Wait for the request */
00182         if (Status == NDIS_STATUS_PENDING)
00183         {
00184             KeWaitForSingleObject(&AdapterContext->AsyncEvent,
00185                                   Executive,
00186                                   KernelMode,
00187                                   FALSE,
00188                                   NULL);
00189             Status = AdapterContext->AsyncStatus;
00190         }
00191 
00192         /* Return the bytes read */
00193         if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.SET_INFORMATION.BytesRead;
00194 
00195         DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information);
00196     }
00197     else
00198     {
00199         /* Bad parameters */
00200         Status = STATUS_INVALID_PARAMETER;
00201     }
00202 
00203     Irp->IoStatus.Status = Status;
00204 
00205     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00206 
00207     return Status;
00208 }
00209 
00210 static
00211 NTSTATUS
00212 QueryAdapterOid(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00213 {
00214     PNDISUIO_ADAPTER_CONTEXT AdapterContext = IrpSp->FileObject->FsContext;
00215     PNDISUIO_QUERY_OID QueryOidRequest;
00216     NDIS_REQUEST Request;
00217     ULONG RequestLength;
00218     NDIS_STATUS Status;
00219 
00220     Irp->IoStatus.Information = 0;
00221 
00222     QueryOidRequest = Irp->AssociatedIrp.SystemBuffer;
00223     RequestLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00224     if (QueryOidRequest && RequestLength >= sizeof(NDIS_OID))
00225     {
00226         /* Setup the NDIS request */
00227         Request.RequestType = NdisRequestQueryInformation;
00228         Request.DATA.QUERY_INFORMATION.Oid = QueryOidRequest->Oid;
00229         Request.DATA.QUERY_INFORMATION.InformationBufferLength = RequestLength - sizeof(NDIS_OID);
00230         if (Request.DATA.QUERY_INFORMATION.InformationBufferLength != 0)
00231         {
00232             Request.DATA.QUERY_INFORMATION.InformationBuffer = QueryOidRequest->Data;
00233         }
00234         else
00235         {
00236             Request.DATA.QUERY_INFORMATION.InformationBuffer = NULL;
00237         }
00238         Request.DATA.QUERY_INFORMATION.BytesWritten = 0;
00239 
00240         DPRINT("Querying OID 0x%x on adapter %wZ\n", QueryOidRequest->Oid, &AdapterContext->DeviceName);
00241         
00242         /* Dispatch the request */
00243         NdisRequest(&Status,
00244                     AdapterContext->BindingHandle,
00245                     &Request);
00246         
00247         /* Wait for the request */
00248         if (Status == NDIS_STATUS_PENDING)
00249         {
00250             KeWaitForSingleObject(&AdapterContext->AsyncEvent,
00251                                   Executive,
00252                                   KernelMode,
00253                                   FALSE,
00254                                   NULL);
00255             Status = AdapterContext->AsyncStatus;
00256         }
00257 
00258         /* Return the bytes written */
00259         if (NT_SUCCESS(Status)) Irp->IoStatus.Information = sizeof(NDIS_OID) + Request.DATA.QUERY_INFORMATION.BytesWritten;
00260 
00261         DPRINT("Final request status: 0x%x (%d)\n", Status, Irp->IoStatus.Information);
00262     }
00263     else
00264     {
00265         /* Bad parameters */
00266         Status = STATUS_INVALID_PARAMETER;
00267     }
00268     
00269     Irp->IoStatus.Status = Status;
00270     
00271     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00272     
00273     return Status;
00274 }
00275 
00276 static
00277 NTSTATUS
00278 OpenDeviceReadWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00279 {
00280     PFILE_OBJECT FileObject = IrpSp->FileObject;
00281     UNICODE_STRING DeviceName;
00282     ULONG NameLength;
00283     NTSTATUS Status;
00284     PNDISUIO_ADAPTER_CONTEXT AdapterContext;
00285     PNDISUIO_OPEN_ENTRY OpenEntry;
00286     KIRQL OldIrql;
00287 
00288     NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00289     if (NameLength != 0)
00290     {
00291         DeviceName.MaximumLength = DeviceName.Length = NameLength;
00292         DeviceName.Buffer = Irp->AssociatedIrp.SystemBuffer;
00293 
00294         /* Check if this already has a context */
00295         AdapterContext = FindAdapterContextByName(&DeviceName);
00296         if (AdapterContext != NULL)
00297         {
00298             DPRINT("Binding file object 0x%x to device %wZ\n", FileObject, &AdapterContext->DeviceName);
00299 
00300             /* Reference the adapter context */
00301             KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
00302             if (AdapterContext->OpenCount != 0)
00303             {
00304                 /* An open for read-write is exclusive,
00305                  * so we can't have any other open handles */
00306                 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
00307                 Status = STATUS_INVALID_PARAMETER;
00308             }
00309             else
00310             {
00311                 /* Add a reference */
00312                 ReferenceAdapterContext(AdapterContext);
00313                 Status = STATUS_SUCCESS;
00314             }
00315         }
00316         else
00317         {
00318             /* Invalid device name */
00319             Status = STATUS_INVALID_PARAMETER;
00320         }
00321 
00322         /* Check that the bind succeeded */
00323         if (NT_SUCCESS(Status))
00324         {
00325             OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
00326             if (OpenEntry)
00327             {
00328                 /* Set the file object pointer */
00329                 OpenEntry->FileObject = FileObject;
00330                 
00331                 /* Set the permissions */
00332                 OpenEntry->WriteOnly = FALSE;
00333 
00334                 /* Associate this FO with the adapter */
00335                 FileObject->FsContext = AdapterContext;
00336                 FileObject->FsContext2 = OpenEntry;
00337 
00338                 /* Add it to the adapter's list */
00339                 InsertTailList(&AdapterContext->OpenEntryList,
00340                                &OpenEntry->ListEntry);
00341 
00342                 /* Success */
00343                 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
00344                 Status = STATUS_SUCCESS;
00345             }
00346             else
00347             {
00348                 /* Remove the reference we added */
00349                 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
00350                 DereferenceAdapterContextWithOpenEntry(AdapterContext, NULL);
00351                 Status = STATUS_NO_MEMORY;
00352             }
00353         }
00354     }
00355     else
00356     {
00357         /* Invalid device name */
00358         Status = STATUS_INVALID_PARAMETER;
00359     }
00360     
00361     Irp->IoStatus.Status = Status;
00362     Irp->IoStatus.Information = 0;
00363     
00364     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00365     
00366     return Status;
00367 }
00368 
00369 #if 0
00370 static
00371 NTSTATUS
00372 OpenDeviceWrite(PIRP Irp, PIO_STACK_LOCATION IrpSp)
00373 {
00374     PFILE_OBJECT FileObject = IrpSp->FileObject;
00375     UNICODE_STRING DeviceName;
00376     ULONG NameLength;
00377     NTSTATUS Status;
00378     PNDISUIO_ADAPTER_CONTEXT AdapterContext;
00379     PNDISUIO_OPEN_ENTRY OpenEntry;
00380     KIRQL OldIrql;
00381     
00382     NameLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
00383     if (NameLength != 0)
00384     {
00385         DeviceName.MaximumLength = DeviceName.Length = NameLength;
00386         DeviceName.Buffer = Irp->AssociatedIrp.SystemBuffer;
00387         
00388         /* Check if this already has a context */
00389         AdapterContext = FindAdapterContextByName(&DeviceName);
00390         if (AdapterContext != NULL)
00391         {
00392             /* Reference the adapter context */
00393             KeAcquireSpinLock(&AdapterContext->Spinlock, &OldIrql);
00394             ReferenceAdapterContext(AdapterContext);
00395             Status = STATUS_SUCCESS;
00396         }
00397         else
00398         {
00399             /* Invalid device name */
00400             Status = STATUS_INVALID_PARAMETER;
00401         }
00402         
00403         /* Check that the bind succeeded */
00404         if (NT_SUCCESS(Status))
00405         {
00406             OpenEntry = ExAllocatePool(NonPagedPool, sizeof(*OpenEntry));
00407             if (OpenEntry)
00408             {
00409                 /* Set the file object pointer */
00410                 OpenEntry->FileObject = FileObject;
00411                 
00412                 /* Associate this FO with the adapter */
00413                 FileObject->FsContext = AdapterContext;
00414                 FileObject->FsContext2 = OpenEntry;
00415                 
00416                 /* Set permissions */
00417                 OpenEntry->WriteOnly = TRUE;
00418                 
00419                 /* Add it to the adapter's list */
00420                 InsertTailList(&AdapterContext->OpenEntryList,
00421                                &OpenEntry->ListEntry);
00422                 
00423                 /* Success */
00424                 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
00425                 Status = STATUS_SUCCESS;
00426             }
00427             else
00428             {
00429                 /* Remove the reference we added */
00430                 KeReleaseSpinLock(&AdapterContext->Spinlock, OldIrql);
00431                 DereferenceAdapterContext(AdapterContext, NULL);
00432                 Status = STATUS_NO_MEMORY;
00433             }
00434         }
00435     }
00436     else
00437     {
00438         /* Invalid device name */
00439         Status = STATUS_INVALID_PARAMETER;
00440     }
00441     
00442     Irp->IoStatus.Status = Status;
00443     Irp->IoStatus.Information = 0;
00444     
00445     IoCompleteRequest(Irp, IO_NO_INCREMENT);
00446     
00447     return Status;
00448 }
00449 #endif
00450 
00451 NTSTATUS
00452 NTAPI
00453 NduDispatchDeviceControl(PDEVICE_OBJECT DeviceObject,
00454                          PIRP Irp)
00455 {
00456     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
00457     PNDISUIO_OPEN_ENTRY OpenEntry;
00458     
00459     ASSERT(DeviceObject == GlobalDeviceObject);
00460 
00461     /* Handle open IOCTLs first */
00462     switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
00463     {
00464         case IOCTL_NDISUIO_OPEN_DEVICE:
00465             return OpenDeviceReadWrite(Irp, IrpSp);
00466 #if 0
00467         case IOCTL_NDISUIO_OPEN_WRITE_DEVICE:
00468             return OpenDeviceWrite(Irp, IrpSp);
00469 #endif
00470         case IOCTL_NDISUIO_BIND_WAIT:
00471             return WaitForBind(Irp, IrpSp);
00472             
00473         case IOCTL_NDISUIO_QUERY_BINDING:
00474             return QueryBinding(Irp, IrpSp);
00475 
00476         default:
00477             /* Fail if this file object has no adapter associated */
00478             if (IrpSp->FileObject->FsContext == NULL)
00479             {
00480                 Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
00481                 Irp->IoStatus.Information = 0;
00482                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
00483                 
00484                 return STATUS_INVALID_PARAMETER;
00485             }
00486 
00487             /* Now handle write IOCTLs */
00488             switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
00489             {
00490                 case IOCTL_NDISUIO_SET_OID_VALUE:
00491                     return SetAdapterOid(Irp, IrpSp);
00492 
00493                 default:
00494                     /* Check that we have read permissions */
00495                     OpenEntry = IrpSp->FileObject->FsContext2;
00496                     if (OpenEntry->WriteOnly)
00497                     {
00498                         Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
00499                         Irp->IoStatus.Information = 0;
00500                         IoCompleteRequest(Irp, IO_NO_INCREMENT);
00501                         
00502                         return STATUS_INVALID_PARAMETER;
00503                     }
00504 
00505                     switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
00506                     {
00507 #if 0
00508                         case IOCTL_CANCEL_READ:
00509                             return CancelPacketRead(Irp, IrpSp);
00510 #endif
00511                         
00512                         case IOCTL_NDISUIO_QUERY_OID_VALUE:
00513                             return QueryAdapterOid(Irp, IrpSp);
00514                         
00515                         default:
00516                             DPRINT1("Unimplemented\n");
00517                             Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
00518                             Irp->IoStatus.Information = 0;
00519                             IoCompleteRequest(Irp, IO_NO_INCREMENT);
00520                             return STATUS_NOT_IMPLEMENTED;
00521                     }
00522             }
00523             break;
00524     }
00525 }

Generated on Sat May 26 2012 04:25:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.