mirror of
https://github.com/reactos/reactos.git
synced 2025-05-28 13:38:19 +00:00
[BTRFS][UBTRFS][SHELLBTRFS] Upgrade to 1.7.6 (#4417)
v1.7.6 (2021-01-14): - Fixed race condition when booting with Quibble - No longer need to restart Windows after initial installation - Forced maximum file name to 255 UTF-8 characters, to match Linux driver - Fixed issue where directories could be created with trailing backslash - Fixed potential deadlock when Windows calls NtCreateSection during flush - Miscellaneous bug fixes
This commit is contained in:
parent
b826992ab2
commit
c982533ea9
19 changed files with 761 additions and 767 deletions
|
@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,5,0
|
||||
PRODUCTVERSION 1,7,5,0
|
||||
FILEVERSION 1,7,6,0
|
||||
PRODUCTVERSION 1,7,6,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -78,12 +78,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs shell extension"
|
||||
VALUE "FileVersion", "1.7.5"
|
||||
VALUE "FileVersion", "1.7.6"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "shellbtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.5"
|
||||
VALUE "ProductVersion", "1.7.6"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,5,0
|
||||
PRODUCTVERSION 1,7,5,0
|
||||
FILEVERSION 1,7,6,0
|
||||
PRODUCTVERSION 1,7,6,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "Btrfs utility DLL"
|
||||
VALUE "FileVersion", "1.7.5"
|
||||
VALUE "FileVersion", "1.7.6"
|
||||
VALUE "InternalName", "ubtrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "ubtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.5"
|
||||
VALUE "ProductVersion", "1.7.6"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -46,20 +46,7 @@ typedef struct {
|
|||
ULONG ExtensionFlags;
|
||||
} DEVOBJ_EXTENSION2;
|
||||
|
||||
typedef enum {
|
||||
system_root_unknown,
|
||||
system_root_partition,
|
||||
system_root_btrfs
|
||||
} system_root_type;
|
||||
|
||||
typedef struct {
|
||||
uint32_t disk_num;
|
||||
uint32_t partition_num;
|
||||
BTRFS_UUID uuid;
|
||||
system_root_type type;
|
||||
} system_root;
|
||||
|
||||
static void get_system_root(system_root* sr) {
|
||||
static bool get_system_root() {
|
||||
NTSTATUS Status;
|
||||
HANDLE h;
|
||||
UNICODE_STRING us, target;
|
||||
|
@ -69,8 +56,6 @@ static void get_system_root(system_root* sr) {
|
|||
|
||||
static const WCHAR system_root[] = L"\\SystemRoot";
|
||||
static const WCHAR boot_device[] = L"\\Device\\BootDevice";
|
||||
static const WCHAR arc_prefix[] = L"\\ArcName\\multi(0)disk(0)rdisk(";
|
||||
static const WCHAR arc_middle[] = L")partition(";
|
||||
static const WCHAR arc_btrfs_prefix[] = L"\\ArcName\\btrfs(";
|
||||
|
||||
us.Buffer = (WCHAR*)system_root;
|
||||
|
@ -82,7 +67,7 @@ static void get_system_root(system_root* sr) {
|
|||
Status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &objatt);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("ZwOpenSymbolicLinkObject returned %08lx\n", Status);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
target.Length = target.MaximumLength = 0;
|
||||
|
@ -91,19 +76,19 @@ static void get_system_root(system_root* sr) {
|
|||
if (Status != STATUS_BUFFER_TOO_SMALL) {
|
||||
ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status);
|
||||
NtClose(h);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retlen == 0) {
|
||||
NtClose(h);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
target.Buffer = ExAllocatePoolWithTag(NonPagedPool, retlen, ALLOC_TAG);
|
||||
if (!target.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
NtClose(h);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
target.Length = target.MaximumLength = (USHORT)retlen;
|
||||
|
@ -113,7 +98,7 @@ static void get_system_root(system_root* sr) {
|
|||
ERR("ZwQuerySymbolicLinkObject returned %08lx\n", Status);
|
||||
NtClose(h);
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
NtClose(h);
|
||||
|
@ -136,85 +121,33 @@ static void get_system_root(system_root* sr) {
|
|||
break;
|
||||
}
|
||||
|
||||
sr->type = system_root_unknown;
|
||||
|
||||
if (target.Length >= sizeof(arc_prefix) - sizeof(WCHAR) &&
|
||||
RtlCompareMemory(target.Buffer, arc_prefix, sizeof(arc_prefix) - sizeof(WCHAR)) == sizeof(arc_prefix) - sizeof(WCHAR)) {
|
||||
WCHAR* s = &target.Buffer[(sizeof(arc_prefix) / sizeof(WCHAR)) - 1];
|
||||
ULONG left = ((target.Length - sizeof(arc_prefix)) / sizeof(WCHAR)) + 1;
|
||||
|
||||
if (left == 0 || s[0] < '0' || s[0] > '9') {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
sr->disk_num = 0;
|
||||
|
||||
while (left > 0 && s[0] >= '0' && s[0] <= '9') {
|
||||
sr->disk_num *= 10;
|
||||
sr->disk_num += s[0] - '0';
|
||||
s++;
|
||||
left--;
|
||||
}
|
||||
|
||||
if (left <= (sizeof(arc_middle) / sizeof(WCHAR)) - 1 ||
|
||||
RtlCompareMemory(s, arc_middle, sizeof(arc_middle) - sizeof(WCHAR)) != sizeof(arc_middle) - sizeof(WCHAR)) {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
s = &s[(sizeof(arc_middle) / sizeof(WCHAR)) - 1];
|
||||
left -= (sizeof(arc_middle) / sizeof(WCHAR)) - 1;
|
||||
|
||||
if (left == 0 || s[0] < '0' || s[0] > '9') {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
sr->partition_num = 0;
|
||||
|
||||
while (left > 0 && s[0] >= '0' && s[0] <= '9') {
|
||||
sr->partition_num *= 10;
|
||||
sr->partition_num += s[0] - '0';
|
||||
s++;
|
||||
left--;
|
||||
}
|
||||
|
||||
sr->type = system_root_partition;
|
||||
} else if (target.Length >= sizeof(arc_btrfs_prefix) - sizeof(WCHAR) &&
|
||||
if (target.Length >= sizeof(arc_btrfs_prefix) - sizeof(WCHAR) &&
|
||||
RtlCompareMemory(target.Buffer, arc_btrfs_prefix, sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) == sizeof(arc_btrfs_prefix) - sizeof(WCHAR)) {
|
||||
WCHAR* s = &target.Buffer[(sizeof(arc_btrfs_prefix) / sizeof(WCHAR)) - 1];
|
||||
#ifdef __REACTOS__
|
||||
unsigned int i;
|
||||
#endif // __REACTOS__
|
||||
|
||||
#ifndef __REACTOS__
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
#else
|
||||
for (i = 0; i < 16; i++) {
|
||||
#endif // __REACTOS__
|
||||
if (*s >= '0' && *s <= '9')
|
||||
sr->uuid.uuid[i] = (*s - '0') << 4;
|
||||
boot_uuid.uuid[i] = (*s - '0') << 4;
|
||||
else if (*s >= 'a' && *s <= 'f')
|
||||
sr->uuid.uuid[i] = (*s - 'a' + 0xa) << 4;
|
||||
boot_uuid.uuid[i] = (*s - 'a' + 0xa) << 4;
|
||||
else if (*s >= 'A' && *s <= 'F')
|
||||
sr->uuid.uuid[i] = (*s - 'A' + 0xa) << 4;
|
||||
boot_uuid.uuid[i] = (*s - 'A' + 0xa) << 4;
|
||||
else {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
||||
if (*s >= '0' && *s <= '9')
|
||||
sr->uuid.uuid[i] |= *s - '0';
|
||||
boot_uuid.uuid[i] |= *s - '0';
|
||||
else if (*s >= 'a' && *s <= 'f')
|
||||
sr->uuid.uuid[i] |= *s - 'a' + 0xa;
|
||||
boot_uuid.uuid[i] |= *s - 'a' + 0xa;
|
||||
else if (*s >= 'A' && *s <= 'F')
|
||||
sr->uuid.uuid[i] |= *s - 'A' + 0xa;
|
||||
boot_uuid.uuid[i] |= *s - 'A' + 0xa;
|
||||
else {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
@ -222,7 +155,7 @@ static void get_system_root(system_root* sr) {
|
|||
if (i == 3 || i == 5 || i == 7 || i == 9) {
|
||||
if (*s != '-') {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
s++;
|
||||
|
@ -231,97 +164,17 @@ static void get_system_root(system_root* sr) {
|
|||
|
||||
if (*s != ')') {
|
||||
ExFreePool(target.Buffer);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
sr->type = system_root_btrfs;
|
||||
ExFreePool(target.Buffer);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ExFreePool(target.Buffer);
|
||||
}
|
||||
|
||||
static void append_int_to_us(UNICODE_STRING* us, unsigned int n) {
|
||||
unsigned int num, digits = 0;
|
||||
WCHAR* ptr;
|
||||
|
||||
if (n == 0) {
|
||||
us->Buffer[us->Length / sizeof(WCHAR)] = '0';
|
||||
us->Length += sizeof(WCHAR);
|
||||
return;
|
||||
}
|
||||
|
||||
num = n;
|
||||
|
||||
while (num > 0) {
|
||||
digits++;
|
||||
num /= 10;
|
||||
}
|
||||
|
||||
ptr = &us->Buffer[(us->Length / sizeof(WCHAR)) + digits - 1];
|
||||
|
||||
while (n > 0) {
|
||||
*ptr = L'0' + (n % 10);
|
||||
ptr--;
|
||||
n /= 10;
|
||||
}
|
||||
|
||||
us->Length += digits * sizeof(WCHAR);
|
||||
}
|
||||
|
||||
static void change_symlink(uint32_t disk_num, uint32_t partition_num, BTRFS_UUID* uuid) {
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING us, us2;
|
||||
WCHAR symlink[60], target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) + 36], *w;
|
||||
#ifdef __REACTOS__
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
static const WCHAR dev_path1[] = L"\\Device\\Harddisk";
|
||||
static const WCHAR dev_path2[] = L"\\Partition";
|
||||
|
||||
us.Buffer = symlink;
|
||||
us.Length = sizeof(dev_path1) - sizeof(WCHAR);
|
||||
us.MaximumLength = sizeof(symlink);
|
||||
|
||||
RtlCopyMemory(symlink, dev_path1, sizeof(dev_path1) - sizeof(WCHAR));
|
||||
|
||||
append_int_to_us(&us, disk_num);
|
||||
|
||||
RtlCopyMemory(&us.Buffer[us.Length / sizeof(WCHAR)], dev_path2, sizeof(dev_path2) - sizeof(WCHAR));
|
||||
us.Length += sizeof(dev_path2) - sizeof(WCHAR);
|
||||
|
||||
append_int_to_us(&us, partition_num);
|
||||
|
||||
Status = IoDeleteSymbolicLink(&us);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoDeleteSymbolicLink returned %08lx\n", Status);
|
||||
|
||||
RtlCopyMemory(target, BTRFS_VOLUME_PREFIX, sizeof(BTRFS_VOLUME_PREFIX) - sizeof(WCHAR));
|
||||
|
||||
w = &target[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1];
|
||||
|
||||
#ifndef __REACTOS__
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
#else
|
||||
for (i = 0; i < 16; i++) {
|
||||
#endif
|
||||
*w = hex_digit(uuid->uuid[i] >> 4); w++;
|
||||
*w = hex_digit(uuid->uuid[i] & 0xf); w++;
|
||||
|
||||
if (i == 3 || i == 5 || i == 7 || i == 9) {
|
||||
*w = L'-';
|
||||
w++;
|
||||
}
|
||||
}
|
||||
|
||||
*w = L'}';
|
||||
|
||||
us2.Buffer = target;
|
||||
us2.Length = us2.MaximumLength = sizeof(target);
|
||||
|
||||
Status = IoCreateSymbolicLink(&us, &us2);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoCreateSymbolicLink returned %08lx\n", Status);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void mountmgr_notification(BTRFS_UUID* uuid) {
|
||||
|
@ -332,9 +185,6 @@ static void mountmgr_notification(BTRFS_UUID* uuid) {
|
|||
ULONG mmtnlen;
|
||||
MOUNTMGR_TARGET_NAME* mmtn;
|
||||
WCHAR* w;
|
||||
#ifdef __REACTOS__
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME);
|
||||
Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject, &mountmgr);
|
||||
|
@ -357,11 +207,7 @@ static void mountmgr_notification(BTRFS_UUID* uuid) {
|
|||
|
||||
w = &mmtn->DeviceName[(sizeof(BTRFS_VOLUME_PREFIX) / sizeof(WCHAR)) - 1];
|
||||
|
||||
#ifndef __REACTOS__
|
||||
for (unsigned int i = 0; i < 16; i++) {
|
||||
#else
|
||||
for (i = 0; i < 16; i++) {
|
||||
#endif
|
||||
*w = hex_digit(uuid->uuid[i] >> 4); w++;
|
||||
*w = hex_digit(uuid->uuid[i] & 0xf); w++;
|
||||
|
||||
|
@ -487,166 +333,52 @@ void boot_add_device(DEVICE_OBJECT* pdo) {
|
|||
mountmgr_notification(&pdode->uuid);
|
||||
}
|
||||
|
||||
/* If booting from Btrfs, Windows will pass the device object for the raw partition to
|
||||
* mount_vol - which is no good to us, as we only use the \Device\Btrfs{} devices we
|
||||
* create so that RAID works correctly.
|
||||
* At the time check_system_root gets called, \SystemRoot is a symlink to the ARC device,
|
||||
* e.g. \ArcName\multi(0)disk(0)rdisk(0)partition(1)\Windows. We can't change the symlink,
|
||||
* as it gets clobbered by IopReassignSystemRoot shortly afterwards, and we can't touch
|
||||
* the \ArcName symlinks as they haven't been created yet. Instead, we need to change the
|
||||
* symlink \Device\HarddiskX\PartitionY, which is what the ArcName symlink will shortly
|
||||
* point to.
|
||||
*/
|
||||
void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count) {
|
||||
system_root sr;
|
||||
void check_system_root() {
|
||||
LIST_ENTRY* le;
|
||||
bool done = false;
|
||||
PDEVICE_OBJECT pdo_to_add = NULL;
|
||||
volume_child* boot_vc = NULL;
|
||||
|
||||
TRACE("(%p, %p, %lu)\n", DriverObject, Context, Count);
|
||||
|
||||
UNUSED(DriverObject);
|
||||
UNUSED(Context);
|
||||
UNUSED(Count);
|
||||
TRACE("()\n");
|
||||
|
||||
// wait for any PNP notifications in progress to finish
|
||||
ExAcquireResourceExclusiveLite(&boot_lock, TRUE);
|
||||
ExReleaseResourceLite(&boot_lock);
|
||||
|
||||
get_system_root(&sr);
|
||||
if (!get_system_root())
|
||||
return;
|
||||
|
||||
if (sr.type == system_root_partition) {
|
||||
TRACE("system boot partition is disk %u, partition %u\n", sr.disk_num, sr.partition_num);
|
||||
ExAcquireResourceSharedLite(&pdo_list_lock, true);
|
||||
|
||||
ExAcquireResourceSharedLite(&pdo_list_lock, true);
|
||||
le = pdo_list.Flink;
|
||||
while (le != &pdo_list) {
|
||||
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
|
||||
|
||||
le = pdo_list.Flink;
|
||||
while (le != &pdo_list) {
|
||||
LIST_ENTRY* le2;
|
||||
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
|
||||
if (RtlCompareMemory(&pdode->uuid, &boot_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
|
||||
if (!pdode->vde)
|
||||
pdo_to_add = pdode->pdo;
|
||||
else if (pdode->vde->device && !(pdode->vde->device->Flags & DO_SYSTEM_BOOT_PARTITION)) { // AddDevice has beaten us to it
|
||||
NTSTATUS Status;
|
||||
|
||||
ExAcquireResourceSharedLite(&pdode->child_lock, true);
|
||||
pdode->vde->device->Flags |= DO_SYSTEM_BOOT_PARTITION;
|
||||
pdode->pdo->Flags |= DO_SYSTEM_BOOT_PARTITION;
|
||||
|
||||
le2 = pdode->children.Flink;
|
||||
Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
|
||||
|
||||
while (le2 != &pdode->children) {
|
||||
volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry);
|
||||
|
||||
if (vc->disk_num == sr.disk_num && vc->part_num == sr.partition_num) {
|
||||
change_symlink(sr.disk_num, sr.partition_num, &pdode->uuid);
|
||||
done = true;
|
||||
|
||||
vc->boot_volume = true;
|
||||
boot_uuid = pdode->uuid;
|
||||
|
||||
if (!pdode->vde)
|
||||
pdo_to_add = pdode->pdo;
|
||||
|
||||
boot_vc = vc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
le2 = le2->Flink;
|
||||
Status = IoSetDeviceInterfaceState(&pdode->vde->bus_name, true);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
|
||||
}
|
||||
|
||||
if (done) {
|
||||
le2 = pdode->children.Flink;
|
||||
|
||||
while (le2 != &pdode->children) {
|
||||
volume_child* vc = CONTAINING_RECORD(le2, volume_child, list_entry);
|
||||
|
||||
/* On Windows 7 we need to clear the DO_SYSTEM_BOOT_PARTITION flag of
|
||||
* all of our underlying partition objects - otherwise IopMountVolume
|
||||
* will bugcheck with UNMOUNTABLE_BOOT_VOLUME when it tries and fails
|
||||
* to mount one. */
|
||||
if (vc->devobj) {
|
||||
PDEVICE_OBJECT dev = vc->devobj;
|
||||
|
||||
ObReferenceObject(dev);
|
||||
|
||||
while (dev) {
|
||||
PDEVICE_OBJECT dev2 = IoGetLowerDeviceObject(dev);
|
||||
|
||||
dev->Flags &= ~DO_SYSTEM_BOOT_PARTITION;
|
||||
|
||||
ObDereferenceObject(dev);
|
||||
|
||||
dev = dev2;
|
||||
}
|
||||
}
|
||||
|
||||
le2 = le2->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&pdode->child_lock);
|
||||
|
||||
le = le->Flink;
|
||||
break;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&pdo_list_lock);
|
||||
} else if (sr.type == system_root_btrfs) {
|
||||
boot_uuid = sr.uuid;
|
||||
|
||||
ExAcquireResourceSharedLite(&pdo_list_lock, true);
|
||||
|
||||
le = pdo_list.Flink;
|
||||
while (le != &pdo_list) {
|
||||
pdo_device_extension* pdode = CONTAINING_RECORD(le, pdo_device_extension, list_entry);
|
||||
|
||||
if (RtlCompareMemory(&pdode->uuid, &sr.uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) {
|
||||
if (!pdode->vde)
|
||||
pdo_to_add = pdode->pdo;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(&pdo_list_lock);
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
if (boot_vc) {
|
||||
NTSTATUS Status;
|
||||
UNICODE_STRING name;
|
||||
ExReleaseResourceLite(&pdo_list_lock);
|
||||
|
||||
/* On Windows 8, mountmgr!MountMgrFindBootVolume returns the first volume in its database
|
||||
* with the DO_SYSTEM_BOOT_PARTITION flag set. We've cleared the bit on the underlying devices,
|
||||
* but as it caches it we need to disable and re-enable the volume so mountmgr receives a PNP
|
||||
* notification to refresh its list. */
|
||||
|
||||
static const WCHAR prefix[] = L"\\??";
|
||||
|
||||
name.Length = name.MaximumLength = boot_vc->pnp_name.Length + sizeof(prefix) - sizeof(WCHAR);
|
||||
|
||||
name.Buffer = ExAllocatePoolWithTag(PagedPool, name.MaximumLength, ALLOC_TAG);
|
||||
if (!name.Buffer)
|
||||
ERR("out of memory\n");
|
||||
else {
|
||||
RtlCopyMemory(name.Buffer, prefix, sizeof(prefix) - sizeof(WCHAR));
|
||||
RtlCopyMemory(&name.Buffer[(sizeof(prefix) / sizeof(WCHAR)) - 1], boot_vc->pnp_name.Buffer, boot_vc->pnp_name.Length);
|
||||
|
||||
Status = IoSetDeviceInterfaceState(&name, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
|
||||
|
||||
Status = IoSetDeviceInterfaceState(&name, true);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IoSetDeviceInterfaceState returned %08lx\n", Status);
|
||||
|
||||
ExFreePool(name.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (sr.type == system_root_btrfs || boot_vc)
|
||||
check_boot_options();
|
||||
check_boot_options();
|
||||
|
||||
// If our FS depends on volumes that aren't there when we do our IoRegisterPlugPlayNotification calls
|
||||
// in DriverEntry, bus_query_device_relations won't get called until it's too late. We need to do our
|
||||
|
|
|
@ -667,6 +667,9 @@ static bool lie_about_fs_type() {
|
|||
INIT_UNICODE_STRING(fsutil, L"FSUTIL.EXE");
|
||||
INIT_UNICODE_STRING(storsvc, L"STORSVC.DLL");
|
||||
|
||||
/* Not doing a Volkswagen, honest! Some IFS tests won't run if not recognized FS. */
|
||||
INIT_UNICODE_STRING(ifstest, L"IFSTEST.EXE");
|
||||
|
||||
if (!PsGetCurrentProcess())
|
||||
return false;
|
||||
|
||||
|
@ -733,6 +736,15 @@ static bool lie_about_fs_type() {
|
|||
blacklist = FsRtlAreNamesEqual(&name, &usstorsvc, true, NULL);
|
||||
}
|
||||
|
||||
if (!blacklist && entry->FullDllName.Length >= usifstest.Length) {
|
||||
UNICODE_STRING name;
|
||||
|
||||
name.Buffer = &entry->FullDllName.Buffer[(entry->FullDllName.Length - usifstest.Length) / sizeof(WCHAR)];
|
||||
name.Length = name.MaximumLength = usifstest.Length;
|
||||
|
||||
blacklist = FsRtlAreNamesEqual(&name, &usifstest, true, NULL);
|
||||
}
|
||||
|
||||
if (blacklist) {
|
||||
void** frames;
|
||||
ULONG i, num_frames;
|
||||
|
@ -1833,10 +1845,6 @@ void reap_fileref(device_extension* Vcb, file_ref* fr) {
|
|||
|
||||
// FIXME - do delete if needed
|
||||
|
||||
ExDeleteResourceLite(&fr->nonpaged->fileref_lock);
|
||||
|
||||
ExFreeToNPagedLookasideList(&Vcb->fileref_np_lookaside, fr->nonpaged);
|
||||
|
||||
// FIXME - throw error if children not empty
|
||||
|
||||
if (fr->fcb->fileref == fr)
|
||||
|
@ -2161,7 +2169,6 @@ void uninit(_In_ device_extension* Vcb) {
|
|||
ExDeletePagedLookasideList(&Vcb->fcb_lookaside);
|
||||
ExDeletePagedLookasideList(&Vcb->name_bit_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->fileref_np_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside);
|
||||
|
||||
ZwClose(Vcb->flush_thread_handle);
|
||||
|
@ -4709,7 +4716,6 @@ static NTSTATUS mount_vol(_In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp) {
|
|||
ExInitializePagedLookasideList(&Vcb->fcb_lookaside, NULL, NULL, 0, sizeof(fcb), ALLOC_TAG, 0);
|
||||
ExInitializePagedLookasideList(&Vcb->name_bit_lookaside, NULL, NULL, 0, sizeof(name_bit), ALLOC_TAG, 0);
|
||||
ExInitializeNPagedLookasideList(&Vcb->range_lock_lookaside, NULL, NULL, 0, sizeof(range_lock), ALLOC_TAG, 0);
|
||||
ExInitializeNPagedLookasideList(&Vcb->fileref_np_lookaside, NULL, NULL, 0, sizeof(file_ref_nonpaged), ALLOC_TAG, 0);
|
||||
ExInitializeNPagedLookasideList(&Vcb->fcb_np_lookaside, NULL, NULL, 0, sizeof(fcb_nonpaged), ALLOC_TAG, 0);
|
||||
init_lookaside = true;
|
||||
|
||||
|
@ -5027,7 +5033,6 @@ exit2:
|
|||
ExDeletePagedLookasideList(&Vcb->fcb_lookaside);
|
||||
ExDeletePagedLookasideList(&Vcb->name_bit_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->range_lock_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->fileref_np_lookaside);
|
||||
ExDeleteNPagedLookasideList(&Vcb->fcb_np_lookaside);
|
||||
}
|
||||
|
||||
|
@ -5764,27 +5769,43 @@ exit:
|
|||
return Status;
|
||||
}
|
||||
|
||||
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream) {
|
||||
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream) {
|
||||
ULONG i;
|
||||
|
||||
if (us->Length < sizeof(WCHAR))
|
||||
return false;
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
if (us->Length > 255 * sizeof(WCHAR))
|
||||
return false;
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
for (i = 0; i < us->Length / sizeof(WCHAR); i++) {
|
||||
if (us->Buffer[i] == '/' || us->Buffer[i] == 0 ||
|
||||
(!posix && (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))))
|
||||
return false;
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
|
||||
if (us->Buffer[0] == '.' && (us->Length == sizeof(WCHAR) || (us->Length == 2 * sizeof(WCHAR) && us->Buffer[1] == '.')))
|
||||
return false;
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
|
||||
return true;
|
||||
/* The Linux driver expects filenames with a maximum length of 255 bytes - make sure
|
||||
* that our UTF-8 length won't be longer than that. */
|
||||
if (us->Length >= 85 * sizeof(WCHAR)) {
|
||||
NTSTATUS Status;
|
||||
ULONG utf8len;
|
||||
|
||||
Status = utf16_to_utf8(NULL, 0, &utf8len, us->Buffer, us->Length);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
if (utf8len > 255)
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
else if (stream && utf8len > 250) // minus five bytes for "user."
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void chunk_lock_range(_In_ device_extension* Vcb, _In_ chunk* c, _In_ uint64_t start, _In_ uint64_t length) {
|
||||
|
@ -6519,7 +6540,7 @@ NTSTATUS __stdcall DriverEntry(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_S
|
|||
|
||||
IoRegisterFileSystem(DeviceObject);
|
||||
|
||||
IoRegisterBootDriverReinitialization(DriverObject, check_system_root, NULL);
|
||||
check_system_root();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ Signature = "$Windows NT$"
|
|||
Class = Volume
|
||||
ClassGuid = {71a27cdd-812a-11d0-bec7-08002be2092f}
|
||||
Provider = %Me%
|
||||
DriverVer = 10/31/2020,1.7.5.0
|
||||
DriverVer = 01/14/2021,1.7.6.0
|
||||
CatalogFile = btrfs.cat
|
||||
|
||||
[DestinationDirs]
|
||||
|
|
|
@ -51,8 +51,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,7,5,0
|
||||
PRODUCTVERSION 1,7,5,0
|
||||
FILEVERSION 1,7,6,0
|
||||
PRODUCTVERSION 1,7,6,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -68,12 +68,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs"
|
||||
VALUE "FileVersion", "1.7.5"
|
||||
VALUE "FileVersion", "1.7.6"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-20"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-21"
|
||||
VALUE "OriginalFilename", "btrfs.sys"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.7.5"
|
||||
VALUE "ProductVersion", "1.7.6"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
|
|
@ -338,10 +338,6 @@ typedef struct _fcb {
|
|||
LIST_ENTRY list_entry_dirty;
|
||||
} fcb;
|
||||
|
||||
typedef struct {
|
||||
ERESOURCE fileref_lock;
|
||||
} file_ref_nonpaged;
|
||||
|
||||
typedef struct _file_ref {
|
||||
fcb* fcb;
|
||||
ANSI_STRING oldutf8;
|
||||
|
@ -350,7 +346,6 @@ typedef struct _file_ref {
|
|||
bool posix_delete;
|
||||
bool deleted;
|
||||
bool created;
|
||||
file_ref_nonpaged* nonpaged;
|
||||
LIST_ENTRY children;
|
||||
LONG refcount;
|
||||
LONG open_count;
|
||||
|
@ -832,7 +827,6 @@ typedef struct _device_extension {
|
|||
PAGED_LOOKASIDE_LIST fcb_lookaside;
|
||||
PAGED_LOOKASIDE_LIST name_bit_lookaside;
|
||||
NPAGED_LOOKASIDE_LIST range_lock_lookaside;
|
||||
NPAGED_LOOKASIDE_LIST fileref_np_lookaside;
|
||||
NPAGED_LOOKASIDE_LIST fcb_np_lookaside;
|
||||
LIST_ENTRY list_entry;
|
||||
} device_extension;
|
||||
|
@ -1122,7 +1116,7 @@ NTSTATUS create_root(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) devi
|
|||
void uninit(_In_ device_extension* Vcb);
|
||||
NTSTATUS dev_ioctl(_In_ PDEVICE_OBJECT DeviceObject, _In_ ULONG ControlCode, _In_reads_bytes_opt_(InputBufferSize) PVOID InputBuffer, _In_ ULONG InputBufferSize,
|
||||
_Out_writes_bytes_opt_(OutputBufferSize) PVOID OutputBuffer, _In_ ULONG OutputBufferSize, _In_ bool Override, _Out_opt_ IO_STATUS_BLOCK* iosb);
|
||||
bool is_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream);
|
||||
NTSTATUS check_file_name_valid(_In_ PUNICODE_STRING us, _In_ bool posix, _In_ bool stream);
|
||||
void send_notification_fileref(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream);
|
||||
void queue_notification_fcb(_In_ file_ref* fileref, _In_ ULONG filter_match, _In_ ULONG action, _In_opt_ PUNICODE_STRING stream);
|
||||
|
||||
|
@ -1419,6 +1413,8 @@ NTSTATUS stream_set_end_of_file_information(device_extension* Vcb, uint16_t end,
|
|||
NTSTATUS fileref_get_filename(file_ref* fileref, PUNICODE_STRING fn, USHORT* name_offset, ULONG* preqlen);
|
||||
void insert_dir_child_into_hash_lists(fcb* fcb, dir_child* dc);
|
||||
void remove_dir_child_from_hash_lists(fcb* fcb, dir_child* dc);
|
||||
void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb);
|
||||
void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb);
|
||||
|
||||
// in reparse.c
|
||||
NTSTATUS get_reparse_point(PFILE_OBJECT FileObject, void* buffer, DWORD buflen, ULONG_PTR* retlen);
|
||||
|
@ -1626,7 +1622,7 @@ NTSTATUS read_send_buffer(device_extension* Vcb, PFILE_OBJECT FileObject, void*
|
|||
NTSTATUS __stdcall compat_FsRtlValidateReparsePointBuffer(IN ULONG BufferLength, IN PREPARSE_DATA_BUFFER ReparseBuffer);
|
||||
|
||||
// in boot.c
|
||||
void __stdcall check_system_root(PDRIVER_OBJECT DriverObject, PVOID Context, ULONG Count);
|
||||
void check_system_root();
|
||||
void boot_add_device(DEVICE_OBJECT* pdo);
|
||||
extern BTRFS_UUID boot_uuid;
|
||||
|
||||
|
|
|
@ -80,6 +80,12 @@ static const GUID GUID_ECP_ATOMIC_CREATE = { 0x4720bd83, 0x52ac, 0x4104, { 0xa1,
|
|||
static const GUID GUID_ECP_QUERY_ON_CREATE = { 0x1aca62e9, 0xabb4, 0x4ff2, { 0xbb, 0x5c, 0x1c, 0x79, 0x02, 0x5e, 0x41, 0x7f } };
|
||||
static const GUID GUID_ECP_CREATE_REDIRECTION = { 0x188d6bd6, 0xa126, 0x4fa8, { 0xbd, 0xf2, 0x1c, 0xcd, 0xf8, 0x96, 0xf3, 0xe0 } };
|
||||
|
||||
typedef struct {
|
||||
device_extension* Vcb;
|
||||
ACCESS_MASK granted_access;
|
||||
file_ref* fileref;
|
||||
} oplock_context;
|
||||
|
||||
fcb* create_fcb(device_extension* Vcb, POOL_TYPE pool_type) {
|
||||
fcb* fcb;
|
||||
|
||||
|
@ -160,13 +166,6 @@ file_ref* create_fileref(device_extension* Vcb) {
|
|||
|
||||
RtlZeroMemory(fr, sizeof(file_ref));
|
||||
|
||||
fr->nonpaged = ExAllocateFromNPagedLookasideList(&Vcb->fileref_np_lookaside);
|
||||
if (!fr->nonpaged) {
|
||||
ERR("out of memory\n");
|
||||
ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, fr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fr->refcount = 1;
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
|
@ -175,8 +174,6 @@ file_ref* create_fileref(device_extension* Vcb) {
|
|||
|
||||
InitializeListHead(&fr->children);
|
||||
|
||||
ExInitializeResourceLite(&fr->nonpaged->fileref_lock);
|
||||
|
||||
return fr;
|
||||
}
|
||||
|
||||
|
@ -1596,7 +1593,7 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex
|
|||
ExReleaseResourceLite(&sf->fcb->nonpaged->dir_children_lock);
|
||||
|
||||
if (duff_fr)
|
||||
reap_fileref(Vcb, duff_fr);
|
||||
ExFreeToPagedLookasideList(&Vcb->fileref_lookaside, duff_fr);
|
||||
} else {
|
||||
root* subvol;
|
||||
uint64_t inode;
|
||||
|
@ -1652,9 +1649,6 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex
|
|||
|
||||
sf2->fcb = fcb;
|
||||
|
||||
if (dc->type == BTRFS_TYPE_DIRECTORY)
|
||||
fcb->fileref = sf2;
|
||||
|
||||
ExAcquireResourceExclusiveLite(&sf->fcb->nonpaged->dir_children_lock, true);
|
||||
|
||||
if (!dc->fileref) {
|
||||
|
@ -1663,6 +1657,9 @@ NTSTATUS open_fileref_child(_Requires_lock_held_(_Curr_->tree_lock) _Requires_ex
|
|||
dc->fileref = sf2;
|
||||
InsertTailList(&sf->children, &sf2->list_entry);
|
||||
increase_fileref_refcount(sf);
|
||||
|
||||
if (dc->type == BTRFS_TYPE_DIRECTORY)
|
||||
fcb->fileref = sf2;
|
||||
} else {
|
||||
duff_fr = sf2;
|
||||
sf2 = dc->fileref;
|
||||
|
@ -2654,9 +2651,6 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
LONG rc;
|
||||
#endif
|
||||
#ifdef __REACTOS__
|
||||
LIST_ENTRY* le;
|
||||
#endif
|
||||
|
||||
TRACE("fpus = %.*S\n", (int)(fpus->Length / sizeof(WCHAR)), fpus->Buffer);
|
||||
TRACE("stream = %.*S\n", (int)(stream->Length / sizeof(WCHAR)), stream->Buffer);
|
||||
|
@ -2671,8 +2665,9 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
if (Status == STATUS_OBJECT_NAME_NOT_FOUND) {
|
||||
UNICODE_STRING fpus2;
|
||||
|
||||
if (!is_file_name_valid(fpus, false, true))
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
Status = check_file_name_valid(fpus, false, true);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
fpus2.Length = fpus2.MaximumLength = fpus->Length;
|
||||
fpus2.Buffer = ExAllocatePoolWithTag(pool_type, fpus2.MaximumLength, ALLOC_TAG);
|
||||
|
@ -2775,6 +2770,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
#endif
|
||||
fcb->subvol = parfileref->fcb->subvol;
|
||||
fcb->inode = parfileref->fcb->inode;
|
||||
fcb->hash = parfileref->fcb->hash;
|
||||
fcb->type = parfileref->fcb->type;
|
||||
|
||||
fcb->ads = true;
|
||||
|
@ -2913,11 +2909,7 @@ static NTSTATUS create_stream(_Requires_lock_held_(_Curr_->tree_lock) _Requires_
|
|||
|
||||
ExAcquireResourceExclusiveLite(&parfileref->fcb->nonpaged->dir_children_lock, true);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
LIST_ENTRY* le = parfileref->fcb->dir_children_index.Flink;
|
||||
#else
|
||||
le = parfileref->fcb->dir_children_index.Flink;
|
||||
#endif
|
||||
while (le != &parfileref->fcb->dir_children_index) {
|
||||
dir_child* dc2 = CONTAINING_RECORD(le, dir_child, list_entry_index);
|
||||
|
||||
|
@ -3143,10 +3135,9 @@ static NTSTATUS file_create(PIRP Irp, _Requires_lock_held_(_Curr_->tree_lock) _R
|
|||
} else {
|
||||
ACCESS_MASK granted_access;
|
||||
|
||||
if (!is_file_name_valid(&fpus, false, false)) {
|
||||
Status = STATUS_OBJECT_NAME_INVALID;
|
||||
Status = check_file_name_valid(&fpus, false, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
}
|
||||
|
||||
SeLockSubjectContext(&IrpSp->Parameters.Create.SecurityContext->AccessState->SubjectSecurityContext);
|
||||
|
||||
|
@ -3581,12 +3572,357 @@ end:
|
|||
fcb->csum_loaded = true;
|
||||
}
|
||||
|
||||
static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, POOL_TYPE pool_type, file_ref* fileref, ACCESS_MASK* granted_access,
|
||||
static NTSTATUS open_file3(device_extension* Vcb, PIRP Irp, ACCESS_MASK granted_access, file_ref* fileref, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
ULONG options = IrpSp->Parameters.Create.Options & FILE_VALID_OPTION_FLAGS;
|
||||
ULONG RequestedDisposition = ((IrpSp->Parameters.Create.Options >> 24) & 0xff);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
POOL_TYPE pool_type = IrpSp->Flags & SL_OPEN_PAGING_FILE ? NonPagedPool : PagedPool;
|
||||
ccb* ccb;
|
||||
|
||||
if (granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) {
|
||||
if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite))
|
||||
return (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) {
|
||||
ULONG defda, oldatts, filter;
|
||||
LARGE_INTEGER time;
|
||||
BTRFS_TIME now;
|
||||
|
||||
if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
|
||||
if (fileref->fcb->ads) {
|
||||
Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, false);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("stream_set_end_of_file_information returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
} else {
|
||||
Status = truncate_file(fileref->fcb, 0, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("truncate_file returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (Irp->Overlay.AllocationSize.QuadPart > 0) {
|
||||
Status = extend_file(fileref->fcb, fileref, Irp->Overlay.AllocationSize.QuadPart, true, NULL, rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("extend_file returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileref->fcb->ads) {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
if (Irp->AssociatedIrp.SystemBuffer && IrpSp->Parameters.Create.EaLength > 0) {
|
||||
ULONG offset;
|
||||
FILE_FULL_EA_INFORMATION* eainfo;
|
||||
|
||||
Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
|
||||
return Status;
|
||||
}
|
||||
|
||||
fileref->fcb->ealen = 4;
|
||||
|
||||
// capitalize EA name
|
||||
eainfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
do {
|
||||
STRING s;
|
||||
|
||||
s.Length = s.MaximumLength = eainfo->EaNameLength;
|
||||
s.Buffer = eainfo->EaName;
|
||||
|
||||
RtlUpperString(&s, &s);
|
||||
|
||||
fileref->fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
|
||||
|
||||
if (eainfo->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
|
||||
} while (true);
|
||||
|
||||
if (fileref->fcb->ea_xattr.Buffer)
|
||||
ExFreePool(fileref->fcb->ea_xattr.Buffer);
|
||||
|
||||
fileref->fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(pool_type, IrpSp->Parameters.Create.EaLength, ALLOC_TAG);
|
||||
if (!fileref->fcb->ea_xattr.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = (USHORT)IrpSp->Parameters.Create.EaLength;
|
||||
RtlCopyMemory(fileref->fcb->ea_xattr.Buffer, Irp->AssociatedIrp.SystemBuffer, fileref->fcb->ea_xattr.Length);
|
||||
} else {
|
||||
if (fileref->fcb->ea_xattr.Length > 0) {
|
||||
ExFreePool(fileref->fcb->ea_xattr.Buffer);
|
||||
fileref->fcb->ea_xattr.Buffer = NULL;
|
||||
fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = 0;
|
||||
|
||||
fileref->fcb->ea_changed = true;
|
||||
fileref->fcb->ealen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// remove streams and send notifications
|
||||
le = fileref->fcb->dir_children_index.Flink;
|
||||
while (le != &fileref->fcb->dir_children_index) {
|
||||
dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
|
||||
LIST_ENTRY* le2 = le->Flink;
|
||||
|
||||
if (dc->index == 0) {
|
||||
if (!dc->fileref) {
|
||||
file_ref* fr2;
|
||||
|
||||
Status = open_fileref_child(Vcb, fileref, &dc->name, true, true, true, PagedPool, &fr2, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
WARN("open_fileref_child returned %08lx\n", Status);
|
||||
}
|
||||
|
||||
if (dc->fileref) {
|
||||
queue_notification_fcb(fileref, FILE_NOTIFY_CHANGE_STREAM_NAME, FILE_ACTION_REMOVED_STREAM, &dc->name);
|
||||
|
||||
Status = delete_fileref(dc->fileref, NULL, false, NULL, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
||||
le = le2;
|
||||
}
|
||||
}
|
||||
|
||||
KeQuerySystemTime(&time);
|
||||
win_time_to_unix(time, &now);
|
||||
|
||||
filter = FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||
|
||||
if (fileref->fcb->ads) {
|
||||
fileref->parent->fcb->inode_item.st_mtime = now;
|
||||
fileref->parent->fcb->inode_item_changed = true;
|
||||
mark_fcb_dirty(fileref->parent->fcb);
|
||||
|
||||
queue_notification_fcb(fileref->parent, filter, FILE_ACTION_MODIFIED, &fileref->dc->name);
|
||||
} else {
|
||||
mark_fcb_dirty(fileref->fcb);
|
||||
|
||||
oldatts = fileref->fcb->atts;
|
||||
|
||||
defda = get_file_attributes(Vcb, fileref->fcb->subvol, fileref->fcb->inode, fileref->fcb->type,
|
||||
fileref->dc && fileref->dc->name.Length >= sizeof(WCHAR) && fileref->dc->name.Buffer[0] == '.', true, Irp);
|
||||
|
||||
if (RequestedDisposition == FILE_SUPERSEDE)
|
||||
fileref->fcb->atts = IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||
else
|
||||
fileref->fcb->atts |= IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
if (fileref->fcb->atts != oldatts) {
|
||||
fileref->fcb->atts_changed = true;
|
||||
fileref->fcb->atts_deleted = IrpSp->Parameters.Create.FileAttributes == defda;
|
||||
filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
fileref->fcb->inode_item.transid = Vcb->superblock.generation;
|
||||
fileref->fcb->inode_item.sequence++;
|
||||
fileref->fcb->inode_item.st_ctime = now;
|
||||
fileref->fcb->inode_item.st_mtime = now;
|
||||
fileref->fcb->inode_item_changed = true;
|
||||
|
||||
queue_notification_fcb(fileref, filter, FILE_ACTION_MODIFIED, NULL);
|
||||
}
|
||||
} else {
|
||||
if (options & FILE_NO_EA_KNOWLEDGE && fileref->fcb->ea_xattr.Length > 0) {
|
||||
FILE_FULL_EA_INFORMATION* ffei = (FILE_FULL_EA_INFORMATION*)fileref->fcb->ea_xattr.Buffer;
|
||||
|
||||
do {
|
||||
if (ffei->Flags & FILE_NEED_EA) {
|
||||
WARN("returning STATUS_ACCESS_DENIED as no EA knowledge\n");
|
||||
|
||||
return STATUS_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
if (ffei->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
ffei = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ffei) + ffei->NextEntryOffset);
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
FileObject->FsContext = fileref->fcb;
|
||||
|
||||
ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ccb), ALLOC_TAG);
|
||||
if (!ccb) {
|
||||
ERR("out of memory\n");
|
||||
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
RtlZeroMemory(ccb, sizeof(*ccb));
|
||||
|
||||
ccb->NodeType = BTRFS_NODE_TYPE_CCB;
|
||||
ccb->NodeSize = sizeof(*ccb);
|
||||
ccb->disposition = RequestedDisposition;
|
||||
ccb->options = options;
|
||||
ccb->query_dir_offset = 0;
|
||||
RtlInitUnicodeString(&ccb->query_string, NULL);
|
||||
ccb->has_wildcard = false;
|
||||
ccb->specific_file = false;
|
||||
ccb->access = granted_access;
|
||||
ccb->case_sensitive = IrpSp->Flags & SL_CASE_SENSITIVE;
|
||||
ccb->reserving = false;
|
||||
ccb->lxss = called_from_lxss();
|
||||
|
||||
ccb->fileref = fileref;
|
||||
|
||||
FileObject->FsContext2 = ccb;
|
||||
FileObject->SectionObjectPointer = &fileref->fcb->nonpaged->segment_object;
|
||||
|
||||
switch (RequestedDisposition) {
|
||||
case FILE_SUPERSEDE:
|
||||
Irp->IoStatus.Information = FILE_SUPERSEDED;
|
||||
break;
|
||||
|
||||
case FILE_OPEN:
|
||||
case FILE_OPEN_IF:
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
break;
|
||||
|
||||
case FILE_OVERWRITE:
|
||||
case FILE_OVERWRITE_IF:
|
||||
Irp->IoStatus.Information = FILE_OVERWRITTEN;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure paging files don't have any extents marked as being prealloc,
|
||||
// as this would mean we'd have to lock exclusively when writing.
|
||||
if (IrpSp->Flags & SL_OPEN_PAGING_FILE) {
|
||||
LIST_ENTRY* le;
|
||||
bool changed = false;
|
||||
|
||||
ExAcquireResourceExclusiveLite(fileref->fcb->Header.Resource, true);
|
||||
|
||||
le = fileref->fcb->extents.Flink;
|
||||
|
||||
while (le != &fileref->fcb->extents) {
|
||||
extent* ext = CONTAINING_RECORD(le, extent, list_entry);
|
||||
|
||||
if (ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
|
||||
ext->extent_data.type = EXTENT_TYPE_REGULAR;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
|
||||
if (changed) {
|
||||
fileref->fcb->extents_changed = true;
|
||||
mark_fcb_dirty(fileref->fcb);
|
||||
}
|
||||
|
||||
fileref->fcb->Header.Flags2 |= FSRTL_FLAG2_IS_PAGING_FILE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
LONG oc = InterlockedIncrement(&fileref->open_count);
|
||||
ERR("fileref %p: open_count now %i\n", fileref, oc);
|
||||
#else
|
||||
InterlockedIncrement(&fileref->open_count);
|
||||
#endif
|
||||
InterlockedIncrement(&Vcb->open_files);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void oplock_complete(PVOID Context, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY rollback;
|
||||
bool skip_lock;
|
||||
oplock_context* ctx = Context;
|
||||
device_extension* Vcb = ctx->Vcb;
|
||||
|
||||
TRACE("(%p, %p)\n", Context, Irp);
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
skip_lock = ExIsResourceAcquiredExclusiveLite(&Vcb->tree_lock);
|
||||
|
||||
if (!skip_lock)
|
||||
ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
|
||||
|
||||
ExAcquireResourceSharedLite(&Vcb->fileref_lock, true);
|
||||
|
||||
// FIXME - trans
|
||||
Status = open_file3(Vcb, Irp, ctx->granted_access, ctx->fileref, &rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free_fileref(ctx->fileref);
|
||||
do_rollback(ctx->Vcb, &rollback);
|
||||
} else
|
||||
clear_rollback(&rollback);
|
||||
|
||||
ExReleaseResourceLite(&Vcb->fileref_lock);
|
||||
|
||||
if (Status == STATUS_SUCCESS) {
|
||||
fcb* fcb2;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
PFILE_OBJECT FileObject = IrpSp->FileObject;
|
||||
bool skip_fcb_lock;
|
||||
|
||||
IrpSp->Parameters.Create.SecurityContext->AccessState->PreviouslyGrantedAccess |= ctx->granted_access;
|
||||
IrpSp->Parameters.Create.SecurityContext->AccessState->RemainingDesiredAccess &= ~(ctx->granted_access | MAXIMUM_ALLOWED);
|
||||
|
||||
if (!FileObject->Vpb)
|
||||
FileObject->Vpb = Vcb->devobj->Vpb;
|
||||
|
||||
fcb2 = FileObject->FsContext;
|
||||
|
||||
if (fcb2->ads) {
|
||||
struct _ccb* ccb2 = FileObject->FsContext2;
|
||||
|
||||
fcb2 = ccb2->fileref->parent->fcb;
|
||||
}
|
||||
|
||||
skip_fcb_lock = ExIsResourceAcquiredExclusiveLite(fcb2->Header.Resource);
|
||||
|
||||
if (!skip_fcb_lock)
|
||||
ExAcquireResourceExclusiveLite(fcb2->Header.Resource, true);
|
||||
|
||||
fcb_load_csums(Vcb, fcb2, Irp);
|
||||
|
||||
if (!skip_fcb_lock)
|
||||
ExReleaseResourceLite(fcb2->Header.Resource);
|
||||
}
|
||||
|
||||
if (!skip_lock)
|
||||
ExReleaseResourceLite(&Vcb->tree_lock);
|
||||
|
||||
// FIXME - call free_trans if failed and within transaction
|
||||
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
|
||||
|
||||
ExFreePool(ctx);
|
||||
}
|
||||
|
||||
static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, file_ref* fileref, ACCESS_MASK* granted_access,
|
||||
PFILE_OBJECT FileObject, UNICODE_STRING* fn, ULONG options, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
file_ref* sf;
|
||||
bool readonly;
|
||||
ccb* ccb;
|
||||
PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
if (RequestedDisposition == FILE_SUPERSEDE || RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) {
|
||||
|
@ -3675,6 +4011,12 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO
|
|||
Status = Vcb->readonly ? STATUS_MEDIA_WRITE_PROTECTED : STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) {
|
||||
WARN("cannot overwrite readonly file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fileref->fcb->type == BTRFS_TYPE_SYMLINK || fileref->fcb->atts & FILE_ATTRIBUTE_REPARSE_POINT) && !(options & FILE_OPEN_REPARSE_POINT)) {
|
||||
|
@ -3716,6 +4058,8 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO
|
|||
}
|
||||
|
||||
if (fileref->open_count > 0) {
|
||||
oplock_context* ctx;
|
||||
|
||||
Status = IoCheckShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access, false);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
@ -3727,296 +4071,37 @@ static NTSTATUS open_file2(device_extension* Vcb, ULONG RequestedDisposition, PO
|
|||
goto end;
|
||||
}
|
||||
|
||||
ctx = ExAllocatePoolWithTag(NonPagedPool, sizeof(oplock_context), ALLOC_TAG);
|
||||
if (!ctx) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end;
|
||||
}
|
||||
|
||||
ctx->Vcb = Vcb;
|
||||
ctx->granted_access = *granted_access;
|
||||
ctx->fileref = fileref;
|
||||
#ifdef __REACTOS__
|
||||
Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, ctx, (POPLOCK_WAIT_COMPLETE_ROUTINE) oplock_complete, NULL);
|
||||
#else
|
||||
Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, ctx, oplock_complete, NULL);
|
||||
#endif /* __REACTOS__ */
|
||||
if (Status == STATUS_PENDING)
|
||||
return Status;
|
||||
|
||||
ExFreePool(ctx);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
WARN("FsRtlCheckOplock returned %08lx\n", Status);
|
||||
goto end;
|
||||
}
|
||||
|
||||
IoUpdateShareAccess(FileObject, &fileref->fcb->share_access);
|
||||
} else
|
||||
IoSetShareAccess(*granted_access, IrpSp->Parameters.Create.ShareAccess, FileObject, &fileref->fcb->share_access);
|
||||
|
||||
if (*granted_access & FILE_WRITE_DATA || options & FILE_DELETE_ON_CLOSE) {
|
||||
if (!MmFlushImageSection(&fileref->fcb->nonpaged->segment_object, MmFlushForWrite)) {
|
||||
Status = (options & FILE_DELETE_ON_CLOSE) ? STATUS_CANNOT_DELETE : STATUS_SHARING_VIOLATION;
|
||||
goto end2;
|
||||
}
|
||||
}
|
||||
Status = open_file3(Vcb, Irp, *granted_access, fileref, rollback);
|
||||
|
||||
// FIXME - this can block waiting for network IO, while we're holding fileref_lock and tree_lock
|
||||
Status = FsRtlCheckOplock(fcb_oplock(fileref->fcb), Irp, NULL, NULL, NULL);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
WARN("FsRtlCheckOplock returned %08lx\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
|
||||
if (RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF || RequestedDisposition == FILE_SUPERSEDE) {
|
||||
ULONG defda, oldatts, filter;
|
||||
LARGE_INTEGER time;
|
||||
BTRFS_TIME now;
|
||||
|
||||
if ((RequestedDisposition == FILE_OVERWRITE || RequestedDisposition == FILE_OVERWRITE_IF) && readonly) {
|
||||
WARN("cannot overwrite readonly file\n");
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
if (!fileref->fcb->ads && (IrpSp->Parameters.Create.FileAttributes & (FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM)) != ((fileref->fcb->atts & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN)))) {
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
if (fileref->fcb->ads) {
|
||||
Status = stream_set_end_of_file_information(Vcb, 0, fileref->fcb, fileref, false);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("stream_set_end_of_file_information returned %08lx\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
} else {
|
||||
Status = truncate_file(fileref->fcb, 0, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("truncate_file returned %08lx\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
}
|
||||
|
||||
if (Irp->Overlay.AllocationSize.QuadPart > 0) {
|
||||
Status = extend_file(fileref->fcb, fileref, Irp->Overlay.AllocationSize.QuadPart, true, NULL, rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("extend_file returned %08lx\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fileref->fcb->ads) {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
if (Irp->AssociatedIrp.SystemBuffer && IrpSp->Parameters.Create.EaLength > 0) {
|
||||
ULONG offset;
|
||||
FILE_FULL_EA_INFORMATION* eainfo;
|
||||
|
||||
Status = IoCheckEaBufferValidity(Irp->AssociatedIrp.SystemBuffer, IrpSp->Parameters.Create.EaLength, &offset);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("IoCheckEaBufferValidity returned %08lx (error at offset %lu)\n", Status, offset);
|
||||
goto end2;
|
||||
}
|
||||
|
||||
fileref->fcb->ealen = 4;
|
||||
|
||||
// capitalize EA name
|
||||
eainfo = Irp->AssociatedIrp.SystemBuffer;
|
||||
do {
|
||||
STRING s;
|
||||
|
||||
s.Length = s.MaximumLength = eainfo->EaNameLength;
|
||||
s.Buffer = eainfo->EaName;
|
||||
|
||||
RtlUpperString(&s, &s);
|
||||
|
||||
fileref->fcb->ealen += 5 + eainfo->EaNameLength + eainfo->EaValueLength;
|
||||
|
||||
if (eainfo->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
eainfo = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)eainfo) + eainfo->NextEntryOffset);
|
||||
} while (true);
|
||||
|
||||
if (fileref->fcb->ea_xattr.Buffer)
|
||||
ExFreePool(fileref->fcb->ea_xattr.Buffer);
|
||||
|
||||
fileref->fcb->ea_xattr.Buffer = ExAllocatePoolWithTag(pool_type, IrpSp->Parameters.Create.EaLength, ALLOC_TAG);
|
||||
if (!fileref->fcb->ea_xattr.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = (USHORT)IrpSp->Parameters.Create.EaLength;
|
||||
RtlCopyMemory(fileref->fcb->ea_xattr.Buffer, Irp->AssociatedIrp.SystemBuffer, fileref->fcb->ea_xattr.Length);
|
||||
} else {
|
||||
if (fileref->fcb->ea_xattr.Length > 0) {
|
||||
ExFreePool(fileref->fcb->ea_xattr.Buffer);
|
||||
fileref->fcb->ea_xattr.Buffer = NULL;
|
||||
fileref->fcb->ea_xattr.Length = fileref->fcb->ea_xattr.MaximumLength = 0;
|
||||
|
||||
fileref->fcb->ea_changed = true;
|
||||
fileref->fcb->ealen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// remove streams and send notifications
|
||||
le = fileref->fcb->dir_children_index.Flink;
|
||||
while (le != &fileref->fcb->dir_children_index) {
|
||||
dir_child* dc = CONTAINING_RECORD(le, dir_child, list_entry_index);
|
||||
LIST_ENTRY* le2 = le->Flink;
|
||||
|
||||
if (dc->index == 0) {
|
||||
if (!dc->fileref) {
|
||||
file_ref* fr2;
|
||||
|
||||
Status = open_fileref_child(Vcb, fileref, &dc->name, true, true, true, PagedPool, &fr2, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
WARN("open_fileref_child returned %08lx\n", Status);
|
||||
}
|
||||
|
||||
if (dc->fileref) {
|
||||
queue_notification_fcb(fileref, FILE_NOTIFY_CHANGE_STREAM_NAME, FILE_ACTION_REMOVED_STREAM, &dc->name);
|
||||
|
||||
Status = delete_fileref(dc->fileref, NULL, false, NULL, rollback);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("delete_fileref returned %08lx\n", Status);
|
||||
goto end2;
|
||||
}
|
||||
}
|
||||
} else
|
||||
break;
|
||||
|
||||
le = le2;
|
||||
}
|
||||
}
|
||||
|
||||
KeQuerySystemTime(&time);
|
||||
win_time_to_unix(time, &now);
|
||||
|
||||
filter = FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE;
|
||||
|
||||
if (fileref->fcb->ads) {
|
||||
fileref->parent->fcb->inode_item.st_mtime = now;
|
||||
fileref->parent->fcb->inode_item_changed = true;
|
||||
mark_fcb_dirty(fileref->parent->fcb);
|
||||
|
||||
queue_notification_fcb(fileref->parent, filter, FILE_ACTION_MODIFIED, &fileref->dc->name);
|
||||
} else {
|
||||
mark_fcb_dirty(fileref->fcb);
|
||||
|
||||
oldatts = fileref->fcb->atts;
|
||||
|
||||
defda = get_file_attributes(Vcb, fileref->fcb->subvol, fileref->fcb->inode, fileref->fcb->type,
|
||||
fileref->dc && fileref->dc->name.Length >= sizeof(WCHAR) && fileref->dc->name.Buffer[0] == '.', true, Irp);
|
||||
|
||||
if (RequestedDisposition == FILE_SUPERSEDE)
|
||||
fileref->fcb->atts = IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||
else
|
||||
fileref->fcb->atts |= IrpSp->Parameters.Create.FileAttributes | FILE_ATTRIBUTE_ARCHIVE;
|
||||
|
||||
if (fileref->fcb->atts != oldatts) {
|
||||
fileref->fcb->atts_changed = true;
|
||||
fileref->fcb->atts_deleted = IrpSp->Parameters.Create.FileAttributes == defda;
|
||||
filter |= FILE_NOTIFY_CHANGE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
fileref->fcb->inode_item.transid = Vcb->superblock.generation;
|
||||
fileref->fcb->inode_item.sequence++;
|
||||
fileref->fcb->inode_item.st_ctime = now;
|
||||
fileref->fcb->inode_item.st_mtime = now;
|
||||
fileref->fcb->inode_item_changed = true;
|
||||
|
||||
queue_notification_fcb(fileref, filter, FILE_ACTION_MODIFIED, NULL);
|
||||
}
|
||||
} else {
|
||||
if (options & FILE_NO_EA_KNOWLEDGE && fileref->fcb->ea_xattr.Length > 0) {
|
||||
FILE_FULL_EA_INFORMATION* ffei = (FILE_FULL_EA_INFORMATION*)fileref->fcb->ea_xattr.Buffer;
|
||||
|
||||
do {
|
||||
if (ffei->Flags & FILE_NEED_EA) {
|
||||
WARN("returning STATUS_ACCESS_DENIED as no EA knowledge\n");
|
||||
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
if (ffei->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
ffei = (FILE_FULL_EA_INFORMATION*)(((uint8_t*)ffei) + ffei->NextEntryOffset);
|
||||
} while (true);
|
||||
}
|
||||
}
|
||||
|
||||
FileObject->FsContext = fileref->fcb;
|
||||
|
||||
ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(*ccb), ALLOC_TAG);
|
||||
if (!ccb) {
|
||||
ERR("out of memory\n");
|
||||
|
||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
RtlZeroMemory(ccb, sizeof(*ccb));
|
||||
|
||||
ccb->NodeType = BTRFS_NODE_TYPE_CCB;
|
||||
ccb->NodeSize = sizeof(*ccb);
|
||||
ccb->disposition = RequestedDisposition;
|
||||
ccb->options = options;
|
||||
ccb->query_dir_offset = 0;
|
||||
RtlInitUnicodeString(&ccb->query_string, NULL);
|
||||
ccb->has_wildcard = false;
|
||||
ccb->specific_file = false;
|
||||
ccb->access = *granted_access;
|
||||
ccb->case_sensitive = IrpSp->Flags & SL_CASE_SENSITIVE;
|
||||
ccb->reserving = false;
|
||||
ccb->lxss = called_from_lxss();
|
||||
|
||||
ccb->fileref = fileref;
|
||||
|
||||
FileObject->FsContext2 = ccb;
|
||||
FileObject->SectionObjectPointer = &fileref->fcb->nonpaged->segment_object;
|
||||
|
||||
switch (RequestedDisposition) {
|
||||
case FILE_SUPERSEDE:
|
||||
Irp->IoStatus.Information = FILE_SUPERSEDED;
|
||||
break;
|
||||
|
||||
case FILE_OPEN:
|
||||
case FILE_OPEN_IF:
|
||||
Irp->IoStatus.Information = FILE_OPENED;
|
||||
break;
|
||||
|
||||
case FILE_OVERWRITE:
|
||||
case FILE_OVERWRITE_IF:
|
||||
Irp->IoStatus.Information = FILE_OVERWRITTEN;
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure paging files don't have any extents marked as being prealloc,
|
||||
// as this would mean we'd have to lock exclusively when writing.
|
||||
if (IrpSp->Flags & SL_OPEN_PAGING_FILE) {
|
||||
LIST_ENTRY* le;
|
||||
bool changed = false;
|
||||
|
||||
ExAcquireResourceExclusiveLite(fileref->fcb->Header.Resource, true);
|
||||
|
||||
le = fileref->fcb->extents.Flink;
|
||||
|
||||
while (le != &fileref->fcb->extents) {
|
||||
extent* ext = CONTAINING_RECORD(le, extent, list_entry);
|
||||
|
||||
if (ext->extent_data.type == EXTENT_TYPE_PREALLOC) {
|
||||
ext->extent_data.type = EXTENT_TYPE_REGULAR;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
|
||||
ExReleaseResourceLite(fileref->fcb->Header.Resource);
|
||||
|
||||
if (changed) {
|
||||
fileref->fcb->extents_changed = true;
|
||||
mark_fcb_dirty(fileref->fcb);
|
||||
}
|
||||
|
||||
fileref->fcb->Header.Flags2 |= FSRTL_FLAG2_IS_PAGING_FILE;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FCB_REFCOUNTS
|
||||
LONG oc = InterlockedIncrement(&fileref->open_count);
|
||||
ERR("fileref %p: open_count now %i\n", fileref, oc);
|
||||
#else
|
||||
InterlockedIncrement(&fileref->open_count);
|
||||
#endif
|
||||
InterlockedIncrement(&Vcb->open_files);
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
|
||||
end2:
|
||||
if (!NT_SUCCESS(Status))
|
||||
IoRemoveShareAccess(FileObject, &fileref->fcb->share_access);
|
||||
|
||||
|
@ -4106,9 +4191,6 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
if (tp.item->key.obj_id == fcb->inode) {
|
||||
if (tp.item->key.obj_type == TYPE_INODE_REF) {
|
||||
INODE_REF* ir = (INODE_REF*)tp.item->data;
|
||||
#ifdef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
if (tp.item->size < offsetof(INODE_REF, name[0]) || tp.item->size < offsetof(INODE_REF, name[0]) + ir->n) {
|
||||
ERR("INODE_REF was too short\n");
|
||||
|
@ -4116,9 +4198,7 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
Status = utf8_to_utf16(NULL, 0, &stringlen, ir->name, ir->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
@ -4156,9 +4236,6 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
break;
|
||||
} else if (tp.item->key.obj_type == TYPE_INODE_EXTREF) {
|
||||
INODE_EXTREF* ier = (INODE_EXTREF*)tp.item->data;
|
||||
#ifdef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
if (tp.item->size < offsetof(INODE_EXTREF, name[0]) || tp.item->size < offsetof(INODE_EXTREF, name[0]) + ier->n) {
|
||||
ERR("INODE_EXTREF was too short\n");
|
||||
|
@ -4166,9 +4243,7 @@ NTSTATUS open_fileref_by_inode(_Requires_exclusive_lock_held_(_Curr_->fcb_lock)
|
|||
return STATUS_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
ULONG stringlen;
|
||||
#endif
|
||||
|
||||
Status = utf8_to_utf16(NULL, 0, &stringlen, ier->name, ier->n);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
|
@ -4601,11 +4676,9 @@ loaded:
|
|||
goto exit;
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(Status)) { // file already exists
|
||||
Status = open_file2(Vcb, RequestedDisposition, pool_type, fileref, &granted_access, FileObject, &fn, options, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto exit;
|
||||
} else {
|
||||
if (NT_SUCCESS(Status)) // file already exists
|
||||
Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn, options, Irp, rollback);
|
||||
else {
|
||||
file_ref* existing_file = NULL;
|
||||
|
||||
Status = file_create(Irp, Vcb, FileObject, related, loaded_related, &fn, RequestedDisposition, options, &existing_file, rollback);
|
||||
|
@ -4613,9 +4686,7 @@ loaded:
|
|||
if (Status == STATUS_OBJECT_NAME_COLLISION) { // already exists
|
||||
fileref = existing_file;
|
||||
|
||||
Status = open_file2(Vcb, RequestedDisposition, pool_type, fileref, &granted_access, FileObject, &fn, options, Irp, rollback);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto exit;
|
||||
Status = open_file2(Vcb, RequestedDisposition, fileref, &granted_access, FileObject, &fn, options, Irp, rollback);
|
||||
} else {
|
||||
Irp->IoStatus.Information = NT_SUCCESS(Status) ? FILE_CREATED : 0;
|
||||
granted_access = IrpSp->Parameters.Create.SecurityContext->DesiredAccess;
|
||||
|
@ -4928,7 +4999,11 @@ NTSTATUS __stdcall drv_create(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) {
|
|||
|
||||
exit:
|
||||
Irp->IoStatus.Status = Status;
|
||||
IoCompleteRequest( Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT );
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
IoMarkIrpPending(Irp);
|
||||
else
|
||||
IoCompleteRequest(Irp, NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT);
|
||||
|
||||
TRACE("create returning %08lx\n", Status);
|
||||
|
||||
|
|
|
@ -499,6 +499,50 @@ static BOOLEAN __stdcall fast_io_unlock_all_by_key(PFILE_OBJECT FileObject, PVOI
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
_Function_class_(FAST_IO_ACQUIRE_FILE)
|
||||
static void __stdcall fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject) {
|
||||
#else
|
||||
static void fast_io_acquire_for_create_section(_In_ PFILE_OBJECT FileObject) {
|
||||
#endif /* __REACTOS__ */
|
||||
fcb* fcb;
|
||||
|
||||
TRACE("(%p)\n", FileObject);
|
||||
|
||||
if (!FileObject)
|
||||
return;
|
||||
|
||||
fcb = FileObject->FsContext;
|
||||
|
||||
if (!fcb)
|
||||
return;
|
||||
|
||||
ExAcquireResourceSharedLite(&fcb->Vcb->tree_lock, true);
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
_Function_class_(FAST_IO_RELEASE_FILE)
|
||||
static void __stdcall fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject) {
|
||||
#else
|
||||
static void fast_io_release_for_create_section(_In_ PFILE_OBJECT FileObject) {
|
||||
#endif /* __REACTOS__ */
|
||||
fcb* fcb;
|
||||
|
||||
TRACE("(%p)\n", FileObject);
|
||||
|
||||
if (!FileObject)
|
||||
return;
|
||||
|
||||
fcb = FileObject->FsContext;
|
||||
|
||||
if (!fcb)
|
||||
return;
|
||||
|
||||
ExReleaseResourceLite(fcb->Header.Resource);
|
||||
ExReleaseResourceLite(&fcb->Vcb->tree_lock);
|
||||
}
|
||||
|
||||
void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
|
||||
RtlZeroMemory(&FastIoDispatch, sizeof(FastIoDispatch));
|
||||
|
||||
|
@ -513,6 +557,8 @@ void init_fast_io_dispatch(FAST_IO_DISPATCH** fiod) {
|
|||
FastIoDispatch.FastIoUnlockSingle = fast_io_unlock_single;
|
||||
FastIoDispatch.FastIoUnlockAll = fast_io_unlock_all;
|
||||
FastIoDispatch.FastIoUnlockAllByKey = fast_io_unlock_all_by_key;
|
||||
FastIoDispatch.AcquireFileForNtCreateSection = fast_io_acquire_for_create_section;
|
||||
FastIoDispatch.ReleaseFileForNtCreateSection = fast_io_release_for_create_section;
|
||||
FastIoDispatch.FastIoQueryNetworkOpenInfo = fast_io_query_network_open_info;
|
||||
FastIoDispatch.AcquireForModWrite = fast_io_acquire_for_mod_write;
|
||||
FastIoDispatch.MdlRead = FsRtlMdlReadDev;
|
||||
|
|
|
@ -801,6 +801,7 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
|
|||
|
||||
fcb->subvol = r;
|
||||
fcb->inode = InterlockedIncrement64(&r->lastinode);
|
||||
fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
|
||||
fcb->type = BTRFS_TYPE_DIRECTORY;
|
||||
|
||||
fcb->inode_item.generation = Vcb->superblock.generation;
|
||||
|
@ -872,7 +873,7 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
|
|||
RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
|
||||
|
||||
acquire_fcb_lock_exclusive(Vcb);
|
||||
InsertTailList(&r->fcbs, &fcb->list_entry);
|
||||
add_fcb_to_subvol(fcb);
|
||||
InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
|
||||
r->fcbs_version++;
|
||||
release_fcb_lock(Vcb);
|
||||
|
@ -884,6 +885,68 @@ static NTSTATUS create_directory_fcb(device_extension* Vcb, root* r, fcb* parfcb
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void add_fcb_to_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb) {
|
||||
LIST_ENTRY* lastle = NULL;
|
||||
uint32_t hash = fcb->hash;
|
||||
|
||||
if (fcb->subvol->fcbs_ptrs[hash >> 24]) {
|
||||
LIST_ENTRY* le = fcb->subvol->fcbs_ptrs[hash >> 24];
|
||||
|
||||
while (le != &fcb->subvol->fcbs) {
|
||||
struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
|
||||
|
||||
if (fcb2->hash > hash) {
|
||||
lastle = le->Blink;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
if (!lastle) {
|
||||
uint8_t c = hash >> 24;
|
||||
|
||||
if (c != 0xff) {
|
||||
uint8_t d = c + 1;
|
||||
|
||||
do {
|
||||
if (fcb->subvol->fcbs_ptrs[d]) {
|
||||
lastle = fcb->subvol->fcbs_ptrs[d]->Blink;
|
||||
break;
|
||||
}
|
||||
|
||||
d++;
|
||||
} while (d != 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (lastle) {
|
||||
InsertHeadList(lastle, &fcb->list_entry);
|
||||
|
||||
if (lastle == &fcb->subvol->fcbs || (CONTAINING_RECORD(lastle, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
|
||||
fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
|
||||
} else {
|
||||
InsertTailList(&fcb->subvol->fcbs, &fcb->list_entry);
|
||||
|
||||
if (fcb->list_entry.Blink == &fcb->subvol->fcbs || (CONTAINING_RECORD(fcb->list_entry.Blink, struct _fcb, list_entry)->hash >> 24) != (hash >> 24))
|
||||
fcb->subvol->fcbs_ptrs[hash >> 24] = &fcb->list_entry;
|
||||
}
|
||||
}
|
||||
|
||||
void remove_fcb_from_subvol(_In_ _Requires_exclusive_lock_held_(_Curr_->Vcb->fcb_lock) fcb* fcb) {
|
||||
uint8_t c = fcb->hash >> 24;
|
||||
|
||||
if (fcb->subvol->fcbs_ptrs[c] == &fcb->list_entry) {
|
||||
if (fcb->list_entry.Flink != &fcb->subvol->fcbs && (CONTAINING_RECORD(fcb->list_entry.Flink, struct _fcb, list_entry)->hash >> 24) == c)
|
||||
fcb->subvol->fcbs_ptrs[c] = fcb->list_entry.Flink;
|
||||
else
|
||||
fcb->subvol->fcbs_ptrs[c] = NULL;
|
||||
}
|
||||
|
||||
RemoveEntryList(&fcb->list_entry);
|
||||
}
|
||||
|
||||
static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destdir, PANSI_STRING utf8, PUNICODE_STRING fnus, PIRP Irp, LIST_ENTRY* rollback) {
|
||||
NTSTATUS Status;
|
||||
LIST_ENTRY move_list, *le;
|
||||
|
@ -930,6 +993,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("add_children_to_move_list returned %08lx\n", Status);
|
||||
ExReleaseResourceLite(me->fileref->fcb->Header.Resource);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
@ -950,8 +1014,6 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
if (me->fileref->fcb->inode != SUBVOL_ROOT_INODE && me->fileref->fcb != fileref->fcb->Vcb->dummy_fcb) {
|
||||
if (!me->dummyfcb) {
|
||||
ULONG defda;
|
||||
bool inserted = false;
|
||||
LIST_ENTRY* le3;
|
||||
|
||||
ExAcquireResourceExclusiveLite(me->fileref->fcb->Header.Resource, true);
|
||||
|
||||
|
@ -964,6 +1026,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
|
||||
me->dummyfcb->subvol = me->fileref->fcb->subvol;
|
||||
me->dummyfcb->inode = me->fileref->fcb->inode;
|
||||
me->dummyfcb->hash = me->fileref->fcb->hash;
|
||||
|
||||
if (!me->dummyfcb->ads) {
|
||||
me->dummyfcb->sd_dirty = me->fileref->fcb->sd_dirty;
|
||||
|
@ -983,6 +1046,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
|
||||
me->fileref->fcb->subvol = destdir->fcb->subvol;
|
||||
me->fileref->fcb->inode = InterlockedIncrement64(&destdir->fcb->subvol->lastinode);
|
||||
me->fileref->fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&me->fileref->fcb->inode, sizeof(uint64_t));
|
||||
me->fileref->fcb->inode_item.st_nlink = 1;
|
||||
|
||||
defda = get_file_attributes(me->fileref->fcb->Vcb, me->fileref->fcb->subvol, me->fileref->fcb->inode,
|
||||
|
@ -1042,32 +1106,21 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
|
||||
le2 = le2->Flink;
|
||||
}
|
||||
|
||||
add_fcb_to_subvol(me->dummyfcb);
|
||||
remove_fcb_from_subvol(me->fileref->fcb);
|
||||
add_fcb_to_subvol(me->fileref->fcb);
|
||||
} else {
|
||||
me->fileref->fcb->subvol = me->parent->fileref->fcb->subvol;
|
||||
me->fileref->fcb->inode = me->parent->fileref->fcb->inode;
|
||||
me->fileref->fcb->hash = me->parent->fileref->fcb->hash;
|
||||
|
||||
// put stream after parent in FCB list
|
||||
InsertHeadList(&me->parent->fileref->fcb->list_entry, &me->fileref->fcb->list_entry);
|
||||
}
|
||||
|
||||
me->fileref->fcb->created = true;
|
||||
|
||||
InsertHeadList(&me->fileref->fcb->list_entry, &me->dummyfcb->list_entry);
|
||||
RemoveEntryList(&me->fileref->fcb->list_entry);
|
||||
|
||||
le3 = destdir->fcb->subvol->fcbs.Flink;
|
||||
while (le3 != &destdir->fcb->subvol->fcbs) {
|
||||
fcb* fcb = CONTAINING_RECORD(le3, struct _fcb, list_entry);
|
||||
|
||||
if (fcb->inode > me->fileref->fcb->inode) {
|
||||
InsertHeadList(le3->Blink, &me->fileref->fcb->list_entry);
|
||||
inserted = true;
|
||||
break;
|
||||
}
|
||||
|
||||
le3 = le3->Flink;
|
||||
}
|
||||
|
||||
if (!inserted)
|
||||
InsertTailList(&destdir->fcb->subvol->fcbs, &me->fileref->fcb->list_entry);
|
||||
|
||||
InsertTailList(&me->fileref->fcb->Vcb->all_fcbs, &me->dummyfcb->list_entry_all);
|
||||
|
||||
while (!IsListEmpty(&me->fileref->fcb->hardlinks)) {
|
||||
|
@ -1159,7 +1212,7 @@ static NTSTATUS move_across_subvols(file_ref* fileref, ccb* ccb, file_ref* destd
|
|||
if (le == move_list.Flink && (me->fileref->dc->utf8.Length != utf8->Length || RtlCompareMemory(me->fileref->dc->utf8.Buffer, utf8->Buffer, utf8->Length) != utf8->Length))
|
||||
name_changed = true;
|
||||
|
||||
if ((le == move_list.Flink || me->fileref->fcb->inode == SUBVOL_ROOT_INODE) && !me->dummyfileref->oldutf8.Buffer) {
|
||||
if (!me->dummyfileref->oldutf8.Buffer) {
|
||||
me->dummyfileref->oldutf8.Buffer = ExAllocatePoolWithTag(PagedPool, me->fileref->dc->utf8.Length, ALLOC_TAG);
|
||||
if (!me->dummyfileref->oldutf8.Buffer) {
|
||||
ERR("out of memory\n");
|
||||
|
@ -1773,11 +1826,18 @@ static NTSTATUS rename_stream_to_file(device_extension* Vcb, file_ref* fileref,
|
|||
dummyfcb->Vcb = Vcb;
|
||||
dummyfcb->subvol = fileref->fcb->subvol;
|
||||
dummyfcb->inode = fileref->fcb->inode;
|
||||
dummyfcb->hash = fileref->fcb->hash;
|
||||
dummyfcb->adsxattr = fileref->fcb->adsxattr;
|
||||
dummyfcb->adshash = fileref->fcb->adshash;
|
||||
dummyfcb->ads = true;
|
||||
dummyfcb->deleted = true;
|
||||
|
||||
acquire_fcb_lock_exclusive(Vcb);
|
||||
add_fcb_to_subvol(dummyfcb);
|
||||
InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all);
|
||||
dummyfcb->subvol->fcbs_version++;
|
||||
release_fcb_lock(Vcb);
|
||||
|
||||
// FIXME - dummyfileref as well?
|
||||
|
||||
mark_fcb_dirty(dummyfcb);
|
||||
|
@ -1839,9 +1899,10 @@ static NTSTATUS rename_stream(device_extension* Vcb, file_ref* fileref, ccb* ccb
|
|||
if (fn.Length == 0)
|
||||
return rename_stream_to_file(Vcb, fileref, ccb, flags, Irp, rollback);
|
||||
|
||||
if (!is_file_name_valid(&fn, false, true)) {
|
||||
Status = check_file_name_valid(&fn, false, true);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && fileref->parent->fcb->atts & FILE_ATTRIBUTE_READONLY) {
|
||||
|
@ -1989,11 +2050,18 @@ static NTSTATUS rename_stream(device_extension* Vcb, file_ref* fileref, ccb* ccb
|
|||
dummyfcb->Vcb = Vcb;
|
||||
dummyfcb->subvol = fileref->fcb->subvol;
|
||||
dummyfcb->inode = fileref->fcb->inode;
|
||||
dummyfcb->hash = fileref->fcb->hash;
|
||||
dummyfcb->adsxattr = fileref->fcb->adsxattr;
|
||||
dummyfcb->adshash = fileref->fcb->adshash;
|
||||
dummyfcb->ads = true;
|
||||
dummyfcb->deleted = true;
|
||||
|
||||
acquire_fcb_lock_exclusive(Vcb);
|
||||
add_fcb_to_subvol(dummyfcb);
|
||||
InsertTailList(&Vcb->all_fcbs, &dummyfcb->list_entry_all);
|
||||
dummyfcb->subvol->fcbs_version++;
|
||||
release_fcb_lock(Vcb);
|
||||
|
||||
mark_fcb_dirty(dummyfcb);
|
||||
|
||||
free_fcb(dummyfcb);
|
||||
|
@ -2078,9 +2146,10 @@ static NTSTATUS rename_file_to_stream(device_extension* Vcb, file_ref* fileref,
|
|||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!is_file_name_valid(&fn, false, true)) {
|
||||
Status = check_file_name_valid(&fn, false, true);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
WARN("invalid stream name %.*S\n", (int)(fn.Length / sizeof(WCHAR)), fn.Buffer);
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (!(flags & FILE_RENAME_IGNORE_READONLY_ATTRIBUTE) && fileref->fcb->atts & FILE_ATTRIBUTE_READONLY) {
|
||||
|
@ -2468,9 +2537,6 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
ACCESS_MASK access;
|
||||
ULONG flags;
|
||||
#ifdef __REACTOS__
|
||||
unsigned int i;
|
||||
#endif
|
||||
|
||||
InitializeListHead(&rollback);
|
||||
|
||||
|
@ -2504,7 +2570,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
for (i = fnlen - 1; i >= 0; i--) {
|
||||
if (fri->FileName[i] == '\\' || fri->FileName[i] == '/') {
|
||||
fn = &fri->FileName[i+1];
|
||||
fnlen = (fri->FileNameLength / sizeof(WCHAR)) - i - 1;
|
||||
fnlen -= i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2555,11 +2621,7 @@ static NTSTATUS set_rename_information(device_extension* Vcb, PIRP Irp, PFILE_OB
|
|||
|
||||
TRACE("fnus = %.*S\n", (int)(fnus.Length / sizeof(WCHAR)), fnus.Buffer);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
for (unsigned int i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) {
|
||||
#else
|
||||
for (i = 0 ; i < fnus.Length / sizeof(WCHAR); i++) {
|
||||
#endif
|
||||
if (fnus.Buffer[i] == ':') {
|
||||
TRACE("colon in filename\n");
|
||||
Status = STATUS_OBJECT_NAME_INVALID;
|
||||
|
|
|
@ -1150,6 +1150,7 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, bool* chan
|
|||
c->cache->subvol = Vcb->root_root;
|
||||
|
||||
c->cache->inode = InterlockedIncrement64(&Vcb->root_root->lastinode);
|
||||
c->cache->hash = calc_crc32c(0xffffffff, (uint8_t*)&c->cache->inode, sizeof(uint64_t));
|
||||
|
||||
c->cache->type = BTRFS_TYPE_FILE;
|
||||
c->cache->created = true;
|
||||
|
@ -1214,6 +1215,8 @@ static NTSTATUS allocate_cache_chunk(device_extension* Vcb, chunk* c, bool* chan
|
|||
c->cache->extents_changed = true;
|
||||
InsertTailList(&Vcb->all_fcbs, &c->cache->list_entry_all);
|
||||
|
||||
add_fcb_to_subvol(c->cache);
|
||||
|
||||
Status = flush_fcb(c->cache, true, batchlist, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("flush_fcb returned %08lx\n", Status);
|
||||
|
|
|
@ -601,8 +601,9 @@ static NTSTATUS create_snapshot(device_extension* Vcb, PFILE_OBJECT FileObject,
|
|||
if (is_subvol_readonly(fcb->subvol, Irp))
|
||||
return STATUS_ACCESS_DENIED;
|
||||
|
||||
if (!is_file_name_valid(&nameus, posix, false))
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
Status = check_file_name_valid(&nameus, posix, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
utf8.Buffer = NULL;
|
||||
|
||||
|
@ -823,8 +824,9 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
|
|||
nameus.Length = nameus.MaximumLength = bcs->namelen;
|
||||
nameus.Buffer = bcs->name;
|
||||
|
||||
if (!is_file_name_valid(&nameus, bcs->posix, false))
|
||||
return STATUS_OBJECT_NAME_INVALID;
|
||||
Status = check_file_name_valid(&nameus, bcs->posix, false);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
utf8.Buffer = NULL;
|
||||
|
||||
|
@ -961,8 +963,9 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
|
|||
rootfcb->Vcb = Vcb;
|
||||
|
||||
rootfcb->subvol = r;
|
||||
rootfcb->inode = SUBVOL_ROOT_INODE;
|
||||
rootfcb->type = BTRFS_TYPE_DIRECTORY;
|
||||
rootfcb->inode = SUBVOL_ROOT_INODE;
|
||||
rootfcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&rootfcb->inode, sizeof(uint64_t)); // FIXME - we can hardcode this
|
||||
|
||||
rootfcb->inode_item.generation = Vcb->superblock.generation;
|
||||
rootfcb->inode_item.transid = Vcb->superblock.generation;
|
||||
|
@ -1006,7 +1009,7 @@ static NTSTATUS create_subvol(device_extension* Vcb, PFILE_OBJECT FileObject, vo
|
|||
rootfcb->inode_item_changed = true;
|
||||
|
||||
acquire_fcb_lock_exclusive(Vcb);
|
||||
InsertTailList(&r->fcbs, &rootfcb->list_entry);
|
||||
add_fcb_to_subvol(rootfcb);
|
||||
InsertTailList(&Vcb->all_fcbs, &rootfcb->list_entry_all);
|
||||
r->fcbs_version++;
|
||||
release_fcb_lock(Vcb);
|
||||
|
@ -3693,6 +3696,44 @@ end:
|
|||
return Status;
|
||||
}
|
||||
|
||||
static NTSTATUS check_inode_used(_In_ _Requires_exclusive_lock_held_(_Curr_->tree_lock) device_extension* Vcb,
|
||||
_In_ root* subvol, _In_ uint64_t inode, _In_ uint32_t hash, _In_opt_ PIRP Irp) {
|
||||
KEY searchkey;
|
||||
traverse_ptr tp;
|
||||
NTSTATUS Status;
|
||||
uint8_t c = hash >> 24;
|
||||
|
||||
if (subvol->fcbs_ptrs[c]) {
|
||||
LIST_ENTRY* le = subvol->fcbs_ptrs[c];
|
||||
|
||||
while (le != &subvol->fcbs) {
|
||||
struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
|
||||
|
||||
if (fcb2->inode == inode)
|
||||
return STATUS_SUCCESS;
|
||||
else if (fcb2->hash > hash)
|
||||
break;
|
||||
|
||||
le = le->Flink;
|
||||
}
|
||||
}
|
||||
|
||||
searchkey.obj_id = inode;
|
||||
searchkey.obj_type = TYPE_INODE_ITEM;
|
||||
searchkey.offset = 0xffffffffffffffff;
|
||||
|
||||
Status = find_item(Vcb, subvol, &tp, &searchkey, false, Irp);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("find_item returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (tp.item->key.obj_id == searchkey.obj_id && tp.item->key.obj_type == searchkey.obj_type)
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data, ULONG datalen, PIRP Irp) {
|
||||
NTSTATUS Status;
|
||||
btrfs_mknod* bmn;
|
||||
|
@ -3705,7 +3746,6 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
|
|||
dir_child* dc;
|
||||
LARGE_INTEGER time;
|
||||
BTRFS_TIME now;
|
||||
LIST_ENTRY* lastle;
|
||||
ANSI_STRING utf8;
|
||||
ULONG len, i;
|
||||
SECURITY_SUBJECT_CONTEXT subjcont;
|
||||
|
@ -3925,35 +3965,33 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
|
|||
acquire_fcb_lock_exclusive(Vcb);
|
||||
|
||||
if (bmn->inode == 0) {
|
||||
inode = InterlockedIncrement64(&parfcb->subvol->lastinode);
|
||||
lastle = parfcb->subvol->fcbs.Blink;
|
||||
fcb->inode = InterlockedIncrement64(&parfcb->subvol->lastinode);
|
||||
fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
|
||||
} else {
|
||||
if (bmn->inode > (uint64_t)parfcb->subvol->lastinode) {
|
||||
inode = parfcb->subvol->lastinode = bmn->inode;
|
||||
lastle = parfcb->subvol->fcbs.Blink;
|
||||
fcb->inode = parfcb->subvol->lastinode = bmn->inode;
|
||||
fcb->hash = calc_crc32c(0xffffffff, (uint8_t*)&fcb->inode, sizeof(uint64_t));
|
||||
} else {
|
||||
LIST_ENTRY* le = parfcb->subvol->fcbs.Flink;
|
||||
uint32_t hash = calc_crc32c(0xffffffff, (uint8_t*)&bmn->inode, sizeof(uint64_t));
|
||||
|
||||
lastle = parfcb->subvol->fcbs.Blink;;
|
||||
while (le != &parfcb->subvol->fcbs) {
|
||||
struct _fcb* fcb2 = CONTAINING_RECORD(le, struct _fcb, list_entry);
|
||||
Status = check_inode_used(Vcb, subvol, bmn->inode, hash, Irp);
|
||||
if (NT_SUCCESS(Status)) { // STATUS_SUCCESS means inode found
|
||||
release_fcb_lock(Vcb);
|
||||
ExReleaseResourceLite(&Vcb->fileref_lock);
|
||||
|
||||
if (fcb2->inode == bmn->inode && !fcb2->deleted) {
|
||||
release_fcb_lock(Vcb);
|
||||
ExReleaseResourceLite(&Vcb->fileref_lock);
|
||||
WARN("inode collision\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
} else if (Status != STATUS_NOT_FOUND) {
|
||||
ERR("check_inode_used returned %08lx\n", Status);
|
||||
|
||||
WARN("inode collision\n");
|
||||
Status = STATUS_INVALID_PARAMETER;
|
||||
goto end;
|
||||
} else if (fcb2->inode > bmn->inode) {
|
||||
lastle = fcb2->list_entry.Blink;
|
||||
break;
|
||||
}
|
||||
|
||||
le = le->Flink;
|
||||
release_fcb_lock(Vcb);
|
||||
ExReleaseResourceLite(&Vcb->fileref_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
inode = bmn->inode;
|
||||
fcb->inode = bmn->inode;
|
||||
fcb->hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4025,7 +4063,7 @@ static NTSTATUS mknod(device_extension* Vcb, PFILE_OBJECT FileObject, void* data
|
|||
RtlZeroMemory(fcb->hash_ptrs_uc, sizeof(LIST_ENTRY*) * 256);
|
||||
}
|
||||
|
||||
InsertHeadList(lastle, &fcb->list_entry);
|
||||
add_fcb_to_subvol(fcb);
|
||||
InsertTailList(&Vcb->all_fcbs, &fcb->list_entry_all);
|
||||
|
||||
if (bmn->type == BTRFS_TYPE_DIRECTORY)
|
||||
|
@ -4924,10 +4962,10 @@ static NTSTATUS fsctl_oplock(device_extension* Vcb, PIRP* Pirp) {
|
|||
|
||||
ExAcquireResourceSharedLite(&Vcb->tree_lock, true);
|
||||
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
|
||||
|
||||
if (fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_1 || fsctl == FSCTL_REQUEST_BATCH_OPLOCK || fsctl == FSCTL_REQUEST_FILTER_OPLOCK ||
|
||||
fsctl == FSCTL_REQUEST_OPLOCK_LEVEL_2 || oplock_request) {
|
||||
ExAcquireResourceExclusiveLite(fcb->Header.Resource, true);
|
||||
|
||||
if (shared_request) {
|
||||
if (fcb->type == BTRFS_TYPE_FILE) {
|
||||
if (fFsRtlCheckLockForOplockRequest)
|
||||
|
@ -4939,8 +4977,7 @@ static NTSTATUS fsctl_oplock(device_extension* Vcb, PIRP* Pirp) {
|
|||
}
|
||||
} else
|
||||
oplock_count = fileref->open_count;
|
||||
} else
|
||||
ExAcquireResourceSharedLite(fcb->Header.Resource, true);
|
||||
}
|
||||
|
||||
#if (NTDDI_VERSION >= NTDDI_WIN7)
|
||||
if ((fsctl == FSCTL_REQUEST_FILTER_OPLOCK || fsctl == FSCTL_REQUEST_BATCH_OPLOCK ||
|
||||
|
|
|
@ -188,6 +188,18 @@ static NTSTATUS bus_pnp(bus_device_extension* bde, PIRP Irp) {
|
|||
bool handled = false;
|
||||
|
||||
switch (IrpSp->MinorFunction) {
|
||||
case IRP_MN_START_DEVICE:
|
||||
case IRP_MN_CANCEL_REMOVE_DEVICE:
|
||||
case IRP_MN_SURPRISE_REMOVAL:
|
||||
case IRP_MN_REMOVE_DEVICE:
|
||||
Status = STATUS_SUCCESS;
|
||||
handled = true;
|
||||
break;
|
||||
|
||||
case IRP_MN_QUERY_REMOVE_DEVICE:
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
handled = true;
|
||||
break;
|
||||
case IRP_MN_QUERY_CAPABILITIES:
|
||||
Status = bus_query_capabilities(Irp);
|
||||
handled = true;
|
||||
|
|
|
@ -317,6 +317,11 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc
|
|||
|
||||
// FIXME - die if not file or directory
|
||||
|
||||
if (fcb->type == BTRFS_TYPE_DIRECTORY && fcb->inode_item.st_size > 0) {
|
||||
TRACE("directory not empty\n");
|
||||
return STATUS_DIRECTORY_NOT_EMPTY;
|
||||
}
|
||||
|
||||
if (buflen < sizeof(ULONG)) {
|
||||
WARN("buffer was not long enough to hold tag\n");
|
||||
return STATUS_INVALID_BUFFER_SIZE;
|
||||
|
@ -328,7 +333,10 @@ NTSTATUS set_reparse_point2(fcb* fcb, REPARSE_DATA_BUFFER* rdb, ULONG buflen, cc
|
|||
return Status;
|
||||
}
|
||||
|
||||
RtlCopyMemory(&tag, rdb, sizeof(ULONG));
|
||||
tag = *(ULONG*)rdb;
|
||||
|
||||
if (tag == IO_REPARSE_TAG_MOUNT_POINT && fcb->type != BTRFS_TYPE_DIRECTORY)
|
||||
return STATUS_NOT_A_DIRECTORY;
|
||||
|
||||
if (fcb->type == BTRFS_TYPE_FILE &&
|
||||
((tag == IO_REPARSE_TAG_SYMLINK && rdb->SymbolicLinkReparseBuffer.Flags & SYMLINK_FLAG_RELATIVE) || tag == IO_REPARSE_TAG_LX_SYMLINK)) {
|
||||
|
|
|
@ -903,7 +903,7 @@ void __stdcall mountmgr_thread(_In_ void* context) {
|
|||
break;
|
||||
}
|
||||
|
||||
Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_QUERY_POINTS, &mmp, sizeof(MOUNTMGR_MOUNT_POINTS), mmps2, mmps.Size,
|
||||
Status = dev_ioctl(mountmgr, IOCTL_MOUNTMGR_QUERY_POINTS, &mmp, sizeof(MOUNTMGR_MOUNT_POINT), mmps2, mmps.Size,
|
||||
false, NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
ERR("IOCTL_MOUNTMGR_QUERY_POINTS returned %08lx\n", Status);
|
||||
|
|
|
@ -95,7 +95,7 @@ void add_user_mapping(WCHAR* sidstring, ULONG sidstringlength, uint32_t uid) {
|
|||
while (sidstringlength > 0) {
|
||||
val = 0;
|
||||
i = 0;
|
||||
while (sidstring[i] != '-' && i < sidstringlength) {
|
||||
while (i < sidstringlength && sidstring[i] != '-') {
|
||||
if (sidstring[i] >= '0' && sidstring[i] <= '9') {
|
||||
val *= 10;
|
||||
val += sidstring[i] - '0';
|
||||
|
|
|
@ -2177,6 +2177,9 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr
|
|||
Status = handle_batch_collision(Vcb, bi, tp.tree, tp.item, td, &br->items, &ignore);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("handle_batch_collision returned %08lx\n", Status);
|
||||
#ifdef _DEBUG
|
||||
int3;
|
||||
#endif
|
||||
|
||||
if (td)
|
||||
ExFreeToPagedLookasideList(&Vcb->tree_data_lookaside, td);
|
||||
|
@ -2258,6 +2261,9 @@ static NTSTATUS commit_batch_list_root(_Requires_exclusive_lock_held_(_Curr_->tr
|
|||
Status = handle_batch_collision(Vcb, bi2, tp.tree, td2, td, &br->items, &ignore);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
ERR("handle_batch_collision returned %08lx\n", Status);
|
||||
#ifdef _DEBUG
|
||||
int3;
|
||||
#endif
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3476,7 +3476,7 @@ NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, P
|
|||
|
||||
Status = insert_prealloc_extent(fcb, oldalloc, newalloc - oldalloc, rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_DISK_FULL) {
|
||||
ERR("insert_prealloc_extent returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
@ -3503,7 +3503,7 @@ NTSTATUS extend_file(fcb* fcb, file_ref* fileref, uint64_t end, bool prealloc, P
|
|||
if (prealloc) {
|
||||
Status = insert_prealloc_extent(fcb, 0, newalloc, rollback);
|
||||
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_DISK_FULL) {
|
||||
ERR("insert_prealloc_extent returned %08lx\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
@ -4285,16 +4285,19 @@ NTSTATUS write_file2(device_extension* Vcb, PIRP Irp, LARGE_INTEGER offset, void
|
|||
Status = Irp->IoStatus.Status;
|
||||
goto end;
|
||||
} else {
|
||||
/* We have to wait in CcCopyWrite - if we return STATUS_PENDING and add this to the work queue,
|
||||
* it can result in CcFlushCache being called before the job has run. See ifstest ReadWriteTest. */
|
||||
|
||||
if (fCcCopyWriteEx) {
|
||||
TRACE("CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, off64, *length, wait, buf, Irp->Tail.Overlay.Thread);
|
||||
if (!fCcCopyWriteEx(FileObject, &offset, *length, wait, buf, Irp->Tail.Overlay.Thread)) {
|
||||
TRACE("CcCopyWriteEx(%p, %I64x, %lx, %u, %p, %p)\n", FileObject, off64, *length, true, buf, Irp->Tail.Overlay.Thread);
|
||||
if (!fCcCopyWriteEx(FileObject, &offset, *length, true, buf, Irp->Tail.Overlay.Thread)) {
|
||||
Status = STATUS_PENDING;
|
||||
goto end;
|
||||
}
|
||||
TRACE("CcCopyWriteEx finished\n");
|
||||
} else {
|
||||
TRACE("CcCopyWrite(%p, %I64x, %lx, %u, %p)\n", FileObject, off64, *length, wait, buf);
|
||||
if (!CcCopyWrite(FileObject, &offset, *length, wait, buf)) {
|
||||
TRACE("CcCopyWrite(%p, %I64x, %lx, %u, %p)\n", FileObject, off64, *length, true, buf);
|
||||
if (!CcCopyWrite(FileObject, &offset, *length, true, buf)) {
|
||||
Status = STATUS_PENDING;
|
||||
goto end;
|
||||
}
|
||||
|
|
|
@ -1263,13 +1263,6 @@ static bool is_mounted_multi_device(HANDLE h, uint32_t sector_size) {
|
|||
bfs = malloc(bfssize);
|
||||
|
||||
Status = NtDeviceIoControlFile(h2, NULL, NULL, NULL, &iosb, IOCTL_BTRFS_QUERY_FILESYSTEMS, NULL, 0, bfs, bfssize);
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
||||
#ifdef __REACTOS__
|
||||
if (bfs) free(bfs);
|
||||
#endif
|
||||
NtClose(h2);
|
||||
return false;
|
||||
}
|
||||
} while (Status == STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
|
|
Loading…
Reference in a new issue