[BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.9 (#4417)

v1.7.9 (2021-10-02):

- Fixed deadlock when mounting on Windows 11
- Added support for BitLocker-encrypted volumes
- Improved filename checks when renaming or creating hard links
- Miscellaneous bug fixes
This commit is contained in:
Vincent Franchomme 2022-04-28 21:35:58 +02:00 committed by Hermès BÉLUSCA - MAÏTO
parent 08d1009892
commit f5556fdc10
14 changed files with 317 additions and 73 deletions

View file

@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico"
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,8,0 FILEVERSION 1,7,9,0
PRODUCTVERSION 1,7,8,0 PRODUCTVERSION 1,7,9,0
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -78,12 +78,12 @@ BEGIN
BLOCK "080904b0" BLOCK "080904b0"
BEGIN BEGIN
VALUE "FileDescription", "WinBtrfs shell extension" VALUE "FileDescription", "WinBtrfs shell extension"
VALUE "FileVersion", "1.7.8" VALUE "FileVersion", "1.7.9"
VALUE "InternalName", "btrfs" VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "OriginalFilename", "shellbtrfs.dll"
VALUE "ProductName", "WinBtrfs" VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.7.8" VALUE "ProductVersion", "1.7.9"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,8,0 FILEVERSION 1,7,9,0
PRODUCTVERSION 1,7,8,0 PRODUCTVERSION 1,7,9,0
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -68,12 +68,12 @@ BEGIN
BLOCK "080904b0" BLOCK "080904b0"
BEGIN BEGIN
VALUE "FileDescription", "Btrfs utility DLL" VALUE "FileDescription", "Btrfs utility DLL"
VALUE "FileVersion", "1.7.8" VALUE "FileVersion", "1.7.9"
VALUE "InternalName", "ubtrfs" VALUE "InternalName", "ubtrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
VALUE "OriginalFilename", "ubtrfs.dll" VALUE "OriginalFilename", "ubtrfs.dll"
VALUE "ProductName", "WinBtrfs" VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.7.8" VALUE "ProductVersion", "1.7.9"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -29,6 +29,8 @@
#define BLAKE2_INLINE inline #define BLAKE2_INLINE inline
#endif #endif
#define NATIVE_LITTLE_ENDIAN
static BLAKE2_INLINE uint32_t load32( const void *src ) static BLAKE2_INLINE uint32_t load32( const void *src )
{ {
#if defined(NATIVE_LITTLE_ENDIAN) #if defined(NATIVE_LITTLE_ENDIAN)

View file

@ -4389,10 +4389,8 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
TRACE("(%p, %p)\n", DeviceObject, Irp); TRACE("(%p, %p)\n", DeviceObject, Irp);
if (DeviceObject != master_devobj) { if (DeviceObject != master_devobj)
Status = STATUS_INVALID_DEVICE_REQUEST; return STATUS_INVALID_DEVICE_REQUEST;
goto exit;
}
IrpSp = IoGetCurrentIrpStackLocation(Irp); IrpSp = IoGetCurrentIrpStackLocation(Irp);
DeviceToMount = IrpSp->Parameters.MountVolume.DeviceObject; DeviceToMount = IrpSp->Parameters.MountVolume.DeviceObject;
@ -4412,7 +4410,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (!not_pnp) { if (!not_pnp) {
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
goto exit2; goto exit;
} }
} else { } else {
PDEVICE_OBJECT pdo; PDEVICE_OBJECT pdo;
@ -4451,7 +4449,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (!vde || vde->type != VCB_TYPE_VOLUME) { if (!vde || vde->type != VCB_TYPE_VOLUME) {
vde = NULL; vde = NULL;
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
goto exit2; goto exit;
} }
} }
@ -4472,11 +4470,13 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (pdode->num_children == 0) { if (pdode->num_children == 0) {
ERR("error - number of devices is zero\n"); ERR("error - number of devices is zero\n");
Status = STATUS_INTERNAL_ERROR; Status = STATUS_INTERNAL_ERROR;
goto exit2; ExReleaseResourceLite(&pdode->child_lock);
goto exit;
} }
Status = STATUS_DEVICE_NOT_READY; Status = STATUS_DEVICE_NOT_READY;
goto exit2; ExReleaseResourceLite(&pdode->child_lock);
goto exit;
} }
le = le2; le = le2;
@ -4485,6 +4485,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (pdode->num_children == 0 || pdode->children_loaded == 0) { if (pdode->num_children == 0 || pdode->children_loaded == 0) {
ERR("error - number of devices is zero\n"); ERR("error - number of devices is zero\n");
Status = STATUS_INTERNAL_ERROR; Status = STATUS_INTERNAL_ERROR;
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
@ -4519,6 +4520,10 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
ERR("IoCreateDevice returned %08lx\n", Status); ERR("IoCreateDevice returned %08lx\n", Status);
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
if (pdode)
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
@ -4558,18 +4563,29 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
else if (Irp->Tail.Overlay.Thread) else if (Irp->Tail.Overlay.Thread)
IoSetHardErrorOrVerifyDevice(Irp, readobj); IoSetHardErrorOrVerifyDevice(Irp, readobj);
if (pdode)
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
if (!vde && Vcb->superblock.num_devices > 1) { if (!vde && Vcb->superblock.num_devices > 1) {
ERR("cannot mount multi-device FS with non-PNP device\n"); ERR("cannot mount multi-device FS with non-PNP device\n");
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
if (pdode)
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
Status = registry_load_volume_options(Vcb); Status = registry_load_volume_options(Vcb);
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
ERR("registry_load_volume_options returned %08lx\n", Status); ERR("registry_load_volume_options returned %08lx\n", Status);
if (pdode)
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
@ -4579,9 +4595,15 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
if (pdode && pdode->children_loaded < pdode->num_children && (!Vcb->options.allow_degraded || !finished_probing || degraded_wait)) { if (pdode && pdode->children_loaded < pdode->num_children && (!Vcb->options.allow_degraded || !finished_probing || degraded_wait)) {
ERR("could not mount as %I64u device(s) missing\n", pdode->num_children - pdode->children_loaded); ERR("could not mount as %I64u device(s) missing\n", pdode->num_children - pdode->children_loaded);
Status = STATUS_DEVICE_NOT_READY; Status = STATUS_DEVICE_NOT_READY;
ExReleaseResourceLite(&pdode->child_lock);
goto exit; goto exit;
} }
if (pdode) {
// Windows holds DeviceObject->DeviceLock, guaranteeing that mount_vol is serialized
ExReleaseResourceLite(&pdode->child_lock);
}
if (Vcb->options.ignore) { if (Vcb->options.ignore) {
TRACE("ignoring volume\n"); TRACE("ignoring volume\n");
Status = STATUS_UNRECOGNIZED_VOLUME; Status = STATUS_UNRECOGNIZED_VOLUME;
@ -5014,10 +5036,6 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
ExInitializeResourceLite(&Vcb->send_load_lock); ExInitializeResourceLite(&Vcb->send_load_lock);
exit: exit:
if (pdode)
ExReleaseResourceLite(&pdode->child_lock);
exit2:
if (Vcb) { if (Vcb) {
ExReleaseResourceLite(&Vcb->tree_lock); ExReleaseResourceLite(&Vcb->tree_lock);
ExReleaseResourceLite(&Vcb->load_lock); ExReleaseResourceLite(&Vcb->load_lock);
@ -5784,6 +5802,14 @@ NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bo
(!posix && !stream && (us->Buffer[i] == '<' || us->Buffer[i] == '>' || us->Buffer[i] == '"' || (!posix && !stream && (us->Buffer[i] == '<' || us->Buffer[i] == '>' || us->Buffer[i] == '"' ||
us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31)))) us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31))))
return STATUS_OBJECT_NAME_INVALID; return STATUS_OBJECT_NAME_INVALID;
/* Don't allow unpaired surrogates ("WTF-16") */
if ((us->Buffer[i] & 0xfc00) == 0xdc00 && (i == 0 || ((us->Buffer[i-1] & 0xfc00) != 0xd800)))
return STATUS_OBJECT_NAME_INVALID;
if ((us->Buffer[i] & 0xfc00) == 0xd800 && (i == (us->Length / sizeof(WCHAR)) - 1 || ((us->Buffer[i+1] & 0xfc00) != 0xdc00)))
return STATUS_OBJECT_NAME_INVALID;
} }
if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.'))) if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.')))
@ -6290,6 +6316,8 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S
is_windows_8 = ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2); is_windows_8 = ver.dwMajorVersion > 6 || (ver.dwMajorVersion == 6 && ver.dwMinorVersion >= 2);
KeInitializeSpinLock(&fve_data_lock);
InitializeListHead(&uid_map_list); InitializeListHead(&uid_map_list);
InitializeListHead(&gid_map_list); InitializeListHead(&gid_map_list);
@ -6516,12 +6544,12 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S
ExInitializeResourceLite(&boot_lock); ExInitializeResourceLite(&boot_lock);
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)&GUID_DEVINTERFACE_VOLUME, DriverObject, volume_notification, DriverObject, &notification_entry2); (PVOID)&GUID_DEVINTERFACE_VOLUME, DriverObject, volume_notification, NULL, &notification_entry2);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status); ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES, Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
(PVOID)&GUID_DEVINTERFACE_HIDDEN_VOLUME, DriverObject, volume_notification, DriverObject, &notification_entry3); (PVOID)&GUID_DEVINTERFACE_HIDDEN_VOLUME, DriverObject, volume_notification, NULL, &notification_entry3);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status); ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);

