mirror of
https://github.com/reactos/reactos.git
synced 2025-01-05 22:12:46 +00:00
[BTRFSLIB]
Sync to 1.0 CORE-13763 svn path=/trunk/; revision=75796
This commit is contained in:
parent
925c2e9d2f
commit
8e31783cb7
3 changed files with 511 additions and 329 deletions
|
@ -5,7 +5,7 @@ The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
|||
|
||||
reactos/drivers/filesystems/btrfs # Synced to 1.0
|
||||
reactos/dll/shellext/shellbtrfs # Synced to 1.0
|
||||
reactos/sdk/lib/fslib/btrfslib # Synced to 0.8
|
||||
reactos/sdk/lib/fslib/btrfslib # Synced to 1.0
|
||||
|
||||
The following FSD are shared with: http://www.ext2fsd.com/
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs)
|
||||
|
||||
add_library(btrfslib btrfslib.c)
|
||||
add_dependencies(btrfslib psdk)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) Mark Harmstone 2016
|
||||
/* Copyright (c) Mark Harmstone 2016-17
|
||||
*
|
||||
* This file is part of WinBtrfs.
|
||||
*
|
||||
|
@ -32,11 +32,12 @@
|
|||
#include <ndk/rtlfuncs.h>
|
||||
#endif
|
||||
#include <ntddscsi.h>
|
||||
#include <ntddstor.h>
|
||||
#include <ata.h>
|
||||
#include <mountmgr.h>
|
||||
#ifdef __REACTOS__
|
||||
#include "../../drivers/filesystems/btrfs/btrfs.h"
|
||||
#include "../../drivers/filesystems/btrfs/btrfsioctl.h"
|
||||
#include "btrfs.h"
|
||||
#include "btrfsioctl.h"
|
||||
#else
|
||||
#include "../btrfs.h"
|
||||
#include "../btrfsioctl.h"
|
||||
|
@ -46,9 +47,11 @@
|
|||
#define FSCTL_LOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 6, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_UNLOCK_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 7, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define FSCTL_DISMOUNT_VOLUME CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 8, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#ifndef _MSC_VER // not in mingw yet
|
||||
#define DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED 0x80000000
|
||||
#endif
|
||||
|
||||
#ifndef __REACTOS__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -65,7 +68,34 @@ NTSYSAPI NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// These are undocumented, and what comes from format.exe
|
||||
typedef struct {
|
||||
void* table;
|
||||
void* unk1;
|
||||
WCHAR* string;
|
||||
} DSTRING;
|
||||
|
||||
typedef struct {
|
||||
void* table;
|
||||
} STREAM_MESSAGE;
|
||||
|
||||
#define FORMAT_FLAG_QUICK_FORMAT 0x00000001
|
||||
#define FORMAT_FLAG_UNKNOWN1 0x00000002
|
||||
#define FORMAT_FLAG_DISMOUNT_FIRST 0x00000004
|
||||
#define FORMAT_FLAG_UNKNOWN2 0x00000040
|
||||
#define FORMAT_FLAG_LARGE_RECORDS 0x00000100
|
||||
#define FORMAT_FLAG_INTEGRITY_DISABLE 0x00000100
|
||||
|
||||
typedef struct {
|
||||
UINT16 unk1;
|
||||
UINT16 unk2;
|
||||
UINT32 flags;
|
||||
DSTRING* label;
|
||||
} options;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
FORCEINLINE VOID InitializeListHead(PLIST_ENTRY ListHead) {
|
||||
ListHead->Flink = ListHead->Blink = ListHead;
|
||||
}
|
||||
|
@ -129,6 +159,8 @@ typedef struct {
|
|||
0))))))
|
||||
|
||||
HMODULE module;
|
||||
ULONG def_sector_size = 0, def_node_size = 0;
|
||||
UINT64 def_incompat_flags = BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA;
|
||||
|
||||
// the following definitions come from fmifs.h in ReactOS
|
||||
|
||||
|
@ -442,10 +474,10 @@ static btrfs_chunk* add_chunk(LIST_ENTRY* chunks, UINT64 flags, btrfs_root* chun
|
|||
|
||||
c->chunk_item->size = size;
|
||||
c->chunk_item->root_id = BTRFS_ROOT_EXTENT;
|
||||
c->chunk_item->stripe_length = 0x10000;
|
||||
c->chunk_item->stripe_length = max(sector_size, 0x10000);
|
||||
c->chunk_item->type = flags;
|
||||
c->chunk_item->opt_io_alignment = 0x10000;
|
||||
c->chunk_item->opt_io_width = 0x10000;
|
||||
c->chunk_item->opt_io_alignment = max(sector_size, 0x10000);
|
||||
c->chunk_item->opt_io_width = max(sector_size, 0x10000);
|
||||
c->chunk_item->sector_size = sector_size;
|
||||
c->chunk_item->num_stripes = stripes;
|
||||
c->chunk_item->sub_stripes = 0;
|
||||
|
@ -507,29 +539,61 @@ typedef struct {
|
|||
TREE_BLOCK_REF tbr;
|
||||
} EXTENT_ITEM_METADATA;
|
||||
|
||||
typedef struct {
|
||||
EXTENT_ITEM ei;
|
||||
EXTENT_ITEM2 ei2;
|
||||
UINT8 type;
|
||||
TREE_BLOCK_REF tbr;
|
||||
} EXTENT_ITEM_METADATA2;
|
||||
|
||||
static void assign_addresses(LIST_ENTRY* roots, btrfs_chunk* sys_chunk, btrfs_chunk* metadata_chunk, UINT32 node_size,
|
||||
btrfs_root* root_root, btrfs_root* extent_root) {
|
||||
btrfs_root* root_root, btrfs_root* extent_root, BOOL skinny) {
|
||||
LIST_ENTRY* le;
|
||||
|
||||
le = roots->Flink;
|
||||
while (le != roots) {
|
||||
btrfs_root* r = CONTAINING_RECORD(le, btrfs_root, list_entry);
|
||||
btrfs_chunk* c = r->id == BTRFS_ROOT_CHUNK ? sys_chunk : metadata_chunk;
|
||||
EXTENT_ITEM_METADATA eim;
|
||||
|
||||
r->header.address = get_next_address(c);
|
||||
r->c = c;
|
||||
c->lastoff = r->header.address + node_size;
|
||||
c->used += node_size;
|
||||
|
||||
if (skinny) {
|
||||
EXTENT_ITEM_METADATA eim;
|
||||
|
||||
eim.ei.refcount = 1;
|
||||
eim.ei.generation = 1;
|
||||
eim.ei.flags = EXTENT_ITEM_TREE_BLOCK;
|
||||
eim.type = TYPE_TREE_BLOCK_REF;
|
||||
eim.tbr.offset = r->id;
|
||||
|
||||
// FIXME - support non-skinny EXTENT_ITEM
|
||||
add_item(extent_root, r->header.address, TYPE_METADATA_ITEM, 0, &eim, sizeof(EXTENT_ITEM_METADATA));
|
||||
} else {
|
||||
EXTENT_ITEM_METADATA2 eim2;
|
||||
KEY firstitem;
|
||||
|
||||
if (r->items.Flink == &r->items) {
|
||||
firstitem.obj_id = 0;
|
||||
firstitem.obj_type = 0;
|
||||
firstitem.offset = 0;
|
||||
} else {
|
||||
btrfs_item* bi = CONTAINING_RECORD(r->items.Flink, btrfs_item, list_entry);
|
||||
|
||||
firstitem = bi->key;
|
||||
}
|
||||
|
||||
eim2.ei.refcount = 1;
|
||||
eim2.ei.generation = 1;
|
||||
eim2.ei.flags = EXTENT_ITEM_TREE_BLOCK;
|
||||
eim2.ei2.firstitem = firstitem;
|
||||
eim2.ei2.level = 0;
|
||||
eim2.type = TYPE_TREE_BLOCK_REF;
|
||||
eim2.tbr.offset = r->id;
|
||||
|
||||
add_item(extent_root, r->header.address, TYPE_EXTENT_ITEM, node_size, &eim2, sizeof(EXTENT_ITEM_METADATA2));
|
||||
}
|
||||
|
||||
if (r->id != BTRFS_ROOT_ROOT && r->id != BTRFS_ROOT_CHUNK) {
|
||||
ROOT_ITEM ri;
|
||||
|
@ -812,7 +876,7 @@ NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
|
|||
#endif
|
||||
|
||||
static NTSTATUS write_superblocks(HANDLE h, btrfs_dev* dev, btrfs_root* chunk_root, btrfs_root* root_root, btrfs_root* extent_root,
|
||||
btrfs_chunk* sys_chunk, UINT32 node_size, BTRFS_UUID* fsuuid, UINT32 sector_size, PUNICODE_STRING label) {
|
||||
btrfs_chunk* sys_chunk, UINT32 node_size, BTRFS_UUID* fsuuid, UINT32 sector_size, PUNICODE_STRING label, UINT64 incompat_flags) {
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
ULONG sblen;
|
||||
|
@ -864,7 +928,7 @@ static NTSTATUS write_superblocks(HANDLE h, btrfs_dev* dev, btrfs_root* chunk_ro
|
|||
sb->stripe_size = sector_size;
|
||||
sb->n = sizeof(KEY) + sizeof(CHUNK_ITEM) + (sys_chunk->chunk_item->num_stripes * sizeof(CHUNK_ITEM_STRIPE));
|
||||
sb->chunk_root_generation = 1;
|
||||
sb->incompat_flags = BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_EXTENDED_IREF | BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA;
|
||||
sb->incompat_flags = incompat_flags;
|
||||
memcpy(&sb->dev_item, &dev->dev_item, sizeof(DEV_ITEM));
|
||||
|
||||
if (label->Length > 0) {
|
||||
|
@ -984,9 +1048,6 @@ GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
|
|||
static void init_fs_tree(btrfs_root* r, UINT32 node_size) {
|
||||
INODE_ITEM ii;
|
||||
INODE_REF* ir;
|
||||
#ifndef __REACTOS__
|
||||
SYSTEMTIME systime;
|
||||
#endif
|
||||
FILETIME filetime;
|
||||
LARGE_INTEGER time;
|
||||
|
||||
|
@ -997,12 +1058,7 @@ static void init_fs_tree(btrfs_root* r, UINT32 node_size) {
|
|||
ii.st_nlink = 1;
|
||||
ii.st_mode = 040755;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
GetSystemTime(&systime);
|
||||
SystemTimeToFileTime(&systime, &filetime);
|
||||
#else
|
||||
GetSystemTimeAsFileTime(&filetime);
|
||||
#endif
|
||||
time.LowPart = filetime.dwLowDateTime;
|
||||
time.HighPart = filetime.dwHighDateTime;
|
||||
|
||||
|
@ -1054,12 +1110,13 @@ static NTSTATUS clear_first_megabyte(HANDLE h) {
|
|||
LARGE_INTEGER zero;
|
||||
UINT8* mb;
|
||||
|
||||
|
||||
#ifndef __REACTOS__
|
||||
mb = malloc(0x100000);
|
||||
#else
|
||||
mb = RtlAllocateHeap(RtlGetProcessHeap(), 0, 0x100000);
|
||||
#endif
|
||||
memset(mb, 0, 0x100000);
|
||||
#else
|
||||
mb = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, 0x100000);
|
||||
#endif
|
||||
|
||||
zero.QuadPart = 0;
|
||||
|
||||
|
@ -1102,22 +1159,34 @@ static BOOL is_ssd(HANDLE h) {
|
|||
if (NT_SUCCESS(Status)) {
|
||||
idd = (IDENTIFY_DEVICE_DATA*)((UINT8*)apte + sizeof(ATA_PASS_THROUGH_EX));
|
||||
|
||||
if (idd->NominalMediaRotationRate == 1)
|
||||
if (idd->NominalMediaRotationRate == 1) {
|
||||
#ifndef __REACTOS__
|
||||
free(apte);
|
||||
#else
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, apte);
|
||||
#endif
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
free(apte);
|
||||
#else
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, apte);
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static NTSTATUS write_btrfs(HANDLE h, UINT64 size, PUNICODE_STRING label, UINT32 sector_size) {
|
||||
static NTSTATUS write_btrfs(HANDLE h, UINT64 size, PUNICODE_STRING label, UINT32 sector_size, UINT32 node_size, UINT64 incompat_flags) {
|
||||
NTSTATUS Status;
|
||||
UINT32 node_size;
|
||||
LIST_ENTRY roots, chunks;
|
||||
btrfs_root *root_root, *chunk_root, *extent_root, *dev_root, *fs_root, *reloc_root;
|
||||
btrfs_chunk *sys_chunk, *metadata_chunk;
|
||||
btrfs_dev dev;
|
||||
BTRFS_UUID fsuuid, chunkuuid;
|
||||
BOOL ssd;
|
||||
UINT64 metadata_flags;
|
||||
#ifdef __REACTOS__
|
||||
ULONG seed;
|
||||
#endif
|
||||
|
@ -1155,18 +1224,25 @@ static NTSTATUS write_btrfs(HANDLE h, UINT64 size, PUNICODE_STRING label, UINT32
|
|||
if (!sys_chunk)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
metadata_chunk = add_chunk(&chunks, BLOCK_FLAG_METADATA | (ssd ? 0 : BLOCK_FLAG_DUPLICATE), chunk_root, &dev, dev_root, &chunkuuid, sector_size);
|
||||
metadata_flags = BLOCK_FLAG_METADATA;
|
||||
|
||||
if (!ssd && !(incompat_flags & BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS))
|
||||
metadata_flags |= BLOCK_FLAG_DUPLICATE;
|
||||
|
||||
if (incompat_flags & BTRFS_INCOMPAT_FLAGS_MIXED_GROUPS)
|
||||
metadata_flags |= BLOCK_FLAG_DATA;
|
||||
|
||||
metadata_chunk = add_chunk(&chunks, metadata_flags, chunk_root, &dev, dev_root, &chunkuuid, sector_size);
|
||||
if (!metadata_chunk)
|
||||
return STATUS_INTERNAL_ERROR;
|
||||
|
||||
node_size = 0x4000;
|
||||
assign_addresses(&roots, sys_chunk, metadata_chunk, node_size, root_root, extent_root);
|
||||
|
||||
add_item(chunk_root, 1, TYPE_DEV_ITEM, dev.dev_item.dev_id, &dev.dev_item, sizeof(DEV_ITEM));
|
||||
|
||||
init_fs_tree(fs_root, node_size);
|
||||
init_fs_tree(reloc_root, node_size);
|
||||
|
||||
assign_addresses(&roots, sys_chunk, metadata_chunk, node_size, root_root, extent_root, incompat_flags & BTRFS_INCOMPAT_FLAGS_SKINNY_METADATA);
|
||||
|
||||
add_block_group_items(&chunks, extent_root);
|
||||
|
||||
Status = write_roots(h, &roots, node_size, &fsuuid, &chunkuuid);
|
||||
|
@ -1177,7 +1253,7 @@ static NTSTATUS write_btrfs(HANDLE h, UINT64 size, PUNICODE_STRING label, UINT32
|
|||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
Status = write_superblocks(h, &dev, chunk_root, root_root, extent_root, sys_chunk, node_size, &fsuuid, sector_size, label);
|
||||
Status = write_superblocks(h, &dev, chunk_root, root_root, extent_root, sys_chunk, node_size, &fsuuid, sector_size, label, incompat_flags);
|
||||
if (!NT_SUCCESS(Status))
|
||||
return Status;
|
||||
|
||||
|
@ -1336,77 +1412,73 @@ end:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void add_drive_letter(HANDLE h) {
|
||||
NTSTATUS Status;
|
||||
static void do_full_trim(HANDLE h) {
|
||||
IO_STATUS_BLOCK iosb;
|
||||
MOUNTDEV_NAME mdn, *mdn2;
|
||||
UNICODE_STRING us;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
HANDLE mountmgr;
|
||||
MOUNTMGR_DRIVE_LETTER_INFORMATION mdli;
|
||||
DEVICE_MANAGE_DATA_SET_ATTRIBUTES dmdsa;
|
||||
|
||||
Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, &mdn, sizeof(mdn));
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||
return;
|
||||
RtlZeroMemory(&dmdsa, sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES));
|
||||
|
||||
#ifndef __REACTOS__
|
||||
mdn2 = malloc(offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength);
|
||||
#else
|
||||
mdn2 = RtlAllocateHeap(RtlGetProcessHeap(), 0, offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength);
|
||||
#endif
|
||||
dmdsa.Size = sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES);
|
||||
dmdsa.Action = DeviceDsmAction_Trim;
|
||||
dmdsa.Flags = DEVICE_DSM_FLAG_ENTIRE_DATA_SET_RANGE | DEVICE_DSM_FLAG_TRIM_NOT_FS_ALLOCATED;
|
||||
dmdsa.ParameterBlockOffset = 0;
|
||||
dmdsa.ParameterBlockLength = 0;
|
||||
dmdsa.DataSetRangesOffset = 0;
|
||||
dmdsa.DataSetRangesLength = 0;
|
||||
|
||||
Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, NULL, 0, mdn2, offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_STORAGE_MANAGE_DATA_SET_ATTRIBUTES, &dmdsa, sizeof(DEVICE_MANAGE_DATA_SET_ATTRIBUTES), NULL, 0);
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME);
|
||||
InitializeObjectAttributes(&attr, &us, 0, NULL, NULL);
|
||||
|
||||
Status = NtOpenFile(&mountmgr, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end;
|
||||
|
||||
// MOUNTDEV_NAME is identical to MOUNTMGR_TARGET_NAME
|
||||
Status = NtDeviceIoControlFile(mountmgr, NULL, NULL, NULL, &iosb, IOCTL_MOUNTMGR_VOLUME_ARRIVAL_NOTIFICATION,
|
||||
mdn2, offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength, NULL, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end2;
|
||||
|
||||
// MOUNTDEV_NAME is identical to MOUNTMGR_DRIVE_LETTER_TARGET
|
||||
Status = NtDeviceIoControlFile(mountmgr, NULL, NULL, NULL, &iosb, IOCTL_MOUNTMGR_NEXT_DRIVE_LETTER,
|
||||
mdn2, offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength, &mdli, sizeof(mdli));
|
||||
if (!NT_SUCCESS(Status))
|
||||
goto end2;
|
||||
|
||||
end2:
|
||||
NtClose(mountmgr);
|
||||
|
||||
end:
|
||||
#ifndef __REACTOS__
|
||||
free(mdn2);
|
||||
#else
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, mdn2);
|
||||
#endif
|
||||
static BOOL is_power_of_two(ULONG i) {
|
||||
return ((i != 0) && !(i & (i - 1)));
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
NTSTATUS NTAPI FormatEx(PUNICODE_STRING DriveRoot, FMIFS_MEDIA_FLAG MediaFlag, PUNICODE_STRING Label,
|
||||
static NTSTATUS NTAPI FormatEx2(PUNICODE_STRING DriveRoot, FMIFS_MEDIA_FLAG MediaFlag, PUNICODE_STRING Label,
|
||||
#else
|
||||
NTSTATUS NTAPI BtrfsFormatEx(PUNICODE_STRING DriveRoot, FMIFS_MEDIA_FLAG MediaFlag, PUNICODE_STRING Label,
|
||||
#endif
|
||||
BOOLEAN QuickFormat, ULONG ClusterSize, PFMIFSCALLBACK Callback)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
HANDLE h;
|
||||
HANDLE h, btrfsh;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
GET_LENGTH_INFORMATION gli;
|
||||
DISK_GEOMETRY_EX dgex;
|
||||
UINT32 sector_size;
|
||||
DISK_GEOMETRY dg;
|
||||
UINT32 sector_size, node_size;
|
||||
UNICODE_STRING btrfsus;
|
||||
#ifndef __REACTOS__
|
||||
HANDLE token;
|
||||
TOKEN_PRIVILEGES tp;
|
||||
LUID luid;
|
||||
#endif
|
||||
UINT64 incompat_flags;
|
||||
|
||||
InitializeObjectAttributes(&attr, DriveRoot, 0, NULL, NULL);
|
||||
static WCHAR btrfs[] = L"\\Btrfs";
|
||||
|
||||
#ifndef __REACTOS__
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
|
||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
|
||||
CloseHandle(token);
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = luid;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
|
||||
CloseHandle(token);
|
||||
return STATUS_PRIVILEGE_NOT_HELD;
|
||||
}
|
||||
|
||||
CloseHandle(token);
|
||||
#endif
|
||||
|
||||
InitializeObjectAttributes(&attr, DriveRoot, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
||||
|
||||
Status = NtOpenFile(&h, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
@ -1420,16 +1492,39 @@ NTSTATUS NTAPI BtrfsFormatEx(PUNICODE_STRING DriveRoot, FMIFS_MEDIA_FLAG MediaFl
|
|||
return Status;
|
||||
}
|
||||
|
||||
Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &dgex, sizeof(dgex));
|
||||
// MSDN tells us to use IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, but there are
|
||||
// some instances where it fails and IOCTL_DISK_GET_DRIVE_GEOMETRY succeeds -
|
||||
// such as with spanned volumes.
|
||||
Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg));
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
NtClose(h);
|
||||
return Status;
|
||||
}
|
||||
|
||||
sector_size = dgex.Geometry.BytesPerSector;
|
||||
if (def_sector_size == 0) {
|
||||
sector_size = dg.BytesPerSector;
|
||||
|
||||
if (sector_size == 0x200 || sector_size == 0)
|
||||
sector_size = 0x1000;
|
||||
} else {
|
||||
if (dg.BytesPerSector != 0 && (def_sector_size < dg.BytesPerSector || def_sector_size % dg.BytesPerSector != 0 || !is_power_of_two(def_sector_size / dg.BytesPerSector))) {
|
||||
NtClose(h);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
sector_size = def_sector_size;
|
||||
}
|
||||
|
||||
if (def_node_size == 0)
|
||||
node_size = 0x4000;
|
||||
else {
|
||||
if (def_node_size < sector_size || def_node_size % sector_size != 0 || !is_power_of_two(def_node_size / sector_size)) {
|
||||
NtClose(h);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
node_size = def_node_size;
|
||||
}
|
||||
|
||||
if (Callback) {
|
||||
ULONG pc = 0;
|
||||
|
@ -1443,18 +1538,57 @@ NTSTATUS NTAPI BtrfsFormatEx(PUNICODE_STRING DriveRoot, FMIFS_MEDIA_FLAG MediaFl
|
|||
goto end;
|
||||
}
|
||||
|
||||
Status = write_btrfs(h, gli.Length.QuadPart, Label, sector_size);
|
||||
do_full_trim(h);
|
||||
|
||||
incompat_flags = def_incompat_flags;
|
||||
incompat_flags |= BTRFS_INCOMPAT_FLAGS_MIXED_BACKREF | BTRFS_INCOMPAT_FLAGS_BIG_METADATA;
|
||||
|
||||
Status = write_btrfs(h, gli.Length.QuadPart, Label, sector_size, node_size, incompat_flags);
|
||||
|
||||
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0);
|
||||
|
||||
end:
|
||||
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
add_drive_letter(h);
|
||||
|
||||
NtClose(h);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
btrfsus.Buffer = btrfs;
|
||||
btrfsus.Length = btrfsus.MaximumLength = wcslen(btrfs) * sizeof(WCHAR);
|
||||
|
||||
InitializeObjectAttributes(&attr, &btrfsus, 0, NULL, NULL);
|
||||
|
||||
Status = NtOpenFile(&btrfsh, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
MOUNTDEV_NAME* mdn;
|
||||
ULONG mdnsize;
|
||||
|
||||
mdnsize = offsetof(MOUNTDEV_NAME, Name[0]) + DriveRoot->Length;
|
||||
#ifndef __REACTOS__
|
||||
mdn = malloc(mdnsize);
|
||||
#else
|
||||
mdn = RtlAllocateHeap(RtlGetProcessHeap(), 0, mdnsize);
|
||||
#endif
|
||||
|
||||
mdn->NameLength = DriveRoot->Length;
|
||||
memcpy(mdn->Name, DriveRoot->Buffer, DriveRoot->Length);
|
||||
|
||||
NtDeviceIoControlFile(btrfsh, NULL, NULL, NULL, &iosb, IOCTL_BTRFS_PROBE_VOLUME, mdn, mdnsize, NULL, 0);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
free(mdn);
|
||||
#else
|
||||
RtlFreeHeap(RtlGetProcessHeap(), 0, mdn);
|
||||
#endif
|
||||
|
||||
NtClose(btrfsh);
|
||||
}
|
||||
|
||||
Status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (Callback) {
|
||||
BOOL success = NT_SUCCESS(Status);
|
||||
Callback(DONE, 0, (PVOID)&success);
|
||||
|
@ -1463,6 +1597,51 @@ end:
|
|||
return Status;
|
||||
}
|
||||
|
||||
BOOL __stdcall FormatEx(DSTRING* root, STREAM_MESSAGE* message, options* opts, UINT32 unk1) {
|
||||
UNICODE_STRING DriveRoot, Label;
|
||||
NTSTATUS Status;
|
||||
|
||||
if (!root || !root->string)
|
||||
return FALSE;
|
||||
|
||||
DriveRoot.Length = DriveRoot.MaximumLength = wcslen(root->string) * sizeof(WCHAR);
|
||||
DriveRoot.Buffer = root->string;
|
||||
|
||||
if (opts && opts->label && opts->label->string) {
|
||||
Label.Length = Label.MaximumLength = wcslen(opts->label->string) * sizeof(WCHAR);
|
||||
Label.Buffer = opts->label->string;
|
||||
} else {
|
||||
Label.Length = Label.MaximumLength = 0;
|
||||
Label.Buffer = NULL;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
Status = FormatEx2(&DriveRoot, FMIFS_HARDDISK, &Label, opts && opts->flags & FORMAT_FLAG_QUICK_FORMAT, 0, NULL);
|
||||
#else
|
||||
Status = BtrfsFormatEx(&DriveRoot, FMIFS_HARDDISK, &Label, opts && opts->flags & FORMAT_FLAG_QUICK_FORMAT, 0, NULL);
|
||||
#endif
|
||||
|
||||
return NT_SUCCESS(Status);
|
||||
}
|
||||
|
||||
void __stdcall SetSizes(ULONG sector, ULONG node) {
|
||||
if (sector != 0)
|
||||
def_sector_size = sector;
|
||||
|
||||
if (node != 0)
|
||||
def_node_size = node;
|
||||
}
|
||||
|
||||
void __stdcall SetIncompatFlags(UINT64 incompat_flags) {
|
||||
def_incompat_flags = incompat_flags;
|
||||
}
|
||||
|
||||
BOOL __stdcall GetFilesystemInformation(UINT32 unk1, UINT32 unk2, void* unk3) {
|
||||
// STUB - undocumented
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__
|
||||
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) {
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
|
|
Loading…
Reference in a new issue