mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
[SHELLBTRFS] Upgrade to 1.5
CORE-16494
This commit is contained in:
parent
86ee9b0cc2
commit
aed50d7e21
18 changed files with 1001 additions and 537 deletions
|
@ -18,6 +18,7 @@ list(APPEND SOURCE
|
|||
factory.cpp
|
||||
iconoverlay.cpp
|
||||
main.cpp
|
||||
mountmgr_local.cpp
|
||||
propsheet.cpp
|
||||
reactos.cpp
|
||||
recv.cpp
|
||||
|
|
|
@ -386,11 +386,9 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) {
|
|||
}
|
||||
|
||||
if (IsDlgButtonChecked(hwndDlg, IDC_DEVID) == BST_CHECKED) {
|
||||
int sel;
|
||||
|
||||
opts->flags |= BTRFS_BALANCE_OPTS_DEVID;
|
||||
|
||||
sel = SendMessageW(GetDlgItem(hwndDlg, IDC_DEVID_COMBO), CB_GETCURSEL, 0, 0);
|
||||
auto sel = SendMessageW(GetDlgItem(hwndDlg, IDC_DEVID_COMBO), CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (sel == CB_ERR)
|
||||
opts->flags &= ~BTRFS_BALANCE_OPTS_DEVID;
|
||||
|
@ -493,11 +491,9 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) {
|
|||
}
|
||||
|
||||
if (IsDlgButtonChecked(hwndDlg, IDC_CONVERT) == BST_CHECKED) {
|
||||
int sel;
|
||||
|
||||
opts->flags |= BTRFS_BALANCE_OPTS_CONVERT;
|
||||
|
||||
sel = SendMessageW(GetDlgItem(hwndDlg, IDC_CONVERT_COMBO), CB_GETCURSEL, 0, 0);
|
||||
auto sel = SendMessageW(GetDlgItem(hwndDlg, IDC_CONVERT_COMBO), CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (sel == CB_ERR || (unsigned int)sel >= sizeof(convtypes2) / sizeof(convtypes2[0]))
|
||||
opts->flags &= ~BTRFS_BALANCE_OPTS_CONVERT;
|
||||
|
|
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;
|
||||
}
|
||||
|
|
84
dll/shellext/shellbtrfs/devices.cpp
Normal file → Executable file
84
dll/shellext/shellbtrfs/devices.cpp
Normal file → Executable file
|
@ -30,11 +30,13 @@
|
|||
#ifndef __REACTOS__
|
||||
#include <algorithm>
|
||||
#include "../btrfs.h"
|
||||
#include "mountmgr.h"
|
||||
#else
|
||||
#include <ntddstor.h>
|
||||
#include <ndk/rtlfuncs.h>
|
||||
#include <ndk/obfuncs.h>
|
||||
#include "btrfs.h"
|
||||
#include "mountmgr_local.h"
|
||||
#endif
|
||||
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_HIDDEN_VOLUME, 0x7f108a28L, 0x9833, 0x4b3b, 0xb7, 0x80, 0x2c, 0x6b, 0x5f, 0xa5, 0xc0, 0x62);
|
||||
|
@ -43,7 +45,6 @@ static wstring get_mountdev_name(const nt_handle& h ) {
|
|||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
MOUNTDEV_NAME mdn, *mdn2;
|
||||
ULONG mdnsize;
|
||||
wstring name;
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
|
@ -51,12 +52,12 @@ static wstring get_mountdev_name(const nt_handle& h ) {
|
|||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||
return L"";
|
||||
|
||||
mdnsize = offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
|
||||
size_t mdnsize = offsetof(MOUNTDEV_NAME, Name[0]) + mdn.NameLength;
|
||||
|
||||
mdn2 = (MOUNTDEV_NAME*)malloc(mdnsize);
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
|
||||
nullptr, 0, mdn2, mdnsize);
|
||||
nullptr, 0, mdn2, (ULONG)mdnsize);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(mdn2);
|
||||
return L"";
|
||||
|
@ -69,10 +70,10 @@ static wstring get_mountdev_name(const nt_handle& h ) {
|
|||
return name;
|
||||
}
|
||||
|
||||
static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr, vector<device>& device_list) {
|
||||
static void find_devices(HWND hwnd, const GUID* guid, const mountmgr& mm, vector<device>& device_list) {
|
||||
HDEVINFO h;
|
||||
|
||||
static WCHAR dosdevices[] = L"\\DosDevices\\";
|
||||
static const wstring dosdevices = L"\\DosDevices\\";
|
||||
|
||||
h = SetupDiGetClassDevs(guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
|
||||
|
||||
|
@ -204,7 +205,7 @@ static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr,
|
|||
if (ss > 0) {
|
||||
WCHAR* desc3 = (WCHAR*)malloc(ss * sizeof(WCHAR));
|
||||
|
||||
if (MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, desc3, ss * sizeof(WCHAR)))
|
||||
if (MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, desc3, (int)(ss * sizeof(WCHAR))))
|
||||
dev.friendly_name = desc3;
|
||||
|
||||
free(desc3);
|
||||
|
@ -235,53 +236,23 @@ static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr,
|
|||
|
||||
free(dli);
|
||||
} else {
|
||||
ULONG mmpsize;
|
||||
MOUNTMGR_MOUNT_POINT* mmp;
|
||||
MOUNTMGR_MOUNT_POINTS mmps;
|
||||
try {
|
||||
auto v = mm.query_points(L"", L"", wstring_view(path.Buffer, path.Length / sizeof(WCHAR)));
|
||||
|
||||
mmpsize = sizeof(MOUNTMGR_MOUNT_POINT) + path.Length;
|
||||
for (const auto& p : v) {
|
||||
if (p.symlink.length() == 14 && p.symlink.substr(0, dosdevices.length()) == dosdevices && p.symlink[13] == ':') {
|
||||
WCHAR dr[3];
|
||||
|
||||
mmp = (MOUNTMGR_MOUNT_POINT*)malloc(mmpsize);
|
||||
dr[0] = p.symlink[12];
|
||||
dr[1] = ':';
|
||||
dr[2] = 0;
|
||||
|
||||
RtlZeroMemory(mmp, sizeof(MOUNTMGR_MOUNT_POINT));
|
||||
mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
mmp->DeviceNameLength = path.Length;
|
||||
RtlCopyMemory(&mmp[1], path.Buffer, path.Length);
|
||||
|
||||
Status = NtDeviceIoControlFile(mountmgr, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
|
||||
mmp, mmpsize, &mmps, sizeof(MOUNTMGR_MOUNT_POINTS));
|
||||
if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) {
|
||||
MOUNTMGR_MOUNT_POINTS* mmps2;
|
||||
|
||||
mmps2 = (MOUNTMGR_MOUNT_POINTS*)malloc(mmps.Size);
|
||||
|
||||
Status = NtDeviceIoControlFile(mountmgr, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
|
||||
mmp, mmpsize, mmps2, mmps.Size);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < mmps2->NumberOfMountPoints; i++) {
|
||||
WCHAR* symlink = (WCHAR*)((uint8_t*)mmps2 + mmps2->MountPoints[i].SymbolicLinkNameOffset);
|
||||
|
||||
if (mmps2->MountPoints[i].SymbolicLinkNameLength == 0x1c &&
|
||||
RtlCompareMemory(symlink, dosdevices, wcslen(dosdevices) * sizeof(WCHAR)) == wcslen(dosdevices) * sizeof(WCHAR) &&
|
||||
symlink[13] == ':'
|
||||
) {
|
||||
WCHAR dr[3];
|
||||
|
||||
dr[0] = symlink[12];
|
||||
dr[1] = ':';
|
||||
dr[2] = 0;
|
||||
|
||||
dev.drive = dr;
|
||||
break;
|
||||
}
|
||||
dev.drive = dr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (...) { // don't fail entirely if mountmgr refuses to co-operate
|
||||
}
|
||||
|
||||
free(mmp);
|
||||
}
|
||||
|
||||
if (!dev.is_disk || !dev.has_parts) {
|
||||
|
@ -364,16 +335,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) {
|
|||
device_list.clear();
|
||||
|
||||
{
|
||||
nt_handle mountmgr;
|
||||
|
||||
RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME);
|
||||
InitializeObjectAttributes(&attr, &us, 0, nullptr, nullptr);
|
||||
|
||||
Status = NtOpenFile(&mountmgr, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_CANT_OPEN_MOUNTMGR);
|
||||
mountmgr mm;
|
||||
|
||||
{
|
||||
nt_handle btrfsh;
|
||||
|
@ -409,9 +371,9 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) {
|
|||
}
|
||||
}
|
||||
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_DISK, mountmgr, device_list);
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_VOLUME, mountmgr, device_list);
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_HIDDEN_VOLUME, mountmgr, device_list);
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_DISK, mm, device_list);
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_VOLUME, mm, device_list);
|
||||
find_devices(hwnd, &GUID_DEVINTERFACE_HIDDEN_VOLUME, mm, device_list);
|
||||
}
|
||||
|
||||
#ifndef __REACTOS__ // Disabled because building with our <algorithm> seems complex right now...
|
||||
|
@ -507,7 +469,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) {
|
|||
name += L")";
|
||||
|
||||
tis.itemex.pszText = (WCHAR*)name.c_str();
|
||||
tis.itemex.cchTextMax = name.length();
|
||||
tis.itemex.cchTextMax = (int)name.length();
|
||||
tis.itemex.lParam = (LPARAM)&device_list[i];
|
||||
|
||||
item = (HTREEITEM)SendMessageW(tree, TVM_INSERTITEMW, 0, (LPARAM)&tis);
|
||||
|
|
312
dll/shellext/shellbtrfs/main.cpp
Normal file → Executable file
312
dll/shellext/shellbtrfs/main.cpp
Normal file → Executable file
|
@ -298,7 +298,7 @@ static void write_reg_key(HKEY root, const wstring& keyname, const WCHAR* val, c
|
|||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGCREATEKEY_FAILED, l);
|
||||
|
||||
l = RegSetValueExW(hk, val, 0, REG_SZ, (const BYTE*)data.c_str(), (data.length() + 1) * sizeof(WCHAR));
|
||||
l = RegSetValueExW(hk, val, 0, REG_SZ, (const BYTE*)data.c_str(), (DWORD)((data.length() + 1) * sizeof(WCHAR)));
|
||||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGSETVALUEEX_FAILED, l);
|
||||
|
||||
|
@ -340,20 +340,71 @@ static void register_clsid(const GUID clsid, const WCHAR* description) {
|
|||
CoTaskMemFree(clsidstring);
|
||||
}
|
||||
|
||||
// implementation of RegDeleteTreeW, only available from Vista on
|
||||
static void reg_delete_tree(HKEY hkey, const wstring& keyname) {
|
||||
HKEY k;
|
||||
LSTATUS ret;
|
||||
|
||||
ret = RegOpenKeyExW(hkey, keyname.c_str(), 0, KEY_READ, &k);
|
||||
|
||||
if (ret != ERROR_SUCCESS)
|
||||
throw last_error(ret);
|
||||
|
||||
try {
|
||||
WCHAR* buf;
|
||||
ULONG bufsize;
|
||||
|
||||
ret = RegQueryInfoKeyW(k, nullptr, nullptr, nullptr, nullptr, &bufsize, nullptr,
|
||||
nullptr, nullptr, nullptr, nullptr, nullptr);
|
||||
if (ret != ERROR_SUCCESS)
|
||||
throw last_error(ret);
|
||||
|
||||
bufsize++;
|
||||
buf = new WCHAR[bufsize];
|
||||
|
||||
try {
|
||||
do {
|
||||
ULONG size = bufsize;
|
||||
|
||||
ret = RegEnumKeyExW(k, 0, buf, &size, nullptr, nullptr, nullptr, nullptr);
|
||||
|
||||
if (ret == ERROR_NO_MORE_ITEMS)
|
||||
break;
|
||||
else if (ret != ERROR_SUCCESS)
|
||||
throw last_error(ret);
|
||||
|
||||
reg_delete_tree(k, buf);
|
||||
} while (true);
|
||||
|
||||
ret = RegDeleteKeyW(hkey, keyname.c_str());
|
||||
if (ret != ERROR_SUCCESS)
|
||||
throw last_error(ret);
|
||||
} catch (...) {
|
||||
delete[] buf;
|
||||
throw;
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
} catch (...) {
|
||||
RegCloseKey(k);
|
||||
throw;
|
||||
}
|
||||
|
||||
RegCloseKey(k);
|
||||
}
|
||||
|
||||
static void unregister_clsid(const GUID clsid) {
|
||||
WCHAR* clsidstring;
|
||||
|
||||
StringFromCLSID(clsid, &clsidstring);
|
||||
|
||||
try {
|
||||
WCHAR clsidkeyname[MAX_PATH];
|
||||
|
||||
wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring);
|
||||
|
||||
LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname);
|
||||
|
||||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGDELETETREE_FAILED, l);
|
||||
#ifndef __REACTOS__
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, L"CLSID\\"s + clsidstring);
|
||||
#else
|
||||
wstring path = wstring(L"CLSID\\") + clsidstring;
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, path);
|
||||
#endif
|
||||
} catch (...) {
|
||||
CoTaskMemFree(clsidstring);
|
||||
throw;
|
||||
|
@ -385,15 +436,11 @@ static void reg_icon_overlay(const GUID clsid, const wstring& name) {
|
|||
|
||||
static void unreg_icon_overlay(const wstring& name) {
|
||||
#ifndef __REACTOS__
|
||||
wstring path = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name;
|
||||
reg_delete_tree(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name);
|
||||
#else
|
||||
wstring path = wstring(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\") + name;
|
||||
reg_delete_tree(HKEY_LOCAL_MACHINE, path);
|
||||
#endif
|
||||
|
||||
LONG l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path.c_str());
|
||||
|
||||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGDELETETREE_FAILED, l);
|
||||
}
|
||||
|
||||
static void reg_context_menu_handler(const GUID clsid, const wstring& filetype, const wstring& name) {
|
||||
|
@ -417,15 +464,11 @@ static void reg_context_menu_handler(const GUID clsid, const wstring& filetype,
|
|||
|
||||
static void unreg_context_menu_handler(const wstring& filetype, const wstring& name) {
|
||||
#ifndef __REACTOS__
|
||||
wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name;
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name);
|
||||
#else
|
||||
wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name;
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, path);
|
||||
#endif
|
||||
|
||||
LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str());
|
||||
|
||||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGDELETETREE_FAILED, l);
|
||||
}
|
||||
|
||||
static void reg_prop_sheet_handler(const GUID clsid, const wstring& filetype, const wstring& name) {
|
||||
|
@ -449,15 +492,11 @@ static void reg_prop_sheet_handler(const GUID clsid, const wstring& filetype, co
|
|||
|
||||
static void unreg_prop_sheet_handler(const wstring& filetype, const wstring& name) {
|
||||
#ifndef __REACTOS__
|
||||
wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name;
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name);
|
||||
#else
|
||||
wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name;
|
||||
reg_delete_tree(HKEY_CLASSES_ROOT, path);
|
||||
#endif
|
||||
|
||||
LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str());
|
||||
|
||||
if (l != ERROR_SUCCESS)
|
||||
throw string_error(IDS_REGDELETETREE_FAILED, l);
|
||||
}
|
||||
|
||||
extern "C" STDAPI DllRegisterServer(void) {
|
||||
|
@ -522,7 +561,6 @@ static void create_subvol(const wstring& fn) {
|
|||
size_t found = fn.rfind(L"\\");
|
||||
wstring path, file;
|
||||
win_handle h;
|
||||
ULONG bcslen;
|
||||
btrfs_create_subvol* bcs;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
|
@ -540,7 +578,7 @@ static void create_subvol(const wstring& fn) {
|
|||
if (h == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR));
|
||||
size_t bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR));
|
||||
bcs = (btrfs_create_subvol*)malloc(bcslen);
|
||||
|
||||
bcs->readonly = false;
|
||||
|
@ -548,7 +586,7 @@ static void create_subvol(const wstring& fn) {
|
|||
bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, file.c_str(), bcs->namelen);
|
||||
|
||||
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
|
||||
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
}
|
||||
|
||||
extern "C" void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||
|
@ -564,7 +602,6 @@ static void create_snapshot2(const wstring& source, const wstring& fn) {
|
|||
size_t found = fn.rfind(L"\\");
|
||||
wstring path, file;
|
||||
win_handle h, src;
|
||||
ULONG bcslen;
|
||||
btrfs_create_snapshot* bcs;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
|
@ -586,7 +623,7 @@ static void create_snapshot2(const wstring& source, const wstring& fn) {
|
|||
if (h == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR));
|
||||
size_t bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR));
|
||||
bcs = (btrfs_create_snapshot*)malloc(bcslen);
|
||||
|
||||
bcs->readonly = false;
|
||||
|
@ -595,7 +632,7 @@ static void create_snapshot2(const wstring& source, const wstring& fn) {
|
|||
memcpy(bcs->name, file.c_str(), bcs->namelen);
|
||||
bcs->subvol = src;
|
||||
|
||||
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
|
||||
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
}
|
||||
|
||||
extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||
|
@ -607,7 +644,7 @@ extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpsz
|
|||
create_snapshot2(args[0], args[1]);
|
||||
}
|
||||
|
||||
void command_line_to_args(LPWSTR cmdline, vector<wstring> args) {
|
||||
void command_line_to_args(LPWSTR cmdline, vector<wstring>& args) {
|
||||
LPWSTR* l;
|
||||
int num_args;
|
||||
|
||||
|
@ -632,6 +669,38 @@ void command_line_to_args(LPWSTR cmdline, vector<wstring> args) {
|
|||
LocalFree(l);
|
||||
}
|
||||
|
||||
static string utf16_to_utf8(const wstring_view& utf16) {
|
||||
string utf8;
|
||||
char* buf;
|
||||
|
||||
if (utf16.empty())
|
||||
return "";
|
||||
|
||||
auto utf8len = WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.length()), nullptr, 0, nullptr, nullptr);
|
||||
|
||||
if (utf8len == 0)
|
||||
throw last_error(GetLastError());
|
||||
|
||||
buf = (char*)malloc(utf8len + sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
throw string_error(IDS_OUT_OF_MEMORY);
|
||||
|
||||
if (WideCharToMultiByte(CP_UTF8, 0, utf16.data(), static_cast<int>(utf16.length()), buf, utf8len, nullptr, nullptr) == 0) {
|
||||
auto le = GetLastError();
|
||||
free(buf);
|
||||
throw last_error(le);
|
||||
}
|
||||
|
||||
buf[utf8len] = 0;
|
||||
|
||||
utf8 = buf;
|
||||
|
||||
free(buf);
|
||||
|
||||
return utf8;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4996)
|
||||
|
@ -657,65 +726,43 @@ string_error::string_error(int resno, ...) {
|
|||
|
||||
va_end(args);
|
||||
|
||||
utf16_to_utf8(s, msg);
|
||||
msg = utf16_to_utf8(s);
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
void utf8_to_utf16(const string& utf8, wstring& utf16) {
|
||||
NTSTATUS Status;
|
||||
ULONG utf16len;
|
||||
wstring utf8_to_utf16(const string_view& utf8) {
|
||||
wstring ret;
|
||||
WCHAR* buf;
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(nullptr, 0, &utf16len, utf8.c_str(), utf8.length());
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
if (utf8.empty())
|
||||
return L"";
|
||||
|
||||
buf = (WCHAR*)malloc(utf16len + sizeof(WCHAR));
|
||||
auto utf16len = MultiByteToWideChar(CP_UTF8, 0, utf8.data(), (int)utf8.length(), nullptr, 0);
|
||||
|
||||
if (utf16len == 0)
|
||||
throw last_error(GetLastError());
|
||||
|
||||
buf = (WCHAR*)malloc((utf16len + 1) * sizeof(WCHAR));
|
||||
|
||||
if (!buf)
|
||||
throw string_error(IDS_OUT_OF_MEMORY);
|
||||
|
||||
Status = RtlUTF8ToUnicodeN(buf, utf16len, &utf16len, utf8.c_str(), utf8.length());
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
if (MultiByteToWideChar(CP_UTF8, 0, utf8.data(), (int)utf8.length(), buf, utf16len) == 0) {
|
||||
auto le = GetLastError();
|
||||
free(buf);
|
||||
throw string_error(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
throw last_error(le);
|
||||
}
|
||||
|
||||
buf[utf16len / sizeof(WCHAR)] = 0;
|
||||
buf[utf16len] = 0;
|
||||
|
||||
utf16 = buf;
|
||||
ret = buf;
|
||||
|
||||
free(buf);
|
||||
}
|
||||
|
||||
void utf16_to_utf8(const wstring& utf16, string& utf8) {
|
||||
NTSTATUS Status;
|
||||
ULONG utf8len;
|
||||
char* buf;
|
||||
|
||||
Status = RtlUnicodeToUTF8N(nullptr, 0, &utf8len, utf16.c_str(), utf16.length() * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_RTLUNICODETOUTF8N_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
||||
buf = (char*)malloc(utf8len + sizeof(char));
|
||||
|
||||
if (!buf)
|
||||
throw string_error(IDS_OUT_OF_MEMORY);
|
||||
|
||||
Status = RtlUnicodeToUTF8N(buf, utf8len, &utf8len, utf16.c_str(), utf16.length() * sizeof(WCHAR));
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(buf);
|
||||
throw string_error(IDS_RECV_RTLUNICODETOUTF8N_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
}
|
||||
|
||||
buf[utf8len] = 0;
|
||||
|
||||
utf8 = buf;
|
||||
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
last_error::last_error(DWORD errnum) {
|
||||
|
@ -726,7 +773,7 @@ last_error::last_error(DWORD errnum) {
|
|||
throw runtime_error("FormatMessage failed");
|
||||
|
||||
try {
|
||||
utf16_to_utf8(buf, msg);
|
||||
msg = utf16_to_utf8(buf);
|
||||
} catch (...) {
|
||||
LocalFree(buf);
|
||||
throw;
|
||||
|
@ -736,16 +783,16 @@ last_error::last_error(DWORD errnum) {
|
|||
}
|
||||
|
||||
void error_message(HWND hwnd, const char* msg) {
|
||||
wstring title, wmsg;
|
||||
wstring title;
|
||||
|
||||
load_string(module, IDS_ERROR, title);
|
||||
|
||||
utf8_to_utf16(msg, wmsg);
|
||||
auto wmsg = utf8_to_utf16(msg);
|
||||
|
||||
MessageBoxW(hwnd, wmsg.c_str(), title.c_str(), MB_ICONERROR);
|
||||
}
|
||||
|
||||
ntstatus_error::ntstatus_error(NTSTATUS Status) {
|
||||
ntstatus_error::ntstatus_error(NTSTATUS Status) : Status(Status) {
|
||||
_RtlNtStatusToDosError RtlNtStatusToDosError;
|
||||
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
|
||||
WCHAR* buf;
|
||||
|
@ -764,7 +811,7 @@ ntstatus_error::ntstatus_error(NTSTATUS Status) {
|
|||
throw runtime_error("FormatMessage failed");
|
||||
|
||||
try {
|
||||
utf16_to_utf8(buf, msg);
|
||||
msg = utf16_to_utf8(buf);
|
||||
} catch (...) {
|
||||
LocalFree(buf);
|
||||
throw;
|
||||
|
@ -778,112 +825,3 @@ ntstatus_error::ntstatus_error(NTSTATUS Status) {
|
|||
|
||||
FreeLibrary(ntdll);
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
NTSTATUS NTAPI RtlUnicodeToUTF8N(CHAR *utf8_dest, ULONG utf8_bytes_max,
|
||||
ULONG *utf8_bytes_written,
|
||||
const WCHAR *uni_src, ULONG uni_bytes)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG i;
|
||||
ULONG written;
|
||||
ULONG ch;
|
||||
BYTE utf8_ch[4];
|
||||
ULONG utf8_ch_len;
|
||||
|
||||
if (!uni_src)
|
||||
return STATUS_INVALID_PARAMETER_4;
|
||||
if (!utf8_bytes_written)
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
if (utf8_dest && uni_bytes % sizeof(WCHAR))
|
||||
return STATUS_INVALID_PARAMETER_5;
|
||||
|
||||
written = 0;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
for (i = 0; i < uni_bytes / sizeof(WCHAR); i++)
|
||||
{
|
||||
/* decode UTF-16 into ch */
|
||||
ch = uni_src[i];
|
||||
if (ch >= 0xdc00 && ch <= 0xdfff)
|
||||
{
|
||||
ch = 0xfffd;
|
||||
status = STATUS_SOME_NOT_MAPPED;
|
||||
}
|
||||
else if (ch >= 0xd800 && ch <= 0xdbff)
|
||||
{
|
||||
if (i + 1 < uni_bytes / sizeof(WCHAR))
|
||||
{
|
||||
ch -= 0xd800;
|
||||
ch <<= 10;
|
||||
if (uni_src[i + 1] >= 0xdc00 && uni_src[i + 1] <= 0xdfff)
|
||||
{
|
||||
ch |= uni_src[i + 1] - 0xdc00;
|
||||
ch += 0x010000;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = 0xfffd;
|
||||
status = STATUS_SOME_NOT_MAPPED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ch = 0xfffd;
|
||||
status = STATUS_SOME_NOT_MAPPED;
|
||||
}
|
||||
}
|
||||
|
||||
/* encode ch as UTF-8 */
|
||||
if (ch < 0x80)
|
||||
{
|
||||
utf8_ch[0] = ch & 0x7f;
|
||||
utf8_ch_len = 1;
|
||||
}
|
||||
else if (ch < 0x800)
|
||||
{
|
||||
utf8_ch[0] = 0xc0 | (ch >> 6 & 0x1f);
|
||||
utf8_ch[1] = 0x80 | (ch >> 0 & 0x3f);
|
||||
utf8_ch_len = 2;
|
||||
}
|
||||
else if (ch < 0x10000)
|
||||
{
|
||||
utf8_ch[0] = 0xe0 | (ch >> 12 & 0x0f);
|
||||
utf8_ch[1] = 0x80 | (ch >> 6 & 0x3f);
|
||||
utf8_ch[2] = 0x80 | (ch >> 0 & 0x3f);
|
||||
utf8_ch_len = 3;
|
||||
}
|
||||
else if (ch < 0x200000)
|
||||
{
|
||||
utf8_ch[0] = 0xf0 | (ch >> 18 & 0x07);
|
||||
utf8_ch[1] = 0x80 | (ch >> 12 & 0x3f);
|
||||
utf8_ch[2] = 0x80 | (ch >> 6 & 0x3f);
|
||||
utf8_ch[3] = 0x80 | (ch >> 0 & 0x3f);
|
||||
utf8_ch_len = 4;
|
||||
}
|
||||
|
||||
if (!utf8_dest)
|
||||
{
|
||||
written += utf8_ch_len;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (utf8_bytes_max >= utf8_ch_len)
|
||||
{
|
||||
memcpy(utf8_dest, utf8_ch, utf8_ch_len);
|
||||
utf8_dest += utf8_ch_len;
|
||||
utf8_bytes_max -= utf8_ch_len;
|
||||
written += utf8_ch_len;
|
||||
}
|
||||
else
|
||||
{
|
||||
utf8_bytes_max = 0;
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
|
||||
*utf8_bytes_written = written;
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
|
180
dll/shellext/shellbtrfs/mountmgr_local.cpp
Normal file
180
dll/shellext/shellbtrfs/mountmgr_local.cpp
Normal file
|
@ -0,0 +1,180 @@
|
|||
#include "shellext.h"
|
||||
#ifndef __REACTOS__
|
||||
#include "mountmgr.h"
|
||||
#else
|
||||
#include "mountmgr_local.h"
|
||||
#endif
|
||||
#include <mountmgr.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
mountmgr::mountmgr() {
|
||||
UNICODE_STRING us;
|
||||
OBJECT_ATTRIBUTES attr;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
|
||||
RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME);
|
||||
InitializeObjectAttributes(&attr, &us, 0, nullptr, nullptr);
|
||||
|
||||
Status = NtOpenFile(&h, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb,
|
||||
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
mountmgr::~mountmgr() {
|
||||
NtClose(h);
|
||||
}
|
||||
|
||||
void mountmgr::create_point(const wstring_view& symlink, const wstring_view& device) const {
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
vector<uint8_t> buf(sizeof(MOUNTMGR_CREATE_POINT_INPUT) + ((symlink.length() + device.length()) * sizeof(WCHAR)));
|
||||
auto mcpi = reinterpret_cast<MOUNTMGR_CREATE_POINT_INPUT*>(buf.data());
|
||||
|
||||
mcpi->SymbolicLinkNameOffset = sizeof(MOUNTMGR_CREATE_POINT_INPUT);
|
||||
mcpi->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
|
||||
mcpi->DeviceNameOffset = (USHORT)(mcpi->SymbolicLinkNameOffset + mcpi->SymbolicLinkNameLength);
|
||||
mcpi->DeviceNameLength = (USHORT)(device.length() * sizeof(WCHAR));
|
||||
|
||||
memcpy((uint8_t*)mcpi + mcpi->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mcpi + mcpi->DeviceNameOffset, device.data(), device.length() * sizeof(WCHAR));
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_CREATE_POINT,
|
||||
buf.data(), (ULONG)buf.size(), nullptr, 0);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
void mountmgr::delete_points(const wstring_view& symlink, const wstring_view& unique_id, const wstring_view& device_name) const {
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
vector<uint8_t> buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR)));
|
||||
auto mmp = reinterpret_cast<MOUNTMGR_MOUNT_POINT*>(buf.data());
|
||||
|
||||
memset(mmp, 0, sizeof(MOUNTMGR_MOUNT_POINT));
|
||||
|
||||
if (symlink.length() > 0) {
|
||||
mmp->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
mmp->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (unique_id.length() > 0) {
|
||||
if (mmp->SymbolicLinkNameLength == 0)
|
||||
mmp->UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
else
|
||||
mmp->UniqueIdOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
|
||||
|
||||
mmp->UniqueIdLength = (USHORT)(unique_id.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->UniqueIdOffset, unique_id.data(), unique_id.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (device_name.length() > 0) {
|
||||
if (mmp->SymbolicLinkNameLength == 0 && mmp->UniqueIdOffset == 0)
|
||||
mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
else if (mmp->SymbolicLinkNameLength != 0)
|
||||
mmp->DeviceNameOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
|
||||
else
|
||||
mmp->DeviceNameOffset = mmp->UniqueIdOffset + mmp->UniqueIdLength;
|
||||
|
||||
mmp->DeviceNameLength = (USHORT)(device_name.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->DeviceNameOffset, device_name.data(), device_name.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
vector<uint8_t> buf2(sizeof(MOUNTMGR_MOUNT_POINTS));
|
||||
auto mmps = reinterpret_cast<MOUNTMGR_MOUNT_POINTS*>(buf2.data());
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_DELETE_POINTS,
|
||||
buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
|
||||
|
||||
if (Status == STATUS_BUFFER_OVERFLOW) {
|
||||
buf2.resize(mmps->Size);
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_DELETE_POINTS,
|
||||
buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
|
||||
}
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
vector<mountmgr_point> mountmgr::query_points(const wstring_view& symlink, const wstring_view& unique_id, const wstring_view& device_name) const {
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
vector<mountmgr_point> v;
|
||||
|
||||
vector<uint8_t> buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR)));
|
||||
auto mmp = reinterpret_cast<MOUNTMGR_MOUNT_POINT*>(buf.data());
|
||||
|
||||
memset(mmp, 0, sizeof(MOUNTMGR_MOUNT_POINT));
|
||||
|
||||
if (symlink.length() > 0) {
|
||||
mmp->SymbolicLinkNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
mmp->SymbolicLinkNameLength = (USHORT)(symlink.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->SymbolicLinkNameOffset, symlink.data(), symlink.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (unique_id.length() > 0) {
|
||||
if (mmp->SymbolicLinkNameLength == 0)
|
||||
mmp->UniqueIdOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
else
|
||||
mmp->UniqueIdOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
|
||||
|
||||
mmp->UniqueIdLength = (USHORT)(unique_id.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->UniqueIdOffset, unique_id.data(), unique_id.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
if (device_name.length() > 0) {
|
||||
if (mmp->SymbolicLinkNameLength == 0 && mmp->UniqueIdOffset == 0)
|
||||
mmp->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
|
||||
else if (mmp->SymbolicLinkNameLength != 0)
|
||||
mmp->DeviceNameOffset = mmp->SymbolicLinkNameOffset + mmp->SymbolicLinkNameLength;
|
||||
else
|
||||
mmp->DeviceNameOffset = mmp->UniqueIdOffset + mmp->UniqueIdLength;
|
||||
|
||||
mmp->DeviceNameLength = (USHORT)(device_name.length() * sizeof(WCHAR));
|
||||
memcpy((uint8_t*)mmp + mmp->DeviceNameOffset, device_name.data(), device_name.length() * sizeof(WCHAR));
|
||||
}
|
||||
|
||||
vector<uint8_t> buf2(sizeof(MOUNTMGR_MOUNT_POINTS));
|
||||
auto mmps = reinterpret_cast<MOUNTMGR_MOUNT_POINTS*>(buf2.data());
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
|
||||
buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
|
||||
|
||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
buf2.resize(mmps->Size);
|
||||
mmps = reinterpret_cast<MOUNTMGR_MOUNT_POINTS*>(buf2.data());
|
||||
|
||||
Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS,
|
||||
buf.data(), (ULONG)buf.size(), buf2.data(), (ULONG)buf2.size());
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
for (ULONG i = 0; i < mmps->NumberOfMountPoints; i++) {
|
||||
wstring_view mpsl, mpdn;
|
||||
string_view mpuid;
|
||||
|
||||
if (mmps->MountPoints[i].SymbolicLinkNameLength)
|
||||
mpsl = wstring_view((WCHAR*)((uint8_t*)mmps + mmps->MountPoints[i].SymbolicLinkNameOffset), mmps->MountPoints[i].SymbolicLinkNameLength / sizeof(WCHAR));
|
||||
|
||||
if (mmps->MountPoints[i].UniqueIdLength)
|
||||
mpuid = string_view((char*)((uint8_t*)mmps + mmps->MountPoints[i].UniqueIdOffset), mmps->MountPoints[i].UniqueIdLength);
|
||||
|
||||
if (mmps->MountPoints[i].DeviceNameLength)
|
||||
mpdn = wstring_view((WCHAR*)((uint8_t*)mmps + mmps->MountPoints[i].DeviceNameOffset), mmps->MountPoints[i].DeviceNameLength / sizeof(WCHAR));
|
||||
|
||||
v.emplace_back(mpsl, mpuid, mpdn);
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
34
dll/shellext/shellbtrfs/mountmgr_local.h
Normal file
34
dll/shellext/shellbtrfs/mountmgr_local.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#ifndef __REACTOS__
|
||||
#include <string_view>
|
||||
#else
|
||||
#define string_view string
|
||||
#define wstring_view wstring
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
class mountmgr_point {
|
||||
public:
|
||||
mountmgr_point(const std::wstring_view& symlink, const std::string_view& unique_id, const std::wstring_view& device_name) : symlink(symlink), device_name(device_name), unique_id(unique_id) {
|
||||
}
|
||||
|
||||
std::wstring symlink, device_name;
|
||||
std::string unique_id;
|
||||
};
|
||||
|
||||
class mountmgr {
|
||||
public:
|
||||
mountmgr();
|
||||
~mountmgr();
|
||||
void create_point(const std::wstring_view& symlink, const std::wstring_view& device) const;
|
||||
void delete_points(const std::wstring_view& symlink, const std::wstring_view& unique_id = L"", const std::wstring_view& device_name = L"") const;
|
||||
std::vector<mountmgr_point> query_points(const std::wstring_view& symlink = L"", const std::wstring_view& unique_id = L"", const std::wstring_view& device_name = L"") const;
|
||||
|
||||
private:
|
||||
HANDLE h;
|
||||
};
|
48
dll/shellext/shellbtrfs/propsheet.cpp
Normal file → Executable file
48
dll/shellext/shellbtrfs/propsheet.cpp
Normal file → Executable file
|
@ -60,6 +60,13 @@ typedef struct _FILE_STANDARD_INFORMATION {
|
|||
|
||||
#define FileStandardInformation (FILE_INFORMATION_CLASS)5
|
||||
|
||||
typedef struct _FILE_FS_SIZE_INFORMATION {
|
||||
LARGE_INTEGER TotalAllocationUnits;
|
||||
LARGE_INTEGER AvailableAllocationUnits;
|
||||
ULONG SectorsPerAllocationUnit;
|
||||
ULONG BytesPerSector;
|
||||
} FILE_FS_SIZE_INFORMATION, *PFILE_FS_SIZE_INFORMATION;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -125,6 +132,7 @@ void BtrfsPropSheet::do_search(const wstring& fn) {
|
|||
sizes[4] += bii2.disk_size_zstd;
|
||||
totalsize += bii2.inline_length + bii2.disk_size_uncompressed + bii2.disk_size_zlib + bii2.disk_size_lzo + bii2.disk_size_zstd;
|
||||
sparsesize += bii2.sparse_size;
|
||||
num_extents += bii2.num_extents == 0 ? 0 : (bii2.num_extents - 1);
|
||||
}
|
||||
|
||||
FILE_STANDARD_INFORMATION fsi;
|
||||
|
@ -247,6 +255,7 @@ HRESULT BtrfsPropSheet::check_file(const wstring& fn, UINT i, UINT num_files, UI
|
|||
}
|
||||
|
||||
sparsesize += bii2.sparse_size;
|
||||
num_extents += bii2.num_extents == 0 ? 0 : (bii2.num_extents - 1);
|
||||
|
||||
FILE_STANDARD_INFORMATION fsi;
|
||||
|
||||
|
@ -288,6 +297,18 @@ HRESULT BtrfsPropSheet::check_file(const wstring& fn, UINT i, UINT num_files, UI
|
|||
if (filesize.QuadPart != 0)
|
||||
can_change_nocow = false;
|
||||
}
|
||||
|
||||
{
|
||||
FILE_FS_SIZE_INFORMATION ffsi;
|
||||
|
||||
Status = NtQueryVolumeInformationFile(h, &iosb, &ffsi, sizeof(ffsi), FileFsSizeInformation);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
sector_size = ffsi.BytesPerSector;
|
||||
|
||||
if (sector_size == 0)
|
||||
sector_size = 4096;
|
||||
}
|
||||
} else
|
||||
return E_FAIL;
|
||||
|
||||
|
@ -623,8 +644,9 @@ void BtrfsPropSheet::apply_changes_file(HWND hDlg, const wstring& fn) {
|
|||
else
|
||||
fbi.FileAttributes &= ~FILE_ATTRIBUTE_READONLY;
|
||||
|
||||
if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(fbi)))
|
||||
throw last_error(GetLastError());
|
||||
Status = NtSetInformationFile(h, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
if (flags_changed || perms_changed || uid_changed || gid_changed || compress_type_changed) {
|
||||
|
@ -693,7 +715,7 @@ void BtrfsPropSheet::apply_changes(HWND hDlg) {
|
|||
}
|
||||
|
||||
void BtrfsPropSheet::set_size_on_disk(HWND hwndDlg) {
|
||||
wstring s, size_on_disk, cr;
|
||||
wstring s, size_on_disk, cr, frag;
|
||||
WCHAR old_text[1024];
|
||||
float ratio;
|
||||
|
||||
|
@ -717,6 +739,21 @@ void BtrfsPropSheet::set_size_on_disk(HWND hwndDlg) {
|
|||
|
||||
if (cr != old_text)
|
||||
SetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, cr.c_str());
|
||||
|
||||
uint64_t extent_size = (allocsize - sparsesize - sizes[0]) / sector_size;
|
||||
|
||||
if (num_extents == 0 || extent_size <= 1)
|
||||
ratio = 0.0f;
|
||||
else
|
||||
ratio = 100.0f * ((float)num_extents / (float)(extent_size - 1));
|
||||
|
||||
wstring_sprintf(frag, frag_format, ratio);
|
||||
|
||||
GetDlgItemTextW(hwndDlg, IDC_FRAGMENTATION, old_text, sizeof(old_text) / sizeof(WCHAR));
|
||||
|
||||
|
||||
if (frag != old_text)
|
||||
SetDlgItemTextW(hwndDlg, IDC_FRAGMENTATION, frag.c_str());
|
||||
}
|
||||
|
||||
void BtrfsPropSheet::change_perm_flag(HWND hDlg, ULONG flag, UINT state) {
|
||||
|
@ -945,6 +982,9 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) {
|
|||
if (cr_format[0] == 0)
|
||||
GetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, cr_format, sizeof(cr_format) / sizeof(WCHAR));
|
||||
|
||||
if (frag_format[0] == 0)
|
||||
GetDlgItemTextW(hwndDlg, IDC_FRAGMENTATION, frag_format, sizeof(frag_format) / sizeof(WCHAR));
|
||||
|
||||
set_size_on_disk(hwndDlg);
|
||||
|
||||
if (thread)
|
||||
|
@ -1180,7 +1220,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
|||
case CBN_SELCHANGE: {
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDC_COMPRESS_TYPE: {
|
||||
int sel = SendMessageW(GetDlgItem(hwndDlg, LOWORD(wParam)), CB_GETCURSEL, 0, 0);
|
||||
auto sel = SendMessageW(GetDlgItem(hwndDlg, LOWORD(wParam)), CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (bps->min_compression_type != bps->max_compression_type) {
|
||||
if (sel == 0)
|
||||
|
|
|
@ -111,8 +111,11 @@ public:
|
|||
|
||||
sizes[0] = sizes[1] = sizes[2] = sizes[3] = sizes[4] = 0;
|
||||
totalsize = allocsize = sparsesize = 0;
|
||||
num_extents = 0;
|
||||
sector_size = 0;
|
||||
size_format[0] = 0;
|
||||
cr_format[0] = 0;
|
||||
frag_format[0] = 0;
|
||||
|
||||
InterlockedIncrement(&objs_loaded);
|
||||
}
|
||||
|
@ -168,7 +171,7 @@ public:
|
|||
bool readonly;
|
||||
bool can_change_perms;
|
||||
bool can_change_nocow;
|
||||
WCHAR size_format[255], cr_format[255];
|
||||
WCHAR size_format[255], cr_format[255], frag_format[255];
|
||||
HANDLE thread;
|
||||
uint32_t min_mode, max_mode, mode, mode_set;
|
||||
uint64_t min_flags, max_flags, flags, flags_set;
|
||||
|
@ -184,9 +187,10 @@ private:
|
|||
STGMEDIUM stgm;
|
||||
bool stgm_set;
|
||||
bool flags_changed, perms_changed, uid_changed, gid_changed;
|
||||
uint64_t sizes[5], totalsize, allocsize, sparsesize;
|
||||
uint64_t sizes[5], totalsize, allocsize, sparsesize, num_extents;
|
||||
deque<wstring> search_list;
|
||||
wstring filename;
|
||||
uint32_t sector_size;
|
||||
|
||||
void apply_changes_file(HWND hDlg, const wstring& fn);
|
||||
HRESULT check_file(const wstring& fn, UINT i, UINT num_files, UINT* sv);
|
||||
|
|
|
@ -84,8 +84,8 @@ static const uint32_t crctable[] = {
|
|||
#define ALIGN_MASK (ALIGN_SIZE - 1)
|
||||
#define CALC_CRC(op, crc, type, buf, len) \
|
||||
do { \
|
||||
for (; (len) >= sizeof (type); (len) -= sizeof(type), buf += sizeof (type)) { \
|
||||
(crc) = op((crc), *(type *) (buf)); \
|
||||
for (; (len) >= sizeof (type); (len) -= (ULONG)sizeof(type), buf += sizeof (type)) { \
|
||||
(crc) = (uint32_t)op((crc), *(type *) (buf)); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
@ -153,7 +153,7 @@ static uint32_t calc_crc32c(uint32_t seed, uint8_t* msg, ULONG msglen) {
|
|||
}
|
||||
|
||||
bool BtrfsRecv::find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len) {
|
||||
ULONG off = 0;
|
||||
size_t off = 0;
|
||||
|
||||
while (off < datalen) {
|
||||
btrfs_send_tlv* tlv = (btrfs_send_tlv*)(data + off);
|
||||
|
@ -178,11 +178,10 @@ void BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, co
|
|||
string name;
|
||||
BTRFS_UUID* uuid;
|
||||
uint64_t* gen;
|
||||
ULONG uuidlen, genlen, bcslen;
|
||||
ULONG uuidlen, genlen;
|
||||
btrfs_create_subvol* bcs;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
wstring nameu;
|
||||
|
||||
{
|
||||
char* namebuf;
|
||||
|
@ -209,9 +208,9 @@ void BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, co
|
|||
this->subvol_uuid = *uuid;
|
||||
this->stransid = *gen;
|
||||
|
||||
utf8_to_utf16(name, nameu);
|
||||
auto nameu = utf8_to_utf16(name);
|
||||
|
||||
bcslen = offsetof(btrfs_create_subvol, name[0]) + (nameu.length() * sizeof(WCHAR));
|
||||
size_t bcslen = offsetof(btrfs_create_subvol, name[0]) + (nameu.length() * sizeof(WCHAR));
|
||||
bcs = (btrfs_create_subvol*)malloc(bcslen);
|
||||
|
||||
bcs->readonly = true;
|
||||
|
@ -219,7 +218,7 @@ void BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, co
|
|||
bcs->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, nameu.c_str(), bcs->namelen);
|
||||
|
||||
Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_CREATE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
||||
|
@ -238,7 +237,7 @@ void BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, co
|
|||
if (master == INVALID_HANDLE_VALUE)
|
||||
throw string_error(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
|
||||
Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
||||
|
@ -269,13 +268,14 @@ void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data,
|
|||
string name;
|
||||
BTRFS_UUID *uuid, *parent_uuid;
|
||||
uint64_t *gen, *parent_transid;
|
||||
ULONG uuidlen, genlen, paruuidlen, partransidlen, bcslen;
|
||||
ULONG uuidlen, genlen, paruuidlen, partransidlen;
|
||||
btrfs_create_snapshot* bcs;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
wstring nameu, parpath;
|
||||
wstring parpath;
|
||||
btrfs_find_subvol bfs;
|
||||
WCHAR parpathw[MAX_PATH], volpathw[MAX_PATH];
|
||||
size_t bcslen;
|
||||
|
||||
{
|
||||
char* namebuf;
|
||||
|
@ -314,7 +314,7 @@ void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data,
|
|||
this->subvol_uuid = *uuid;
|
||||
this->stransid = *gen;
|
||||
|
||||
utf8_to_utf16(name, nameu);
|
||||
auto nameu = utf8_to_utf16(name);
|
||||
|
||||
bfs.uuid = *parent_uuid;
|
||||
bfs.ctransid = *parent_transid;
|
||||
|
@ -350,7 +350,7 @@ void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data,
|
|||
bcs->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR));
|
||||
memcpy(bcs->name, nameu.c_str(), bcs->namelen);
|
||||
|
||||
Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_CREATE_SNAPSHOT_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
}
|
||||
|
@ -370,7 +370,7 @@ void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data,
|
|||
if (master == INVALID_HANDLE_VALUE)
|
||||
throw string_error(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
|
||||
Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, nullptr, 0);
|
||||
Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw string_error(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
||||
|
@ -389,7 +389,7 @@ void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data,
|
|||
|
||||
void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
||||
uint64_t *inode, *rdev = nullptr, *mode = nullptr;
|
||||
ULONG inodelen, bmnsize;
|
||||
ULONG inodelen;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
btrfs_mknod* bmn;
|
||||
|
@ -402,7 +402,7 @@ void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&name, &namelen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(name, namelen), nameu);
|
||||
nameu = utf8_to_utf16(string(name, namelen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_INODE, (void**)&inode, &inodelen))
|
||||
|
@ -432,10 +432,10 @@ void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_LINK, (void**)&pathlink, &pathlinklen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path_link");
|
||||
|
||||
utf8_to_utf16(string(pathlink, pathlinklen), pathlinku);
|
||||
pathlinku = utf8_to_utf16(string(pathlink, pathlinklen));
|
||||
}
|
||||
|
||||
bmnsize = sizeof(btrfs_mknod) - sizeof(WCHAR) + (nameu.length() * sizeof(WCHAR));
|
||||
size_t bmnsize = sizeof(btrfs_mknod) - sizeof(WCHAR) + (nameu.length() * sizeof(WCHAR));
|
||||
bmn = (btrfs_mknod*)malloc(bmnsize);
|
||||
|
||||
bmn->inode = *inode;
|
||||
|
@ -455,7 +455,7 @@ void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
bmn->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR));
|
||||
memcpy(bmn->name, nameu.c_str(), bmn->namelen);
|
||||
|
||||
Status = NtFsControlFile(dir, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
|
||||
Status = NtFsControlFile(dir, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bmn);
|
||||
throw string_error(IDS_RECV_MKNOD_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
@ -465,10 +465,9 @@ void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
|
||||
if (cmd->cmd == BTRFS_SEND_CMD_SYMLINK) {
|
||||
REPARSE_DATA_BUFFER* rdb;
|
||||
ULONG rdblen;
|
||||
btrfs_set_inode_info bsii;
|
||||
|
||||
rdblen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0]) + (2 * pathlinku.length() * sizeof(WCHAR));
|
||||
size_t rdblen = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer[0]) + (2 * pathlinku.length() * sizeof(WCHAR));
|
||||
|
||||
if (rdblen >= 0x10000)
|
||||
throw string_error(IDS_RECV_PATH_TOO_LONG, funcname);
|
||||
|
@ -495,7 +494,7 @@ void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, nameu.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
}
|
||||
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_SET_REPARSE_POINT, rdb, rdblen, nullptr, 0);
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_SET_REPARSE_POINT, rdb, (ULONG)rdblen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(rdb);
|
||||
throw string_error(IDS_RECV_SET_REPARSE_POINT_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
@ -548,7 +547,7 @@ void BtrfsRecv::cmd_rename(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &path_len))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, path_len), pathu);
|
||||
pathu = utf8_to_utf16(string(path, path_len));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -558,7 +557,7 @@ void BtrfsRecv::cmd_rename(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_TO, (void**)&path_to, &path_to_len))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path_to");
|
||||
|
||||
utf8_to_utf16(string(path_to, path_to_len), path_tou);
|
||||
path_tou = utf8_to_utf16(string(path_to, path_to_len));
|
||||
}
|
||||
|
||||
if (!MoveFileW((subvolpath + pathu).c_str(), (subvolpath + path_tou).c_str()))
|
||||
|
@ -575,7 +574,7 @@ void BtrfsRecv::cmd_link(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &path_len))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, path_len), pathu);
|
||||
pathu = utf8_to_utf16(string(path, path_len));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -585,7 +584,7 @@ void BtrfsRecv::cmd_link(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_LINK, (void**)&path_link, &path_link_len))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path_link");
|
||||
|
||||
utf8_to_utf16(string(path_link, path_link_len), path_linku);
|
||||
path_linku = utf8_to_utf16(string(path_link, path_link_len));
|
||||
}
|
||||
|
||||
if (!CreateHardLinkW((subvolpath + pathu).c_str(), (subvolpath + path_linku).c_str(), nullptr))
|
||||
|
@ -603,7 +602,7 @@ void BtrfsRecv::cmd_unlink(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
att = GetFileAttributesW((subvolpath + pathu).c_str());
|
||||
|
@ -630,7 +629,7 @@ void BtrfsRecv::cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
att = GetFileAttributesW((subvolpath + pathu).c_str());
|
||||
|
@ -659,7 +658,7 @@ void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -677,10 +676,9 @@ void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
|
||||
if (xattrname.length() > XATTR_USER.length() && xattrname.substr(0, XATTR_USER.length()) == XATTR_USER &&
|
||||
xattrname != EA_DOSATTRIB && xattrname != EA_EA && xattrname != EA_REPARSE) {
|
||||
wstring streamname;
|
||||
ULONG att;
|
||||
|
||||
utf8_to_utf16(xattrname, streamname);
|
||||
auto streamname = utf8_to_utf16(xattrname);
|
||||
|
||||
att = GetFileAttributesW((subvolpath + pathu).c_str());
|
||||
if (att == INVALID_FILE_ATTRIBUTES)
|
||||
|
@ -710,7 +708,7 @@ void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
} else {
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
ULONG bsxalen, perms = FILE_WRITE_ATTRIBUTES;
|
||||
ULONG perms = FILE_WRITE_ATTRIBUTES;
|
||||
btrfs_set_xattr* bsxa;
|
||||
|
||||
if (xattrname == EA_NTACL)
|
||||
|
@ -723,7 +721,7 @@ void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
if (h == INVALID_HANDLE_VALUE)
|
||||
throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
|
||||
bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length() + xattrdatalen;
|
||||
size_t bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length() + xattrdatalen;
|
||||
bsxa = (btrfs_set_xattr*)malloc(bsxalen);
|
||||
if (!bsxa)
|
||||
throw string_error(IDS_OUT_OF_MEMORY);
|
||||
|
@ -733,7 +731,7 @@ void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
memcpy(bsxa->data, xattrname.c_str(), xattrname.length());
|
||||
memcpy(&bsxa->data[xattrname.length()], xattrdata, xattrdatalen);
|
||||
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, nullptr, 0);
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, (ULONG)bsxalen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bsxa);
|
||||
throw string_error(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
@ -754,7 +752,7 @@ void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* dat
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -769,9 +767,8 @@ void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* dat
|
|||
|
||||
if (xattrname.length() > XATTR_USER.length() && xattrname.substr(0, XATTR_USER.length()) == XATTR_USER && xattrname != EA_DOSATTRIB && xattrname != EA_EA) { // deleting stream
|
||||
ULONG att;
|
||||
wstring streamname;
|
||||
|
||||
utf8_to_utf16(xattrname, streamname);
|
||||
auto streamname = utf8_to_utf16(xattrname);
|
||||
|
||||
streamname = streamname.substr(XATTR_USER.length());
|
||||
|
||||
|
@ -794,7 +791,7 @@ void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* dat
|
|||
} else {
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
ULONG bsxalen, perms = FILE_WRITE_ATTRIBUTES;
|
||||
ULONG perms = FILE_WRITE_ATTRIBUTES;
|
||||
btrfs_set_xattr* bsxa;
|
||||
|
||||
if (xattrname == EA_NTACL)
|
||||
|
@ -807,7 +804,7 @@ void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* dat
|
|||
if (h == INVALID_HANDLE_VALUE)
|
||||
throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
|
||||
bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length();
|
||||
size_t bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length();
|
||||
bsxa = (btrfs_set_xattr*)malloc(bsxalen);
|
||||
if (!bsxa)
|
||||
throw string_error(IDS_OUT_OF_MEMORY);
|
||||
|
@ -816,7 +813,7 @@ void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* dat
|
|||
bsxa->valuelen = 0;
|
||||
memcpy(bsxa->data, xattrname.c_str(), xattrname.length());
|
||||
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, nullptr, 0);
|
||||
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, (ULONG)bsxalen, nullptr, 0);
|
||||
if (!NT_SUCCESS(Status)) {
|
||||
free(bsxa);
|
||||
throw string_error(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str());
|
||||
|
@ -833,6 +830,8 @@ void BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
wstring pathu;
|
||||
HANDLE h;
|
||||
LARGE_INTEGER offli;
|
||||
NTSTATUS Status;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
{
|
||||
char* path;
|
||||
|
@ -841,7 +840,7 @@ void BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_OFFSET, (void**)&offset, &offsetlen))
|
||||
|
@ -884,8 +883,9 @@ void BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
|
||||
fbi.LastWriteTime.QuadPart = -1;
|
||||
|
||||
if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
|
||||
throw string_error(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||
Status = NtSetInformationFile(h, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
} else
|
||||
h = lastwritefile;
|
||||
|
||||
|
@ -930,7 +930,7 @@ void BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_UUID, (void**)&cloneuuid, &cloneuuidlen))
|
||||
|
@ -952,7 +952,7 @@ void BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_PATH, (void**)&clonepath, &clonepathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_path");
|
||||
|
||||
utf8_to_utf16(string(clonepath, clonepathlen), clonepathu);
|
||||
clonepathu = utf8_to_utf16(string(clonepath, clonepathlen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_OFFSET, (void**)&cloneoffset, &cloneoffsetlen))
|
||||
|
@ -1047,7 +1047,7 @@ void BtrfsRecv::cmd_truncate(HWND hwnd, btrfs_send_command* cmd, uint8_t* data)
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_SIZE, (void**)&size, &sizelen))
|
||||
|
@ -1103,7 +1103,7 @@ void BtrfsRecv::cmd_chmod(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen))
|
||||
|
@ -1141,7 +1141,7 @@ void BtrfsRecv::cmd_chown(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES | WRITE_OWNER | WRITE_DAC, 0, nullptr, OPEN_EXISTING,
|
||||
|
@ -1187,6 +1187,8 @@ void BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
FILE_BASIC_INFO fbi;
|
||||
BTRFS_TIME* time;
|
||||
ULONG timelen;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
|
||||
{
|
||||
char* path;
|
||||
|
@ -1195,7 +1197,7 @@ void BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen))
|
||||
throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path");
|
||||
|
||||
utf8_to_utf16(string(path, pathlen), pathu);
|
||||
pathu = utf8_to_utf16(string(path, pathlen));
|
||||
}
|
||||
|
||||
h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES, 0, nullptr, OPEN_EXISTING,
|
||||
|
@ -1217,8 +1219,9 @@ void BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) {
|
|||
if (find_tlv(data, cmd->length, BTRFS_SEND_TLV_CTIME, (void**)&time, &timelen) && timelen >= sizeof(BTRFS_TIME))
|
||||
fbi.ChangeTime.QuadPart = unix_time_to_win(time);
|
||||
|
||||
if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
|
||||
throw string_error(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||
Status = NtSetInformationFile(h, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
static void delete_directory(const wstring& dir) {
|
||||
|
@ -1496,9 +1499,7 @@ DWORD BtrfsRecv::recv_thread() {
|
|||
} while (pos < (uint64_t)size.QuadPart);
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
wstring msg;
|
||||
|
||||
utf8_to_utf16(e.what(), msg);
|
||||
auto msg = utf8_to_utf16(e.what());
|
||||
|
||||
SetDlgItemTextW(hwnd, IDC_RECV_MSG, msg.c_str());
|
||||
|
||||
|
@ -1552,9 +1553,7 @@ INT_PTR CALLBACK BtrfsRecv::RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM
|
|||
if (!thread)
|
||||
throw string_error(IDS_RECV_CREATETHREAD_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||
} catch (const exception& e) {
|
||||
wstring msg;
|
||||
|
||||
utf8_to_utf16(e.what(), msg);
|
||||
auto msg = utf8_to_utf16(e.what());
|
||||
|
||||
SetDlgItemTextW(hwnd, IDC_RECV_MSG, msg.c_str());
|
||||
|
||||
|
|
14
dll/shellext/shellbtrfs/resource.h
Normal file → Executable file
14
dll/shellext/shellbtrfs/resource.h
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
|||
//{{NO_DEPENDENCIES}}
|
||||
//{{NO_DEPENDENCIES}}
|
||||
// Microsoft Visual C++ generated include file.
|
||||
// Used by shellbtrfs.rc
|
||||
//
|
||||
|
@ -92,6 +92,7 @@
|
|||
#define IDS_PARTITION 174
|
||||
#define IDS_WHOLE_DISK 175
|
||||
#define IDS_CANNOT_REMOVE_RAID 176
|
||||
#define IDD_DRIVE_LETTER 176
|
||||
#define IDS_REMOVE_DEVICE_CONFIRMATION 177
|
||||
#define IDS_CONFIRMATION_TITLE 178
|
||||
#define IDS_ADD_DEVICE_CONFIRMATION 179
|
||||
|
@ -133,7 +134,6 @@
|
|||
#define IDS_OUT_OF_MEMORY 215
|
||||
#define IDS_RECV_UNKNOWN_COMMAND 216
|
||||
#define IDS_RECV_CANT_OPEN_PATH 217
|
||||
#define IDS_RECV_RTLUTF8TOUNICODEN_FAILED 218
|
||||
#define IDS_RECV_CREATE_SUBVOL_FAILED 219
|
||||
#define IDS_RECV_MISSING_PARAM 220
|
||||
#define IDS_RECV_SHORT_PARAM 221
|
||||
|
@ -145,7 +145,6 @@
|
|||
#define IDS_RECV_CREATEHARDLINK_FAILED 227
|
||||
#define IDS_RECV_SETENDOFFILE_FAILED 228
|
||||
#define IDS_RECV_CANT_CREATE_FILE 229
|
||||
#define IDS_RECV_SETFILEINFO_FAILED 230
|
||||
#define IDS_RECV_SETINODEINFO_FAILED 231
|
||||
#define IDS_RECV_SUCCESS 232
|
||||
#define IDS_RECV_BUTTON_OK 233
|
||||
|
@ -197,11 +196,9 @@
|
|||
#define IDS_BALANCE_COMPLETE_SHRINK 279
|
||||
#define IDS_BALANCE_FAILED_SHRINK 280
|
||||
#define IDS_COMPRESS_ZSTD 281
|
||||
#define IDS_RECV_RTLUNICODETOUTF8N_FAILED 282
|
||||
#define IDS_REGCREATEKEY_FAILED 283
|
||||
#define IDS_REGSETVALUEEX_FAILED 284
|
||||
#define IDS_REGCLOSEKEY_FAILED 285
|
||||
#define IDS_REGDELETETREE_FAILED 286
|
||||
#define IDS_CANT_REFLINK_DIFFERENT_FS 287
|
||||
#define IDS_INITCOMMONCONTROLSEX_FAILED 288
|
||||
#define IDS_CANT_OPEN_MOUNTMGR 289
|
||||
|
@ -240,6 +237,7 @@
|
|||
#define IDC_SIZE_ZSTD 1023
|
||||
#define IDC_COMPRESSION_RATIO 1023
|
||||
#define IDC_PROFILES 1024
|
||||
#define IDC_FRAGMENTATION 1024
|
||||
#define IDC_PROFILES_SINGLE 1025
|
||||
#define IDC_PROFILES_DUP 1026
|
||||
#define IDC_VOL_DEVICES 1026
|
||||
|
@ -332,14 +330,16 @@
|
|||
#define IDC_RESIZE_CURSIZE 1071
|
||||
#define IDC_RESIZE_SLIDER 1072
|
||||
#define IDC_RESIZE_NEWSIZE 1073
|
||||
#define IDC_VOL_CHANGE_DRIVE_LETTER 1073
|
||||
#define IDC_DRIVE_LETTER_COMBO 1074
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 175
|
||||
#define _APS_NEXT_RESOURCE_VALUE 178
|
||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||
#define _APS_NEXT_CONTROL_VALUE 1073
|
||||
#define _APS_NEXT_CONTROL_VALUE 1075
|
||||
#define _APS_NEXT_SYMED_VALUE 101
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,7 @@ DWORD BtrfsSend::Thread() {
|
|||
btrfs_send_subvol* bss;
|
||||
btrfs_send_header header;
|
||||
btrfs_send_command end;
|
||||
ULONG bss_size, i;
|
||||
ULONG i;
|
||||
|
||||
buf = (char*)malloc(SEND_BUFFER_LEN);
|
||||
|
||||
|
@ -44,7 +44,7 @@ DWORD BtrfsSend::Thread() {
|
|||
throw string_error(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||
|
||||
try {
|
||||
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||
size_t bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||
bss = (btrfs_send_subvol*)malloc(bss_size);
|
||||
memset(bss, 0, bss_size);
|
||||
|
||||
|
@ -64,7 +64,7 @@ DWORD BtrfsSend::Thread() {
|
|||
} else
|
||||
bss->parent = nullptr;
|
||||
|
||||
bss->num_clones = clones.size();
|
||||
bss->num_clones = (ULONG)clones.size();
|
||||
|
||||
for (i = 0; i < bss->num_clones; i++) {
|
||||
HANDLE h;
|
||||
|
@ -86,7 +86,7 @@ DWORD BtrfsSend::Thread() {
|
|||
bss->clones[i] = h;
|
||||
}
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, (ULONG)bss_size, nullptr, 0);
|
||||
|
||||
for (i = 0; i < bss->num_clones; i++) {
|
||||
CloseHandle(bss->clones[i]);
|
||||
|
@ -141,7 +141,7 @@ DWORD BtrfsSend::Thread() {
|
|||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, nullptr, 0, buf, SEND_BUFFER_LEN);
|
||||
|
||||
if (NT_SUCCESS(Status)) {
|
||||
if (!WriteFile(stream, buf, iosb.Information, nullptr, nullptr))
|
||||
if (!WriteFile(stream, buf, (DWORD)iosb.Information, nullptr, nullptr))
|
||||
throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||
}
|
||||
} while (NT_SUCCESS(Status));
|
||||
|
@ -162,11 +162,14 @@ DWORD BtrfsSend::Thread() {
|
|||
|
||||
fdi.DeleteFile = true;
|
||||
|
||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||
Status = NtSetInformationFile(stream, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
|
||||
|
||||
CloseHandle(stream);
|
||||
stream = INVALID_HANDLE_VALUE;
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
|
@ -195,9 +198,7 @@ DWORD BtrfsSend::Thread() {
|
|||
throw;
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
wstring msg;
|
||||
|
||||
utf8_to_utf16(e.what(), msg);
|
||||
auto msg = utf8_to_utf16(e.what());
|
||||
|
||||
SetDlgItemTextW(hwnd, IDC_SEND_STATUS, msg.c_str());
|
||||
return 0;
|
||||
|
@ -232,7 +233,6 @@ static DWORD WINAPI send_thread(LPVOID lpParameter) {
|
|||
void BtrfsSend::StartSend(HWND hwnd) {
|
||||
wstring s;
|
||||
HWND cl;
|
||||
ULONG num_clones;
|
||||
|
||||
if (started)
|
||||
return;
|
||||
|
@ -269,16 +269,13 @@ void BtrfsSend::StartSend(HWND hwnd) {
|
|||
clones.clear();
|
||||
|
||||
cl = GetDlgItem(hwnd, IDC_CLONE_LIST);
|
||||
num_clones = SendMessageW(cl, LB_GETCOUNT, 0, 0);
|
||||
auto num_clones = SendMessageW(cl, LB_GETCOUNT, 0, 0);
|
||||
|
||||
if ((LRESULT)num_clones != LB_ERR) {
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < num_clones; i++) {
|
||||
if (num_clones != LB_ERR) {
|
||||
for (unsigned int i = 0; i < (unsigned int)num_clones; i++) {
|
||||
WCHAR* t;
|
||||
ULONG len;
|
||||
|
||||
len = SendMessageW(cl, LB_GETTEXTLEN, i, 0);
|
||||
auto len = SendMessageW(cl, LB_GETTEXTLEN, i, 0);
|
||||
t = (WCHAR*)malloc((len + 1) * sizeof(WCHAR));
|
||||
|
||||
SendMessageW(cl, LB_GETTEXT, i, (LPARAM)t);
|
||||
|
@ -442,12 +439,18 @@ INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
|||
TerminateThread(thread, 0);
|
||||
|
||||
if (stream != INVALID_HANDLE_VALUE) {
|
||||
NTSTATUS Status;
|
||||
FILE_DISPOSITION_INFO fdi;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
|
||||
fdi.DeleteFile = true;
|
||||
|
||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||
Status = NtSetInformationFile(stream, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
|
||||
|
||||
CloseHandle(stream);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
}
|
||||
|
||||
if (dirh != INVALID_HANDLE_VALUE)
|
||||
|
@ -568,7 +571,7 @@ void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int
|
|||
static void send_subvol(const wstring& subvol, const wstring& file, const wstring& parent, const vector<wstring>& clones) {
|
||||
char* buf;
|
||||
win_handle dirh, stream;
|
||||
ULONG bss_size, i;
|
||||
ULONG i;
|
||||
btrfs_send_subvol* bss;
|
||||
IO_STATUS_BLOCK iosb;
|
||||
NTSTATUS Status;
|
||||
|
@ -587,7 +590,7 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin
|
|||
throw last_error(GetLastError());
|
||||
|
||||
try {
|
||||
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||
size_t bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||
bss = (btrfs_send_subvol*)malloc(bss_size);
|
||||
memset(bss, 0, bss_size);
|
||||
|
||||
|
@ -602,7 +605,7 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin
|
|||
} else
|
||||
bss->parent = nullptr;
|
||||
|
||||
bss->num_clones = clones.size();
|
||||
bss->num_clones = (ULONG)clones.size();
|
||||
|
||||
for (i = 0; i < bss->num_clones; i++) {
|
||||
HANDLE h;
|
||||
|
@ -624,7 +627,7 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin
|
|||
bss->clones[i] = h;
|
||||
}
|
||||
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0);
|
||||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, (ULONG)bss_size, nullptr, 0);
|
||||
|
||||
for (i = 0; i < bss->num_clones; i++) {
|
||||
CloseHandle(bss->clones[i]);
|
||||
|
@ -645,7 +648,7 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin
|
|||
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, nullptr, 0, buf, SEND_BUFFER_LEN);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
WriteFile(stream, buf, iosb.Information, nullptr, nullptr);
|
||||
WriteFile(stream, buf, (DWORD)iosb.Information, nullptr, nullptr);
|
||||
} while (NT_SUCCESS(Status));
|
||||
|
||||
if (Status != STATUS_END_OF_FILE)
|
||||
|
@ -664,7 +667,9 @@ static void send_subvol(const wstring& subvol, const wstring& file, const wstrin
|
|||
|
||||
fdi.DeleteFile = true;
|
||||
|
||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||
Status = NtSetInformationFile(stream, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
throw ntstatus_error(Status);
|
||||
|
||||
throw;
|
||||
}
|
||||
|
|
207
dll/shellext/shellbtrfs/shellbtrfs.rc
Normal file → Executable file
207
dll/shellext/shellbtrfs/shellbtrfs.rc
Normal file → Executable file
|
@ -25,18 +25,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
|
|||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
1 TEXTINCLUDE
|
||||
1 TEXTINCLUDE
|
||||
BEGIN
|
||||
"resource.h\0"
|
||||
END
|
||||
|
||||
2 TEXTINCLUDE
|
||||
2 TEXTINCLUDE
|
||||
BEGIN
|
||||
"#include ""winres.h""\r\n"
|
||||
"\0"
|
||||
END
|
||||
|
||||
3 TEXTINCLUDE
|
||||
3 TEXTINCLUDE
|
||||
BEGIN
|
||||
"\r\n"
|
||||
"\0"
|
||||
|
@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico"
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 1,1,0,0
|
||||
PRODUCTVERSION 1,1,0,0
|
||||
FILEVERSION 1,5,0,0
|
||||
PRODUCTVERSION 1,5,0,0
|
||||
FILEFLAGSMASK 0x17L
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -78,12 +78,12 @@ BEGIN
|
|||
BLOCK "080904b0"
|
||||
BEGIN
|
||||
VALUE "FileDescription", "WinBtrfs shell extension"
|
||||
VALUE "FileVersion", "1.1"
|
||||
VALUE "FileVersion", "1.5"
|
||||
VALUE "InternalName", "btrfs"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18"
|
||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-19"
|
||||
VALUE "OriginalFilename", "shellbtrfs.dll"
|
||||
VALUE "ProductName", "WinBtrfs"
|
||||
VALUE "ProductVersion", "1.1"
|
||||
VALUE "ProductVersion", "1.5"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -98,51 +98,53 @@ END
|
|||
// Dialog
|
||||
//
|
||||
|
||||
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 257
|
||||
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 271
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
|
||||
CAPTION "Inode property sheet"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
||||
BEGIN
|
||||
LTEXT "Subvolume:",IDC_STATIC,14,21,38,8
|
||||
LTEXT "Inode:",IDC_STATIC,14,35,21,8
|
||||
GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,85
|
||||
GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,99
|
||||
LTEXT "Type:",IDC_STATIC,14,49,18,8
|
||||
GROUPBOX "POSIX permissions",IDC_STATIC,7,96,221,102
|
||||
LTEXT "User:",IDC_STATIC,14,111,17,8
|
||||
LTEXT "Group:",IDC_STATIC,14,127,22,8
|
||||
EDITTEXT IDC_UID,94,109,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_GID,94,125,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "User",IDC_STATIC,14,158,15,8
|
||||
LTEXT "Group",IDC_STATIC,14,168,20,8
|
||||
LTEXT "Others",IDC_STATIC,14,182,22,8
|
||||
LTEXT "Read",IDC_STATIC,50,148,17,8
|
||||
LTEXT "Write",IDC_STATIC,89,148,18,8
|
||||
LTEXT "Execute",IDC_STATIC,129,148,30,8
|
||||
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,161,16,10
|
||||
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,172,16,10
|
||||
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,182,16,10
|
||||
CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,161,16,10
|
||||
CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,172,16,10
|
||||
CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,182,16,10
|
||||
CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,161,16,10
|
||||
CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,172,16,10
|
||||
CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,182,16,10
|
||||
GROUPBOX "Flags",IDC_STATIC,7,204,221,48
|
||||
CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,218,86,10
|
||||
GROUPBOX "POSIX permissions",IDC_STATIC,7,110,221,102
|
||||
LTEXT "User:",IDC_STATIC,14,125,17,8
|
||||
LTEXT "Group:",IDC_STATIC,14,141,22,8
|
||||
EDITTEXT IDC_UID,94,123,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_GID,94,139,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||
LTEXT "User",IDC_STATIC,14,172,15,8
|
||||
LTEXT "Group",IDC_STATIC,14,182,20,8
|
||||
LTEXT "Others",IDC_STATIC,14,196,22,8
|
||||
LTEXT "Read",IDC_STATIC,50,162,17,8
|
||||
LTEXT "Write",IDC_STATIC,89,162,18,8
|
||||
LTEXT "Execute",IDC_STATIC,129,162,30,8
|
||||
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,175,16,10
|
||||
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,186,16,10
|
||||
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,196,16,10
|
||||
CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,175,16,10
|
||||
CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,186,16,10
|
||||
CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,196,16,10
|
||||
CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,175,16,10
|
||||
CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,186,16,10
|
||||
CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,196,16,10
|
||||
GROUPBOX "Flags",IDC_STATIC,7,218,221,48
|
||||
CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,232,86,10
|
||||
LTEXT "(blank)",IDC_INODE,78,35,70,8
|
||||
LTEXT "(blank)",IDC_TYPE,78,49,116,8
|
||||
CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,232,46,10
|
||||
CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,246,46,10
|
||||
LTEXT "Size on disk:",IDC_STATIC,14,63,61,8
|
||||
CONTROL "%s (<a>Details</a>)",IDC_SIZE_ON_DISK,"SysLink",WS_TABSTOP,78,63,142,8
|
||||
COMBOBOX IDC_COMPRESS_TYPE,63,231,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,218,80,10
|
||||
COMBOBOX IDC_COMPRESS_TYPE,63,245,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
||||
CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,232,80,10
|
||||
LTEXT "(blank)",IDC_SUBVOL,78,21,70,8
|
||||
PUSHBUTTON "&Open as Admin",IDC_OPEN_ADMIN,151,21,70,14
|
||||
CONTROL "Set UID",IDC_SETUID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,161,40,10
|
||||
CONTROL "Set GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,172,40,10
|
||||
CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,182,34,10
|
||||
CONTROL "Set UID",IDC_SETUID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,175,40,10
|
||||
CONTROL "Set GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,186,40,10
|
||||
CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,196,34,10
|
||||
LTEXT "Compression ratio:",IDC_STATIC,14,77,61,8
|
||||
LTEXT "%1.1f%%",IDC_COMPRESSION_RATIO,78,77,116,8
|
||||
LTEXT "Fragmentation:",IDC_STATIC,14,91,61,8
|
||||
LTEXT "%1.1f%%",IDC_FRAGMENTATION,78,91,116,8
|
||||
END
|
||||
|
||||
IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 98
|
||||
|
@ -163,25 +165,26 @@ BEGIN
|
|||
LTEXT "(blank)",IDC_SIZE_ZSTD,63,59,142,8
|
||||
END
|
||||
|
||||
IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 251
|
||||
IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 273
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
|
||||
CAPTION "s"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
||||
BEGIN
|
||||
PUSHBUTTON "Show &usage...",IDC_VOL_SHOW_USAGE,154,47,67,19
|
||||
PUSHBUTTON "&Balance...",IDC_VOL_BALANCE,154,105,67,19
|
||||
PUSHBUTTON "&Devices...",IDC_VOL_DEVICES,154,162,67,19
|
||||
LTEXT "UUID:",IDC_STATIC,7,15,20,8
|
||||
LTEXT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",IDC_UUID,32,15,294,8
|
||||
GROUPBOX "Usage",IDC_STATIC,7,31,221,53
|
||||
LTEXT "Show detailed information about internal filesystem usage. This is the equivalent to the command ""btrfs fi usage"" on Linux.",IDC_STATIC,14,44,131,33
|
||||
GROUPBOX "Balance",IDC_STATIC,7,87,221,53
|
||||
LTEXT "Balancing reads and rewrites data and metadata. It can be used to consolidate free space, as well as to convert between different RAID types.",IDC_STATIC,15,98,131,39
|
||||
GROUPBOX "Devices",IDC_STATIC,7,146,221,45
|
||||
LTEXT "Allows you to add disks or partitions to this filesystem, or remove those already present.",IDC_STATIC,14,159,131,30
|
||||
GROUPBOX "Scrub",IDC_STATIC,7,199,221,45
|
||||
LTEXT "Scrubbing verifies the data and metadata of a filesystem, and where possible will correct any errors.",IDC_STATIC,15,212,131,27
|
||||
PUSHBUTTON "&Scrub...",IDC_VOL_SCRUB,154,215,67,19
|
||||
PUSHBUTTON "Change drive &letter...",IDC_VOL_CHANGE_DRIVE_LETTER,7,30,101,19
|
||||
PUSHBUTTON "Show &usage...",IDC_VOL_SHOW_USAGE,154,69,67,19
|
||||
PUSHBUTTON "&Balance...",IDC_VOL_BALANCE,154,127,67,19
|
||||
PUSHBUTTON "&Devices...",IDC_VOL_DEVICES,154,184,67,19
|
||||
GROUPBOX "Usage",IDC_STATIC,7,53,221,53
|
||||
LTEXT "Show detailed information about internal filesystem usage. This is the equivalent to the command ""btrfs fi usage"" on Linux.",IDC_STATIC,14,66,131,33
|
||||
GROUPBOX "Balance",IDC_STATIC,7,109,221,53
|
||||
LTEXT "Balancing reads and rewrites data and metadata. It can be used to consolidate free space, as well as to convert between different RAID types.",IDC_STATIC,15,120,131,39
|
||||
GROUPBOX "Devices",IDC_STATIC,7,168,221,45
|
||||
LTEXT "Allows you to add disks or partitions to this filesystem, or remove those already present.",IDC_STATIC,14,181,131,30
|
||||
GROUPBOX "Scrub",IDC_STATIC,7,221,221,45
|
||||
LTEXT "Scrubbing verifies the data and metadata of a filesystem, and where possible will correct any errors.",IDC_STATIC,15,234,131,27
|
||||
PUSHBUTTON "&Scrub...",IDC_VOL_SCRUB,154,237,67,19
|
||||
END
|
||||
|
||||
IDD_VOL_USAGE DIALOGEX 0, 0, 235, 242
|
||||
|
@ -364,6 +367,17 @@ BEGIN
|
|||
LTEXT "New size: %s",IDC_RESIZE_NEWSIZE,18,53,238,8
|
||||
END
|
||||
|
||||
IDD_DRIVE_LETTER DIALOGEX 0, 0, 131, 61
|
||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||
CAPTION "Change drive letter"
|
||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||
BEGIN
|
||||
DEFPUSHBUTTON "OK",IDOK,7,40,50,14
|
||||
PUSHBUTTON "Cancel",IDCANCEL,74,40,50,14
|
||||
COMBOBOX IDC_DRIVE_LETTER_COMBO,64,17,60,30,CBS_DROPDOWN | CBS_SORT | WS_VSCROLL | WS_TABSTOP
|
||||
LTEXT "Drive letter:",IDC_STATIC,15,19,45,8
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -378,7 +392,7 @@ BEGIN
|
|||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 228
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 238
|
||||
BOTTOMMARGIN, 266
|
||||
END
|
||||
|
||||
IDD_SIZE_DETAILS, DIALOG
|
||||
|
@ -394,7 +408,7 @@ BEGIN
|
|||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 228
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 244
|
||||
BOTTOMMARGIN, 266
|
||||
END
|
||||
|
||||
IDD_VOL_USAGE, DIALOG
|
||||
|
@ -476,6 +490,14 @@ BEGIN
|
|||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 126
|
||||
END
|
||||
|
||||
IDD_DRIVE_LETTER, DIALOG
|
||||
BEGIN
|
||||
LEFTMARGIN, 7
|
||||
RIGHTMARGIN, 124
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 54
|
||||
END
|
||||
END
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
|
@ -503,6 +525,16 @@ BEGIN
|
|||
0
|
||||
END
|
||||
|
||||
IDD_VOL_PROP_SHEET AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
IDD_DRIVE_LETTER AFX_DIALOG_LAYOUT
|
||||
BEGIN
|
||||
0
|
||||
END
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
@ -595,9 +627,9 @@ BEGIN
|
|||
IDS_DEVLIST_READONLY_NO "No"
|
||||
IDS_DEVLIST_ALLOC "Allocated"
|
||||
IDS_DEVLIST_ALLOC_PC "%"
|
||||
IDS_BALANCE_RUNNING_REMOVAL
|
||||
IDS_BALANCE_RUNNING_REMOVAL
|
||||
"Currently removing device %llu (%llu out of %llu chunks processed, %1.1f%%)"
|
||||
IDS_BALANCE_PAUSED_REMOVAL
|
||||
IDS_BALANCE_PAUSED_REMOVAL
|
||||
"Removal of device %llu paused (%llu out of %llu chunks processed, %1.1f%%)"
|
||||
IDS_BALANCE_CANCELLED_REMOVAL "Device removal cancelled."
|
||||
IDS_BALANCE_COMPLETE_REMOVAL "Device removal completed successfully."
|
||||
|
@ -608,12 +640,12 @@ END
|
|||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_CANNOT_REMOVE_RAID "The current RAID levels do not allow this device to be removed. You must do a conversion balance before you will be able to proceed."
|
||||
IDS_REMOVE_DEVICE_CONFIRMATION
|
||||
IDS_REMOVE_DEVICE_CONFIRMATION
|
||||
"Are you sure that you want to remove device %s, %s?"
|
||||
IDS_CONFIRMATION_TITLE "Confirmation"
|
||||
IDS_ADD_DEVICE_CONFIRMATION
|
||||
IDS_ADD_DEVICE_CONFIRMATION
|
||||
"Are you sure that you want to add this device?"
|
||||
IDS_ADD_DEVICE_CONFIRMATION_FS
|
||||
IDS_ADD_DEVICE_CONFIRMATION_FS
|
||||
"Are you sure that you want to add this device? It already appears to contain a filesystem (%s)."
|
||||
IDS_BALANCE_FAILED "Balance failed (error %08x, %s)"
|
||||
IDS_BALANCE_FAILED_REMOVAL "Device removal failed (error %08x, %s)"
|
||||
|
@ -624,32 +656,32 @@ BEGIN
|
|||
IDS_SCRUB_FINISHED "Scrub finished."
|
||||
IDS_SCRUB_PAUSED "Scrub paused (%llu out of %llu chunks processed, %1.1f%%)"
|
||||
IDS_SCRUB_MSG_STARTED "Scrub started at %s %s."
|
||||
IDS_SCRUB_MSG_RECOVERABLE_DATA
|
||||
IDS_SCRUB_MSG_RECOVERABLE_DATA
|
||||
"Recovered from data checksum error at %llx on device %llx."
|
||||
IDS_SCRUB_MSG_RECOVERABLE_METADATA
|
||||
IDS_SCRUB_MSG_RECOVERABLE_METADATA
|
||||
"Recovered from metadata checksum error at %llx on device %llx."
|
||||
END
|
||||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_DATA
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_DATA
|
||||
"Unrecoverable data checksum error at %llx on device %llx (%.*s, offset %llx)"
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL
|
||||
"Unrecoverable data checksum error at %llx on device %llx (subvol %llx, %.*s, offset %llx)"
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA
|
||||
"Unrecoverable metadata checksum error at %llx on device %llx (root %llx, level %x)"
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM
|
||||
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM
|
||||
"Unrecoverable metadata checksum error at %llx on device %llx (root %llx, level %x, first item %llx,%x,%llx)"
|
||||
IDS_SCRUB_MSG_FINISHED "Scrub finished at %s %s."
|
||||
IDS_SCRUB_MSG_SUMMARY "Scrubbed %s in %llu seconds (%s/s)."
|
||||
IDS_BALANCE_SCRUB_RUNNING "Cannot start balance while scrub running."
|
||||
IDS_SCRUB_BALANCE_RUNNING "Cannot start scrub while balance running."
|
||||
IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE "Recovered from %llu error(s)."
|
||||
IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE
|
||||
IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE
|
||||
"%llu unrecoverable error(s) found."
|
||||
IDS_SCRUB_FAILED "Scrub failed with error %08x."
|
||||
IDS_LOCK_FAILED "Unable to lock volume: error %08x. Make sure that there are no files open, and that you have closed any Explorer windows."
|
||||
IDS_SCRUB_MSG_RECOVERABLE_PARITY
|
||||
IDS_SCRUB_MSG_RECOVERABLE_PARITY
|
||||
"Recovered from parity error at %llx on device %llx."
|
||||
IDS_COMPRESS_ANY "(any)"
|
||||
IDS_COMPRESS_ZLIB "Zlib"
|
||||
|
@ -668,13 +700,12 @@ BEGIN
|
|||
IDS_OUT_OF_MEMORY "Out of memory."
|
||||
IDS_RECV_UNKNOWN_COMMAND "Unrecognized command %u encountered."
|
||||
IDS_RECV_CANT_OPEN_PATH "Couldn't open path %s (error %u, %s)."
|
||||
IDS_RECV_RTLUTF8TOUNICODEN_FAILED "RtlUTF8ToUnicodeN returned %08x (%s)."
|
||||
IDS_RECV_CREATE_SUBVOL_FAILED
|
||||
IDS_RECV_CREATE_SUBVOL_FAILED
|
||||
"FSCTL_BTRFS_CREATE_SUBVOL returned %08x (%s)."
|
||||
IDS_RECV_MISSING_PARAM "%S: could not find %s parameter."
|
||||
IDS_RECV_SHORT_PARAM "%S: length of parameter %s was %u, expected %u."
|
||||
IDS_RECV_MKNOD_FAILED "FSCTL_BTRFS_MKNOD returned %08x (%s)."
|
||||
IDS_RECV_SET_REPARSE_POINT_FAILED
|
||||
IDS_RECV_SET_REPARSE_POINT_FAILED
|
||||
"FSCTL_SET_REPARSE_POINT returned %08x (%s)."
|
||||
END
|
||||
|
||||
|
@ -683,19 +714,17 @@ BEGIN
|
|||
IDS_RECV_MOVEFILE_FAILED "MoveFile (%s -> %s) failed (error %u, %s)."
|
||||
IDS_RECV_SETFILEPOINTER_FAILED "SetFilePointer failed (error %u, %s)."
|
||||
IDS_RECV_WRITEFILE_FAILED "WriteFile failed (error %u, %s)."
|
||||
IDS_RECV_CREATEHARDLINK_FAILED
|
||||
IDS_RECV_CREATEHARDLINK_FAILED
|
||||
"CreateHardLink (%s -> %s) failed (error %u, %s)."
|
||||
IDS_RECV_SETENDOFFILE_FAILED "SetEndOfFile failed (error %u, %s)."
|
||||
IDS_RECV_CANT_CREATE_FILE "Couldn't create %s (error %u, %s)."
|
||||
IDS_RECV_SETFILEINFO_FAILED
|
||||
"SetFileInformationByHandle failed (error %u, %s)."
|
||||
IDS_RECV_SETINODEINFO_FAILED
|
||||
IDS_RECV_SETINODEINFO_FAILED
|
||||
"FSCTL_BTRFS_SET_INODE_INFO returned %08x (%s)."
|
||||
IDS_RECV_SUCCESS "Received 1 subvolume successfully."
|
||||
IDS_RECV_BUTTON_OK "OK"
|
||||
IDS_RECV_SETFILEATTRIBUTES_FAILED
|
||||
IDS_RECV_SETFILEATTRIBUTES_FAILED
|
||||
"SetFileAttributes failed (error %u, %s)."
|
||||
IDS_RECV_GETFILEATTRIBUTES_FAILED
|
||||
IDS_RECV_GETFILEATTRIBUTES_FAILED
|
||||
"GetFileAttributes failed (error %u, %s)."
|
||||
IDS_RECV_CSUM_ERROR "Checksum error."
|
||||
IDS_RECV_NOT_A_SEND_STREAM "File was not a send stream."
|
||||
|
@ -705,28 +734,28 @@ END
|
|||
|
||||
STRINGTABLE
|
||||
BEGIN
|
||||
IDS_RECV_RECEIVED_SUBVOL_FAILED
|
||||
IDS_RECV_RECEIVED_SUBVOL_FAILED
|
||||
"FSCTL_BTRFS_RECEIVED_SUBVOL returned %08x (%s)."
|
||||
IDS_RECV_SETSECURITYOBJECT_FAILED
|
||||
IDS_RECV_SETSECURITYOBJECT_FAILED
|
||||
"NtSetSecurityObject returned %08x (%s)."
|
||||
IDS_RECV_SETXATTR_FAILED "FSCTL_BTRFS_SET_XATTR returned %08x (%s)."
|
||||
IDS_RECV_CREATETHREAD_FAILED "CreateThread failed (error %u, %s)."
|
||||
IDS_RECV_FILE_TRUNCATED "File was truncated."
|
||||
IDS_RECV_RESERVE_SUBVOL_FAILED
|
||||
IDS_RECV_RESERVE_SUBVOL_FAILED
|
||||
"FSCTL_BTRFS_RESERVE_SUBVOL returned %08x (%s)."
|
||||
IDS_RECV_CANCELLED "Receiving cancelled."
|
||||
IDS_RECV_CANT_FIND_PARENT_SUBVOL "Could not find parent subvolume."
|
||||
IDS_RECV_FIND_SUBVOL_FAILED "FSCTL_BTRFS_FIND_SUBVOL returned %08x (%s)."
|
||||
IDS_RECV_CREATE_SNAPSHOT_FAILED
|
||||
IDS_RECV_CREATE_SNAPSHOT_FAILED
|
||||
"FSCTL_BTRFS_CREATE_SNAPSHOT returned %08x (%s)."
|
||||
IDS_RECV_GETVOLUMEPATHNAME_FAILED
|
||||
IDS_RECV_GETVOLUMEPATHNAME_FAILED
|
||||
"GetVolumePathName failed (error %u, %s)."
|
||||
IDS_RECV_DELETEFILE_FAILED "DeleteFile failed for %s (error %u, %s)."
|
||||
IDS_RECV_REMOVEDIRECTORY_FAILED
|
||||
IDS_RECV_REMOVEDIRECTORY_FAILED
|
||||
"RemoveDirectory failed for %s (error %u, %s)."
|
||||
IDS_RECV_CANT_FIND_CLONE_SUBVOL "Could not find clone subvolume."
|
||||
IDS_RECV_GETFILESIZEEX_FAILED "GetFileSizeEx failed (error %u, %s)."
|
||||
IDS_RECV_DUPLICATE_EXTENTS_FAILED
|
||||
IDS_RECV_DUPLICATE_EXTENTS_FAILED
|
||||
"FSCTL_DUPLICATE_EXTENTS_TO_FILE returned %08x (%s)."
|
||||
END
|
||||
|
||||
|
@ -737,13 +766,13 @@ BEGIN
|
|||
IDS_SEND_SUBVOL_HELP "Exports a subvolume so that it can be recreated on another volume."
|
||||
IDS_SEND_CANT_OPEN_FILE "Error opening file %s (error %u, %s)."
|
||||
IDS_SEND_CANT_OPEN_DIR "Error opening directory %s (error %u, %s)."
|
||||
IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED
|
||||
IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED
|
||||
"FSCTL_BTRFS_SEND_SUBVOL returned error %08x (%s)."
|
||||
IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED
|
||||
IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED
|
||||
"FSCTL_BTRFS_READ_SEND_BUFFER returned error %08x (%s)."
|
||||
IDS_SEND_SUCCESS "Stream written successfully."
|
||||
IDS_SEND_WRITEFILE_FAILED "Writing to file failed (error %u, %s)."
|
||||
IDS_SEND_GET_FILE_INFO_FAILED
|
||||
IDS_SEND_GET_FILE_INFO_FAILED
|
||||
"GetFileInformationByHandle failed (error %u, %s)."
|
||||
IDS_SEND_NOT_READONLY "Subvolume not readonly."
|
||||
IDS_NOT_SUBVOL "Directory was not a subvolume."
|
||||
|
@ -759,20 +788,18 @@ BEGIN
|
|||
IDS_SEND_WRITING "Writing..."
|
||||
IDS_MISSING "(missing)"
|
||||
IDS_RESIZE_SUCCESSFUL "Device %llx successfully resized to %s."
|
||||
IDS_BALANCE_RUNNING_SHRINK
|
||||
IDS_BALANCE_RUNNING_SHRINK
|
||||
"Currently shrinking device %llu (%llu out of %llu chunks processed, %1.1f%%)"
|
||||
IDS_BALANCE_PAUSED_SHRINK
|
||||
IDS_BALANCE_PAUSED_SHRINK
|
||||
"Shrinking of device %llu paused (%llu out of %llu chunks processed, %1.1f%%)"
|
||||
IDS_BALANCE_CANCELLED_SHRINK "Device shrinking cancelled."
|
||||
IDS_BALANCE_COMPLETE_SHRINK "Device successfully shrunk."
|
||||
IDS_BALANCE_FAILED_SHRINK "Device shrinking failed (error %08x, %s)"
|
||||
IDS_COMPRESS_ZSTD "Zstd"
|
||||
IDS_RECV_RTLUNICODETOUTF8N_FAILED "RtlUnicodeToUTF8N returned %08x (%s)."
|
||||
IDS_REGCREATEKEY_FAILED "RegCreateKey returned %08x"
|
||||
IDS_REGSETVALUEEX_FAILED "RegSetValueEx returned %08x"
|
||||
IDS_REGCLOSEKEY_FAILED "RegCloseKey returned %08x"
|
||||
IDS_REGDELETETREE_FAILED "RegDeleteTree returned %08x"
|
||||
IDS_CANT_REFLINK_DIFFERENT_FS
|
||||
IDS_CANT_REFLINK_DIFFERENT_FS
|
||||
"Cannot create a reflink between two different filesystems."
|
||||
END
|
||||
|
||||
|
|
|
@ -21,3 +21,4 @@
|
|||
@ stdcall -private SendSubvolW(ptr ptr wstr long)
|
||||
@ stdcall -private RecvSubvolW(ptr ptr wstr long)
|
||||
@ stdcall -private ResizeDeviceW(ptr ptr wstr long)
|
||||
@ stdcall -private ShowChangeDriveLetterW(ptr ptr wstr long)
|
||||
|
|
72
dll/shellext/shellbtrfs/shellext.h
Normal file → Executable file
72
dll/shellext/shellbtrfs/shellext.h
Normal file → Executable file
|
@ -44,6 +44,10 @@
|
|||
#include <ndk/obfuncs.h>
|
||||
#endif
|
||||
#include <string>
|
||||
#ifdef __REACTOS__
|
||||
#define string_view string
|
||||
#define wstring_view wstring
|
||||
#endif
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#ifndef __REACTOS__
|
||||
|
@ -105,36 +109,55 @@ NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO
|
|||
|
||||
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer,
|
||||
ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
|
||||
#endif
|
||||
|
||||
NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR UnicodeStringDestination, ULONG UnicodeStringMaxWCharCount,
|
||||
PULONG UnicodeStringActualWCharCount, PCCH UTF8StringSource,
|
||||
ULONG UTF8StringByteCount);
|
||||
|
||||
NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF8StringMaxByteCount,
|
||||
PULONG UTF8StringActualByteCount, PCWCH UnicodeStringSource,
|
||||
ULONG UnicodeStringByteCount);
|
||||
|
||||
#ifndef __REACTOS__
|
||||
NTSTATUS WINAPI NtSetEaFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length);
|
||||
|
||||
NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor);
|
||||
|
||||
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
|
||||
NTSTATUS NTAPI NtSetInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass);
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FileBasicInformation (FILE_INFORMATION_CLASS)4
|
||||
#define FileStandardInformation (FILE_INFORMATION_CLASS)5
|
||||
#define FileDispositionInformation (FILE_INFORMATION_CLASS)13
|
||||
#define FileEndOfFileInformation (FILE_INFORMATION_CLASS)20
|
||||
#define FileStreamInformation (FILE_INFORMATION_CLASS)22
|
||||
|
||||
typedef enum _FSINFOCLASS {
|
||||
FileFsVolumeInformation = 1,
|
||||
FileFsLabelInformation,
|
||||
FileFsSizeInformation,
|
||||
FileFsDeviceInformation,
|
||||
FileFsAttributeInformation,
|
||||
FileFsControlInformation,
|
||||
FileFsFullSizeInformation,
|
||||
FileFsObjectIdInformation,
|
||||
FileFsDriverPathInformation,
|
||||
FileFsVolumeFlagsInformation,
|
||||
FileFsSectorSizeInformation,
|
||||
FileFsDataCopyInformation,
|
||||
FileFsMetadataSizeInformation,
|
||||
FileFsFullSizeInformationEx,
|
||||
FileFsMaximumInformation
|
||||
} FS_INFORMATION_CLASS, *PFS_INFORMATION_CLASS;
|
||||
|
||||
typedef struct _FILE_STREAM_INFORMATION {
|
||||
ULONG NextEntryOffset;
|
||||
ULONG StreamNameLength;
|
||||
LARGE_INTEGER StreamSize;
|
||||
LARGE_INTEGER StreamAllocationSize;
|
||||
WCHAR StreamName[1];
|
||||
} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
|
||||
#endif
|
||||
|
||||
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length,
|
||||
FS_INFORMATION_CLASS FsInformationClass);
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
BOOL
|
||||
WINAPI
|
||||
SetFileInformationByHandle(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
|
||||
BOOL
|
||||
WINAPI
|
||||
GetFileInformationByHandleEx(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __REACTOS__
|
||||
typedef struct _REPARSE_DATA_BUFFER {
|
||||
|
@ -358,6 +381,8 @@ public:
|
|||
return msg.c_str();
|
||||
}
|
||||
|
||||
NTSTATUS Status;
|
||||
|
||||
private:
|
||||
string msg;
|
||||
};
|
||||
|
@ -376,7 +401,6 @@ wstring format_message(ULONG last_error);
|
|||
wstring format_ntstatus(NTSTATUS Status);
|
||||
bool load_string(HMODULE module, UINT id, wstring& s);
|
||||
void wstring_sprintf(wstring& s, wstring fmt, ...);
|
||||
void command_line_to_args(LPWSTR cmdline, vector<wstring> args);
|
||||
void utf8_to_utf16(const string& utf8, wstring& utf16);
|
||||
void utf16_to_utf8(const wstring& utf16, string& utf8);
|
||||
void command_line_to_args(LPWSTR cmdline, vector<wstring>& args);
|
||||
wstring utf8_to_utf16(const string_view& utf8);
|
||||
void error_message(HWND hwnd, const char* msg);
|
||||
|
|
0
dll/shellext/shellbtrfs/subvol.ico
Normal file → Executable file
0
dll/shellext/shellbtrfs/subvol.ico
Normal file → Executable file
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 91 KiB |
217
dll/shellext/shellbtrfs/volpropsheet.cpp
Normal file → Executable file
217
dll/shellext/shellbtrfs/volpropsheet.cpp
Normal file → Executable file
|
@ -38,6 +38,15 @@
|
|||
|
||||
#include "volpropsheet.h"
|
||||
#include "resource.h"
|
||||
#ifndef __REACTOS__
|
||||
#include "mountmgr.h"
|
||||
#else
|
||||
#include "mountmgr_local.h"
|
||||
#endif
|
||||
|
||||
#ifndef __REACTOS__
|
||||
static const NTSTATUS STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034;
|
||||
#endif
|
||||
|
||||
HRESULT __stdcall BtrfsVolPropSheet::QueryInterface(REFIID riid, void **ppObj) {
|
||||
if (riid == IID_IUnknown || riid == IID_IShellPropSheetExt) {
|
||||
|
@ -705,7 +714,7 @@ void BtrfsVolPropSheet::RefreshDevList(HWND devlist) {
|
|||
|
||||
RtlZeroMemory(&lvi, sizeof(LVITEMW));
|
||||
lvi.mask = LVIF_TEXT | LVIF_PARAM;
|
||||
lvi.iItem = SendMessageW(devlist, LVM_GETITEMCOUNT, 0, 0);
|
||||
lvi.iItem = (int)SendMessageW(devlist, LVM_GETITEMCOUNT, 0, 0);
|
||||
lvi.lParam = (LPARAM)bd->dev_id;
|
||||
|
||||
s = to_wstring(bd->dev_id);
|
||||
|
@ -1035,19 +1044,18 @@ INT_PTR CALLBACK BtrfsVolPropSheet::DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARA
|
|||
{
|
||||
WCHAR sel[MAX_PATH];
|
||||
HWND devlist;
|
||||
int index;
|
||||
LVITEMW lvi;
|
||||
|
||||
devlist = GetDlgItem(hwndDlg, IDC_DEVLIST);
|
||||
|
||||
index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
auto index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
|
||||
if (index == -1)
|
||||
return true;
|
||||
|
||||
RtlZeroMemory(&lvi, sizeof(LVITEMW));
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = index;
|
||||
lvi.iItem = (int)index;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = sel;
|
||||
lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR);
|
||||
|
@ -1063,19 +1071,18 @@ INT_PTR CALLBACK BtrfsVolPropSheet::DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARA
|
|||
WCHAR modfn[MAX_PATH], sel[MAX_PATH], sel2[MAX_PATH];
|
||||
HWND devlist;
|
||||
SHELLEXECUTEINFOW sei;
|
||||
int index;
|
||||
LVITEMW lvi;
|
||||
|
||||
devlist = GetDlgItem(hwndDlg, IDC_DEVLIST);
|
||||
|
||||
index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
auto index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
|
||||
if (index == -1)
|
||||
return true;
|
||||
|
||||
RtlZeroMemory(&lvi, sizeof(LVITEMW));
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = index;
|
||||
lvi.iItem = (int)index;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = sel;
|
||||
lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR);
|
||||
|
@ -1129,7 +1136,6 @@ INT_PTR CALLBACK BtrfsVolPropSheet::DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARA
|
|||
case IDC_DEVICE_RESIZE:
|
||||
{
|
||||
HWND devlist;
|
||||
int index;
|
||||
LVITEMW lvi;
|
||||
wstring t;
|
||||
WCHAR modfn[MAX_PATH], sel[100];
|
||||
|
@ -1137,14 +1143,14 @@ INT_PTR CALLBACK BtrfsVolPropSheet::DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARA
|
|||
|
||||
devlist = GetDlgItem(hwndDlg, IDC_DEVLIST);
|
||||
|
||||
index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
auto index = SendMessageW(devlist, LVM_GETNEXTITEM, -1, LVNI_SELECTED);
|
||||
|
||||
if (index == -1)
|
||||
return true;
|
||||
|
||||
RtlZeroMemory(&lvi, sizeof(LVITEMW));
|
||||
lvi.mask = LVIF_TEXT;
|
||||
lvi.iItem = index;
|
||||
lvi.iItem = (int)index;
|
||||
lvi.iSubItem = 0;
|
||||
lvi.pszText = sel;
|
||||
lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR);
|
||||
|
@ -1288,6 +1294,36 @@ void BtrfsVolPropSheet::ShowScrub(HWND hwndDlg) {
|
|||
CloseHandle(sei.hProcess);
|
||||
}
|
||||
|
||||
void BtrfsVolPropSheet::ShowChangeDriveLetter(HWND hwndDlg) {
|
||||
wstring t;
|
||||
WCHAR modfn[MAX_PATH];
|
||||
SHELLEXECUTEINFOW sei;
|
||||
|
||||
GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR));
|
||||
|
||||
#ifndef __REACTOS__
|
||||
t = L"\""s + modfn + L"\",ShowChangeDriveLetter "s + fn;
|
||||
#else
|
||||
t = wstring(L"\"") + modfn + wstring(L"\",ShowChangeDriveLetter ") + fn;
|
||||
#endif
|
||||
|
||||
RtlZeroMemory(&sei, sizeof(sei));
|
||||
|
||||
sei.cbSize = sizeof(sei);
|
||||
sei.hwnd = hwndDlg;
|
||||
sei.lpVerb = L"runas";
|
||||
sei.lpFile = L"rundll32.exe";
|
||||
sei.lpParameters = t.c_str();
|
||||
sei.nShow = SW_SHOW;
|
||||
sei.fMask = SEE_MASK_NOCLOSEPROCESS;
|
||||
|
||||
if (!ShellExecuteExW(&sei))
|
||||
throw last_error(GetLastError());
|
||||
|
||||
WaitForSingleObject(sei.hProcess, INFINITE);
|
||||
CloseHandle(sei.hProcess);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
try {
|
||||
switch (uMsg) {
|
||||
|
@ -1331,6 +1367,7 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
|||
SetDlgItemTextW(hwndDlg, IDC_UUID, L"");
|
||||
|
||||
SendMessageW(GetDlgItem(hwndDlg, IDC_VOL_SCRUB), BCM_SETSHIELD, 0, true);
|
||||
SendMessageW(GetDlgItem(hwndDlg, IDC_VOL_CHANGE_DRIVE_LETTER), BCM_SETSHIELD, 0, true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1368,6 +1405,10 @@ static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
|||
case IDC_VOL_SCRUB:
|
||||
bps->ShowScrub(hwndDlg);
|
||||
break;
|
||||
|
||||
case IDC_VOL_CHANGE_DRIVE_LETTER:
|
||||
bps->ShowChangeDriveLetter(hwndDlg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1430,6 +1471,156 @@ HRESULT __stdcall BtrfsVolPropSheet::ReplacePage(UINT uPageID, LPFNADDPROPSHEETP
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void BtrfsChangeDriveLetter::do_change(HWND hwndDlg) {
|
||||
unsigned int sel = (unsigned int)SendDlgItemMessageW(hwndDlg, IDC_DRIVE_LETTER_COMBO, CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (sel >= 0 && sel < letters.size()) {
|
||||
wstring dd;
|
||||
|
||||
if (fn.length() == 3 && fn[1] == L':' && fn[2] == L'\\') {
|
||||
dd = L"\\DosDevices\\?:";
|
||||
|
||||
dd[12] = fn[0];
|
||||
} else
|
||||
#ifndef __REACTOS__
|
||||
throw runtime_error("Volume path was not root of drive.");
|
||||
#else
|
||||
error_message(nullptr, "Volume path was not root of drive.");
|
||||
#endif
|
||||
|
||||
mountmgr mm;
|
||||
wstring dev_name;
|
||||
|
||||
{
|
||||
auto v = mm.query_points(dd);
|
||||
|
||||
if (v.empty())
|
||||
#ifndef __REACTOS__
|
||||
throw runtime_error("Error finding device name.");
|
||||
#else
|
||||
error_message(nullptr, "Error finding device name.");
|
||||
#endif
|
||||
|
||||
dev_name = v[0].device_name;
|
||||
}
|
||||
|
||||
wstring new_dd = L"\\DosDevices\\?:";
|
||||
new_dd[12] = letters[sel];
|
||||
|
||||
mm.delete_points(dd);
|
||||
|
||||
try {
|
||||
mm.create_point(new_dd, dev_name);
|
||||
} catch (...) {
|
||||
// if fails, try to recreate old symlink, so we're not left with no drive letter at all
|
||||
mm.create_point(dd, dev_name);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
EndDialog(hwndDlg, 1);
|
||||
}
|
||||
|
||||
INT_PTR BtrfsChangeDriveLetter::DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
try {
|
||||
switch (uMsg) {
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
HWND cb = GetDlgItem(hwndDlg, IDC_DRIVE_LETTER_COMBO);
|
||||
|
||||
SendMessageW(cb, CB_RESETCONTENT, 0, 0);
|
||||
|
||||
mountmgr mm;
|
||||
wstring drv;
|
||||
|
||||
drv = L"\\DosDevices\\?:";
|
||||
|
||||
for (wchar_t l = 'A'; l <= 'Z'; l++) {
|
||||
bool found = true;
|
||||
|
||||
drv[12] = l;
|
||||
|
||||
try {
|
||||
auto v = mm.query_points(drv);
|
||||
|
||||
if (v.empty())
|
||||
found = false;
|
||||
} catch (const ntstatus_error& ntstatus) {
|
||||
if (ntstatus.Status == STATUS_OBJECT_NAME_NOT_FOUND)
|
||||
found = false;
|
||||
else
|
||||
throw;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
wstring str = L"?:";
|
||||
|
||||
str[0] = l;
|
||||
letters.push_back(l);
|
||||
|
||||
SendMessageW(cb, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (HIWORD(wParam)) {
|
||||
case BN_CLICKED:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDOK:
|
||||
do_change(hwndDlg);
|
||||
return true;
|
||||
|
||||
case IDCANCEL:
|
||||
EndDialog(hwndDlg, 0);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (const exception& e) {
|
||||
error_message(hwndDlg, e.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef __REACTOS__
|
||||
INT_PTR CALLBACK VolPropSheetDlgproc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
BtrfsChangeDriveLetter* bcdl;
|
||||
|
||||
if (uMsg == WM_INITDIALOG) {
|
||||
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam);
|
||||
bcdl = (BtrfsChangeDriveLetter*)lParam;
|
||||
} else
|
||||
bcdl = (BtrfsChangeDriveLetter*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
|
||||
|
||||
return bcdl->DlgProc(hwndDlg, uMsg, wParam, lParam);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BtrfsChangeDriveLetter::show() {
|
||||
#ifndef __REACTOS__
|
||||
DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DRIVE_LETTER), hwnd, [](HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||
BtrfsChangeDriveLetter* bcdl;
|
||||
|
||||
if (uMsg == WM_INITDIALOG) {
|
||||
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam);
|
||||
bcdl = (BtrfsChangeDriveLetter*)lParam;
|
||||
} else
|
||||
bcdl = (BtrfsChangeDriveLetter*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
|
||||
|
||||
return bcdl->DlgProc(hwndDlg, uMsg, wParam, lParam);
|
||||
}, (LPARAM)this);
|
||||
#else
|
||||
DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DRIVE_LETTER), hwnd, VolPropSheetDlgproc, (LPARAM)this);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -1488,6 +1679,12 @@ void CALLBACK ResetStatsW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC
|
|||
}
|
||||
}
|
||||
|
||||
void CALLBACK ShowChangeDriveLetterW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||
BtrfsChangeDriveLetter bcdl(hwnd, lpszCmdLine);
|
||||
|
||||
bcdl.show();
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
17
dll/shellext/shellbtrfs/volpropsheet.h
Normal file → Executable file
17
dll/shellext/shellbtrfs/volpropsheet.h
Normal file → Executable file
|
@ -92,6 +92,7 @@ public:
|
|||
INT_PTR CALLBACK DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
void ShowDevices(HWND hwndDlg);
|
||||
void ShowScrub(HWND hwndDlg);
|
||||
void ShowChangeDriveLetter(HWND hwndDlg);
|
||||
INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
void ShowStats(HWND hwndDlg, uint64_t devid);
|
||||
void ResetStats(HWND hwndDlg);
|
||||
|
@ -110,3 +111,19 @@ private:
|
|||
wstring fn;
|
||||
uint64_t stats_dev;
|
||||
};
|
||||
|
||||
class BtrfsChangeDriveLetter {
|
||||
public:
|
||||
BtrfsChangeDriveLetter(HWND hwnd, const wstring_view& fn) : hwnd(hwnd), fn(fn) {
|
||||
}
|
||||
|
||||
void show();
|
||||
INT_PTR DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||
|
||||
private:
|
||||
void do_change(HWND hwndDlg);
|
||||
|
||||
HWND hwnd;
|
||||
wstring fn;
|
||||
vector<wchar_t> letters;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue