From 7b718d3627d04806da5a11c474be103e2768b913 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 16 Dec 2018 12:04:40 +0100 Subject: [PATCH] [SHELLBTRFS] Upgrade to 1.1 CORE-15452 --- dll/shellext/shellbtrfs/CMakeLists.txt | 4 + dll/shellext/shellbtrfs/balance.cpp | 1398 +++++++------- dll/shellext/shellbtrfs/balance.h | 28 +- dll/shellext/shellbtrfs/contextmenu.cpp | 1733 ++++++++--------- dll/shellext/shellbtrfs/contextmenu.h | 18 +- dll/shellext/shellbtrfs/devices.cpp | 971 +++++----- dll/shellext/shellbtrfs/devices.h | 35 +- dll/shellext/shellbtrfs/factory.cpp | 4 +- dll/shellext/shellbtrfs/iconoverlay.cpp | 24 +- dll/shellext/shellbtrfs/main.cpp | 897 +++++---- dll/shellext/shellbtrfs/propsheet.cpp | 1186 ++++++------ dll/shellext/shellbtrfs/propsheet.h | 80 +- dll/shellext/shellbtrfs/recv.cpp | 2224 +++++++++------------- dll/shellext/shellbtrfs/recv.h | 64 +- dll/shellext/shellbtrfs/resource.h | 15 +- dll/shellext/shellbtrfs/scrub.cpp | 789 ++++---- dll/shellext/shellbtrfs/scrub.h | 14 +- dll/shellext/shellbtrfs/send.cpp | 865 ++++----- dll/shellext/shellbtrfs/send.h | 18 +- dll/shellext/shellbtrfs/shellbtrfs.rc | 180 +- dll/shellext/shellbtrfs/shellext.h | 177 +- dll/shellext/shellbtrfs/volpropsheet.cpp | 1711 ++++++++--------- dll/shellext/shellbtrfs/volpropsheet.h | 24 +- media/doc/README.FSD | 2 +- 24 files changed, 5979 insertions(+), 6482 deletions(-) diff --git a/dll/shellext/shellbtrfs/CMakeLists.txt b/dll/shellext/shellbtrfs/CMakeLists.txt index 6802f6b1088..5b239ca2e1b 100644 --- a/dll/shellext/shellbtrfs/CMakeLists.txt +++ b/dll/shellext/shellbtrfs/CMakeLists.txt @@ -3,6 +3,10 @@ set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL) remove_definitions(-D_WIN32_WINNT=0x502) add_definitions(-D_WIN32_WINNT=0x603) +if(NOT MSVC) + add_compile_flags_language("-std=c++11" "CXX") +endif() + include_directories(${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs) spec2def(shellbtrfs.dll shellbtrfs.spec) diff --git a/dll/shellext/shellbtrfs/balance.cpp b/dll/shellext/shellbtrfs/balance.cpp index edcfecea511..a442a72c24c 100644 --- a/dll/shellext/shellbtrfs/balance.cpp +++ b/dll/shellext/shellbtrfs/balance.cpp @@ -42,22 +42,22 @@ #include #include -static UINT64 convtypes2[] = { BLOCK_FLAG_SINGLE, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID6, BLOCK_FLAG_RAID10 }; +static uint64_t convtypes2[] = { BLOCK_FLAG_SINGLE, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID6, BLOCK_FLAG_RAID10 }; -static WCHAR hex_digit(UINT8 u) { +static WCHAR hex_digit(uint8_t u) { if (u >= 0xa && u <= 0xf) - return u - 0xa + 'a'; + return (uint8_t)(u - 0xa + 'a'); else - return u + '0'; + return (uint8_t)(u + '0'); } static void serialize(void* data, ULONG len, WCHAR* s) { - UINT8* d; + uint8_t* d; - d = (UINT8*)data; + d = (uint8_t*)data; - while (TRUE) { - *s = hex_digit(*d >> 4); s++; + while (true) { + *s = hex_digit((uint8_t)(*d >> 4)); s++; *s = hex_digit(*d & 0xf); s++; d++; @@ -71,15 +71,18 @@ static void serialize(void* data, ULONG len, WCHAR* s) { } void BtrfsBalance::StartBalance(HWND hwndDlg) { - WCHAR t[MAX_PATH + 600], u[600]; + wstring t; + WCHAR modfn[MAX_PATH], u[600]; SHELLEXECUTEINFOW sei; btrfs_start_balance bsb; - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",StartBalance "); - wcscat(t, fn); - wcscat(t, L" "); + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",StartBalance "s + fn + L" "s; +#else + t = wstring(L"\"") + modfn + wstring(L"\",StartBalance ") + fn + wstring(L" "); +#endif RtlCopyMemory(&bsb.opts[0], &data_opts, sizeof(btrfs_balance_opts)); RtlCopyMemory(&bsb.opts[1], &metadata_opts, sizeof(btrfs_balance_opts)); @@ -101,7 +104,8 @@ void BtrfsBalance::StartBalance(HWND hwndDlg) { bsb.opts[2].flags &= ~BTRFS_BALANCE_OPTS_ENABLED; serialize(&bsb, sizeof(btrfs_start_balance), u); - wcscat(t, u); + + t += u; RtlZeroMemory(&sei, sizeof(sei)); @@ -109,44 +113,46 @@ void BtrfsBalance::StartBalance(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); - cancelling = FALSE; - removing = FALSE; - shrinking = FALSE; + cancelling = false; + removing = false; + shrinking = false; balance_status = BTRFS_BALANCE_RUNNING; - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), data_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), metadata_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), system_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), data_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), metadata_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), system_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), false); WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); } void BtrfsBalance::PauseBalance(HWND hwndDlg) { - WCHAR t[MAX_PATH + 100]; + WCHAR modfn[MAX_PATH]; + wstring t; SHELLEXECUTEINFOW sei; - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",PauseBalance "); - wcscat(t, fn); + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",PauseBalance " + fn; +#else + t = wstring(L"\"") + modfn + wstring(L"\",PauseBalance ") + fn; +#endif RtlZeroMemory(&sei, sizeof(sei)); @@ -154,27 +160,29 @@ void BtrfsBalance::PauseBalance(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); } void BtrfsBalance::StopBalance(HWND hwndDlg) { - WCHAR t[MAX_PATH + 100]; + WCHAR modfn[MAX_PATH]; + wstring t; SHELLEXECUTEINFOW sei; - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",StopBalance "); - wcscat(t, fn); + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",StopBalance " + fn; +#else + t = wstring(L"\"") + modfn + wstring(L"\",StopBalance ") + fn; +#endif RtlZeroMemory(&sei, sizeof(sei)); @@ -182,44 +190,37 @@ void BtrfsBalance::StopBalance(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); - cancelling = TRUE; + cancelling = true; WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); } -void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { - HANDLE h; - BOOL balancing = FALSE; - WCHAR s[255], t[255]; +void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, bool first) { + bool balancing = false; + wstring s, t; - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; + { + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb, sizeof(btrfs_query_balance)); + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_BALANCE, nullptr, 0, &bqb, sizeof(btrfs_query_balance)); - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); } if (cancelling) @@ -231,13 +232,13 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { if (first || balance_status != BTRFS_BALANCE_STOPPED) { int resid; - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), false); SendMessageW(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), PBM_SETSTATE, PBST_NORMAL, 0); - EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), true); if (balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) { CheckDlgButton(hwndDlg, IDC_DATA, BST_UNCHECKED); @@ -247,9 +248,9 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { SendMessage(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), PBM_SETPOS, 0, 0); } - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED ? true : false); if (bqb.status & BTRFS_BALANCE_ERROR) { if (removing) @@ -259,15 +260,12 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { else resid = IDS_BALANCE_FAILED; - if (!LoadStringW(module, resid, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, resid, s)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, bqb.error, format_ntstatus(bqb.error).c_str()) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(t, s, bqb.error, format_ntstatus(bqb.error).c_str()); - SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, t); + SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, t.c_str()); } else { if (cancelling) resid = removing ? IDS_BALANCE_CANCELLED_REMOVAL : (shrinking ? IDS_BALANCE_CANCELLED_SHRINK : IDS_BALANCE_CANCELLED); @@ -276,41 +274,39 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { else resid = IDS_NO_BALANCE; - if (!LoadStringW(module, resid, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, resid, s)) + throw last_error(GetLastError()); - SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, s); + SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, s.c_str()); } EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || - IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? TRUE: FALSE); + IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? true: false); balance_status = bqb.status; - cancelling = FALSE; + cancelling = false; } return; } if (first || !(balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED))) { - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM), false); CheckDlgButton(hwndDlg, IDC_DATA, bqb.data_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_METADATA, bqb.metadata_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwndDlg, IDC_SYSTEM, bqb.system_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), bqb.data_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), bqb.metadata_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), bqb.system_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? TRUE : FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), bqb.data_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), bqb.metadata_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), bqb.system_opts.flags & BTRFS_BALANCE_OPTS_ENABLED ? true : false); - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), false); } SendMessageW(GetDlgItem(hwndDlg, IDC_BALANCE_PROGRESS), PBM_SETRANGE32, 0, (LPARAM)bqb.total_chunks); @@ -324,44 +320,35 @@ void BtrfsBalance::RefreshBalanceDlg(HWND hwndDlg, BOOL first) { balance_status = bqb.status; if (bqb.status & BTRFS_BALANCE_REMOVAL) { - if (!LoadStringW(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED_REMOVAL : IDS_BALANCE_RUNNING_REMOVAL, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED_REMOVAL : IDS_BALANCE_RUNNING_REMOVAL, s)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, bqb.data_opts.devid, bqb.total_chunks - bqb.chunks_left, - bqb.total_chunks, (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(t, s, bqb.data_opts.devid, bqb.total_chunks - bqb.chunks_left, bqb.total_chunks, + (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks); - removing = TRUE; - shrinking = FALSE; + removing = true; + shrinking = false; } else if (bqb.status & BTRFS_BALANCE_SHRINKING) { - if (!LoadStringW(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED_SHRINK : IDS_BALANCE_RUNNING_SHRINK, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED_SHRINK : IDS_BALANCE_RUNNING_SHRINK, s)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, bqb.data_opts.devid, bqb.total_chunks - bqb.chunks_left, - bqb.total_chunks, (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(t, s, bqb.data_opts.devid, bqb.total_chunks - bqb.chunks_left, bqb.total_chunks, + (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks); - removing = FALSE; - shrinking = TRUE; + removing = false; + shrinking = true; } else { - if (!LoadStringW(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED : IDS_BALANCE_RUNNING, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, balance_status & BTRFS_BALANCE_PAUSED ? IDS_BALANCE_PAUSED : IDS_BALANCE_RUNNING, s)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, bqb.total_chunks - bqb.chunks_left, - bqb.total_chunks, (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(t, s, bqb.total_chunks - bqb.chunks_left, bqb.total_chunks, + (float)(bqb.total_chunks - bqb.chunks_left) * 100.0f / (float)bqb.total_chunks); - removing = FALSE; - shrinking = FALSE; + removing = false; + shrinking = false; } - SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, t); + SetDlgItemTextW(hwndDlg, IDC_BALANCE_STATUS, t.c_str()); } void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { @@ -411,7 +398,7 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { btrfs_device* bd = devices; int i = 0; - while (TRUE) { + while (true) { if (i == sel) { opts->devid = bd->dev_id; break; @@ -420,7 +407,7 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { i++; if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } @@ -441,10 +428,8 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { GetWindowTextW(GetDlgItem(hwndDlg, IDC_DRANGE_END), s, sizeof(s) / sizeof(WCHAR)); opts->drange_end = _wtoi64(s); - if (opts->drange_end < opts->drange_start) { - ShowStringError(hwndDlg, IDS_DRANGE_END_BEFORE_START); - return; - } + if (opts->drange_end < opts->drange_start) + throw string_error(IDS_DRANGE_END_BEFORE_START); } if (IsDlgButtonChecked(hwndDlg, IDC_VRANGE) == BST_CHECKED) { @@ -458,10 +443,8 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { GetWindowTextW(GetDlgItem(hwndDlg, IDC_VRANGE_END), s, sizeof(s) / sizeof(WCHAR)); opts->vrange_end = _wtoi64(s); - if (opts->vrange_end < opts->vrange_start) { - ShowStringError(hwndDlg, IDS_VRANGE_END_BEFORE_START); - return; - } + if (opts->vrange_end < opts->vrange_start) + throw string_error(IDS_VRANGE_END_BEFORE_START); } if (IsDlgButtonChecked(hwndDlg, IDC_LIMIT) == BST_CHECKED) { @@ -475,10 +458,8 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { GetWindowTextW(GetDlgItem(hwndDlg, IDC_LIMIT_END), s, sizeof(s) / sizeof(WCHAR)); opts->limit_end = _wtoi64(s); - if (opts->limit_end < opts->limit_start) { - ShowStringError(hwndDlg, IDS_LIMIT_END_BEFORE_START); - return; - } + if (opts->limit_end < opts->limit_start) + throw string_error(IDS_LIMIT_END_BEFORE_START); } if (IsDlgButtonChecked(hwndDlg, IDC_STRIPES) == BST_CHECKED) { @@ -487,15 +468,13 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { opts->flags |= BTRFS_BALANCE_OPTS_STRIPES; GetWindowTextW(GetDlgItem(hwndDlg, IDC_STRIPES_START), s, sizeof(s) / sizeof(WCHAR)); - opts->stripes_start = _wtoi(s); + opts->stripes_start = (uint8_t)_wtoi(s); GetWindowTextW(GetDlgItem(hwndDlg, IDC_STRIPES_END), s, sizeof(s) / sizeof(WCHAR)); - opts->stripes_end = _wtoi(s); + opts->stripes_end = (uint8_t)_wtoi(s); - if (opts->stripes_end < opts->stripes_start) { - ShowStringError(hwndDlg, IDS_STRIPES_END_BEFORE_START); - return; - } + if (opts->stripes_end < opts->stripes_start) + throw string_error(IDS_STRIPES_END_BEFORE_START); } if (IsDlgButtonChecked(hwndDlg, IDC_USAGE) == BST_CHECKED) { @@ -504,15 +483,13 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { opts->flags |= BTRFS_BALANCE_OPTS_USAGE; GetWindowTextW(GetDlgItem(hwndDlg, IDC_USAGE_START), s, sizeof(s) / sizeof(WCHAR)); - opts->usage_start = _wtoi(s); + opts->usage_start = (uint8_t)_wtoi(s); GetWindowTextW(GetDlgItem(hwndDlg, IDC_USAGE_END), s, sizeof(s) / sizeof(WCHAR)); - opts->usage_end = _wtoi(s); + opts->usage_end = (uint8_t)_wtoi(s); - if (opts->usage_end < opts->usage_start) { - ShowStringError(hwndDlg, IDS_USAGE_END_BEFORE_START); - return; - } + if (opts->usage_end < opts->usage_start) + throw string_error(IDS_USAGE_END_BEFORE_START); } if (IsDlgButtonChecked(hwndDlg, IDC_CONVERT) == BST_CHECKED) { @@ -535,331 +512,323 @@ void BtrfsBalance::SaveBalanceOpts(HWND hwndDlg) { } INT_PTR CALLBACK BtrfsBalance::BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - HWND devcb, convcb; - btrfs_device* bd; - btrfs_balance_opts* opts; - static int convtypes[] = { IDS_SINGLE2, IDS_DUP, IDS_RAID0, IDS_RAID1, IDS_RAID5, IDS_RAID6, IDS_RAID10, 0 }; - int i, num_devices = 0, num_writeable_devices = 0; - WCHAR s[255], u[255]; - BOOL balance_started = balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED); + try { + switch (uMsg) { + case WM_INITDIALOG: + { + HWND devcb, convcb; + btrfs_device* bd; + btrfs_balance_opts* opts; + static int convtypes[] = { IDS_SINGLE2, IDS_DUP, IDS_RAID0, IDS_RAID1, IDS_RAID5, IDS_RAID6, IDS_RAID10, 0 }; + int i, num_devices = 0, num_writeable_devices = 0; + wstring s, u; + bool balance_started = balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED); - switch (opts_type) { - case 1: - opts = balance_started ? &bqb.data_opts : &data_opts; - break; + switch (opts_type) { + case 1: + opts = balance_started ? &bqb.data_opts : &data_opts; + break; - case 2: - opts = balance_started ? &bqb.metadata_opts : &metadata_opts; - break; + case 2: + opts = balance_started ? &bqb.metadata_opts : &metadata_opts; + break; - case 3: - opts = balance_started ? &bqb.system_opts : &system_opts; - break; + case 3: + opts = balance_started ? &bqb.system_opts : &system_opts; + break; - default: - return TRUE; - } + default: + return true; + } - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - devcb = GetDlgItem(hwndDlg, IDC_DEVID_COMBO); + devcb = GetDlgItem(hwndDlg, IDC_DEVID_COMBO); - if (!LoadStringW(module, IDS_DEVID_LIST, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } + if (!load_string(module, IDS_DEVID_LIST, u)) + throw last_error(GetLastError()); - bd = devices; - while (TRUE) { - WCHAR t[255], v[255]; + bd = devices; + while (true) { + wstring t, v; - if (bd->device_number == 0xffffffff) { - memcpy(s, bd->name, bd->namelen); - s[bd->namelen / sizeof(WCHAR)] = 0; - } else if (bd->partition_number == 0) { - if (!LoadStringW(module, IDS_DISK_NUM, v, sizeof(v) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return TRUE; + if (bd->device_number == 0xffffffff) + s = wstring(bd->name, bd->namelen); + else if (bd->partition_number == 0) { + if (!load_string(module, IDS_DISK_NUM, v)) + throw last_error(GetLastError()); + + wstring_sprintf(s, v, bd->device_number); + } else { + if (!load_string(module, IDS_DISK_PART_NUM, v)) + throw last_error(GetLastError()); + + wstring_sprintf(s, v, bd->device_number, bd->partition_number); } - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), v, bd->device_number) == STRSAFE_E_INSUFFICIENT_BUFFER) - break; - } else { - if (!LoadStringW(module, IDS_DISK_PART_NUM, v, sizeof(v) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } + wstring_sprintf(t, u, bd->dev_id, s.c_str()); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), v, bd->device_number, bd->partition_number) == STRSAFE_E_INSUFFICIENT_BUFFER) + SendMessage(devcb, CB_ADDSTRING, 0, (LPARAM)t.c_str()); + + if (opts->devid == bd->dev_id) + SendMessage(devcb, CB_SETCURSEL, num_devices, 0); + + num_devices++; + + if (!bd->readonly) + num_writeable_devices++; + + if (bd->next_entry > 0) + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); + else break; } - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, bd->dev_id, s) == STRSAFE_E_INSUFFICIENT_BUFFER) - break; + convcb = GetDlgItem(hwndDlg, IDC_CONVERT_COMBO); - SendMessage(devcb, CB_ADDSTRING, NULL, (LPARAM)t); + if (num_writeable_devices == 0) + num_writeable_devices = num_devices; - if (opts->devid == bd->dev_id) - SendMessage(devcb, CB_SETCURSEL, num_devices, 0); + i = 0; + while (convtypes[i] != 0) { + if (!load_string(module, convtypes[i], s)) + throw last_error(GetLastError()); - num_devices++; + SendMessage(convcb, CB_ADDSTRING, 0, (LPARAM)s.c_str()); - if (!bd->readonly) - num_writeable_devices++; + if (opts->convert == convtypes2[i]) + SendMessage(convcb, CB_SETCURSEL, i, 0); - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); - else - break; - } + i++; - convcb = GetDlgItem(hwndDlg, IDC_CONVERT_COMBO); - - if (num_writeable_devices == 0) - num_writeable_devices = num_devices; - - i = 0; - while (convtypes[i] != 0) { - if (!LoadStringW(module, convtypes[i], s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - break; + if (num_writeable_devices < 2 && i == 2) + break; + else if (num_writeable_devices < 3 && i == 4) + break; + else if (num_writeable_devices < 4 && i == 5) + break; } - SendMessage(convcb, CB_ADDSTRING, NULL, (LPARAM)s); + // profiles - if (opts->convert == convtypes2[i]) - SendMessage(convcb, CB_SETCURSEL, i, 0); + CheckDlgButton(hwndDlg, IDC_PROFILES, opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_SINGLE, opts->profiles & BLOCK_FLAG_SINGLE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_DUP, opts->profiles & BLOCK_FLAG_DUPLICATE ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_RAID0, opts->profiles & BLOCK_FLAG_RAID0 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_RAID1, opts->profiles & BLOCK_FLAG_RAID1 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_RAID10, opts->profiles & BLOCK_FLAG_RAID10 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_RAID5, opts->profiles & BLOCK_FLAG_RAID5 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PROFILES_RAID6, opts->profiles & BLOCK_FLAG_RAID6 ? BST_CHECKED : BST_UNCHECKED); - i++; + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_SINGLE), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_DUP), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID0), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID1), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID10), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID5), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID6), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES), balance_started ? false : true); - if (num_writeable_devices < 2 && i == 2) - break; - else if (num_writeable_devices < 3 && i == 4) - break; - else if (num_writeable_devices < 4 && i == 5) - break; + // usage + + CheckDlgButton(hwndDlg, IDC_USAGE, opts->flags & BTRFS_BALANCE_OPTS_USAGE ? BST_CHECKED : BST_UNCHECKED); + + s = to_wstring(opts->usage_start); + SetDlgItemTextW(hwndDlg, IDC_USAGE_START, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), UDM_SETRANGE32, 0, 100); + + s = to_wstring(opts->usage_end); + SetDlgItemTextW(hwndDlg, IDC_USAGE_END, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), UDM_SETRANGE32, 0, 100); + + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE), balance_started ? false : true); + + // devid + + if (num_devices < 2 || balance_started) + EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID), false); + + CheckDlgButton(hwndDlg, IDC_DEVID, opts->flags & BTRFS_BALANCE_OPTS_DEVID ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(devcb, (opts->flags & BTRFS_BALANCE_OPTS_DEVID && num_devices >= 2 && !balance_started) ? true : false); + + // drange + + CheckDlgButton(hwndDlg, IDC_DRANGE, opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? BST_CHECKED : BST_UNCHECKED); + + s = to_wstring(opts->drange_start); + SetDlgItemTextW(hwndDlg, IDC_DRANGE_START, s.c_str()); + + s = to_wstring(opts->drange_end); + SetDlgItemTextW(hwndDlg, IDC_DRANGE_END, s.c_str()); + + EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE), balance_started ? false : true); + + // vrange + + CheckDlgButton(hwndDlg, IDC_VRANGE, opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? BST_CHECKED : BST_UNCHECKED); + + s = to_wstring(opts->vrange_start); + SetDlgItemTextW(hwndDlg, IDC_VRANGE_START, s.c_str()); + + s = to_wstring(opts->vrange_end); + SetDlgItemTextW(hwndDlg, IDC_VRANGE_END, s.c_str()); + + EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE), balance_started ? false : true); + + // limit + + CheckDlgButton(hwndDlg, IDC_LIMIT, opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? BST_CHECKED : BST_UNCHECKED); + + s = to_wstring(opts->limit_start); + SetDlgItemTextW(hwndDlg, IDC_LIMIT_START, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff); + + s = to_wstring(opts->limit_end); + SetDlgItemTextW(hwndDlg, IDC_LIMIT_END, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff); + + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), balance_started ? false : true); + + // stripes + + CheckDlgButton(hwndDlg, IDC_STRIPES, opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? BST_CHECKED : BST_UNCHECKED); + + s = to_wstring(opts->stripes_start); + SetDlgItemTextW(hwndDlg, IDC_STRIPES_START, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), UDM_SETRANGE32, 0, 0xffff); + + s = to_wstring(opts->stripes_end); + SetDlgItemTextW(hwndDlg, IDC_STRIPES_END, s.c_str()); + SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), UDM_SETRANGE32, 0, 0xffff); + + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES), balance_started ? false : true); + + // convert + + CheckDlgButton(hwndDlg, IDC_CONVERT, opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_SOFT, opts->flags & BTRFS_BALANCE_OPTS_SOFT ? BST_CHECKED : BST_UNCHECKED); + + EnableWindow(GetDlgItem(hwndDlg, IDC_SOFT), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? true : false); + EnableWindow(convcb, !balance_started && opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? true : false); + EnableWindow(GetDlgItem(hwndDlg, IDC_CONVERT), balance_started ? false : true); + + break; } - // profiles + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + if (balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) + EndDialog(hwndDlg, 0); + else + SaveBalanceOpts(hwndDlg); + return true; - CheckDlgButton(hwndDlg, IDC_PROFILES, opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_SINGLE, opts->profiles & BLOCK_FLAG_SINGLE ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_DUP, opts->profiles & BLOCK_FLAG_DUPLICATE ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_RAID0, opts->profiles & BLOCK_FLAG_RAID0 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_RAID1, opts->profiles & BLOCK_FLAG_RAID1 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_RAID10, opts->profiles & BLOCK_FLAG_RAID10 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_RAID5, opts->profiles & BLOCK_FLAG_RAID5 ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_PROFILES_RAID6, opts->profiles & BLOCK_FLAG_RAID6 ? BST_CHECKED : BST_UNCHECKED); + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_SINGLE), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_DUP), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID0), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID1), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID10), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID5), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID6), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_PROFILES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES), balance_started ? FALSE : TRUE); + case IDC_PROFILES: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_PROFILES) == BST_CHECKED ? true : false; - // usage + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_SINGLE), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_DUP), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID0), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID1), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID10), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID5), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID6), enabled); + break; + } - CheckDlgButton(hwndDlg, IDC_USAGE, opts->flags & BTRFS_BALANCE_OPTS_USAGE ? BST_CHECKED : BST_UNCHECKED); + case IDC_USAGE: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_USAGE) == BST_CHECKED ? true : false; - _itow(opts->usage_start, s, 10); - SetDlgItemTextW(hwndDlg, IDC_USAGE_START, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), UDM_SETRANGE32, 0, 100); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), enabled); + break; + } - _itow(opts->usage_end, s, 10); - SetDlgItemTextW(hwndDlg, IDC_USAGE_END, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), UDM_SETRANGE32, 0, 100); + case IDC_DEVID: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_DEVID) == BST_CHECKED ? true : false; - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_USAGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE), balance_started ? FALSE : TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID_COMBO), enabled); + break; + } - // devid + case IDC_DRANGE: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_DRANGE) == BST_CHECKED ? true : false; - if (num_devices < 2 || balance_started) - EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_START), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_END), enabled); + break; + } - CheckDlgButton(hwndDlg, IDC_DEVID, opts->flags & BTRFS_BALANCE_OPTS_DEVID ? BST_CHECKED : BST_UNCHECKED); - EnableWindow(devcb, (opts->flags & BTRFS_BALANCE_OPTS_DEVID && num_devices >= 2 && !balance_started) ? TRUE : FALSE); + case IDC_VRANGE: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_VRANGE) == BST_CHECKED ? true : false; - // drange + EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_START), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_END), enabled); + break; + } - CheckDlgButton(hwndDlg, IDC_DRANGE, opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? BST_CHECKED : BST_UNCHECKED); + case IDC_LIMIT: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_LIMIT) == BST_CHECKED ? true : false; - _itow(opts->drange_start, s, 10); - SetDlgItemTextW(hwndDlg, IDC_DRANGE_START, s); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), enabled); + break; + } - _itow(opts->drange_end, s, 10); - SetDlgItemTextW(hwndDlg, IDC_DRANGE_END, s); + case IDC_STRIPES: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_STRIPES) == BST_CHECKED ? true : false; - EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE), balance_started ? FALSE : TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), enabled); + break; + } - // vrange - - CheckDlgButton(hwndDlg, IDC_VRANGE, opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? BST_CHECKED : BST_UNCHECKED); - - _itow(opts->vrange_start, s, 10); - SetDlgItemTextW(hwndDlg, IDC_VRANGE_START, s); - - _itow(opts->vrange_end, s, 10); - SetDlgItemTextW(hwndDlg, IDC_VRANGE_END, s); - - EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE), balance_started ? FALSE : TRUE); - - // limit - - CheckDlgButton(hwndDlg, IDC_LIMIT, opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? BST_CHECKED : BST_UNCHECKED); - - _itow(opts->limit_start, s, 10); - SetDlgItemTextW(hwndDlg, IDC_LIMIT_START, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff); - - _itow(opts->limit_end, s, 10); - SetDlgItemTextW(hwndDlg, IDC_LIMIT_END, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff); - - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT), balance_started ? FALSE : TRUE); - - // stripes - - CheckDlgButton(hwndDlg, IDC_STRIPES, opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? BST_CHECKED : BST_UNCHECKED); - - _itow(opts->stripes_start, s, 10); - SetDlgItemTextW(hwndDlg, IDC_STRIPES_START, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), UDM_SETRANGE32, 0, 0xffff); - - _itow(opts->stripes_end, s, 10); - SetDlgItemTextW(hwndDlg, IDC_STRIPES_END, s); - SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), UDM_SETRANGE32, 0, 0xffff); - - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES), balance_started ? FALSE : TRUE); - - // convert - - CheckDlgButton(hwndDlg, IDC_CONVERT, opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? BST_CHECKED : BST_UNCHECKED); - CheckDlgButton(hwndDlg, IDC_SOFT, opts->flags & BTRFS_BALANCE_OPTS_SOFT ? BST_CHECKED : BST_UNCHECKED); - - EnableWindow(GetDlgItem(hwndDlg, IDC_SOFT), !balance_started && opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? TRUE : FALSE); - EnableWindow(convcb, !balance_started && opts->flags & BTRFS_BALANCE_OPTS_CONVERT ? TRUE : FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CONVERT), balance_started ? FALSE : TRUE); + case IDC_CONVERT: { + bool enabled = IsDlgButtonChecked(hwndDlg, IDC_CONVERT) == BST_CHECKED ? true : false; + EnableWindow(GetDlgItem(hwndDlg, IDC_CONVERT_COMBO), enabled); + EnableWindow(GetDlgItem(hwndDlg, IDC_SOFT), enabled); + break; + } + } + break; + } break; } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - if (balance_status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) - EndDialog(hwndDlg, 0); - else - SaveBalanceOpts(hwndDlg); - return TRUE; - - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; - - case IDC_PROFILES: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_PROFILES) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_SINGLE), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_DUP), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID0), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID1), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID10), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID5), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_PROFILES_RAID6), enabled); - break; - } - - case IDC_USAGE: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_USAGE) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), enabled); - break; - } - - case IDC_DEVID: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_DEVID) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID_COMBO), enabled); - break; - } - - case IDC_DRANGE: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_DRANGE) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_START), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_END), enabled); - break; - } - - case IDC_VRANGE: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_VRANGE) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_START), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_END), enabled); - break; - } - - case IDC_LIMIT: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_LIMIT) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), enabled); - break; - } - - case IDC_STRIPES: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_STRIPES) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), enabled); - break; - } - - case IDC_CONVERT: { - BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_CONVERT) == BST_CHECKED ? TRUE : FALSE; - - EnableWindow(GetDlgItem(hwndDlg, IDC_CONVERT_COMBO), enabled); - EnableWindow(GetDlgItem(hwndDlg, IDC_SOFT), enabled); - break; - } - } - break; - } - break; + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -875,112 +844,116 @@ static INT_PTR CALLBACK stub_BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM if (bb) return bb->BalanceOptsDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } -void BtrfsBalance::ShowBalanceOptions(HWND hwndDlg, UINT8 type) { +void BtrfsBalance::ShowBalanceOptions(HWND hwndDlg, uint8_t type) { opts_type = type; DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_BALANCE_OPTIONS), hwndDlg, stub_BalanceOptsDlgProc, (LPARAM)this); } INT_PTR CALLBACK BtrfsBalance::BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + try { + switch (uMsg) { + case WM_INITDIALOG: + { + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - RtlZeroMemory(&data_opts, sizeof(btrfs_balance_opts)); - RtlZeroMemory(&metadata_opts, sizeof(btrfs_balance_opts)); - RtlZeroMemory(&system_opts, sizeof(btrfs_balance_opts)); + RtlZeroMemory(&data_opts, sizeof(btrfs_balance_opts)); + RtlZeroMemory(&metadata_opts, sizeof(btrfs_balance_opts)); + RtlZeroMemory(&system_opts, sizeof(btrfs_balance_opts)); - removing = called_from_RemoveDevice; - shrinking = called_from_ShrinkDevice; - balance_status = (removing || shrinking) ? BTRFS_BALANCE_RUNNING : BTRFS_BALANCE_STOPPED; - cancelling = FALSE; - RefreshBalanceDlg(hwndDlg, TRUE); + removing = called_from_RemoveDevice; + shrinking = called_from_ShrinkDevice; + balance_status = (removing || shrinking) ? BTRFS_BALANCE_RUNNING : BTRFS_BALANCE_STOPPED; + cancelling = false; + RefreshBalanceDlg(hwndDlg, true); - if (readonly) { - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), FALSE); - } + if (readonly) { + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), false); + } - SendMessageW(GetDlgItem(hwndDlg, IDC_START_BALANCE), BCM_SETSHIELD, 0, TRUE); - SendMessageW(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), BCM_SETSHIELD, 0, TRUE); - SendMessageW(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), BCM_SETSHIELD, 0, TRUE); + SendMessageW(GetDlgItem(hwndDlg, IDC_START_BALANCE), BCM_SETSHIELD, 0, true); + SendMessageW(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), BCM_SETSHIELD, 0, true); + SendMessageW(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), BCM_SETSHIELD, 0, true); - SetTimer(hwndDlg, 1, 1000, NULL); + SetTimer(hwndDlg, 1, 1000, nullptr); - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - KillTimer(hwndDlg, 1); - EndDialog(hwndDlg, 0); - return TRUE; - - case IDC_DATA: - EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED ? TRUE : FALSE); - - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || - IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? TRUE: FALSE); - return TRUE; - - case IDC_METADATA: - EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED ? TRUE : FALSE); - - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || - IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? TRUE: FALSE); - return TRUE; - - case IDC_SYSTEM: - EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED ? TRUE : FALSE); - - EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || - IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? TRUE: FALSE); - return TRUE; - - case IDC_DATA_OPTIONS: - ShowBalanceOptions(hwndDlg, 1); - return TRUE; - - case IDC_METADATA_OPTIONS: - ShowBalanceOptions(hwndDlg, 2); - return TRUE; - - case IDC_SYSTEM_OPTIONS: - ShowBalanceOptions(hwndDlg, 3); - return TRUE; - - case IDC_START_BALANCE: - StartBalance(hwndDlg); - return TRUE; - - case IDC_PAUSE_BALANCE: - PauseBalance(hwndDlg); - RefreshBalanceDlg(hwndDlg, FALSE); - return TRUE; - - case IDC_CANCEL_BALANCE: - StopBalance(hwndDlg); - RefreshBalanceDlg(hwndDlg, FALSE); - return TRUE; - } break; } - break; - case WM_TIMER: - RefreshBalanceDlg(hwndDlg, FALSE); + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + KillTimer(hwndDlg, 1); + EndDialog(hwndDlg, 0); + return true; + + case IDC_DATA: + EnableWindow(GetDlgItem(hwndDlg, IDC_DATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED ? true : false); + + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || + IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? true: false); + return true; + + case IDC_METADATA: + EnableWindow(GetDlgItem(hwndDlg, IDC_METADATA_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED ? true : false); + + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || + IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? true: false); + return true; + + case IDC_SYSTEM: + EnableWindow(GetDlgItem(hwndDlg, IDC_SYSTEM_OPTIONS), IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED ? true : false); + + EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), !readonly && (IsDlgButtonChecked(hwndDlg, IDC_DATA) == BST_CHECKED || + IsDlgButtonChecked(hwndDlg, IDC_METADATA) == BST_CHECKED || IsDlgButtonChecked(hwndDlg, IDC_SYSTEM) == BST_CHECKED) ? true: false); + return true; + + case IDC_DATA_OPTIONS: + ShowBalanceOptions(hwndDlg, 1); + return true; + + case IDC_METADATA_OPTIONS: + ShowBalanceOptions(hwndDlg, 2); + return true; + + case IDC_SYSTEM_OPTIONS: + ShowBalanceOptions(hwndDlg, 3); + return true; + + case IDC_START_BALANCE: + StartBalance(hwndDlg); + return true; + + case IDC_PAUSE_BALANCE: + PauseBalance(hwndDlg); + RefreshBalanceDlg(hwndDlg, false); + return true; + + case IDC_CANCEL_BALANCE: + StopBalance(hwndDlg); + RefreshBalanceDlg(hwndDlg, false); + return true; + } + break; + } break; + + case WM_TIMER: + RefreshBalanceDlg(hwndDlg, false); + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -996,70 +969,64 @@ static INT_PTR CALLBACK stub_BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPar if (bb) return bb->BalanceDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } void BtrfsBalance::ShowBalance(HWND hwndDlg) { - HANDLE h; btrfs_device* bd; if (devices) { free(devices); - devices = NULL; + devices = nullptr; } - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + { + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - ULONG devsize, i; + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + ULONG devsize, i; - i = 0; - devsize = 1024; + i = 0; + devsize = 1024; - devices = (btrfs_device*)malloc(devsize); + devices = (btrfs_device*)malloc(devsize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); - if (Status == STATUS_BUFFER_OVERFLOW) { - if (i < 8) { - devsize += 1024; + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); + if (Status == STATUS_BUFFER_OVERFLOW) { + if (i < 8) { + devsize += 1024; - free(devices); - devices = (btrfs_device*)malloc(devsize); + free(devices); + devices = (btrfs_device*)malloc(devsize); - i++; + i++; + } else + return; } else - return; - } else - break; - } + break; + } - if (!NT_SUCCESS(Status)) { - CloseHandle(h); - ShowNtStatusError(hwndDlg, Status); - return; - } - - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); } - readonly = TRUE; + readonly = true; bd = devices; - while (TRUE) { + while (true) { if (!bd->readonly) { - readonly = FALSE; + readonly = false; break; } if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } @@ -1067,22 +1034,22 @@ void BtrfsBalance::ShowBalance(HWND hwndDlg) { DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_BALANCE), hwndDlg, stub_BalanceDlgProc, (LPARAM)this); } -static UINT8 from_hex_digit(WCHAR c) { +static uint8_t from_hex_digit(WCHAR c) { if (c >= 'a' && c <= 'f') - return c - 'a' + 0xa; + return (uint8_t)(c - 'a' + 0xa); else if (c >= 'A' && c <= 'F') - return c - 'A' + 0xa; + return (uint8_t)(c - 'A' + 0xa); else - return c - '0'; + return (uint8_t)(c - '0'); } static void unserialize(void* data, ULONG len, WCHAR* s) { - UINT8* d; + uint8_t* d; - d = (UINT8*)data; + d = (uint8_t*)data; while (s[0] != 0 && s[1] != 0 && len > 0) { - *d = from_hex_digit(s[0]) << 4 | from_hex_digit(s[1]); + *d = (uint8_t)(from_hex_digit(s[0]) << 4) | from_hex_digit(s[1]); s += 2; d++; @@ -1095,205 +1062,156 @@ extern "C" { #endif void CALLBACK StartBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - WCHAR *s, *vol, *block; - HANDLE h, token; - btrfs_start_balance bsb; - TOKEN_PRIVILEGES tp; - LUID luid; + try { + WCHAR *s, *vol, *block; + win_handle h, token; + btrfs_start_balance bsb; + TOKEN_PRIVILEGES tp; + LUID luid; - s = wcsstr(lpszCmdLine, L" "); - if (!s) - return; + s = wcsstr(lpszCmdLine, L" "); + if (!s) + return; - s[0] = 0; + s[0] = 0; - vol = lpszCmdLine; - block = &s[1]; + vol = lpszCmdLine; + block = &s[1]; - RtlZeroMemory(&bsb, sizeof(btrfs_start_balance)); - unserialize(&bsb, sizeof(btrfs_start_balance), block); + RtlZeroMemory(&bsb, sizeof(btrfs_start_balance)); + unserialize(&bsb, sizeof(btrfs_start_balance), block); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; - } + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); - h = CreateFileW(vol, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(vol, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_BALANCE, &bsb, sizeof(btrfs_start_balance), NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_START_BALANCE, &bsb, sizeof(btrfs_start_balance), nullptr, 0); - if (Status == STATUS_DEVICE_NOT_READY) { - btrfs_query_scrub bqs; - NTSTATUS Status2; + if (Status == STATUS_DEVICE_NOT_READY) { + btrfs_query_scrub bqs; + NTSTATUS Status2; - Status2 = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub)); + Status2 = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, &bqs, sizeof(btrfs_query_scrub)); - if ((NT_SUCCESS(Status2) || Status2 == STATUS_BUFFER_OVERFLOW) && bqs.status != BTRFS_SCRUB_STOPPED) { - ShowStringError(hwnd, IDS_BALANCE_SCRUB_RUNNING); - CloseHandle(h); - goto end; + if ((NT_SUCCESS(Status2) || Status2 == STATUS_BUFFER_OVERFLOW) && bqs.status != BTRFS_SCRUB_STOPPED) + throw string_error(IDS_BALANCE_SCRUB_RUNNING); } - } - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(h); - goto end; - } - - CloseHandle(h); - } else { - ShowError(hwnd, GetLastError()); - goto end; + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - -end: - CloseHandle(token); } void CALLBACK PauseBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE h, token; - TOKEN_PRIVILEGES tp; - LUID luid; + try { + win_handle h, token; + TOKEN_PRIVILEGES tp; + LUID luid; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + h = CreateFileW(lpszCmdLine, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + btrfs_query_balance bqb2; + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_BALANCE, nullptr, 0, &bqb2, sizeof(btrfs_query_balance)); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (bqb2.status & BTRFS_BALANCE_PAUSED) + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESUME_BALANCE, nullptr, 0, nullptr, 0); + else if (bqb2.status & BTRFS_BALANCE_RUNNING) + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_PAUSE_BALANCE, nullptr, 0, nullptr, 0); + else + return; + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - h = CreateFileW(lpszCmdLine, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - btrfs_query_balance bqb2; - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb2, sizeof(btrfs_query_balance)); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(h); - goto end; - } - - if (bqb2.status & BTRFS_BALANCE_PAUSED) - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESUME_BALANCE, NULL, 0, NULL, 0); - else if (bqb2.status & BTRFS_BALANCE_RUNNING) - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_PAUSE_BALANCE, NULL, 0, NULL, 0); - else { - CloseHandle(h); - goto end; - } - - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(h); - goto end; - } - - CloseHandle(h); - } else { - ShowError(hwnd, GetLastError()); - goto end; - } - -end: - CloseHandle(token); } void CALLBACK StopBalanceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE h, token; - TOKEN_PRIVILEGES tp; - LUID luid; + try { + win_handle h, token; + TOKEN_PRIVILEGES tp; + LUID luid; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + h = CreateFileW(lpszCmdLine, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + btrfs_query_balance bqb2; + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_BALANCE, nullptr, 0, &bqb2, sizeof(btrfs_query_balance)); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (bqb2.status & BTRFS_BALANCE_PAUSED || bqb2.status & BTRFS_BALANCE_RUNNING) + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_STOP_BALANCE, nullptr, 0, nullptr, 0); + else + return; + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - h = CreateFileW(lpszCmdLine, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - btrfs_query_balance bqb2; - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb2, sizeof(btrfs_query_balance)); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(h); - goto end; - } - - if (bqb2.status & BTRFS_BALANCE_PAUSED || bqb2.status & BTRFS_BALANCE_RUNNING) - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_BALANCE, NULL, 0, NULL, 0); - else { - CloseHandle(h); - goto end; - } - - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(h); - goto end; - } - - CloseHandle(h); - } else { - ShowError(hwnd, GetLastError()); - goto end; - } - -end: - CloseHandle(token); } #ifdef __REACTOS__ diff --git a/dll/shellext/shellbtrfs/balance.h b/dll/shellext/shellbtrfs/balance.h index 0c07de4c2c4..b6235376ea8 100644 --- a/dll/shellext/shellbtrfs/balance.h +++ b/dll/shellext/shellbtrfs/balance.h @@ -26,12 +26,12 @@ class BtrfsBalance { public: - BtrfsBalance(WCHAR* drive, BOOL RemoveDevice = FALSE, BOOL ShrinkDevice = FALSE) { - removing = FALSE; - devices = NULL; + BtrfsBalance(const wstring& drive, bool RemoveDevice = false, bool ShrinkDevice = false) { + removing = false; + devices = nullptr; called_from_RemoveDevice = RemoveDevice; called_from_ShrinkDevice = ShrinkDevice; - wcscpy(fn, drive); + fn = drive; } void ShowBalance(HWND hwndDlg); @@ -39,22 +39,22 @@ public: INT_PTR CALLBACK BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); private: - void ShowBalanceOptions(HWND hwndDlg, UINT8 type); + void ShowBalanceOptions(HWND hwndDlg, uint8_t type); void SaveBalanceOpts(HWND hwndDlg); void StartBalance(HWND hwndDlg); - void RefreshBalanceDlg(HWND hwndDlg, BOOL first); + void RefreshBalanceDlg(HWND hwndDlg, bool first); void PauseBalance(HWND hwndDlg); void StopBalance(HWND hwndDlg); - UINT32 balance_status; + uint32_t balance_status; btrfs_balance_opts data_opts, metadata_opts, system_opts; - UINT8 opts_type; + uint8_t opts_type; btrfs_query_balance bqb; - BOOL cancelling; - BOOL removing; - BOOL shrinking; - WCHAR fn[MAX_PATH]; + bool cancelling; + bool removing; + bool shrinking; + wstring fn; btrfs_device* devices; - BOOL readonly; - BOOL called_from_RemoveDevice, called_from_ShrinkDevice; + bool readonly; + bool called_from_RemoveDevice, called_from_ShrinkDevice; }; diff --git a/dll/shellext/shellbtrfs/contextmenu.cpp b/dll/shellext/shellbtrfs/contextmenu.cpp index a5769be5500..6e51a0f9eeb 100644 --- a/dll/shellext/shellbtrfs/contextmenu.cpp +++ b/dll/shellext/shellbtrfs/contextmenu.cpp @@ -15,9 +15,6 @@ * You should have received a copy of the GNU Lesser General Public Licence * along with WinBtrfs. If not, see . */ -#ifndef __REACTOS__ -#define UNICODE -#endif #include "shellext.h" #ifndef __REACTOS__ #include @@ -35,8 +32,8 @@ #undef DeleteFile #endif #include -#include #include +#include #define NO_SHLWAPI_STRFCNS #include @@ -66,6 +63,8 @@ typedef struct { USHORT Reserved; } reparse_header; +static void path_remove_file(wstring& path); + // FIXME - don't assume subvol's top inode is 0x100 HRESULT __stdcall BtrfsContextMenu::QueryInterface(REFIID riid, void **ppObj) { @@ -79,18 +78,17 @@ HRESULT __stdcall BtrfsContextMenu::QueryInterface(REFIID riid, void **ppObj) { return S_OK; } - *ppObj = NULL; + *ppObj = nullptr; return E_NOINTERFACE; } HRESULT __stdcall BtrfsContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) { - HANDLE h; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; NTSTATUS Status; if (!pidlFolder) { - FORMATETC format = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; UINT num_files, i; WCHAR fn[MAX_PATH]; HDROP hdrop; @@ -103,49 +101,47 @@ HRESULT __stdcall BtrfsContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDa if (FAILED(pdtobj->GetData(&format, &stgm))) return E_INVALIDARG; - stgm_set = TRUE; + stgm_set = true; hdrop = (HDROP)GlobalLock(stgm.hGlobal); if (!hdrop) { ReleaseStgMedium(&stgm); - stgm_set = FALSE; + stgm_set = false; return E_INVALIDARG; } - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); for (i = 0; i < num_files; i++) { if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) { - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + win_handle h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (h != INVALID_HANDLE_VALUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) { - WCHAR parpath[MAX_PATH]; - HANDLE h2; + wstring parpath; - StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn); + { + win_handle h2; - PathRemoveFileSpecW(parpath); + parpath = fn; + path_remove_file(parpath); - h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + h2 = CreateFileW(parpath.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (h2 != INVALID_HANDLE_VALUE) - allow_snapshot = TRUE; + if (h2 != INVALID_HANDLE_VALUE) + allow_snapshot = true; + } - CloseHandle(h2); + ignore = false; + bg = false; - ignore = FALSE; - bg = FALSE; - - CloseHandle(h); GlobalUnlock(hdrop); return S_OK; } - - CloseHandle(h); } } } @@ -155,36 +151,40 @@ HRESULT __stdcall BtrfsContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDa return S_OK; } - if (!SHGetPathFromIDListW(pidlFolder, path)) - return E_FAIL; + { + WCHAR pathbuf[MAX_PATH]; - // check we have permissions to create new subdirectory + if (!SHGetPathFromIDListW(pidlFolder, pathbuf)) + return E_FAIL; - h = CreateFileW(path, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if (h == INVALID_HANDLE_VALUE) - return E_FAIL; - - // check is Btrfs volume - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); - - if (!NT_SUCCESS(Status)) { - CloseHandle(h); - return E_FAIL; + path = pathbuf; } - CloseHandle(h); + { + // check we have permissions to create new subdirectory - ignore = FALSE; - bg = TRUE; + win_handle h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + + if (h == INVALID_HANDLE_VALUE) + return E_FAIL; + + // check is Btrfs volume + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); + + if (!NT_SUCCESS(Status)) + return E_FAIL; + } + + ignore = false; + bg = true; return S_OK; } -static BOOL get_volume_path_parent(const WCHAR* fn, WCHAR* volpath, ULONG volpathlen) { +static bool get_volume_path_parent(const WCHAR* fn, WCHAR* volpath, ULONG volpathlen) { WCHAR *f, *p; - BOOL b; + bool b; f = PathFindFileNameW(fn); @@ -202,53 +202,53 @@ static BOOL get_volume_path_parent(const WCHAR* fn, WCHAR* volpath, ULONG volpat return b; } -static BOOL show_reflink_paste(WCHAR* path) { +static bool show_reflink_paste(const wstring& path) { HDROP hdrop; HANDLE lh; ULONG num_files; WCHAR fn[MAX_PATH], volpath1[255], volpath2[255]; if (!IsClipboardFormatAvailable(CF_HDROP)) - return FALSE; + return false; - if (!GetVolumePathNameW(path, volpath1, sizeof(volpath1) / sizeof(WCHAR))) - return FALSE; + if (!GetVolumePathNameW(path.c_str(), volpath1, sizeof(volpath1) / sizeof(WCHAR))) + return false; - if (!OpenClipboard(NULL)) - return FALSE; + if (!OpenClipboard(nullptr)) + return false; hdrop = (HDROP)GetClipboardData(CF_HDROP); if (!hdrop) { CloseClipboard(); - return FALSE; + return false; } lh = GlobalLock(hdrop); if (!lh) { CloseClipboard(); - return FALSE; + return false; } - num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0); if (num_files == 0) { GlobalUnlock(lh); CloseClipboard(); - return FALSE; + return false; } if (!DragQueryFileW(hdrop, 0, fn, sizeof(fn) / sizeof(WCHAR))) { GlobalUnlock(lh); CloseClipboard(); - return FALSE; + return false; } if (!get_volume_path_parent(fn, volpath2, sizeof(volpath2) / sizeof(WCHAR))) { GlobalUnlock(lh); CloseClipboard(); - return FALSE; + return false; } GlobalUnlock(lh); @@ -276,30 +276,30 @@ static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HB BITMAPINFO bmi; HDC hdcUsed; - *phBmp = NULL; + *phBmp = nullptr; InitBitmapInfo(&bmi, sizeof(bmi), psize->cx, psize->cy, 32); - hdcUsed = hdc ? hdc : GetDC(NULL); + hdcUsed = hdc ? hdc : GetDC(nullptr); if (hdcUsed) { - *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, NULL, 0); + *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, nullptr, 0); if (hdc != hdcUsed) - ReleaseDC(NULL, hdcUsed); + ReleaseDC(nullptr, hdcUsed); } return !*phBmp ? E_OUTOFMEMORY : S_OK; } void BtrfsContextMenu::get_uac_icon() { - IWICImagingFactory* factory = NULL; + IWICImagingFactory* factory = nullptr; IWICBitmap* bitmap; HRESULT hr; #ifdef __REACTOS__ - hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void **)&factory); + hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void **)&factory); #else - hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)); + hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory)); #endif if (SUCCEEDED(hr)) { @@ -321,11 +321,11 @@ void BtrfsContextMenu::get_uac_icon() { sz.cx = (int)cx; sz.cy = -(int)cy; - hr = Create32BitHBITMAP(NULL, &sz, (void**)&buf, &uacicon); + hr = Create32BitHBITMAP(nullptr, &sz, (void**)&buf, &uacicon); if (SUCCEEDED(hr)) { UINT stride = cx * sizeof(DWORD); UINT buflen = cy * stride; - bitmap->CopyPixels(NULL, stride, buflen, buf); + bitmap->CopyPixels(nullptr, stride, buflen, buf); } } @@ -337,7 +337,7 @@ void BtrfsContextMenu::get_uac_icon() { } HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) { - WCHAR str[256]; + wstring str; ULONG entries = 0; if (ignore) @@ -348,10 +348,10 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu if (!bg) { if (allow_snapshot) { - if (LoadStringW(module, IDS_CREATE_SNAPSHOT, str, sizeof(str) / sizeof(WCHAR)) == 0) + if (load_string(module, IDS_CREATE_SNAPSHOT, str) == 0) return E_FAIL; - if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str)) + if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str.c_str())) return E_FAIL; entries = 1; @@ -360,7 +360,7 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu if (idCmdFirst + entries <= idCmdLast) { MENUITEMINFOW mii; - if (LoadStringW(module, IDS_SEND_SUBVOL, str, sizeof(str) / sizeof(WCHAR)) == 0) + if (load_string(module, IDS_SEND_SUBVOL, str) == 0) return E_FAIL; if (!uacicon) @@ -369,20 +369,20 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu memset(&mii, 0, sizeof(MENUITEMINFOW)); mii.cbSize = sizeof(MENUITEMINFOW); mii.fMask = MIIM_STRING | MIIM_ID | MIIM_BITMAP; - mii.dwTypeData = str; + mii.dwTypeData = (WCHAR*)str.c_str(); mii.wID = idCmdFirst + entries; mii.hbmpItem = uacicon; - if (!InsertMenuItemW(hmenu, indexMenu + entries, TRUE, &mii)) + if (!InsertMenuItemW(hmenu, indexMenu + entries, true, &mii)) return E_FAIL; entries++; } } else { - if (LoadStringW(module, IDS_NEW_SUBVOL, str, sizeof(str) / sizeof(WCHAR)) == 0) + if (load_string(module, IDS_NEW_SUBVOL, str) == 0) return E_FAIL; - if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str)) + if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str.c_str())) return E_FAIL; entries = 1; @@ -390,7 +390,7 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu if (idCmdFirst + 1 <= idCmdLast) { MENUITEMINFOW mii; - if (LoadStringW(module, IDS_RECV_SUBVOL, str, sizeof(str) / sizeof(WCHAR)) == 0) + if (load_string(module, IDS_RECV_SUBVOL, str) == 0) return E_FAIL; if (!uacicon) @@ -399,21 +399,21 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu memset(&mii, 0, sizeof(MENUITEMINFOW)); mii.cbSize = sizeof(MENUITEMINFOW); mii.fMask = MIIM_STRING | MIIM_ID | MIIM_BITMAP; - mii.dwTypeData = str; + mii.dwTypeData = (WCHAR*)str.c_str(); mii.wID = idCmdFirst + 1; mii.hbmpItem = uacicon; - if (!InsertMenuItemW(hmenu, indexMenu + 1, TRUE, &mii)) + if (!InsertMenuItemW(hmenu, indexMenu + 1, true, &mii)) return E_FAIL; entries++; } if (idCmdFirst + 2 <= idCmdLast && show_reflink_paste(path)) { - if (LoadStringW(module, IDS_REFLINK_PASTE, str, sizeof(str) / sizeof(WCHAR)) == 0) + if (load_string(module, IDS_REFLINK_PASTE, str) == 0) return E_FAIL; - if (!InsertMenuW(hmenu, indexMenu + 2, MF_BYPOSITION, idCmdFirst + 2, str)) + if (!InsertMenuW(hmenu, indexMenu + 2, MF_BYPOSITION, idCmdFirst + 2, str.c_str())) return E_FAIL; entries++; @@ -423,119 +423,126 @@ HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu return MAKE_HRESULT(SEVERITY_SUCCESS, 0, entries); } -static void create_snapshot(HWND hwnd, WCHAR* fn) { - HANDLE h; +static void path_remove_file(wstring& path) { + size_t bs = path.rfind(L"\\"); + + if (bs == string::npos) + return; + + if (bs == path.find(L"\\")) { // only one backslash + path = path.substr(0, bs + 1); + return; + } + + path = path.substr(0, bs); +} + +static void path_strip_path(wstring& path) { + size_t bs = path.rfind(L"\\"); + + if (bs == string::npos) { + path = L""; + return; + } + + path = path.substr(bs + 1); +} + +static void create_snapshot(HWND hwnd, const wstring& fn) { + win_handle h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (h != INVALID_HANDLE_VALUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) { - WCHAR parpath[MAX_PATH], subvolname[MAX_PATH], templ[MAX_PATH], name[MAX_PATH], searchpath[MAX_PATH]; - HANDLE h2, fff; + wstring subvolname, parpath, searchpath, temp1, name, nameorig; + win_handle h2; btrfs_create_snapshot* bcs; - ULONG namelen, pathend; + ULONG namelen; WIN32_FIND_DATAW wfd; SYSTEMTIME time; - StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn); - PathRemoveFileSpecW(parpath); + parpath = fn; + path_remove_file(parpath); - StringCchCopyW(subvolname, sizeof(subvolname) / sizeof(WCHAR), fn); - PathStripPathW(subvolname); + subvolname = fn; + path_strip_path(subvolname); - h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + h2 = CreateFileW(parpath.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (h2 == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - CloseHandle(h); - return; - } + if (h2 == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - if (!LoadStringW(module, IDS_SNAPSHOT_FILENAME, templ, MAX_PATH)) { - ShowError(hwnd, GetLastError()); - CloseHandle(h); - CloseHandle(h2); - return; - } + if (!load_string(module, IDS_SNAPSHOT_FILENAME, temp1)) + throw last_error(GetLastError()); GetLocalTime(&time); - if (StringCchPrintfW(name, sizeof(name) / sizeof(WCHAR), templ, subvolname, time.wYear, time.wMonth, time.wDay) == STRSAFE_E_INSUFFICIENT_BUFFER) { - MessageBoxW(hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR); - CloseHandle(h); - CloseHandle(h2); - return; - } + wstring_sprintf(name, temp1, subvolname.c_str(), time.wYear, time.wMonth, time.wDay); + nameorig = name; - StringCchCopyW(searchpath, sizeof(searchpath) / sizeof(WCHAR), parpath); - StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), L"\\"); - pathend = wcslen(searchpath); + searchpath = parpath + L"\\" + name; - StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), name); - - fff = FindFirstFileW(searchpath, &wfd); + fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd); if (fff != INVALID_HANDLE_VALUE) { - ULONG i = wcslen(searchpath), num = 2; + ULONG num = 2; do { - FindClose(fff); +#ifndef __REACTOS__ + name = nameorig + L" (" + to_wstring(num) + L")"; +#else + { + WCHAR buffer[32]; - searchpath[i] = 0; - if (StringCchPrintfW(searchpath, sizeof(searchpath) / sizeof(WCHAR), L"%s (%u)", searchpath, num) == STRSAFE_E_INSUFFICIENT_BUFFER) { - MessageBoxW(hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR); - CloseHandle(h); - CloseHandle(h2); - return; + swprintf(buffer, L"%d", num); + name = nameorig + L" (" + buffer + L")"; } +#endif + searchpath = parpath + L"\\" + name; - fff = FindFirstFileW(searchpath, &wfd); + fff = FindFirstFileW(searchpath.c_str(), &wfd); num++; } while (fff != INVALID_HANDLE_VALUE); } - namelen = wcslen(&searchpath[pathend]) * sizeof(WCHAR); + namelen = name.length() * sizeof(WCHAR); bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen); - bcs->readonly = FALSE; - bcs->posix = FALSE; + bcs->readonly = false; + bcs->posix = false; bcs->subvol = h; - bcs->namelen = namelen; - memcpy(bcs->name, &searchpath[pathend], namelen); + bcs->namelen = (uint16_t)namelen; + memcpy(bcs->name, name.c_str(), namelen); - Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen, NULL, 0); + Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen, nullptr, 0); if (!NT_SUCCESS(Status)) - ShowNtStatusError(hwnd, Status); - - CloseHandle(h2); + throw ntstatus_error(Status); } - - CloseHandle(h); } else - ShowError(hwnd, GetLastError()); + throw last_error(GetLastError()); } -static UINT64 __inline sector_align(UINT64 n, UINT64 a) { +static uint64_t __inline sector_align(uint64_t n, uint64_t a) { if (n & (a - 1)) n = (n + a) & ~(a - 1); return n; } -BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir) { - HANDLE source, dest; +void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir) { + win_handle source, dest; WCHAR* name, volpath1[255], volpath2[255]; - std::wstring dirw, newpath; - BOOL ret = FALSE; + wstring dirw, newpath; FILE_BASIC_INFO fbi; FILETIME atime, mtime; - btrfs_inode_info bii; + btrfs_inode_info2 bii; btrfs_set_inode_info bsii; ULONG bytesret; NTSTATUS Status; @@ -555,58 +562,44 @@ BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir newpath = dirw; newpath += name; - if (!get_volume_path_parent(fn, volpath1, sizeof(volpath1) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return FALSE; - } + if (!get_volume_path_parent(fn, volpath1, sizeof(volpath1) / sizeof(WCHAR))) + throw last_error(GetLastError()); - if (!GetVolumePathNameW(dir, volpath2, sizeof(volpath2) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return FALSE; - } + if (!GetVolumePathNameW(dir, volpath2, sizeof(volpath2) / sizeof(WCHAR))) + throw last_error(GetLastError()); if (wcscmp(volpath1, volpath2)) // different filesystems - return FALSE; + throw string_error(IDS_CANT_REFLINK_DIFFERENT_FS); - source = CreateFileW(fn, GENERIC_READ | FILE_TRAVERSE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT, NULL); - if (source == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - return FALSE; - } + source = CreateFileW(fn, GENERIC_READ | FILE_TRAVERSE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT, nullptr); + if (source == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii, sizeof(btrfs_inode_info)); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(source); - return FALSE; - } + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2)); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); // if subvol, do snapshot instead if (bii.inode == SUBVOL_ROOT_INODE) { btrfs_create_snapshot* bcs; - HANDLE dirh, fff; - std::wstring destname, search; + win_handle dirh; + wstring destname, search; WIN32_FIND_DATAW wfd; int num = 2; - dirh = CreateFileW(dir, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - CloseHandle(source); - return FALSE; - } + dirh = CreateFileW(dir, FILE_ADD_SUBDIRECTORY, 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()); search = dirw; search += name; destname = name; - fff = FindFirstFileW(search.c_str(), &wfd); + fff_handle fff = FindFirstFileW(search.c_str(), &wfd); if (fff != INVALID_HANDLE_VALUE) { do { - std::wstringstream ss; - - FindClose(fff); + wstringstream ss; ss << name; ss << L" ("; @@ -623,42 +616,30 @@ BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + (destname.length() * sizeof(WCHAR))); bcs->subvol = source; - bcs->namelen = destname.length() * sizeof(WCHAR); + bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR)); memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR)); - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen, NULL, 0); + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen, nullptr, 0); free(bcs); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(source); - CloseHandle(dirh); - return FALSE; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); - CloseHandle(source); - CloseHandle(dirh); - return TRUE; + return; } - if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) { - ShowError(hwnd, GetLastError()); - CloseHandle(source); - return FALSE; - } + if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) + throw last_error(GetLastError()); if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) { - HANDLE dirh; + win_handle dirh; ULONG bmnsize; btrfs_mknod* bmn; - dirh = CreateFileW(dir, FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - CloseHandle(source); - return FALSE; - } + 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)); bmn = (btrfs_mknod*)malloc(bmnsize); @@ -666,43 +647,36 @@ BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir bmn->inode = 0; bmn->type = bii.type; bmn->st_rdev = bii.st_rdev; - bmn->namelen = wcslen(name) * sizeof(WCHAR); + bmn->namelen = (uint16_t)(wcslen(name) * sizeof(WCHAR)); memcpy(bmn->name, name, bmn->namelen); - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, NULL, 0); + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0); if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - CloseHandle(dirh); - CloseHandle(source); free(bmn); - return FALSE; + throw ntstatus_error(Status); } - CloseHandle(dirh); free(bmn); - dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, 0, NULL); + dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr); } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (CreateDirectoryExW(fn, newpath.c_str(), NULL)) + if (CreateDirectoryExW(fn, newpath.c_str(), nullptr)) dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); else dest = INVALID_HANDLE_VALUE; } else - dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, source); + dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source); if (dest == INVALID_HANDLE_VALUE) { int num = 2; - if (GetLastError() != ERROR_FILE_EXISTS && GetLastError() != ERROR_ALREADY_EXISTS && wcscmp(fn, newpath.c_str())) { - ShowError(hwnd, GetLastError()); - CloseHandle(source); - return FALSE; - } + if (GetLastError() != ERROR_FILE_EXISTS && GetLastError() != ERROR_ALREADY_EXISTS && wcscmp(fn, newpath.c_str())) + throw last_error(GetLastError()); do { WCHAR* ext; - std::wstringstream ss; + wstringstream ss; ext = PathFindExtensionW(fn); @@ -714,7 +688,7 @@ BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir ss << num; ss << L")"; } else { - std::wstring namew = name; + wstring namew = name; ss << namew.substr(0, ext - name); ss << L" ("; @@ -725,514 +699,449 @@ BOOL BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir newpath = ss.str(); if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (CreateDirectoryExW(fn, newpath.c_str(), NULL)) - dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (CreateDirectoryExW(fn, newpath.c_str(), nullptr)) + dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); else dest = INVALID_HANDLE_VALUE; } else - dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, source); + dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source); if (dest == INVALID_HANDLE_VALUE) { - if (GetLastError() != ERROR_FILE_EXISTS && GetLastError() != ERROR_ALREADY_EXISTS) { - ShowError(hwnd, GetLastError()); - CloseHandle(source); - return FALSE; - } + if (GetLastError() != ERROR_FILE_EXISTS && GetLastError() != ERROR_ALREADY_EXISTS) + throw last_error(GetLastError()); num++; } else break; - } while (TRUE); + } while (true); } - memset(&bsii, 0, sizeof(btrfs_set_inode_info)); + try { + memset(&bsii, 0, sizeof(btrfs_set_inode_info)); - bsii.flags_changed = TRUE; - bsii.flags = bii.flags; + bsii.flags_changed = true; + bsii.flags = bii.flags; - if (bii.flags & BTRFS_INODE_COMPRESS) { - bsii.compression_type_changed = TRUE; - bsii.compression_type = bii.compression_type; - } - - Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - goto end; - } - - if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - HANDLE h; - WIN32_FIND_DATAW fff; - std::wstring qs; - - qs = fn; - qs += L"\\*"; - - h = FindFirstFileW(qs.c_str(), &fff); - if (h != INVALID_HANDLE_VALUE) { - do { - std::wstring fn2; - - if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0))) - continue; - - fn2 = fn; - fn2 += L"\\"; - fn2 += fff.cFileName; - - if (!reflink_copy(hwnd, fn2.c_str(), newpath.c_str())) - goto end; - } while (FindNextFileW(h, &fff)); - - FindClose(h); - } + if (bii.flags & BTRFS_INODE_COMPRESS) { + bsii.compression_type_changed = true; + bsii.compression_type = bii.compression_type; } - // CreateDirectoryExW also copies streams, no need to do it here - } else { - HANDLE h; - WIN32_FIND_STREAM_DATA fsd; + Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); - if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - reparse_header rh; - ULONG rplen; - UINT8* rp; + if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + fff_handle h; + WIN32_FIND_DATAW fff; + wstring qs; - if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, &rh, sizeof(reparse_header), &bytesret, NULL)) { - if (GetLastError() != ERROR_MORE_DATA) { - ShowError(hwnd, GetLastError()); - goto end; - } - } + qs = fn; + qs += L"\\*"; - rplen = sizeof(reparse_header) + rh.ReparseDataLength; - rp = (UINT8*)malloc(rplen); + h = FindFirstFileW(qs.c_str(), &fff); + if (h != INVALID_HANDLE_VALUE) { + do { + wstring fn2; - if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, rp, rplen, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, NULL, 0, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - free(rp); - } else { - FILE_STANDARD_INFO fsi; - FILE_END_OF_FILE_INFO feofi; - FSCTL_GET_INTEGRITY_INFORMATION_BUFFER fgiib; - FSCTL_SET_INTEGRITY_INFORMATION_BUFFER fsiib; - DUPLICATE_EXTENTS_DATA ded; - UINT64 offset, alloc_size; - ULONG maxdup; - - if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) { - ShowError(hwnd, GetLastError()); - goto end; - } - - if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, NULL, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { - if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - } - - fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm; - fsiib.Reserved = 0; - fsiib.Flags = fgiib.Flags; - if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), NULL, 0, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - feofi.EndOfFile = fsi.EndOfFile; - if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO))){ - ShowError(hwnd, GetLastError()); - goto end; - } - - ded.FileHandle = source; - maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1; - - alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes); - - offset = 0; - while (offset < alloc_size) { - ded.SourceFileOffset.QuadPart = ded.TargetFileOffset.QuadPart = offset; - ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset); - if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), NULL, 0, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - offset += ded.ByteCount.QuadPart; - } - } - - h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0); - if (h != INVALID_HANDLE_VALUE) { - do { - std::wstring sn; - - sn = fsd.cStreamName; - - if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") { - HANDLE stream; - UINT8* data = NULL; - - if (fsd.StreamSize.QuadPart > 0) { - std::wstring fn2; + if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0))) + continue; fn2 = fn; - fn2 += sn; + fn2 += L"\\"; + fn2 += fff.cFileName; - stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); + reflink_copy(hwnd, fn2.c_str(), newpath.c_str()); + } while (FindNextFileW(h, &fff)); + } + } + + // 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)) { + if (GetLastError() != ERROR_MORE_DATA) + throw last_error(GetLastError()); + } + + rplen = sizeof(reparse_header) + rh.ReparseDataLength; + rp = (uint8_t*)malloc(rplen); + + if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr)) + throw last_error(GetLastError()); + + if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + + free(rp); + } else { + FILE_STANDARD_INFO fsi; + FILE_END_OF_FILE_INFO feofi; + FSCTL_GET_INTEGRITY_INFORMATION_BUFFER fgiib; + FSCTL_SET_INTEGRITY_INFORMATION_BUFFER fsiib; + DUPLICATE_EXTENTS_DATA ded; + uint64_t offset, alloc_size; + ULONG maxdup; + + if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) + throw last_error(GetLastError()); + + if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr)) + throw last_error(GetLastError()); + + if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { + if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + } + + fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm; + fsiib.Reserved = 0; + fsiib.Flags = fgiib.Flags; + if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + + feofi.EndOfFile = fsi.EndOfFile; + if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO))) + throw last_error(GetLastError()); + + ded.FileHandle = source; + maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1; + + alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes); + + offset = 0; + while (offset < alloc_size) { + ded.SourceFileOffset.QuadPart = ded.TargetFileOffset.QuadPart = offset; + ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset); + if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + + offset += ded.ByteCount.QuadPart; + } + } + + fff_handle h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0); + if (h != INVALID_HANDLE_VALUE) { + do { + wstring sn; + + sn = fsd.cStreamName; + + 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; + + if (fsd.StreamSize.QuadPart > 0) { + wstring fn2; + + fn2 = fn; + fn2 += sn; + + stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr); + + if (stream == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + // We can get away with this because our streams are guaranteed to be below 64 KB - + // don't do this on NTFS! + data = (uint8_t*)malloc(stream_size); + + if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) { + free(data); + throw last_error(GetLastError()); + } + } + + stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr); if (stream == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - FindClose(h); - goto end; + if (data) free(data); + throw last_error(GetLastError()); } - // We can get away with this because our streams are guaranteed to be below 64 KB - - // don't do this on NTFS! - data = (UINT8*)malloc(fsd.StreamSize.QuadPart); + if (data) { + if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) { + free(data); + throw last_error(GetLastError()); + } - if (!ReadFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - FindClose(h); free(data); - CloseHandle(stream); - goto end; } - - CloseHandle(stream); } - - stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, NULL); - - if (stream == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - - FindClose(h); - if (data) free(data); - - goto end; - } - - if (data) { - if (!WriteFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) { - ShowError(hwnd, GetLastError()); - FindClose(h); - free(data); - CloseHandle(stream); - goto end; - } - - free(data); - } - - CloseHandle(stream); - } - } while (FindNextStreamW(h, &fsd)); - - FindClose(h); - } - } - - atime.dwLowDateTime = fbi.LastAccessTime.LowPart; - atime.dwHighDateTime = fbi.LastAccessTime.HighPart; - mtime.dwLowDateTime = fbi.LastWriteTime.LowPart; - mtime.dwHighDateTime = fbi.LastWriteTime.HighPart; - SetFileTime(dest, NULL, &atime, &mtime); - - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, &bsxa, sizeof(btrfs_set_xattr)); - - if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) { - ULONG xalen = 0; - btrfs_set_xattr *xa = NULL, *xa2; - - do { - xalen += 1024; - - if (xa) free(xa); - xa = (btrfs_set_xattr*)malloc(xalen); - - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, xa, xalen); - } while (Status == STATUS_BUFFER_OVERFLOW); - - if (!NT_SUCCESS(Status)) { - free(xa); - ShowNtStatusError(hwnd, Status); - goto end; + } while (FindNextStreamW(h, &fsd)); + } } - xa2 = xa; - while (xa2->valuelen > 0) { - Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_XATTR, xa2, - offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, NULL, 0); + atime.dwLowDateTime = fbi.LastAccessTime.LowPart; + atime.dwHighDateTime = fbi.LastAccessTime.HighPart; + mtime.dwLowDateTime = fbi.LastWriteTime.LowPart; + mtime.dwHighDateTime = fbi.LastWriteTime.HighPart; + SetFileTime(dest, nullptr, &atime, &mtime); + + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr)); + + if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) { + ULONG xalen = 0; + btrfs_set_xattr *xa = nullptr, *xa2; + + do { + xalen += 1024; + + if (xa) free(xa); + xa = (btrfs_set_xattr*)malloc(xalen); + + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen); + } while (Status == STATUS_BUFFER_OVERFLOW); + if (!NT_SUCCESS(Status)) { free(xa); - ShowNtStatusError(hwnd, Status); - goto end; + throw ntstatus_error(Status); } - xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen]; - } - free(xa); - } else if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - goto end; - } + 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); + if (!NT_SUCCESS(Status)) { + free(xa); + throw ntstatus_error(Status); + } + xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen]; + } - ret = TRUE; - -end: - if (!ret) { + free(xa); + } else if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } catch (...) { FILE_DISPOSITION_INFO fdi; - fdi.DeleteFile = TRUE; + fdi.DeleteFile = true; if (!SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO))) - ShowError(hwnd, GetLastError()); + throw last_error(GetLastError()); + + throw; } - - CloseHandle(dest); - CloseHandle(source); - - return ret; } HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) { LPCMINVOKECOMMANDINFOEX pici = (LPCMINVOKECOMMANDINFOEX)picia; - if (ignore) - return E_INVALIDARG; + try { + if (ignore) + return E_INVALIDARG; - if (!bg) { - if ((IS_INTRESOURCE(pici->lpVerb) && allow_snapshot && pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SNAPSHOT_VERBA))) { - UINT num_files, i; - WCHAR fn[MAX_PATH]; + if (!bg) { + if ((IS_INTRESOURCE(pici->lpVerb) && allow_snapshot && pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SNAPSHOT_VERBA))) { + UINT num_files, i; + WCHAR fn[MAX_PATH]; - if (!stgm_set) - return E_FAIL; + if (!stgm_set) + return E_FAIL; - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); - if (num_files == 0) - return E_FAIL; + if (num_files == 0) + return E_FAIL; - for (i = 0; i < num_files; i++) { - if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) { - create_snapshot(pici->hwnd, fn); - } - } - - return S_OK; - } else if ((IS_INTRESOURCE(pici->lpVerb) && ((allow_snapshot && (ULONG_PTR)pici->lpVerb == 1) || (!allow_snapshot && (ULONG_PTR)pici->lpVerb == 0))) || - (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SEND_VERBA))) { - UINT num_files, i; - WCHAR dll[MAX_PATH], fn[MAX_PATH]; - std::wstring t; - SHELLEXECUTEINFOW sei; - - GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR)); - - if (!stgm_set) - return E_FAIL; - - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); - - if (num_files == 0) - return E_FAIL; - - for (i = 0; i < num_files; i++) { - if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) { - t = L"\""; - t += dll; - t += L"\",SendSubvolGUI "; - t += fn; - - RtlZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(sei); - sei.hwnd = pici->hwnd; - 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)) { - ShowError(pici->hwnd, GetLastError()); - return E_FAIL; + for (i = 0; i < num_files; i++) { + if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) { + create_snapshot(pici->hwnd, fn); } - - WaitForSingleObject(sei.hProcess, INFINITE); - CloseHandle(sei.hProcess); } - } - return S_OK; - } - } else { - if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, NEW_SUBVOL_VERBA))) { - HANDLE h; - IO_STATUS_BLOCK iosb; - NTSTATUS Status; - ULONG pathlen, searchpathlen, pathend, bcslen; - WCHAR name[MAX_PATH], *searchpath; - btrfs_create_subvol* bcs; - HANDLE fff; - WIN32_FIND_DATAW wfd; - - if (!LoadStringW(module, IDS_NEW_SUBVOL_FILENAME, name, MAX_PATH)) { - ShowError(pici->hwnd, GetLastError()); - return E_FAIL; - } - - h = CreateFileW(path, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - - if (h == INVALID_HANDLE_VALUE) { - ShowError(pici->hwnd, GetLastError()); - return E_FAIL; - } - - pathlen = wcslen(path); - - searchpathlen = pathlen + wcslen(name) + 10; - searchpath = (WCHAR*)malloc(searchpathlen * sizeof(WCHAR)); - - StringCchCopyW(searchpath, searchpathlen, path); - StringCchCatW(searchpath, searchpathlen, L"\\"); - pathend = wcslen(searchpath); - - StringCchCatW(searchpath, searchpathlen, name); - - fff = FindFirstFileW(searchpath, &wfd); - - if (fff != INVALID_HANDLE_VALUE) { - ULONG i = wcslen(searchpath), num = 2; - - do { - FindClose(fff); - - searchpath[i] = 0; - if (StringCchPrintfW(searchpath, searchpathlen, L"%s (%u)", searchpath, num) == STRSAFE_E_INSUFFICIENT_BUFFER) { - MessageBoxW(pici->hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR); - CloseHandle(h); - return E_FAIL; - } - - fff = FindFirstFileW(searchpath, &wfd); - num++; - } while (fff != INVALID_HANDLE_VALUE); - } - - bcslen = offsetof(btrfs_create_subvol, name[0]) + (wcslen(&searchpath[pathend]) * sizeof(WCHAR)); - bcs = (btrfs_create_subvol*)malloc(bcslen); - - bcs->readonly = FALSE; - bcs->posix = FALSE; - bcs->namelen = wcslen(&searchpath[pathend]) * sizeof(WCHAR); - memcpy(bcs->name, &searchpath[pathend], bcs->namelen); - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0); - - free(searchpath); - free(bcs); - - if (!NT_SUCCESS(Status)) { - CloseHandle(h); - ShowNtStatusError(pici->hwnd, Status); - return E_FAIL; - } - - CloseHandle(h); - - return S_OK; - } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 1) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, RECV_VERBA))) { - WCHAR dll[MAX_PATH]; - std::wstring t; - SHELLEXECUTEINFOW sei; - - GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR)); - - t = L"\""; - t += dll; - t += L"\",RecvSubvolGUI "; - t += path; - - RtlZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(sei); - sei.hwnd = pici->hwnd; - 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)) { - ShowError(pici->hwnd, GetLastError()); - return E_FAIL; - } - - WaitForSingleObject(sei.hProcess, INFINITE); - CloseHandle(sei.hProcess); - - return S_OK; - } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 2) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, REFLINK_VERBA))) { - HDROP hdrop; - - if (!IsClipboardFormatAvailable(CF_HDROP)) return S_OK; + } else if ((IS_INTRESOURCE(pici->lpVerb) && ((allow_snapshot && (ULONG_PTR)pici->lpVerb == 1) || (!allow_snapshot && (ULONG_PTR)pici->lpVerb == 0))) || + (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SEND_VERBA))) { + UINT num_files, i; + WCHAR dll[MAX_PATH], fn[MAX_PATH]; + wstring t; + SHELLEXECUTEINFOW sei; - if (!OpenClipboard(pici->hwnd)) { - ShowError(pici->hwnd, GetLastError()); - return E_FAIL; + GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR)); + + if (!stgm_set) + return E_FAIL; + + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); + + if (num_files == 0) + return E_FAIL; + + for (i = 0; i < num_files; i++) { + if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) { + t = L"\""; + t += dll; + t += L"\",SendSubvolGUI "; + t += fn; + + RtlZeroMemory(&sei, sizeof(sei)); + + sei.cbSize = sizeof(sei); + sei.hwnd = pici->hwnd; + 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); + } + } + + return S_OK; } + } else { + if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, NEW_SUBVOL_VERBA))) { + win_handle h; + IO_STATUS_BLOCK iosb; + NTSTATUS Status; + ULONG bcslen; + wstring name, nameorig, searchpath; + btrfs_create_subvol* bcs; + WIN32_FIND_DATAW wfd; - hdrop = (HDROP)GetClipboardData(CF_HDROP); + if (!load_string(module, IDS_NEW_SUBVOL_FILENAME, name)) + throw last_error(GetLastError()); - if (hdrop) { - HANDLE lh; + h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - lh = GlobalLock(hdrop); + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - if (lh) { - ULONG num_files, i; - WCHAR fn[MAX_PATH]; + searchpath = path + L"\\" + name; + nameorig = name; - num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, NULL, 0); + { + fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd); - for (i = 0; i < num_files; i++) { - if (DragQueryFileW(hdrop, i, fn, sizeof(fn) / sizeof(WCHAR))) { - if (!reflink_copy(pici->hwnd, fn, pici->lpDirectoryW)) { - GlobalUnlock(lh); - CloseClipboard(); - return E_FAIL; + if (fff != INVALID_HANDLE_VALUE) { + ULONG num = 2; + + do { +#ifndef __REACTOS__ + name = nameorig + L" (" + to_wstring(num) + L")"; +#else + { + WCHAR buffer[32]; + + swprintf(buffer, L"%d", num); + name = nameorig + L" (" + buffer + L")"; } +#endif + searchpath = path + L"\\" + name; + + fff = FindFirstFileW(searchpath.c_str(), &wfd); + num++; + } while (fff != INVALID_HANDLE_VALUE); + } + } + + bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR)); + bcs = (btrfs_create_subvol*)malloc(bcslen); + + bcs->readonly = false; + bcs->posix = false; + 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); + + free(bcs); + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + return S_OK; + } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 1) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, RECV_VERBA))) { + WCHAR dll[MAX_PATH]; + wstring t; + SHELLEXECUTEINFOW sei; + + GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR)); + + t = L"\""; + t += dll; + t += L"\",RecvSubvolGUI "; + t += path; + + RtlZeroMemory(&sei, sizeof(sei)); + + sei.cbSize = sizeof(sei); + sei.hwnd = pici->hwnd; + 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); + + return S_OK; + } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 2) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, REFLINK_VERBA))) { + HDROP hdrop; + + if (!IsClipboardFormatAvailable(CF_HDROP)) + return S_OK; + + if (!OpenClipboard(pici->hwnd)) + throw last_error(GetLastError()); + + try { + hdrop = (HDROP)GetClipboardData(CF_HDROP); + + if (hdrop) { + HANDLE lh; + + lh = GlobalLock(hdrop); + + if (lh) { + try { + ULONG num_files, i; + WCHAR fn[MAX_PATH]; + + num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0); + + for (i = 0; i < num_files; i++) { + if (DragQueryFileW(hdrop, i, fn, sizeof(fn) / sizeof(WCHAR))) { + reflink_copy(pici->hwnd, fn, pici->lpDirectoryW); + } + } + } catch (...) { + GlobalUnlock(lh); + throw; + } + + GlobalUnlock(lh); } } - - GlobalUnlock(lh); + } catch (...) { + CloseClipboard(); + throw; } + + CloseClipboard(); + + return S_OK; } - - CloseClipboard(); - - return S_OK; } + } catch (const exception& e) { + error_message(pici->hwnd, e.what()); } return E_FAIL; @@ -1389,71 +1298,63 @@ HRESULT __stdcall BtrfsContextMenu::GetCommandString(UINT_PTR idCmd, UINT uFlags } } -static void reflink_copy2(std::wstring srcfn, std::wstring destdir, std::wstring destname) { - HANDLE source, dest; - BOOL ret = FALSE; +static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const wstring& destname) { + win_handle source, dest; FILE_BASIC_INFO fbi; FILETIME atime, mtime; - btrfs_inode_info bii; + btrfs_inode_info2 bii; btrfs_set_inode_info bsii; ULONG bytesret; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_set_xattr bsxa; - source = CreateFileW(srcfn.c_str(), GENERIC_READ | FILE_TRAVERSE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT, NULL); + source = CreateFileW(srcfn.c_str(), GENERIC_READ | FILE_TRAVERSE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT, nullptr); if (source == INVALID_HANDLE_VALUE) - return; + throw last_error(GetLastError()); - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii, sizeof(btrfs_inode_info)); - if (!NT_SUCCESS(Status)) { - CloseHandle(source); - return; - } + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2)); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); // if subvol, do snapshot instead if (bii.inode == SUBVOL_ROOT_INODE) { ULONG bcslen; btrfs_create_snapshot* bcs; - HANDLE dirh; + win_handle dirh; - dirh = CreateFileW(destdir.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) { - CloseHandle(source); - return; - } + dirh = CreateFileW(destdir.c_str(), FILE_ADD_SUBDIRECTORY, 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()); bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR)); bcs = (btrfs_create_snapshot*)malloc(bcslen); bcs->subvol = source; - bcs->namelen = destname.length() * sizeof(WCHAR); + bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR)); memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR)); - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, NULL, 0); + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0); + if (!NT_SUCCESS(Status)) { + free(bcs); + throw ntstatus_error(Status); + } free(bcs); - CloseHandle(source); - CloseHandle(dirh); - return; } - if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) { - CloseHandle(source); - return; - } + if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) + throw last_error(GetLastError()); if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) { - HANDLE dirh; + 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, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) { - CloseHandle(source); - return; - } + 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)); bmn = (btrfs_mknod*)malloc(bmnsize); @@ -1461,261 +1362,246 @@ static void reflink_copy2(std::wstring srcfn, std::wstring destdir, std::wstring bmn->inode = 0; bmn->type = bii.type; bmn->st_rdev = bii.st_rdev; - bmn->namelen = destname.length() * sizeof(WCHAR); + bmn->namelen = (uint16_t)(destname.length() * sizeof(WCHAR)); memcpy(bmn->name, destname.c_str(), bmn->namelen); - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, NULL, 0); + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0); if (!NT_SUCCESS(Status)) { - CloseHandle(dirh); - CloseHandle(source); free(bmn); - return; + throw ntstatus_error(Status); } - CloseHandle(dirh); free(bmn); - dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, 0, NULL); + dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr); } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), NULL)) + if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), nullptr)) dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - else - dest = INVALID_HANDLE_VALUE; + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + else + dest = INVALID_HANDLE_VALUE; } else - dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, source); + dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source); - if (dest == INVALID_HANDLE_VALUE) { - CloseHandle(source); - return; - } + if (dest == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); memset(&bsii, 0, sizeof(btrfs_set_inode_info)); - bsii.flags_changed = TRUE; + bsii.flags_changed = true; bsii.flags = bii.flags; if (bii.flags & BTRFS_INODE_COMPRESS) { - bsii.compression_type_changed = TRUE; + bsii.compression_type_changed = true; bsii.compression_type = bii.compression_type; } - Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) - goto end; + try { + Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); - if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { - HANDLE h; - WIN32_FIND_DATAW fff; - std::wstring qs; + if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + WIN32_FIND_DATAW fff; + wstring qs; - qs = srcfn; - qs += L"\\*"; + qs = srcfn; + qs += L"\\*"; - h = FindFirstFileW(qs.c_str(), &fff); - if (h != INVALID_HANDLE_VALUE) { - do { - std::wstring fn2; + fff_handle h = FindFirstFileW(qs.c_str(), &fff); + if (h != INVALID_HANDLE_VALUE) { + do { + wstring fn2; - if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0))) - continue; - - fn2 = srcfn; - fn2 += L"\\"; - fn2 += fff.cFileName; - - reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName); - } while (FindNextFileW(h, &fff)); - - FindClose(h); - } - } - - // CreateDirectoryExW also copies streams, no need to do it here - } else { - HANDLE h; - WIN32_FIND_STREAM_DATA fsd; - - if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { - reparse_header rh; - ULONG rplen; - UINT8* rp; - - if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, &rh, sizeof(reparse_header), &bytesret, NULL)) { - if (GetLastError() != ERROR_MORE_DATA) - goto end; - } - - rplen = sizeof(reparse_header) + rh.ReparseDataLength; - rp = (UINT8*)malloc(rplen); - - if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, rp, rplen, &bytesret, NULL)) - goto end; - - if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, NULL, 0, &bytesret, NULL)) - goto end; - - free(rp); - } else { - FILE_STANDARD_INFO fsi; - FILE_END_OF_FILE_INFO feofi; - FSCTL_GET_INTEGRITY_INFORMATION_BUFFER fgiib; - FSCTL_SET_INTEGRITY_INFORMATION_BUFFER fsiib; - DUPLICATE_EXTENTS_DATA ded; - UINT64 offset, alloc_size; - ULONG maxdup; - - if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) - goto end; - - if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, NULL, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, NULL)) - goto end; - - if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { - if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &bytesret, NULL)) - goto end; - } - - fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm; - fsiib.Reserved = 0; - fsiib.Flags = fgiib.Flags; - if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), NULL, 0, &bytesret, NULL)) - goto end; - - feofi.EndOfFile = fsi.EndOfFile; - if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO))) - goto end; - - ded.FileHandle = source; - maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1; - - alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes); - - offset = 0; - while (offset < alloc_size) { - ded.SourceFileOffset.QuadPart = ded.TargetFileOffset.QuadPart = offset; - ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset); - if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), NULL, 0, &bytesret, NULL)) - goto end; - - offset += ded.ByteCount.QuadPart; - } - } - - h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0); - if (h != INVALID_HANDLE_VALUE) { - do { - std::wstring sn; - - sn = fsd.cStreamName; - - if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") { - HANDLE stream; - UINT8* data = NULL; - - if (fsd.StreamSize.QuadPart > 0) { - std::wstring fn2; + if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0))) + continue; fn2 = srcfn; - fn2 += sn; + fn2 += L"\\"; + fn2 += fff.cFileName; - stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); - - if (stream == INVALID_HANDLE_VALUE) - goto end; - - // We can get away with this because our streams are guaranteed to be below 64 KB - - // don't do this on NTFS! - data = (UINT8*)malloc(fsd.StreamSize.QuadPart); - - if (!ReadFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) { - free(data); - CloseHandle(stream); - goto end; - } - - CloseHandle(stream); - } - - stream = CreateFileW((destdir + destname + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, NULL); - - if (stream == INVALID_HANDLE_VALUE) { - if (data) free(data); - goto end; - } - - if (data) { - if (!WriteFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) { - free(data); - CloseHandle(stream); - goto end; - } - - free(data); - } - - CloseHandle(stream); + reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName); + } while (FindNextFileW(h, &fff)); } - } while (FindNextStreamW(h, &fsd)); + } - FindClose(h); - } - } + // CreateDirectoryExW also copies streams, no need to do it here + } else { + WIN32_FIND_STREAM_DATA fsd; - atime.dwLowDateTime = fbi.LastAccessTime.LowPart; - atime.dwHighDateTime = fbi.LastAccessTime.HighPart; - mtime.dwLowDateTime = fbi.LastWriteTime.LowPart; - mtime.dwHighDateTime = fbi.LastWriteTime.HighPart; - SetFileTime(dest, NULL, &atime, &mtime); + if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + reparse_header rh; + ULONG rplen; + uint8_t* rp; - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, &bsxa, sizeof(btrfs_set_xattr)); + if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) { + if (GetLastError() != ERROR_MORE_DATA) + throw last_error(GetLastError()); + } - if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) { - ULONG xalen = 0; - btrfs_set_xattr *xa = NULL, *xa2; + rplen = sizeof(reparse_header) + rh.ReparseDataLength; + rp = (uint8_t*)malloc(rplen); - do { - xalen += 1024; + try { + if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr)) + throw last_error(GetLastError()); - if (xa) free(xa); - xa = (btrfs_set_xattr*)malloc(xalen); + if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + } catch (...) { + free(rp); + throw; + } - Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, xa, xalen); - } while (Status == STATUS_BUFFER_OVERFLOW); + free(rp); + } else { + FILE_STANDARD_INFO fsi; + FILE_END_OF_FILE_INFO feofi; + FSCTL_GET_INTEGRITY_INFORMATION_BUFFER fgiib; + FSCTL_SET_INTEGRITY_INFORMATION_BUFFER fsiib; + DUPLICATE_EXTENTS_DATA ded; + uint64_t offset, alloc_size; + ULONG maxdup; - if (!NT_SUCCESS(Status)) { - free(xa); - goto end; + if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) + throw last_error(GetLastError()); + + if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr)) + throw last_error(GetLastError()); + + if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) { + if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + } + + fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm; + fsiib.Reserved = 0; + fsiib.Flags = fgiib.Flags; + if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + + feofi.EndOfFile = fsi.EndOfFile; + if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO))) + throw last_error(GetLastError()); + + ded.FileHandle = source; + maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1; + + alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes); + + offset = 0; + while (offset < alloc_size) { + ded.SourceFileOffset.QuadPart = ded.TargetFileOffset.QuadPart = offset; + ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset); + if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr)) + throw last_error(GetLastError()); + + offset += ded.ByteCount.QuadPart; + } + } + + fff_handle h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0); + if (h != INVALID_HANDLE_VALUE) { + do { + wstring sn; + + sn = fsd.cStreamName; + + if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") { + win_handle stream; + uint8_t* data = nullptr; + + if (fsd.StreamSize.QuadPart > 0) { + wstring fn2; + uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart; + + fn2 = srcfn; + fn2 += sn; + + stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr); + + if (stream == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + // We can get away with this because our streams are guaranteed to be below 64 KB - + // don't do this on NTFS! + data = (uint8_t*)malloc(stream_size); + + if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) { + free(data); + throw last_error(GetLastError()); + } + } + + stream = CreateFileW((destdir + destname + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr); + + if (stream == INVALID_HANDLE_VALUE) { + if (data) free(data); + throw last_error(GetLastError()); + } + + if (data) { + if (!WriteFile(stream, data, (uint32_t)fsd.StreamSize.QuadPart, &bytesret, nullptr)) { + free(data); + throw last_error(GetLastError()); + } + + free(data); + } + } + } while (FindNextStreamW(h, &fsd)); + } } - xa2 = xa; - while (xa2->valuelen > 0) { - Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_XATTR, xa2, - offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, NULL, 0); + atime.dwLowDateTime = fbi.LastAccessTime.LowPart; + atime.dwHighDateTime = fbi.LastAccessTime.HighPart; + mtime.dwLowDateTime = fbi.LastWriteTime.LowPart; + mtime.dwHighDateTime = fbi.LastWriteTime.HighPart; + SetFileTime(dest, nullptr, &atime, &mtime); + + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr)); + + if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) { + ULONG xalen = 0; + btrfs_set_xattr *xa = nullptr, *xa2; + + do { + xalen += 1024; + + if (xa) free(xa); + xa = (btrfs_set_xattr*)malloc(xalen); + + Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen); + } while (Status == STATUS_BUFFER_OVERFLOW); + if (!NT_SUCCESS(Status)) { free(xa); - goto end; + throw ntstatus_error(Status); } - xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen]; - } - free(xa); - } else if (!NT_SUCCESS(Status)) - goto end; + 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); + if (!NT_SUCCESS(Status)) { + free(xa); + throw ntstatus_error(Status); + } + xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen]; + } - ret = TRUE; - -end: - if (!ret) { + free(xa); + } else if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } catch (...) { FILE_DISPOSITION_INFO fdi; - fdi.DeleteFile = TRUE; + fdi.DeleteFile = true; SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); - } - CloseHandle(dest); - CloseHandle(source); + throw; + } } #ifdef __REACTOS__ @@ -1723,39 +1609,36 @@ extern "C" { #endif void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; + vector args; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + command_line_to_args(lpszCmdLine, args); - if (!args) - return; - - if (num_args >= 2) { - HANDLE destdirh; - BOOL dest_is_dir = FALSE; - std::wstring dest = args[num_args - 1], destdir, destname; + if (args.size() >= 2) { + bool dest_is_dir = false; + wstring dest = args[args.size() - 1], destdir, destname; WCHAR volpath2[MAX_PATH]; - int i; - destdirh = CreateFileW(dest.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (destdirh != INVALID_HANDLE_VALUE) { - BY_HANDLE_FILE_INFORMATION bhfi; + { + win_handle destdirh = CreateFileW(dest.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (GetFileInformationByHandle(destdirh, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - dest_is_dir = TRUE; + if (destdirh != INVALID_HANDLE_VALUE) { + BY_HANDLE_FILE_INFORMATION bhfi; - destdir = dest; - if (destdir.substr(destdir.length() - 1, 1) != L"\\") - destdir += L"\\"; + if (GetFileInformationByHandle(destdirh, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + dest_is_dir = true; + + destdir = dest; + if (destdir.substr(destdir.length() - 1, 1) != L"\\") + destdir += L"\\"; + } } - CloseHandle(destdirh); } if (!dest_is_dir) { size_t found = dest.rfind(L"\\"); - if (found == std::wstring::npos) { + if (found == wstring::npos) { destdir = L""; destname = dest; } else { @@ -1765,19 +1648,18 @@ void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int n } if (!GetVolumePathNameW(dest.c_str(), volpath2, sizeof(volpath2) / sizeof(WCHAR))) - goto end; + return; - for (i = 0; i < num_args - 1; i++) { + for (unsigned int i = 0; i < args.size() - 1; i++) { WIN32_FIND_DATAW ffd; - HANDLE h; - h = FindFirstFileW(args[i], &ffd); + fff_handle h = FindFirstFileW(args[i].c_str(), &ffd); if (h != INVALID_HANDLE_VALUE) { WCHAR volpath1[MAX_PATH]; - std::wstring path = args[i]; + wstring path = args[i]; size_t found = path.rfind(L"\\"); - if (found == std::wstring::npos) + if (found == wstring::npos) path = L""; else path = path.substr(0, found); @@ -1787,18 +1669,17 @@ void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int n if (get_volume_path_parent(path.c_str(), volpath1, sizeof(volpath1) / sizeof(WCHAR))) { if (!wcscmp(volpath1, volpath2)) { do { - reflink_copy2(path + ffd.cFileName, destdir, dest_is_dir ? ffd.cFileName : destname); + try { + reflink_copy2(path + ffd.cFileName, destdir, dest_is_dir ? ffd.cFileName : destname); + } catch (const exception& e) { + cerr << "Error: " << e.what() << endl; + } } while (FindNextFileW(h, &ffd)); } } - - FindClose(h); } } } - -end: - LocalFree(args); } #ifdef __REACTOS__ diff --git a/dll/shellext/shellbtrfs/contextmenu.h b/dll/shellext/shellbtrfs/contextmenu.h index 12779f422bf..fe48f9ad852 100644 --- a/dll/shellext/shellbtrfs/contextmenu.h +++ b/dll/shellext/shellbtrfs/contextmenu.h @@ -25,10 +25,10 @@ class BtrfsContextMenu : public IShellExtInit, IContextMenu { public: BtrfsContextMenu() { refcount = 0; - ignore = TRUE; - stgm_set = FALSE; - uacicon = NULL; - allow_snapshot = FALSE; + ignore = true; + stgm_set = false; + uacicon = nullptr; + allow_snapshot = false; InterlockedIncrement(&objs_loaded); } @@ -73,13 +73,13 @@ public: private: LONG refcount; - BOOL ignore, allow_snapshot; - BOOL bg; - WCHAR path[MAX_PATH]; + bool ignore, allow_snapshot; + bool bg; + wstring path; STGMEDIUM stgm; - BOOL stgm_set; + bool stgm_set; HBITMAP uacicon; - BOOL reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir); + void reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir); void get_uac_icon(); }; diff --git a/dll/shellext/shellbtrfs/devices.cpp b/dll/shellext/shellbtrfs/devices.cpp index 8feb747e10d..f2c297b15f6 100644 --- a/dll/shellext/shellbtrfs/devices.cpp +++ b/dll/shellext/shellbtrfs/devices.cpp @@ -27,8 +27,8 @@ #include #include #include -#include #ifndef __REACTOS__ +#include #include "../btrfs.h" #else #include @@ -39,15 +39,15 @@ DEFINE_GUID(GUID_DEVINTERFACE_HIDDEN_VOLUME, 0x7f108a28L, 0x9833, 0x4b3b, 0xb7, 0x80, 0x2c, 0x6b, 0x5f, 0xa5, 0xc0, 0x62); -static std::wstring get_mountdev_name(HANDLE h) { +static wstring get_mountdev_name(const nt_handle& h ) { NTSTATUS Status; IO_STATUS_BLOCK iosb; MOUNTDEV_NAME mdn, *mdn2; ULONG mdnsize; - std::wstring name; + wstring name; - Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, - NULL, 0, &mdn, sizeof(MOUNTDEV_NAME)); + Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, + nullptr, 0, &mdn, sizeof(MOUNTDEV_NAME)); if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) return L""; @@ -55,26 +55,26 @@ static std::wstring get_mountdev_name(HANDLE h) { mdn2 = (MOUNTDEV_NAME*)malloc(mdnsize); - Status = NtDeviceIoControlFile(h, NULL, NULL, NULL, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, - NULL, 0, mdn2, mdnsize); + Status = NtDeviceIoControlFile(h, nullptr, nullptr, nullptr, &iosb, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, + nullptr, 0, mdn2, mdnsize); if (!NT_SUCCESS(Status)) { free(mdn2); return L""; } - name = std::wstring(mdn2->Name, mdn2->NameLength / sizeof(WCHAR)); + name = wstring(mdn2->Name, mdn2->NameLength / sizeof(WCHAR)); free(mdn2); return name; } -static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vector* device_list) { +static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr, vector& device_list) { HDEVINFO h; static WCHAR dosdevices[] = L"\\DosDevices\\"; - h = SetupDiGetClassDevs(guid, NULL, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + h = SetupDiGetClassDevs(guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); if (h != INVALID_HANDLE_VALUE) { DWORD index = 0; @@ -82,7 +82,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect did.cbSize = sizeof(did); - if (!SetupDiEnumDeviceInterfaces(h, NULL, guid, index, &did)) + if (!SetupDiEnumDeviceInterfaces(h, nullptr, guid, index, &did)) return; do { @@ -92,7 +92,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect dd.cbSize = sizeof(dd); - SetupDiGetDeviceInterfaceDetailW(h, &did, NULL, 0, &size, NULL); + SetupDiGetDeviceInterfaceDetailW(h, &did, nullptr, 0, &size, nullptr); detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W*)malloc(size); memset(detail, 0, size); @@ -101,7 +101,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect if (SetupDiGetDeviceInterfaceDetailW(h, &did, detail, size, &size, &dd)) { NTSTATUS Status; - HANDLE file; + nt_handle file; device dev; STORAGE_DEVICE_NUMBER sdn; IO_STATUS_BLOCK iosb; @@ -109,30 +109,36 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect OBJECT_ATTRIBUTES attr; GET_LENGTH_INFORMATION gli; ULONG i; - UINT8 sb[4096]; + uint8_t sb[4096]; path.Buffer = detail->DevicePath; - path.Length = path.MaximumLength = wcslen(detail->DevicePath) * sizeof(WCHAR); + path.Length = path.MaximumLength = (uint16_t)(wcslen(detail->DevicePath) * sizeof(WCHAR)); if (path.Length > 4 * sizeof(WCHAR) && path.Buffer[0] == '\\' && path.Buffer[1] == '\\' && path.Buffer[2] == '?' && path.Buffer[3] == '\\') path.Buffer[1] = '?'; - InitializeObjectAttributes(&attr, &path, 0, NULL, NULL); + InitializeObjectAttributes(&attr, &path, 0, nullptr, nullptr); Status = NtOpenFile(&file, FILE_GENERIC_READ, &attr, &iosb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SYNCHRONOUS_IO_ALERT); - if (!NT_SUCCESS(Status)) - goto nextitem2; + if (!NT_SUCCESS(Status)) { + free(detail); + index++; + continue; + } dev.pnp_name = detail->DevicePath; - Status = NtDeviceIoControlFile(file, NULL, NULL, NULL, &iosb, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &gli, sizeof(GET_LENGTH_INFORMATION)); - if (!NT_SUCCESS(Status)) - goto nextitem; + Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &gli, sizeof(GET_LENGTH_INFORMATION)); + if (!NT_SUCCESS(Status)) { + free(detail); + index++; + continue; + } dev.size = gli.Length.QuadPart; - Status = NtDeviceIoControlFile(file, NULL, NULL, NULL, &iosb, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(STORAGE_DEVICE_NUMBER)); + Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_GET_DEVICE_NUMBER, nullptr, 0, &sdn, sizeof(STORAGE_DEVICE_NUMBER)); if (!NT_SUCCESS(Status)) { dev.disk_num = 0xffffffff; dev.part_num = 0xffffffff; @@ -144,9 +150,9 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect dev.friendly_name = L""; dev.drive = L""; dev.fstype = L""; - dev.has_parts = FALSE; - dev.ignore = FALSE; - dev.multi_device = FALSE; + dev.has_parts = false; + dev.ignore = false; + dev.multi_device = false; dev.is_disk = RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) == sizeof(GUID); @@ -160,21 +166,21 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect spq.QueryType = PropertyStandardQuery; spq.AdditionalParameters[0] = 0; - Status = NtDeviceIoControlFile(file, NULL, NULL, NULL, &iosb, IOCTL_STORAGE_QUERY_PROPERTY, + Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(STORAGE_PROPERTY_QUERY), &sdd, sizeof(STORAGE_DEVICE_DESCRIPTOR)); if (NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW) { sdd2 = (STORAGE_DEVICE_DESCRIPTOR*)malloc(sdd.Size); - Status = NtDeviceIoControlFile(file, NULL, NULL, NULL, &iosb, IOCTL_STORAGE_QUERY_PROPERTY, - &spq, sizeof(STORAGE_PROPERTY_QUERY), sdd2, sdd.Size); + Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_STORAGE_QUERY_PROPERTY, + &spq, sizeof(STORAGE_PROPERTY_QUERY), sdd2, sdd.Size); if (NT_SUCCESS(Status)) { - std::string desc2; + string desc2; desc2 = ""; if (sdd2->VendorIdOffset != 0) { - desc2 += (char*)((UINT8*)sdd2 + sdd2->VendorIdOffset); + desc2 += (char*)((uint8_t*)sdd2 + sdd2->VendorIdOffset); while (desc2.length() > 0 && desc2[desc2.length() - 1] == ' ') desc2 = desc2.substr(0, desc2.length() - 1); @@ -184,7 +190,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect if (sdd2->VendorIdOffset != 0 && desc2.length() != 0 && desc2[desc2.length() - 1] != ' ') desc2 += " "; - desc2 += (char*)((UINT8*)sdd2 + sdd2->ProductIdOffset); + desc2 += (char*)((uint8_t*)sdd2 + sdd2->ProductIdOffset); while (desc2.length() > 0 && desc2[desc2.length() - 1] == ' ') desc2 = desc2.substr(0, desc2.length() - 1); @@ -193,7 +199,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect if (sdd2->VendorIdOffset != 0 || sdd2->ProductIdOffset != 0) { ULONG ss; - ss = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, NULL, 0); + ss = MultiByteToWideChar(CP_OEMCP, MB_PRECOMPOSED, desc2.c_str(), -1, nullptr, 0); if (ss > 0) { WCHAR* desc3 = (WCHAR*)malloc(ss * sizeof(WCHAR)); @@ -210,7 +216,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect } dlisize = 0; - dli = NULL; + dli = nullptr; do { dlisize += 1024; @@ -220,12 +226,12 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect dli = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(dlisize); - Status = NtDeviceIoControlFile(file, NULL, NULL, NULL, &iosb, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, - NULL, 0, dli, dlisize); + Status = NtDeviceIoControlFile(file, nullptr, nullptr, nullptr, &iosb, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, + nullptr, 0, dli, dlisize); } while (Status == STATUS_BUFFER_TOO_SMALL); if (NT_SUCCESS(Status) && dli->PartitionCount > 0) - dev.has_parts = TRUE; + dev.has_parts = true; free(dli); } else { @@ -242,21 +248,21 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect mmp->DeviceNameLength = path.Length; RtlCopyMemory(&mmp[1], path.Buffer, path.Length); - Status = NtDeviceIoControlFile(mountmgr, NULL, NULL, NULL, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS, + 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, NULL, NULL, NULL, &iosb, IOCTL_MOUNTMGR_QUERY_POINTS, + 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*)mmps2 + mmps2->MountPoints[i].SymbolicLinkNameOffset); + 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) && @@ -285,7 +291,7 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect LARGE_INTEGER off; off.QuadPart = fs_ident[i].kboff * 1024; - Status = NtReadFile(file, NULL, NULL, NULL, &iosb, sb, sizeof(sb), &off, NULL); + Status = NtReadFile(file, nullptr, nullptr, nullptr, &iosb, sb, sizeof(sb), &off, nullptr); } if (NT_SUCCESS(Status)) { @@ -307,35 +313,30 @@ static void find_devices(HWND hwnd, const GUID* guid, HANDLE mountmgr, std::vect } if (dev.fstype == L"Btrfs" && RtlCompareMemory(guid, &GUID_DEVINTERFACE_DISK, sizeof(GUID)) != sizeof(GUID)) { - std::wstring name; - std::wstring pref = L"\\Device\\Btrfs{"; + wstring name; + wstring pref = L"\\Device\\Btrfs{"; name = get_mountdev_name(file); if (name.length() > pref.length() && RtlCompareMemory(name.c_str(), pref.c_str(), pref.length() * sizeof(WCHAR)) == pref.length() * sizeof(WCHAR)) - dev.ignore = TRUE; + dev.ignore = true; } } - device_list->push_back(dev); - -nextitem: - NtClose(file); + device_list.push_back(dev); } -nextitem2: free(detail); index++; - } while (SetupDiEnumDeviceInterfaces(h, NULL, guid, index, &did)); + } while (SetupDiEnumDeviceInterfaces(h, nullptr, guid, index, &did)); SetupDiDestroyDeviceInfoList(h); - } else { - ShowError(hwnd, GetLastError()); - return; - } + } else + throw last_error(GetLastError()); } +#ifndef __REACTOS__ // Disabled because building with our seems complex right now... static bool sort_devices(device i, device j) { if (i.disk_num < j.disk_num) return true; @@ -345,6 +346,7 @@ static bool sort_devices(device i, device j) { return false; } +#endif void BtrfsDeviceAdd::populate_device_tree(HWND tree) { HWND hwnd = GetParent(tree); @@ -355,68 +357,72 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { OBJECT_ATTRIBUTES attr; UNICODE_STRING us; IO_STATUS_BLOCK iosb; - HANDLE mountmgr, btrfsh; - btrfs_filesystem* bfs = NULL; + btrfs_filesystem* bfs = nullptr; static WCHAR btrfs[] = L"\\Btrfs"; device_list.clear(); - RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME); - InitializeObjectAttributes(&attr, &us, 0, NULL, NULL); + { + nt_handle mountmgr; - Status = NtOpenFile(&mountmgr, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb, - FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); - if (!NT_SUCCESS(Status)) { - MessageBoxW(hwnd, L"Could not get handle to mount manager.", L"Error", MB_ICONERROR); - return; - } + RtlInitUnicodeString(&us, MOUNTMGR_DEVICE_NAME); + InitializeObjectAttributes(&attr, &us, 0, nullptr, nullptr); - us.Length = us.MaximumLength = wcslen(btrfs) * sizeof(WCHAR); - us.Buffer = btrfs; + Status = NtOpenFile(&mountmgr, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb, + FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); - InitializeObjectAttributes(&attr, &us, 0, NULL, NULL); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_CANT_OPEN_MOUNTMGR); - Status = NtOpenFile(&btrfsh, SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &iosb, - FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); - if (NT_SUCCESS(Status)) { - ULONG bfssize = 0; + { + nt_handle btrfsh; - do { - bfssize += 1024; + us.Length = us.MaximumLength = (uint16_t)(wcslen(btrfs) * sizeof(WCHAR)); + us.Buffer = btrfs; - if (bfs) free(bfs); - bfs = (btrfs_filesystem*)malloc(bfssize); + InitializeObjectAttributes(&attr, &us, 0, nullptr, nullptr); - Status = NtDeviceIoControlFile(btrfsh, NULL, NULL, NULL, &iosb, IOCTL_BTRFS_QUERY_FILESYSTEMS, NULL, 0, bfs, bfssize); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { - free(bfs); - bfs = NULL; - break; + Status = NtOpenFile(&btrfsh, SYNCHRONIZE | FILE_READ_ATTRIBUTES, &attr, &iosb, + FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_ALERT); + if (NT_SUCCESS(Status)) { + ULONG bfssize = 0; + + do { + bfssize += 1024; + + if (bfs) free(bfs); + bfs = (btrfs_filesystem*)malloc(bfssize); + + Status = NtDeviceIoControlFile(btrfsh, nullptr, nullptr, nullptr, &iosb, IOCTL_BTRFS_QUERY_FILESYSTEMS, nullptr, 0, bfs, bfssize); + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { + free(bfs); + bfs = nullptr; + break; + } + } while (Status == STATUS_BUFFER_OVERFLOW); + + if (bfs && bfs->num_devices == 0) { // no mounted filesystems found + free(bfs); + bfs = nullptr; + } } - } while (Status == STATUS_BUFFER_OVERFLOW); - - if (bfs && bfs->num_devices == 0) { // no mounted filesystems found - free(bfs); - bfs = NULL; } + + 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); } - NtClose(btrfsh); - 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); - - NtClose(mountmgr); - - std::sort(device_list.begin(), device_list.end(), sort_devices); +#ifndef __REACTOS__ // Disabled because building with our seems complex right now... + sort(device_list.begin(), device_list.end(), sort_devices); +#endif for (i = 0; i < device_list.size(); i++) { if (!device_list[i].ignore) { TVINSERTSTRUCTW tis; HTREEITEM item; - std::wstring name; - WCHAR size[255]; + wstring name, size; if (device_list[i].disk_num != 0xffffffff && device_list[i].disk_num == last_disk_num) tis.hParent = diskitem; @@ -429,17 +435,12 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { tis.itemex.stateMask = TVIS_EXPANDED; if (device_list[i].disk_num != 0xffffffff) { - WCHAR t[255], u[255]; + wstring t; - if (!LoadStringW(module, device_list[i].part_num != 0 ? IDS_PARTITION : IDS_DISK_NUM, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return; - } + if (!load_string(module, device_list[i].part_num != 0 ? IDS_PARTITION : IDS_DISK_NUM, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, device_list[i].part_num != 0 ? device_list[i].part_num : device_list[i].disk_num) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - - name = u; + wstring_sprintf(name, t, device_list[i].part_num != 0 ? device_list[i].part_num : device_list[i].disk_num); } else name = device_list[i].pnp_name; @@ -447,7 +448,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { if (bfs && device_list[i].drive == L"" && device_list[i].fstype == L"Btrfs") { btrfs_filesystem* bfs2 = bfs; - while (TRUE) { + while (true) { if (RtlCompareMemory(&bfs2->uuid, &device_list[i].fs_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { ULONG j, k; btrfs_filesystem_device* dev; @@ -456,7 +457,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { if (j == 0) dev = &bfs2->device; else - dev = (btrfs_filesystem_device*)((UINT8*)dev + offsetof(btrfs_filesystem_device, name[0]) + dev->name_length); + dev = (btrfs_filesystem_device*)((uint8_t*)dev + offsetof(btrfs_filesystem_device, name[0]) + dev->name_length); if (RtlCompareMemory(&device_list[i].dev_uuid, &device_list[i].dev_uuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { for (k = 0; k < device_list.size(); k++) { @@ -477,7 +478,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { } if (bfs2->next_entry != 0) - bfs2 = (btrfs_filesystem*)((UINT8*)bfs2 + bfs2->next_entry); + bfs2 = (btrfs_filesystem*)((uint8_t*)bfs2 + bfs2->next_entry); else break; } @@ -500,7 +501,7 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { name += L", "; } - format_size(device_list[i].size, size, sizeof(size) / sizeof(WCHAR), FALSE); + format_size(device_list[i].size, size, false); name += size; name += L")"; @@ -510,10 +511,8 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { tis.itemex.lParam = (LPARAM)&device_list[i]; item = (HTREEITEM)SendMessageW(tree, TVM_INSERTITEMW, 0, (LPARAM)&tis); - if (!item) { - MessageBoxW(hwnd, L"TVM_INSERTITEM failed", L"Error", MB_ICONERROR); - return; - } + if (!item) + throw string_error(IDS_TVM_INSERTITEM_FAILED); if (device_list[i].part_num == 0) { diskitem = item; @@ -524,12 +523,11 @@ void BtrfsDeviceAdd::populate_device_tree(HWND tree) { } void BtrfsDeviceAdd::AddDevice(HWND hwndDlg) { - WCHAR mess[255], title[255]; + wstring mess, title; NTSTATUS Status; UNICODE_STRING vn; OBJECT_ATTRIBUTES attr; IO_STATUS_BLOCK iosb; - HANDLE h, h2; if (!sel) { EndDialog(hwndDlg, 0); @@ -537,154 +535,123 @@ void BtrfsDeviceAdd::AddDevice(HWND hwndDlg) { } if (sel->fstype != L"") { - WCHAR s[255]; + wstring s; - if (!LoadStringW(module, IDS_ADD_DEVICE_CONFIRMATION_FS, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, IDS_ADD_DEVICE_CONFIRMATION_FS, s)) + throw last_error(GetLastError()); - if (StringCchPrintfW(mess, sizeof(mess) / sizeof(WCHAR), s, sel->fstype.c_str()) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(mess, s, sel->fstype.c_str()); } else { - if (!LoadStringW(module, IDS_ADD_DEVICE_CONFIRMATION, mess, sizeof(mess) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; + if (!load_string(module, IDS_ADD_DEVICE_CONFIRMATION, mess)) + throw last_error(GetLastError()); + } + + if (!load_string(module, IDS_CONFIRMATION_TITLE, title)) + throw last_error(GetLastError()); + + if (MessageBoxW(hwndDlg, mess.c_str(), title.c_str(), MB_YESNO) != IDYES) + return; + + win_handle h = CreateFileW(cmdline, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + { + nt_handle h2; + + vn.Length = vn.MaximumLength = (uint16_t)(sel->pnp_name.length() * sizeof(WCHAR)); + vn.Buffer = (WCHAR*)sel->pnp_name.c_str(); + + InitializeObjectAttributes(&attr, &vn, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr); + + Status = NtOpenFile(&h2, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (!sel->is_disk) { + Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_LOCK_VOLUME, nullptr, 0, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_LOCK_FAILED, Status); + } + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_ADD_DEVICE, &h2, sizeof(HANDLE), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (!sel->is_disk) { + Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_DISMOUNT_VOLUME, nullptr, 0, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_UNLOCK_VOLUME, nullptr, 0, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); } } - if (!LoadStringW(module, IDS_CONFIRMATION_TITLE, title, sizeof(title) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - - if (MessageBoxW(hwndDlg, mess, title, MB_YESNO) != IDYES) - return; - - h = CreateFileW(cmdline, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - - if (h == INVALID_HANDLE_VALUE) { - ShowError(hwndDlg, GetLastError()); - return; - } - - vn.Length = vn.MaximumLength = sel->pnp_name.length() * sizeof(WCHAR); - vn.Buffer = (WCHAR*)sel->pnp_name.c_str(); - - InitializeObjectAttributes(&attr, &vn, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); - - Status = NtOpenFile(&h2, FILE_GENERIC_READ | FILE_GENERIC_WRITE, &attr, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_ALERT); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } - - if (!sel->is_disk) { - Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0); - if (!NT_SUCCESS(Status)) { - WCHAR t[255], u[255]; - - if (!LoadStringW(module, IDS_LOCK_FAILED, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, Status) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - - if (!LoadStringW(module, IDS_ERROR, title, sizeof(title) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - - MessageBoxW(hwndDlg, u, title, MB_ICONERROR); - - NtClose(h2); - CloseHandle(h); - return; - } - } - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_ADD_DEVICE, &h2, sizeof(HANDLE), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - NtClose(h2); - CloseHandle(h); - return; - } - - if (!sel->is_disk) { - Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0); - if (!NT_SUCCESS(Status)) - ShowNtStatusError(hwndDlg, Status); - - Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0); - if (!NT_SUCCESS(Status)) - ShowNtStatusError(hwndDlg, Status); - } - - NtClose(h2); - CloseHandle(h); - EndDialog(hwndDlg, 0); } INT_PTR CALLBACK BtrfsDeviceAdd::DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - populate_device_tree(GetDlgItem(hwndDlg, IDC_DEVICE_TREE)); - EnableWindow(GetDlgItem(hwndDlg, IDOK), FALSE); - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - AddDevice(hwndDlg); - return TRUE; - - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; - } + try { + switch (uMsg) { + case WM_INITDIALOG: + { + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + populate_device_tree(GetDlgItem(hwndDlg, IDC_DEVICE_TREE)); + EnableWindow(GetDlgItem(hwndDlg, IDOK), false); break; } - break; - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case TVN_SELCHANGEDW: - { - NMTREEVIEWW* nmtv = (NMTREEVIEWW*)lParam; - TVITEMW tvi; - BOOL enable = FALSE; + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + AddDevice(hwndDlg); + return true; - RtlZeroMemory(&tvi, sizeof(TVITEMW)); - tvi.hItem = nmtv->itemNew.hItem; - tvi.mask = TVIF_PARAM | TVIF_HANDLE; - - if (SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_TREE), TVM_GETITEMW, 0, (LPARAM)&tvi)) - sel = tvi.lParam == 0 ? NULL : (device*)tvi.lParam; - else - sel = NULL; - - if (sel) - enable = (!sel->is_disk || !sel->has_parts) && !sel->multi_device; - - EnableWindow(GetDlgItem(hwndDlg, IDOK), enable); + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; + } break; } - } - break; + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case TVN_SELCHANGEDW: + { + NMTREEVIEWW* nmtv = (NMTREEVIEWW*)lParam; + TVITEMW tvi; + bool enable = false; + + RtlZeroMemory(&tvi, sizeof(TVITEMW)); + tvi.hItem = nmtv->itemNew.hItem; + tvi.mask = TVIF_PARAM | TVIF_HANDLE; + + if (SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_TREE), TVM_GETITEMW, 0, (LPARAM)&tvi)) + sel = tvi.lParam == 0 ? nullptr : (device*)tvi.lParam; + else + sel = nullptr; + + if (sel) + enable = (!sel->is_disk || !sel->has_parts) && !sel->multi_device; + + EnableWindow(GetDlgItem(hwndDlg, IDOK), enable); + break; + } + } + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -700,7 +667,7 @@ static INT_PTR CALLBACK stub_DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wP if (bda) return bda->DeviceAddDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } void BtrfsDeviceAdd::ShowDialog() { @@ -712,182 +679,174 @@ BtrfsDeviceAdd::BtrfsDeviceAdd(HINSTANCE hinst, HWND hwnd, WCHAR* cmdline) { this->hwnd = hwnd; this->cmdline = cmdline; - sel = NULL; + sel = nullptr; } void BtrfsDeviceResize::do_resize(HWND hwndDlg) { - HANDLE h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_resize br; - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + { + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h == INVALID_HANDLE_VALUE) { - ShowError(hwndDlg, GetLastError()); - return; + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + br.device = dev_id; + br.size = new_size; + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESIZE, &br, sizeof(btrfs_resize), nullptr, 0); + + if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status)) + throw ntstatus_error(Status); } - br.device = dev_id; - br.size = new_size; - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESIZE, &br, sizeof(btrfs_resize), NULL, 0); - - if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } - - CloseHandle(h); - if (Status != STATUS_MORE_PROCESSING_REQUIRED) { - WCHAR s[255], t[255], u[255]; + wstring s, t, u; - LoadStringW(module, IDS_RESIZE_SUCCESSFUL, s, sizeof(s) / sizeof(WCHAR)); - format_size(new_size, u, sizeof(u) / sizeof(WCHAR), TRUE); - StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, dev_id, u); - MessageBoxW(hwndDlg, t, L"", MB_OK); + load_string(module, IDS_RESIZE_SUCCESSFUL, s); + format_size(new_size, u, true); + wstring_sprintf(t, s, dev_id, u.c_str()); + MessageBoxW(hwndDlg, t.c_str(), L"", MB_OK); EndDialog(hwndDlg, 0); } else { - BtrfsBalance* bb; HWND par; par = GetParent(hwndDlg); EndDialog(hwndDlg, 0); - bb = new BtrfsBalance(fn, FALSE, TRUE); - - bb->ShowBalance(par); - - delete bb; + BtrfsBalance bb(fn, false, true); + bb.ShowBalance(par); } } INT_PTR CALLBACK BtrfsDeviceResize::DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - HANDLE h; - WCHAR s[255], t[255], u[255]; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + win_handle h; + WCHAR s[255]; + wstring t, u; - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - GetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, s, sizeof(s) / sizeof(WCHAR)); - StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, dev_id); - SetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, t); + GetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, s, sizeof(s) / sizeof(WCHAR)); + wstring_sprintf(t, s, dev_id); + SetDlgItemTextW(hwndDlg, IDC_RESIZE_DEVICE_ID, t.c_str()); - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - btrfs_device *devices, *bd; - ULONG devsize; - BOOL found = FALSE; - HWND slider; + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + btrfs_device *devices, *bd; + ULONG devsize; + bool found = false; + HWND slider; - devsize = 1024; - devices = (btrfs_device*)malloc(devsize); + devsize = 1024; + devices = (btrfs_device*)malloc(devsize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); - if (Status == STATUS_BUFFER_OVERFLOW) { - devsize += 1024; + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); + if (Status == STATUS_BUFFER_OVERFLOW) { + devsize += 1024; + free(devices); + devices = (btrfs_device*)malloc(devsize); + } else + break; + } + + if (!NT_SUCCESS(Status)) { free(devices); - devices = (btrfs_device*)malloc(devsize); - } else - break; - } - - if (!NT_SUCCESS(Status)) { - free(devices); - CloseHandle(h); - return FALSE; - } - - bd = devices; - - while (TRUE) { - if (bd->dev_id == dev_id) { - memcpy(&dev_info, bd, sizeof(btrfs_device)); - found = TRUE; - break; + return false; } - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); - else - break; - } + bd = devices; - if (!found) { - free(devices); - CloseHandle(h); - return FALSE; - } + while (true) { + if (bd->dev_id == dev_id) { + memcpy(&dev_info, bd, sizeof(btrfs_device)); + found = true; + break; + } - free(devices); - CloseHandle(h); - - GetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, s, sizeof(s) / sizeof(WCHAR)); - format_size(dev_info.size, u, sizeof(u) / sizeof(WCHAR), TRUE); - StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, u); - SetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, t); - - new_size = dev_info.size; - - GetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, new_size_text, sizeof(new_size_text) / sizeof(WCHAR)); - StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), new_size_text, u); - SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t); - - slider = GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER); - SendMessageW(slider, TBM_SETRANGEMIN, FALSE, 0); - SendMessageW(slider, TBM_SETRANGEMAX, FALSE, dev_info.max_size / 1048576); - SendMessageW(slider, TBM_SETPOS, TRUE, new_size / 1048576); - } else - return FALSE; - - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - do_resize(hwndDlg); - return TRUE; - - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; + if (bd->next_entry > 0) + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); + else + break; } + + if (!found) { + free(devices); + return false; + } + + free(devices); + + GetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, s, sizeof(s) / sizeof(WCHAR)); + format_size(dev_info.size, u, true); + wstring_sprintf(t, s, u.c_str()); + SetDlgItemTextW(hwndDlg, IDC_RESIZE_CURSIZE, t.c_str()); + + new_size = dev_info.size; + + GetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, new_size_text, sizeof(new_size_text) / sizeof(WCHAR)); + wstring_sprintf(t, new_size_text, u.c_str()); + SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t.c_str()); + + slider = GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER); + SendMessageW(slider, TBM_SETRANGEMIN, false, 0); + SendMessageW(slider, TBM_SETRANGEMAX, false, (LPARAM)(dev_info.max_size / 1048576)); + SendMessageW(slider, TBM_SETPOS, true, (LPARAM)(new_size / 1048576)); + } else + return false; + break; } - break; - case WM_HSCROLL: - { - WCHAR t[255], u[255]; - - new_size = UInt32x32To64(SendMessageW(GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER), TBM_GETPOS, 0, 0), 1048576); - - format_size(new_size, u, sizeof(u) / sizeof(WCHAR), TRUE); - StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), new_size_text, u); - SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t); - - EnableWindow(GetDlgItem(hwndDlg, IDOK), new_size > 0 ? TRUE : FALSE); + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + do_resize(hwndDlg); + return true; + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; + } + break; + } break; + + case WM_HSCROLL: + { + wstring t, u; + + new_size = UInt32x32To64(SendMessageW(GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER), TBM_GETPOS, 0, 0), 1048576); + + format_size(new_size, u, true); + wstring_sprintf(t, new_size_text, u.c_str()); + SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t.c_str()); + + EnableWindow(GetDlgItem(hwndDlg, IDOK), new_size > 0 ? true : false); + + break; + } } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -902,12 +861,12 @@ static INT_PTR CALLBACK stub_DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM if (bdr) return bdr->DeviceResizeDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } -void BtrfsDeviceResize::ShowDialog(HWND hwnd, WCHAR* fn, UINT64 dev_id) { +void BtrfsDeviceResize::ShowDialog(HWND hwnd, const wstring& fn, uint64_t dev_id) { this->dev_id = dev_id; - wcscpy(this->fn, fn); + this->fn = fn; DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_RESIZE), hwnd, stub_DeviceResizeDlgProc, (LPARAM)this); } @@ -917,163 +876,135 @@ extern "C" { #endif void CALLBACK AddDeviceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE token; - TOKEN_PRIVILEGES tp; - LUID luid; - BtrfsDeviceAdd* bda; + try { + win_handle token; + TOKEN_PRIVILEGES tp; + LUID luid; - set_dpi_aware(); + set_dpi_aware(); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + BtrfsDeviceAdd bda(hinst, hwnd, lpszCmdLine); + bda.ShowDialog(); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - bda = new BtrfsDeviceAdd(hinst, hwnd, lpszCmdLine); - bda->ShowDialog(); - delete bda; - -end: - CloseHandle(token); } void CALLBACK RemoveDeviceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - WCHAR *s, *vol, *dev; - UINT64 devid; - HANDLE h, token; - TOKEN_PRIVILEGES tp; - LUID luid; - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - BtrfsBalance* bb; + try { + WCHAR *s, *vol, *dev; + uint64_t devid; + win_handle h, token; + TOKEN_PRIVILEGES tp; + LUID luid; + NTSTATUS Status; + IO_STATUS_BLOCK iosb; - set_dpi_aware(); + set_dpi_aware(); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + s = wcsstr(lpszCmdLine, L"|"); + if (!s) + return; + + s[0] = 0; + + vol = lpszCmdLine; + dev = &s[1]; + + devid = _wtoi(dev); + if (devid == 0) + return; + + h = CreateFileW(vol, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_REMOVE_DEVICE, &devid, sizeof(uint64_t), nullptr, 0); + if (!NT_SUCCESS(Status)) { + if (Status == STATUS_CANNOT_DELETE) + throw string_error(IDS_CANNOT_REMOVE_RAID); + else + throw ntstatus_error(Status); + + return; + } + + BtrfsBalance bb(vol, true); + bb.ShowBalance(hwnd); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - s = wcsstr(lpszCmdLine, L"|"); - if (!s) - goto end; - - s[0] = 0; - - vol = lpszCmdLine; - dev = &s[1]; - - devid = _wtoi(dev); - if (devid == 0) - goto end; - - h = CreateFileW(vol, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - - if (h == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - goto end; - } - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_REMOVE_DEVICE, &devid, sizeof(UINT64), NULL, 0); - if (!NT_SUCCESS(Status)) { - if (Status == STATUS_CANNOT_DELETE) - ShowStringError(hwnd, IDS_CANNOT_REMOVE_RAID); - else - ShowNtStatusError(hwnd, Status); - - CloseHandle(h); - goto end; - } - - CloseHandle(h); - - bb = new BtrfsBalance(vol, TRUE); - - bb->ShowBalance(hwnd); - - delete bb; - -end: - CloseHandle(token); } void CALLBACK ResizeDeviceW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - WCHAR *s, *vol, *dev; - UINT64 devid; - HANDLE token; - TOKEN_PRIVILEGES tp; - LUID luid; - BtrfsDeviceResize* bdr; + try { + WCHAR *s, *vol, *dev; + uint64_t devid; + win_handle token; + TOKEN_PRIVILEGES tp; + LUID luid; - set_dpi_aware(); + set_dpi_aware(); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + s = wcsstr(lpszCmdLine, L"|"); + if (!s) + return; + + s[0] = 0; + + vol = lpszCmdLine; + dev = &s[1]; + + devid = _wtoi(dev); + if (devid == 0) + return; + + BtrfsDeviceResize bdr; + bdr.ShowDialog(hwnd, vol, devid); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - s = wcsstr(lpszCmdLine, L"|"); - if (!s) - goto end; - - s[0] = 0; - - vol = lpszCmdLine; - dev = &s[1]; - - devid = _wtoi(dev); - if (devid == 0) - goto end; - - bdr = new BtrfsDeviceResize; - bdr->ShowDialog(hwnd, vol, devid); - delete bdr; - -end: - CloseHandle(token); } #ifdef __cplusplus diff --git a/dll/shellext/shellbtrfs/devices.h b/dll/shellext/shellbtrfs/devices.h index e6b949abd91..cc5724c9bfe 100644 --- a/dll/shellext/shellbtrfs/devices.h +++ b/dll/shellext/shellbtrfs/devices.h @@ -28,8 +28,6 @@ #include #endif #include -#include -#include #ifndef __REACTOS__ #include "../btrfsioctl.h" #else @@ -37,27 +35,27 @@ #endif typedef struct { - std::wstring pnp_name; - std::wstring friendly_name; - std::wstring drive; - std::wstring fstype; + wstring pnp_name; + wstring friendly_name; + wstring drive; + wstring fstype; ULONG disk_num; ULONG part_num; - UINT64 size; - BOOL has_parts; + uint64_t size; + bool has_parts; BTRFS_UUID fs_uuid; BTRFS_UUID dev_uuid; - BOOL ignore; - BOOL multi_device; - BOOL is_disk; + bool ignore; + bool multi_device; + bool is_disk; } device; typedef struct { const WCHAR* name; const char* magic; ULONG magiclen; - UINT32 sboff; - UINT32 kboff; + uint32_t sboff; + uint32_t kboff; } fs_identifier; // This list is compiled from information in libblkid, part of util-linux @@ -135,7 +133,7 @@ const static fs_identifier fs_ident[] = { { L"FAT", "\353", 1, 0, 0 }, { L"FAT", "\351", 1, 0, 0}, { L"FAT", "\125\252", 2, 0x1fe, 0 }, - { NULL, 0, 0, 0 } + { nullptr, 0, 0, 0 } }; class BtrfsDeviceAdd { @@ -152,18 +150,19 @@ private: HWND hwnd; WCHAR* cmdline; device* sel; - std::vector device_list; + vector device_list; }; class BtrfsDeviceResize { public: INT_PTR CALLBACK DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - void ShowDialog(HWND hwnd, WCHAR* fn, UINT64 dev_id); + void ShowDialog(HWND hwnd, const wstring& fn, uint64_t dev_id); private: void do_resize(HWND hwndDlg); - UINT64 dev_id, new_size; - WCHAR fn[MAX_PATH], new_size_text[255]; + uint64_t dev_id, new_size; + wstring fn; + WCHAR new_size_text[255]; btrfs_device dev_info; }; diff --git a/dll/shellext/shellbtrfs/factory.cpp b/dll/shellext/shellbtrfs/factory.cpp index 90083592caa..e5a5455f232 100644 --- a/dll/shellext/shellbtrfs/factory.cpp +++ b/dll/shellext/shellbtrfs/factory.cpp @@ -27,7 +27,7 @@ HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) { if (iid == IID_IUnknown || iid == IID_IClassFactory) { *ppv = static_cast(this); } else { - *ppv = NULL; + *ppv = nullptr; return E_NOINTERFACE; } @@ -89,6 +89,6 @@ HRESULT __stdcall Factory::CreateInstance(IUnknown* pUnknownOuter, const IID& ii break; } - *ppv = NULL; + *ppv = nullptr; return E_NOINTERFACE; } diff --git a/dll/shellext/shellbtrfs/iconoverlay.cpp b/dll/shellext/shellbtrfs/iconoverlay.cpp index cfc312c78eb..6cfbe4b6492 100644 --- a/dll/shellext/shellbtrfs/iconoverlay.cpp +++ b/dll/shellext/shellbtrfs/iconoverlay.cpp @@ -39,17 +39,16 @@ HRESULT __stdcall BtrfsIconOverlay::QueryInterface(REFIID riid, void **ppObj) { return S_OK; } - *ppObj = NULL; + *ppObj = nullptr; return E_NOINTERFACE; } HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) { - WCHAR dllpath[MAX_PATH]; + if (GetModuleFileNameW(module, pwszIconFile, cchMax) == 0) + return E_FAIL; - GetModuleFileNameW(module, dllpath, sizeof(dllpath)); - - if ((size_t)cchMax < wcslen(dllpath)) - return E_INVALIDARG; + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + return E_FAIL; if (!pIndex) return E_INVALIDARG; @@ -57,7 +56,6 @@ HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMa if (!pdwFlags) return E_INVALIDARG; - wcscpy(pwszIconFile, dllpath); *pIndex = 0; *pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX; @@ -74,24 +72,20 @@ HRESULT __stdcall BtrfsIconOverlay::GetPriority(int *pPriority) { } HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) { - HANDLE h; + win_handle h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; - h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) return S_FALSE; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); - if (!NT_SUCCESS(Status)) { - CloseHandle(h); + if (!NT_SUCCESS(Status)) return S_FALSE; - } - - CloseHandle(h); return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE; } diff --git a/dll/shellext/shellbtrfs/main.cpp b/dll/shellext/shellbtrfs/main.cpp index a7ac6a2cc05..92f4c5b710f 100644 --- a/dll/shellext/shellbtrfs/main.cpp +++ b/dll/shellext/shellbtrfs/main.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "factory.h" #include "resource.h" @@ -46,68 +47,6 @@ typedef HRESULT (WINAPI *_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value); HMODULE module; LONG objs_loaded = 0; -void ShowError(HWND hwnd, ULONG err) { - WCHAR* buf; - - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - err, 0, (WCHAR*)&buf, 0, NULL) == 0) { - MessageBoxW(hwnd, L"FormatMessage failed", L"Error", MB_ICONERROR); - return; - } - - MessageBoxW(hwnd, buf, L"Error", MB_ICONERROR); - - LocalFree(buf); -} - -void ShowStringError(HWND hwndDlg, int num, ...) { - WCHAR title[255], s[1024], t[1024]; - va_list ap; - - if (!LoadStringW(module, IDS_ERROR, title, sizeof(title) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - - if (!LoadStringW(module, num, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - - va_start(ap, num); -#ifndef __REACTOS__ - vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#else - vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#endif - - MessageBoxW(hwndDlg, t, title, MB_ICONERROR); - - va_end(ap); -} - -void ShowNtStatusError(HWND hwnd, NTSTATUS Status) { - _RtlNtStatusToDosError RtlNtStatusToDosError; - HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); - - if (!ntdll) { - MessageBoxW(hwnd, L"Error loading ntdll.dll", L"Error", MB_ICONERROR); - return; - } - - RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); - - if (!RtlNtStatusToDosError) { - MessageBoxW(hwnd, L"Error loading RtlNtStatusToDosError in ntdll.dll", L"Error", MB_ICONERROR); - FreeLibrary(ntdll); - return; - } - - ShowError(hwnd, RtlNtStatusToDosError(Status)); - - FreeLibrary(ntdll); -} - void set_dpi_aware() { _SetProcessDpiAwareness SetProcessDpiAwareness; HMODULE shcore = LoadLibraryW(L"shcore.dll"); @@ -123,21 +62,31 @@ void set_dpi_aware() { SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE); } -void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes) { - WCHAR nb[255], nb2[255], t[255], bytes[255]; - WCHAR kb[255]; +void format_size(uint64_t size, wstring& s, bool show_bytes) { + wstring t, bytes, kb, nb; + WCHAR nb2[255]; ULONG sr; float f; NUMBERFMTW fmt; - WCHAR thou[4], grouping[64], *c; + WCHAR dec[2], thou[4], grouping[64], *c; +#ifdef __REACTOS__ + WCHAR buffer[64]; +#endif - _i64tow(size, nb, 10); +#ifndef __REACTOS__ + nb = to_wstring(size); +#else + swprintf(buffer, L"%I64d", size); + nb = wstring(buffer); +#endif GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thou, sizeof(thou) / sizeof(WCHAR)); + dec[0] = '.'; dec[1] = 0; // not used, but silences gcc warning + fmt.NumDigits = 0; fmt.LeadingZero = 1; - fmt.lpDecimalSep = (LPWSTR)L"."; // not used + fmt.lpDecimalSep = dec; fmt.lpThousandSep = thou; fmt.NegativeOrder = 0; @@ -161,32 +110,21 @@ void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes) { else fmt.Grouping *= 10; - GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb, &fmt, nb2, sizeof(nb2) / sizeof(WCHAR)); + GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb.c_str(), &fmt, nb2, sizeof(nb2) / sizeof(WCHAR)); if (size < 1024) { - if (!LoadStringW(module, size == 1 ? IDS_SIZE_BYTE : IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(NULL, GetLastError()); - return; - } - - if (StringCchPrintfW(s, len, t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); - return; - } + if (!load_string(module, size == 1 ? IDS_SIZE_BYTE : IDS_SIZE_BYTES, t)) + throw last_error(GetLastError()); + wstring_sprintf(s, t, nb2); return; } if (show_bytes) { - if (!LoadStringW(module, IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(NULL, GetLastError()); - return; - } + if (!load_string(module, IDS_SIZE_BYTES, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(bytes, sizeof(bytes) / sizeof(WCHAR), t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); - return; - } + wstring_sprintf(bytes, t, nb2); } if (size >= 1152921504606846976) { @@ -209,40 +147,26 @@ void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes) { f = (float)size / 1024.0f; } - if (!LoadStringW(module, sr, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(NULL, GetLastError()); - return; - } + if (!load_string(module, sr, t)) + throw last_error(GetLastError()); if (show_bytes) { - if (StringCchPrintfW(kb, sizeof(kb) / sizeof(WCHAR), t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); - return; - } + wstring_sprintf(kb, t, f); - if (!LoadStringW(module, IDS_SIZE_LARGE, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(NULL, GetLastError()); - return; - } + if (!load_string(module, IDS_SIZE_LARGE, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(s, len, t, kb, bytes) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); - return; - } - } else { - if (StringCchPrintfW(s, len, t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(NULL, ERROR_INSUFFICIENT_BUFFER); - return; - } - } + wstring_sprintf(s, t, kb.c_str(), bytes.c_str()); + } else + wstring_sprintf(s, t, f); } -std::wstring format_message(ULONG last_error) { +wstring format_message(ULONG last_error) { WCHAR* buf; - std::wstring s; + wstring s; - if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - last_error, 0, (WCHAR*)&buf, 0, NULL) == 0) { + if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + last_error, 0, (WCHAR*)&buf, 0, nullptr) == 0) { return L"(error retrieving message)"; } @@ -257,9 +181,9 @@ std::wstring format_message(ULONG last_error) { return s; } -std::wstring format_ntstatus(NTSTATUS Status) { +wstring format_ntstatus(NTSTATUS Status) { _RtlNtStatusToDosError RtlNtStatusToDosError; - std::wstring s; + wstring s; HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); if (!ntdll) @@ -279,15 +203,51 @@ std::wstring format_ntstatus(NTSTATUS Status) { return s; } -#ifdef __cplusplus -extern "C" { +bool load_string(HMODULE module, UINT id, wstring& s) { + int len; + LPWSTR retstr = nullptr; + + len = LoadStringW(module, id, (LPWSTR)&retstr, 0); + + if (len == 0) + return false; + + s = wstring(retstr, len); + + return true; +} + +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4996) #endif -STDAPI DllCanUnloadNow(void) { +void wstring_sprintf(wstring& s, wstring fmt, ...) { + int len; + va_list args; + + va_start(args, fmt); + len = _vsnwprintf(nullptr, 0, fmt.c_str(), args); + + if (len == 0) + s = L""; + else { + s.resize(len); + _vsnwprintf((wchar_t*)s.c_str(), len, fmt.c_str(), args); + } + + va_end(args); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +extern "C" STDAPI DllCanUnloadNow(void) { return objs_loaded == 0 ? S_OK : S_FALSE; } -STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { +extern "C" STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { if (rclsid == CLSID_ShellBtrfsIconHandler) { Factory* fact = new Factory; if (!fact) @@ -329,312 +289,244 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { return CLASS_E_CLASSNOTAVAILABLE; } -static BOOL write_reg_key(HKEY root, const WCHAR* keyname, const WCHAR* val, DWORD type, const BYTE* data, DWORD datasize) { +static void write_reg_key(HKEY root, const wstring& keyname, const WCHAR* val, const wstring& data) { LONG l; HKEY hk; DWORD dispos; - l = RegCreateKeyExW(root, keyname, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dispos); - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegCreateKey returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); + l = RegCreateKeyExW(root, keyname.c_str(), 0, nullptr, 0, KEY_ALL_ACCESS, nullptr, &hk, &dispos); + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGCREATEKEY_FAILED, l); - return FALSE; - } - - l = RegSetValueExW(hk, val, 0, type, data, datasize); - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegSetValueEx returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - return FALSE; - } + l = RegSetValueExW(hk, val, 0, REG_SZ, (const BYTE*)data.c_str(), (data.length() + 1) * sizeof(WCHAR)); + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGSETVALUEEX_FAILED, l); l = RegCloseKey(hk); - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegCloseKey returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - return FALSE; - } - - return TRUE; + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGCLOSEKEY_FAILED, l); } -static BOOL register_clsid(const GUID clsid, const WCHAR* description) { +static void register_clsid(const GUID clsid, const WCHAR* description) { WCHAR* clsidstring; - WCHAR inproc[MAX_PATH], progid[MAX_PATH], clsidkeyname[MAX_PATH], dllpath[MAX_PATH]; - BOOL ret = FALSE; + wstring inproc, progid, clsidkeyname; + WCHAR dllpath[MAX_PATH]; StringFromCLSID(clsid, &clsidstring); - wsprintfW(inproc, L"CLSID\\%s\\InprocServer32", clsidstring); - wsprintfW(progid, L"CLSID\\%s\\ProgId", clsidstring); - wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); + try { +#ifndef __REACTOS__ + inproc = L"CLSID\\"s + clsidstring + L"\\InprocServer32"s; + progid = L"CLSID\\"s + clsidstring + L"\\ProgId"s; + clsidkeyname = L"CLSID\\"s + clsidstring; +#else + inproc = wstring(L"CLSID\\") + clsidstring + wstring(L"\\InprocServer32"); + progid = wstring(L"CLSID\\") + clsidstring + wstring(L"\\ProgId"); + clsidkeyname = wstring(L"CLSID\\") + clsidstring; +#endif - if (!write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, NULL, REG_SZ, (BYTE*)description, (wcslen(description) + 1) * sizeof(WCHAR))) - goto end; + write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, nullptr, description); - GetModuleFileNameW(module, dllpath, sizeof(dllpath)); + GetModuleFileNameW(module, dllpath, sizeof(dllpath)); - if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, NULL, REG_SZ, (BYTE*)dllpath, (wcslen(dllpath) + 1) * sizeof(WCHAR))) - goto end; + write_reg_key(HKEY_CLASSES_ROOT, inproc, nullptr, dllpath); - if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", REG_SZ, (BYTE*)L"Apartment", (wcslen(L"Apartment") + 1) * sizeof(WCHAR))) - goto end; - - ret = TRUE; - -end: - CoTaskMemFree(clsidstring); - - return ret; -} - -static BOOL unregister_clsid(const GUID clsid) { - WCHAR* clsidstring; - WCHAR clsidkeyname[MAX_PATH]; - BOOL ret = FALSE; - LONG l; - - StringFromCLSID(clsid, &clsidstring); - wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); - - l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname); - - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegDeleteTree returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - ret = FALSE; - } else - ret = TRUE; + write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", L"Apartment"); + } catch (...) { + CoTaskMemFree(clsidstring); + throw; + } CoTaskMemFree(clsidstring); - - return ret; } -static BOOL reg_icon_overlay(const GUID clsid, const WCHAR* name) { - WCHAR path[MAX_PATH]; +static void unregister_clsid(const GUID clsid) { WCHAR* clsidstring; - BOOL ret = FALSE; StringFromCLSID(clsid, &clsidstring); - wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"); - wcscat(path, name); + try { + WCHAR clsidkeyname[MAX_PATH]; - if (!write_reg_key(HKEY_LOCAL_MACHINE, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) - goto end; + wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring); - ret = TRUE; + LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname); + + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGDELETETREE_FAILED, l); + } catch (...) { + CoTaskMemFree(clsidstring); + throw; + } -end: CoTaskMemFree(clsidstring); - - return ret; } -static BOOL unreg_icon_overlay(const WCHAR* name) { - WCHAR path[MAX_PATH]; - LONG l; - - wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"); - wcscat(path, name); - - l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path); - - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegDeleteTree returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - return FALSE; - } else - return TRUE; -} - -static BOOL reg_context_menu_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) { - WCHAR path[MAX_PATH]; +static void reg_icon_overlay(const GUID clsid, const wstring& name) { WCHAR* clsidstring; - BOOL ret = FALSE; StringFromCLSID(clsid, &clsidstring); - wcscpy(path, filetype); - wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\"); - wcscat(path, name); + try { +#ifndef __REACTOS__ + wstring path = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name; +#else + wstring path = wstring(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\") + name; +#endif - if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) - goto end; + write_reg_key(HKEY_LOCAL_MACHINE, path, nullptr, clsidstring); + } catch (...) { + CoTaskMemFree(clsidstring); + throw; + } - ret = TRUE; - -end: CoTaskMemFree(clsidstring); - - return ret; } -static BOOL unreg_context_menu_handler(const WCHAR* filetype, const WCHAR* name) { - WCHAR path[MAX_PATH]; - LONG l; +static void unreg_icon_overlay(const wstring& name) { +#ifndef __REACTOS__ + wstring path = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\"s + name; +#else + wstring path = wstring(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\") + name; +#endif - wcscpy(path, filetype); - wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\"); - wcscat(path, name); + LONG l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path.c_str()); - l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path); - - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegDeleteTree returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - return FALSE; - } else - return TRUE; + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGDELETETREE_FAILED, l); } -static BOOL reg_prop_sheet_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) { - WCHAR path[MAX_PATH]; +static void reg_context_menu_handler(const GUID clsid, const wstring& filetype, const wstring& name) { WCHAR* clsidstring; - BOOL ret = FALSE; StringFromCLSID(clsid, &clsidstring); - wcscpy(path, filetype); - wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\"); - wcscat(path, name); + try { +#ifndef __REACTOS__ + wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name; +#else + wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name; +#endif - if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR))) - goto end; - - ret = TRUE; - -end: - CoTaskMemFree(clsidstring); - - return ret; + write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring); + } catch (...) { + CoTaskMemFree(clsidstring); + throw; + } } -static BOOL unreg_prop_sheet_handler(const WCHAR* filetype, const WCHAR* name) { - WCHAR path[MAX_PATH]; - LONG l; +static void unreg_context_menu_handler(const wstring& filetype, const wstring& name) { +#ifndef __REACTOS__ + wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name; +#else + wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name; +#endif - wcscpy(path, filetype); - wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\"); - wcscat(path, name); + LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str()); - l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path); - - if (l != ERROR_SUCCESS) { - WCHAR s[255]; - wsprintfW(s, L"RegDeleteTree returned %08x", l); - MessageBoxW(0, s, NULL, MB_ICONERROR); - - return FALSE; - } else - return TRUE; + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGDELETETREE_FAILED, l); } -STDAPI DllRegisterServer(void) { - if (!register_clsid(CLSID_ShellBtrfsIconHandler, COM_DESCRIPTION_ICON_HANDLER)) - return E_FAIL; +static void reg_prop_sheet_handler(const GUID clsid, const wstring& filetype, const wstring& name) { + WCHAR* clsidstring; - if (!register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU)) - return E_FAIL; + StringFromCLSID(clsid, &clsidstring); - if (!register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET)) - return E_FAIL; + try { +#ifndef __REACTOS__ + wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name; +#else + wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name; +#endif - if (!register_clsid(CLSID_ShellBtrfsVolPropSheet, COM_DESCRIPTION_VOL_PROP_SHEET)) - return E_FAIL; - - if (!reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register icon overlay.", NULL, MB_ICONERROR); - return E_FAIL; + write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring); + } catch (...) { + CoTaskMemFree(clsidstring); + throw; } +} - if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR); - return E_FAIL; - } +static void unreg_prop_sheet_handler(const wstring& filetype, const wstring& name) { +#ifndef __REACTOS__ + wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name; +#else + wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name; +#endif - if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR); - return E_FAIL; - } + LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str()); - if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR); - return E_FAIL; - } + if (l != ERROR_SUCCESS) + throw string_error(IDS_REGDELETETREE_FAILED, l); +} - if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"*", ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR); - return E_FAIL; - } +extern "C" STDAPI DllRegisterServer(void) { + try { + register_clsid(CLSID_ShellBtrfsIconHandler, COM_DESCRIPTION_ICON_HANDLER); + register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU); + register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET); + register_clsid(CLSID_ShellBtrfsVolPropSheet, COM_DESCRIPTION_VOL_PROP_SHEET); - if (!reg_prop_sheet_handler(CLSID_ShellBtrfsVolPropSheet, L"Drive", ICON_OVERLAY_NAME)) { - MessageBoxW(0, L"Failed to register volume property sheet handler.", NULL, MB_ICONERROR); + reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME); + + reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME); + reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME); + + reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME); + reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"*", ICON_OVERLAY_NAME); + reg_prop_sheet_handler(CLSID_ShellBtrfsVolPropSheet, L"Drive", ICON_OVERLAY_NAME); + } catch (const exception& e) { + error_message(nullptr, e.what()); return E_FAIL; } return S_OK; } -STDAPI DllUnregisterServer(void) { - unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME); - unreg_prop_sheet_handler(L"*", ICON_OVERLAY_NAME); - unreg_prop_sheet_handler(L"Drive", ICON_OVERLAY_NAME); - unreg_context_menu_handler(L"Folder", ICON_OVERLAY_NAME); - unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME); - unreg_icon_overlay(ICON_OVERLAY_NAME); +extern "C" STDAPI DllUnregisterServer(void) { + try { + unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME); + unreg_prop_sheet_handler(L"*", ICON_OVERLAY_NAME); + unreg_prop_sheet_handler(L"Drive", ICON_OVERLAY_NAME); + unreg_context_menu_handler(L"Folder", ICON_OVERLAY_NAME); + unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME); + unreg_icon_overlay(ICON_OVERLAY_NAME); - if (!unregister_clsid(CLSID_ShellBtrfsVolPropSheet)) - return E_FAIL; - - if (!unregister_clsid(CLSID_ShellBtrfsPropSheet)) - return E_FAIL; - - if (!unregister_clsid(CLSID_ShellBtrfsContextMenu)) - return E_FAIL; - - if (!unregister_clsid(CLSID_ShellBtrfsIconHandler)) + unregister_clsid(CLSID_ShellBtrfsVolPropSheet); + unregister_clsid(CLSID_ShellBtrfsPropSheet); + unregister_clsid(CLSID_ShellBtrfsContextMenu); + unregister_clsid(CLSID_ShellBtrfsIconHandler); + } catch (const exception& e) { + error_message(nullptr, e.what()); return E_FAIL; + } return S_OK; } -STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { +extern "C" STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { if (bInstall) return DllRegisterServer(); else return DllUnregisterServer(); } -BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { +extern "C" BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) { if (dwReason == DLL_PROCESS_ATTACH) module = (HMODULE)hModule; - return TRUE; + return true; } -static void create_subvol(std::wstring fn) { +static void create_subvol(const wstring& fn) { size_t found = fn.rfind(L"\\"); - std::wstring path, file; - HANDLE h; + wstring path, file; + win_handle h; ULONG bcslen; btrfs_create_subvol* bcs; IO_STATUS_BLOCK iosb; - if (found == std::wstring::npos) { + if (found == wstring::npos) { path = L""; file = fn; } else { @@ -643,7 +535,7 @@ static void create_subvol(std::wstring fn) { } path += L"\\"; - h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (h == INVALID_HANDLE_VALUE) return; @@ -651,40 +543,32 @@ static void create_subvol(std::wstring fn) { bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR)); bcs = (btrfs_create_subvol*)malloc(bcslen); - bcs->readonly = FALSE; - bcs->posix = FALSE; - bcs->namelen = file.length() * sizeof(WCHAR); + bcs->readonly = false; + bcs->posix = false; + bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR)); memcpy(bcs->name, file.c_str(), bcs->namelen); - NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0); - - CloseHandle(h); + NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0); } -void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; +extern "C" void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { + vector args; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + command_line_to_args(lpszCmdLine, args); - if (!args) - return; - - if (num_args >= 1) + if (args.size() >= 1) create_subvol(args[0]); - - LocalFree(args); } -static void create_snapshot2(std::wstring source, std::wstring fn) { +static void create_snapshot2(const wstring& source, const wstring& fn) { size_t found = fn.rfind(L"\\"); - std::wstring path, file; - HANDLE h, src; + wstring path, file; + win_handle h, src; ULONG bcslen; btrfs_create_snapshot* bcs; IO_STATUS_BLOCK iosb; - if (found == std::wstring::npos) { + if (found == wstring::npos) { path = L""; file = fn; } else { @@ -693,47 +577,314 @@ static void create_snapshot2(std::wstring source, std::wstring fn) { } path += L"\\"; - src = CreateFileW(source.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + src = CreateFileW(source.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); if (src == INVALID_HANDLE_VALUE) return; - h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); - if (h == INVALID_HANDLE_VALUE) { - CloseHandle(src); + if (h == INVALID_HANDLE_VALUE) return; - } bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR)); bcs = (btrfs_create_snapshot*)malloc(bcslen); - bcs->readonly = FALSE; - bcs->posix = FALSE; - bcs->namelen = file.length() * sizeof(WCHAR); + bcs->readonly = false; + bcs->posix = false; + bcs->namelen = (uint16_t)(file.length() * sizeof(WCHAR)); memcpy(bcs->name, file.c_str(), bcs->namelen); bcs->subvol = src; - NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, NULL, 0); - - CloseHandle(h); - CloseHandle(src); + NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0); } -void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; +extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { + vector args; + + command_line_to_args(lpszCmdLine, args); + + if (args.size() >= 2) + create_snapshot2(args[0], args[1]); +} + +void command_line_to_args(LPWSTR cmdline, vector args) { + LPWSTR* l; int num_args; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + args.clear(); - if (!args) + l = CommandLineToArgvW(cmdline, &num_args); + + if (!l) return; - if (num_args >= 2) - create_snapshot2(args[0], args[1]); + try { + args.reserve(num_args); - LocalFree(args); + for (unsigned int i = 0; i < (unsigned int)num_args; i++) { + args.push_back(l[i]); + } + } catch (...) { + LocalFree(l); + throw; + } + + LocalFree(l); } -#ifdef __cplusplus +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4996) +#endif + +string_error::string_error(int resno, ...) { + wstring fmt, s; + int len; + va_list args; + + if (!load_string(module, resno, fmt)) + throw runtime_error("LoadString failed."); // FIXME + + va_start(args, resno); + len = _vsnwprintf(nullptr, 0, fmt.c_str(), args); + + if (len == 0) + s = L""; + else { + s.resize(len); + _vsnwprintf((wchar_t*)s.c_str(), len, fmt.c_str(), args); + } + + va_end(args); + + utf16_to_utf8(s, msg); +} + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +void utf8_to_utf16(const string& utf8, wstring& utf16) { + NTSTATUS Status; + ULONG utf16len; + 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()); + + buf = (WCHAR*)malloc(utf16len + 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)) { + free(buf); + throw string_error(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str()); + } + + buf[utf16len / sizeof(WCHAR)] = 0; + + utf16 = 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); +} + +last_error::last_error(DWORD errnum) { + WCHAR* buf; + + if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + errnum, 0, (WCHAR*)&buf, 0, nullptr) == 0) + throw runtime_error("FormatMessage failed"); + + try { + utf16_to_utf8(buf, msg); + } catch (...) { + LocalFree(buf); + throw; + } + + LocalFree(buf); +} + +void error_message(HWND hwnd, const char* msg) { + wstring title, wmsg; + + load_string(module, IDS_ERROR, title); + + utf8_to_utf16(msg, wmsg); + + MessageBoxW(hwnd, wmsg.c_str(), title.c_str(), MB_ICONERROR); +} + +ntstatus_error::ntstatus_error(NTSTATUS Status) { + _RtlNtStatusToDosError RtlNtStatusToDosError; + HMODULE ntdll = LoadLibraryW(L"ntdll.dll"); + WCHAR* buf; + + if (!ntdll) + throw runtime_error("Error loading ntdll.dll."); + + try { + RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError"); + + if (!RtlNtStatusToDosError) + throw runtime_error("Error loading RtlNtStatusToDosError in ntdll.dll."); + + if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + RtlNtStatusToDosError(Status), 0, (WCHAR*)&buf, 0, nullptr) == 0) + throw runtime_error("FormatMessage failed"); + + try { + utf16_to_utf8(buf, msg); + } catch (...) { + LocalFree(buf); + throw; + } + + LocalFree(buf); + } catch (...) { + FreeLibrary(ntdll); + throw; + } + + 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 */ + ASSERT(ch <= 0x10ffff); + 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/propsheet.cpp b/dll/shellext/shellbtrfs/propsheet.cpp index d329e3c02f6..4c3478f9e85 100644 --- a/dll/shellext/shellbtrfs/propsheet.cpp +++ b/dll/shellext/shellbtrfs/propsheet.cpp @@ -50,6 +50,16 @@ typedef struct _FILE_ACCESS_INFORMATION { #define FileAccessInformation (FILE_INFORMATION_CLASS)8 +typedef struct _FILE_STANDARD_INFORMATION { + LARGE_INTEGER AllocationSize; + LARGE_INTEGER EndOfFile; + ULONG NumberOfLinks; + BOOLEAN DeletePending; + BOOLEAN Directory; +} FILE_STANDARD_INFORMATION, *PFILE_STANDARD_INFORMATION; + +#define FileStandardInformation (FILE_INFORMATION_CLASS)5 + #endif #endif @@ -64,91 +74,83 @@ HRESULT __stdcall BtrfsPropSheet::QueryInterface(REFIID riid, void **ppObj) { return S_OK; } - *ppObj = NULL; + *ppObj = nullptr; return E_NOINTERFACE; } -void BtrfsPropSheet::add_to_search_list(WCHAR* fn) { - WCHAR* s; - - s = (WCHAR*)malloc((wcslen(fn) + 1) * sizeof(WCHAR)); - if (!s) - return; - - memcpy(s, fn, (wcslen(fn) + 1) * sizeof(WCHAR)); - - search_list.push_back(s); -} - -void BtrfsPropSheet::do_search(WCHAR* fn) { - HANDLE h; - WCHAR* ss; +void BtrfsPropSheet::do_search(const wstring& fn) { + wstring ss; WIN32_FIND_DATAW ffd; - ss = (WCHAR*)malloc((wcslen(fn) + 3) * sizeof(WCHAR)); - if (!ss) - return; +#ifndef __REACTOS__ + ss = fn + L"\\*"s; +#else + ss = fn + wstring(L"\\*"); +#endif - memcpy(ss, fn, (wcslen(fn) + 1) * sizeof(WCHAR)); - wcscat(ss, L"\\*"); - - h = FindFirstFileW(ss, &ffd); + fff_handle h = FindFirstFileW(ss.c_str(), &ffd); if (h == INVALID_HANDLE_VALUE) return; do { if (ffd.cFileName[0] != '.' || ((ffd.cFileName[1] != 0) && (ffd.cFileName[1] != '.' || ffd.cFileName[2] != 0))) { - WCHAR* fn2 = (WCHAR*)malloc((wcslen(fn) + 1 + wcslen(ffd.cFileName) + 1) * sizeof(WCHAR)); + wstring fn2; - memcpy(fn2, fn, (wcslen(fn) + 1) * sizeof(WCHAR)); - wcscat(fn2, L"\\"); - wcscat(fn2, ffd.cFileName); +#ifndef __REACTOS__ + fn2 = fn + L"\\"s + ffd.cFileName; +#else + fn2 = fn + wstring(L"\\") + ffd.cFileName; +#endif - if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - add_to_search_list(fn2); - } else { - HANDLE fh; - - fh = CreateFileW(fn2, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) + search_list.push_back(fn2); + else { + win_handle fh = CreateFileW(fn2.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (fh != INVALID_HANDLE_VALUE) { NTSTATUS Status; IO_STATUS_BLOCK iosb; - btrfs_inode_info bii2; + btrfs_inode_info2 bii2; - Status = NtFsControlFile(fh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii2, sizeof(btrfs_inode_info)); + memset(&bii2, 0, sizeof(bii2)); + + Status = NtFsControlFile(fh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii2, sizeof(btrfs_inode_info2)); if (NT_SUCCESS(Status)) { sizes[0] += bii2.inline_length; - sizes[1] += bii2.disk_size[0]; - sizes[2] += bii2.disk_size[1]; - sizes[3] += bii2.disk_size[2]; - totalsize += bii2.inline_length + bii2.disk_size[0] + bii2.disk_size[1] + bii2.disk_size[2]; + sizes[1] += bii2.disk_size_uncompressed; + sizes[2] += bii2.disk_size_zlib; + sizes[3] += bii2.disk_size_lzo; + 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; } - CloseHandle(fh); - } + FILE_STANDARD_INFORMATION fsi; - free(fn2); + Status = NtQueryInformationFile(fh, &iosb, &fsi, sizeof(fsi), FileStandardInformation); + + if (NT_SUCCESS(Status)) { + if (bii2.inline_length > 0) + allocsize += fsi.EndOfFile.QuadPart; + else + allocsize += fsi.AllocationSize.QuadPart; + } + } } } } while (FindNextFileW(h, &ffd)); - - FindClose(h); } DWORD BtrfsPropSheet::search_list_thread() { while (!search_list.empty()) { - WCHAR* fn = search_list.front(); - - do_search(fn); + do_search(search_list.front()); search_list.pop_front(); - free(fn); } - thread = NULL; + thread = nullptr; return 0; } @@ -159,25 +161,23 @@ static DWORD WINAPI global_search_list_thread(LPVOID lpParameter) { return bps->search_list_thread(); } -HRESULT BtrfsPropSheet::check_file(std::wstring fn, UINT i, UINT num_files, UINT* sv) { - HANDLE h; +HRESULT BtrfsPropSheet::check_file(const wstring& fn, UINT i, UINT num_files, UINT* sv) { + win_handle h; IO_STATUS_BLOCK iosb; NTSTATUS Status; FILE_ACCESS_INFORMATION fai; BY_HANDLE_FILE_INFORMATION bhfi; - btrfs_inode_info bii2; + btrfs_inode_info2 bii2; - h = CreateFileW(fn.c_str(), MAXIMUM_ALLOWED, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(fn.c_str(), MAXIMUM_ALLOWED, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) return E_FAIL; Status = NtQueryInformationFile(h, &iosb, &fai, sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation); - if (!NT_SUCCESS(Status)) { - CloseHandle(h); + if (!NT_SUCCESS(Status)) return E_FAIL; - } if (fai.AccessFlags & FILE_READ_ATTRIBUTES) can_change_perms = fai.AccessFlags & WRITE_DAC; @@ -185,16 +185,16 @@ HRESULT BtrfsPropSheet::check_file(std::wstring fn, UINT i, UINT num_files, UINT readonly = !(fai.AccessFlags & FILE_WRITE_ATTRIBUTES); if (!readonly && num_files == 1 && !can_change_perms) - show_admin_button = TRUE; + show_admin_button = true; if (GetFileInformationByHandle(h, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - add_to_search_list((WCHAR*)fn.c_str()); + search_list.push_back(fn); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii2, sizeof(btrfs_inode_info)); + memset(&bii2, 0, sizeof(bii2)); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii2, sizeof(btrfs_inode_info2)); if (NT_SUCCESS(Status) && !bii2.top) { - int j; - LARGE_INTEGER filesize; if (i == 0) { @@ -206,19 +206,19 @@ HRESULT BtrfsPropSheet::check_file(std::wstring fn, UINT i, UINT num_files, UINT rdev = bii2.st_rdev; } else { if (subvol != bii2.subvol) - various_subvols = TRUE; + various_subvols = true; if (inode != bii2.inode) - various_inodes = TRUE; + various_inodes = true; if (type != bii2.type) - various_types = TRUE; + various_types = true; if (uid != bii2.st_uid) - various_uids = TRUE; + various_uids = true; if (gid != bii2.st_gid) - various_gids = TRUE; + various_gids = true; } if (bii2.inline_length > 0) { @@ -226,13 +226,40 @@ HRESULT BtrfsPropSheet::check_file(std::wstring fn, UINT i, UINT num_files, UINT sizes[0] += bii2.inline_length; } - for (j = 0; j < 3; j++) { - if (bii2.disk_size[j] > 0) { - totalsize += bii2.disk_size[j]; - sizes[j + 1] += bii2.disk_size[j]; - } + if (bii2.disk_size_uncompressed > 0) { + totalsize += bii2.disk_size_uncompressed; + sizes[1] += bii2.disk_size_uncompressed; } + if (bii2.disk_size_zlib > 0) { + totalsize += bii2.disk_size_zlib; + sizes[2] += bii2.disk_size_zlib; + } + + if (bii2.disk_size_lzo > 0) { + totalsize += bii2.disk_size_lzo; + sizes[3] += bii2.disk_size_lzo; + } + + if (bii2.disk_size_zstd > 0) { + totalsize += bii2.disk_size_zstd; + sizes[4] += bii2.disk_size_zstd; + } + + sparsesize += bii2.sparse_size; + + FILE_STANDARD_INFORMATION fsi; + + Status = NtQueryInformationFile(h, &iosb, &fsi, sizeof(fsi), FileStandardInformation); + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (bii2.inline_length > 0) + allocsize += fsi.EndOfFile.QuadPart; + else + allocsize += fsi.AllocationSize.QuadPart; + min_mode |= ~bii2.st_mode; max_mode |= bii2.st_mode; min_flags |= ~bii2.flags; @@ -241,32 +268,28 @@ HRESULT BtrfsPropSheet::check_file(std::wstring fn, UINT i, UINT num_files, UINT max_compression_type = bii2.compression_type > max_compression_type ? bii2.compression_type : max_compression_type; if (bii2.inode == SUBVOL_ROOT_INODE) { - BOOL ro = bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY; + bool ro = bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY; - has_subvols = TRUE; + has_subvols = true; if (*sv == 0) ro_subvol = ro; else { if (ro_subvol != ro) - various_ro = TRUE; + various_ro = true; } (*sv)++; } - ignore = FALSE; + ignore = false; if (bii2.type != BTRFS_TYPE_DIRECTORY && GetFileSizeEx(h, &filesize)) { if (filesize.QuadPart != 0) - can_change_nocow = FALSE; + can_change_nocow = false; } - - CloseHandle(h); - } else { - CloseHandle(h); + } else return E_FAIL; - } return S_OK; } @@ -275,7 +298,7 @@ HRESULT BtrfsPropSheet::load_file_list() { UINT num_files, i, sv = 0; WCHAR fn[MAX_PATH]; - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); min_mode = 0; max_mode = 0; @@ -283,12 +306,13 @@ HRESULT BtrfsPropSheet::load_file_list() { max_flags = 0; min_compression_type = 0xff; max_compression_type = 0; - various_subvols = various_inodes = various_types = various_uids = various_gids = various_ro = FALSE; + various_subvols = various_inodes = various_types = various_uids = various_gids = various_ro = false; - can_change_perms = TRUE; - can_change_nocow = TRUE; + can_change_perms = true; + can_change_nocow = true; - sizes[0] = sizes[1] = sizes[2] = sizes[3] = 0; + sizes[0] = sizes[1] = sizes[2] = sizes[3] = sizes[4] = 0; + totalsize = allocsize = sparsesize = 0; for (i = 0; i < num_files; i++) { if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(MAX_PATH))) { @@ -314,54 +338,65 @@ HRESULT BtrfsPropSheet::load_file_list() { } HRESULT __stdcall BtrfsPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) { - FORMATETC format = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; - HDROP hdrop; - HRESULT hr; + try { + FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + HDROP hdrop; + HRESULT hr; + + if (pidlFolder) + return E_FAIL; + + if (!pdtobj) + return E_FAIL; + + stgm.tymed = TYMED_HGLOBAL; + + if (FAILED(pdtobj->GetData(&format, &stgm))) + return E_INVALIDARG; + + stgm_set = true; + + hdrop = (HDROP)GlobalLock(stgm.hGlobal); + + if (!hdrop) { + ReleaseStgMedium(&stgm); + stgm_set = false; + return E_INVALIDARG; + } + + try { + hr = load_file_list(); + if (FAILED(hr)) + return hr; + + if (search_list.size() > 0) { + thread = CreateThread(nullptr, 0, global_search_list_thread, this, 0, nullptr); + + if (!thread) + throw last_error(GetLastError()); + } + } catch (...) { + GlobalUnlock(hdrop); + throw; + } + + GlobalUnlock(hdrop); + } catch (const exception& e) { + error_message(nullptr, e.what()); - if (pidlFolder) return E_FAIL; - - if (!pdtobj) - return E_FAIL; - - stgm.tymed = TYMED_HGLOBAL; - - if (FAILED(pdtobj->GetData(&format, &stgm))) - return E_INVALIDARG; - - stgm_set = TRUE; - - hdrop = (HDROP)GlobalLock(stgm.hGlobal); - - if (!hdrop) { - ReleaseStgMedium(&stgm); - stgm_set = FALSE; - return E_INVALIDARG; } - hr = load_file_list(); - if (FAILED(hr)) - return hr; - - if (search_list.size() > 0) { - thread = CreateThread(NULL, 0, global_search_list_thread, this, 0, NULL); - - if (!thread) - ShowError(NULL, GetLastError()); - } - - GlobalUnlock(hdrop); - return S_OK; } -void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { - HANDLE h; +void BtrfsPropSheet::set_cmdline(const wstring& cmdline) { + win_handle h; IO_STATUS_BLOCK iosb; NTSTATUS Status; UINT sv = 0; BY_HANDLE_FILE_INFORMATION bhfi; - btrfs_inode_info bii2; + btrfs_inode_info2 bii2; FILE_ACCESS_INFORMATION fai; min_mode = 0; @@ -370,22 +405,20 @@ void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { max_flags = 0; min_compression_type = 0xff; max_compression_type = 0; - various_subvols = various_inodes = various_types = various_uids = various_gids = various_ro = FALSE; + various_subvols = various_inodes = various_types = various_uids = various_gids = various_ro = false; - can_change_perms = TRUE; - can_change_nocow = TRUE; + can_change_perms = true; + can_change_nocow = true; - h = CreateFileW(cmdline.c_str(), MAXIMUM_ALLOWED, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(cmdline.c_str(), MAXIMUM_ALLOWED, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h == INVALID_HANDLE_VALUE) return; Status = NtQueryInformationFile(h, &iosb, &fai, sizeof(FILE_ACCESS_INFORMATION), FileAccessInformation); - if (!NT_SUCCESS(Status)) { - CloseHandle(h); + if (!NT_SUCCESS(Status)) return; - } if (fai.AccessFlags & FILE_READ_ATTRIBUTES) can_change_perms = fai.AccessFlags & WRITE_DAC; @@ -393,13 +426,13 @@ void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { readonly = !(fai.AccessFlags & FILE_WRITE_ATTRIBUTES); if (GetFileInformationByHandle(h, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) - add_to_search_list((WCHAR*)cmdline.c_str()); + search_list.push_back(cmdline); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii2, sizeof(btrfs_inode_info)); + memset(&bii2, 0, sizeof(bii2)); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii2, sizeof(btrfs_inode_info2)); if (NT_SUCCESS(Status) && !bii2.top) { - int j; - LARGE_INTEGER filesize; subvol = bii2.subvol; @@ -414,13 +447,40 @@ void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { sizes[0] += bii2.inline_length; } - for (j = 0; j < 3; j++) { - if (bii2.disk_size[j] > 0) { - totalsize += bii2.disk_size[j]; - sizes[j + 1] += bii2.disk_size[j]; - } + if (bii2.disk_size_uncompressed > 0) { + totalsize += bii2.disk_size_uncompressed; + sizes[1] += bii2.disk_size_uncompressed; } + if (bii2.disk_size_zlib > 0) { + totalsize += bii2.disk_size_zlib; + sizes[2] += bii2.disk_size_zlib; + } + + if (bii2.disk_size_lzo > 0) { + totalsize += bii2.disk_size_lzo; + sizes[3] += bii2.disk_size_lzo; + } + + if (bii2.disk_size_zstd > 0) { + totalsize += bii2.disk_size_zstd; + sizes[4] += bii2.disk_size_zstd; + } + + sparsesize += bii2.sparse_size; + + FILE_STANDARD_INFORMATION fsi; + + Status = NtQueryInformationFile(h, &iosb, &fsi, sizeof(fsi), FileStandardInformation); + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + if (bii2.inline_length > 0) + allocsize += fsi.EndOfFile.QuadPart; + else + allocsize += fsi.AllocationSize.QuadPart; + min_mode |= ~bii2.st_mode; max_mode |= bii2.st_mode; min_flags |= ~bii2.flags; @@ -429,32 +489,28 @@ void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { max_compression_type = bii2.compression_type > max_compression_type ? bii2.compression_type : max_compression_type; if (bii2.inode == SUBVOL_ROOT_INODE) { - BOOL ro = bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY; + bool ro = bhfi.dwFileAttributes & FILE_ATTRIBUTE_READONLY; - has_subvols = TRUE; + has_subvols = true; if (sv == 0) ro_subvol = ro; else { if (ro_subvol != ro) - various_ro = TRUE; + various_ro = true; } sv++; } - ignore = FALSE; + ignore = false; if (bii2.type != BTRFS_TYPE_DIRECTORY && GetFileSizeEx(h, &filesize)) { if (filesize.QuadPart != 0) - can_change_nocow = FALSE; + can_change_nocow = false; } - - CloseHandle(h); - } else { - CloseHandle(h); + } else return; - } min_mode = ~min_mode; min_flags = ~min_flags; @@ -466,16 +522,16 @@ void BtrfsPropSheet::set_cmdline(std::wstring cmdline) { flags_set = ~(min_flags ^ max_flags); if (search_list.size() > 0) { - thread = CreateThread(NULL, 0, global_search_list_thread, this, 0, NULL); + thread = CreateThread(nullptr, 0, global_search_list_thread, this, 0, nullptr); if (!thread) - ShowError(NULL, GetLastError()); + throw last_error(GetLastError()); } this->filename = cmdline; } -static ULONG inode_type_to_string_ref(UINT8 type) { +static ULONG inode_type_to_string_ref(uint8_t type) { switch (type) { case BTRFS_TYPE_FILE: return IDS_INODE_FILE; @@ -503,7 +559,7 @@ static ULONG inode_type_to_string_ref(UINT8 type) { } } -void BtrfsPropSheet::change_inode_flag(HWND hDlg, UINT64 flag, UINT state) { +void BtrfsPropSheet::change_inode_flag(HWND hDlg, uint64_t flag, UINT state) { if (flag & BTRFS_INODE_NODATACOW) flag |= BTRFS_INODE_NODATASUM; @@ -517,17 +573,17 @@ void BtrfsPropSheet::change_inode_flag(HWND hDlg, UINT64 flag, UINT state) { flags_set = ~flag; } - flags_changed = TRUE; + flags_changed = true; SendMessageW(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); } -void BtrfsPropSheet::apply_changes_file(HWND hDlg, std::wstring fn) { - HANDLE h; +void BtrfsPropSheet::apply_changes_file(HWND hDlg, const wstring& fn) { + win_handle h; IO_STATUS_BLOCK iosb; NTSTATUS Status; btrfs_set_inode_info bsii; - btrfs_inode_info bii2; + btrfs_inode_info2 bii2; ULONG perms = FILE_TRAVERSE | FILE_READ_ATTRIBUTES; if (flags_changed || ro_changed) @@ -539,32 +595,25 @@ void BtrfsPropSheet::apply_changes_file(HWND hDlg, std::wstring fn) { if (mode_set & S_ISUID && (((min_mode & S_ISUID) != (max_mode & S_ISUID)) || ((min_mode & S_ISUID) != (mode & S_ISUID)))) perms |= WRITE_OWNER; - h = CreateFileW(fn.c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + h = CreateFileW(fn.c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h == INVALID_HANDLE_VALUE) { - ShowError(hDlg, GetLastError()); - return; - } + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); ZeroMemory(&bsii, sizeof(btrfs_set_inode_info)); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii2, sizeof(btrfs_inode_info)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii2, sizeof(btrfs_inode_info2)); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hDlg, Status); - CloseHandle(h); - return; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); if (bii2.inode == SUBVOL_ROOT_INODE && ro_changed) { BY_HANDLE_FILE_INFORMATION bhfi; FILE_BASIC_INFO fbi; - if (!GetFileInformationByHandle(h, &bhfi)) { - ShowError(hDlg, GetLastError()); - return; - } + if (!GetFileInformationByHandle(h, &bhfi)) + throw last_error(GetLastError()); memset(&fbi, 0, sizeof(fbi)); fbi.FileAttributes = bhfi.dwFileAttributes; @@ -574,49 +623,41 @@ void BtrfsPropSheet::apply_changes_file(HWND hDlg, std::wstring fn) { else fbi.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(fbi))) { - CloseHandle(h); - ShowError(hDlg, GetLastError()); - return; - } + if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(fbi))) + throw last_error(GetLastError()); } if (flags_changed || perms_changed || uid_changed || gid_changed || compress_type_changed) { if (flags_changed) { - bsii.flags_changed = TRUE; + bsii.flags_changed = true; bsii.flags = (bii2.flags & ~flags_set) | (flags & flags_set); } if (perms_changed) { - bsii.mode_changed = TRUE; + bsii.mode_changed = true; bsii.st_mode = (bii2.st_mode & ~mode_set) | (mode & mode_set); } if (uid_changed) { - bsii.uid_changed = TRUE; + bsii.uid_changed = true; bsii.st_uid = uid; } if (gid_changed) { - bsii.gid_changed = TRUE; + bsii.gid_changed = true; bsii.st_gid = gid; } if (compress_type_changed) { - bsii.compression_type_changed = TRUE; + bsii.compression_type_changed = true; bsii.compression_type = compress_type; } - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hDlg, Status); - CloseHandle(h); - return; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); } - - CloseHandle(h); } void BtrfsPropSheet::apply_changes(HWND hDlg) { @@ -624,10 +665,10 @@ void BtrfsPropSheet::apply_changes(HWND hDlg) { WCHAR fn[MAX_PATH]; // FIXME - is this long enough? if (various_uids) - uid_changed = FALSE; + uid_changed = false; if (various_gids) - gid_changed = FALSE; + gid_changed = false; if (!flags_changed && !perms_changed && !uid_changed && !gid_changed && !compress_type_changed && !ro_changed) return; @@ -635,7 +676,7 @@ void BtrfsPropSheet::apply_changes(HWND hDlg) { if (filename[0] != 0) apply_changes_file(hDlg, filename); else { - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); for (i = 0; i < num_files; i++) { if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(MAX_PATH))) { @@ -644,27 +685,38 @@ void BtrfsPropSheet::apply_changes(HWND hDlg) { } } - flags_changed = FALSE; - perms_changed = FALSE; - uid_changed = FALSE; - gid_changed = FALSE; - ro_changed = FALSE; + flags_changed = false; + perms_changed = false; + uid_changed = false; + gid_changed = false; + ro_changed = false; } void BtrfsPropSheet::set_size_on_disk(HWND hwndDlg) { - WCHAR size_on_disk[1024], s[1024], old_text[1024]; + wstring s, size_on_disk, cr; + WCHAR old_text[1024]; + float ratio; - format_size(totalsize, size_on_disk, sizeof(size_on_disk) / sizeof(WCHAR), TRUE); + format_size(totalsize, size_on_disk, true); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), size_format, size_on_disk) == STRSAFE_E_INSUFFICIENT_BUFFER) { - ShowError(hwndDlg, ERROR_INSUFFICIENT_BUFFER); - return; - } + wstring_sprintf(s, size_format, size_on_disk.c_str()); + + if (allocsize == sparsesize || totalsize == 0) + ratio = 0.0f; + else + ratio = 100.0f * (1.0f - ((float)totalsize / (float)(allocsize - sparsesize))); + + wstring_sprintf(cr, cr_format, ratio); GetDlgItemTextW(hwndDlg, IDC_SIZE_ON_DISK, old_text, sizeof(old_text) / sizeof(WCHAR)); - if (wcscmp(s, old_text)) - SetDlgItemTextW(hwndDlg, IDC_SIZE_ON_DISK, s); + if (s != old_text) + SetDlgItemTextW(hwndDlg, IDC_SIZE_ON_DISK, s.c_str()); + + GetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, old_text, sizeof(old_text) / sizeof(WCHAR)); + + if (cr != old_text) + SetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, cr.c_str()); } void BtrfsPropSheet::change_perm_flag(HWND hDlg, ULONG flag, UINT state) { @@ -678,86 +730,91 @@ void BtrfsPropSheet::change_perm_flag(HWND hDlg, ULONG flag, UINT state) { mode_set = ~flag; } - perms_changed = TRUE; + perms_changed = true; SendMessageW(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); } -void BtrfsPropSheet::change_uid(HWND hDlg, UINT32 uid) { +void BtrfsPropSheet::change_uid(HWND hDlg, uint32_t uid) { if (this->uid != uid) { this->uid = uid; - uid_changed = TRUE; + uid_changed = true; SendMessageW(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); } } -void BtrfsPropSheet::change_gid(HWND hDlg, UINT32 gid) { +void BtrfsPropSheet::change_gid(HWND hDlg, uint32_t gid) { if (this->gid != gid) { this->gid = gid; - gid_changed = TRUE; + gid_changed = true; SendMessageW(GetParent(hDlg), PSM_CHANGED, (WPARAM)hDlg, 0); } } void BtrfsPropSheet::update_size_details_dialog(HWND hDlg) { - WCHAR size[1024], old_text[1024]; + wstring size; + WCHAR old_text[1024]; int i; - ULONG items[] = { IDC_SIZE_INLINE, IDC_SIZE_UNCOMPRESSED, IDC_SIZE_ZLIB, IDC_SIZE_LZO }; + ULONG items[] = { IDC_SIZE_INLINE, IDC_SIZE_UNCOMPRESSED, IDC_SIZE_ZLIB, IDC_SIZE_LZO, IDC_SIZE_ZSTD }; - for (i = 0; i < 4; i++) { - format_size(sizes[i], size, sizeof(size) / sizeof(WCHAR), TRUE); + for (i = 0; i < 5; i++) { + format_size(sizes[i], size, true); GetDlgItemTextW(hDlg, items[i], old_text, sizeof(old_text) / sizeof(WCHAR)); - if (wcscmp(size, old_text)) - SetDlgItemTextW(hDlg, items[i], size); + if (size != old_text) + SetDlgItemTextW(hDlg, items[i], size.c_str()); } } static INT_PTR CALLBACK SizeDetailsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - BtrfsPropSheet* bps = (BtrfsPropSheet*)lParam; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + BtrfsPropSheet* bps = (BtrfsPropSheet*)lParam; - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); - bps->update_size_details_dialog(hwndDlg); - - if (bps->thread) - SetTimer(hwndDlg, 1, 250, NULL); - - return TRUE; - } - - case WM_COMMAND: - if (HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) { - EndDialog(hwndDlg, 0); - return TRUE; - } - break; - - case WM_TIMER: - { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - if (bps) { bps->update_size_details_dialog(hwndDlg); - if (!bps->thread) - KillTimer(hwndDlg, 1); + if (bps->thread) + SetTimer(hwndDlg, 1, 250, nullptr); + + return true; } + case WM_COMMAND: + if (HIWORD(wParam) == BN_CLICKED && (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)) { + EndDialog(hwndDlg, 0); + return true; + } break; + + case WM_TIMER: + { + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + if (bps) { + bps->update_size_details_dialog(hwndDlg); + + if (!bps->thread) + KillTimer(hwndDlg, 1); + } + + break; + } } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } -static void set_check_box(HWND hwndDlg, ULONG id, UINT64 min, UINT64 max) { +static void set_check_box(HWND hwndDlg, ULONG id, uint64_t min, uint64_t max) { if (min && max) { SendDlgItemMessage(hwndDlg, id, BM_SETCHECK, BST_CHECKED, 0); } else if (!min && !max) { @@ -776,19 +833,25 @@ static void set_check_box(HWND hwndDlg, ULONG id, UINT64 min, UINT64 max) { void BtrfsPropSheet::open_as_admin(HWND hwndDlg) { ULONG num_files, i; - WCHAR fn[MAX_PATH]; + WCHAR fn[MAX_PATH], modfn[MAX_PATH]; - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); + + if (num_files == 0) + return; + + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); for (i = 0; i < num_files; i++) { if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(MAX_PATH))) { - WCHAR t[MAX_PATH + 100]; + wstring t; SHELLEXECUTEINFOW sei; - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",ShowPropSheet "); - wcscat(t, fn); +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",ShowPropSheet "s + fn; +#else + t = wstring(L"\"") + modfn + wstring(L"\",ShowPropSheet ") + fn; +#endif RtlZeroMemory(&sei, sizeof(sei)); @@ -796,14 +859,12 @@ void BtrfsPropSheet::open_as_admin(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); @@ -815,11 +876,11 @@ void BtrfsPropSheet::open_as_admin(HWND hwndDlg) { } // based on functions in sys/sysmacros.h -#define major(rdev) ((((rdev) >> 8) & 0xFFF) | ((UINT32)((rdev) >> 32) & ~0xFFF)) -#define minor(rdev) (((rdev) & 0xFF) | ((UINT32)((rdev) >> 12) & ~0xFF)) +#define major(rdev) ((((rdev) >> 8) & 0xFFF) | ((uint32_t)((rdev) >> 32) & ~0xFFF)) +#define minor(rdev) (((rdev) & 0xFF) | ((uint32_t)((rdev) >> 12) & ~0xFF)) void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { - WCHAR s[255]; + wstring s; ULONG sr; int i; HWND comptype; @@ -827,31 +888,23 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { static ULONG perm_controls[] = { IDC_USERR, IDC_USERW, IDC_USERX, IDC_GROUPR, IDC_GROUPW, IDC_GROUPX, IDC_OTHERR, IDC_OTHERW, IDC_OTHERX, IDC_SETUID, IDC_SETGID, IDC_STICKY, 0 }; static ULONG perms[] = { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH, S_ISUID, S_ISGID, S_ISVTX, 0 }; - static ULONG comp_types[] = { IDS_COMPRESS_ANY, IDS_COMPRESS_ZLIB, IDS_COMPRESS_LZO, 0 }; + static ULONG comp_types[] = { IDS_COMPRESS_ANY, IDS_COMPRESS_ZLIB, IDS_COMPRESS_LZO, IDS_COMPRESS_ZSTD, 0 }; if (various_subvols) { - if (!LoadStringW(module, IDS_VARIOUS, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - } else { - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%llx", subvol) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - } + if (!load_string(module, IDS_VARIOUS, s)) + throw last_error(GetLastError()); + } else + wstring_sprintf(s, L"%llx", subvol); - SetDlgItemTextW(hwndDlg, IDC_SUBVOL, s); + SetDlgItemTextW(hwndDlg, IDC_SUBVOL, s.c_str()); if (various_inodes) { - if (!LoadStringW(module, IDS_VARIOUS, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } - } else { - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%llx", inode) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - } + if (!load_string(module, IDS_VARIOUS, s)) + throw last_error(GetLastError()); + } else + wstring_sprintf(s, L"%llx", inode); - SetDlgItemTextW(hwndDlg, IDC_INODE, s); + SetDlgItemTextW(hwndDlg, IDC_INODE, s.c_str()); if (various_types) sr = IDS_VARIOUS; @@ -866,60 +919,59 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { } if (sr == IDS_INODE_UNKNOWN) { - WCHAR t[255]; + wstring t; - if (!LoadStringW(module, sr, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, sr, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, type) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(s, t, type); } else if (sr == IDS_INODE_CHAR || sr == IDS_INODE_BLOCK) { - WCHAR t[255]; + wstring t; - if (!LoadStringW(module, sr, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, sr, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, major(rdev), minor(rdev)) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(s, t, major(rdev), minor(rdev)); } else { - if (!LoadStringW(module, sr, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, sr, s)) + throw last_error(GetLastError()); } - SetDlgItemTextW(hwndDlg, IDC_TYPE, s); + SetDlgItemTextW(hwndDlg, IDC_TYPE, s.c_str()); + + if (size_format[0] == 0) + GetDlgItemTextW(hwndDlg, IDC_SIZE_ON_DISK, size_format, sizeof(size_format) / sizeof(WCHAR)); + + if (cr_format[0] == 0) + GetDlgItemTextW(hwndDlg, IDC_COMPRESSION_RATIO, cr_format, sizeof(cr_format) / sizeof(WCHAR)); - GetDlgItemTextW(hwndDlg, IDC_SIZE_ON_DISK, size_format, sizeof(size_format) / sizeof(WCHAR)); set_size_on_disk(hwndDlg); if (thread) - SetTimer(hwndDlg, 1, 250, NULL); + SetTimer(hwndDlg, 1, 250, nullptr); set_check_box(hwndDlg, IDC_NODATACOW, min_flags & BTRFS_INODE_NODATACOW, max_flags & BTRFS_INODE_NODATACOW); set_check_box(hwndDlg, IDC_COMPRESS, min_flags & BTRFS_INODE_COMPRESS, max_flags & BTRFS_INODE_COMPRESS); comptype = GetDlgItem(hwndDlg, IDC_COMPRESS_TYPE); + while (SendMessage(comptype, CB_GETCOUNT, 0, 0) > 0) { + SendMessage(comptype, CB_DELETESTRING, 0, 0); + } + if (min_compression_type != max_compression_type) { - SendMessage(comptype, CB_ADDSTRING, NULL, (LPARAM)L""); + SendMessage(comptype, CB_ADDSTRING, 0, (LPARAM)L""); SendMessage(comptype, CB_SETCURSEL, 0, 0); } i = 0; while (comp_types[i] != 0) { - WCHAR t[255]; + wstring t; - if (!LoadStringW(module, comp_types[i], t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, comp_types[i], t)) + throw last_error(GetLastError()); - SendMessage(comptype, CB_ADDSTRING, NULL, (LPARAM)t); + SendMessage(comptype, CB_ADDSTRING, 0, (LPARAM)t.c_str()); i++; } @@ -938,32 +990,24 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { } if (various_uids) { - if (!LoadStringW(module, IDS_VARIOUS, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, IDS_VARIOUS, s)) + throw last_error(GetLastError()); EnableWindow(GetDlgItem(hwndDlg, IDC_UID), 0); - } else { - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%u", uid) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - } + } else + s = to_wstring(uid); - SetDlgItemTextW(hwndDlg, IDC_UID, s); + SetDlgItemTextW(hwndDlg, IDC_UID, s.c_str()); if (various_gids) { - if (!LoadStringW(module, IDS_VARIOUS, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, IDS_VARIOUS, s)) + throw last_error(GetLastError()); EnableWindow(GetDlgItem(hwndDlg, IDC_GID), 0); - } else { - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%u", gid) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; - } + } else + s = to_wstring(gid); - SetDlgItemTextW(hwndDlg, IDC_GID, s); + SetDlgItemTextW(hwndDlg, IDC_GID, s.c_str()); ShowWindow(GetDlgItem(hwndDlg, IDC_SUBVOL_RO), has_subvols); @@ -992,259 +1036,266 @@ void BtrfsPropSheet::init_propsheet(HWND hwndDlg) { } if (show_admin_button) { - SendMessageW(GetDlgItem(hwndDlg, IDC_OPEN_ADMIN), BCM_SETSHIELD, 0, TRUE); + SendMessageW(GetDlgItem(hwndDlg, IDC_OPEN_ADMIN), BCM_SETSHIELD, 0, true); ShowWindow(GetDlgItem(hwndDlg, IDC_OPEN_ADMIN), SW_SHOW); } else ShowWindow(GetDlgItem(hwndDlg, IDC_OPEN_ADMIN), SW_HIDE); } static INT_PTR CALLBACK PropSheetDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; - BtrfsPropSheet* bps = (BtrfsPropSheet*)psp->lParam; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; + BtrfsPropSheet* bps = (BtrfsPropSheet*)psp->lParam; - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); - bps->init_propsheet(hwndDlg); + bps->init_propsheet(hwndDlg); - return FALSE; - } + return false; + } - case WM_COMMAND: - { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + case WM_COMMAND: + { + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - if (bps && !bps->readonly) { - switch (HIWORD(wParam)) { - case BN_CLICKED: { - switch (LOWORD(wParam)) { - case IDC_NODATACOW: - bps->change_inode_flag(hwndDlg, BTRFS_INODE_NODATACOW, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_COMPRESS: - bps->change_inode_flag(hwndDlg, BTRFS_INODE_COMPRESS, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - - EnableWindow(GetDlgItem(hwndDlg, IDC_COMPRESS_TYPE), IsDlgButtonChecked(hwndDlg, LOWORD(wParam)) != BST_UNCHECKED); - break; - - case IDC_USERR: - bps->change_perm_flag(hwndDlg, S_IRUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_USERW: - bps->change_perm_flag(hwndDlg, S_IWUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_USERX: - bps->change_perm_flag(hwndDlg, S_IXUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_GROUPR: - bps->change_perm_flag(hwndDlg, S_IRGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_GROUPW: - bps->change_perm_flag(hwndDlg, S_IWGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_GROUPX: - bps->change_perm_flag(hwndDlg, S_IXGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_OTHERR: - bps->change_perm_flag(hwndDlg, S_IROTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_OTHERW: - bps->change_perm_flag(hwndDlg, S_IWOTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_OTHERX: - bps->change_perm_flag(hwndDlg, S_IXOTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_SETUID: - bps->change_perm_flag(hwndDlg, S_ISUID, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_SETGID: - bps->change_perm_flag(hwndDlg, S_ISGID, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_STICKY: - bps->change_perm_flag(hwndDlg, S_ISVTX, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - break; - - case IDC_SUBVOL_RO: - switch (IsDlgButtonChecked(hwndDlg, LOWORD(wParam))) { - case BST_CHECKED: - bps->ro_subvol = TRUE; - bps->ro_changed = TRUE; - break; - - case BST_UNCHECKED: - bps->ro_subvol = FALSE; - bps->ro_changed = TRUE; - break; - - case BST_INDETERMINATE: - bps->ro_changed = FALSE; - break; - } - - SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); - break; - - case IDC_OPEN_ADMIN: - bps->open_as_admin(hwndDlg); - break; - } - - break; - } - - case EN_CHANGE: { - switch (LOWORD(wParam)) { - case IDC_UID: { - WCHAR s[255]; - - GetDlgItemTextW(hwndDlg, LOWORD(wParam), s, sizeof(s) / sizeof(WCHAR)); - - bps->change_uid(hwndDlg, _wtoi(s)); + if (bps && !bps->readonly) { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + switch (LOWORD(wParam)) { + case IDC_NODATACOW: + bps->change_inode_flag(hwndDlg, BTRFS_INODE_NODATACOW, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); break; - } - case IDC_GID: { - WCHAR s[255]; + case IDC_COMPRESS: + bps->change_inode_flag(hwndDlg, BTRFS_INODE_COMPRESS, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); - GetDlgItemTextW(hwndDlg, LOWORD(wParam), s, sizeof(s) / sizeof(WCHAR)); - - bps->change_gid(hwndDlg, _wtoi(s)); + EnableWindow(GetDlgItem(hwndDlg, IDC_COMPRESS_TYPE), IsDlgButtonChecked(hwndDlg, LOWORD(wParam)) != BST_UNCHECKED); break; - } - } - break; - } + case IDC_USERR: + bps->change_perm_flag(hwndDlg, S_IRUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; - case CBN_SELCHANGE: { - switch (LOWORD(wParam)) { - case IDC_COMPRESS_TYPE: { - int sel = SendMessageW(GetDlgItem(hwndDlg, LOWORD(wParam)), CB_GETCURSEL, 0, 0); + case IDC_USERW: + bps->change_perm_flag(hwndDlg, S_IWUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; - if (bps->min_compression_type != bps->max_compression_type) { - if (sel == 0) - bps->compress_type_changed = FALSE; - else { - bps->compress_type = sel - 1; - bps->compress_type_changed = TRUE; + case IDC_USERX: + bps->change_perm_flag(hwndDlg, S_IXUSR, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_GROUPR: + bps->change_perm_flag(hwndDlg, S_IRGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_GROUPW: + bps->change_perm_flag(hwndDlg, S_IWGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_GROUPX: + bps->change_perm_flag(hwndDlg, S_IXGRP, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_OTHERR: + bps->change_perm_flag(hwndDlg, S_IROTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_OTHERW: + bps->change_perm_flag(hwndDlg, S_IWOTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_OTHERX: + bps->change_perm_flag(hwndDlg, S_IXOTH, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_SETUID: + bps->change_perm_flag(hwndDlg, S_ISUID, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_SETGID: + bps->change_perm_flag(hwndDlg, S_ISGID, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_STICKY: + bps->change_perm_flag(hwndDlg, S_ISVTX, IsDlgButtonChecked(hwndDlg, LOWORD(wParam))); + break; + + case IDC_SUBVOL_RO: + switch (IsDlgButtonChecked(hwndDlg, LOWORD(wParam))) { + case BST_CHECKED: + bps->ro_subvol = true; + bps->ro_changed = true; + break; + + case BST_UNCHECKED: + bps->ro_subvol = false; + bps->ro_changed = true; + break; + + case BST_INDETERMINATE: + bps->ro_changed = false; + break; } - } else { - bps->compress_type = sel; - bps->compress_type_changed = TRUE; - } - SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); + SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); + break; + case IDC_OPEN_ADMIN: + bps->open_as_admin(hwndDlg); break; } + + break; } + case EN_CHANGE: { + switch (LOWORD(wParam)) { + case IDC_UID: { + WCHAR s[255]; + + GetDlgItemTextW(hwndDlg, LOWORD(wParam), s, sizeof(s) / sizeof(WCHAR)); + + bps->change_uid(hwndDlg, _wtoi(s)); + break; + } + + case IDC_GID: { + WCHAR s[255]; + + GetDlgItemTextW(hwndDlg, LOWORD(wParam), s, sizeof(s) / sizeof(WCHAR)); + + bps->change_gid(hwndDlg, _wtoi(s)); + break; + } + } + + break; + } + + case CBN_SELCHANGE: { + switch (LOWORD(wParam)) { + case IDC_COMPRESS_TYPE: { + int sel = SendMessageW(GetDlgItem(hwndDlg, LOWORD(wParam)), CB_GETCURSEL, 0, 0); + + if (bps->min_compression_type != bps->max_compression_type) { + if (sel == 0) + bps->compress_type_changed = false; + else { + bps->compress_type = (uint8_t)(sel - 1); + bps->compress_type_changed = true; + } + } else { + bps->compress_type = (uint8_t)sel; + bps->compress_type_changed = true; + } + + SendMessageW(GetParent(hwndDlg), PSM_CHANGED, (WPARAM)hwndDlg, 0); + + break; + } + } + + break; + } + } + } + + break; + } + + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->code) { + case PSN_KILLACTIVE: + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, false); + break; + + case PSN_APPLY: { + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + bps->apply_changes(hwndDlg); + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); + break; + } + + case NM_CLICK: + case NM_RETURN: { + if (((LPNMHDR)lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_SIZE_ON_DISK)) { + PNMLINK pNMLink = (PNMLINK)lParam; + + if (pNMLink->item.iLink == 0) + DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SIZE_DETAILS), hwndDlg, SizeDetailsDlgProc, GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); + } break; } } } - break; - } + case WM_TIMER: + { + BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + + if (bps) { + bps->set_size_on_disk(hwndDlg); + + if (!bps->thread) + KillTimer(hwndDlg, 1); + } - case WM_NOTIFY: - { - switch (((LPNMHDR)lParam)->code) { - case PSN_KILLACTIVE: - SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, FALSE); break; - - case PSN_APPLY: { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - bps->apply_changes(hwndDlg); - SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, PSNRET_NOERROR); - break; - } - - case NM_CLICK: - case NM_RETURN: { - if (((LPNMHDR)lParam)->hwndFrom == GetDlgItem(hwndDlg, IDC_SIZE_ON_DISK)) { - PNMLINK pNMLink = (PNMLINK)lParam; - - if (pNMLink->item.iLink == 0) - DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SIZE_DETAILS), hwndDlg, SizeDetailsDlgProc, GetWindowLongPtr(hwndDlg, GWLP_USERDATA)); - } - break; - } } } - - case WM_TIMER: - { - BtrfsPropSheet* bps = (BtrfsPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - - if (bps) { - bps->set_size_on_disk(hwndDlg); - - if (!bps->thread) - KillTimer(hwndDlg, 1); - } - - break; - } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } HRESULT __stdcall BtrfsPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) { - PROPSHEETPAGE psp; - HPROPSHEETPAGE hPage; - INITCOMMONCONTROLSEX icex; + try { + PROPSHEETPAGE psp; + HPROPSHEETPAGE hPage; + INITCOMMONCONTROLSEX icex; - if (ignore) - return S_OK; - - icex.dwSize = sizeof(icex); - icex.dwICC = ICC_LINK_CLASS; - - if (!InitCommonControlsEx(&icex)) { - MessageBoxW(NULL, L"InitCommonControlsEx failed", L"Error", MB_ICONERROR); - } - - psp.dwSize = sizeof(psp); - psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; - psp.hInstance = module; - psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_SHEET); - psp.hIcon = 0; - psp.pszTitle = MAKEINTRESOURCE(IDS_PROP_SHEET_TITLE); - psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; - psp.pcRefParent = (UINT*)&objs_loaded; - psp.pfnCallback = NULL; - psp.lParam = (LPARAM)this; - - hPage = CreatePropertySheetPage(&psp); - - if (hPage) { - if (pfnAddPage(hPage, lParam)) { - this->AddRef(); + if (ignore) return S_OK; + + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_LINK_CLASS; + + if (!InitCommonControlsEx(&icex)) + throw string_error(IDS_INITCOMMONCONTROLSEX_FAILED); + + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; + psp.hInstance = module; + psp.pszTemplate = MAKEINTRESOURCE(IDD_PROP_SHEET); + psp.hIcon = 0; + psp.pszTitle = MAKEINTRESOURCE(IDS_PROP_SHEET_TITLE); + psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; + psp.pcRefParent = (UINT*)&objs_loaded; + psp.pfnCallback = nullptr; + psp.lParam = (LPARAM)this; + + hPage = CreatePropertySheetPage(&psp); + + if (hPage) { + if (pfnAddPage(hPage, lParam)) { + this->AddRef(); + return S_OK; + } else + DestroyPropertySheetPage(hPage); } else - DestroyPropertySheetPage(hPage); - } else - return E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } catch (const exception& e) { + error_message(nullptr, e.what()); + } return E_FAIL; } @@ -1258,39 +1309,42 @@ extern "C" { #endif void CALLBACK ShowPropSheetW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - BtrfsPropSheet* bps; - PROPSHEETPAGEW psp; - PROPSHEETHEADERW psh; - WCHAR title[255]; + try { + BtrfsPropSheet bps; + PROPSHEETPAGEW psp; + PROPSHEETHEADERW psh; + wstring title; - set_dpi_aware(); + set_dpi_aware(); - LoadStringW(module, IDS_STANDALONE_PROPSHEET_TITLE, title, sizeof(title) / sizeof(WCHAR)); + load_string(module, IDS_STANDALONE_PROPSHEET_TITLE, title); - bps = new BtrfsPropSheet; - bps->set_cmdline(lpszCmdLine); + bps.set_cmdline(lpszCmdLine); - psp.dwSize = sizeof(psp); - psp.dwFlags = PSP_USETITLE; - psp.hInstance = module; - psp.pszTemplate = MAKEINTRESOURCEW(IDD_PROP_SHEET); - psp.hIcon = 0; - psp.pszTitle = MAKEINTRESOURCEW(IDS_PROP_SHEET_TITLE); - psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; - psp.pfnCallback = NULL; - psp.lParam = (LPARAM)bps; + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_USETITLE; + psp.hInstance = module; + psp.pszTemplate = MAKEINTRESOURCEW(IDD_PROP_SHEET); + psp.hIcon = 0; + psp.pszTitle = MAKEINTRESOURCEW(IDS_PROP_SHEET_TITLE); + psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; + psp.pfnCallback = nullptr; + psp.lParam = (LPARAM)&bps; - memset(&psh, 0, sizeof(PROPSHEETHEADERW)); + memset(&psh, 0, sizeof(PROPSHEETHEADERW)); - psh.dwSize = sizeof(PROPSHEETHEADERW); - psh.dwFlags = PSH_PROPSHEETPAGE; - psh.hwndParent = hwnd; - psh.hInstance = psp.hInstance; - psh.pszCaption = title; - psh.nPages = 1; - psh.ppsp = &psp; + psh.dwSize = sizeof(PROPSHEETHEADERW); + psh.dwFlags = PSH_PROPSHEETPAGE; + psh.hwndParent = hwnd; + psh.hInstance = psp.hInstance; + psh.pszCaption = title.c_str(); + psh.nPages = 1; + psh.ppsp = &psp; - PropertySheetW(&psh); + PropertySheetW(&psh); + } catch (const exception& e) { + error_message(hwnd, e.what()); + } } #ifdef __cplusplus diff --git a/dll/shellext/shellbtrfs/propsheet.h b/dll/shellext/shellbtrfs/propsheet.h index 1920dbb9402..8e4f234f15a 100644 --- a/dll/shellext/shellbtrfs/propsheet.h +++ b/dll/shellext/shellbtrfs/propsheet.h @@ -19,7 +19,6 @@ #include #include -#include #ifndef __REACTOS__ #include "../btrfsioctl.h" #else @@ -93,25 +92,27 @@ class BtrfsPropSheet : public IShellExtInit, IShellPropSheetExt { public: BtrfsPropSheet() { refcount = 0; - ignore = TRUE; - stgm_set = FALSE; - readonly = FALSE; - flags_changed = FALSE; - perms_changed = FALSE; - uid_changed = FALSE; - gid_changed = FALSE; - compress_type_changed = FALSE; - ro_changed = FALSE; - can_change_perms = FALSE; - show_admin_button = FALSE; - thread = NULL; + ignore = true; + stgm_set = false; + readonly = false; + flags_changed = false; + perms_changed = false; + uid_changed = false; + gid_changed = false; + compress_type_changed = false; + ro_changed = false; + can_change_perms = false; + show_admin_button = false; + thread = nullptr; mode = mode_set = 0; flags = flags_set = 0; - has_subvols = FALSE; + has_subvols = false; filename = L""; - sizes[0] = sizes[1] = sizes[2] = sizes[3] = 0; - totalsize = 0; + sizes[0] = sizes[1] = sizes[2] = sizes[3] = sizes[4] = 0; + totalsize = allocsize = sparsesize = 0; + size_format[0] = 0; + cr_format[0] = 0; InterlockedIncrement(&objs_loaded); } @@ -152,43 +153,42 @@ public: virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam); void init_propsheet(HWND hwndDlg); - void change_inode_flag(HWND hDlg, UINT64 flag, UINT state); + void change_inode_flag(HWND hDlg, uint64_t flag, UINT state); void change_perm_flag(HWND hDlg, ULONG perm, UINT state); - void change_uid(HWND hDlg, UINT32 uid); - void change_gid(HWND hDlg, UINT32 gid); + void change_uid(HWND hDlg, uint32_t uid); + void change_gid(HWND hDlg, uint32_t gid); void apply_changes(HWND hDlg); void set_size_on_disk(HWND hwndDlg); - void add_to_search_list(WCHAR* fn); DWORD search_list_thread(); - void do_search(WCHAR* fn); + void do_search(const wstring& fn); void update_size_details_dialog(HWND hDlg); void open_as_admin(HWND hwndDlg); - void set_cmdline(std::wstring cmdline); + void set_cmdline(const wstring& cmdline); - BOOL readonly; - BOOL can_change_perms; - BOOL can_change_nocow; - WCHAR size_format[255]; + bool readonly; + bool can_change_perms; + bool can_change_nocow; + WCHAR size_format[255], cr_format[255]; HANDLE thread; - UINT32 min_mode, max_mode, mode, mode_set; - UINT64 min_flags, max_flags, flags, flags_set; - UINT64 subvol, inode, rdev; - UINT8 type, min_compression_type, max_compression_type, compress_type; - UINT32 uid, gid; - BOOL various_subvols, various_inodes, various_types, various_uids, various_gids, compress_type_changed, has_subvols, + uint32_t min_mode, max_mode, mode, mode_set; + uint64_t min_flags, max_flags, flags, flags_set; + uint64_t subvol, inode, rdev; + uint8_t type, min_compression_type, max_compression_type, compress_type; + uint32_t uid, gid; + bool various_subvols, various_inodes, various_types, various_uids, various_gids, compress_type_changed, has_subvols, ro_subvol, various_ro, ro_changed, show_admin_button; private: LONG refcount; - BOOL ignore; + bool ignore; STGMEDIUM stgm; - BOOL stgm_set; - BOOL flags_changed, perms_changed, uid_changed, gid_changed; - UINT64 sizes[4], totalsize; - std::deque search_list; - std::wstring filename; + bool stgm_set; + bool flags_changed, perms_changed, uid_changed, gid_changed; + uint64_t sizes[5], totalsize, allocsize, sparsesize; + deque search_list; + wstring filename; - void apply_changes_file(HWND hDlg, std::wstring fn); - HRESULT check_file(std::wstring fn, UINT i, UINT num_files, UINT* sv); + void apply_changes_file(HWND hDlg, const wstring& fn); + HRESULT check_file(const wstring& fn, UINT i, UINT num_files, UINT* sv); HRESULT load_file_list(); }; diff --git a/dll/shellext/shellbtrfs/recv.cpp b/dll/shellext/shellbtrfs/recv.cpp index f52a0092a4f..0cdb609aa58 100644 --- a/dll/shellext/shellbtrfs/recv.cpp +++ b/dll/shellext/shellbtrfs/recv.cpp @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "recv.h" #include "resource.h" @@ -34,17 +34,17 @@ #include #endif -#define EA_NTACL "security.NTACL" -#define EA_DOSATTRIB "user.DOSATTRIB" -#define EA_REPARSE "user.reparse" -#define EA_EA "user.EA" -#define XATTR_USER "user." +const string EA_NTACL = "security.NTACL"; +const string EA_DOSATTRIB = "user.DOSATTRIB"; +const string EA_REPARSE = "user.reparse"; +const string EA_EA = "user.EA"; +const string XATTR_USER = "user."; #ifndef __REACTOS__ -BOOL have_sse42 = FALSE; +bool have_sse42 = false; #endif -static const UINT32 crctable[] = { +static const uint32_t crctable[] = { 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4, 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb, 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b, 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24, 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b, 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384, @@ -90,7 +90,7 @@ do { \ } while(0) #ifndef __REACTOS__ -static UINT32 crc32c_hw(const void *input, ULONG len, UINT32 crc) { +static uint32_t crc32c_hw(const void *input, ULONG len, uint32_t crc) { const char* buf = (const char*)input; // Annoyingly, the CRC32 intrinsics don't work properly in modern versions of MSVC - @@ -108,36 +108,36 @@ static UINT32 crc32c_hw(const void *input, ULONG len, UINT32 crc) { #ifdef _AMD64_ #ifdef _MSC_VER #pragma warning(push) -#pragma warning(disable:4244) // _mm_crc32_u64 wants to return UINT64(!) +#pragma warning(disable:4244) // _mm_crc32_u64 wants to return uint64_t(!) #pragma warning(disable:4242) #endif - CALC_CRC(_mm_crc32_u64, crc, UINT64, buf, len); + CALC_CRC(_mm_crc32_u64, crc, uint64_t, buf, len); #ifdef _MSC_VER #pragma warning(pop) #endif #endif - CALC_CRC(_mm_crc32_u32, crc, UINT32, buf, len); + CALC_CRC(_mm_crc32_u32, crc, uint32_t, buf, len); #ifdef _MSC_VER for (; len > 0; len--, buf++) { crc = crctable[(crc ^ *buf) & 0xff] ^ (crc >> 8); } #else - CALC_CRC(_mm_crc32_u16, crc, UINT16, buf, len); - CALC_CRC(_mm_crc32_u8, crc, UINT8, buf, len); + CALC_CRC(_mm_crc32_u16, crc, uint16_t, buf, len); + CALC_CRC(_mm_crc32_u8, crc, uint8_t, buf, len); #endif return crc; } #endif -static UINT32 calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen) { +static uint32_t calc_crc32c(uint32_t seed, uint8_t* msg, ULONG msglen) { #ifndef __REACTOS__ if (have_sse42) return crc32c_hw(msg, msglen, seed); else { #endif - UINT32 rem; + uint32_t rem; ULONG i; rem = seed; @@ -152,116 +152,76 @@ static UINT32 calc_crc32c(UINT32 seed, UINT8* msg, ULONG msglen) { #endif } -BOOL BtrfsRecv::find_tlv(UINT8* data, ULONG datalen, UINT16 type, void** value, ULONG* len) { +bool BtrfsRecv::find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len) { ULONG off = 0; while (off < datalen) { btrfs_send_tlv* tlv = (btrfs_send_tlv*)(data + off); - UINT8* payload = data + off + sizeof(btrfs_send_tlv); + uint8_t* payload = data + off + sizeof(btrfs_send_tlv); if (off + sizeof(btrfs_send_tlv) + tlv->length > datalen) // file is truncated - return FALSE; + return false; if (tlv->type == type) { *value = payload; *len = tlv->length; - return TRUE; + return true; } off += sizeof(btrfs_send_tlv) + tlv->length; } - return FALSE; + return false; } -BOOL BtrfsRecv::utf8_to_utf16(HWND hwnd, char* utf8, ULONG utf8len, std::wstring* utf16) { - NTSTATUS Status; - ULONG utf16len; - WCHAR* buf; - - Status = RtlUTF8ToUnicodeN(NULL, 0, &utf16len, utf8, utf8len); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } - - buf = (WCHAR*)malloc(utf16len + sizeof(WCHAR)); - - if (!buf) { - ShowRecvError(IDS_OUT_OF_MEMORY); - return FALSE; - } - - Status = RtlUTF8ToUnicodeN(buf, utf16len, &utf16len, utf8, utf8len); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_RTLUTF8TOUNICODEN_FAILED, Status, format_ntstatus(Status).c_str()); - free(buf); - return FALSE; - } - - buf[utf16len / sizeof(WCHAR)] = 0; - - *utf16 = buf; - - free(buf); - - return TRUE; -} - -BOOL BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* name; +void BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent) { + string name; BTRFS_UUID* uuid; - UINT64* gen; - ULONG namelen, uuidlen, genlen, bcslen; + uint64_t* gen; + ULONG uuidlen, genlen, bcslen; btrfs_create_subvol* bcs; NTSTATUS Status; IO_STATUS_BLOCK iosb; - std::wstring nameu; + wstring nameu; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&name, &namelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* namebuf; + ULONG namelen; + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&namebuf, &namelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path"); + + name = string(namebuf, namelen); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_UUID, (void**)&uuid, &uuidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"uuid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_UUID, (void**)&uuid, &uuidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"uuid"); - if (uuidlen < sizeof(BTRFS_UUID)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"uuid", uuidlen, sizeof(BTRFS_UUID)); - return FALSE; - } + if (uuidlen < sizeof(BTRFS_UUID)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"uuid", uuidlen, sizeof(BTRFS_UUID)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_TRANSID, (void**)&gen, &genlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"transid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_TRANSID, (void**)&gen, &genlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"transid"); - if (genlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"transid", genlen, sizeof(UINT64)); - return FALSE; - } + if (genlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"transid", genlen, sizeof(uint64_t)); this->subvol_uuid = *uuid; this->stransid = *gen; - if (!utf8_to_utf16(hwnd, name, namelen, &nameu)) - return FALSE; + utf8_to_utf16(name, nameu); bcslen = offsetof(btrfs_create_subvol, name[0]) + (nameu.length() * sizeof(WCHAR)); bcs = (btrfs_create_subvol*)malloc(bcslen); - bcs->readonly = TRUE; - bcs->posix = TRUE; - bcs->namelen = nameu.length() * sizeof(WCHAR); + bcs->readonly = true; + bcs->posix = true; + bcs->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR)); memcpy(bcs->name, nameu.c_str(), bcs->namelen); - Status = NtFsControlFile(parent, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_CREATE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } + Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_CREATE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); subvolpath = dirpath; subvolpath += L"\\"; @@ -274,36 +234,28 @@ BOOL BtrfsRecv::cmd_subvol(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { CloseHandle(master); master = CreateFileW(subvolpath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (master == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + 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, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } + Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); dir = CreateFileW(subvolpath.c_str(), FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (dir == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (dir == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); subvolpath += L"\\"; add_cache_entry(&this->subvol_uuid, this->stransid, subvolpath); num_received++; - - return TRUE; } -void BtrfsRecv::add_cache_entry(BTRFS_UUID* uuid, UINT64 transid, std::wstring path) { +void BtrfsRecv::add_cache_entry(BTRFS_UUID* uuid, uint64_t transid, const wstring& path) { subvol_cache sc; sc.uuid = *uuid; @@ -313,87 +265,69 @@ void BtrfsRecv::add_cache_entry(BTRFS_UUID* uuid, UINT64 transid, std::wstring p cache.push_back(sc); } -BOOL BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* name; +void BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent) { + string name; BTRFS_UUID *uuid, *parent_uuid; - UINT64 *gen, *parent_transid; - ULONG namelen, uuidlen, genlen, paruuidlen, partransidlen, bcslen; + uint64_t *gen, *parent_transid; + ULONG uuidlen, genlen, paruuidlen, partransidlen, bcslen; btrfs_create_snapshot* bcs; NTSTATUS Status; IO_STATUS_BLOCK iosb; - std::wstring nameu, parpath; + wstring nameu, parpath; btrfs_find_subvol bfs; WCHAR parpathw[MAX_PATH], volpathw[MAX_PATH]; - HANDLE subvol; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&name, &namelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* namebuf; + ULONG namelen; + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&namebuf, &namelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"path"); + + name = string(namebuf, namelen); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_UUID, (void**)&uuid, &uuidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"uuid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_UUID, (void**)&uuid, &uuidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"uuid"); - if (uuidlen < sizeof(BTRFS_UUID)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"uuid", uuidlen, sizeof(BTRFS_UUID)); - return FALSE; - } + if (uuidlen < sizeof(BTRFS_UUID)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"uuid", uuidlen, sizeof(BTRFS_UUID)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_TRANSID, (void**)&gen, &genlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"transid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_TRANSID, (void**)&gen, &genlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"transid"); - if (genlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"transid", genlen, sizeof(UINT64)); - return FALSE; - } + if (genlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"transid", genlen, sizeof(uint64_t)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_UUID, (void**)&parent_uuid, &paruuidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_uuid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_UUID, (void**)&parent_uuid, &paruuidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_uuid"); - if (paruuidlen < sizeof(BTRFS_UUID)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_uuid", paruuidlen, sizeof(BTRFS_UUID)); - return FALSE; - } + if (paruuidlen < sizeof(BTRFS_UUID)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_uuid", paruuidlen, sizeof(BTRFS_UUID)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_CTRANSID, (void**)&parent_transid, &partransidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_ctransid"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_CTRANSID, (void**)&parent_transid, &partransidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_ctransid"); - if (partransidlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_ctransid", partransidlen, sizeof(UINT64)); - return FALSE; - } + if (partransidlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_ctransid", partransidlen, sizeof(uint64_t)); this->subvol_uuid = *uuid; this->stransid = *gen; - if (!utf8_to_utf16(hwnd, name, namelen, &nameu)) - return FALSE; + utf8_to_utf16(name, nameu); bfs.uuid = *parent_uuid; bfs.ctransid = *parent_transid; - Status = NtFsControlFile(parent, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_FIND_SUBVOL, &bfs, sizeof(btrfs_find_subvol), + Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_FIND_SUBVOL, &bfs, sizeof(btrfs_find_subvol), parpathw, sizeof(parpathw)); - if (Status == STATUS_NOT_FOUND) { - ShowRecvError(IDS_RECV_CANT_FIND_PARENT_SUBVOL); - return FALSE; - } else if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_FIND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } + if (Status == STATUS_NOT_FOUND) + throw string_error(IDS_RECV_CANT_FIND_PARENT_SUBVOL); + else if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_FIND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - if (!GetVolumePathNameW(dirpath.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) { - ShowRecvError(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!GetVolumePathNameW(dirpath.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) + throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); parpath = volpathw; if (parpath.substr(parpath.length() - 1) == L"\\") @@ -401,26 +335,24 @@ BOOL BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { parpath += parpathw; - subvol = CreateFileW(parpath.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (subvol == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, parpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + { + win_handle subvol = CreateFileW(parpath.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (subvol == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_PATH, parpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - bcslen = offsetof(btrfs_create_snapshot, name[0]) + (nameu.length() * sizeof(WCHAR)); - bcs = (btrfs_create_snapshot*)malloc(bcslen); + bcslen = offsetof(btrfs_create_snapshot, name[0]) + (nameu.length() * sizeof(WCHAR)); + bcs = (btrfs_create_snapshot*)malloc(bcslen); - bcs->readonly = TRUE; - bcs->posix = TRUE; - bcs->subvol = subvol; - bcs->namelen = nameu.length() * sizeof(WCHAR); - memcpy(bcs->name, nameu.c_str(), bcs->namelen); + bcs->readonly = true; + bcs->posix = true; + bcs->subvol = subvol; + bcs->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR)); + memcpy(bcs->name, nameu.c_str(), bcs->namelen); - Status = NtFsControlFile(parent, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_CREATE_SNAPSHOT_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; + Status = NtFsControlFile(parent, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_CREATE_SNAPSHOT_FAILED, Status, format_ntstatus(Status).c_str()); } subvolpath = dirpath; @@ -434,96 +366,75 @@ BOOL BtrfsRecv::cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { CloseHandle(master); master = CreateFileW(subvolpath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (master == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + 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, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } + Status = NtFsControlFile(master, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESERVE_SUBVOL, bcs, bcslen, nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_RESERVE_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); dir = CreateFileW(subvolpath.c_str(), FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (dir == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (dir == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_PATH, subvolpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); subvolpath += L"\\"; add_cache_entry(&this->subvol_uuid, this->stransid, subvolpath); num_received++; - - return TRUE; } -BOOL BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *name, *pathlink; - UINT64 *inode, *rdev = NULL, *mode = NULL; - ULONG namelen, inodelen, bmnsize; +void BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + uint64_t *inode, *rdev = nullptr, *mode = nullptr; + ULONG inodelen, bmnsize; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_mknod* bmn; - std::wstring nameu, pathlinku; + wstring nameu, pathlinku; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&name, &namelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* name; + ULONG namelen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_INODE, (void**)&inode, &inodelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"inode"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_INODE, (void**)&inode, &inodelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"inode"); - if (inodelen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"inode", inodelen, sizeof(UINT64)); - return FALSE; - } + if (inodelen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"inode", inodelen, sizeof(uint64_t)); if (cmd->cmd == BTRFS_SEND_CMD_MKNOD || cmd->cmd == BTRFS_SEND_CMD_MKFIFO || cmd->cmd == BTRFS_SEND_CMD_MKSOCK) { ULONG rdevlen, modelen; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_RDEV, (void**)&rdev, &rdevlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"rdev"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_RDEV, (void**)&rdev, &rdevlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"rdev"); - if (rdevlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"rdev", rdev, sizeof(UINT64)); - return FALSE; - } + if (rdevlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"rdev", rdev, sizeof(uint64_t)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"mode"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"mode"); - if (modelen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(UINT64)); - return FALSE; - } + if (modelen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(uint64_t)); } else if (cmd->cmd == BTRFS_SEND_CMD_SYMLINK) { + char* pathlink; ULONG pathlinklen; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_LINK, (void**)&pathlink, &pathlinklen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path_link"); - return FALSE; - } + 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"); - if (!utf8_to_utf16(hwnd, pathlink, pathlinklen, &pathlinku)) - return FALSE; + utf8_to_utf16(string(pathlink, pathlinklen), pathlinku); } - if (!utf8_to_utf16(hwnd, name, namelen, &nameu)) - return FALSE; - bmnsize = sizeof(btrfs_mknod) - sizeof(WCHAR) + (nameu.length() * sizeof(WCHAR)); bmn = (btrfs_mknod*)malloc(bmnsize); @@ -541,521 +452,430 @@ BOOL BtrfsRecv::cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { bmn->type = BTRFS_TYPE_FILE; bmn->st_rdev = rdev ? *rdev : 0; - bmn->namelen = nameu.length() * sizeof(WCHAR); + bmn->namelen = (uint16_t)(nameu.length() * sizeof(WCHAR)); memcpy(bmn->name, nameu.c_str(), bmn->namelen); - Status = NtFsControlFile(dir, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, NULL, 0); + Status = NtFsControlFile(dir, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0); if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_MKNOD_FAILED, Status, format_ntstatus(Status).c_str()); free(bmn); - return FALSE; + throw string_error(IDS_RECV_MKNOD_FAILED, Status, format_ntstatus(Status).c_str()); } free(bmn); if (cmd->cmd == BTRFS_SEND_CMD_SYMLINK) { - HANDLE h; REPARSE_DATA_BUFFER* rdb; ULONG rdblen; btrfs_set_inode_info bsii; 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); + rdb = (REPARSE_DATA_BUFFER*)malloc(rdblen); rdb->ReparseTag = IO_REPARSE_TAG_SYMLINK; - rdb->ReparseDataLength = rdblen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer); + rdb->ReparseDataLength = (uint16_t)(rdblen - offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer)); rdb->Reserved = 0; rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset = 0; - rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = pathlinku.length() * sizeof(WCHAR); - rdb->SymbolicLinkReparseBuffer.PrintNameOffset = pathlinku.length() * sizeof(WCHAR); - rdb->SymbolicLinkReparseBuffer.PrintNameLength = pathlinku.length() * sizeof(WCHAR); + rdb->SymbolicLinkReparseBuffer.SubstituteNameLength = (uint16_t)(pathlinku.length() * sizeof(WCHAR)); + rdb->SymbolicLinkReparseBuffer.PrintNameOffset = (uint16_t)(pathlinku.length() * sizeof(WCHAR)); + rdb->SymbolicLinkReparseBuffer.PrintNameLength = (uint16_t)(pathlinku.length() * sizeof(WCHAR)); rdb->SymbolicLinkReparseBuffer.Flags = SYMLINK_FLAG_RELATIVE; memcpy(rdb->SymbolicLinkReparseBuffer.PathBuffer, pathlinku.c_str(), rdb->SymbolicLinkReparseBuffer.SubstituteNameLength); memcpy(rdb->SymbolicLinkReparseBuffer.PathBuffer + (rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR)), pathlinku.c_str(), rdb->SymbolicLinkReparseBuffer.PrintNameLength); - h = CreateFileW((subvolpath + nameu).c_str(), GENERIC_WRITE | WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); + win_handle h = CreateFileW((subvolpath + nameu).c_str(), GENERIC_WRITE | WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, nameu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); free(rdb); - return FALSE; + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, nameu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); } - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_SET_REPARSE_POINT, rdb, rdblen, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_SET_REPARSE_POINT, rdb, rdblen, nullptr, 0); if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SET_REPARSE_POINT_FAILED, Status, format_ntstatus(Status).c_str()); free(rdb); - CloseHandle(h); - return FALSE; + throw string_error(IDS_RECV_SET_REPARSE_POINT_FAILED, Status, format_ntstatus(Status).c_str()); } free(rdb); memset(&bsii, 0, sizeof(btrfs_set_inode_info)); - bsii.mode_changed = TRUE; + bsii.mode_changed = true; bsii.st_mode = 0777; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return FALSE; - } - - CloseHandle(h); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); } else if (cmd->cmd == BTRFS_SEND_CMD_MKNOD || cmd->cmd == BTRFS_SEND_CMD_MKFIFO || cmd->cmd == BTRFS_SEND_CMD_MKSOCK) { - UINT64* mode; + uint64_t* mode; ULONG modelen; if (find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen)) { - HANDLE h; btrfs_set_inode_info bsii; - if (modelen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(UINT64)); - return FALSE; - } + if (modelen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(uint64_t)); - h = CreateFileW((subvolpath + nameu).c_str(), WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, nameu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + win_handle h = CreateFileW((subvolpath + nameu).c_str(), WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, nameu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); memset(&bsii, 0, sizeof(btrfs_set_inode_info)); - bsii.mode_changed = TRUE; - bsii.st_mode = *mode; + bsii.mode_changed = true; + bsii.st_mode = (uint32_t)*mode; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return FALSE; - } - - CloseHandle(h); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); } } - - return TRUE; } -BOOL BtrfsRecv::cmd_rename(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *path, *path_to; - ULONG path_len, path_to_len; - std::wstring pathu, path_tou; +void BtrfsRecv::cmd_rename(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu, path_tou; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &path_len)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG path_len; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_TO, (void**)&path_to, &path_to_len)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path_to"); - return FALSE; + { + char* path_to; + ULONG path_to_len; + + 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); } - if (!utf8_to_utf16(hwnd, path, path_len, &pathu)) - return FALSE; - - if (!utf8_to_utf16(hwnd, path_to, path_to_len, &path_tou)) - return FALSE; - - if (!MoveFileW((subvolpath + pathu).c_str(), (subvolpath + path_tou).c_str())) { - ShowRecvError(IDS_RECV_MOVEFILE_FAILED, pathu.c_str(), path_tou.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - return TRUE; + if (!MoveFileW((subvolpath + pathu).c_str(), (subvolpath + path_tou).c_str())) + throw string_error(IDS_RECV_MOVEFILE_FAILED, pathu.c_str(), path_tou.c_str(), GetLastError(), format_message(GetLastError()).c_str()); } -BOOL BtrfsRecv::cmd_link(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *path, *path_link; - ULONG path_len, path_link_len; - std::wstring pathu, path_linku; +void BtrfsRecv::cmd_link(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu, path_linku; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &path_len)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG path_len; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH_LINK, (void**)&path_link, &path_link_len)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path_link"); - return FALSE; + { + char* path_link; + ULONG path_link_len; + + 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); } - if (!utf8_to_utf16(hwnd, path, path_len, &pathu)) - return FALSE; - - if (!utf8_to_utf16(hwnd, path_link, path_link_len, &path_linku)) - return FALSE; - - if (!CreateHardLinkW((subvolpath + pathu).c_str(), (subvolpath + path_linku).c_str(), NULL)) { - ShowRecvError(IDS_RECV_CREATEHARDLINK_FAILED, pathu.c_str(), path_linku.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - return TRUE; + if (!CreateHardLinkW((subvolpath + pathu).c_str(), (subvolpath + path_linku).c_str(), nullptr)) + throw string_error(IDS_RECV_CREATEHARDLINK_FAILED, pathu.c_str(), path_linku.c_str(), GetLastError(), format_message(GetLastError()).c_str()); } -BOOL BtrfsRecv::cmd_unlink(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* path; - ULONG pathlen; - std::wstring pathu; +void BtrfsRecv::cmd_unlink(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu; ULONG att; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; - } + { + char* path; + ULONG pathlen; - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; + 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); + } att = GetFileAttributesW((subvolpath + pathu).c_str()); - if (att == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (att == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - if (!DeleteFileW((subvolpath + pathu).c_str())) { - ShowRecvError(IDS_RECV_DELETEFILE_FAILED, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - return TRUE; + if (!DeleteFileW((subvolpath + pathu).c_str())) + throw string_error(IDS_RECV_DELETEFILE_FAILED, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); } -BOOL BtrfsRecv::cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* path; - ULONG pathlen; - std::wstring pathu; +void BtrfsRecv::cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu; ULONG att; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; - } + { + char* path; + ULONG pathlen; - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; + 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); + } att = GetFileAttributesW((subvolpath + pathu).c_str()); - if (att == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (att == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - if (!RemoveDirectoryW((subvolpath + pathu).c_str())) { - ShowRecvError(IDS_RECV_REMOVEDIRECTORY_FAILED, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - return TRUE; + if (!RemoveDirectoryW((subvolpath + pathu).c_str())) + throw string_error(IDS_RECV_REMOVEDIRECTORY_FAILED, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); } -BOOL BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *path, *xattrname; - UINT8* xattrdata; - ULONG pathlen, xattrnamelen, xattrdatalen; - std::wstring pathu; +void BtrfsRecv::cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + string xattrname; + uint8_t* xattrdata; + ULONG xattrdatalen; + wstring pathu; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_NAME, (void**)&xattrname, &xattrnamelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"xattr_name"); - return FALSE; + { + char* xattrnamebuf; + ULONG xattrnamelen; + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_NAME, (void**)&xattrnamebuf, &xattrnamelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"xattr_name"); + + xattrname = string(xattrnamebuf, xattrnamelen); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_DATA, (void**)&xattrdata, &xattrdatalen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"xattr_data"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_DATA, (void**)&xattrdata, &xattrdatalen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"xattr_data"); - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - if (xattrnamelen > strlen(XATTR_USER) && !memcmp(xattrname, XATTR_USER, strlen(XATTR_USER)) && - (xattrnamelen != strlen(EA_DOSATTRIB) || memcmp(xattrname, EA_DOSATTRIB, xattrnamelen)) && - (xattrnamelen != strlen(EA_EA) || memcmp(xattrname, EA_EA, xattrnamelen)) && - (xattrnamelen != strlen(EA_REPARSE) || memcmp(xattrname, EA_REPARSE, xattrnamelen))) { - HANDLE h; - std::wstring streamname; + 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; - if (!utf8_to_utf16(hwnd, xattrname, xattrnamelen, &streamname)) - return FALSE; + utf8_to_utf16(xattrname, streamname); att = GetFileAttributesW((subvolpath + pathu).c_str()); - if (att == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (att == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - streamname = streamname.substr(strlen(XATTR_USER)); + streamname = streamname.substr(XATTR_USER.length()); - h = CreateFileW((subvolpath + pathu + L":" + streamname).c_str(), GENERIC_WRITE, 0, - NULL, CREATE_ALWAYS, FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_CREATE_FILE, (pathu + L":" + streamname).c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + win_handle h = CreateFileW((subvolpath + pathu + L":" + streamname).c_str(), GENERIC_WRITE, 0, + nullptr, CREATE_ALWAYS, FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_CREATE_FILE, (pathu + L":" + streamname).c_str(), GetLastError(), format_message(GetLastError()).c_str()); if (xattrdatalen > 0) { - if (!WriteFile(h, xattrdata, xattrdatalen, NULL, NULL)) { - ShowRecvError(IDS_RECV_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(h); - return FALSE; - } + if (!WriteFile(h, xattrdata, xattrdatalen, nullptr, nullptr)) + throw string_error(IDS_RECV_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - CloseHandle(h); - if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } } else { - HANDLE h; IO_STATUS_BLOCK iosb; NTSTATUS Status; ULONG bsxalen, perms = FILE_WRITE_ATTRIBUTES; btrfs_set_xattr* bsxa; - if (xattrnamelen == strlen(EA_NTACL) && !memcmp(xattrname, EA_NTACL, xattrnamelen)) + if (xattrname == EA_NTACL) perms |= WRITE_DAC | WRITE_OWNER; - else if (xattrnamelen == strlen(EA_EA) && !memcmp(xattrname, EA_EA, xattrnamelen)) + else if (xattrname == EA_EA) perms |= FILE_WRITE_EA; - h = CreateFileW((subvolpath + pathu).c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_OPEN_REPARSE_POINT, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + win_handle h = CreateFileW((subvolpath + pathu).c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_OPEN_REPARSE_POINT, nullptr); + 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]) + xattrnamelen + xattrdatalen; + bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length() + xattrdatalen; bsxa = (btrfs_set_xattr*)malloc(bsxalen); - if (!bsxa) { - ShowRecvError(IDS_OUT_OF_MEMORY); - CloseHandle(h); - return FALSE; - } + if (!bsxa) + throw string_error(IDS_OUT_OF_MEMORY); - bsxa->namelen = xattrnamelen; - bsxa->valuelen = xattrdatalen; - memcpy(bsxa->data, xattrname, xattrnamelen); - memcpy(&bsxa->data[xattrnamelen], xattrdata, xattrdatalen); + bsxa->namelen = (uint16_t)xattrname.length(); + bsxa->valuelen = (uint16_t)xattrdatalen; + memcpy(bsxa->data, xattrname.c_str(), xattrname.length()); + memcpy(&bsxa->data[xattrname.length()], xattrdata, xattrdatalen); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, nullptr, 0); if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str()); free(bsxa); - CloseHandle(h); - return FALSE; + throw string_error(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str()); } free(bsxa); - CloseHandle(h); } - - return TRUE; } -BOOL BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *path, *xattrname; - ULONG pathlen, xattrnamelen; - std::wstring pathu; +void BtrfsRecv::cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu; + string xattrname; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_NAME, (void**)&xattrname, &xattrnamelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"xattr_name"); - return FALSE; + { + char* xattrnamebuf; + ULONG xattrnamelen; + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_XATTR_NAME, (void**)&xattrnamebuf, &xattrnamelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"xattr_name"); + + xattrname = string(xattrnamebuf, xattrnamelen); } - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - if (xattrnamelen > strlen(XATTR_USER) && !memcmp(xattrname, XATTR_USER, strlen(XATTR_USER)) && - (xattrnamelen != strlen(EA_DOSATTRIB) || memcmp(xattrname, EA_DOSATTRIB, xattrnamelen)) && - (xattrnamelen != strlen(EA_EA) || memcmp(xattrname, EA_EA, xattrnamelen))) { // deleting stream + if (xattrname.length() > XATTR_USER.length() && xattrname.substr(0, XATTR_USER.length()) == XATTR_USER && xattrname != EA_DOSATTRIB && xattrname != EA_EA) { // deleting stream ULONG att; - std::wstring streamname; + wstring streamname; - if (!utf8_to_utf16(hwnd, xattrname, xattrnamelen, &streamname)) - return FALSE; + utf8_to_utf16(xattrname, streamname); - streamname = streamname.substr(strlen(XATTR_USER)); + streamname = streamname.substr(XATTR_USER.length()); att = GetFileAttributesW((subvolpath + pathu).c_str()); - if (att == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (att == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - if (!DeleteFileW((subvolpath + pathu + L":" + streamname).c_str())) { - ShowRecvError(IDS_RECV_DELETEFILE_FAILED, (pathu + L":" + streamname).c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!DeleteFileW((subvolpath + pathu + L":" + streamname).c_str())) + throw string_error(IDS_RECV_DELETEFILE_FAILED, (pathu + L":" + streamname).c_str(), GetLastError(), format_message(GetLastError()).c_str()); if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } } else { - HANDLE h; IO_STATUS_BLOCK iosb; NTSTATUS Status; ULONG bsxalen, perms = FILE_WRITE_ATTRIBUTES; btrfs_set_xattr* bsxa; - if (xattrnamelen == strlen(EA_NTACL) && !memcmp(xattrname, EA_NTACL, xattrnamelen)) + if (xattrname == EA_NTACL) perms |= WRITE_DAC | WRITE_OWNER; - else if (xattrnamelen == strlen(EA_EA) && !memcmp(xattrname, EA_EA, xattrnamelen)) + else if (xattrname == EA_EA) perms |= FILE_WRITE_EA; - h = CreateFileW((subvolpath + pathu).c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_OPEN_REPARSE_POINT, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + win_handle h = CreateFileW((subvolpath + pathu).c_str(), perms, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS | FILE_OPEN_REPARSE_POINT, nullptr); + 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]) + xattrnamelen; + bsxalen = offsetof(btrfs_set_xattr, data[0]) + xattrname.length(); bsxa = (btrfs_set_xattr*)malloc(bsxalen); - if (!bsxa) { - ShowRecvError(IDS_OUT_OF_MEMORY); - CloseHandle(h); - return FALSE; - } + if (!bsxa) + throw string_error(IDS_OUT_OF_MEMORY); - bsxa->namelen = xattrnamelen; + bsxa->namelen = (uint16_t)(xattrname.length()); bsxa->valuelen = 0; - memcpy(bsxa->data, xattrname, xattrnamelen); + memcpy(bsxa->data, xattrname.c_str(), xattrname.length()); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, bsxa, bsxalen, nullptr, 0); if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str()); free(bsxa); - CloseHandle(h); - return FALSE; + throw string_error(IDS_RECV_SETXATTR_FAILED, Status, format_ntstatus(Status).c_str()); } free(bsxa); - CloseHandle(h); } - - return TRUE; } -BOOL BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* path; - UINT64* offset; - UINT8* writedata; - ULONG pathlen, offsetlen, datalen; - std::wstring pathu; +void BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + uint64_t* offset; + uint8_t* writedata; + ULONG offsetlen, datalen; + wstring pathu; HANDLE h; LARGE_INTEGER offli; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_OFFSET, (void**)&offset, &offsetlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"offset"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_OFFSET, (void**)&offset, &offsetlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"offset"); - if (offsetlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"offset", offsetlen, sizeof(UINT64)); - return FALSE; - } + if (offsetlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"offset", offsetlen, sizeof(uint64_t)); - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_DATA, (void**)&writedata, &datalen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"data"); - return FALSE; - } - - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_DATA, (void**)&writedata, &datalen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"data"); if (lastwritepath != pathu) { FILE_BASIC_INFO fbi; if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } CloseHandle(lastwritefile); lastwriteatt = GetFileAttributesW((subvolpath + pathu).c_str()); - if (lastwriteatt == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (lastwriteatt == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), lastwriteatt & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), lastwriteatt & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); lastwritepath = pathu; lastwritefile = h; @@ -1064,113 +884,87 @@ BOOL BtrfsRecv::cmd_write(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { fbi.LastWriteTime.QuadPart = -1; - if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) { - ShowRecvError(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) + throw string_error(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } else h = lastwritefile; offli.QuadPart = *offset; - if (SetFilePointer(h, offli.LowPart, &offli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - ShowRecvError(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (SetFilePointer(h, offli.LowPart, &offli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + throw string_error(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - if (!WriteFile(h, writedata, datalen, NULL, NULL)) { - ShowRecvError(IDS_RECV_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - return TRUE; + if (!WriteFile(h, writedata, datalen, nullptr, nullptr)) + throw string_error(IDS_RECV_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } -BOOL BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char *path, *clonepath; - UINT64 *offset, *cloneoffset, *clonetransid, *clonelen; +void BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + uint64_t *offset, *cloneoffset, *clonetransid, *clonelen; BTRFS_UUID* cloneuuid; - ULONG i, offsetlen, pathlen, clonepathlen, cloneoffsetlen, cloneuuidlen, clonetransidlen, clonelenlen; - std::wstring pathu, clonepathu, clonepar; + ULONG i, offsetlen, cloneoffsetlen, cloneuuidlen, clonetransidlen, clonelenlen; + wstring pathu, clonepathu, clonepar; btrfs_find_subvol bfs; NTSTATUS Status; IO_STATUS_BLOCK iosb; WCHAR cloneparw[MAX_PATH]; - HANDLE src, dest; DUPLICATE_EXTENTS_DATA ded; LARGE_INTEGER filesize; - BOOL found = FALSE; + bool found = false; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_OFFSET, (void**)&offset, &offsetlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"offset"); - return FALSE; + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_OFFSET, (void**)&offset, &offsetlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"offset"); + + if (offsetlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"offset", offsetlen, sizeof(uint64_t)); + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_LENGTH, (void**)&clonelen, &clonelenlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_len"); + + if (clonelenlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_len", clonelenlen, sizeof(uint64_t)); + + { + char* path; + ULONG pathlen; + + 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); } - if (offsetlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"offset", offsetlen, sizeof(UINT64)); - return FALSE; + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_UUID, (void**)&cloneuuid, &cloneuuidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_uuid"); + + if (cloneuuidlen < sizeof(BTRFS_UUID)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_uuid", cloneuuidlen, sizeof(BTRFS_UUID)); + + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_CTRANSID, (void**)&clonetransid, &clonetransidlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_ctransid"); + + if (clonetransidlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_ctransid", clonetransidlen, sizeof(uint64_t)); + + { + char* clonepath; + ULONG clonepathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_LENGTH, (void**)&clonelen, &clonelenlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_len"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_OFFSET, (void**)&cloneoffset, &cloneoffsetlen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"clone_offset"); - if (clonelenlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_len", clonelenlen, sizeof(UINT64)); - return FALSE; - } - - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; - } - - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_UUID, (void**)&cloneuuid, &cloneuuidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_uuid"); - return FALSE; - } - - if (cloneuuidlen < sizeof(BTRFS_UUID)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_uuid", cloneuuidlen, sizeof(BTRFS_UUID)); - return FALSE; - } - - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_CTRANSID, (void**)&clonetransid, &clonetransidlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_ctransid"); - return FALSE; - } - - if (clonetransidlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_ctransid", clonetransidlen, sizeof(UINT64)); - return FALSE; - } - - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_PATH, (void**)&clonepath, &clonepathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_path"); - return FALSE; - } - - if (!utf8_to_utf16(hwnd, clonepath, clonepathlen, &clonepathu)) - return FALSE; - - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_CLONE_OFFSET, (void**)&cloneoffset, &cloneoffsetlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"clone_offset"); - return FALSE; - } - - if (cloneoffsetlen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"clone_offset", cloneoffsetlen, sizeof(UINT64)); - return FALSE; - } + if (cloneoffsetlen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"clone_offset", cloneoffsetlen, sizeof(uint64_t)); for (i = 0; i < cache.size(); i++) { if (!memcmp(cloneuuid, &cache[i].uuid, sizeof(BTRFS_UUID)) && *clonetransid == cache[i].transid) { clonepar = cache[i].path; - found = TRUE; + found = true; break; } } @@ -1181,20 +975,15 @@ BOOL BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { bfs.uuid = *cloneuuid; bfs.ctransid = *clonetransid; - Status = NtFsControlFile(dir, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_FIND_SUBVOL, &bfs, sizeof(btrfs_find_subvol), + Status = NtFsControlFile(dir, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_FIND_SUBVOL, &bfs, sizeof(btrfs_find_subvol), cloneparw, sizeof(cloneparw)); - if (Status == STATUS_NOT_FOUND) { - ShowRecvError(IDS_RECV_CANT_FIND_CLONE_SUBVOL); - return FALSE; - } else if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_FIND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - return FALSE; - } + if (Status == STATUS_NOT_FOUND) + throw string_error(IDS_RECV_CANT_FIND_CLONE_SUBVOL); + else if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_FIND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - if (!GetVolumePathNameW(dirpath.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) { - ShowRecvError(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!GetVolumePathNameW(dirpath.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) + throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); clonepar = volpathw; if (clonepar.substr(clonepar.length() - 1) == L"\\") @@ -1206,237 +995,175 @@ BOOL BtrfsRecv::cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { add_cache_entry(cloneuuid, *clonetransid, clonepar); } - src = CreateFileW((clonepar + clonepathu).c_str(), FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (src == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, (clonepar + clonepathu).c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + { + win_handle src = CreateFileW((clonepar + clonepathu).c_str(), FILE_READ_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (src == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, (clonepar + clonepathu).c_str(), GetLastError(), format_message(GetLastError()).c_str()); - dest = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (dest == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(src); - return FALSE; - } + win_handle dest = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (dest == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - if (!GetFileSizeEx(dest, &filesize)) { - ShowRecvError(IDS_RECV_GETFILESIZEEX_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(dest); - CloseHandle(src); - return FALSE; - } + if (!GetFileSizeEx(dest, &filesize)) + throw string_error(IDS_RECV_GETFILESIZEEX_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - if ((UINT64)filesize.QuadPart < *offset + *clonelen) { - LARGE_INTEGER sizeli; + if ((uint64_t)filesize.QuadPart < *offset + *clonelen) { + LARGE_INTEGER sizeli; - sizeli.QuadPart = *offset + *clonelen; + sizeli.QuadPart = *offset + *clonelen; - if (SetFilePointer(dest, sizeli.LowPart, &sizeli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - ShowRecvError(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(dest); - CloseHandle(src); - return FALSE; + if (SetFilePointer(dest, sizeli.LowPart, &sizeli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + throw string_error(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + if (!SetEndOfFile(dest)) + throw string_error(IDS_RECV_SETENDOFFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - if (!SetEndOfFile(dest)) { - ShowRecvError(IDS_RECV_SETENDOFFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(dest); - CloseHandle(src); - return FALSE; - } + ded.FileHandle = src; + ded.SourceFileOffset.QuadPart = *cloneoffset; + ded.TargetFileOffset.QuadPart = *offset; + ded.ByteCount.QuadPart = *clonelen; + + Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), + nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_DUPLICATE_EXTENTS_FAILED, Status, format_ntstatus(Status).c_str()); } - - ded.FileHandle = src; - ded.SourceFileOffset.QuadPart = *cloneoffset; - ded.TargetFileOffset.QuadPart = *offset; - ded.ByteCount.QuadPart = *clonelen; - - Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), - NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_DUPLICATE_EXTENTS_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(dest); - CloseHandle(src); - return FALSE; - } - - CloseHandle(dest); - CloseHandle(src); - - return TRUE; } -BOOL BtrfsRecv::cmd_truncate(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* path; - UINT64* size; - ULONG pathlen, sizelen; - std::wstring pathu; - HANDLE h; +void BtrfsRecv::cmd_truncate(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + uint64_t* size; + ULONG sizelen; + wstring pathu; LARGE_INTEGER sizeli; DWORD att; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_SIZE, (void**)&size, &sizelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"size"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_SIZE, (void**)&size, &sizelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"size"); - if (sizelen < sizeof(UINT64)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"size", sizelen, sizeof(UINT64)); - return FALSE; - } - - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; + if (sizelen < sizeof(uint64_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"size", sizelen, sizeof(uint64_t)); att = GetFileAttributesW((subvolpath + pathu).c_str()); - if (att == INVALID_FILE_ATTRIBUTES) { - ShowRecvError(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; + if (att == INVALID_FILE_ATTRIBUTES) + throw string_error(IDS_RECV_GETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + if (att & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + } + + { + win_handle h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); + + sizeli.QuadPart = *size; + + if (SetFilePointer(h, sizeli.LowPart, &sizeli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + throw string_error(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + if (!SetEndOfFile(h)) + throw string_error(IDS_RECV_SETENDOFFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att & ~FILE_ATTRIBUTE_READONLY)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } - - h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_DATA, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - - sizeli.QuadPart = *size; - - if (SetFilePointer(h, sizeli.LowPart, &sizeli.HighPart, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { - ShowRecvError(IDS_RECV_SETFILEPOINTER_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(h); - return FALSE; - } - - if (!SetEndOfFile(h)) { - ShowRecvError(IDS_RECV_SETENDOFFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(h); - return FALSE; - } - - CloseHandle(h); - - if (att & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + pathu).c_str(), att)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } - } - - return TRUE; } -BOOL BtrfsRecv::cmd_chmod(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - HANDLE h; - char* path; - UINT32* mode; - ULONG pathlen, modelen; - std::wstring pathu; +void BtrfsRecv::cmd_chmod(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + win_handle h; + uint32_t* mode; + ULONG modelen; + wstring pathu; btrfs_set_inode_info bsii; NTSTATUS Status; IO_STATUS_BLOCK iosb; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"mode"); - return FALSE; - } + if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_MODE, (void**)&mode, &modelen)) + throw string_error(IDS_RECV_MISSING_PARAM, funcname, L"mode"); - if (modelen < sizeof(UINT32)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(UINT32)); - return FALSE; - } + if (modelen < sizeof(uint32_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"mode", modelen, sizeof(uint32_t)); - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - h = CreateFileW((subvolpath + pathu).c_str(), WRITE_DAC, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + h = CreateFileW((subvolpath + pathu).c_str(), WRITE_DAC, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); memset(&bsii, 0, sizeof(btrfs_set_inode_info)); - bsii.mode_changed = TRUE; + bsii.mode_changed = true; bsii.st_mode = *mode; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return FALSE; - } - - CloseHandle(h); - - return TRUE; + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); } -BOOL BtrfsRecv::cmd_chown(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - HANDLE h; - char* path; - UINT32 *uid, *gid; - ULONG pathlen, uidlen, gidlen; - std::wstring pathu; +void BtrfsRecv::cmd_chown(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + win_handle h; + uint32_t *uid, *gid; + ULONG uidlen, gidlen; + wstring pathu; btrfs_set_inode_info bsii; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES | WRITE_OWNER | WRITE_DAC, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES | WRITE_OWNER | WRITE_DAC, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); memset(&bsii, 0, sizeof(btrfs_set_inode_info)); if (find_tlv(data, cmd->length, BTRFS_SEND_TLV_UID, (void**)&uid, &uidlen)) { - if (uidlen < sizeof(UINT32)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"uid", uidlen, sizeof(UINT32)); - CloseHandle(h); - return FALSE; - } + if (uidlen < sizeof(uint32_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"uid", uidlen, sizeof(uint32_t)); - bsii.uid_changed = TRUE; + bsii.uid_changed = true; bsii.st_uid = *uid; } if (find_tlv(data, cmd->length, BTRFS_SEND_TLV_GID, (void**)&gid, &gidlen)) { - if (gidlen < sizeof(UINT32)) { - ShowRecvError(IDS_RECV_SHORT_PARAM, funcname, L"gid", gidlen, sizeof(UINT32)); - CloseHandle(h); - return FALSE; - } + if (gidlen < sizeof(uint32_t)) + throw string_error(IDS_RECV_SHORT_PARAM, funcname, L"gid", gidlen, sizeof(uint32_t)); - bsii.gid_changed = TRUE; + bsii.gid_changed = true; bsii.st_gid = *gid; } @@ -1444,46 +1171,37 @@ BOOL BtrfsRecv::cmd_chown(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { NTSTATUS Status; IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return FALSE; - } + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_SETINODEINFO_FAILED, Status, format_ntstatus(Status).c_str()); } - - CloseHandle(h); - - return TRUE; } -static __inline UINT64 unix_time_to_win(BTRFS_TIME* t) { +static __inline uint64_t unix_time_to_win(BTRFS_TIME* t) { return (t->seconds * 10000000) + (t->nanoseconds / 100) + 116444736000000000; } -BOOL BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, UINT8* data) { - char* path; - ULONG pathlen; - std::wstring pathu; - HANDLE h; +void BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data) { + wstring pathu; + win_handle h; FILE_BASIC_INFO fbi; BTRFS_TIME* time; ULONG timelen; - if (!find_tlv(data, cmd->length, BTRFS_SEND_TLV_PATH, (void**)&path, &pathlen)) { - ShowRecvError(IDS_RECV_MISSING_PARAM, funcname, L"path"); - return FALSE; + { + char* path; + ULONG pathlen; + + 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); } - if (!utf8_to_utf16(hwnd, path, pathlen, &pathu)) - return FALSE; - - h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + h = CreateFileW((subvolpath + pathu).c_str(), FILE_WRITE_ATTRIBUTES, 0, nullptr, OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_OPEN_REPARSE_POINT | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, pathu.c_str(), GetLastError(), format_message(GetLastError()).c_str()); memset(&fbi, 0, sizeof(FILE_BASIC_INFO)); @@ -1499,54 +1217,20 @@ BOOL BtrfsRecv::cmd_utimes(HWND hwnd, btrfs_send_command* cmd, UINT8* 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))) { - ShowRecvError(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(h); - return FALSE; - } - - CloseHandle(h); - - return TRUE; + if (!SetFileInformationByHandle(h, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO))) + throw string_error(IDS_RECV_SETFILEINFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } -void BtrfsRecv::ShowRecvError(int resid, ...) { - WCHAR s[1024], t[1024]; - va_list ap; - - if (!hwnd) - return; - - if (!LoadStringW(module, resid, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return; - } - - va_start(ap, resid); -#ifndef __REACTOS__ - vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#else - vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#endif - - SetDlgItemTextW(hwnd, IDC_RECV_MSG, t); - - va_end(ap); - - SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETSTATE, PBST_ERROR, 0); -} - -static void delete_directory(std::wstring dir) { - HANDLE h; +static void delete_directory(const wstring& dir) { WIN32_FIND_DATAW fff; - h = FindFirstFileW((dir + L"*").c_str(), &fff); + fff_handle h = FindFirstFileW((dir + L"*").c_str(), &fff); if (h == INVALID_HANDLE_VALUE) return; do { - std::wstring file; + wstring file; file = fff.cFileName; @@ -1564,328 +1248,290 @@ static void delete_directory(std::wstring dir) { } } while (FindNextFileW(h, &fff)); - FindClose(h); - RemoveDirectoryW(dir.c_str()); } -static BOOL check_csum(btrfs_send_command* cmd, UINT8* data) { - UINT32 crc32 = cmd->csum, calc; +static bool check_csum(btrfs_send_command* cmd, uint8_t* data) { + uint32_t crc32 = cmd->csum, calc; cmd->csum = 0; - calc = calc_crc32c(0, (UINT8*)cmd, sizeof(btrfs_send_command)); + calc = calc_crc32c(0, (uint8_t*)cmd, sizeof(btrfs_send_command)); if (cmd->length > 0) calc = calc_crc32c(calc, data, cmd->length); - return calc == crc32 ? TRUE : FALSE; + return calc == crc32 ? true : false; } -BOOL BtrfsRecv::do_recv(HANDLE f, UINT64* pos, UINT64 size) { - btrfs_send_header header; - BOOL b = TRUE, ended = FALSE; +void BtrfsRecv::do_recv(const win_handle& f, uint64_t* pos, uint64_t size, const win_handle& parent) { + try { + btrfs_send_header header; + bool ended = false; - if (!ReadFile(f, &header, sizeof(btrfs_send_header), NULL, NULL)) { - ShowRecvError(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + if (!ReadFile(f, &header, sizeof(btrfs_send_header), nullptr, nullptr)) + throw string_error(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - *pos += sizeof(btrfs_send_header); + *pos += sizeof(btrfs_send_header); - if (memcmp(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic))) { - ShowRecvError(IDS_RECV_NOT_A_SEND_STREAM); - return FALSE; - } + if (memcmp(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic))) + throw string_error(IDS_RECV_NOT_A_SEND_STREAM); - if (header.version > 1) { - ShowRecvError(IDS_RECV_UNSUPPORTED_VERSION, header.version); - return FALSE; - } + if (header.version > 1) + throw string_error(IDS_RECV_UNSUPPORTED_VERSION, header.version); - SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETRANGE32, 0, (LPARAM)65536); + SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETRANGE32, 0, (LPARAM)65536); - lastwritefile = INVALID_HANDLE_VALUE; - lastwritepath = L""; - lastwriteatt = 0; + lastwritefile = INVALID_HANDLE_VALUE; + lastwritepath = L""; + lastwriteatt = 0; - while (TRUE) { - btrfs_send_command cmd; - UINT8* data; - ULONG progress; + while (true) { + btrfs_send_command cmd; + uint8_t* data = nullptr; + ULONG progress; - if (cancelling) { - b = FALSE; - break; - } + if (cancelling) + break; - progress = (ULONG)((float)*pos * 65536.0f / (float)size); - SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETPOS, progress, 0); + progress = (ULONG)((float)*pos * 65536.0f / (float)size); + SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETPOS, progress, 0); + + if (!ReadFile(f, &cmd, sizeof(btrfs_send_command), nullptr, nullptr)) { + if (GetLastError() != ERROR_HANDLE_EOF) + throw string_error(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - if (!ReadFile(f, &cmd, sizeof(btrfs_send_command), NULL, NULL)) { - if (GetLastError() != ERROR_HANDLE_EOF) { - ShowRecvError(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); break; } - break; - } + *pos += sizeof(btrfs_send_command); - *pos += sizeof(btrfs_send_command); + if (cmd.length > 0) { + if (*pos + cmd.length > size) + throw string_error(IDS_RECV_FILE_TRUNCATED); - if (cmd.length > 0) { - if (*pos + cmd.length > size) { - ShowRecvError(IDS_RECV_FILE_TRUNCATED); - b = FALSE; - break; + data = (uint8_t*)malloc(cmd.length); + if (!data) + throw string_error(IDS_OUT_OF_MEMORY); } - data = (UINT8*)malloc(cmd.length); - if (!data) { - ShowRecvError(IDS_OUT_OF_MEMORY); - b = FALSE; - break; - } + try { + if (data) { + if (!ReadFile(f, data, cmd.length, nullptr, nullptr)) + throw string_error(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - if (!ReadFile(f, data, cmd.length, NULL, NULL)) { - ShowRecvError(IDS_RECV_READFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - free(data); - b = FALSE; - break; - } - - *pos += cmd.length; - } else - data = NULL; - - if (!check_csum(&cmd, data)) { - ShowRecvError(IDS_RECV_CSUM_ERROR); - if (data) free(data); - b = FALSE; - break; - } - - if (cmd.cmd == BTRFS_SEND_CMD_END) { - if (data) free(data); - ended = TRUE; - break; - } - - if (lastwritefile != INVALID_HANDLE_VALUE && cmd.cmd != BTRFS_SEND_CMD_WRITE) { - if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; + *pos += cmd.length; } + + if (!check_csum(&cmd, data)) + throw string_error(IDS_RECV_CSUM_ERROR); + + if (cmd.cmd == BTRFS_SEND_CMD_END) { + ended = true; + break; + } + + if (lastwritefile != INVALID_HANDLE_VALUE && cmd.cmd != BTRFS_SEND_CMD_WRITE) { + if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + } + + CloseHandle(lastwritefile); + + lastwritefile = INVALID_HANDLE_VALUE; + lastwritepath = L""; + lastwriteatt = 0; + } + + switch (cmd.cmd) { + case BTRFS_SEND_CMD_SUBVOL: + cmd_subvol(hwnd, &cmd, data, parent); + break; + + case BTRFS_SEND_CMD_SNAPSHOT: + cmd_snapshot(hwnd, &cmd, data, parent); + break; + + case BTRFS_SEND_CMD_MKFILE: + case BTRFS_SEND_CMD_MKDIR: + case BTRFS_SEND_CMD_MKNOD: + case BTRFS_SEND_CMD_MKFIFO: + case BTRFS_SEND_CMD_MKSOCK: + case BTRFS_SEND_CMD_SYMLINK: + cmd_mkfile(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_RENAME: + cmd_rename(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_LINK: + cmd_link(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_UNLINK: + cmd_unlink(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_RMDIR: + cmd_rmdir(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_SET_XATTR: + cmd_setxattr(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_REMOVE_XATTR: + cmd_removexattr(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_WRITE: + cmd_write(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_CLONE: + cmd_clone(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_TRUNCATE: + cmd_truncate(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_CHMOD: + cmd_chmod(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_CHOWN: + cmd_chown(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_UTIMES: + cmd_utimes(hwnd, &cmd, data); + break; + + case BTRFS_SEND_CMD_UPDATE_EXTENT: + // does nothing + break; + + default: + throw string_error(IDS_RECV_UNKNOWN_COMMAND, cmd.cmd); + } + } catch (...) { + if (data) free(data); + throw; + } + + if (data) free(data); + } + + if (lastwritefile != INVALID_HANDLE_VALUE) { + if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { + if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) + throw string_error(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); } CloseHandle(lastwritefile); - - lastwritefile = INVALID_HANDLE_VALUE; - lastwritepath = L""; - lastwriteatt = 0; } - switch (cmd.cmd) { - case BTRFS_SEND_CMD_SUBVOL: - b = cmd_subvol(hwnd, &cmd, data); - break; + if (!ended && !cancelling) + throw string_error(IDS_RECV_FILE_TRUNCATED); - case BTRFS_SEND_CMD_SNAPSHOT: - b = cmd_snapshot(hwnd, &cmd, data); - break; + if (!cancelling) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + btrfs_received_subvol brs; - case BTRFS_SEND_CMD_MKFILE: - case BTRFS_SEND_CMD_MKDIR: - case BTRFS_SEND_CMD_MKNOD: - case BTRFS_SEND_CMD_MKFIFO: - case BTRFS_SEND_CMD_MKSOCK: - case BTRFS_SEND_CMD_SYMLINK: - b = cmd_mkfile(hwnd, &cmd, data); - break; + brs.generation = stransid; + brs.uuid = subvol_uuid; - case BTRFS_SEND_CMD_RENAME: - b = cmd_rename(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_LINK: - b = cmd_link(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_UNLINK: - b = cmd_unlink(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_RMDIR: - b = cmd_rmdir(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_SET_XATTR: - b = cmd_setxattr(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_REMOVE_XATTR: - b = cmd_removexattr(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_WRITE: - b = cmd_write(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_CLONE: - b = cmd_clone(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_TRUNCATE: - b = cmd_truncate(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_CHMOD: - b = cmd_chmod(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_CHOWN: - b = cmd_chown(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_UTIMES: - b = cmd_utimes(hwnd, &cmd, data); - break; - - case BTRFS_SEND_CMD_UPDATE_EXTENT: - // does nothing - break; - - default: - ShowRecvError(IDS_RECV_UNKNOWN_COMMAND, cmd.cmd); - b = FALSE; - break; + Status = NtFsControlFile(dir, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RECEIVED_SUBVOL, &brs, sizeof(btrfs_received_subvol), + nullptr, 0); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_RECV_RECEIVED_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); } - if (data) free(data); + CloseHandle(dir); - if (!b) - break; - } + if (master != INVALID_HANDLE_VALUE) + CloseHandle(master); + } catch (...) { + if (subvolpath != L"") { + ULONG attrib; - if (lastwritefile != INVALID_HANDLE_VALUE) { - if (lastwriteatt & FILE_ATTRIBUTE_READONLY) { - if (!SetFileAttributesW((subvolpath + lastwritepath).c_str(), lastwriteatt)) { - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return FALSE; - } + attrib = GetFileAttributesW(subvolpath.c_str()); + attrib &= ~FILE_ATTRIBUTE_READONLY; + + if (SetFileAttributesW(subvolpath.c_str(), attrib)) + delete_directory(subvolpath); } - CloseHandle(lastwritefile); + throw; } - - if (b && !ended) { - ShowRecvError(IDS_RECV_FILE_TRUNCATED); - b = FALSE; - } - - if (b) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - btrfs_received_subvol brs; - - brs.generation = stransid; - brs.uuid = subvol_uuid; - - Status = NtFsControlFile(dir, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RECEIVED_SUBVOL, &brs, sizeof(btrfs_received_subvol), - NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowRecvError(IDS_RECV_RECEIVED_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - b = FALSE; - } - } - - CloseHandle(dir); - - if (master != INVALID_HANDLE_VALUE) - CloseHandle(master); - - if (!b && subvolpath != L"") { - ULONG attrib; - - attrib = GetFileAttributesW(subvolpath.c_str()); - attrib &= ~FILE_ATTRIBUTE_READONLY; - - if (!SetFileAttributesW(subvolpath.c_str(), attrib)) - ShowRecvError(IDS_RECV_SETFILEATTRIBUTES_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - else - delete_directory(subvolpath); - } - - return b; } DWORD BtrfsRecv::recv_thread() { - HANDLE f; LARGE_INTEGER size; - UINT64 pos = 0; - BOOL b; + uint64_t pos = 0; + bool b = true; - running = TRUE; + running = true; - f = CreateFileW(streamfile.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL); - if (f == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_FILE, funcname, streamfile.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - goto end; + try { + win_handle f = CreateFileW(streamfile.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr); + if (f == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_FILE, funcname, streamfile.c_str(), GetLastError(), format_message(GetLastError()).c_str()); + + if (!GetFileSizeEx(f, &size)) + throw string_error(IDS_RECV_GETFILESIZEEX_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + { + win_handle parent = CreateFileW(dirpath.c_str(), FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, nullptr); + if (parent == INVALID_HANDLE_VALUE) + throw string_error(IDS_RECV_CANT_OPEN_PATH, dirpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); + + do { + do_recv(f, &pos, size.QuadPart, parent); + } while (pos < (uint64_t)size.QuadPart); + } + } catch (const exception& e) { + wstring msg; + + utf8_to_utf16(e.what(), msg); + + SetDlgItemTextW(hwnd, IDC_RECV_MSG, msg.c_str()); + + SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETSTATE, PBST_ERROR, 0); + + b = false; } - if (!GetFileSizeEx(f, &size)) { - ShowRecvError(IDS_RECV_GETFILESIZEEX_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - goto end; - } - - parent = CreateFileW(dirpath.c_str(), FILE_ADD_SUBDIRECTORY | FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_POSIX_SEMANTICS, NULL); - if (parent == INVALID_HANDLE_VALUE) { - ShowRecvError(IDS_RECV_CANT_OPEN_PATH, dirpath.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(f); - goto end; - } - - do { - b = do_recv(f, &pos, size.QuadPart); - } while (b && pos < (UINT64)size.QuadPart); - - CloseHandle(parent); - CloseHandle(f); - if (b && hwnd) { - WCHAR s[255]; + wstring s; SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETPOS, 65536, 0); if (num_received == 1) { - if (!LoadStringW(module, IDS_RECV_SUCCESS, s, sizeof(s) / sizeof(WCHAR))) - ShowError(hwnd, GetLastError()); - else - SetDlgItemTextW(hwnd, IDC_RECV_MSG, s); + load_string(module, IDS_RECV_SUCCESS, s); + SetDlgItemTextW(hwnd, IDC_RECV_MSG, s.c_str()); } else { - if (!LoadStringW(module, IDS_RECV_SUCCESS_PLURAL, s, sizeof(s) / sizeof(WCHAR))) - ShowError(hwnd, GetLastError()); - else { - WCHAR t[255]; + wstring t; - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, num_received) == STRSAFE_E_INSUFFICIENT_BUFFER) - ShowError(hwnd, ERROR_INSUFFICIENT_BUFFER); - else - SetDlgItemTextW(hwnd, IDC_RECV_MSG, t); - } + load_string(module, IDS_RECV_SUCCESS_PLURAL, s); + + wstring_sprintf(t, s, num_received); + + SetDlgItemTextW(hwnd, IDC_RECV_MSG, t.c_str()); } - if (!LoadStringW(module, IDS_RECV_BUTTON_OK, s, sizeof(s) / sizeof(WCHAR))) - ShowError(hwnd, GetLastError()); - else - SetDlgItemTextW(hwnd, IDCANCEL, s); + load_string(module, IDS_RECV_BUTTON_OK, s); + + SetDlgItemTextW(hwnd, IDCANCEL, s.c_str()); } -end: - thread = NULL; - running = FALSE; + thread = nullptr; + running = false; return 0; } @@ -1899,11 +1545,21 @@ static DWORD WINAPI global_recv_thread(LPVOID lpParameter) { INT_PTR CALLBACK BtrfsRecv::RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_INITDIALOG: - this->hwnd = hwndDlg; - thread = CreateThread(NULL, 0, global_recv_thread, this, 0, NULL); + try { + this->hwnd = hwndDlg; + thread = CreateThread(nullptr, 0, global_recv_thread, this, 0, nullptr); - if (!thread) - ShowRecvError(IDS_RECV_CREATETHREAD_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + 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); + + SetDlgItemTextW(hwnd, IDC_RECV_MSG, msg.c_str()); + + SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETSTATE, PBST_ERROR, 0); + } break; case WM_COMMAND: @@ -1913,35 +1569,31 @@ INT_PTR CALLBACK BtrfsRecv::RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM case IDOK: case IDCANCEL: if (running) { - WCHAR s[255]; + wstring s; - cancelling = TRUE; + cancelling = true; - if (!LoadStringW(module, IDS_RECV_CANCELLED, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return FALSE; - } + if (!load_string(module, IDS_RECV_CANCELLED, s)) + throw last_error(GetLastError()); - SetDlgItemTextW(hwnd, IDC_RECV_MSG, s); + SetDlgItemTextW(hwnd, IDC_RECV_MSG, s.c_str()); SendMessageW(GetDlgItem(hwnd, IDC_RECV_PROGRESS), PBM_SETPOS, 0, 0); - if (!LoadStringW(module, IDS_RECV_BUTTON_OK, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return FALSE; - } + if (!load_string(module, IDS_RECV_BUTTON_OK, s)) + throw last_error(GetLastError()); - SetDlgItemTextW(hwnd, IDCANCEL, s); + SetDlgItemTextW(hwnd, IDCANCEL, s.c_str()); } else EndDialog(hwndDlg, 1); - return TRUE; + return true; } break; } break; } - return FALSE; + return false; } static INT_PTR CALLBACK stub_RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -1957,12 +1609,12 @@ static INT_PTR CALLBACK stub_RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM if (br) return br->RecvProgressDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } -void BtrfsRecv::Open(HWND hwnd, WCHAR* file, WCHAR* path, BOOL quiet) { +void BtrfsRecv::Open(HWND hwnd, const wstring& file, const wstring& path, bool quiet) { #ifndef __REACTOS__ - UINT32 cpuInfo[4]; + uint32_t cpuInfo[4]; #endif streamfile = file; @@ -1983,7 +1635,7 @@ void BtrfsRecv::Open(HWND hwnd, WCHAR* file, WCHAR* path, BOOL quiet) { recv_thread(); else { if (DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_RECV_PROGRESS), hwnd, stub_RecvProgressDlgProc, (LPARAM)this) <= 0) - ShowError(hwnd, GetLastError()); + throw last_error(GetLastError()); } } @@ -1992,162 +1644,136 @@ extern "C" { #endif void CALLBACK RecvSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - OPENFILENAMEW ofn; - WCHAR file[MAX_PATH]; - BtrfsRecv* recv; - HANDLE token; - TOKEN_PRIVILEGES* tp; - LUID luid; - ULONG tplen; - - set_dpi_aware(); - - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; - } - - tplen = offsetof(TOKEN_PRIVILEGES, Privileges[0]) + (3 * sizeof(LUID_AND_ATTRIBUTES)); - tp = (TOKEN_PRIVILEGES*)malloc(tplen); - if (!tp) { - ShowStringError(hwnd, IDS_OUT_OF_MEMORY); - CloseHandle(token); - return; - } - - tp->PrivilegeCount = 3; - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - free(tp); - CloseHandle(token); - return; - } - - tp->Privileges[0].Luid = luid; - tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!LookupPrivilegeValueW(NULL, L"SeSecurityPrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - free(tp); - CloseHandle(token); - return; - } - - tp->Privileges[1].Luid = luid; - tp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; - - if (!LookupPrivilegeValueW(NULL, L"SeRestorePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - free(tp); - CloseHandle(token); - return; - } - - tp->Privileges[2].Luid = luid; - tp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, tp, tplen, NULL, NULL)) { - ShowError(hwnd, GetLastError()); - free(tp); - CloseHandle(token); - return; - } - - file[0] = 0; - - memset(&ofn, 0, sizeof(OPENFILENAMEW)); - ofn.lStructSize = sizeof(OPENFILENAMEW); - ofn.hwndOwner = hwnd; - ofn.hInstance = module; - ofn.lpstrFile = file; - ofn.nMaxFile = sizeof(file) / sizeof(WCHAR); - ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; - - if (GetOpenFileNameW(&ofn)) { - recv = new BtrfsRecv; - - recv->Open(hwnd, file, lpszCmdLine, FALSE); - - delete recv; - } - - free(tp); - CloseHandle(token); -} - -void CALLBACK RecvSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; - - args = CommandLineToArgvW(lpszCmdLine, &num_args); - - if (!args) - return; - - if (num_args >= 2) { - BtrfsRecv* br; - HANDLE token; + try { + OPENFILENAMEW ofn; + WCHAR file[MAX_PATH]; + win_handle token; TOKEN_PRIVILEGES* tp; - ULONG tplen; LUID luid; + ULONG tplen; + + set_dpi_aware(); if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) - goto end; + throw last_error(GetLastError()); tplen = offsetof(TOKEN_PRIVILEGES, Privileges[0]) + (3 * sizeof(LUID_AND_ATTRIBUTES)); tp = (TOKEN_PRIVILEGES*)malloc(tplen); - if (!tp) { - CloseHandle(token); - goto end; - } + if (!tp) + throw string_error(IDS_OUT_OF_MEMORY); tp->PrivilegeCount = 3; - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) { free(tp); - CloseHandle(token); - goto end; + throw last_error(GetLastError()); } tp->Privileges[0].Luid = luid; tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - if (!LookupPrivilegeValueW(NULL, L"SeSecurityPrivilege", &luid)) { + if (!LookupPrivilegeValueW(nullptr, L"SeSecurityPrivilege", &luid)) { free(tp); - CloseHandle(token); - goto end; + throw last_error(GetLastError()); } tp->Privileges[1].Luid = luid; tp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; - if (!LookupPrivilegeValueW(NULL, L"SeRestorePrivilege", &luid)) { + if (!LookupPrivilegeValueW(nullptr, L"SeRestorePrivilege", &luid)) { free(tp); - CloseHandle(token); - goto end; + throw last_error(GetLastError()); } tp->Privileges[2].Luid = luid; tp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; - if (!AdjustTokenPrivileges(token, FALSE, tp, tplen, NULL, NULL)) { + if (!AdjustTokenPrivileges(token, false, tp, tplen, nullptr, nullptr)) { free(tp); - CloseHandle(token); - goto end; + throw last_error(GetLastError()); + } + + file[0] = 0; + + memset(&ofn, 0, sizeof(OPENFILENAMEW)); + ofn.lStructSize = sizeof(OPENFILENAMEW); + ofn.hwndOwner = hwnd; + ofn.hInstance = module; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof(file) / sizeof(WCHAR); + ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; + + if (GetOpenFileNameW(&ofn)) { + BtrfsRecv recv; + + recv.Open(hwnd, file, lpszCmdLine, false); } free(tp); - CloseHandle(token); - - br = new BtrfsRecv; - br->Open(NULL, args[0], args[1], TRUE); - - delete br; + } catch (const exception& e) { + error_message(hwnd, e.what()); } +} -end: - LocalFree(args); +void CALLBACK RecvSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { + try { + vector args; + + command_line_to_args(lpszCmdLine, args); + + if (args.size() >= 2) { + win_handle token; + TOKEN_PRIVILEGES* tp; + ULONG tplen; + LUID luid; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + return; + + tplen = offsetof(TOKEN_PRIVILEGES, Privileges[0]) + (3 * sizeof(LUID_AND_ATTRIBUTES)); + tp = (TOKEN_PRIVILEGES*)malloc(tplen); + if (!tp) + return; + + tp->PrivilegeCount = 3; + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) { + free(tp); + return; + } + + tp->Privileges[0].Luid = luid; + tp->Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!LookupPrivilegeValueW(nullptr, L"SeSecurityPrivilege", &luid)) { + free(tp); + return; + } + + tp->Privileges[1].Luid = luid; + tp->Privileges[1].Attributes = SE_PRIVILEGE_ENABLED; + + if (!LookupPrivilegeValueW(nullptr, L"SeRestorePrivilege", &luid)) { + free(tp); + return; + } + + tp->Privileges[2].Luid = luid; + tp->Privileges[2].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, tp, tplen, nullptr, nullptr)) { + free(tp); + return; + } + + free(tp); + + BtrfsRecv br; + br.Open(nullptr, args[0], args[1], true); + } + } catch (const exception& e) { + cerr << "Error: " << e.what() << endl; + } } #ifdef __REACTOS__ diff --git a/dll/shellext/shellbtrfs/recv.h b/dll/shellext/shellbtrfs/recv.h index 8301a20f28e..90f0ef993c7 100644 --- a/dll/shellext/shellbtrfs/recv.h +++ b/dll/shellext/shellbtrfs/recv.h @@ -18,8 +18,6 @@ #pragma once #include -#include -#include #ifndef __REACTOS__ #include "../btrfs.h" #else @@ -30,21 +28,21 @@ extern LONG objs_loaded; typedef struct { BTRFS_UUID uuid; - UINT64 transid; - std::wstring path; + uint64_t transid; + wstring path; } subvol_cache; class BtrfsRecv { public: BtrfsRecv() { - thread = NULL; + thread = nullptr; master = INVALID_HANDLE_VALUE; dir = INVALID_HANDLE_VALUE; - running = FALSE; - cancelling = FALSE; + running = false; + cancelling = false; stransid = 0; num_received = 0; - hwnd = NULL; + hwnd = nullptr; cache.clear(); } @@ -52,39 +50,37 @@ public: cache.clear(); } - void Open(HWND hwnd, WCHAR* file, WCHAR* path, BOOL quiet); + void Open(HWND hwnd, const wstring& file, const wstring& path, bool quiet); DWORD recv_thread(); INT_PTR CALLBACK RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); private: - BOOL cmd_subvol(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_rename(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_link(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_unlink(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_write(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_truncate(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_chmod(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_chown(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - BOOL cmd_utimes(HWND hwnd, btrfs_send_command* cmd, UINT8* data); - void add_cache_entry(BTRFS_UUID* uuid, UINT64 transid, std::wstring path); - BOOL utf8_to_utf16(HWND hwnd, char* utf8, ULONG utf8len, std::wstring* utf16); - void ShowRecvError(int resid, ...); - BOOL find_tlv(UINT8* data, ULONG datalen, UINT16 type, void** value, ULONG* len); - BOOL do_recv(HANDLE f, UINT64* pos, UINT64 size); + void cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent); + void cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent); + void cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_rename(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_link(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_unlink(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_clone(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_truncate(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_chmod(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_chown(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data); + void add_cache_entry(BTRFS_UUID* uuid, uint64_t transid, const wstring& path); + bool find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len); + void do_recv(const win_handle& f, uint64_t* pos, uint64_t size, const win_handle& parent); - HANDLE dir, parent, master, thread, lastwritefile; + HANDLE dir, master, thread, lastwritefile; HWND hwnd; - std::wstring streamfile, dirpath, subvolpath, lastwritepath; + wstring streamfile, dirpath, subvolpath, lastwritepath; DWORD lastwriteatt; ULONG num_received; - UINT64 stransid; + uint64_t stransid; BTRFS_UUID subvol_uuid; - BOOL running, cancelling; - std::vector cache; + bool running, cancelling; + vector cache; }; diff --git a/dll/shellext/shellbtrfs/resource.h b/dll/shellext/shellbtrfs/resource.h index 2506652f743..793f86cc53b 100644 --- a/dll/shellext/shellbtrfs/resource.h +++ b/dll/shellext/shellbtrfs/resource.h @@ -196,6 +196,17 @@ #define IDS_BALANCE_CANCELLED_SHRINK 278 #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 +#define IDS_TVM_INSERTITEM_FAILED 290 +#define IDS_RECV_PATH_TOO_LONG 291 #define IDC_UID 1001 #define IDC_GID 1002 #define IDC_USERR 1003 @@ -226,6 +237,8 @@ #define IDC_SIZE_LZO 1022 #define IDC_VOL_SHOW_USAGE 1022 #define IDC_VOL_BALANCE 1023 +#define IDC_SIZE_ZSTD 1023 +#define IDC_COMPRESSION_RATIO 1023 #define IDC_PROFILES 1024 #define IDC_PROFILES_SINGLE 1025 #define IDC_PROFILES_DUP 1026 @@ -324,7 +337,7 @@ // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 173 +#define _APS_NEXT_RESOURCE_VALUE 175 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1073 #define _APS_NEXT_SYMED_VALUE 101 diff --git a/dll/shellext/shellbtrfs/scrub.cpp b/dll/shellext/shellbtrfs/scrub.cpp index 1faaa9ec5d0..c0b39c0ad4b 100644 --- a/dll/shellext/shellbtrfs/scrub.cpp +++ b/dll/shellext/shellbtrfs/scrub.cpp @@ -37,345 +37,287 @@ #include #include #endif -#include #define NO_SHLWAPI_STRFCNS #include #include void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) { - btrfs_query_scrub* bqs2 = NULL; - BOOL alloc_bqs2 = FALSE; + btrfs_query_scrub* bqs2 = nullptr; + bool alloc_bqs2 = false; NTSTATUS Status; - std::wstring s; - WCHAR t[255], u[255], dt[255], tm[255]; + wstring s, t, u; + WCHAR dt[255], tm[255]; FILETIME filetime; SYSTEMTIME systime; - UINT64 recoverable_errors = 0, unrecoverable_errors = 0; + uint64_t recoverable_errors = 0, unrecoverable_errors = 0; - if (bqs->num_errors > 0) { - HANDLE h; - IO_STATUS_BLOCK iosb; - ULONG len; + try { + if (bqs->num_errors > 0) { + win_handle h; + IO_STATUS_BLOCK iosb; + ULONG len; - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowError(hwndDlg, GetLastError()); - return; - } + h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - len = 0; + len = 0; - do { - len += 1024; + try { + do { + len += 1024; - if (bqs2) - free(bqs2); + if (bqs2) { + free(bqs2); + bqs2 = nullptr; + } - bqs2 = (btrfs_query_scrub*)malloc(len); + bqs2 = (btrfs_query_scrub*)malloc(len); - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, bqs2, len); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, bqs2, len); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - free(bqs2); - return; + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) + throw ntstatus_error(Status); + } while (Status == STATUS_BUFFER_OVERFLOW); + } catch (...) { + if (bqs2) + free(bqs2); + + throw; } - } while (Status == STATUS_BUFFER_OVERFLOW); - alloc_bqs2 = TRUE; + alloc_bqs2 = true; + } else + bqs2 = bqs; - CloseHandle(h); - } else - bqs2 = bqs; + // "scrub started" + if (bqs2->start_time.QuadPart > 0) { + filetime.dwLowDateTime = bqs2->start_time.LowPart; + filetime.dwHighDateTime = bqs2->start_time.HighPart; - s[0] = 0; + if (!FileTimeToSystemTime(&filetime, &systime)) + throw last_error(GetLastError()); - // "scrub started" - if (bqs2->start_time.QuadPart > 0) { - filetime.dwLowDateTime = bqs2->start_time.LowPart; - filetime.dwHighDateTime = bqs2->start_time.HighPart; + if (!SystemTimeToTzSpecificLocalTime(nullptr, &systime, &systime)) + throw last_error(GetLastError()); - if (!FileTimeToSystemTime(&filetime, &systime)) { - ShowError(hwndDlg, GetLastError()); - goto end; + if (!load_string(module, IDS_SCRUB_MSG_STARTED, t)) + throw last_error(GetLastError()); + + if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, nullptr, dt, sizeof(dt) / sizeof(WCHAR))) + throw last_error(GetLastError()); + + if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, nullptr, tm, sizeof(tm) / sizeof(WCHAR))) + throw last_error(GetLastError()); + + wstring_sprintf(u, t, dt, tm); + + s += u; + s += L"\r\n"; } - if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!LoadStringW(module, IDS_SCRUB_MSG_STARTED, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - s += u; - s += L"\r\n"; - } - - // errors - if (bqs2->num_errors > 0) { - btrfs_scrub_error* bse = &bqs2->errors; - - do { - if (bse->recovered) - recoverable_errors++; - else - unrecoverable_errors++; - - if (bse->parity) { - if (!LoadStringW(module, IDS_SCRUB_MSG_RECOVERABLE_PARITY, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } else if (bse->is_metadata) { - int message; + // errors + if (bqs2->num_errors > 0) { + btrfs_scrub_error* bse = &bqs2->errors; + do { if (bse->recovered) - message = IDS_SCRUB_MSG_RECOVERABLE_METADATA; - else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) - message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA; + recoverable_errors++; else - message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM; + unrecoverable_errors++; - if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (bse->parity) { + if (!load_string(module, IDS_SCRUB_MSG_RECOVERABLE_PARITY, t)) + throw last_error(GetLastError()); - if (bse->recovered) { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, - bse->metadata.root, bse->metadata.level) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(u, t, bse->address, bse->device); + } else if (bse->is_metadata) { + int message; + + if (bse->recovered) + message = IDS_SCRUB_MSG_RECOVERABLE_METADATA; + else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) + message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA; + else + message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM; + + if (!load_string(module, message, t)) + throw last_error(GetLastError()); + + if (bse->recovered) + wstring_sprintf(u, t, bse->address, bse->device); + else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) + wstring_sprintf(u, t, bse->address, bse->device, bse->metadata.root, bse->metadata.level); + else + wstring_sprintf(u, t, bse->address, bse->device, bse->metadata.root, bse->metadata.level, bse->metadata.firstitem.obj_id, + bse->metadata.firstitem.obj_type, bse->metadata.firstitem.offset); } else { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, - bse->metadata.root, bse->metadata.level, bse->metadata.firstitem.obj_id, bse->metadata.firstitem.obj_type, - bse->metadata.firstitem.offset) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } - } else { - int message; + int message; - if (bse->recovered) - message = IDS_SCRUB_MSG_RECOVERABLE_DATA; - else if (bse->data.subvol != 0) - message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL; + if (bse->recovered) + message = IDS_SCRUB_MSG_RECOVERABLE_DATA; + else if (bse->data.subvol != 0) + message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL; + else + message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA; + + if (!load_string(module, message, t)) + throw last_error(GetLastError()); + + if (bse->recovered) + wstring_sprintf(u, t, bse->address, bse->device); + else if (bse->data.subvol != 0) + wstring_sprintf(u, t, bse->address, bse->device, bse->data.subvol, + bse->data.filename_length / sizeof(WCHAR), bse->data.filename, bse->data.offset); + else + wstring_sprintf(u, t, bse->address, bse->device, bse->data.filename_length / sizeof(WCHAR), + bse->data.filename, bse->data.offset); + } + + s += u; + s += L"\r\n"; + + if (bse->next_entry == 0) + break; else - message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA; + bse = (btrfs_scrub_error*)((uint8_t*)bse + bse->next_entry); + } while (true); + } - if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (bqs2->finish_time.QuadPart > 0) { + wstring d1, d2; + float speed; - if (bse->recovered) { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } else if (bse->data.subvol != 0) { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, bse->data.subvol, - bse->data.filename_length / sizeof(WCHAR), bse->data.filename, bse->data.offset) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } else { - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, bse->data.filename_length / sizeof(WCHAR), - bse->data.filename, bse->data.offset) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } - } + // "scrub finished" + + filetime.dwLowDateTime = bqs2->finish_time.LowPart; + filetime.dwHighDateTime = bqs2->finish_time.HighPart; + + if (!FileTimeToSystemTime(&filetime, &systime)) + throw last_error(GetLastError()); + + if (!SystemTimeToTzSpecificLocalTime(nullptr, &systime, &systime)) + throw last_error(GetLastError()); + + if (!load_string(module, IDS_SCRUB_MSG_FINISHED, t)) + throw last_error(GetLastError()); + + if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, nullptr, dt, sizeof(dt) / sizeof(WCHAR))) + throw last_error(GetLastError()); + + if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, nullptr, tm, sizeof(tm) / sizeof(WCHAR))) + throw last_error(GetLastError()); + + wstring_sprintf(u, t, dt, tm); s += u; s += L"\r\n"; - if (bse->next_entry == 0) - break; - else - bse = (btrfs_scrub_error*)((UINT8*)bse + bse->next_entry); - } while (TRUE); + // summary + + if (!load_string(module, IDS_SCRUB_MSG_SUMMARY, t)) + throw last_error(GetLastError()); + + format_size(bqs2->data_scrubbed, d1, false); + + speed = (float)bqs2->data_scrubbed / ((float)bqs2->duration / 10000000.0f); + + format_size((uint64_t)speed, d2, false); + + wstring_sprintf(u, t, d1.c_str(), bqs2->duration / 10000000, d2.c_str()); + + s += u; + s += L"\r\n"; + + // recoverable errors + + if (!load_string(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE, t)) + throw last_error(GetLastError()); + + wstring_sprintf(u, t, recoverable_errors); + + s += u; + s += L"\r\n"; + + // unrecoverable errors + + if (!load_string(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE, t)) + throw last_error(GetLastError()); + + wstring_sprintf(u, t, unrecoverable_errors); + + s += u; + s += L"\r\n"; + } + + SetWindowTextW(GetDlgItem(hwndDlg, IDC_SCRUB_INFO), s.c_str()); + } catch (...) { + if (alloc_bqs2) + free(bqs2); + + throw; } - if (bqs2->finish_time.QuadPart > 0) { - WCHAR d1[255], d2[255]; - float speed; - - // "scrub finished" - - filetime.dwLowDateTime = bqs2->finish_time.LowPart; - filetime.dwHighDateTime = bqs2->finish_time.HighPart; - - if (!FileTimeToSystemTime(&filetime, &systime)) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!LoadStringW(module, IDS_SCRUB_MSG_FINISHED, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - s += u; - s += L"\r\n"; - - // summary - - if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - format_size(bqs2->data_scrubbed, d1, sizeof(d1) / sizeof(WCHAR), FALSE); - - speed = (float)bqs2->data_scrubbed / ((float)bqs2->duration / 10000000.0f); - - format_size((UINT64)speed, d2, sizeof(d2) / sizeof(WCHAR), FALSE); - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, d1, bqs2->duration / 10000000, d2) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - s += u; - s += L"\r\n"; - - // recoverable errors - - if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, recoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - s += u; - s += L"\r\n"; - - // unrecoverable errors - - if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, unrecoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - s += u; - s += L"\r\n"; - } - - SetWindowTextW(GetDlgItem(hwndDlg, IDC_SCRUB_INFO), s.c_str()); - -end: if (alloc_bqs2) free(bqs2); } -void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, BOOL first_time) { - HANDLE h; +void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, bool first_time) { btrfs_query_scrub bqs; - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - if (h != INVALID_HANDLE_VALUE) { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; + { + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + if (h != INVALID_HANDLE_VALUE) { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, &bqs, sizeof(btrfs_query_scrub)); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } - - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); } if (first_time || status != bqs.status || chunks_left != bqs.chunks_left) { - WCHAR s[255]; + wstring s; if (bqs.status == BTRFS_SCRUB_STOPPED) { - EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), FALSE); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), false); if (bqs.error != STATUS_SUCCESS) { - WCHAR t[255]; + wstring t; - if (!LoadStringW(module, IDS_SCRUB_FAILED, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, IDS_SCRUB_FAILED, t)) + throw last_error(GetLastError()); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, bqs.error) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(s, t, bqs.error); } else { - if (!LoadStringW(module, bqs.total_chunks == 0 ? IDS_NO_SCRUB : IDS_SCRUB_FINISHED, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, bqs.total_chunks == 0 ? IDS_NO_SCRUB : IDS_SCRUB_FINISHED, s)) + throw last_error(GetLastError()); } } else { - WCHAR t[255]; + wstring t; float pc; - EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), FALSE); - EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), TRUE); + EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), false); + EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), true); + EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), true); - if (!LoadStringW(module, bqs.status == BTRFS_SCRUB_PAUSED ? IDS_SCRUB_PAUSED : IDS_SCRUB_RUNNING, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!load_string(module, bqs.status == BTRFS_SCRUB_PAUSED ? IDS_SCRUB_PAUSED : IDS_SCRUB_RUNNING, t)) + throw last_error(GetLastError()); pc = ((float)(bqs.total_chunks - bqs.chunks_left) / (float)bqs.total_chunks) * 100.0f; - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, bqs.total_chunks - bqs.chunks_left, bqs.total_chunks, pc) == STRSAFE_E_INSUFFICIENT_BUFFER) - return; + wstring_sprintf(s, t, bqs.total_chunks - bqs.chunks_left, bqs.total_chunks, pc); } - SetDlgItemTextW(hwndDlg, IDC_SCRUB_STATUS, s); + SetDlgItemTextW(hwndDlg, IDC_SCRUB_STATUS, s.c_str()); if (first_time || status != bqs.status) { EnableWindow(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), bqs.status != BTRFS_SCRUB_STOPPED); @@ -412,142 +354,117 @@ void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, BOOL first_time) { } void BtrfsScrub::StartScrub(HWND hwndDlg) { - HANDLE h; + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_START_SCRUB, nullptr, 0, nullptr, 0); if (Status == STATUS_DEVICE_NOT_READY) { btrfs_query_balance bqb; NTSTATUS Status2; - Status2 = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb, sizeof(btrfs_query_balance)); + Status2 = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_BALANCE, nullptr, 0, &bqb, sizeof(btrfs_query_balance)); - if (NT_SUCCESS(Status2) && bqb.status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) { - ShowStringError(hwndDlg, IDS_SCRUB_BALANCE_RUNNING); - CloseHandle(h); - return; - } + if (NT_SUCCESS(Status2) && bqb.status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) + throw string_error(IDS_SCRUB_BALANCE_RUNNING); } - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); - RefreshScrubDlg(hwndDlg, TRUE); - - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; - } + RefreshScrubDlg(hwndDlg, true); + } else + throw last_error(GetLastError()); } void BtrfsScrub::PauseScrub(HWND hwndDlg) { - HANDLE h; btrfs_query_scrub bqs; - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, &bqs, sizeof(btrfs_query_scrub)); - if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } + if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) + throw ntstatus_error(Status); if (bqs.status == BTRFS_SCRUB_PAUSED) - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESUME_SCRUB, NULL, 0, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESUME_SCRUB, nullptr, 0, nullptr, 0); else - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_PAUSE_SCRUB, NULL, 0, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_PAUSE_SCRUB, nullptr, 0, nullptr, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } - - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); } void BtrfsScrub::StopScrub(HWND hwndDlg) { - HANDLE h; + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; IO_STATUS_BLOCK iosb; - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_STOP_SCRUB, nullptr, 0, nullptr, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwndDlg, Status); - CloseHandle(h); - return; - } - - CloseHandle(h); - } else { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } else + throw last_error(GetLastError()); } INT_PTR CALLBACK BtrfsScrub::ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - RefreshScrubDlg(hwndDlg, TRUE); - SetTimer(hwndDlg, 1, 1000, NULL); - break; + try { + switch (uMsg) { + case WM_INITDIALOG: + RefreshScrubDlg(hwndDlg, true); + SetTimer(hwndDlg, 1, 1000, nullptr); + break; - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; - case IDC_START_SCRUB: - StartScrub(hwndDlg); - return TRUE; + case IDC_START_SCRUB: + StartScrub(hwndDlg); + return true; - case IDC_PAUSE_SCRUB: - PauseScrub(hwndDlg); - return TRUE; + case IDC_PAUSE_SCRUB: + PauseScrub(hwndDlg); + return true; - case IDC_CANCEL_SCRUB: - StopScrub(hwndDlg); - return TRUE; - } - break; - } - break; + case IDC_CANCEL_SCRUB: + StopScrub(hwndDlg); + return true; + } + break; + } + break; - case WM_TIMER: - RefreshScrubDlg(hwndDlg, FALSE); - break; + case WM_TIMER: + RefreshScrubDlg(hwndDlg, false); + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -563,7 +480,7 @@ static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam if (bs) return bs->ScrubDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } #ifdef __REACTOS__ @@ -571,132 +488,104 @@ extern "C" { #endif void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE token; - TOKEN_PRIVILEGES tp; - LUID luid; - BtrfsScrub* scrub; + try { + win_handle token; + TOKEN_PRIVILEGES tp; + LUID luid; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + set_dpi_aware(); + + BtrfsScrub scrub(lpszCmdLine); + + DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SCRUB), hwnd, stub_ScrubDlgProc, (LPARAM)&scrub); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - set_dpi_aware(); - - scrub = new BtrfsScrub(lpszCmdLine); - - DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SCRUB), hwnd, stub_ScrubDlgProc, (LPARAM)scrub); - - delete scrub; - -end: - CloseHandle(token); } void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; + vector args; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + command_line_to_args(lpszCmdLine, args); - if (!args) - return; - - if (num_args >= 1) { - HANDLE h, token; + if (args.size() >= 1) { LUID luid; TOKEN_PRIVILEGES tp; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) - goto end; + { + win_handle token; - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - CloseHandle(token); - goto end; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + return; + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + return; + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + return; } - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - CloseHandle(token); - goto end; - } - - CloseHandle(token); - - h = CreateFileW(args[0], FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(args[0].c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { IO_STATUS_BLOCK iosb; - NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0); - - CloseHandle(h); + NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_START_SCRUB, nullptr, 0, nullptr, 0); } } - -end: - LocalFree(args); } void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; + vector args; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + command_line_to_args(lpszCmdLine, args); - if (!args) - return; - - if (num_args >= 1) { - HANDLE h, token; + if (args.size() >= 1) { LUID luid; TOKEN_PRIVILEGES tp; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) - goto end; + { + win_handle token; - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) - goto end; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + return; - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + return; - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) - goto end; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - CloseHandle(token); + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + return; + } - h = CreateFileW(args[0], FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(args[0].c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { IO_STATUS_BLOCK iosb; - NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0); - - CloseHandle(h); + NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_STOP_SCRUB, nullptr, 0, nullptr, 0); } } - -end: - LocalFree(args); } #ifdef __REACTOS__ diff --git a/dll/shellext/shellbtrfs/scrub.h b/dll/shellext/shellbtrfs/scrub.h index daae71255ee..5494283cd10 100644 --- a/dll/shellext/shellbtrfs/scrub.h +++ b/dll/shellext/shellbtrfs/scrub.h @@ -28,21 +28,21 @@ class BtrfsScrub { public: - BtrfsScrub(WCHAR* drive) { - wcscpy(fn, drive); + BtrfsScrub(const wstring& drive) { + fn = drive; } INT_PTR CALLBACK ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); private: - void RefreshScrubDlg(HWND hwndDlg, BOOL first_time); + void RefreshScrubDlg(HWND hwndDlg, bool first_time); void UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs); void StartScrub(HWND hwndDlg); void PauseScrub(HWND hwndDlg); void StopScrub(HWND hwndDlg); - WCHAR fn[MAX_PATH]; - UINT32 status; - UINT64 chunks_left; - UINT32 num_errors; + wstring fn; + uint32_t status; + uint64_t chunks_left; + uint32_t num_errors; }; diff --git a/dll/shellext/shellbtrfs/send.cpp b/dll/shellext/shellbtrfs/send.cpp index a1ab8b49b60..2b6a1bf52cf 100644 --- a/dll/shellext/shellbtrfs/send.cpp +++ b/dll/shellext/shellbtrfs/send.cpp @@ -23,202 +23,202 @@ #ifdef __REACTOS__ #undef DeleteFile #endif +#include #define SEND_BUFFER_LEN 1048576 -void BtrfsSend::ShowSendError(UINT msg, ...) { - WCHAR s[1024], t[1024]; - va_list ap; - - if (!LoadStringW(module, msg, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(hwnd, GetLastError()); - return; - } - - va_start(ap, msg); -#ifndef __REACTOS__ - vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#else - vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap); -#endif - - SetDlgItemTextW(hwnd, IDC_SEND_STATUS, t); - - va_end(ap); -} - DWORD BtrfsSend::Thread() { - NTSTATUS Status; - IO_STATUS_BLOCK iosb; - btrfs_send_subvol* bss; - btrfs_send_header header; - btrfs_send_command end; - BOOL success = FALSE; - ULONG bss_size, i; + try { + NTSTATUS Status; + IO_STATUS_BLOCK iosb; + btrfs_send_subvol* bss; + btrfs_send_header header; + btrfs_send_command end; + ULONG bss_size, i; - buf = (char*)malloc(SEND_BUFFER_LEN); + buf = (char*)malloc(SEND_BUFFER_LEN); - dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) { - ShowSendError(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - goto end3; - } + try { + dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (dirh == INVALID_HANDLE_VALUE) + throw string_error(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str()); - bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE)); - bss = (btrfs_send_subvol*)malloc(bss_size); - memset(bss, 0, bss_size); + try { + bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE)); + bss = (btrfs_send_subvol*)malloc(bss_size); + memset(bss, 0, bss_size); - if (incremental) { - WCHAR parent[MAX_PATH]; - HANDLE parenth; + if (incremental) { + WCHAR parent[MAX_PATH]; + HANDLE parenth; - parent[0] = 0; + parent[0] = 0; - GetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent, sizeof(parent) / sizeof(WCHAR)); + GetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent, sizeof(parent) / sizeof(WCHAR)); - parenth = CreateFileW(parent, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (parenth == INVALID_HANDLE_VALUE) { - ShowSendError(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str()); - goto end2; - } + parenth = CreateFileW(parent, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (parenth == INVALID_HANDLE_VALUE) + throw string_error(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str()); - bss->parent = parenth; - } else - bss->parent = NULL; + bss->parent = parenth; + } else + bss->parent = nullptr; - bss->num_clones = clones.size(); + bss->num_clones = clones.size(); - for (i = 0; i < bss->num_clones; i++) { - HANDLE h; + for (i = 0; i < bss->num_clones; i++) { + HANDLE h; - h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ULONG j; + h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) { + auto le = GetLastError(); + ULONG j; - ShowSendError(IDS_SEND_CANT_OPEN_DIR, clones[i].c_str(), GetLastError(), format_message(GetLastError()).c_str()); + for (j = 0; j < i; j++) { + CloseHandle(bss->clones[j]); + } - for (j = 0; j < i; j++) { - CloseHandle(bss->clones[j]); - } + if (bss->parent) CloseHandle(bss->parent); - if (bss->parent) CloseHandle(bss->parent); - goto end2; - } + throw string_error(IDS_SEND_CANT_OPEN_DIR, clones[i].c_str(), le, format_message(le).c_str()); + } - bss->clones[i] = h; - } - - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0); - - for (i = 0; i < bss->num_clones; i++) { - CloseHandle(bss->clones[i]); - } - - if (!NT_SUCCESS(Status)) { - if (Status == (NTSTATUS)STATUS_INVALID_PARAMETER) { - BY_HANDLE_FILE_INFORMATION fileinfo; - if (!GetFileInformationByHandle(dirh, &fileinfo)) { - ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - if (bss->parent) CloseHandle(bss->parent); - goto end2; - } - - if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { - ShowSendError(IDS_SEND_NOT_READONLY); - if (bss->parent) CloseHandle(bss->parent); - goto end2; - } - - if (bss->parent) { - if (!GetFileInformationByHandle(bss->parent, &fileinfo)) { - ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - CloseHandle(bss->parent); - goto end2; + bss->clones[i] = h; } - if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { - ShowSendError(IDS_SEND_PARENT_NOT_READONLY); - CloseHandle(bss->parent); - goto end2; + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0); + + for (i = 0; i < bss->num_clones; i++) { + CloseHandle(bss->clones[i]); } + + if (!NT_SUCCESS(Status)) { + if (Status == (NTSTATUS)STATUS_INVALID_PARAMETER) { + BY_HANDLE_FILE_INFORMATION fileinfo; + if (!GetFileInformationByHandle(dirh, &fileinfo)) { + auto le = GetLastError(); + if (bss->parent) CloseHandle(bss->parent); + throw string_error(IDS_SEND_GET_FILE_INFO_FAILED, le, format_message(le).c_str()); + } + + if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { + if (bss->parent) CloseHandle(bss->parent); + throw string_error(IDS_SEND_NOT_READONLY); + } + + if (bss->parent) { + if (!GetFileInformationByHandle(bss->parent, &fileinfo)) { + auto le = GetLastError(); + CloseHandle(bss->parent); + throw string_error(IDS_SEND_GET_FILE_INFO_FAILED, le, format_message(le).c_str()); + } + + if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { + CloseHandle(bss->parent); + throw string_error(IDS_SEND_PARENT_NOT_READONLY); + } + } + } + + if (bss->parent) CloseHandle(bss->parent); + throw string_error(IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); + } + + if (bss->parent) CloseHandle(bss->parent); + + stream = CreateFileW(file, FILE_WRITE_DATA | DELETE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (stream == INVALID_HANDLE_VALUE) + throw string_error(IDS_SEND_CANT_OPEN_FILE, file, GetLastError(), format_message(GetLastError()).c_str()); + + try { + memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic)); + header.version = 1; + + if (!WriteFile(stream, &header, sizeof(header), nullptr, nullptr)) + throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + do { + 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)) + throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + } + } while (NT_SUCCESS(Status)); + + if (Status != STATUS_END_OF_FILE) + throw string_error(IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED, Status, format_ntstatus(Status).c_str()); + + end.length = 0; + end.cmd = BTRFS_SEND_CMD_END; + end.csum = 0x9dc96c50; + + if (!WriteFile(stream, &end, sizeof(end), nullptr, nullptr)) + throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); + + SetEndOfFile(stream); + } catch (...) { + FILE_DISPOSITION_INFO fdi; + + fdi.DeleteFile = true; + + SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); + + CloseHandle(stream); + stream = INVALID_HANDLE_VALUE; + + throw; + } + + CloseHandle(stream); + stream = INVALID_HANDLE_VALUE; + } catch (...) { + CloseHandle(dirh); + dirh = INVALID_HANDLE_VALUE; + + throw; } + + CloseHandle(dirh); + dirh = INVALID_HANDLE_VALUE; + } catch (...) { + free(buf); + buf = nullptr; + + started = false; + + SetDlgItemTextW(hwnd, IDCANCEL, closetext); + EnableWindow(GetDlgItem(hwnd, IDOK), true); + EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true); + EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true); + + throw; } + } catch (const exception& e) { + wstring msg; - ShowSendError(IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str()); - if (bss->parent) CloseHandle(bss->parent); - goto end2; + utf8_to_utf16(e.what(), msg); + + SetDlgItemTextW(hwnd, IDC_SEND_STATUS, msg.c_str()); + return 0; } - if (bss->parent) CloseHandle(bss->parent); - stream = CreateFileW(file, FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (stream == INVALID_HANDLE_VALUE) { - ShowSendError(IDS_SEND_CANT_OPEN_FILE, file, GetLastError(), format_message(GetLastError()).c_str()); - goto end2; - } - - memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic)); - header.version = 1; - - if (!WriteFile(stream, &header, sizeof(header), NULL, NULL)) { - ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - goto end; - } - - do { - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN); - - if (NT_SUCCESS(Status)) { - if (!WriteFile(stream, buf, iosb.Information, NULL, NULL)) - ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - } - } while (NT_SUCCESS(Status)); - - if (Status != STATUS_END_OF_FILE) { - ShowSendError(IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED, Status, format_ntstatus(Status).c_str()); - goto end; - } - - end.length = 0; - end.cmd = BTRFS_SEND_CMD_END; - end.csum = 0x9dc96c50; - - if (!WriteFile(stream, &end, sizeof(end), NULL, NULL)) { - ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - goto end; - } - - SetEndOfFile(stream); - - ShowSendError(IDS_SEND_SUCCESS); - success = TRUE; - -end: - if (!success) { - FILE_DISPOSITION_INFO fdi; - - fdi.DeleteFile = TRUE; - - SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); - } - - CloseHandle(stream); - stream = INVALID_HANDLE_VALUE; - -end2: - CloseHandle(dirh); - dirh = INVALID_HANDLE_VALUE; - -end3: free(buf); - buf = NULL; + buf = nullptr; - started = FALSE; + started = false; SetDlgItemTextW(hwnd, IDCANCEL, closetext); - EnableWindow(GetDlgItem(hwnd, IDOK), TRUE); - EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE); - EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE); + EnableWindow(GetDlgItem(hwnd, IDOK), true); + EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true); + EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true); + + wstring success; + + load_string(module, IDS_SEND_SUCCESS, success); + + SetDlgItemTextW(hwnd, IDC_SEND_STATUS, success.c_str()); return 0; } @@ -230,7 +230,7 @@ static DWORD WINAPI send_thread(LPVOID lpParameter) { } void BtrfsSend::StartSend(HWND hwnd) { - WCHAR s[255]; + wstring s; HWND cl; ULONG num_clones; @@ -251,15 +251,20 @@ void BtrfsSend::StartSend(HWND hwnd) { return; } - started = TRUE; - ShowSendError(IDS_SEND_WRITING); + started = true; - LoadStringW(module, IDS_SEND_CANCEL, s, sizeof(s) / sizeof(WCHAR)); - SetDlgItemTextW(hwnd, IDCANCEL, s); + wstring writing; - EnableWindow(GetDlgItem(hwnd, IDOK), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE); + load_string(module, IDS_SEND_WRITING, writing); + + SetDlgItemTextW(hwnd, IDC_SEND_STATUS, writing.c_str()); + + load_string(module, IDS_SEND_CANCEL, s); + SetDlgItemTextW(hwnd, IDCANCEL, s.c_str()); + + EnableWindow(GetDlgItem(hwnd, IDOK), false); + EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), false); + EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), false); clones.clear(); @@ -270,24 +275,24 @@ void BtrfsSend::StartSend(HWND hwnd) { ULONG i; for (i = 0; i < num_clones; i++) { - WCHAR* s; + WCHAR* t; ULONG len; len = SendMessageW(cl, LB_GETTEXTLEN, i, 0); - s = (WCHAR*)malloc((len + 1) * sizeof(WCHAR)); + t = (WCHAR*)malloc((len + 1) * sizeof(WCHAR)); - SendMessageW(cl, LB_GETTEXT, i, (LPARAM)s); + SendMessageW(cl, LB_GETTEXT, i, (LPARAM)t); - clones.push_back(s); + clones.push_back(t); - free(s); + free(t); } } - thread = CreateThread(NULL, 0, send_thread, this, 0, NULL); + thread = CreateThread(nullptr, 0, send_thread, this, 0, nullptr); if (!thread) - ShowError(NULL, GetLastError()); + throw last_error(GetLastError()); } void BtrfsSend::Browse(HWND hwnd) { @@ -313,21 +318,16 @@ void BtrfsSend::BrowseParent(HWND hwnd) { PIDLIST_ABSOLUTE root, pidl; HRESULT hr; WCHAR parent[MAX_PATH], volpathw[MAX_PATH]; - HANDLE h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; - if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) { - ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return; - } + if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) + throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); hr = SHParseDisplayName(volpathw, 0, &root, 0, 0); - if (FAILED(hr)) { - ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED); - return; - } + if (FAILED(hr)) + throw string_error(IDS_SHPARSEDISPLAYNAME_FAILED); memset(&bi, 0, sizeof(BROWSEINFOW)); @@ -340,30 +340,21 @@ void BtrfsSend::BrowseParent(HWND hwnd) { if (!pidl) return; - if (!SHGetPathFromIDListW(pidl, parent)) { - ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED); - return; + if (!SHGetPathFromIDListW(pidl, parent)) + throw string_error(IDS_SHGETPATHFROMIDLIST_FAILED); + + { + win_handle h = CreateFileW(parent, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str()); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str()); } - h = CreateFileW(parent, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowStringError(hwnd, IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str()); - return; - } - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); - if (!NT_SUCCESS(Status)) { - ShowStringError(hwnd, IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return; - } - - CloseHandle(h); - - if (bgfi.inode != 0x100 || bgfi.top) { - ShowStringError(hwnd, IDS_NOT_SUBVOL); - return; - } + if (bgfi.inode != 0x100 || bgfi.top) + throw string_error(IDS_NOT_SUBVOL); SetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent); } @@ -373,21 +364,16 @@ void BtrfsSend::AddClone(HWND hwnd) { PIDLIST_ABSOLUTE root, pidl; HRESULT hr; WCHAR path[MAX_PATH], volpathw[MAX_PATH]; - HANDLE h; NTSTATUS Status; IO_STATUS_BLOCK iosb; btrfs_get_file_ids bgfi; - if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) { - ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); - return; - } + if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) + throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str()); hr = SHParseDisplayName(volpathw, 0, &root, 0, 0); - if (FAILED(hr)) { - ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED); - return; - } + if (FAILED(hr)) + throw string_error(IDS_SHPARSEDISPLAYNAME_FAILED); memset(&bi, 0, sizeof(BROWSEINFOW)); @@ -400,30 +386,21 @@ void BtrfsSend::AddClone(HWND hwnd) { if (!pidl) return; - if (!SHGetPathFromIDListW(pidl, path)) { - ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED); - return; + if (!SHGetPathFromIDListW(pidl, path)) + throw string_error(IDS_SHGETPATHFROMIDLIST_FAILED); + + { + win_handle h = CreateFileW(path, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) + throw string_error(IDS_SEND_CANT_OPEN_DIR, path, GetLastError(), format_message(GetLastError()).c_str()); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids)); + if (!NT_SUCCESS(Status)) + throw string_error(IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str()); } - h = CreateFileW(path, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ShowStringError(hwnd, IDS_SEND_CANT_OPEN_DIR, path, GetLastError(), format_message(GetLastError()).c_str()); - return; - } - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids)); - if (!NT_SUCCESS(Status)) { - ShowStringError(hwnd, IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str()); - CloseHandle(h); - return; - } - - CloseHandle(h); - - if (bgfi.inode != 0x100 || bgfi.top) { - ShowStringError(hwnd, IDS_NOT_SUBVOL); - return; - } + if (bgfi.inode != 0x100 || bgfi.top) + throw string_error(IDS_NOT_SUBVOL); SendMessageW(GetDlgItem(hwnd, IDC_CLONE_LIST), LB_ADDSTRING, 0, (LPARAM)path); } @@ -440,89 +417,93 @@ void BtrfsSend::RemoveClone(HWND hwnd) { SendMessageW(cl, LB_DELETESTRING, sel, 0); if (SendMessageW(cl, LB_GETCURSEL, 0, 0) == LB_ERR) - EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), FALSE); + EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), false); } INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - this->hwnd = hwndDlg; + try { + switch (uMsg) { + case WM_INITDIALOG: + this->hwnd = hwndDlg; - GetDlgItemTextW(hwndDlg, IDCANCEL, closetext, sizeof(closetext) / sizeof(WCHAR)); - break; + GetDlgItemTextW(hwndDlg, IDCANCEL, closetext, sizeof(closetext) / sizeof(WCHAR)); + break; - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - StartSend(hwndDlg); - return TRUE; + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + StartSend(hwndDlg); + return true; - case IDCANCEL: - if (started) { - TerminateThread(thread, 0); + case IDCANCEL: + if (started) { + TerminateThread(thread, 0); - if (stream != INVALID_HANDLE_VALUE) { - FILE_DISPOSITION_INFO fdi; + if (stream != INVALID_HANDLE_VALUE) { + FILE_DISPOSITION_INFO fdi; - fdi.DeleteFile = TRUE; + fdi.DeleteFile = true; - SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); - CloseHandle(stream); - } + SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); + CloseHandle(stream); + } - if (dirh != INVALID_HANDLE_VALUE) - CloseHandle(dirh); + if (dirh != INVALID_HANDLE_VALUE) + CloseHandle(dirh); - started = FALSE; + started = false; - SetDlgItemTextW(hwndDlg, IDCANCEL, closetext); + SetDlgItemTextW(hwndDlg, IDCANCEL, closetext); - EnableWindow(GetDlgItem(hwnd, IDOK), TRUE); - EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE); - EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE); - } else - EndDialog(hwndDlg, 1); - return TRUE; + EnableWindow(GetDlgItem(hwnd, IDOK), true); + EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true); + EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true); + } else + EndDialog(hwndDlg, 1); + return true; - case IDC_BROWSE: - Browse(hwndDlg); - return TRUE; + case IDC_BROWSE: + Browse(hwndDlg); + return true; - case IDC_INCREMENTAL: - incremental = IsDlgButtonChecked(hwndDlg, LOWORD(wParam)); + case IDC_INCREMENTAL: + incremental = IsDlgButtonChecked(hwndDlg, LOWORD(wParam)); - EnableWindow(GetDlgItem(hwnd, IDC_PARENT_SUBVOL), incremental); - EnableWindow(GetDlgItem(hwnd, IDC_PARENT_BROWSE), incremental); - return TRUE; + EnableWindow(GetDlgItem(hwnd, IDC_PARENT_SUBVOL), incremental); + EnableWindow(GetDlgItem(hwnd, IDC_PARENT_BROWSE), incremental); + return true; - case IDC_PARENT_BROWSE: - BrowseParent(hwndDlg); - return TRUE; + case IDC_PARENT_BROWSE: + BrowseParent(hwndDlg); + return true; - case IDC_CLONE_ADD: - AddClone(hwndDlg); - return TRUE; + case IDC_CLONE_ADD: + AddClone(hwndDlg); + return true; - case IDC_CLONE_REMOVE: - RemoveClone(hwndDlg); - return TRUE; - } - break; + case IDC_CLONE_REMOVE: + RemoveClone(hwndDlg); + return true; + } + break; - case LBN_SELCHANGE: - switch (LOWORD(wParam)) { - case IDC_CLONE_LIST: - EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), TRUE); - return TRUE; - } - break; - } - break; + case LBN_SELCHANGE: + switch (LOWORD(wParam)) { + case IDC_CLONE_LIST: + EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), true); + return true; + } + break; + } + break; + } + } catch (const exception& e) { + error_message(hwnd, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -537,14 +518,14 @@ static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, if (bs) return bs->SendDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } void BtrfsSend::Open(HWND hwnd, LPWSTR path) { subvol = path; if (DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SEND_SUBVOL), hwnd, stub_SendDlgProc, (LPARAM)this) <= 0) - ShowError(hwnd, GetLastError()); + throw last_error(GetLastError()); } #ifdef __REACTOS__ @@ -552,156 +533,146 @@ extern "C" { #endif void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE token; - TOKEN_PRIVILEGES tp; - LUID luid; - BtrfsSend* bs; + try { + win_handle token; + TOKEN_PRIVILEGES tp; + LUID luid; - set_dpi_aware(); + set_dpi_aware(); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + BtrfsSend bs; + + bs.Open(hwnd, lpszCmdLine); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - CloseHandle(token); - return; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - CloseHandle(token); - return; - } - - bs = new BtrfsSend; - - bs->Open(hwnd, lpszCmdLine); - - delete bs; - - CloseHandle(token); } #ifdef __REACTOS__ } /* extern "C" */ #endif -static void send_subvol(std::wstring subvol, std::wstring file, std::wstring parent, std::vector clones) { +static void send_subvol(const wstring& subvol, const wstring& file, const wstring& parent, const vector& clones) { char* buf; - HANDLE dirh, stream; + win_handle dirh, stream; ULONG bss_size, i; btrfs_send_subvol* bss; IO_STATUS_BLOCK iosb; NTSTATUS Status; btrfs_send_header header; btrfs_send_command end; - BOOL success = FALSE; buf = (char*)malloc(SEND_BUFFER_LEN); - dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (dirh == INVALID_HANDLE_VALUE) - goto end3; + try { + dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, 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()); - stream = CreateFileW(file.c_str(), FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (stream == INVALID_HANDLE_VALUE) { - CloseHandle(dirh); - goto end3; - } + stream = CreateFileW(file.c_str(), FILE_WRITE_DATA | DELETE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (stream == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE)); - bss = (btrfs_send_subvol*)malloc(bss_size); - memset(bss, 0, bss_size); + try { + bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE)); + bss = (btrfs_send_subvol*)malloc(bss_size); + memset(bss, 0, bss_size); - if (parent != L"") { - HANDLE parenth; + if (parent != L"") { + HANDLE parenth; - parenth = CreateFileW(parent.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (parenth == INVALID_HANDLE_VALUE) - goto end2; + parenth = CreateFileW(parent.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (parenth == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - bss->parent = parenth; - } else - bss->parent = NULL; + bss->parent = parenth; + } else + bss->parent = nullptr; - bss->num_clones = clones.size(); + bss->num_clones = clones.size(); - for (i = 0; i < bss->num_clones; i++) { - HANDLE h; + for (i = 0; i < bss->num_clones; i++) { + HANDLE h; - h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); - if (h == INVALID_HANDLE_VALUE) { - ULONG j; + h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr); + if (h == INVALID_HANDLE_VALUE) { + auto le = GetLastError(); + ULONG j; - for (j = 0; j < i; j++) { - CloseHandle(bss->clones[j]); + for (j = 0; j < i; j++) { + CloseHandle(bss->clones[j]); + } + + if (bss->parent) CloseHandle(bss->parent); + + throw last_error(le); + } + + bss->clones[i] = h; + } + + Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0); + + for (i = 0; i < bss->num_clones; i++) { + CloseHandle(bss->clones[i]); } if (bss->parent) CloseHandle(bss->parent); - goto end2; + + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + + memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic)); + header.version = 1; + + if (!WriteFile(stream, &header, sizeof(header), nullptr, nullptr)) + throw last_error(GetLastError()); + + do { + 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); + } while (NT_SUCCESS(Status)); + + if (Status != STATUS_END_OF_FILE) + throw ntstatus_error(Status); + + end.length = 0; + end.cmd = BTRFS_SEND_CMD_END; + end.csum = 0x9dc96c50; + + if (!WriteFile(stream, &end, sizeof(end), nullptr, nullptr)) + throw last_error(GetLastError()); + + SetEndOfFile(stream); + } catch (...) { + FILE_DISPOSITION_INFO fdi; + + fdi.DeleteFile = true; + + SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); + + throw; } - - bss->clones[i] = h; + } catch (...) { + free(buf); + throw; } - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0); - - for (i = 0; i < bss->num_clones; i++) { - CloseHandle(bss->clones[i]); - } - - if (bss->parent) CloseHandle(bss->parent); - - if (!NT_SUCCESS(Status)) - goto end2; - - memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic)); - header.version = 1; - - if (!WriteFile(stream, &header, sizeof(header), NULL, NULL)) - goto end2; - - do { - Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN); - - if (NT_SUCCESS(Status)) - WriteFile(stream, buf, iosb.Information, NULL, NULL); - } while (NT_SUCCESS(Status)); - - if (Status != STATUS_END_OF_FILE) - goto end2; - - end.length = 0; - end.cmd = BTRFS_SEND_CMD_END; - end.csum = 0x9dc96c50; - - if (!WriteFile(stream, &end, sizeof(end), NULL, NULL)) - goto end2; - - SetEndOfFile(stream); - - success = TRUE; - -end2: - if (!success) { - FILE_DISPOSITION_INFO fdi; - - fdi.DeleteFile = TRUE; - - SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)); - } - - CloseHandle(dirh); - CloseHandle(stream); - -end3: free(buf); } @@ -710,40 +681,36 @@ extern "C" { #endif void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - LPWSTR* args; - int num_args; - std::wstring subvol = L"", parent = L"", file = L""; - std::vector clones; + vector args; + wstring subvol = L"", parent = L"", file = L""; + vector clones; - args = CommandLineToArgvW(lpszCmdLine, &num_args); + command_line_to_args(lpszCmdLine, args); - if (!args) - return; - - if (num_args >= 2) { - HANDLE token; + if (args.size() >= 2) { TOKEN_PRIVILEGES tp; LUID luid; - int i; - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) - goto end; + { + win_handle token; - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) - goto end; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + return; - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + return; - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) - goto end; + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - CloseHandle(token); + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + return; + } - for (i = 0; i < num_args; i++) { + for (unsigned int i = 0; i < args.size(); i++) { if (args[i][0] == '-') { - if (args[i][2] == 0 && i < num_args - 1) { + if (args[i][2] == 0 && i < args.size() - 1) { if (args[i][1] == 'p') { parent = args[i+1]; i++; @@ -760,12 +727,14 @@ void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC } } - if (subvol != L"" && file != L"") - send_subvol(subvol, file, parent, clones); + if (subvol != L"" && file != L"") { + try { + send_subvol(subvol, file, parent, clones); + } catch (const exception& e) { + cerr << "Error: " << e.what() << endl; + } + } } - -end: - LocalFree(args); } #ifdef __REACTOS__ diff --git a/dll/shellext/shellbtrfs/send.h b/dll/shellext/shellbtrfs/send.h index 5d1b939aa90..7940c4f19f0 100644 --- a/dll/shellext/shellbtrfs/send.h +++ b/dll/shellext/shellbtrfs/send.h @@ -19,23 +19,20 @@ #ifdef __REACTOS__ #include "btrfs.h" -#include #else #include "../btrfs.h" #endif -#include -#include class BtrfsSend { public: BtrfsSend() { - started = FALSE; + started = false; file[0] = 0; dirh = INVALID_HANDLE_VALUE; stream = INVALID_HANDLE_VALUE; subvol = L""; - buf = NULL; - incremental = FALSE; + buf = nullptr; + incremental = false; } ~BtrfsSend() { @@ -53,14 +50,13 @@ private: void BrowseParent(HWND hwnd); void AddClone(HWND hwnd); void RemoveClone(HWND hwnd); - void ShowSendError(UINT msg, ...); - BOOL started; - BOOL incremental; + bool started; + bool incremental; WCHAR file[MAX_PATH], closetext[255]; HANDLE thread, dirh, stream; HWND hwnd; - std::wstring subvol; + wstring subvol; char* buf; - std::vector clones; + vector clones; }; diff --git a/dll/shellext/shellbtrfs/shellbtrfs.rc b/dll/shellext/shellbtrfs/shellbtrfs.rc index 5e2938ed1d4..fed0af890b8 100644 --- 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,0,2,0 - PRODUCTVERSION 1,0,2,0 + FILEVERSION 1,1,0,0 + PRODUCTVERSION 1,1,0,0 FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS 0x1L @@ -78,12 +78,12 @@ BEGIN BLOCK "080904b0" BEGIN VALUE "FileDescription", "WinBtrfs shell extension" - VALUE "FileVersion", "1.0.2" + VALUE "FileVersion", "1.1" VALUE "InternalName", "btrfs" VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18" VALUE "OriginalFilename", "shellbtrfs.dll" VALUE "ProductName", "WinBtrfs" - VALUE "ProductVersion", "1.0.2" + VALUE "ProductVersion", "1.1" END END BLOCK "VarFileInfo" @@ -98,57 +98,59 @@ END // Dialog // -IDD_PROP_SHEET DIALOGEX 0, 0, 235, 245 +IDD_PROP_SHEET DIALOGEX 0, 0, 235, 257 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,71 + GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,85 LTEXT "Type:",IDC_STATIC,14,49,18,8 - GROUPBOX "POSIX permissions",IDC_STATIC,7,82,221,102 - LTEXT "User:",IDC_STATIC,14,97,17,8 - LTEXT "Group:",IDC_STATIC,14,113,22,8 - EDITTEXT IDC_UID,94,95,40,14,ES_AUTOHSCROLL | ES_NUMBER - EDITTEXT IDC_GID,94,111,40,14,ES_AUTOHSCROLL | ES_NUMBER - LTEXT "User",IDC_STATIC,14,144,15,8 - LTEXT "Group",IDC_STATIC,14,156,20,8 - LTEXT "Others",IDC_STATIC,14,168,22,8 - LTEXT "Read",IDC_STATIC,50,134,17,8 - LTEXT "Write",IDC_STATIC,89,134,18,8 - LTEXT "Execute",IDC_STATIC,129,134,30,8 - CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,147,16,10 - CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,158,16,10 - CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,168,16,10 - CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,147,16,10 - CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,158,16,10 - CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,168,16,10 - CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,147,16,10 - CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,158,16,10 - CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,168,16,10 - GROUPBOX "Flags",IDC_STATIC,7,190,221,48 - CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,204,86,10 + 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 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,218,46,10 + CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,232,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,217,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP - CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,204,80,10 + 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 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,147,40,10 - CONTROL "Set GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,158,40,10 - CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,168,34,10 + 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 + LTEXT "Compression ratio:",IDC_STATIC,14,77,61,8 + LTEXT "%1.1f%%",IDC_COMPRESSION_RATIO,78,77,116,8 END -IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 85 +IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 98 STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Size details" FONT 8, "MS Shell Dlg", 400, 0, 0x1 BEGIN - DEFPUSHBUTTON "OK",IDOK,81,64,50,14 + DEFPUSHBUTTON "OK",IDOK,81,77,50,14 LTEXT "Inline:",IDC_STATIC,7,7,21,8 LTEXT "Uncompressed:",IDC_STATIC,7,20,49,8 LTEXT "ZLIB:",IDC_STATIC,7,33,18,8 @@ -157,6 +159,8 @@ BEGIN LTEXT "(blank)",IDC_SIZE_UNCOMPRESSED,63,20,142,8 LTEXT "(blank)",IDC_SIZE_ZLIB,63,33,142,8 LTEXT "(blank)",IDC_SIZE_LZO,63,46,142,8 + LTEXT "Zstd:",IDC_STATIC,7,59,16,8 + LTEXT "(blank)",IDC_SIZE_ZSTD,63,59,142,8 END IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 251 @@ -382,7 +386,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 205 TOPMARGIN, 7 - BOTTOMMARGIN, 78 + BOTTOMMARGIN, 93 END IDD_VOL_PROP_SHEET, DIALOG @@ -484,6 +488,22 @@ END 2 RT_MANIFEST "shellbtrfs.manifest" +///////////////////////////////////////////////////////////////////////////// +// +// AFX_DIALOG_LAYOUT +// + +IDD_SIZE_DETAILS AFX_DIALOG_LAYOUT +BEGIN + 0 +END + +IDD_PROP_SHEET AFX_DIALOG_LAYOUT +BEGIN + 0 +END + + ///////////////////////////////////////////////////////////////////////////// // // String Table @@ -575,9 +595,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." @@ -588,12 +608,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)" @@ -604,32 +624,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" @@ -649,12 +669,12 @@ BEGIN 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 @@ -663,19 +683,19 @@ 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 + 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." @@ -685,28 +705,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 @@ -717,13 +737,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." @@ -739,13 +759,29 @@ 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 + "Cannot create a reflink between two different filesystems." +END + +STRINGTABLE +BEGIN + IDS_INITCOMMONCONTROLSEX_FAILED "InitCommonControlsEx failed." + IDS_CANT_OPEN_MOUNTMGR "Could not get a handle to mount manager." + IDS_TVM_INSERTITEM_FAILED "TVM_INSERTITEM failed." + IDS_RECV_PATH_TOO_LONG "%S: path was too long." END #endif // English (United Kingdom) resources diff --git a/dll/shellext/shellbtrfs/shellext.h b/dll/shellext/shellbtrfs/shellext.h index a31c44badad..6b16911c62f 100644 --- a/dll/shellext/shellbtrfs/shellext.h +++ b/dll/shellext/shellbtrfs/shellext.h @@ -34,8 +34,11 @@ #include #include #include +#include #endif #include +#include +#include #ifndef __REACTOS__ #include "../btrfs.h" #include "../btrfsioctl.h" @@ -44,6 +47,8 @@ #include "btrfsioctl.h" #endif +using namespace std; + #ifndef __REACTOS__ #define STATUS_SUCCESS (NTSTATUS)0x00000000 #define STATUS_BUFFER_OVERFLOW (NTSTATUS)0x80000005 @@ -79,6 +84,10 @@ #define funcname __func__ #endif +#ifdef _MSC_VER +#pragma warning(disable: 4800) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -95,6 +104,10 @@ NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR UnicodeStringDestination, ULONG UnicodeS 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); @@ -179,11 +192,163 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER { #endif +class win_handle { +public: + win_handle() { + } + + win_handle(HANDLE nh) { + h = nh; + } + + ~win_handle() { + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + } + + operator HANDLE() const { + return h; + } + + win_handle& operator=(const HANDLE nh) { + if (h != INVALID_HANDLE_VALUE) + CloseHandle(h); + + h = nh; + + return *this; + } + + HANDLE* operator&() { + return &h; + } + +private: + HANDLE h = INVALID_HANDLE_VALUE; +}; + +class fff_handle { +public: + fff_handle() { + } + + fff_handle(HANDLE nh) { + h = nh; + } + + ~fff_handle() { + if (h != INVALID_HANDLE_VALUE) + FindClose(h); + } + + operator HANDLE() const { + return h; + } + + fff_handle& operator=(const HANDLE nh) { + if (h != INVALID_HANDLE_VALUE) + FindClose(h); + + h = nh; + + return *this; + } + + HANDLE* operator&() { + return &h; + } + +private: + HANDLE h = INVALID_HANDLE_VALUE; +}; + +class nt_handle { +public: + nt_handle() { + } + + nt_handle(HANDLE nh) { + h = nh; + } + + ~nt_handle() { + if (h != INVALID_HANDLE_VALUE) + NtClose(h); + } + + operator HANDLE() const { + return h; + } + + nt_handle& operator=(const HANDLE nh) { + if (h != INVALID_HANDLE_VALUE) + NtClose(h); + + h = nh; + + return *this; + } + + HANDLE* operator&() { + return &h; + } + +private: + HANDLE h = INVALID_HANDLE_VALUE; +}; + +class string_error : public exception { +public: + string_error(int resno, ...); + + const char* what() const noexcept { + return msg.c_str(); + } + +private: + string msg; +}; + + +class last_error : public exception { +public: + last_error(DWORD errnum); + + const char* what() const noexcept { + return msg.c_str(); + } + +private: + string msg; +}; + +class ntstatus_error : public exception { +public: + ntstatus_error(NTSTATUS Status); + + const char* what() const noexcept { + return msg.c_str(); + } + +private: + string msg; +}; + +#ifdef __REACTOS__ +inline wstring to_wstring(uint8_t a) { WCHAR buffer[16]; swprintf(buffer, L"%d", a); return wstring(buffer); } +inline wstring to_wstring(uint16_t a) { WCHAR buffer[16]; swprintf(buffer, L"%d", a); return wstring(buffer); } +inline wstring to_wstring(uint32_t a) { WCHAR buffer[32]; swprintf(buffer, L"%ld", a); return wstring(buffer); } +inline wstring to_wstring(uint64_t a) { WCHAR buffer[64]; swprintf(buffer, L"%I64d", a); return wstring(buffer); } +#endif + extern HMODULE module; -void ShowError(HWND hwnd, ULONG err); -void ShowNtStatusError(HWND hwnd, NTSTATUS Status); -void ShowStringError(HWND hwndDlg, int num, ...); -void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes); +void format_size(uint64_t size, wstring& s, bool show_bytes); void set_dpi_aware(); -std::wstring format_message(ULONG last_error); -std::wstring format_ntstatus(NTSTATUS Status); +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 error_message(HWND hwnd, const char* msg); diff --git a/dll/shellext/shellbtrfs/volpropsheet.cpp b/dll/shellext/shellbtrfs/volpropsheet.cpp index 9f2ae8d7f6b..8189f39625c 100644 --- a/dll/shellext/shellbtrfs/volpropsheet.cpp +++ b/dll/shellext/shellbtrfs/volpropsheet.cpp @@ -50,15 +50,15 @@ HRESULT __stdcall BtrfsVolPropSheet::QueryInterface(REFIID riid, void **ppObj) { return S_OK; } - *ppObj = NULL; + *ppObj = nullptr; return E_NOINTERFACE; } HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) { - HANDLE h; ULONG num_files; - FORMATETC format = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; + FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HDROP hdrop; + WCHAR fnbuf[MAX_PATH]; if (pidlFolder) return E_FAIL; @@ -71,26 +71,28 @@ HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, ID if (FAILED(pdtobj->GetData(&format, &stgm))) return E_INVALIDARG; - stgm_set = TRUE; + stgm_set = true; hdrop = (HDROP)GlobalLock(stgm.hGlobal); if (!hdrop) { ReleaseStgMedium(&stgm); - stgm_set = FALSE; + stgm_set = false; return E_INVALIDARG; } - num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0); + num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0); if (num_files > 1) { GlobalUnlock(hdrop); return E_FAIL; } - if (DragQueryFileW((HDROP)stgm.hGlobal, 0, fn, sizeof(fn) / sizeof(MAX_PATH))) { - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (DragQueryFileW((HDROP)stgm.hGlobal, 0, fnbuf, sizeof(fnbuf) / sizeof(MAX_PATH))) { + fn = fnbuf; + + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; @@ -102,8 +104,8 @@ HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, ID devices = (btrfs_device*)malloc(devsize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); if (Status == STATUS_BUFFER_OVERFLOW) { if (i < 8) { devsize += 1024; @@ -113,7 +115,6 @@ HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, ID i++; } else { - CloseHandle(h); GlobalUnlock(hdrop); return E_FAIL; } @@ -122,18 +123,15 @@ HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, ID } if (!NT_SUCCESS(Status)) { - CloseHandle(h); GlobalUnlock(hdrop); return E_FAIL; } - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_UUID, NULL, 0, &uuid, sizeof(BTRFS_UUID)); + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_UUID, nullptr, 0, &uuid, sizeof(BTRFS_UUID)); uuid_set = NT_SUCCESS(Status); - ignore = FALSE; + ignore = false; balance = new BtrfsBalance(fn); - - CloseHandle(h); } else { GlobalUnlock(hdrop); return E_FAIL; @@ -149,94 +147,73 @@ HRESULT __stdcall BtrfsVolPropSheet::Initialize(PCIDLIST_ABSOLUTE pidlFolder, ID } typedef struct { - UINT64 dev_id; - WCHAR* name; - UINT64 alloc; - UINT64 size; + uint64_t dev_id; + wstring name; + uint64_t alloc; + uint64_t size; } dev; -void BtrfsVolPropSheet::FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_usage* usage) { - UINT8 i, j; - UINT64 num_devs, k, dev_size, dev_alloc, data_size, data_alloc, metadata_size, metadata_alloc; +void BtrfsVolPropSheet::FormatUsage(HWND hwndDlg, wstring& s, btrfs_usage* usage) { + uint8_t i, j; + uint64_t num_devs, dev_size, dev_alloc, data_size, data_alloc, metadata_size, metadata_alloc; btrfs_device* bd; - dev* devs = NULL; + vector devs; btrfs_usage* bue; - WCHAR t[255], u[255], v[255]; + wstring t, u, v; - static const UINT64 types[] = { BLOCK_FLAG_DATA, BLOCK_FLAG_DATA | BLOCK_FLAG_METADATA, BLOCK_FLAG_METADATA, BLOCK_FLAG_SYSTEM }; + static const uint64_t types[] = { BLOCK_FLAG_DATA, BLOCK_FLAG_DATA | BLOCK_FLAG_METADATA, BLOCK_FLAG_METADATA, BLOCK_FLAG_SYSTEM }; static const ULONG typestrings[] = { IDS_USAGE_DATA, IDS_USAGE_MIXED, IDS_USAGE_METADATA, IDS_USAGE_SYSTEM }; - static const UINT64 duptypes[] = { 0, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, BLOCK_FLAG_RAID10, BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID6 }; + static const uint64_t duptypes[] = { 0, BLOCK_FLAG_DUPLICATE, BLOCK_FLAG_RAID0, BLOCK_FLAG_RAID1, BLOCK_FLAG_RAID10, BLOCK_FLAG_RAID5, BLOCK_FLAG_RAID6 }; static const ULONG dupstrings[] = { IDS_SINGLE, IDS_DUP, IDS_RAID0, IDS_RAID1, IDS_RAID10, IDS_RAID5, IDS_RAID6 }; - s[0] = 0; + s = L""; num_devs = 0; bd = devices; - while (TRUE) { + while (true) { num_devs++; if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } - devs = (dev*)malloc(sizeof(dev) * num_devs); - memset(devs, 0, sizeof(dev) * num_devs); - bd = devices; - k = 0; dev_size = 0; - while (TRUE) { + while (true) { + dev d; + if (bd->missing) { - if (!LoadStringW(module, IDS_MISSING, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_MISSING, d.name)) + throw last_error(GetLastError()); + } else if (bd->device_number == 0xffffffff) + d.name = wstring(bd->name, bd->namelen / sizeof(WCHAR)); + else if (bd->partition_number == 0) { + if (!load_string(module, IDS_DISK_NUM, u)) + throw last_error(GetLastError()); - devs[k].name = (WCHAR*)malloc((wcslen(u) + 1) * sizeof(WCHAR)); - wcscpy(devs[k].name, u); - } else if (bd->device_number == 0xffffffff) { - devs[k].name = (WCHAR*)malloc(bd->namelen + sizeof(WCHAR)); - memcpy(devs[k].name, bd->name, bd->namelen); - devs[k].name[bd->namelen / sizeof(WCHAR)] = 0; - } else if (bd->partition_number == 0) { - if (!LoadStringW(module, IDS_DISK_NUM, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } - - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, bd->device_number) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - devs[k].name = (WCHAR*)malloc((wcslen(t) + 1) * sizeof(WCHAR)); - wcscpy(devs[k].name, t); + wstring_sprintf(d.name, u, bd->device_number); } else { - if (!LoadStringW(module, IDS_DISK_PART_NUM, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_DISK_PART_NUM, u)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, bd->device_number, bd->partition_number) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - devs[k].name = (WCHAR*)malloc((wcslen(t) + 1) * sizeof(WCHAR)); - wcscpy(devs[k].name, t); + wstring_sprintf(d.name, u, bd->device_number, bd->partition_number); } - devs[k].dev_id = bd->dev_id; - devs[k].alloc = 0; - devs[k].size = bd->size; + d.dev_id = bd->dev_id; + d.alloc = 0; + d.size = bd->size; + + devs.push_back(d); dev_size += bd->size; - k++; - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } @@ -246,8 +223,8 @@ void BtrfsVolPropSheet::FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_us metadata_size = metadata_alloc = 0; bue = usage; - while (TRUE) { - for (k = 0; k < bue->num_devices; k++) { + while (true) { + for (uint64_t k = 0; k < bue->num_devices; k++) { dev_alloc += bue->devices[k].alloc; if (bue->type & BLOCK_FLAG_DATA) { @@ -259,250 +236,176 @@ void BtrfsVolPropSheet::FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_us } } - if (bue->type & BLOCK_FLAG_DATA) { + if (bue->type & BLOCK_FLAG_DATA) data_size += bue->size; - } - if (bue->type & BLOCK_FLAG_METADATA) { + if (bue->type & BLOCK_FLAG_METADATA) metadata_size += bue->size; - } if (bue->next_entry > 0) - bue = (btrfs_usage*)((UINT8*)bue + bue->next_entry); + bue = (btrfs_usage*)((uint8_t*)bue + bue->next_entry); else break; } // device size - if (!LoadStringW(module, IDS_USAGE_DEV_SIZE, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_DEV_SIZE, u)) + throw last_error(GetLastError()); - format_size(dev_size, v, sizeof(v) / sizeof(WCHAR), FALSE); + format_size(dev_size, v, false); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, v) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, u, v.c_str()); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + s += t + L"\r\n"; // device allocated - if (!LoadStringW(module, IDS_USAGE_DEV_ALLOC, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_DEV_ALLOC, u)) + throw last_error(GetLastError()); - format_size(dev_alloc, v, sizeof(v) / sizeof(WCHAR), FALSE); + format_size(dev_alloc, v, false); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, v) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, u, v.c_str()); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; +#ifndef __REACTOS__ + s += t + L"\r\n"s; +#else + s += t + L"\r\n"; +#endif // device unallocated - if (!LoadStringW(module, IDS_USAGE_DEV_UNALLOC, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_DEV_UNALLOC, u)) + throw last_error(GetLastError()); - format_size(dev_size - dev_alloc, v, sizeof(v) / sizeof(WCHAR), FALSE); + format_size(dev_size - dev_alloc, v, false); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, v) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, u, v.c_str()); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; +#ifndef __REACTOS__ + s += t + L"\r\n"s; +#else + s += t + L"\r\n"; +#endif // data ratio if (data_alloc > 0) { - if (!LoadStringW(module, IDS_USAGE_DATA_RATIO, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_DATA_RATIO, u)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, (float)data_alloc / (float)data_size) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, u, (float)data_alloc / (float)data_size); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; +#ifndef __REACTOS__ + s += t + L"\r\n"s; +#else + s += t + L"\r\n"; +#endif } // metadata ratio - if (!LoadStringW(module, IDS_USAGE_METADATA_RATIO, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_METADATA_RATIO, u)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, (float)metadata_alloc / (float)metadata_size) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, u, (float)metadata_alloc / (float)metadata_size); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + s += t + L"\r\n\r\n"; for (i = 0; i < sizeof(types) / sizeof(types[0]); i++) { for (j = 0; j < sizeof(duptypes) / sizeof(duptypes[0]); j++) { bue = usage; - while (TRUE) { + while (true) { if ((bue->type & types[i]) == types[i] && ((duptypes[j] == 0 && (bue->type & (BLOCK_FLAG_DUPLICATE | BLOCK_FLAG_RAID0 | BLOCK_FLAG_RAID1 | BLOCK_FLAG_RAID10 | BLOCK_FLAG_RAID5 | BLOCK_FLAG_RAID6)) == 0) || bue->type & duptypes[j])) { - WCHAR typestring[255], dupstring[255], sizestring[255], usedstring[255]; + wstring sizestring, usedstring, typestring, dupstring; if (bue->type & BLOCK_FLAG_DATA && bue->type & BLOCK_FLAG_METADATA && (types[i] == BLOCK_FLAG_DATA || types[i] == BLOCK_FLAG_METADATA)) break; - if (!LoadStringW(module, typestrings[i], typestring, sizeof(typestring) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, typestrings[i], typestring)) + throw last_error(GetLastError()); - if (!LoadStringW(module, dupstrings[j], dupstring, sizeof(dupstring) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, dupstrings[j], dupstring)) + throw last_error(GetLastError()); - format_size(bue->size, sizestring, sizeof(sizestring) / sizeof(WCHAR), FALSE); - format_size(bue->used, usedstring, sizeof(usedstring) / sizeof(WCHAR), FALSE); + format_size(bue->size, sizestring, false); + format_size(bue->used, usedstring, false); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), typestring, dupstring, sizestring, usedstring) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, typestring, dupstring.c_str(), sizestring.c_str(), usedstring.c_str()); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + s += t + L"\r\n"; - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + for (uint64_t k = 0; k < bue->num_devices; k++) { + bool found = false; - for (k = 0; k < bue->num_devices; k++) { - UINT64 l; - BOOL found = FALSE; + format_size(bue->devices[k].alloc, sizestring, false); - format_size(bue->devices[k].alloc, sizestring, sizeof(sizestring) / sizeof(WCHAR), FALSE); - - for (l = 0; l < num_devs; l++) { + for (size_t l = 0; l < min((uint64_t)SIZE_MAX, num_devs); l++) { if (devs[l].dev_id == bue->devices[k].dev_id) { - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), L"%s\t%s", devs[l].name, sizestring) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + s += devs[l].name + L"\t" + sizestring + L"\r\n"; devs[l].alloc += bue->devices[k].alloc; - found = TRUE; + found = true; break; } } if (!found) { - if (!LoadStringW(module, IDS_UNKNOWN_DEVICE, typestring, sizeof(typestring) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_UNKNOWN_DEVICE, typestring)) + throw last_error(GetLastError()); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), typestring, bue->devices[k].dev_id) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + wstring_sprintf(t, typestring, bue->devices[k].dev_id); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\t") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, sizestring) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; +#ifndef __REACTOS__ + s += t + L"\t"s + sizestring + L"\r\n"s; +#else + s += t + L"\t" + sizestring + L"\r\n"; +#endif } } - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + s += L"\r\n"; break; } if (bue->next_entry > 0) - bue = (btrfs_usage*)((UINT8*)bue + bue->next_entry); + bue = (btrfs_usage*)((uint8_t*)bue + bue->next_entry); else break; } } } - if (!LoadStringW(module, IDS_USAGE_UNALLOC, t, sizeof(t) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - goto end; - } + if (!load_string(module, IDS_USAGE_UNALLOC, t)) + throw last_error(GetLastError()); - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; +#ifndef __REACTOS__ + s += t + L"\r\n"s; +#else + s += t + L"\r\n"; +#endif - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; + for (size_t k = 0; k < min((uint64_t)SIZE_MAX, num_devs); k++) { + wstring sizestring; - for (k = 0; k < num_devs; k++) { - WCHAR sizestring[255]; + format_size(devs[k].size - devs[k].alloc, sizestring, false); - format_size(devs[k].size - devs[k].alloc, sizestring, sizeof(sizestring) / sizeof(WCHAR), FALSE); - - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), L"%s\t%s", devs[k].name, sizestring) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, t) == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - - if (StringCchCatW(s, size, L"\r\n") == STRSAFE_E_INSUFFICIENT_BUFFER) - goto end; - } - -end: - if (devs) { - for (k = 0; k < num_devs; k++) { - if (devs[k].name) free(devs[k].name); - } - - free(devs); + s += devs[k].name + L"\t" + sizestring + L"\r\n"; } } void BtrfsVolPropSheet::RefreshUsage(HWND hwndDlg) { - HANDLE h; - WCHAR s[4096]; + wstring s; btrfs_usage* usage; - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; @@ -514,8 +417,8 @@ void BtrfsVolPropSheet::RefreshUsage(HWND hwndDlg) { devices = (btrfs_device*)malloc(devsize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); if (Status == STATUS_BUFFER_OVERFLOW) { if (i < 8) { devsize += 1024; @@ -530,18 +433,16 @@ void BtrfsVolPropSheet::RefreshUsage(HWND hwndDlg) { break; } - if (!NT_SUCCESS(Status)) { - CloseHandle(h); + if (!NT_SUCCESS(Status)) return; - } i = 0; usagesize = 1024; usage = (btrfs_usage*)malloc(usagesize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_USAGE, NULL, 0, usage, usagesize); + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_USAGE, nullptr, 0, usage, usagesize); if (Status == STATUS_BUFFER_OVERFLOW) { if (i < 8) { usagesize += 1024; @@ -558,100 +459,97 @@ void BtrfsVolPropSheet::RefreshUsage(HWND hwndDlg) { if (!NT_SUCCESS(Status)) { free(usage); - CloseHandle(h); return; } - ignore = FALSE; - - CloseHandle(h); + ignore = false; } else return; - FormatUsage(hwndDlg, s, sizeof(s) / sizeof(WCHAR), usage); + FormatUsage(hwndDlg, s, usage); - SetDlgItemTextW(hwndDlg, IDC_USAGE_BOX, s); + SetDlgItemTextW(hwndDlg, IDC_USAGE_BOX, s.c_str()); free(usage); } INT_PTR CALLBACK BtrfsVolPropSheet::UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - WCHAR s[4096]; - int i; - ULONG usagesize; - NTSTATUS Status; - HANDLE h; - IO_STATUS_BLOCK iosb; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + wstring s; + int i; + ULONG usagesize; + NTSTATUS Status; + IO_STATUS_BLOCK iosb; - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - if (h != INVALID_HANDLE_VALUE) { - btrfs_usage* usage; + if (h != INVALID_HANDLE_VALUE) { + btrfs_usage* usage; - i = 0; - usagesize = 1024; + i = 0; + usagesize = 1024; - usage = (btrfs_usage*)malloc(usagesize); + usage = (btrfs_usage*)malloc(usagesize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_USAGE, NULL, 0, usage, usagesize); - if (Status == STATUS_BUFFER_OVERFLOW) { - if (i < 8) { - usagesize += 1024; + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_USAGE, nullptr, 0, usage, usagesize); + if (Status == STATUS_BUFFER_OVERFLOW) { + if (i < 8) { + usagesize += 1024; - free(usage); - usage = (btrfs_usage*)malloc(usagesize); + free(usage); + usage = (btrfs_usage*)malloc(usagesize); - i++; + i++; + } else + break; } else break; - } else - break; - } - - if (!NT_SUCCESS(Status)) { - free(usage); - CloseHandle(h); - break; - } - - CloseHandle(h); - - FormatUsage(hwndDlg, s, sizeof(s) / sizeof(WCHAR), usage); - - SetDlgItemTextW(hwndDlg, IDC_USAGE_BOX, s); - - free(usage); - } - - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; - - case IDC_USAGE_REFRESH: - RefreshUsage(hwndDlg); - return TRUE; } + + if (!NT_SUCCESS(Status)) { + free(usage); + break; + } + + FormatUsage(hwndDlg, s, usage); + + SetDlgItemTextW(hwndDlg, IDC_USAGE_BOX, s.c_str()); + + free(usage); + } + break; } - break; + + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; + + case IDC_USAGE_REFRESH: + RefreshUsage(hwndDlg); + return true; + } + break; + } + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -667,7 +565,7 @@ static INT_PTR CALLBACK stub_UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam if (bvps) return bvps->UsageDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } void BtrfsVolPropSheet::ShowUsage(HWND hwndDlg) { @@ -676,15 +574,13 @@ void BtrfsVolPropSheet::ShowUsage(HWND hwndDlg) { static void add_lv_column(HWND list, int string, int cx) { LVCOLUMNW lvc; - WCHAR s[255]; + wstring s; - if (!LoadStringW(module, string, s, sizeof(s) / sizeof(WCHAR))) { - ShowError(GetParent(list), GetLastError()); - return; - } + if (!load_string(module, string, s)) + throw last_error(GetLastError()); lvc.mask = LVCF_TEXT|LVCF_WIDTH; - lvc.pszText = s; + lvc.pszText = (WCHAR*)s.c_str(); lvc.cx = cx; SendMessageW(list, LVM_INSERTCOLUMNW, 0, (LPARAM)&lvc); } @@ -698,15 +594,15 @@ static int CALLBACK lv_sort(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { return 0; } -static UINT64 find_dev_alloc(UINT64 dev_id, btrfs_usage* usage) { +static uint64_t find_dev_alloc(uint64_t dev_id, btrfs_usage* usage) { btrfs_usage* bue; - UINT64 alloc; + uint64_t alloc; alloc = 0; bue = usage; - while (TRUE) { - UINT64 k; + while (true) { + uint64_t k; for (k = 0; k < bue->num_devices; k++) { if (bue->devices[k].dev_id == dev_id) @@ -714,7 +610,7 @@ static UINT64 find_dev_alloc(UINT64 dev_id, btrfs_usage* usage) { } if (bue->next_entry > 0) - bue = (btrfs_usage*)((UINT8*)bue + bue->next_entry); + bue = (btrfs_usage*)((uint8_t*)bue + bue->next_entry); else break; } @@ -723,105 +619,97 @@ static UINT64 find_dev_alloc(UINT64 dev_id, btrfs_usage* usage) { } void BtrfsVolPropSheet::RefreshDevList(HWND devlist) { - HANDLE h; NTSTATUS Status; IO_STATUS_BLOCK iosb; ULONG usagesize, devsize; btrfs_usage* usage; btrfs_device* bd; int i; - UINT64 num_rw_devices; + uint64_t num_rw_devices; + { + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); - if (h == INVALID_HANDLE_VALUE) { - ShowError(GetParent(devlist), GetLastError()); - return; - } + i = 0; + devsize = 1024; - i = 0; - devsize = 1024; + if (devices) + free(devices); - if (devices) - free(devices); + devices = (btrfs_device*)malloc(devsize); - devices = (btrfs_device*)malloc(devsize); + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); + if (Status == STATUS_BUFFER_OVERFLOW) { + if (i < 8) { + devsize += 1024; - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); - if (Status == STATUS_BUFFER_OVERFLOW) { - if (i < 8) { - devsize += 1024; + free(devices); + devices = (btrfs_device*)malloc(devsize); - free(devices); - devices = (btrfs_device*)malloc(devsize); - - i++; + i++; + } else + return; } else - return; - } else - break; + break; + } + + if (!NT_SUCCESS(Status)) + return; + + bd = devices; + + i = 0; + usagesize = 1024; + + usage = (btrfs_usage*)malloc(usagesize); + + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_USAGE, nullptr, 0, usage, usagesize); + if (Status == STATUS_BUFFER_OVERFLOW) { + if (i < 8) { + usagesize += 1024; + + free(usage); + usage = (btrfs_usage*)malloc(usagesize); + + i++; + } else { + free(usage); + return; + } + } else + break; + } + + if (!NT_SUCCESS(Status)) { + free(usage); + return; + } } - if (!NT_SUCCESS(Status)) { - CloseHandle(h); - return; - } - - bd = devices; - - i = 0; - usagesize = 1024; - - usage = (btrfs_usage*)malloc(usagesize); - - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_USAGE, NULL, 0, usage, usagesize); - if (Status == STATUS_BUFFER_OVERFLOW) { - if (i < 8) { - usagesize += 1024; - - free(usage); - usage = (btrfs_usage*)malloc(usagesize); - - i++; - } else { - free(usage); - CloseHandle(h); - return; - } - } else - break; - } - - if (!NT_SUCCESS(Status)) { - free(usage); - CloseHandle(h); - return; - } - - CloseHandle(h); - SendMessageW(devlist, LVM_DELETEALLITEMS, 0, 0); num_rw_devices = 0; i = 0; - while (TRUE) { + while (true) { LVITEMW lvi; - WCHAR s[255], u[255]; - UINT64 alloc; + wstring s, u; + uint64_t alloc; // ID RtlZeroMemory(&lvi, sizeof(LVITEMW)); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = SendMessageW(devlist, LVM_GETITEMCOUNT, 0, 0); - lvi.lParam = bd->dev_id; + lvi.lParam = (LPARAM)bd->dev_id; - StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%llu", bd->dev_id); - lvi.pszText = s; + s = to_wstring(bd->dev_id); + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_INSERTITEMW, 0, (LPARAM)&lvi); @@ -831,42 +719,31 @@ void BtrfsVolPropSheet::RefreshDevList(HWND devlist) { lvi.iSubItem = 1; if (bd->missing) { - if (!LoadStringW(module, IDS_MISSING, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(GetParent(devlist), GetLastError()); - break; - } + if (!load_string(module, IDS_MISSING, s)) + throw last_error(GetLastError()); + } else if (bd->device_number == 0xffffffff) + s = wstring(bd->name, bd->namelen / sizeof(WCHAR)); + else if (bd->partition_number == 0) { + if (!load_string(module, IDS_DISK_NUM, u)) + throw last_error(GetLastError()); - wcscpy(s, u); - } else if (bd->device_number == 0xffffffff) { - memcpy(s, bd->name, bd->namelen); - s[bd->namelen / sizeof(WCHAR)] = 0; - } else if (bd->partition_number == 0) { - if (!LoadStringW(module, IDS_DISK_NUM, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(GetParent(devlist), GetLastError()); - break; - } - - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), u, bd->device_number) == STRSAFE_E_INSUFFICIENT_BUFFER) - break; + wstring_sprintf(s, u, bd->device_number); } else { - if (!LoadStringW(module, IDS_DISK_PART_NUM, u, sizeof(u) / sizeof(WCHAR))) { - ShowError(GetParent(devlist), GetLastError()); - break; - } + if (!load_string(module, IDS_DISK_PART_NUM, u)) + throw last_error(GetLastError()); - if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), u, bd->device_number, bd->partition_number) == STRSAFE_E_INSUFFICIENT_BUFFER) - break; + wstring_sprintf(s, u, bd->device_number, bd->partition_number); } - lvi.pszText = s; + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_SETITEMW, 0, (LPARAM)&lvi); // readonly lvi.iSubItem = 2; - LoadStringW(module, bd->readonly ? IDS_DEVLIST_READONLY_YES : IDS_DEVLIST_READONLY_NO, s, sizeof(s) / sizeof(WCHAR)); - lvi.pszText = s; + load_string(module, bd->readonly ? IDS_DEVLIST_READONLY_YES : IDS_DEVLIST_READONLY_NO, s); + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_SETITEMW, 0, (LPARAM)&lvi); if (!bd->readonly) @@ -875,8 +752,8 @@ void BtrfsVolPropSheet::RefreshDevList(HWND devlist) { // size lvi.iSubItem = 3; - format_size(bd->size, s, sizeof(s) / sizeof(WCHAR), FALSE); - lvi.pszText = s; + format_size(bd->size, s, false); + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_SETITEMW, 0, (LPARAM)&lvi); // alloc @@ -884,21 +761,21 @@ void BtrfsVolPropSheet::RefreshDevList(HWND devlist) { alloc = find_dev_alloc(bd->dev_id, usage); lvi.iSubItem = 4; - format_size(alloc, s, sizeof(s) / sizeof(WCHAR), FALSE); - lvi.pszText = s; + format_size(alloc, s, false); + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_SETITEMW, 0, (LPARAM)&lvi); // alloc % - StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), L"%1.1f%%", (float)alloc * 100.0f / (float)bd->size); + wstring_sprintf(s, L"%1.1f%%", (float)alloc * 100.0f / (float)bd->size); lvi.iSubItem = 5; - lvi.pszText = s; + lvi.pszText = (LPWSTR)s.c_str(); SendMessageW(devlist, LVM_SETITEMW, 0, (LPARAM)&lvi); i++; if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); else break; } @@ -912,18 +789,19 @@ void BtrfsVolPropSheet::RefreshDevList(HWND devlist) { } void BtrfsVolPropSheet::ResetStats(HWND hwndDlg) { - HANDLE h; - WCHAR t[MAX_PATH + 100], sel[10]; + wstring t, sel; + WCHAR modfn[MAX_PATH]; SHELLEXECUTEINFOW sei; - _itow(stats_dev, sel, 10); + sel = to_wstring(stats_dev); - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",ResetStats "); - wcscat(t, fn); - wcscat(t, L"|"); - wcscat(t, sel); + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",ResetStats " + fn + L"|" + sel; +#else + t = wstring(L"\"") + modfn + wstring(L"\",ResetStats ") + fn + wstring(L"|") + sel; +#endif RtlZeroMemory(&sei, sizeof(sei)); @@ -931,20 +809,18 @@ void BtrfsVolPropSheet::ResetStats(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); WaitForSingleObject(sei.hProcess, INFINITE); CloseHandle(sei.hProcess); - h = CreateFileW(fn, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); + win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); if (h != INVALID_HANDLE_VALUE) { NTSTATUS Status; @@ -957,8 +833,8 @@ void BtrfsVolPropSheet::ResetStats(HWND hwndDlg) { free(devices); devices = (btrfs_device*)malloc(devsize); - while (TRUE) { - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_DEVICES, NULL, 0, devices, devsize); + while (true) { + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_DEVICES, nullptr, 0, devices, devsize); if (Status == STATUS_BUFFER_OVERFLOW) { if (i < 8) { devsize += 1024; @@ -972,84 +848,84 @@ void BtrfsVolPropSheet::ResetStats(HWND hwndDlg) { } else break; } - - CloseHandle(h); } EndDialog(hwndDlg, 0); } INT_PTR CALLBACK BtrfsVolPropSheet::StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - WCHAR s[255], t[255]; - btrfs_device *bd, *dev = NULL; - int i; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + WCHAR s[255]; + wstring t; + btrfs_device *bd, *dev = nullptr; + int i; - static int stat_ids[] = { IDC_WRITE_ERRS, IDC_READ_ERRS, IDC_FLUSH_ERRS, IDC_CORRUPTION_ERRS, IDC_GENERATION_ERRS }; + static int stat_ids[] = { IDC_WRITE_ERRS, IDC_READ_ERRS, IDC_FLUSH_ERRS, IDC_CORRUPTION_ERRS, IDC_GENERATION_ERRS }; - bd = devices; + bd = devices; - while (TRUE) { - if (bd->dev_id == stats_dev) { - dev = bd; - break; + while (true) { + if (bd->dev_id == stats_dev) { + dev = bd; + break; + } + + if (bd->next_entry > 0) + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); + else + break; } - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); - else - break; - } + if (!dev) { + EndDialog(hwndDlg, 0); + throw string_error(IDS_CANNOT_FIND_DEVICE); + } - if (!dev) { - EndDialog(hwndDlg, 0); - ShowStringError(hwndDlg, IDS_CANNOT_FIND_DEVICE); - return FALSE; - } + GetDlgItemTextW(hwndDlg, IDC_DEVICE_ID, s, sizeof(s) / sizeof(WCHAR)); - GetDlgItemTextW(hwndDlg, IDC_DEVICE_ID, s, sizeof(s) / sizeof(WCHAR)); + wstring_sprintf(t, s, dev->dev_id); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, dev->dev_id) == STRSAFE_E_INSUFFICIENT_BUFFER) - return FALSE; + SetDlgItemTextW(hwndDlg, IDC_DEVICE_ID, t.c_str()); - SetDlgItemTextW(hwndDlg, IDC_DEVICE_ID, t); + for (i = 0; i < 5; i++) { + GetDlgItemTextW(hwndDlg, stat_ids[i], s, sizeof(s) / sizeof(WCHAR)); - for (i = 0; i < 5; i++) { - GetDlgItemTextW(hwndDlg, stat_ids[i], s, sizeof(s) / sizeof(WCHAR)); + wstring_sprintf(t, s, dev->stats[i]); - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, dev->stats[i]) == STRSAFE_E_INSUFFICIENT_BUFFER) - return FALSE; + SetDlgItemTextW(hwndDlg, stat_ids[i], t.c_str()); + } - SetDlgItemTextW(hwndDlg, stat_ids[i], t); - } + SendMessageW(GetDlgItem(hwndDlg, IDC_RESET_STATS), BCM_SETSHIELD, 0, true); + EnableWindow(GetDlgItem(hwndDlg, IDC_RESET_STATS), !readonly); - SendMessageW(GetDlgItem(hwndDlg, IDC_RESET_STATS), BCM_SETSHIELD, 0, TRUE); - EnableWindow(GetDlgItem(hwndDlg, IDC_RESET_STATS), !readonly); - - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - EndDialog(hwndDlg, 0); - return TRUE; - - case IDC_RESET_STATS: - ResetStats(hwndDlg); - return TRUE; - } break; } - break; + + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + EndDialog(hwndDlg, 0); + return true; + + case IDC_RESET_STATS: + ResetStats(hwndDlg); + return true; + } + break; + } + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -1065,300 +941,301 @@ static INT_PTR CALLBACK stub_StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam if (bvps) return bvps->StatsDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } -void BtrfsVolPropSheet::ShowStats(HWND hwndDlg, UINT64 devid) { +void BtrfsVolPropSheet::ShowStats(HWND hwndDlg, uint64_t devid) { stats_dev = devid; DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_DEVICE_STATS), hwndDlg, stub_StatsDlgProc, (LPARAM)this); } INT_PTR CALLBACK BtrfsVolPropSheet::DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { - switch (uMsg) { - case WM_INITDIALOG: - { - HWND devlist; - RECT rect; - ULONG w; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + HWND devlist; + RECT rect; + ULONG w; - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); + devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); - GetClientRect(devlist, &rect); - w = rect.right - rect.left; + GetClientRect(devlist, &rect); + w = rect.right - rect.left; - add_lv_column(devlist, IDS_DEVLIST_ALLOC_PC, w * 5 / 44); - add_lv_column(devlist, IDS_DEVLIST_ALLOC, w * 6 / 44); - add_lv_column(devlist, IDS_DEVLIST_SIZE, w * 6 / 44); - add_lv_column(devlist, IDS_DEVLIST_READONLY, w * 7 / 44); - add_lv_column(devlist, IDS_DEVLIST_DESC, w * 16 / 44); - add_lv_column(devlist, IDS_DEVLIST_ID, w * 4 / 44); + add_lv_column(devlist, IDS_DEVLIST_ALLOC_PC, w * 5 / 44); + add_lv_column(devlist, IDS_DEVLIST_ALLOC, w * 6 / 44); + add_lv_column(devlist, IDS_DEVLIST_SIZE, w * 6 / 44); + add_lv_column(devlist, IDS_DEVLIST_READONLY, w * 7 / 44); + add_lv_column(devlist, IDS_DEVLIST_DESC, w * 16 / 44); + add_lv_column(devlist, IDS_DEVLIST_ID, w * 4 / 44); - SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_ADD), BCM_SETSHIELD, 0, TRUE); - SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_REMOVE), BCM_SETSHIELD, 0, TRUE); - SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), BCM_SETSHIELD, 0, TRUE); + SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_ADD), BCM_SETSHIELD, 0, true); + SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_REMOVE), BCM_SETSHIELD, 0, true); + SendMessageW(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), BCM_SETSHIELD, 0, true); - RefreshDevList(devlist); + RefreshDevList(devlist); - break; - } - - case WM_COMMAND: - switch (HIWORD(wParam)) { - case BN_CLICKED: - switch (LOWORD(wParam)) { - case IDOK: - case IDCANCEL: - KillTimer(hwndDlg, 1); - EndDialog(hwndDlg, 0); - return TRUE; - - case IDC_DEVICE_ADD: - { - WCHAR t[MAX_PATH + 100]; - SHELLEXECUTEINFOW sei; - - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",AddDevice "); - wcscat(t, fn); - - RtlZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(sei); - sei.hwnd = hwndDlg; - sei.lpVerb = L"runas"; - sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; - sei.nShow = SW_SHOW; - sei.fMask = SEE_MASK_NOCLOSEPROCESS; - - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } - - WaitForSingleObject(sei.hProcess, INFINITE); - CloseHandle(sei.hProcess); - - RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); - - return TRUE; - } - - case IDC_DEVICE_REFRESH: - RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); - return TRUE; - - case IDC_DEVICE_SHOW_STATS: - { - WCHAR sel[MAX_PATH]; - HWND devlist; - int index; - LVITEMW lvi; - - devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); - - 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.iSubItem = 0; - lvi.pszText = sel; - lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); - SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); - - ShowStats(hwndDlg, _wtoi(sel)); - return TRUE; - } - - case IDC_DEVICE_REMOVE: - { - WCHAR t[2*MAX_PATH + 100], sel[MAX_PATH], sel2[MAX_PATH], mess[255], mess2[255], title[255]; - HWND devlist; - SHELLEXECUTEINFOW sei; - int index; - LVITEMW lvi; - - devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); - - 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.iSubItem = 0; - lvi.pszText = sel; - lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); - SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); - - lvi.iSubItem = 1; - lvi.pszText = sel2; - lvi.cchTextMax = sizeof(sel2) / sizeof(WCHAR); - SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); - - if (!LoadStringW(module, IDS_REMOVE_DEVICE_CONFIRMATION, mess, sizeof(mess) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } - - if (StringCchPrintfW(mess2, sizeof(mess2) / sizeof(WCHAR), mess, sel, sel2) == STRSAFE_E_INSUFFICIENT_BUFFER) - return TRUE; - - if (!LoadStringW(module, IDS_CONFIRMATION_TITLE, title, sizeof(title) / sizeof(WCHAR))) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } - - if (MessageBoxW(hwndDlg, mess2, title, MB_YESNO) != IDYES) - return TRUE; - - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",RemoveDevice "); - wcscat(t, fn); - wcscat(t, L"|"); - wcscat(t, sel); - - RtlZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(sei); - sei.hwnd = hwndDlg; - sei.lpVerb = L"runas"; - sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; - sei.nShow = SW_SHOW; - sei.fMask = SEE_MASK_NOCLOSEPROCESS; - - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } - - WaitForSingleObject(sei.hProcess, INFINITE); - CloseHandle(sei.hProcess); - - RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); - - return TRUE; - } - - case IDC_DEVICE_RESIZE: - { - HWND devlist; - int index; - LVITEMW lvi; - WCHAR sel[100], t[2*MAX_PATH + 100]; - SHELLEXECUTEINFOW sei; - - devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); - - 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.iSubItem = 0; - lvi.pszText = sel; - lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); - SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); - - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",ResizeDevice "); - wcscat(t, fn); - wcscat(t, L"|"); - wcscat(t, sel); - - RtlZeroMemory(&sei, sizeof(sei)); - - sei.cbSize = sizeof(sei); - sei.hwnd = hwndDlg; - sei.lpVerb = L"runas"; - sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; - sei.nShow = SW_SHOW; - sei.fMask = SEE_MASK_NOCLOSEPROCESS; - - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return TRUE; - } - - WaitForSingleObject(sei.hProcess, INFINITE); - CloseHandle(sei.hProcess); - - RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); - } - } break; } - break; - case WM_NOTIFY: - switch (((LPNMHDR)lParam)->code) { - case LVN_ITEMCHANGED: - { - NMLISTVIEW* nmv = (NMLISTVIEW*)lParam; + case WM_COMMAND: + switch (HIWORD(wParam)) { + case BN_CLICKED: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + KillTimer(hwndDlg, 1); + EndDialog(hwndDlg, 0); + return true; - EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_SHOW_STATS), nmv->uNewState & LVIS_SELECTED); + case IDC_DEVICE_ADD: + { + wstring t; + WCHAR modfn[MAX_PATH]; + SHELLEXECUTEINFOW sei; - if (nmv->uNewState & LVIS_SELECTED && !readonly) { - HWND devlist; - btrfs_device* bd; - BOOL device_readonly = FALSE; - LVITEMW lvi; - WCHAR sel[MAX_PATH]; - UINT64 devid; + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); - devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",AddDevice "s + fn; +#else + t = wstring(L"\"") + modfn + wstring(L"\",AddDevice ") + fn; +#endif - RtlZeroMemory(&lvi, sizeof(LVITEMW)); - lvi.mask = LVIF_TEXT; - lvi.iItem = nmv->iItem; - lvi.iSubItem = 0; - lvi.pszText = sel; - lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); - SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); - devid = _wtoi(sel); + RtlZeroMemory(&sei, sizeof(sei)); - bd = devices; + 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; - while (TRUE) { - if (bd->dev_id == devid) { - device_readonly = bd->readonly; - break; + if (!ShellExecuteExW(&sei)) + throw last_error(GetLastError()); + + WaitForSingleObject(sei.hProcess, INFINITE); + CloseHandle(sei.hProcess); + + RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); + + return true; } - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); - else - break; + case IDC_DEVICE_REFRESH: + RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); + return true; + + case IDC_DEVICE_SHOW_STATS: + { + WCHAR sel[MAX_PATH]; + HWND devlist; + int index; + LVITEMW lvi; + + devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); + + 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.iSubItem = 0; + lvi.pszText = sel; + lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); + SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); + + ShowStats(hwndDlg, _wtoi(sel)); + return true; + } + + case IDC_DEVICE_REMOVE: + { + wstring t, mess, mess2, title; + 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); + + if (index == -1) + return true; + + RtlZeroMemory(&lvi, sizeof(LVITEMW)); + lvi.mask = LVIF_TEXT; + lvi.iItem = index; + lvi.iSubItem = 0; + lvi.pszText = sel; + lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); + SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); + + lvi.iSubItem = 1; + lvi.pszText = sel2; + lvi.cchTextMax = sizeof(sel2) / sizeof(WCHAR); + SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); + + if (!load_string(module, IDS_REMOVE_DEVICE_CONFIRMATION, mess)) + throw last_error(GetLastError()); + + wstring_sprintf(mess2, mess, sel, sel2); + + if (!load_string(module, IDS_CONFIRMATION_TITLE, title)) + throw last_error(GetLastError()); + + if (MessageBoxW(hwndDlg, mess2.c_str(), title.c_str(), MB_YESNO) != IDYES) + return true; + + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",RemoveDevice "s + fn + L"|"s + sel; +#else + t = wstring(L"\"") + modfn + wstring(L"\",RemoveDevice ") + fn + wstring(L"|") + sel; +#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); + + RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); + + return true; + } + + case IDC_DEVICE_RESIZE: + { + HWND devlist; + int index; + LVITEMW lvi; + wstring t; + WCHAR modfn[MAX_PATH], sel[100]; + SHELLEXECUTEINFOW sei; + + devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); + + 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.iSubItem = 0; + lvi.pszText = sel; + lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); + SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); + + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",ResizeDevice "s + fn + L"|"s + sel; +#else + t = wstring(L"\"") + modfn + wstring(L"\",ResizeDevice ") + fn + wstring(L"|") + sel; +#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); + + RefreshDevList(GetDlgItem(hwndDlg, IDC_DEVLIST)); + } } - - EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), !device_readonly); - } else - EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), FALSE); - break; } - } - break; + break; + + case WM_NOTIFY: + switch (((LPNMHDR)lParam)->code) { + case LVN_ITEMCHANGED: + { + NMLISTVIEW* nmv = (NMLISTVIEW*)lParam; + + EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_SHOW_STATS), nmv->uNewState & LVIS_SELECTED); + + if (nmv->uNewState & LVIS_SELECTED && !readonly) { + HWND devlist; + btrfs_device* bd; + bool device_readonly = false; + LVITEMW lvi; + WCHAR sel[MAX_PATH]; + uint64_t devid; + + devlist = GetDlgItem(hwndDlg, IDC_DEVLIST); + + RtlZeroMemory(&lvi, sizeof(LVITEMW)); + lvi.mask = LVIF_TEXT; + lvi.iItem = nmv->iItem; + lvi.iSubItem = 0; + lvi.pszText = sel; + lvi.cchTextMax = sizeof(sel) / sizeof(WCHAR); + SendMessageW(devlist, LVM_GETITEMW, 0, (LPARAM)&lvi); + devid = _wtoi(sel); + + bd = devices; + + while (true) { + if (bd->dev_id == devid) { + device_readonly = bd->readonly; + break; + } + + if (bd->next_entry > 0) + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); + else + break; + } + + EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), !device_readonly); + } else + EnableWindow(GetDlgItem(hwndDlg, IDC_DEVICE_RESIZE), false); + + break; + } + } + break; + } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } static INT_PTR CALLBACK stub_DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -1374,7 +1251,7 @@ static INT_PTR CALLBACK stub_DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wPara if (bvps) return bvps->DeviceDlgProc(hwndDlg, uMsg, wParam, lParam); else - return FALSE; + return false; } void BtrfsVolPropSheet::ShowDevices(HWND hwndDlg) { @@ -1382,13 +1259,17 @@ void BtrfsVolPropSheet::ShowDevices(HWND hwndDlg) { } void BtrfsVolPropSheet::ShowScrub(HWND hwndDlg) { - WCHAR t[MAX_PATH + 100]; + wstring t; + WCHAR modfn[MAX_PATH]; SHELLEXECUTEINFOW sei; - t[0] = '"'; - GetModuleFileNameW(module, t + 1, (sizeof(t) / sizeof(WCHAR)) - 1); - wcscat(t, L"\",ShowScrub "); - wcscat(t, fn); + GetModuleFileNameW(module, modfn, sizeof(modfn) / sizeof(WCHAR)); + +#ifndef __REACTOS__ + t = L"\""s + modfn + L"\",ShowScrub "s + fn; +#else + t = wstring(L"\"") + modfn + wstring(L"\",ShowScrub ") + fn; +#endif RtlZeroMemory(&sei, sizeof(sei)); @@ -1396,146 +1277,151 @@ void BtrfsVolPropSheet::ShowScrub(HWND hwndDlg) { sei.hwnd = hwndDlg; sei.lpVerb = L"runas"; sei.lpFile = L"rundll32.exe"; - sei.lpParameters = t; + sei.lpParameters = t.c_str(); sei.nShow = SW_SHOW; sei.fMask = SEE_MASK_NOCLOSEPROCESS; - if (!ShellExecuteExW(&sei)) { - ShowError(hwndDlg, GetLastError()); - return; - } + 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) { - switch (uMsg) { - case WM_INITDIALOG: - { - PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; - BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)psp->lParam; - btrfs_device* bd; + try { + switch (uMsg) { + case WM_INITDIALOG: + { + PROPSHEETPAGE* psp = (PROPSHEETPAGE*)lParam; + BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)psp->lParam; + btrfs_device* bd; - EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); + EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB); - SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); + SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)bps); - bps->readonly = TRUE; - bd = bps->devices; + bps->readonly = true; + bd = bps->devices; - while (TRUE) { - if (!bd->readonly) { - bps->readonly = FALSE; - break; + while (true) { + if (!bd->readonly) { + bps->readonly = false; + break; + } + + if (bd->next_entry > 0) + bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry); + else + break; } - if (bd->next_entry > 0) - bd = (btrfs_device*)((UINT8*)bd + bd->next_entry); - else - break; + if (bps->uuid_set) { + WCHAR s[255]; + wstring t; + + GetDlgItemTextW(hwndDlg, IDC_UUID, s, sizeof(s) / sizeof(WCHAR)); + + wstring_sprintf(t, s, bps->uuid.uuid[0], bps->uuid.uuid[1], bps->uuid.uuid[2], bps->uuid.uuid[3], bps->uuid.uuid[4], bps->uuid.uuid[5], + bps->uuid.uuid[6], bps->uuid.uuid[7], bps->uuid.uuid[8], bps->uuid.uuid[9], bps->uuid.uuid[10], bps->uuid.uuid[11], + bps->uuid.uuid[12], bps->uuid.uuid[13], bps->uuid.uuid[14], bps->uuid.uuid[15]); + + SetDlgItemTextW(hwndDlg, IDC_UUID, t.c_str()); + } else + SetDlgItemTextW(hwndDlg, IDC_UUID, L""); + + SendMessageW(GetDlgItem(hwndDlg, IDC_VOL_SCRUB), BCM_SETSHIELD, 0, true); + + return false; } - if (bps->uuid_set) { - WCHAR s[255], t[255]; - - GetDlgItemTextW(hwndDlg, IDC_UUID, s, sizeof(s) / sizeof(WCHAR)); - - if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), s, - bps->uuid.uuid[0], bps->uuid.uuid[1], bps->uuid.uuid[2], bps->uuid.uuid[3], bps->uuid.uuid[4], bps->uuid.uuid[5], bps->uuid.uuid[6], bps->uuid.uuid[7], - bps->uuid.uuid[8], bps->uuid.uuid[9], bps->uuid.uuid[10], bps->uuid.uuid[11], bps->uuid.uuid[12], bps->uuid.uuid[13], bps->uuid.uuid[14], bps->uuid.uuid[15] - ) != STRSAFE_E_INSUFFICIENT_BUFFER) - SetDlgItemTextW(hwndDlg, IDC_UUID, t); - else - SetDlgItemTextW(hwndDlg, IDC_UUID, L""); - } else - SetDlgItemTextW(hwndDlg, IDC_UUID, L""); - - SendMessageW(GetDlgItem(hwndDlg, IDC_VOL_SCRUB), BCM_SETSHIELD, 0, TRUE); - - return FALSE; - } - - case WM_NOTIFY: - { - switch (((LPNMHDR)lParam)->code) { - case PSN_KILLACTIVE: - SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, FALSE); + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->code) { + case PSN_KILLACTIVE: + SetWindowLongPtrW(hwndDlg, DWLP_MSGRESULT, false); + break; + } break; } - break; - } - case WM_COMMAND: - { - BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); + case WM_COMMAND: + { + BtrfsVolPropSheet* bps = (BtrfsVolPropSheet*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); - if (bps) { - switch (HIWORD(wParam)) { - case BN_CLICKED: { - switch (LOWORD(wParam)) { - case IDC_VOL_SHOW_USAGE: - bps->ShowUsage(hwndDlg); - break; + if (bps) { + switch (HIWORD(wParam)) { + case BN_CLICKED: { + switch (LOWORD(wParam)) { + case IDC_VOL_SHOW_USAGE: + bps->ShowUsage(hwndDlg); + break; - case IDC_VOL_BALANCE: - bps->balance->ShowBalance(hwndDlg); - break; + case IDC_VOL_BALANCE: + bps->balance->ShowBalance(hwndDlg); + break; - case IDC_VOL_DEVICES: - bps->ShowDevices(hwndDlg); - break; + case IDC_VOL_DEVICES: + bps->ShowDevices(hwndDlg); + break; - case IDC_VOL_SCRUB: - bps->ShowScrub(hwndDlg); - break; + case IDC_VOL_SCRUB: + bps->ShowScrub(hwndDlg); + break; + } } } } - } - break; + break; + } } + } catch (const exception& e) { + error_message(hwndDlg, e.what()); } - return FALSE; + return false; } HRESULT __stdcall BtrfsVolPropSheet::AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam) { - PROPSHEETPAGE psp; - HPROPSHEETPAGE hPage; - INITCOMMONCONTROLSEX icex; + try { + PROPSHEETPAGE psp; + HPROPSHEETPAGE hPage; + INITCOMMONCONTROLSEX icex; - if (ignore) - return S_OK; - - icex.dwSize = sizeof(icex); - icex.dwICC = ICC_LINK_CLASS; - - if (!InitCommonControlsEx(&icex)) - MessageBoxW(NULL, L"InitCommonControlsEx failed", L"Error", MB_ICONERROR); - - psp.dwSize = sizeof(psp); - psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; - psp.hInstance = module; - psp.pszTemplate = MAKEINTRESOURCE(IDD_VOL_PROP_SHEET); - psp.hIcon = 0; - psp.pszTitle = MAKEINTRESOURCE(IDS_VOL_PROP_SHEET_TITLE); - psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; - psp.pcRefParent = (UINT*)&objs_loaded; - psp.pfnCallback = NULL; - psp.lParam = (LPARAM)this; - - hPage = CreatePropertySheetPage(&psp); - - if (hPage) { - if (pfnAddPage(hPage, lParam)) { - this->AddRef(); + if (ignore) return S_OK; + + icex.dwSize = sizeof(icex); + icex.dwICC = ICC_LINK_CLASS; + + if (!InitCommonControlsEx(&icex)) + throw string_error(IDS_INITCOMMONCONTROLSEX_FAILED); + + psp.dwSize = sizeof(psp); + psp.dwFlags = PSP_USEREFPARENT | PSP_USETITLE; + psp.hInstance = module; + psp.pszTemplate = MAKEINTRESOURCE(IDD_VOL_PROP_SHEET); + psp.hIcon = 0; + psp.pszTitle = MAKEINTRESOURCE(IDS_VOL_PROP_SHEET_TITLE); + psp.pfnDlgProc = (DLGPROC)PropSheetDlgProc; + psp.pcRefParent = (UINT*)&objs_loaded; + psp.pfnCallback = nullptr; + psp.lParam = (LPARAM)this; + + hPage = CreatePropertySheetPage(&psp); + + if (hPage) { + if (pfnAddPage(hPage, lParam)) { + this->AddRef(); + return S_OK; + } else + DestroyPropertySheetPage(hPage); } else - DestroyPropertySheetPage(hPage); - } else - return E_OUTOFMEMORY; + return E_OUTOFMEMORY; + } catch (const exception& e) { + error_message(nullptr, e.what()); + } return E_FAIL; } @@ -1549,68 +1435,57 @@ extern "C" { #endif void CALLBACK ResetStatsW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) { - HANDLE token, h; - NTSTATUS Status; - TOKEN_PRIVILEGES tp; - LUID luid; - UINT64 devid; - WCHAR *s, *vol, *dev; - IO_STATUS_BLOCK iosb; + try { + win_handle token; + NTSTATUS Status; + TOKEN_PRIVILEGES tp; + LUID luid; + uint64_t devid; + wstring cmdline, vol, dev; + size_t pipe; + IO_STATUS_BLOCK iosb; - set_dpi_aware(); + set_dpi_aware(); - if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) { - ShowError(hwnd, GetLastError()); - return; + cmdline = lpszCmdLine; + + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) + throw last_error(GetLastError()); + + if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid)) + throw last_error(GetLastError()); + + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + throw last_error(GetLastError()); + + pipe = cmdline.find(L"|"); + + if (pipe == string::npos) + return; + + vol = cmdline.substr(0, pipe); + dev = cmdline.substr(pipe + 1); + + devid = _wtoi(dev.c_str()); + if (devid == 0) + return; + + win_handle h = CreateFileW(vol.c_str(), FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, + OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr); + + if (h == INVALID_HANDLE_VALUE) + throw last_error(GetLastError()); + + Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESET_STATS, &devid, sizeof(uint64_t), nullptr, 0); + if (!NT_SUCCESS(Status)) + throw ntstatus_error(Status); + } catch (const exception& e) { + error_message(hwnd, e.what()); } - - if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; - - if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) { - ShowError(hwnd, GetLastError()); - goto end; - } - - s = wcsstr(lpszCmdLine, L"|"); - if (!s) - goto end; - - s[0] = 0; - - vol = lpszCmdLine; - dev = &s[1]; - - devid = _wtoi(dev); - if (devid == 0) - goto end; - - h = CreateFileW(vol, FILE_TRAVERSE | FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, - OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); - - if (h == INVALID_HANDLE_VALUE) { - ShowError(hwnd, GetLastError()); - goto end; - } - - Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESET_STATS, &devid, sizeof(UINT64), NULL, 0); - if (!NT_SUCCESS(Status)) { - ShowNtStatusError(hwnd, Status); - - CloseHandle(h); - goto end; - } - - CloseHandle(h); - -end: - CloseHandle(token); } #ifdef __cplusplus diff --git a/dll/shellext/shellbtrfs/volpropsheet.h b/dll/shellext/shellbtrfs/volpropsheet.h index 6600dbbf4be..0497673e064 100644 --- a/dll/shellext/shellbtrfs/volpropsheet.h +++ b/dll/shellext/shellbtrfs/volpropsheet.h @@ -34,13 +34,13 @@ class BtrfsVolPropSheet : public IShellExtInit, IShellPropSheetExt { public: BtrfsVolPropSheet() { refcount = 0; - ignore = TRUE; - stgm_set = FALSE; - devices = NULL; + ignore = true; + stgm_set = false; + devices = nullptr; InterlockedIncrement(&objs_loaded); - balance = NULL; + balance = nullptr; } virtual ~BtrfsVolPropSheet() { @@ -84,7 +84,7 @@ public: virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam); virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam); - void FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_usage* usage); + void FormatUsage(HWND hwndDlg, wstring& s, btrfs_usage* usage); void RefreshUsage(HWND hwndDlg); void ShowUsage(HWND hwndDlg); INT_PTR CALLBACK UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -93,20 +93,20 @@ public: void ShowDevices(HWND hwndDlg); void ShowScrub(HWND hwndDlg); INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - void ShowStats(HWND hwndDlg, UINT64 devid); + void ShowStats(HWND hwndDlg, uint64_t devid); void ResetStats(HWND hwndDlg); btrfs_device* devices; - BOOL readonly; + bool readonly; BtrfsBalance* balance; BTRFS_UUID uuid; - BOOL uuid_set; + bool uuid_set; private: LONG refcount; - BOOL ignore; + bool ignore; STGMEDIUM stgm; - BOOL stgm_set; - WCHAR fn[MAX_PATH]; - UINT64 stats_dev; + bool stgm_set; + wstring fn; + uint64_t stats_dev; }; diff --git a/media/doc/README.FSD b/media/doc/README.FSD index 8e1489e12c2..07c2702f100 100644 --- a/media/doc/README.FSD +++ b/media/doc/README.FSD @@ -4,7 +4,7 @@ The following FSD are shared with: https://github.com/maharmstone/btrfs. reactos/drivers/filesystems/btrfs # Synced to 1.1 -reactos/dll/shellext/shellbtrfs # Synced to 1.0.2 +reactos/dll/shellext/shellbtrfs # Synced to 1.1 reactos/sdk/lib/fslib/btrfslib # Synced to 1.0.2 The following FSD are shared with: http://www.ext2fsd.com/