View file

@ -10,7 +10,7 @@ Signature = "$Windows NT$"
Class = Volume Class = Volume
ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f} ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
Provider = %Me% Provider = %Me%
DriverVer = 06/07/2021,1.7.8.0 DriverVer = 10/02/2021,1.7.9
CatalogFile = btrfs.cat CatalogFile = btrfs.cat
[DestinationDirs] [DestinationDirs]

View file

@ -51,8 +51,8 @@ END
// //
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,7,8,0 FILEVERSION 1,7,9,0
PRODUCTVERSION 1,7,8,0 PRODUCTVERSION 1,7,9,0
FILEFLAGSMASK 0x17L FILEFLAGSMASK 0x17L
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 0x1L FILEFLAGS 0x1L
@ -68,12 +68,12 @@ BEGIN
BLOCK "080904b0" BLOCK "080904b0"
BEGIN BEGIN
VALUE "FileDescription", "WinBtrfs" VALUE "FileDescription", "WinBtrfs"
VALUE "FileVersion", "1.7.8" VALUE "FileVersion", "1.7.9"
VALUE "InternalName", "btrfs" VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
VALUE "OriginalFilename", "btrfs.sys" VALUE "OriginalFilename", "btrfs.sys"
VALUE "ProductName", "WinBtrfs" VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "1.7.8" VALUE "ProductVersion", "1.7.9"
END END
END END
BLOCK "VarFileInfo" BLOCK "VarFileInfo"

