static void mount_item_proc(mount_ctx *mnt) { dev_hook *hook; int resl; hook = mnt->hook; resl = dc_mount_device(hook->dev_name, NULL, 0); if ( (resl != ST_RW_ERR) && (resl != ST_MEDIA_CHANGED) && (resl != ST_NO_MEDIA) ) { hook->mnt_probed = 1; } if (resl != ST_OK) { if (lock_inc(&hook->mnt_probe_cnt) > MAX_MNT_PROBES) { hook->mnt_probed = 1; } } if (hook->flags & F_ENABLED) { io_read_write_irp(hook, mnt->irp); } else { if (IS_DEVICE_BLOCKED(hook) != 0) { dc_release_irp(hook, mnt->irp, STATUS_ACCESS_DENIED); } else { dc_forward_irp(hook, mnt->irp); } } mm_pool_free(mnt); }
NTSTATUS dc_probe_mount(dev_hook *hook, PIRP irp) { mount_ctx *mnt; if ( (mnt = mm_pool_alloc(sizeof(mount_ctx))) == NULL ) { return dc_release_irp(hook, irp, STATUS_INSUFFICIENT_RESOURCES); } IoMarkIrpPending(irp); mnt->irp = irp; mnt->hook = hook; ExInitializeWorkItem(&mnt->wrk_item, mount_item_proc, mnt); ExQueueWorkItem(&mnt->wrk_item, DelayedWorkQueue); return STATUS_PENDING; }
NTSTATUS dc_io_control_irp(dev_hook *hook, PIRP irp) { PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp); ULONG iocode = irp_sp->Parameters.DeviceIoControl.IoControlCode; if (iocode == IOCTL_DISK_GET_LENGTH_INFO || iocode == IOCTL_DISK_GET_PARTITION_INFO || iocode == IOCTL_DISK_GET_PARTITION_INFO_EX || iocode == IOCTL_CDROM_GET_DRIVE_GEOMETRY_EX || IS_VERIFY_IOCTL(iocode) ) { IoCopyCurrentIrpStackLocationToNext(irp); IoSetCompletionRoutine(irp, dc_ioctl_complete, NULL, TRUE, TRUE, TRUE); return IoCallDriver(hook->orig_dev, irp); } if (hook->flags & F_ENABLED) { if (iocode == IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES) return dc_trim_irp(hook, irp); if (iocode == IOCTL_VOLUME_UPDATE_PROPERTIES) return dc_release_irp(hook, irp, dc_update_volume(hook)); } return dc_forward_irp(hook, irp); }
NTSTATUS dc_power_irp(dev_hook *hook, PIRP irp) { pw_irp_ctx *pwc; if (KeGetCurrentIrql() == PASSIVE_LEVEL) { return dc_process_power_irp(hook, irp); } if ( (pwc = mm_alloc(sizeof(pw_irp_ctx), 0)) == NULL ) { PoStartNextPowerIrp(irp); return dc_release_irp(hook, irp, STATUS_INSUFFICIENT_RESOURCES); } pwc->hook = hook; pwc->irp = irp; IoMarkIrpPending(irp); ExInitializeWorkItem(&pwc->wrk_item, dc_power_irp_worker, pwc); ExQueueWorkItem(&pwc->wrk_item, DelayedWorkQueue); return STATUS_PENDING; }
static NTSTATUS dc_trim_irp(dev_hook *hook, PIRP irp) { PIO_STACK_LOCATION irp_sp = IoGetCurrentIrpStackLocation(irp); PDEVICE_MANAGE_DATA_SET_ATTRIBUTES p_set = irp->AssociatedIrp.SystemBuffer; u32 length = irp_sp->Parameters.DeviceIoControl.InputBufferLength; u64 offset, rnglen; PDEVICE_DATA_SET_RANGE range; PDEVICE_MANAGE_DATA_SET_ATTRIBUTES n_set; u64 off1, off2; u64 len1, len2; u32 i; if ( (length < sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES)) || (p_set->Action != DeviceDsmAction_Trim) || (length < d64(p_set->DataSetRangesOffset) + d64(p_set->DataSetRangesLength)) ) { return dc_forward_irp(hook, irp); } if (dc_conf_flags & CONF_DISABLE_TRIM) { return dc_release_irp(hook, irp, STATUS_SUCCESS); } if ( (n_set = mm_pool_alloc(TRIM_BUFF_MAX(p_set))) == NULL ) { return dc_release_irp(hook, irp, STATUS_INSUFFICIENT_RESOURCES); } n_set->Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES); n_set->Action = DeviceDsmAction_Trim; n_set->Flags = 0; n_set->ParameterBlockOffset = 0; n_set->ParameterBlockLength = 0; n_set->DataSetRangesOffset = _align(sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), sizeof(DEVICE_DATA_SET_RANGE)); n_set->DataSetRangesLength = 0; if (p_set->Flags & DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE) { if (hook->flags & F_NO_REDIRECT) { TRIM_ADD_RANGE(n_set, hook->head_len, hook->dsk_size - hook->head_len); } else { TRIM_ADD_RANGE(n_set, hook->head_len, LEN_BEFORE_STORAGE(hook)); TRIM_ADD_RANGE(n_set, OFF_END_OF_STORAGE(hook), LEN_AFTER_STORAGE(hook)); } } else { for (i = 0, range = addof(p_set, p_set->DataSetRangesOffset); i < p_set->DataSetRangesLength / sizeof(DEVICE_DATA_SET_RANGE); i++, range++) { if ( (offset = range->StartingOffset) + (rnglen = range->LengthInBytes) > hook->use_size ) { continue; } if (hook->flags & F_NO_REDIRECT) { TRIM_ADD_RANGE(n_set, offset + hook->head_len, min(rnglen, hook->use_size - offset)); continue; } len1 = intersect(&off1, offset, rnglen, hook->head_len, LEN_BEFORE_STORAGE(hook)); len2 = intersect(&off2, offset, rnglen, OFF_END_OF_STORAGE(hook), LEN_AFTER_STORAGE(hook)); TRIM_ADD_RANGE(n_set, off1, len1); TRIM_ADD_RANGE(n_set, off2, len2); } } if (n_set->DataSetRangesLength != 0) { io_hook_ioctl(hook, IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES, n_set, TRIM_BUFF_LENGTH(n_set), NULL, 0); } mm_pool_free(n_set); return dc_release_irp(hook, irp, STATUS_SUCCESS); }