Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenioctl.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
1.7.6.1
|