mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 09:34:43 +00:00
[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:
parent
08d1009892
commit
f5556fdc10
14 changed files with 317 additions and 73 deletions
|
@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,8,0
|
||||
PRODUCTVERSION 1,7,8,0
|
||||
FILEVERSION 1,7,9,0
|
||||
PRODUCTVERSION 1,7,9,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -78,12 +78,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs shell extension"
|
||||
VALUE "FileVersion", "1.7.8"
|
||||
VALUE "FileVersion", "1.7.9"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "shellbtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.8"
|
||||
VALUE "ProductVersion", "1.7.9"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,8,0
|
||||
PRODUCTVERSION 1,7,8,0
|
||||
FILEVERSION 1,7,9,0
|
||||
PRODUCTVERSION 1,7,9,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "Btrfs utility DLL"
|
||||
VALUE "FileVersion", "1.7.8"
|
||||
VALUE "FileVersion", "1.7.9"
|
||||
VALUE "InternalName", "ubtrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "ubtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.8"
|
||||
VALUE "ProductVersion", "1.7.9"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define BLAKE2_INLINE inline
|
||||
#endif
|
||||
|
||||
#define NATIVE_LITTLE_ENDIAN
|
||||
|
||||
static BLAKE2_INLINE uint32_t load32( const void *src )
|
||||
{
|
||||
#if defined(NATIVE_LITTLE_ENDIAN)
|
||||
|
|
|
@ -4389,10 +4389,8 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
|
||||
TRACE("(%p, %p)\n", DeviceObject, Irp);
|
||||
|
||||
if (DeviceObject != master_devobj) {
|
||||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
goto exit;
|
||||
}
|
||||
if (DeviceObject != master_devobj)
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
DeviceToMount = IrpSp->Parameters.MountVolume.DeviceObject;
|
||||
|
@ -4412,7 +4410,7 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
|
||||
if (!not_pnp) {
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
goto exit2;
|
||||
goto exit;
|
||||
}
|
||||
} else {
|
||||
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) {
|
||||
vde = NULL;
|
||||
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) {
|
||||
ERR("error - number of devices is zero\n");
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
goto exit2;
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = STATUS_DEVICE_NOT_READY;
|
||||
goto exit2;
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
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) {
|
||||
ERR("error - number of devices is zero\n");
|
||||
Status = STATUS_INTERNAL_ERROR;
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -4519,6 +4520,10 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoCreateDevice returned %08lx\n", Status);
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
|
||||
if (pdode)
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
|
@ -4558,18 +4563,29 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
else if (Irp->Tail.Overlay.Thread)
|
||||
IoSetHardErrorOrVerifyDevice(Irp, readobj);
|
||||
|
||||
if (pdode)
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (!vde && Vcb->superblock.num_devices > 1) {
|
||||
ERR("cannot mount multi-device FS with non-PNP device\n");
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
|
||||
if (pdode)
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
goto exit;
|
||||
}
|
||||
|
||||
Status = registry_load_volume_options(Vcb);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("registry_load_volume_options returned %08lx\n", Status);
|
||||
|
||||
if (pdode)
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
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)) {
|
||||
ERR("could not mount as %I64u device(s) missing\n", pdode->num_children - pdode->children_loaded);
|
||||
Status = STATUS_DEVICE_NOT_READY;
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (pdode) {
|
||||
// Windows holds DeviceObject->DeviceLock, guaranteeing that mount_vol is serialized
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
}
|
||||
|
||||
if (Vcb->options.ignore) {
|
||||
TRACE("ignoring volume\n");
|
||||
Status = STATUS_UNRECOGNIZED_VOLUME;
|
||||
|
@ -5014,10 +5036,6 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
ExInitializeResourceLite(&Vcb->send_load_lock);
|
||||
|
||||
exit:
|
||||
if (pdode)
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
exit2:
|
||||
if (Vcb) {
|
||||
ExReleaseResourceLite(&Vcb->tree_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] == '"' ||
|
||||
us->Buffer[i] == '|' || us->Buffer[i] == '?' || us->Buffer[i] == '*' || (us->Buffer[i] >= 1 && us->Buffer[i] <= 31))))
|
||||
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] == '.')))
|
||||
|
@ -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);
|
||||
|
||||
KeInitializeSpinLock(&fve_data_lock);
|
||||
|
||||
InitializeListHead(&uid_map_list);
|
||||
InitializeListHead(&gid_map_list);
|
||||
|
||||
|
@ -6516,12 +6544,12 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S
|
|||
ExInitializeResourceLite(&boot_lock);
|
||||
|
||||
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
|
||||
(PVOID)&GUID_DEVINTERFACE_VOLUME, DriverObject, volume_notification, DriverObject, ¬ification_entry2);
|
||||
(PVOID)&GUID_DEVINTERFACE_VOLUME, DriverObject, volume_notification, NULL, ¬ification_entry2);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
|
||||
|
||||
Status = IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange, PNPNOTIFY_DEVICE_INTERFACE_INCLUDE_EXISTING_INTERFACES,
|
||||
(PVOID)&GUID_DEVINTERFACE_HIDDEN_VOLUME, DriverObject, volume_notification, DriverObject, ¬ification_entry3);
|
||||
(PVOID)&GUID_DEVINTERFACE_HIDDEN_VOLUME, DriverObject, volume_notification, NULL, ¬ification_entry3);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoRegisterPlugPlayNotification returned %08lx\n", Status);
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ Signature = "$Windows NT$"
|
|||
Class = Volume
|
||||
ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
|
||||
Provider = %Me%
|
||||
DriverVer = 06/07/2021,1.7.8.0
|
||||
DriverVer = 10/02/2021,1.7.9
|
||||
CatalogFile = btrfs.cat
|
||||
|
||||
[DestinationDirs]
|
||||
|
|
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,8,0
|
||||
PRODUCTVERSION 1,7,8,0
|
||||
FILEVERSION 1,7,9,0
|
||||
PRODUCTVERSION 1,7,9,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs"
|
||||
VALUE "FileVersion", "1.7.8"
|
||||
VALUE "FileVersion", "1.7.9"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "btrfs.sys"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.8"
|
||||
VALUE "ProductVersion", "1.7.9"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -1317,15 +1317,16 @@ void __stdcall mountmgr_thread(_In_ void* context);
|
|||
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
|
||||
NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context);
|
||||
|
||||
void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
|
||||
void volume_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
|
||||
void volume_removal(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath);
|
||||
void disk_arrival(PUNICODE_STRING devpath);
|
||||
bool volume_arrival(PUNICODE_STRING devpath, bool fve_callback);
|
||||
void volume_removal(PUNICODE_STRING devpath);
|
||||
|
||||
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
|
||||
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,
|
||||
_In_ volume_child* vc, _In_ bool skip_dev);
|
||||
extern KSPIN_LOCK fve_data_lock;
|
||||
|
||||
// in cache.c
|
||||
void init_cache();
|
||||
|
|
|
@ -1774,11 +1774,11 @@ NTSTATUS open_fileref(_Requires_lock_held_(_Curr_->tree_lock) _Requires_exclusiv
|
|||
name_bit* nb;
|
||||
|
||||
nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry);
|
||||
ExFreePool(nb);
|
||||
ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
|
||||
|
||||
if (has_stream && !IsListEmpty(&parts)) {
|
||||
nb = CONTAINING_RECORD(RemoveTailList(&parts), name_bit, list_entry);
|
||||
ExFreePool(nb);
|
||||
ExFreeToPagedLookasideList(&Vcb->name_bit_lookaside, nb);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RtlZeroMemory(dc, sizeof(dir_child));
|
||||
|
||||
dc->utf8.Buffer = ExAllocatePoolWithTag(PagedPool, utf8->Length, ALLOC_TAG);
|
||||
if (!dc->utf8.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
|
|
|
@ -202,12 +202,12 @@ static NTSTATUS probe_volume(void* data, ULONG length, KPROCESSOR_MODE processor
|
|||
|
||||
ObDereferenceObject(FileObject);
|
||||
|
||||
volume_removal(drvobj, &pnp_name);
|
||||
volume_removal(&pnp_name);
|
||||
|
||||
if (RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID))
|
||||
disk_arrival(drvobj, &pnp_name);
|
||||
disk_arrival(&pnp_name);
|
||||
else
|
||||
volume_arrival(drvobj, &pnp_name);
|
||||
volume_arrival(&pnp_name, false);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -2326,7 +2326,7 @@ static NTSTATUS rename_file_to_stream(device_extension* Vcb, file_ref* fileref,
|
|||
|
||||
dc = ExAllocatePoolWithTag(PagedPool, sizeof(dir_child), ALLOC_TAG);
|
||||
if (!dc) {
|
||||
ERR("short read\n");
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;;
|
||||
ExFreePool(utf8.Buffer);
|
||||
ExFreePool(utf16.Buffer);
|
||||
|
@ -2561,8 +2561,9 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
} else {
|
||||
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--;
|
||||
}
|
||||
|
||||
if (fnlen == 0)
|
||||
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);
|
||||
|
||||
for (unsigned int i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) {
|
||||
if (fnus.Buffer[i] == ':') {
|
||||
TRACE("colon in filename\n");
|
||||
Status = STATUS_OBJECT_NAME_INVALID;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
Status = check_file_name_valid(&fnus, false, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
|
||||
origutf8len = fileref->dc->utf8.Length;
|
||||
|
||||
|
@ -3444,8 +3441,9 @@ static NTSTATUS set_link_information(device_extension* Vcb, PIRP Irp, PFILE_OBJE
|
|||
tfofcb = tfo->FsContext;
|
||||
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--;
|
||||
}
|
||||
|
||||
if (fnlen == 0)
|
||||
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);
|
||||
|
||||
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));
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
#include <ntddscsi.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
|
||||
|
||||
|
|
|
@ -2874,7 +2874,7 @@ static NTSTATUS add_device(device_extension* Vcb, PIRP Irp, KPROCESSOR_MODE proc
|
|||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
volume_removal(drvobj, &pnp_name);
|
||||
volume_removal(&pnp_name);
|
||||
|
||||
ExAcquireResourceExclusiveLite(&Vcb->tree_lock, true);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <initguid.h>
|
||||
#include <wdmguid.h>
|
||||
#include <ioevent.h>
|
||||
|
||||
extern ERESOURCE pdo_list_lock;
|
||||
extern LIST_ENTRY pdo_list;
|
||||
|
@ -37,11 +38,30 @@ extern bool shutting_down;
|
|||
extern PDEVICE_OBJECT busobj;
|
||||
extern tIoUnregisterPlugPlayNotificationEx fIoUnregisterPlugPlayNotificationEx;
|
||||
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;
|
||||
|
||||
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) {
|
||||
UNICODE_STRING path, ignoreus;
|
||||
NTSTATUS Status;
|
||||
|
@ -115,12 +135,187 @@ static bool fs_ignored(BTRFS_UUID* uuid) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void test_vol(PDEVICE_OBJECT DeviceObject, PFILE_OBJECT FileObject,
|
||||
PUNICODE_STRING devpath, DWORD disk_num, DWORD part_num, uint64_t length) {
|
||||
typedef struct {
|
||||
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;
|
||||
ULONG toread;
|
||||
uint8_t* data = NULL;
|
||||
uint32_t sector_size;
|
||||
bool ret = true;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else if (Status == STATUS_FVE_LOCKED_VOLUME) {
|
||||
if (fve_callback)
|
||||
ret = false;
|
||||
else
|
||||
register_fve_callback(DeviceObject, FileObject, devpath);
|
||||
}
|
||||
|
||||
deref:
|
||||
if (data)
|
||||
ExFreePool(data);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
|
||||
void disk_arrival(PUNICODE_STRING devpath) {
|
||||
PFILE_OBJECT fileobj;
|
||||
PDEVICE_OBJECT devobj;
|
||||
NTSTATUS Status;
|
||||
|
@ -265,8 +467,6 @@ void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
|
|||
IO_STATUS_BLOCK iosb;
|
||||
GET_LENGTH_INFORMATION gli;
|
||||
|
||||
UNUSED(DriverObject);
|
||||
|
||||
ExAcquireResourceSharedLite(&boot_lock, TRUE);
|
||||
|
||||
Status = IoGetDeviceObjectPointer(devpath, FILE_READ_ATTRIBUTES, &fileobj, &devobj);
|
||||
|
@ -319,7 +519,8 @@ void disk_arrival(PDRIVER_OBJECT DriverObject, PUNICODE_STRING devpath) {
|
|||
} else
|
||||
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:
|
||||
ObDereferenceObject(fileobj);
|
||||
|
@ -489,12 +690,13 @@ void remove_volume_child(_Inout_ _Requires_exclusive_lock_held_(_Curr_->child_lo
|
|||
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;
|
||||
PFILE_OBJECT fileobj;
|
||||
PDEVICE_OBJECT devobj;
|
||||
GET_LENGTH_INFORMATION gli;
|
||||
NTSTATUS Status;
|
||||
bool ret = true;
|
||||
|
||||
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)) {
|
||||
ExReleaseResourceLite(&boot_lock);
|
||||
ERR("IoGetDeviceObjectPointer returned %08lx\n", Status);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
// make sure we're not processing devices we've created ourselves
|
||||
|
||||
if (devobj->DriverObject == DriverObject)
|
||||
if (devobj->DriverObject == drvobj)
|
||||
goto end;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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:
|
||||
ObDereferenceObject(fileobj);
|
||||
|
||||
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;
|
||||
UNICODE_STRING devpath2;
|
||||
|
||||
TRACE("%.*S\n", (int)(devpath->Length / sizeof(WCHAR)), devpath->Buffer);
|
||||
|
||||
UNUSED(DriverObject);
|
||||
|
||||
devpath2 = *devpath;
|
||||
|
||||
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 {
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
UNICODE_STRING name;
|
||||
pnp_callback func;
|
||||
PIO_WORKITEM work_item;
|
||||
|
@ -655,7 +861,7 @@ static void __stdcall do_pnp_callback(PDEVICE_OBJECT DeviceObject, PVOID con) {
|
|||
|
||||
UNUSED(DeviceObject);
|
||||
|
||||
context->func(context->DriverObject, &context->name);
|
||||
context->func(&context->name);
|
||||
|
||||
if (context->name.Buffer)
|
||||
ExFreePool(context->name.Buffer);
|
||||
|
@ -665,7 +871,7 @@ static void __stdcall do_pnp_callback(PDEVICE_OBJECT DeviceObject, PVOID con) {
|
|||
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;
|
||||
pnp_callback_context* context;
|
||||
|
||||
|
@ -683,8 +889,6 @@ static void enqueue_pnp_callback(PDRIVER_OBJECT DriverObject, PUNICODE_STRING na
|
|||
return;
|
||||
}
|
||||
|
||||
context->DriverObject = DriverObject;
|
||||
|
||||
if (name->Length > 0) {
|
||||
context->name.Buffer = ExAllocatePoolWithTag(PagedPool, name->Length, ALLOC_TAG);
|
||||
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)
|
||||
NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Context) {
|
||||
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))
|
||||
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))
|
||||
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, volume_removal);
|
||||
enqueue_pnp_callback(dicn->SymbolicLinkName, volume_removal);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -723,12 +928,13 @@ NTSTATUS __stdcall volume_notification(PVOID NotificationStructure, PVOID Contex
|
|||
_Function_class_(DRIVER_NOTIFICATION_CALLBACK_ROUTINE)
|
||||
NTSTATUS __stdcall pnp_notification(PVOID NotificationStructure, PVOID Context) {
|
||||
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))
|
||||
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))
|
||||
enqueue_pnp_callback(DriverObject, dicn->SymbolicLinkName, volume_removal);
|
||||
enqueue_pnp_callback(dicn->SymbolicLinkName, volume_removal);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -621,7 +621,7 @@ FORCE_INLINE_TEMPLATE size_t ZSTD_HcFindBestMatch_extDict_selectMLS (
|
|||
*********************************/
|
||||
typedef enum { search_hashChain, search_binaryTree } searchMethod_e;
|
||||
|
||||
FORCE_INLINE_TEMPLATE size_t
|
||||
size_t
|
||||
ZSTD_compressBlock_lazy_generic(
|
||||
ZSTD_matchState_t* ms, seqStore_t* seqStore,
|
||||
U32 rep[ZSTD_REP_NUM],
|
||||
|
|
Loading…
Reference in a new issue