// // Handle IO control requests in the device thread // VOID VfdIoCtlThread( IN PDEVICE_EXTENSION DeviceExtension, IN PIRP Irp, IN ULONG ControlCode) { switch (ControlCode) { case IOCTL_VFD_OPEN_IMAGE: // open the file from the caller's security context // -- this allows this driver to open network files if (DeviceExtension->SecurityContext) { SeImpersonateClient(DeviceExtension->SecurityContext, NULL); } Irp->IoStatus.Status = VfdOpenImage(DeviceExtension, (PVFD_IMAGE_INFO)Irp->AssociatedIrp.SystemBuffer); PsRevertToSelf(); break; case IOCTL_VFD_CLOSE_IMAGE: case IOCTL_DISK_EJECT_MEDIA: case IOCTL_STORAGE_EJECT_MEDIA: VfdCloseImage(DeviceExtension); Irp->IoStatus.Status = STATUS_SUCCESS; break; case IOCTL_DISK_FORMAT_TRACKS: case IOCTL_DISK_FORMAT_TRACKS_EX: Irp->IoStatus.Status = VfdFormatTrack(DeviceExtension, (PFORMAT_PARAMETERS)Irp->AssociatedIrp.SystemBuffer); break; default: // This shouldn't happen... VFDTRACE(0, ("[VFD] %s passed to the device thread\n", GetIoControlName(ControlCode))); Irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } #if DBG if ((NT_SUCCESS(Irp->IoStatus.Status) && (TraceFlags & VFDINFO) == VFDINFO) || (TraceFlags & VFDWARN) == VFDWARN) { VFDTRACE(0,("[VFD] %-40s - %s\n", GetIoControlName(ControlCode), GetStatusName(Irp->IoStatus.Status))); } #endif }
//前面说到为每一个磁盘设备对象生成了一个系统线程,用来处理Irp VOID FileDiskThread ( IN PVOID Context ) { PDEVICE_OBJECT device_object; PDEVICE_EXTENSION device_extension; PLIST_ENTRY request; PIRP irp; PIO_STACK_LOCATION io_stack; PUCHAR system_buffer; PUCHAR buffer; ASSERT(Context != NULL); device_object = (PDEVICE_OBJECT) Context; device_extension = (PDEVICE_EXTENSION) device_object->DeviceExtension; KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); for (;;) { KeWaitForSingleObject( &device_extension->request_event, Executive, KernelMode, FALSE, NULL ); if (device_extension->terminate_thread) { PsTerminateSystemThread(STATUS_SUCCESS); } while (request = ExInterlockedRemoveHeadList( &device_extension->list_head, &device_extension->list_lock )) { irp = CONTAINING_RECORD(request, IRP, Tail.Overlay.ListEntry); io_stack = IoGetCurrentIrpStackLocation(irp); switch (io_stack->MajorFunction) { case IRP_MJ_READ: system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (system_buffer == NULL) { irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; irp->IoStatus.Information = 0; break; } buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length); if (buffer == NULL) { irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; irp->IoStatus.Information = 0; break; } ZwReadFile( device_extension->file_handle, NULL, NULL, NULL, &irp->IoStatus, buffer, io_stack->Parameters.Read.Length, &io_stack->Parameters.Read.ByteOffset, NULL ); RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length); ExFreePool(buffer); break; case IRP_MJ_WRITE: if ((io_stack->Parameters.Write.ByteOffset.QuadPart + io_stack->Parameters.Write.Length) > device_extension->file_size.QuadPart) { irp->IoStatus.Status = STATUS_INVALID_PARAMETER; irp->IoStatus.Information = 0; } ZwWriteFile( device_extension->file_handle, NULL, NULL, NULL, &irp->IoStatus, MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority), io_stack->Parameters.Write.Length, &io_stack->Parameters.Write.ByteOffset, NULL ); break; case IRP_MJ_DEVICE_CONTROL: switch (io_stack->Parameters.DeviceIoControl.IoControlCode) { case IOCTL_FILE_DISK_OPEN_FILE: SeImpersonateClient(device_extension->security_client_context, NULL); irp->IoStatus.Status = FileDiskOpenFile(device_object, irp); PsRevertToSelf(); break; case IOCTL_FILE_DISK_CLOSE_FILE: irp->IoStatus.Status = FileDiskCloseFile(device_object, irp); break; default: irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } break; default: irp->IoStatus.Status = STATUS_DRIVER_INTERNAL_ERROR; } IoCompleteRequest( irp, (CCHAR) (NT_SUCCESS(irp->IoStatus.Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT) ); } } }