From aed50d7e21469170d18ae219c99cb548ae4d3bc6 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 12 Nov 2019 21:45:49 +0100 Subject: [PATCH] [SHELLBTRFS] Upgrade to 1.5 CORE-16494 --- dll/shellext/shellbtrfs/CMakeLists.txt | 1 + dll/shellext/shellbtrfs/balance.cpp | 8 +- dll/shellext/shellbtrfs/contextmenu.cpp | 169 ++++++----- dll/shellext/shellbtrfs/devices.cpp | 84 ++---- dll/shellext/shellbtrfs/main.cpp | 312 +++++++++------------ dll/shellext/shellbtrfs/mountmgr_local.cpp | 180 ++++++++++++ dll/shellext/shellbtrfs/mountmgr_local.h | 34 +++ dll/shellext/shellbtrfs/propsheet.cpp | 48 +++- dll/shellext/shellbtrfs/propsheet.h | 8 +- dll/shellext/shellbtrfs/recv.cpp | 113 ++++---- dll/shellext/shellbtrfs/resource.h | 14 +- dll/shellext/shellbtrfs/send.cpp | 53 ++-- dll/shellext/shellbtrfs/shellbtrfs.rc | 207 ++++++++------ dll/shellext/shellbtrfs/shellbtrfs.spec | 1 + dll/shellext/shellbtrfs/shellext.h | 72 +++-- dll/shellext/shellbtrfs/subvol.ico | Bin dll/shellext/shellbtrfs/volpropsheet.cpp | 217 +++++++++++++- dll/shellext/shellbtrfs/volpropsheet.h | 17 ++ 18 files changed, 1001 insertions(+), 537 deletions(-) mode change 100644 => 100755 dll/shellext/shellbtrfs/contextmenu.cpp mode change 100644 => 100755 dll/shellext/shellbtrfs/devices.cpp mode change 100644 => 100755 dll/shellext/shellbtrfs/main.cpp create mode 100644 dll/shellext/shellbtrfs/mountmgr_local.cpp create mode 100644 dll/shellext/shellbtrfs/mountmgr_local.h mode change 100644 => 100755 dll/shellext/shellbtrfs/propsheet.cpp mode change 100644 => 100755 dll/shellext/shellbtrfs/resource.h mode change 100644 => 100755 dll/shellext/shellbtrfs/shellbtrfs.rc mode change 100644 => 100755 dll/shellext/shellbtrfs/shellext.h mode change 100644 => 100755 dll/shellext/shellbtrfs/subvol.ico mode change 100644 => 100755 dll/shellext/shellbtrfs/volpropsheet.cpp mode change 100644 => 100755 dll/shellext/shellbtrfs/volpropsheet.h diff --git a/dll/shellext/shellbtrfs/CMakeLists.txt b/dll/shellext/shellbtrfs/CMakeLists.txt index 660699cd43f..7022dc05a56 100644 --- a/dll/shellext/shellbtrfs/CMakeLists.txt +++ b/dll/shellext/shellbtrfs/CMakeLists.txt @@ -18,6 +18,7 @@ list(APPEND SOURCE factory.cpp iconoverlay.cpp main.cpp + mountmgr_local.cpp propsheet.cpp reactos.cpp recv.cpp diff --git a/dll/shellext/shellbtrfs/balance.cpp b/dll/shellext/shellbtrfs/balance.cpp index a442a72c24c..11503112410 100644 --- a/dll/shellext/shellbtrfs/balance.cpp +++ b/dll/shellext/shellbtrfs/balance.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; diff --git a/dll/shellext/shellbtrfs/contextmenu.cpp b/dll/shellext/shellbtrfs/contextmenu.cpp old mode 100644 new mode 100755 index 8fcdf2cc551..3fbca1cb7c2 --- a/dll/shellext/shellbtrfs/contextmenu.cpp +++ b/dll/shellext/shellbtrfs/contextmenu.cpp @@ -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 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(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(reinterpret_cast(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 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(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(reinterpret_cast(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; } diff --git a/dll/shellext/shellbtrfs/devices.cpp b/dll/shellext/shellbtrfs/devices.cpp old mode 100644 new mode 100755 index f2c297b15f6..b17f9b25823 --- a/dll/shellext/shellbtrfs/devices.cpp +++ b/dll/shellext/shellbtrfs/devices.cpp @@ -30,11 +30,13 @@ #ifndef __REACTOS__ #include #include "../btrfs.h" +#include "mountmgr.h" #else #include #include #include #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_list) { +static void find_devices(HWND hwnd, const GUID* guid, const mountmgr& mm, vector& 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 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); diff --git a/dll/shellext/shellbtrfs/main.cpp b/dll/shellext/shellbtrfs/main.cpp old mode 100644 new mode 100755 index ba9c419ff87..d11b81e9f82 --- a/dll/shellext/shellbtrfs/main.cpp +++ b/dll/shellext/shellbtrfs/main.cpp @@ -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 args) { +void command_line_to_args(LPWSTR cmdline, vector& args) { LPWSTR* l; int num_args; @@ -632,6 +669,38 @@ void command_line_to_args(LPWSTR cmdline, vector 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(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(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 diff --git a/dll/shellext/shellbtrfs/mountmgr_local.cpp b/dll/shellext/shellbtrfs/mountmgr_local.cpp new file mode 100644 index 00000000000..2f02984e5b6 --- /dev/null +++ b/dll/shellext/shellbtrfs/mountmgr_local.cpp @@ -0,0 +1,180 @@ +#include "shellext.h" +#ifndef __REACTOS__ +#include "mountmgr.h" +#else +#include "mountmgr_local.h" +#endif +#include + +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 buf(sizeof(MOUNTMGR_CREATE_POINT_INPUT) + ((symlink.length() + device.length()) * sizeof(WCHAR))); + auto mcpi = reinterpret_cast(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 buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR))); + auto mmp = reinterpret_cast(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 buf2(sizeof(MOUNTMGR_MOUNT_POINTS)); + auto mmps = reinterpret_cast(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::query_points(const wstring_view& symlink, const wstring_view& unique_id, const wstring_view& device_name) const { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + vector v; + + vector buf(sizeof(MOUNTMGR_MOUNT_POINT) + ((symlink.length() + unique_id.length() + device_name.length()) * sizeof(WCHAR))); + auto mmp = reinterpret_cast(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 buf2(sizeof(MOUNTMGR_MOUNT_POINTS)); + auto mmps = reinterpret_cast(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(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; +} diff --git a/dll/shellext/shellbtrfs/mountmgr_local.h b/dll/shellext/shellbtrfs/mountmgr_local.h new file mode 100644 index 00000000000..c26566b230d --- /dev/null +++ b/dll/shellext/shellbtrfs/mountmgr_local.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include +#ifndef __REACTOS__ +#include +#else +#define string_view string +#define wstring_view wstring +#endif +#include +#include + +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 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; +}; diff --git a/dll/shellext/shellbtrfs/propsheet.cpp b/dll/shellext/shellbtrfs/propsheet.cpp old mode 100644 new mode 100755 index 153d6484fb4..90ee53b27d2 --- a/dll/shellext/shellbtrfs/propsheet.cpp +++ b/dll/shellext/shellbtrfs/propsheet.cpp @@ -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) diff --git a/dll/shellext/shellbtrfs/propsheet.h b/dll/shellext/shellbtrfs/propsheet.h index 8e4f234f15a..0da0034c4c2 100644 --- a/dll/shellext/shellbtrfs/propsheet.h +++ b/dll/shellext/shellbtrfs/propsheet.h @@ -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 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); diff --git a/dll/shellext/shellbtrfs/recv.cpp b/dll/shellext/shellbtrfs/recv.cpp index 0cdb609aa58..87e337f98d7 100644 --- a/dll/shellext/shellbtrfs/recv.cpp +++ b/dll/shellext/shellbtrfs/recv.cpp @@ -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()); diff --git a/dll/shellext/shellbtrfs/resource.h b/dll/shellext/shellbtrfs/resource.h old mode 100644 new mode 100755 index 793f86cc53b..da6f5bd3627 --- a/dll/shellext/shellbtrfs/resource.h +++ b/dll/shellext/shellbtrfs/resource.h @@ -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 diff --git a/dll/shellext/shellbtrfs/send.cpp b/dll/shellext/shellbtrfs/send.cpp index 2b6a1bf52cf..ac4dbfb6898 100644 --- a/dll/shellext/shellbtrfs/send.cpp +++ b/dll/shellext/shellbtrfs/send.cpp @@ -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& 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; } diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc old mode 100644 new mode 100755 index fed0af890b8..0adfa2c6cf5 --- a/dll/shellext/shellbtrfs/shellbtrfs.rc +++ b/dll/shellext/shellbtrfs/shellbtrfs.rc @@ -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 (Details)",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 diff --git a/dll/shellext/shellbtrfs/shellbtrfs.spec b/dll/shellext/shellbtrfs/shellbtrfs.spec index 38bd22fe9db..4fbc85d5239 100644 --- a/dll/shellext/shellbtrfs/shellbtrfs.spec +++ b/dll/shellext/shellbtrfs/shellbtrfs.spec @@ -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) diff --git a/dll/shellext/shellbtrfs/shellext.h b/dll/shellext/shellbtrfs/shellext.h old mode 100644 new mode 100755 index cb9e605ac5f..af7776cb5a3 --- a/dll/shellext/shellbtrfs/shellext.h +++ b/dll/shellext/shellbtrfs/shellext.h @@ -44,6 +44,10 @@ #include #endif #include +#ifdef __REACTOS__ +#define string_view string +#define wstring_view wstring +#endif #include #include #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 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& args); +wstring utf8_to_utf16(const string_view& utf8); void error_message(HWND hwnd, const char* msg); diff --git a/dll/shellext/shellbtrfs/subvol.ico b/dll/shellext/shellbtrfs/subvol.ico old mode 100644 new mode 100755 diff --git a/dll/shellext/shellbtrfs/volpropsheet.cpp b/dll/shellext/shellbtrfs/volpropsheet.cpp old mode 100644 new mode 100755 index 8189f39625c..9c23456d2b5 --- a/dll/shellext/shellbtrfs/volpropsheet.cpp +++ b/dll/shellext/shellbtrfs/volpropsheet.cpp @@ -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(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 diff --git a/dll/shellext/shellbtrfs/volpropsheet.h b/dll/shellext/shellbtrfs/volpropsheet.h old mode 100644 new mode 100755 index 0497673e064..cce9e6e40a7 --- a/dll/shellext/shellbtrfs/volpropsheet.h +++ b/dll/shellext/shellbtrfs/volpropsheet.h @@ -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 letters; +};