/* A filedisk's thread routine. */ static VOID STDCALL WvFilediskThread_(IN OUT WVL_SP_THREAD_ITEM item) { WV_SP_FILEDISK_T filedisk = CONTAINING_RECORD( item, WV_S_FILEDISK_T, Thread[0].Main ); LARGE_INTEGER timeout; WVL_SP_THREAD_ITEM work_item; PLIST_ENTRY irp_item; /* Wake up at least every 30 seconds. */ timeout.QuadPart = -300000000LL; while ( (filedisk->Thread->State == WvlThreadStateStarted) || (filedisk->Thread->State == WvlThreadStateStopping) ) { /* Wait for the work signal or the timeout. */ KeWaitForSingleObject( &filedisk->Thread->Signal, Executive, KernelMode, FALSE, &timeout ); /* Reset the work signal. */ KeResetEvent(&filedisk->Thread->Signal); /* Process work items. One of these might be a stopper. */ while (work_item = WvlThreadGetItem(filedisk->Thread)) work_item->Func(work_item); /* Process SCSI IRPs. */ while (irp_item = ExInterlockedRemoveHeadList( filedisk->Irps, filedisk->IrpsLock )) { PIRP irp; PIO_STACK_LOCATION io_stack_loc; irp = CONTAINING_RECORD(irp_item, IRP, Tail.Overlay.ListEntry); io_stack_loc = IoGetCurrentIrpStackLocation(irp); if (io_stack_loc->MajorFunction != IRP_MJ_SCSI) { DBG("Non-SCSI IRP!\n"); continue; } WvlDiskScsi(filedisk->Dev->Self, irp, filedisk->disk); } /* Are we finished? */ if (filedisk->Thread->State == WvlThreadStateStopping) filedisk->Thread->State = WvlThreadStateStopped; } /* while thread started or stopping. */ /* Close any open file handle. */ if (filedisk->file) ZwClose(filedisk->file); return; }
/* Handle an IRP. */ static NTSTATUS WvFilediskIrpDispatch( IN PDEVICE_OBJECT dev_obj, IN PIRP irp ) { PIO_STACK_LOCATION io_stack_loc; WV_SP_FILEDISK_T filedisk; NTSTATUS status; io_stack_loc = IoGetCurrentIrpStackLocation(irp); filedisk = dev_obj->DeviceExtension; switch (io_stack_loc->MajorFunction) { case IRP_MJ_SCSI: return WvlDiskScsi(dev_obj, irp, filedisk->disk); case IRP_MJ_PNP: status = WvlDiskPnp(dev_obj, irp, filedisk->disk); /* Note any state change. */ filedisk->Dev->OldState = filedisk->disk->OldState; filedisk->Dev->State = filedisk->disk->State; if (filedisk->Dev->State == WvlDiskStateNotStarted) { if (!filedisk->Dev->BusNode.Linked) { /* Unlinked _and_ deleted */ DBG("Deleting filedisk PDO: %p", dev_obj); IoDeleteDevice(dev_obj); } } return status; case IRP_MJ_DEVICE_CONTROL: return WvlDiskDevCtl( filedisk->disk, irp, io_stack_loc->Parameters.DeviceIoControl.IoControlCode ); case IRP_MJ_POWER: return WvlDiskPower(dev_obj, irp, filedisk->disk); case IRP_MJ_CREATE: case IRP_MJ_CLOSE: /* Always succeed with nothing to do. */ return WvlIrpComplete(irp, 0, STATUS_SUCCESS); case IRP_MJ_SYSTEM_CONTROL: return WvlDiskSysCtl(dev_obj, irp, filedisk->disk); default: DBG("Unhandled IRP_MJ_*: %d\n", io_stack_loc->MajorFunction); } return WvlIrpComplete(irp, 0, STATUS_NOT_SUPPORTED); }
NTSTATUS STDCALL WvDiskScsi(IN WV_SP_DEV_T dev, IN PIRP irp, IN UCHAR c) { WVL_SP_DISK_T disk = disk__get_ptr(dev); return WvlDiskScsi(dev->Self, irp, disk); }