[ext2fs] improve error reporting

* Also clean up VDS error messages
This commit is contained in:
Pete Batard 2019-05-02 15:41:42 +01:00
parent 5f9e65707f
commit 5ae6e4f494
No known key found for this signature in database
GPG Key ID: 38E0CF5E69EDD671
6 changed files with 64 additions and 53 deletions

View File

@ -1363,8 +1363,10 @@ static BOOL ClearPartition(HANDLE hDrive, LARGE_INTEGER offset, DWORD size)
if (buffer == NULL)
return FALSE;
if (!SetFilePointerEx(hDrive, offset, NULL, FILE_BEGIN))
if (!SetFilePointerEx(hDrive, offset, NULL, FILE_BEGIN)) {
free(buffer);
return FALSE;
}
r = WriteFileWithRetry(hDrive, buffer, size, &size, WRITE_RETRIES);
free(buffer);

View File

@ -1,2 +1,3 @@
[*]
indent_style = tab
tab_width = 8

View File

@ -31,6 +31,7 @@
#include "msapi_utf8.h"
extern char* NtStatusError(NTSTATUS Status);
static DWORD LastWinError = 0;
PF_TYPE_DECL(NTAPI, ULONG, RtlNtStatusToDosError, (NTSTATUS));
PF_TYPE_DECL(NTAPI, NTSTATUS, NtClose, (HANDLE));
@ -95,7 +96,7 @@ io_manager nt_io_manager(void)
typedef struct {
ULONG WinError;
int errnocode;
}ERROR_ENTRY;
} ERROR_ENTRY;
static ERROR_ENTRY ErrorTable[] = {
{ ERROR_INVALID_FUNCTION, EINVAL },
@ -149,6 +150,7 @@ static unsigned _MapDosError(IN ULONG WinError)
{
int i;
LastWinError = WinError;
for (i = 0; i < (sizeof(ErrorTable)/sizeof(ErrorTable[0])); ++i) {
if (WinError == ErrorTable[i].WinError) {
return ErrorTable[i].errnocode;
@ -171,6 +173,12 @@ static __inline unsigned _MapNtStatus(IN NTSTATUS Status)
return (pfRtlNtStatusToDosError == NULL) ? EFAULT: _MapDosError(pfRtlNtStatusToDosError(Status));
}
// Return the last Windows Error
DWORD ext2_last_winerror(DWORD default_error)
{
return ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | (LastWinError ? LastWinError : default_error);
}
//
// Helper functions
//
@ -201,7 +209,6 @@ static NTSTATUS _OpenNtName(IN PCSTR Name, IN BOOLEAN Readonly, OUT PHANDLE Hand
&ObjectAttributes, &IoStatusBlock, FILE_SHARE_WRITE | FILE_SHARE_READ,
FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status)) {
uprintf("_OpenNtName: [%x] %s", Status, NtStatusError(Status));
// Maybe was just mounted? wait 0.5 sec and retry.
LARGE_INTEGER Interval;
Interval.QuadPart = -5000000; // 0.5 sec. from now
@ -339,7 +346,9 @@ static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE H
CHAR NormalizedDeviceName[512];
NTSTATUS Status;
LastWinError = 0;
if (Name == NULL) {
LastWinError = ERROR_INVALID_PARAMETER;
if (ARGUMENT_PRESENT(Errno))
*Errno = ENOENT;
return FALSE;
@ -351,6 +360,7 @@ static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE H
} else {
Name = _NormalizeDeviceName(Name, NormalizedDeviceName);
if (Name == NULL) {
LastWinError = ERROR_INVALID_PARAMETER;
if (ARGUMENT_PRESENT(Errno))
*Errno = ENOENT;
return FALSE;
@ -368,7 +378,7 @@ static BOOLEAN _Ext2OpenDevice(IN PCSTR Name, IN BOOLEAN ReadOnly, OUT PHANDLE H
return TRUE;
}
static BOOLEAN _BlockIo(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN OUT PCHAR Buffer, IN BOOLEAN Read, OUT unsigned* Errno)
static BOOLEAN _BlockIo(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN OUT PCHAR Buffer, IN BOOLEAN Read, OUT errcode_t *Errno OPTIONAL)
{
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS Status = STATUS_DLL_NOT_FOUND;
@ -379,6 +389,7 @@ static BOOLEAN _BlockIo(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Byte
assert((Bytes % 512) == 0);
assert((Offset.LowPart % 512) == 0);
LastWinError = 0;
// Perform io
if(Read) {
Status = pfNtReadFile(Handle, NULL, NULL, NULL,
@ -389,22 +400,23 @@ static BOOLEAN _BlockIo(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Byte
}
out:
if (NT_SUCCESS(Status)) {
*Errno = 0;
return TRUE;
if (!NT_SUCCESS(Status)) {
if (ARGUMENT_PRESENT(Errno))
*Errno = _MapNtStatus(Status);
return FALSE;
}
*Errno = _MapNtStatus(Status);
return FALSE;
if (ARGUMENT_PRESENT(Errno))
*Errno = 0;
return TRUE;
}
static BOOLEAN _RawWrite(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, OUT const CHAR* Buffer, OUT unsigned* Errno)
static BOOLEAN _RawWrite(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, OUT const CHAR* Buffer, OUT errcode_t* Errno)
{
return _BlockIo(Handle, Offset, Bytes, (PCHAR)Buffer, FALSE, Errno);
}
static BOOLEAN _RawRead(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN PCHAR Buffer, OUT unsigned* Errno)
static BOOLEAN _RawRead(IN HANDLE Handle, IN LARGE_INTEGER Offset, IN ULONG Bytes, IN PCHAR Buffer, OUT errcode_t* Errno)
{
return _BlockIo(Handle, Offset, Bytes, Buffer, TRUE, Errno);
}
@ -425,13 +437,14 @@ static BOOLEAN _SetPartType(IN HANDLE Handle, IN UCHAR Type)
//
errcode_t ext2fs_check_if_mounted(const char *file, int *mount_flags)
{
errcode_t errcode = 0;
HANDLE h;
BOOLEAN Readonly;
*mount_flags = 0;
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL))
return 0;
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode))
return errcode;
*mount_flags &= _IsMounted(h) ? EXT2_MF_MOUNTED : 0;
_CloseDisk(h);
@ -450,14 +463,13 @@ errcode_t ext2fs_check_mount_point(const char *file, int *mount_flags, char *mtp
// different removable devices (e.g. UFD) may be remounted under the same path.
errcode_t ext2fs_get_device_size2(const char *file, int blocksize, blk64_t *retblocks)
{
errcode_t errcode;
__int64 fs_size = 0;
HANDLE h;
BOOLEAN Readonly;
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, NULL)) {
uprintf("FAILED TO OPEN '%s'", file);
return EACCES;
}
if (!_Ext2OpenDevice(file, TRUE, &h, &Readonly, &errcode))
return errcode;
_GetDeviceSize(h, &fs_size);
_CloseDisk(h);
@ -604,7 +616,7 @@ static errcode_t nt_read_blk(io_channel channel, unsigned long block, int count,
ULONG size;
LARGE_INTEGER offset;
PNT_PRIVATE_DATA nt_data = NULL;
unsigned errcode = 0;
errcode_t errcode = 0;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;
@ -653,7 +665,7 @@ static errcode_t nt_write_blk(io_channel channel, unsigned long block, int count
ULONG write_size;
LARGE_INTEGER offset;
PNT_PRIVATE_DATA nt_data = NULL;
unsigned errcode = 0;
errcode_t errcode = 0;
EXT2_CHECK_MAGIC(channel, EXT2_ET_MAGIC_IO_CHANNEL);
nt_data = (PNT_PRIVATE_DATA) channel->private_data;

View File

@ -244,6 +244,8 @@ static BOOLEAN __stdcall ChkdskCallback(FILE_SYSTEM_CALLBACK_COMMAND Command, DW
/*
* Converts an UTF-8 label to a valid FAT/NTFS one
* TODO: Use IVdsService::QueryFileSystemTypes -> VDS_FILE_SYSTEM_TYPE_PROP
* to get the list of unauthorised and max length for each FS.
*/
static void ToValidLabel(char* Label, BOOL bFAT)
{
@ -877,7 +879,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
// Figure out the volume size and block size
r = ext2fs_get_device_size2(volume_name, KB, &size);
if ((r != 0) || (size == 0)) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_READ_FAULT;
FormatStatus = ext2_last_winerror(ERROR_READ_FAULT);
uprintf("Could not read device size: %s", error_message(r));
goto out;
}
@ -922,7 +924,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
// Now that we have set our base features, initialize a virtual superblock
r = ext2fs_initialize(volume_name, EXT2_FLAG_EXCLUSIVE | EXT2_FLAG_64BITS, &features, manager, &ext2fs);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_DATA;
FormatStatus = ext2_last_winerror(ERROR_INVALID_DATA);
uprintf("Could not initialize %s features: %s", FSName, error_message(r));
goto out;
}
@ -933,7 +935,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
r = io_channel_write_blk64(ext2fs->io, 0, 16, buf);
safe_free(buf);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("Could not zero %s superblock area: %s", FSName, error_message(r));
goto out;
}
@ -951,7 +953,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
r = ext2fs_allocate_tables(ext2fs);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_INVALID_DATA;
FormatStatus = ext2_last_winerror(ERROR_INVALID_DATA);
uprintf("Could not allocate %s tables: %s", FSName, error_message(r));
goto out;
}
@ -973,7 +975,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
* EXT2_BLOCK_SIZE(ext2fs->super), EXT2_BLOCK_SIZE(ext2fs->super));
r = ext2fs_zero_blocks2(ext2fs, cur, count, &cur, &count);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("\r\nCould not zero inode set at position %llu (%d blocks): %s", cur, count, error_message(r));
goto out;
}
@ -983,14 +985,14 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
// Create root and lost+found dirs
r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_DIR_NOT_ROOT;
FormatStatus = ext2_last_winerror(ERROR_DIR_NOT_ROOT);
uprintf("Failed to create %s root dir: %s", FSName, error_message(r));
goto out;
}
ext2fs->umask = 077;
r = ext2fs_mkdir(ext2fs, EXT2_ROOT_INO, 0, "lost+found");
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_DIR_NOT_ROOT;
FormatStatus = ext2_last_winerror(ERROR_DIR_NOT_ROOT);
uprintf("Failed to create %s 'lost+found' dir: %s", FSName, error_message(r));
goto out;
}
@ -1002,14 +1004,14 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
r = ext2fs_mark_inode_bitmap2(ext2fs->inode_map, EXT2_BAD_INO);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("Could not set inode bitmaps: %s", error_message(r));
goto out;
}
ext2fs_inode_alloc_stats(ext2fs, EXT2_BAD_INO, 1);
r = ext2fs_update_bb_inode(ext2fs, NULL);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("Could not set inode stats: %s", error_message(r));
goto out;
}
@ -1025,7 +1027,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
r = ext2fs_add_journal_inode(ext2fs, journal_size, EXT2_MKJOURNAL_NO_MNT_CHECK | ((Flags & FP_QUICK) ? EXT2_MKJOURNAL_LAZYINIT : 0));
uprintfs("\r\n");
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("Could not create %s journal: %s", FSName, error_message(r));
goto out;
}
@ -1034,7 +1036,7 @@ BOOL FormatExtFs(DWORD DriveIndex, DWORD PartitionIndex, DWORD BlockSize, LPCSTR
// Finally we can call close() to get the file system gets created
r = ext2fs_close(ext2fs);
if (r != 0) {
FormatStatus = ERROR_SEVERITY_ERROR | FAC(FACILITY_STORAGE) | ERROR_WRITE_FAULT;
FormatStatus = ext2_last_winerror(ERROR_WRITE_FAULT);
uprintf("Could not create %s volume: %s", FSName, error_message(r));
goto out;
}
@ -2594,6 +2596,8 @@ DWORD WINAPI FormatThread(void* param)
hLogicalVolume = INVALID_HANDLE_VALUE;
// VDS wants us to unlock the phys
// TODO: IVdsDiskOnline::Offline? -> NOPE, NO_GO for removable media
// TODO: IVdsService::Refresh()? IVdsHwProvider::Reenumerate()??
if (use_vds)
safe_unlockclose(hPhysicalDrive);

View File

@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDD_DIALOG DIALOGEX 12, 12, 232, 326
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_ACCEPTFILES
CAPTION "Rufus 3.6.1529"
CAPTION "Rufus 3.6.1530"
FONT 9, "Segoe UI Symbol", 400, 0, 0x0
BEGIN
LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP
@ -394,8 +394,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,6,1529,0
PRODUCTVERSION 3,6,1529,0
FILEVERSION 3,6,1530,0
PRODUCTVERSION 3,6,1530,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -413,13 +413,13 @@ BEGIN
VALUE "Comments", "https://akeo.ie"
VALUE "CompanyName", "Akeo Consulting"
VALUE "FileDescription", "Rufus"
VALUE "FileVersion", "3.6.1529"
VALUE "FileVersion", "3.6.1530"
VALUE "InternalName", "Rufus"
VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)"
VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html"
VALUE "OriginalFilename", "rufus-3.6.exe"
VALUE "ProductName", "Rufus"
VALUE "ProductVersion", "3.6.1529"
VALUE "ProductVersion", "3.6.1530"
END
END
BLOCK "VarFileInfo"