View file

@ -1317,15 +1317,16 @@ void __stdcall mountmgr_thread(_In_ void* context);
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context); NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context);
void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath); void disk_arrival(PUNICODE_STRING devpath);
void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath); bool volume_arrival(PUNICODE_STRING devpath, bool fve_callback);
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath); void volume_removal(PUNICODE_STRING devpath);
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context); NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context);
void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension* vde, void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lock) _Releases_exclusive_lock_(_Curr_->child_lock) _In_ volume_device_extension* vde,
_In_ volume_child* vc, _In_ bool skip_dev); _In_ volume_child* vc, _In_ bool skip_dev);
extern KSPIN_LOCK fve_data_lock;
// in cache.c // in cache.c
void init_cache(); void init_cache();

View file

@ -1774,11 +1774,11 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv
name_bit* nb; name_bit* nb;
nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry); nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry);
ExFreePool(nb); ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
if (has_stream && !IsListEmpty(&parts)) { if (has_stream && !IsListEmpty(&parts)) {
nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry); nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry);
ExFreePool(nb); ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
has_stream = false; has_stream = false;
} }
@ -1877,6 +1877,8 @@ NTSTATUS add_dir_child(fcb* fcb, uint64_t inode, bool subvol, PANSI_STRING utf8,
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
} }
RtlZeroMemory(dc, sizeof(dir_child));
dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, utf8->Length, ALLOC_TAG); dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, utf8->Length, ALLOC_TAG);
if (!dc->utf8.Buffer) { if (!dc->utf8.Buffer) {
ERR("out of memory\n"); ERR("out of memory\n");

View file

@ -202,12 +202,12 @@ static NTSTATUS probe_volume(void* data, ULONG length, KPROCESSOR_MODE processor
ObDereferenceObject(FileObject); ObDereferenceObject(FileObject);
volume_removal(drvobj, &pnp_name); volume_removal(&pnp_name);
if (RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID)) if (RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID))
disk_arrival(drvobj, &pnp_name); disk_arrival(&pnp_name);
else else
volume_arrival(drvobj, &pnp_name); volume_arrival(&pnp_name, false);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -2326,7 +2326,7 @@ static NTSTATUS rename_file_to_stream(device_extension* Vcb, file_ref* fileref,
dc = ExAllocatePoolWithTag(PagedPool, sizeof(dir_child), ALLOC_TAG); dc = ExAllocatePoolWithTag(PagedPool, sizeof(dir_child), ALLOC_TAG);
if (!dc) { if (!dc) {
ERR("short read\n"); ERR("out of memory\n");
Status = STATUS_INSUFFICIENT_RESOURCES;; Status = STATUS_INSUFFICIENT_RESOURCES;;
ExFreePool(utf8.Buffer); ExFreePool(utf8.Buffer);
ExFreePool(utf16.Buffer); ExFreePool(utf16.Buffer);
@ -2561,8 +2561,9 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
} else { } else {
LONG i; LONG i;
while (fnlen > 0 && (fri->FileName[fnlen - 1] == '/' || fri->FileName[fnlen - 1] == '\\')) while (fnlen > 0 && (fri->FileName[fnlen - 1] == '/' || fri->FileName[fnlen - 1] == '\\')) {
fnlen--; fnlen--;
}
if (fnlen == 0) if (fnlen == 0)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@ -2621,13 +2622,9 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer); TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
for (unsigned int i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) { Status = check_file_name_valid(&fnus, false, false);
if (fnus.Buffer[i] == ':') { if (!NT_SUCCESS(Status))
TRACE("colon in filename\n"); goto end;
Status = STATUS_OBJECT_NAME_INVALID;
goto end;
}
}
origutf8len = fileref->dc->utf8.Length; origutf8len = fileref->dc->utf8.Length;
@ -3444,8 +3441,9 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
tfofcb = tfo->FsContext; tfofcb = tfo->FsContext;
parfcb = tfofcb; parfcb = tfofcb;
while (fnlen > 0 && (fli->FileName[fnlen - 1] == '/' || fli->FileName[fnlen - 1] == '\\')) while (fnlen > 0 && (fli->FileName[fnlen - 1] == '/' || fli->FileName[fnlen - 1] == '\\')) {
fnlen--; fnlen--;
}
if (fnlen == 0) if (fnlen == 0)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
@ -3485,6 +3483,10 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer); TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
Status = check_file_name_valid(&fnus, false, false);
if (!NT_SUCCESS(Status))
goto end;
Status = utf16_to_utf8(NULL, 0, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR)); Status = utf16_to_utf8(NULL, 0, &utf8len, fn, (ULONG)fnlen * sizeof(WCHAR));
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
goto end; goto end;

View file

@ -22,7 +22,10 @@
#include <ntddscsi.h> #include <ntddscsi.h>
#include <ntddstor.h> #include <ntddstor.h>
#define MAX_CSUM_SIZE (4096 - sizeof(tree_header) - sizeof(leaf_node)) /* cf. __MAX_CSUM_ITEMS in Linux - it needs sizeof(leaf_node) bytes free
* so it can do a split. Linux tries to get it so a run will fit in a
* sector, but the MAX_CSUM_ITEMS logic is wrong... */
#define MAX_CSUM_SIZE (4096 - sizeof(tree_header) - (2 * sizeof(leaf_node)))
// #define DEBUG_WRITE_LOOPS // #define DEBUG_WRITE_LOOPS

View file

@ -2874,7 +2874,7 @@ static NTSTATUS add_device(device_extension* Vcb, PIRP Irp, KPROCESSOR_MODE proc
return STATUS_INTERNAL_ERROR; return STATUS_INTERNAL_ERROR;
} }
volume_removal(drvobj, &pnp_name); volume_removal(&pnp_name);
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true); ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);

