static int dc_ioctl_process(u32 code, dc_ioctl *data) { int resl = ST_ERROR; switch (code) { case DC_CTL_ADD_PASS: { dc_add_password(&data->passw1); resl = ST_OK; } break; case DC_CTL_MOUNT: { resl = dc_mount_device(data->device, &data->passw1, data->flags); if ( (resl == ST_OK) && (dc_conf_flags & CONF_CACHE_PASSWORD) ) { dc_add_password(&data->passw1); } } break; case DC_CTL_MOUNT_ALL: { data->n_mount = dc_mount_all(&data->passw1, data->flags); resl = ST_OK; if ( (data->n_mount != 0) && (dc_conf_flags & CONF_CACHE_PASSWORD) ) { dc_add_password(&data->passw1); } } break; case DC_CTL_UNMOUNT: { resl = dc_unmount_device(data->device, (data->flags & MF_FORCE)); } break; case DC_CTL_CHANGE_PASS: { resl = dc_change_pass(data->device, &data->passw1, &data->passw2); if ( (resl == ST_OK) && (dc_conf_flags & CONF_CACHE_PASSWORD) ) { dc_add_password(&data->passw2); } } break; case DC_CTL_ENCRYPT_START: { resl = dc_encrypt_start(data->device, &data->passw1, &data->crypt); if ( (resl == ST_OK) && (dc_conf_flags & CONF_CACHE_PASSWORD) ) { dc_add_password(&data->passw1); } } break; case DC_CTL_DECRYPT_START: { resl = dc_decrypt_start(data->device, &data->passw1); } break; case DC_CTL_RE_ENC_START: { resl = dc_reencrypt_start(data->device, &data->passw1, &data->crypt); } break; case DC_CTL_ENCRYPT_STEP: { resl = dc_send_sync_packet(data->device, S_OP_ENC_BLOCK, pv(data->crypt.wp_mode)); } break; case DC_CTL_DECRYPT_STEP: { resl = dc_send_sync_packet(data->device, S_OP_DEC_BLOCK, 0); } break; case DC_CTL_SYNC_STATE: { resl = dc_send_sync_packet(data->device, S_OP_SYNC, 0); } break; case DC_CTL_RESOLVE: { while (dc_resolve_link(data->device, data->device, sizeof(data->device)) == ST_OK) { resl = ST_OK; } } break; case DC_FORMAT_START: { resl = dc_format_start(data->device, &data->passw1, &data->crypt); if ( (resl == ST_OK) && (dc_conf_flags & CONF_CACHE_PASSWORD) ) { dc_add_password(&data->passw1); } } break; case DC_FORMAT_STEP: { resl = dc_format_step(data->device, data->crypt.wp_mode); } break; case DC_FORMAT_DONE: { resl = dc_format_done(data->device); } break; } return resl; }
/* this routine process unmounting the device unmount options: UM_NOFSCTL - unmount without reporting to FS UM_FORCE - force unmounting */ int dc_process_unmount(dev_hook *hook, int opt) { IO_STATUS_BLOCK iosb; NTSTATUS status; HANDLE h_dev = NULL; int locked = 0; int resl; DbgMsg("dc_process_unmount, dev=%ws\n", hook->dev_name); if ((hook->flags & F_ENABLED) == 0) { return ST_NO_MOUNT; } wait_object_infinity(&hook->busy_lock); if ((hook->flags & F_ENABLED) == 0) { resl = ST_NO_MOUNT; goto cleanup; } do { if (hook->flags & F_FORMATTING) { dc_format_done(hook->dev_name); } if ( !(hook->flags & F_SYSTEM) && !(opt & MF_NOFSCTL) ) { h_dev = io_open_device(hook->dev_name); if ( (h_dev == NULL) && !(opt & MF_FORCE) ) { resl = ST_LOCK_ERR; break; } if (h_dev != NULL) { status = ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); if ( (NT_SUCCESS(status) == FALSE) && !(opt & MF_FORCE) ) { resl = ST_LOCK_ERR; break; } locked = (NT_SUCCESS(status) != FALSE); ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); } } if ((opt & MF_NOSYNC) == 0) { // temporary disable IRP processing hook->flags |= F_DISABLE; // wait for pending IRPs completion if ((opt & MF_NOWAIT_IO) == 0) { while (hook->remove_lock.Common.IoCount > 1) dc_delay(20); } if (hook->flags & F_SYNC) { // send signal to syncronous mode thread dc_send_sync_packet(hook->dev_name, S_OP_FINALIZE, 0); } } hook->flags &= ~F_CLEAR_ON_UNMOUNT; hook->use_size = hook->dsk_size; hook->tmp_size = 0; hook->mnt_flags = 0; resl = ST_OK; // increment mount changes counter lock_inc(&hook->chg_mount); // free encryption key if (hook->dsk_key != NULL) { mm_secure_free(hook->dsk_key); hook->dsk_key = NULL; } if ( !(opt & MF_NOSYNC) ) { /* enable IRP processing */ hook->flags &= ~F_DISABLE; } } while (0); if (h_dev != NULL) { if (locked != 0) { ZwFsControlFile(h_dev, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); } ZwClose(h_dev); } cleanup: KeReleaseMutex(&hook->busy_lock, FALSE); return resl; }
int dc_format_step(wchar_t *dev_name, int wp_mode) { dev_hook *hook = NULL; u8 *buff; int resl; u64 offs; u32 size; do { if ( (hook = dc_find_hook(dev_name)) == NULL ) { resl = ST_NF_DEVICE; break; } wait_object_infinity(&hook->busy_lock); if ( !(hook->flags & F_FORMATTING) ) { resl = ST_ERROR; break; } offs = hook->tmp_size; buff = hook->tmp_buff; size = d32(min(hook->dsk_size - offs, ENC_BLOCK_SIZE)); if (size == 0) { dc_format_done(dev_name); resl = ST_FINISHED; break; } if (hook->crypt.wp_mode != wp_mode) { dc_wipe_free(&hook->wp_ctx); resl = dc_wipe_init( &hook->wp_ctx, hook, ENC_BLOCK_SIZE, wp_mode, hook->crypt.cipher_id); if (resl == ST_OK) { hook->crypt.wp_mode = d8(wp_mode); } else { dc_wipe_init(&hook->wp_ctx, hook, ENC_BLOCK_SIZE, WP_NONE, 0); hook->crypt.wp_mode = WP_NONE; } } /* wipe sectors */ dc_wipe_process(&hook->wp_ctx, offs, size); /* zero buffer */ memset(buff, 0, size); /* encrypt buffer with temporary key */ cp_fast_encrypt(buff, buff, size, offs, hook->tmp_key); /* write pseudo-random data to device */ resl = io_hook_rw(hook, buff, size, offs, 0); if ( (resl == ST_OK) || (resl == ST_RW_ERR) ) { hook->tmp_size += size; } if ( (resl == ST_MEDIA_CHANGED) || (resl == ST_NO_MEDIA) ) { dc_process_unmount(hook, MF_NOFSCTL); resl = ST_FINISHED; } } while (0); if (hook != NULL) { KeReleaseMutex(&hook->busy_lock, FALSE); dc_deref_hook(hook); } return resl; }