mirror of
https://github.com/reactos/reactos.git
synced 2026-06-08 08:52:59 +08:00
[SHELLBTRFS] Upgrade to 1.5
CORE-16494
This commit is contained in:
169
dll/shellext/shellbtrfs/contextmenu.cpp
Normal file → Executable file
169
dll/shellext/shellbtrfs/contextmenu.cpp
Normal file → Executable file
@@ -323,7 +323,7 @@ void BtrfsContextMenu::get_uac_icon() {
|
||||
|
||||
hr = Create32BitHBITMAP(nullptr, &sz, (void**)&buf, &uacicon);
|
||||
if (SUCCEEDED(hr)) {
|
||||
UINT stride = cx * sizeof(DWORD);
|
||||
UINT stride = (UINT)(cx * sizeof(DWORD));
|
||||
UINT buflen = cy * stride;
|
||||
bitmap->CopyPixels(nullptr, stride, buflen, buf);
|
||||
}
|
||||
@@ -462,8 +462,6 @@ static void create_snapshot(HWND hwnd, const wstring& fn) {
|
||||
if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) {
|
||||
wstring subvolname, parpath, searchpath, temp1, name, nameorig;
|
||||
win_handle h2;
|
||||
btrfs_create_snapshot* bcs;
|
||||
ULONG namelen;
|
||||
WIN32_FIND_DATAW wfd;
|
||||
SYSTEMTIME time;
|
||||
|
||||
@@ -511,16 +509,17 @@ static void create_snapshot(HWND hwnd, const wstring& fn) {
|
||||
} while (fff != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
namelen = name.length() * sizeof(WCHAR);
|
||||
size_t namelen = name.length() * sizeof(WCHAR);
|
||||
|
||||
bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
|
||||
auto bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
|
||||
bcs->readonly = false;
|
||||
bcs->posix = false;
|
||||
bcs->subvol = h;
|
||||
bcs->namelen = (uint16_t)namelen;
|
||||
memcpy(bcs->name, name.c_str(), namelen);
|
||||
|
||||
Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen, nullptr, 0);
|
||||
Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
|
||||
(ULONG)(sizeof(btrfs_create_snapshot) - 1 + namelen), nullptr, 0);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
@@ -619,7 +618,8 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
|
||||
(ULONG)(sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen), nullptr, 0);
|
||||
|
||||
free(bcs);
|
||||
|
||||
@@ -629,19 +629,19 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
|
||||
win_handle dirh;
|
||||
ULONG bmnsize;
|
||||
btrfs_mknod* bmn;
|
||||
|
||||
dirh = CreateFileW(dir, FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
if (dirh == INVALID_HANDLE_VALUE)
|
||||
throw last_error(GetLastError());
|
||||
|
||||
bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
|
||||
size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
|
||||
bmn = (btrfs_mknod*)malloc(bmnsize);
|
||||
|
||||
bmn->inode = 0;
|
||||
@@ -650,7 +650,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
bmn->namelen = (uint16_t)(wcslen(name) * sizeof(WCHAR));
|
||||
memcpy(bmn->name, name, bmn->namelen);
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bmn);
|
||||
throw ntstatus_error(Status);
|
||||
@@ -759,11 +759,8 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
|
||||
// CreateDirectoryExW also copies streams, no need to do it here
|
||||
} else {
|
||||
WIN32_FIND_STREAM_DATA fsd;
|
||||
|
||||
if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
reparse_header rh;
|
||||
ULONG rplen;
|
||||
uint8_t* rp;
|
||||
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
|
||||
@@ -771,13 +768,13 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
throw last_error(GetLastError());
|
||||
}
|
||||
|
||||
rplen = sizeof(reparse_header) + rh.ReparseDataLength;
|
||||
size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
|
||||
rp = (uint8_t*)malloc(rplen);
|
||||
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (ULONG)rplen, &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
|
||||
if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
|
||||
if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (ULONG)rplen, nullptr, 0, &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
|
||||
free(rp);
|
||||
@@ -790,8 +787,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
uint64_t offset, alloc_size;
|
||||
ULONG maxdup;
|
||||
|
||||
if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
@@ -808,8 +806,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
throw last_error(GetLastError());
|
||||
|
||||
feofi.EndOfFile = fsi.EndOfFile;
|
||||
if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
ded.FileHandle = source;
|
||||
maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
|
||||
@@ -827,19 +826,34 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
}
|
||||
}
|
||||
|
||||
fff_handle h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
wstring sn;
|
||||
ULONG streambufsize = 0;
|
||||
vector<char> streambuf;
|
||||
|
||||
sn = fsd.cStreamName;
|
||||
do {
|
||||
streambufsize += 0x1000;
|
||||
streambuf.resize(streambufsize);
|
||||
|
||||
memset(streambuf.data(), 0, streambufsize);
|
||||
|
||||
Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
|
||||
} while (Status == STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
|
||||
|
||||
while (true) {
|
||||
if (fsi->StreamNameLength > 0) {
|
||||
wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
|
||||
|
||||
if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
|
||||
win_handle stream;
|
||||
uint8_t* data = nullptr;
|
||||
uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
|
||||
auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
|
||||
|
||||
if (fsd.StreamSize.QuadPart > 0) {
|
||||
|
||||
if (stream_size > 0) {
|
||||
wstring fn2;
|
||||
|
||||
fn2 = fn;
|
||||
@@ -876,7 +890,12 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
} while (FindNextStreamW(h, &fsd));
|
||||
}
|
||||
|
||||
if (fsi->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,7 +928,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
xa2 = xa;
|
||||
while (xa2->valuelen > 0) {
|
||||
Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
|
||||
offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
|
||||
(ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(xa);
|
||||
throw ntstatus_error(Status);
|
||||
@@ -924,8 +943,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
|
||||
FILE_DISPOSITION_INFO fdi;
|
||||
|
||||
fdi.DeleteFile = true;
|
||||
if (!SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
throw;
|
||||
}
|
||||
@@ -1007,7 +1027,6 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
|
||||
win_handle h;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
ULONG bcslen;
|
||||
wstring name, nameorig, searchpath;
|
||||
btrfs_create_subvol* bcs;
|
||||
WIN32_FIND_DATAW wfd;
|
||||
@@ -1048,7 +1067,7 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
|
||||
}
|
||||
}
|
||||
|
||||
bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
|
||||
size_t bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
|
||||
bcs = (btrfs_create_subvol*)malloc(bcslen);
|
||||
|
||||
bcs->readonly = false;
|
||||
@@ -1056,7 +1075,7 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
|
||||
bcs->namelen = (uint16_t)(name.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, name.c_str(), name.length() * sizeof(WCHAR));
|
||||
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
|
||||
free(bcs);
|
||||
|
||||
@@ -1319,7 +1338,6 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
|
||||
// if subvol, do snapshot instead
|
||||
if (bii.inode == SUBVOL_ROOT_INODE) {
|
||||
ULONG bcslen;
|
||||
btrfs_create_snapshot* bcs;
|
||||
win_handle dirh;
|
||||
|
||||
@@ -1327,13 +1345,13 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
if (dirh == INVALID_HANDLE_VALUE)
|
||||
throw last_error(GetLastError());
|
||||
|
||||
bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
|
||||
size_t bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
|
||||
bcs = (btrfs_create_snapshot*)malloc(bcslen);
|
||||
bcs->subvol = source;
|
||||
bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bcs);
|
||||
throw ntstatus_error(Status);
|
||||
@@ -1344,19 +1362,19 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
return;
|
||||
}
|
||||
|
||||
if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
|
||||
win_handle dirh;
|
||||
ULONG bmnsize;
|
||||
btrfs_mknod* bmn;
|
||||
|
||||
dirh = CreateFileW(destdir.c_str(), FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||
if (dirh == INVALID_HANDLE_VALUE)
|
||||
throw last_error(GetLastError());
|
||||
|
||||
bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
|
||||
size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
|
||||
bmn = (btrfs_mknod*)malloc(bmnsize);
|
||||
|
||||
bmn->inode = 0;
|
||||
@@ -1365,7 +1383,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
bmn->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
|
||||
memcpy(bmn->name, destname.c_str(), bmn->namelen);
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bmn);
|
||||
throw ntstatus_error(Status);
|
||||
@@ -1428,11 +1446,8 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
|
||||
// CreateDirectoryExW also copies streams, no need to do it here
|
||||
} else {
|
||||
WIN32_FIND_STREAM_DATA fsd;
|
||||
|
||||
if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
reparse_header rh;
|
||||
ULONG rplen;
|
||||
uint8_t* rp;
|
||||
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
|
||||
@@ -1440,14 +1455,14 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
throw last_error(GetLastError());
|
||||
}
|
||||
|
||||
rplen = sizeof(reparse_header) + rh.ReparseDataLength;
|
||||
size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
|
||||
rp = (uint8_t*)malloc(rplen);
|
||||
|
||||
try {
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
|
||||
if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (DWORD)rplen, &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
|
||||
if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
|
||||
if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (DWORD)rplen, nullptr, 0, &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
} catch (...) {
|
||||
free(rp);
|
||||
@@ -1464,8 +1479,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
uint64_t offset, alloc_size;
|
||||
ULONG maxdup;
|
||||
|
||||
if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
|
||||
throw last_error(GetLastError());
|
||||
@@ -1482,8 +1498,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
throw last_error(GetLastError());
|
||||
|
||||
feofi.EndOfFile = fsi.EndOfFile;
|
||||
if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
ded.FileHandle = source;
|
||||
maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
|
||||
@@ -1501,20 +1518,34 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
}
|
||||
}
|
||||
|
||||
fff_handle h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0);
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
wstring sn;
|
||||
ULONG streambufsize = 0;
|
||||
vector<char> streambuf;
|
||||
|
||||
sn = fsd.cStreamName;
|
||||
do {
|
||||
streambufsize += 0x1000;
|
||||
streambuf.resize(streambufsize);
|
||||
|
||||
memset(streambuf.data(), 0, streambufsize);
|
||||
|
||||
Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
|
||||
} while (Status == STATUS_BUFFER_OVERFLOW);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
|
||||
|
||||
while (true) {
|
||||
if (fsi->StreamNameLength > 0) {
|
||||
wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
|
||||
|
||||
if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
|
||||
win_handle stream;
|
||||
uint8_t* data = nullptr;
|
||||
auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
|
||||
|
||||
if (fsd.StreamSize.QuadPart > 0) {
|
||||
if (stream_size > 0) {
|
||||
wstring fn2;
|
||||
uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
|
||||
|
||||
fn2 = srcfn;
|
||||
fn2 += sn;
|
||||
@@ -1542,7 +1573,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
}
|
||||
|
||||
if (data) {
|
||||
if (!WriteFile(stream, data, (uint32_t)fsd.StreamSize.QuadPart, &bytesret, nullptr)) {
|
||||
if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
|
||||
free(data);
|
||||
throw last_error(GetLastError());
|
||||
}
|
||||
@@ -1550,7 +1581,13 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
} while (FindNextStreamW(h, &fsd));
|
||||
|
||||
}
|
||||
|
||||
if (fsi->NextEntryOffset == 0)
|
||||
break;
|
||||
|
||||
fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1583,7 +1620,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
xa2 = xa;
|
||||
while (xa2->valuelen > 0) {
|
||||
Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
|
||||
offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
|
||||
(ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(xa);
|
||||
throw ntstatus_error(Status);
|
||||
@@ -1598,7 +1635,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
|
||||
FILE_DISPOSITION_INFO fdi;
|
||||
|
||||
fdi.DeleteFile = true;
|
||||
SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||
Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user