View File

@ -1,6 +1,6 @@
/*
* Rufus: The Reliable USB Formatting Utility
* Standard User I/O Routines (logging, status, etc.)
* Standard User I/O Routines (logging, status, error, etc.)
* Copyright © 2011-2019 Pete Batard <pete@akeo.ie>
*
* This program is free software: you can redistribute it and/or modify
@ -375,13 +375,11 @@ static const char *GetVdsError(DWORD error_code)
case 0x8004250F: // VDS_E_BAD_PNP_MESSAGE
return "The PNP service sent a corrupted notification to the provider.";
case 0x80042510: // VDS_E_NO_PNP_DISK_ARRIVE
return "No disk arrival notification was received.";
case 0x80042511: // VDS_E_NO_PNP_VOLUME_ARRIVE
return "No volume arrival notification was received.";
return "No disk/volume arrival notification was received.";
case 0x80042512: // VDS_E_NO_PNP_DISK_REMOVE
return "No disk removal notification was received.";
case 0x80042513: // VDS_E_NO_PNP_VOLUME_REMOVE
return "No volume removal notification was received.";
return "No disk/volume removal notification was received.";
case 0x80042514: // VDS_E_PROVIDER_EXITING
return "The provider is exiting.";
case 0x00042517: // VDS_S_NO_NOTIFICATION
@ -401,7 +399,7 @@ static const char *GetVdsError(DWORD error_code)
case 0x8004253F: // VDS_E_DISK_LAYOUT_PARTITIONS_TOO_SMALL
return "The disk layout contains partitions which are less than the minimum required size.";
case 0x80042540: // VDS_E_DISK_IO_FAILING
return "The IO to the disk is failing.";
return "The I/O to the disk is failing.";
case 0x80042543: // VDS_E_GPT_ATTRIBUTES_INVALID
return "Invalid GPT attributes were specified.";
case 0x8004254D: // VDS_E_UNEXPECTED_DISK_LAYOUT_CHANGE
@ -473,7 +471,7 @@ static const char *GetVdsError(DWORD error_code)
case 0x80042572: // VDS_E_PROVIDER_INTERNAL_ERROR
return "An internal error has occurred in the provider.";
case 0x80042575: // VDS_E_UNRECOVERABLE_PROVIDER_ERROR
return "An unrecoverable error occurred in a provider.";
return "An unrecoverable error occurred in the provider.";
case 0x80042576: // VDS_E_VOLUME_HIDDEN
return "Cannot assign a mount point to a hidden volume.";
case 0x00042577: // VDS_S_DISMOUNT_FAILED
@ -536,15 +534,12 @@ static const char *GetVdsError(DWORD error_code)
case 0x00042809: // VDS_S_DISK_DISMOUNT_FAILED
return "One or more of the volumes on the disk could not be mounted/dismounted.";
case 0x8004280A: // VDS_E_DISK_IS_OFFLINE
return "The operation cannot be performed on a disk that is offline.";
case 0x8004280B: // VDS_E_DISK_IS_READ_ONLY
return "The operation cannot be performed on a disk that is read-only.";
return "The operation cannot be performed on a disk that is offline or read-only.";
case 0x8004280C: // VDS_E_PAGEFILE_DISK
return "The operation cannot be performed on a disk that contains a pagefile volume.";
case 0x8004280D: // VDS_E_HIBERNATION_FILE_DISK
return "The operation cannot be performed on a disk that contains a hibernation file volume.";
case 0x8004280E: // VDS_E_CRASHDUMP_DISK
return "The operation cannot be performed on a disk that contains a crashdump file volume.";
return "The operation cannot be performed on a disk that contains a pagefile, hibernation or crashdump volume.";
case 0x8004280F: // VDS_E_UNABLE_TO_FIND_SYSTEM_DISK
return "A system error occurred while retrieving the system disk information.";
case 0x80042810: // VDS_E_INCORRECT_SYSTEM_VOLUME_EXTENT_INFO
@ -564,19 +559,16 @@ static const char *GetVdsError(DWORD error_code)
case 0x8004290F: // VDS_E_DELETE_WITH_CRITICAL
return "Delete is not allowed on a critical volume.";
case 0x80042910: // VDS_E_CLEAN_WITH_DATA
return "The FORCE parameter MUST be set to TRUE in order to clean a disk that contains a data volume.";
case 0x80042911: // VDS_E_CLEAN_WITH_OEM
return "The FORCE parameter MUST be set to TRUE in order to clean a disk that contains an OEM volume.";
return "The FORCE parameter MUST be set to TRUE in order to clean a disk that contains a data or OEM volume.";
case 0x80042912: // VDS_E_CLEAN_WITH_CRITICAL
return "Clean is not allowed on a critical disk.";
case 0x80042913: // VDS_E_FORMAT_CRITICAL
return "Format is not allowed on a critical volume.";
case 0x80042914: // VDS_E_NTFS_FORMAT_NOT_SUPPORTED
return "The NTFS file system format is not supported on this volume.";
case 0x80042915: // VDS_E_FAT32_FORMAT_NOT_SUPPORTED
return "The FAT32 file system format is not supported on this volume.";
case 0x80042916: // VDS_E_FAT_FORMAT_NOT_SUPPORTED
return "The FAT file system format is not supported on this volume.";
return "The requested file system format is not supported on this volume.";
case 0x80042917: // VDS_E_FORMAT_NOT_SUPPORTED
return "The volume is not formattable.";
case 0x80042918: // VDS_E_COMPRESSION_NOT_SUPPORTED