View file

@ -27,6 +27,7 @@
#include <initguid.h> #include <initguid.h>
#include <wdmguid.h> #include <wdmguid.h>
#include <ioevent.h>
extern ERESOURCE pdo_list_lock; extern ERESOURCE pdo_list_lock;
extern LIST_ENTRY pdo_list; extern LIST_ENTRY pdo_list;
@ -37,11 +38,30 @@ extern bool shutting_down;
extern PDEVICE_OBJECT busobj; extern PDEVICE_OBJECT busobj;
extern tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx; extern tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx;
extern ERESOURCE boot_lock; extern ERESOURCE boot_lock;
extern PDRIVER_OBJECT drvobj;
typedef void (*pnp_callback)(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath); typedef void (*pnp_callback)(PUNICODE_STRING devpath);
#ifndef __REACTOS__
// not in mingw yet
#ifndef _MSC_VER
DEFINE_GUID(GUID_IO_VOLUME_FVE_STATUS_CHANGE, 0x062998b2, 0xee1f, 0x4b6a, 0xb8, 0x57, 0xe7, 0x6c, 0xbb, 0xe9, 0xa6, 0xda);
#endif
#endif // __REACTOS__
extern PDEVICE_OBJECT master_devobj; extern PDEVICE_OBJECT master_devobj;
typedef struct {
LIST_ENTRY list_entry;
PDEVICE_OBJECT devobj;
void* notification_entry;
UNICODE_STRING devpath;
WCHAR buf[1];
} fve_data;
static LIST_ENTRY fve_data_list = { &fve_data_list, &fve_data_list };
KSPIN_LOCK fve_data_lock;
static bool fs_ignored(BTRFS_UUID* uuid) { static bool fs_ignored(BTRFS_UUID* uuid) {
UNICODE_STRING path, ignoreus; UNICODE_STRING path, ignoreus;
NTSTATUS Status; NTSTATUS Status;
@ -115,12 +135,187 @@ static bool fs_ignored(BTRFS_UUID* uuid) {
return ret; return ret;
} }
static void test_vol(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject, typedef struct {
PUNICODE_STRING devpath, DWORD disk_num, DWORD part_num, uint64_t length) { PIO_WORKITEM work_item;
PFILE_OBJECT fileobj;
PDEVICE_OBJECT devobj;
UNICODE_STRING devpath;
WCHAR buf[1];
} fve_callback_context;
_Function_class_(IO_WORKITEM_ROUTINE)
static void __stdcall fve_callback(PDEVICE_OBJECT DeviceObject, PVOID con) {
fve_callback_context* ctx = con;
UNUSED(DeviceObject);
if (volume_arrival(&ctx->devpath, true)) {
KIRQL irql;
LIST_ENTRY* le;
fve_data* d = NULL;
// volume no longer locked - unregister notification
KeAcquireSpinLock(&fve_data_lock, &irql);
le = fve_data_list.Flink;
while (le != &fve_data_list) {
fve_data* d2 = CONTAINING_RECORD(le, fve_data, list_entry);
if (d2->devobj == ctx->devobj) {
RemoveEntryList(&d2->list_entry);
d = d2;
break;
}
le = le->Flink;
}
KeReleaseSpinLock(&fve_data_lock, irql);
if (d) {
IoUnregisterPlugPlayNotification(d->notification_entry);
ExFreePool(d);
}
}
IoFreeWorkItem(ctx->work_item);
ExFreePool(ctx);
}
static NTSTATUS __stdcall event_notification(PVOID NotificationStructure, PVOID Context) {
TARGET_DEVICE_REMOVAL_NOTIFICATION* tdrn = NotificationStructure;
PDEVICE_OBJECT devobj = Context;
PIO_WORKITEM work_item;
fve_callback_context* ctx;
LIST_ENTRY* le;
KIRQL irql;
if (RtlCompareMemory(&tdrn->Event, &GUID_IO_VOLUME_FVE_STATUS_CHANGE, sizeof(GUID)) != sizeof(GUID))
return STATUS_SUCCESS;
/* The FVE event has trailing data, presumably telling us whether the volume has
* been unlocked or whatever, but unfortunately it's undocumented! */
work_item = IoAllocateWorkItem(master_devobj);
if (!work_item) {
ERR("out of memory\n");
return STATUS_SUCCESS;
}
KeAcquireSpinLock(&fve_data_lock, &irql);
le = fve_data_list.Flink;
while (le != &fve_data_list) {
fve_data* d = CONTAINING_RECORD(le, fve_data, list_entry);
if (d->devobj == devobj) {
ctx = ExAllocatePoolWithTag(NonPagedPool, offsetof(fve_callback_context, buf) + d->devpath.Length,
ALLOC_TAG);
if (!ctx) {
KeReleaseSpinLock(&fve_data_lock, irql);
ERR("out of memory\n");
IoFreeWorkItem(work_item);
return STATUS_SUCCESS;
}
RtlCopyMemory(ctx->buf, d->devpath.Buffer, d->devpath.Length);
ctx->devpath.Length = ctx->devpath.MaximumLength = d->devpath.Length;
KeReleaseSpinLock(&fve_data_lock, irql);
ctx->devpath.Buffer = ctx->buf;
ctx->fileobj = tdrn->FileObject;
ctx->devobj = devobj;
ctx->work_item = work_item;
IoQueueWorkItem(work_item, fve_callback, DelayedWorkQueue, ctx);
return STATUS_SUCCESS;
}
le = le->Flink;
}
KeReleaseSpinLock(&fve_data_lock, irql);
IoFreeWorkItem(work_item);
return STATUS_SUCCESS;
}
static void register_fve_callback(PDEVICE_OBJECT devobj, PFILE_OBJECT fileobj,
PUNICODE_STRING devpath) {
NTSTATUS Status;
KIRQL irql;
LIST_ENTRY* le;
fve_data* d = ExAllocatePoolWithTag(NonPagedPool, offsetof(fve_data, buf) + devpath->Length, ALLOC_TAG);
if (!d) {
ERR("out of memory\n");
return;
}
d->devpath.Buffer = d->buf;
d->devpath.Length = d->devpath.MaximumLength = devpath->Length;
RtlCopyMemory(d->devpath.Buffer, devpath->Buffer, devpath->Length);
KeAcquireSpinLock(&fve_data_lock, &irql);
le = fve_data_list.Flink;
while (le != &fve_data_list) {
fve_data* d2 = CONTAINING_RECORD(le, fve_data, list_entry);
if (d2->devobj == devobj) {
KeReleaseSpinLock(&fve_data_lock, irql);
ExFreePool(d);
return;
}
le = le->Flink;
}
KeReleaseSpinLock(&fve_data_lock, irql);
Status = IoRegisterPlugPlayNotification(EventCategoryTargetDeviceChange, 0, fileobj, drvobj, event_notification,
devobj, &d->notification_entry);
if (!NT_SUCCESS(Status)) {
ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
return;
}
KeAcquireSpinLock(&fve_data_lock, &irql);
le = fve_data_list.Flink;
while (le != &fve_data_list) {
fve_data* d2 = CONTAINING_RECORD(le, fve_data, list_entry);
if (d2->devobj == devobj) {
KeReleaseSpinLock(&fve_data_lock, irql);
IoUnregisterPlugPlayNotification(d->notification_entry);
ExFreePool(d);
return;
}
le = le->Flink;
}
d->devobj = devobj;
InsertTailList(&fve_data_list, &d->list_entry);
KeReleaseSpinLock(&fve_data_lock, irql);
}
static bool test_vol(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
PUNICODE_STRING devpath, DWORD disk_num, DWORD part_num, uint64_t length,
bool fve_callback) {
NTSTATUS Status; NTSTATUS Status;
ULONG toread; ULONG toread;
uint8_t* data = NULL; uint8_t* data = NULL;
uint32_t sector_size; uint32_t sector_size;
bool ret = true;
TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer); TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
@ -195,11 +390,18 @@ static void test_vol(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
add_volume_device(sb, devpath, length, disk_num, part_num); add_volume_device(sb, devpath, length, disk_num, part_num);
} }
} }
} else if (Status == STATUS_FVE_LOCKED_VOLUME) {
if (fve_callback)
ret = false;
else
register_fve_callback(DeviceObject, FileObject, devpath);
} }
deref: deref:
if (data) if (data)
ExFreePool(data); ExFreePool(data);
return ret;
} }
NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath) { NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath) {
@ -255,7 +457,7 @@ NTSTATUS remove_drive_letter(PDEVICE_OBJECT mountmgr, PUNICODE_STRING devpath) {
return Status; return Status;
} }
void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) { void disk_arrival(PUNICODE_STRING devpath) {
PFILE_OBJECT fileobj; PFILE_OBJECT fileobj;
PDEVICE_OBJECT devobj; PDEVICE_OBJECT devobj;
NTSTATUS Status; NTSTATUS Status;
@ -265,8 +467,6 @@ void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
IO_STATUS_BLOCK iosb; IO_STATUS_BLOCK iosb;
GET_LENGTH_INFORMATION gli; GET_LENGTH_INFORMATION gli;
UNUSED(DriverObject);
ExAcquireResourceSharedLite(&boot_lock, TRUE); ExAcquireResourceSharedLite(&boot_lock, TRUE);
Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &fileobj, &devobj); Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &fileobj, &devobj);
@ -319,7 +519,8 @@ void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
} else } else
TRACE("DeviceType = %lu, DeviceNumber = %lu, PartitionNumber = %lu\n", sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber); TRACE("DeviceType = %lu, DeviceNumber = %lu, PartitionNumber = %lu\n", sdn.DeviceType, sdn.DeviceNumber, sdn.PartitionNumber);
test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber, gli.Length.QuadPart); test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber,
gli.Length.QuadPart, false);
end: end:
ObDereferenceObject(fileobj); ObDereferenceObject(fileobj);
@ -489,12 +690,13 @@ void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lo
ExReleaseResourceLite(&pdode->child_lock); ExReleaseResourceLite(&pdode->child_lock);
} }
void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) { bool volume_arrival(PUNICODE_STRING devpath, bool fve_callback) {
STORAGE_DEVICE_NUMBER sdn; STORAGE_DEVICE_NUMBER sdn;
PFILE_OBJECT fileobj; PFILE_OBJECT fileobj;
PDEVICE_OBJECT devobj; PDEVICE_OBJECT devobj;
GET_LENGTH_INFORMATION gli; GET_LENGTH_INFORMATION gli;
NTSTATUS Status; NTSTATUS Status;
bool ret = true;
TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer); TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
@ -504,12 +706,12 @@ void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
if (!NT_SUCCESS(Status)) { if (!NT_SUCCESS(Status)) {
ExReleaseResourceLite(&boot_lock); ExReleaseResourceLite(&boot_lock);
ERR("IoGetDeviceObjectPointer returned %08lx\n", Status); ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
return; return false;
} }
// make sure we're not processing devices we've created ourselves // make sure we're not processing devices we've created ourselves
if (devobj->DriverObject == DriverObject) if (devobj->DriverObject == drvobj)
goto end; goto end;
Status = dev_ioctl(devobj, IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, true, NULL); Status = dev_ioctl(devobj, IOCTL_VOLUME_ONLINE, NULL, 0, NULL, 0, true, NULL);
@ -575,22 +777,27 @@ void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
ExReleaseResourceLite(&pdo_list_lock); ExReleaseResourceLite(&pdo_list_lock);
} }
test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber, gli.Length.QuadPart); ret = test_vol(devobj, fileobj, devpath, sdn.DeviceNumber, sdn.PartitionNumber,
gli.Length.QuadPart, fve_callback);
end: end:
ObDereferenceObject(fileobj); ObDereferenceObject(fileobj);
ExReleaseResourceLite(&boot_lock); ExReleaseResourceLite(&boot_lock);
return ret;
} }
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) { static void volume_arrival2(PUNICODE_STRING devpath) {
volume_arrival(devpath, false);
}
void volume_removal(PUNICODE_STRING devpath) {
LIST_ENTRY* le; LIST_ENTRY* le;
UNICODE_STRING devpath2; UNICODE_STRING devpath2;
TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer); TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
UNUSED(DriverObject);
devpath2 = *devpath; devpath2 = *devpath;
if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') && if (devpath->Length > 4 * sizeof(WCHAR) && devpath->Buffer[0] == '\\' && (devpath->Buffer[1] == '\\' || devpath->Buffer[1] == '?') &&
@ -643,7 +850,6 @@ void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
} }
typedef struct { typedef struct {
PDRIVER_OBJECT DriverObject;
UNICODE_STRING name; UNICODE_STRING name;
pnp_callback func; pnp_callback func;
PIO_WORKITEM work_item; PIO_WORKITEM work_item;
@ -655,7 +861,7 @@ static void __stdcall do_pnp_callback(PDEVICE_OBJECT DeviceObject, PVOID con) {
UNUSED(DeviceObject); UNUSED(DeviceObject);
context->func(context->DriverObject, &context->name); context->func(&context->name);
if (context->name.Buffer) if (context->name.Buffer)
ExFreePool(context->name.Buffer); ExFreePool(context->name.Buffer);
@ -665,7 +871,7 @@ static void __stdcall do_pnp_callback(PDEVICE_OBJECT DeviceObject, PVOID con) {
ExFreePool(context); ExFreePool(context);
} }
static void enqueue_pnp_callback(PDRIVER_OBJECT DriverObject, PUNICODE_STRING name, pnp_callback func) { static void enqueue_pnp_callback(PUNICODE_STRING name, pnp_callback func) {
PIO_WORKITEM work_item; PIO_WORKITEM work_item;
pnp_callback_context* context; pnp_callback_context* context;
@ -683,8 +889,6 @@ static void enqueue_pnp_callback(PDRIVER_OBJECT DriverObject, PUNICODE_STRING na
return; return;
} }
context->DriverObject = DriverObject;
if (name->Length > 0) { if (name->Length > 0) {
context->name.Buffer = ExAllocatePoolWithTag(PagedPool, name->Length, ALLOC_TAG); context->name.Buffer = ExAllocatePoolWithTag(PagedPool, name->Length, ALLOC_TAG);
if (!context->name.Buffer) { if (!context->name.Buffer) {
@ -710,12 +914,13 @@ static void enqueue_pnp_callback(PDRIVER_OBJECT DriverObject, PUNICODE_STRING na
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context) { NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context) {
DEVICE_INTERFACE_CHANGE_NOTIFICATION* dicn = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; DEVICE_INTERFACE_CHANGE_NOTIFICATION* dicn = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;
UNUSED(Context);
if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID)) if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID))
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, volume_arrival); enqueue_pnp_callback(dicn->SymbolicLinkName, volume_arrival2);
else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID)) else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID))
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, volume_removal); enqueue_pnp_callback(dicn->SymbolicLinkName, volume_removal);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -723,12 +928,13 @@ NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Contex
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE) _Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context) { NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context) {
DEVICE_INTERFACE_CHANGE_NOTIFICATION* dicn = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure; DEVICE_INTERFACE_CHANGE_NOTIFICATION* dicn = (DEVICE_INTERFACE_CHANGE_NOTIFICATION*)NotificationStructure;
PDRIVER_OBJECT DriverObject = (PDRIVER_OBJECT)Context;
UNUSED(Context);
if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID)) if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_ARRIVAL, sizeof(GUID)) == sizeof(GUID))
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, disk_arrival); enqueue_pnp_callback(dicn->SymbolicLinkName, disk_arrival);
else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID)) else if (RtlCompareMemory(&dicn->Event, &GUID_DEVICE_INTERFACE_REMOVAL, sizeof(GUID)) == sizeof(GUID))
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, volume_removal); enqueue_pnp_callback(dicn->SymbolicLinkName, volume_removal);
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }

View file

@ -621,7 +621,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
*********************************/ *********************************/
typedef enum { search_hashChain, search_binaryTree } searchMethod_e; typedef enum { search_hashChain, search_binaryTree } searchMethod_e;
FORCE_INLINE_TEMPLATE size_t size_t
ZSTD_compressBlock_lazy_generic( ZSTD_compressBlock_lazy_generic(
ZSTD_matchState_t* ms, seqStore_t* seqStore, ZSTD_matchState_t* ms, seqStore_t* seqStore,
U32 rep[ZSTD_REP_NUM], U32 rep[ZSTD_REP_NUM],