[SHELLBTRFS] Upgrade to 1.1
authorPierre Schweitzer <pierre@reactos.org>
Sun, 16 Dec 2018 11:04:40 +0000 (12:04 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Sun, 16 Dec 2018 11:06:46 +0000 (12:06 +0100)
CORE-15452

24 files changed:
dll/shellext/shellbtrfs/CMakeLists.txt
dll/shellext/shellbtrfs/balance.cpp
dll/shellext/shellbtrfs/balance.h
dll/shellext/shellbtrfs/contextmenu.cpp
dll/shellext/shellbtrfs/contextmenu.h
dll/shellext/shellbtrfs/devices.cpp
dll/shellext/shellbtrfs/devices.h
dll/shellext/shellbtrfs/factory.cpp
dll/shellext/shellbtrfs/iconoverlay.cpp
dll/shellext/shellbtrfs/main.cpp
dll/shellext/shellbtrfs/propsheet.cpp
dll/shellext/shellbtrfs/propsheet.h
dll/shellext/shellbtrfs/recv.cpp
dll/shellext/shellbtrfs/recv.h
dll/shellext/shellbtrfs/resource.h
dll/shellext/shellbtrfs/scrub.cpp
dll/shellext/shellbtrfs/scrub.h
dll/shellext/shellbtrfs/send.cpp
dll/shellext/shellbtrfs/send.h
dll/shellext/shellbtrfs/shellbtrfs.rc
dll/shellext/shellbtrfs/shellext.h
dll/shellext/shellbtrfs/volpropsheet.cpp
dll/shellext/shellbtrfs/volpropsheet.h
media/doc/README.FSD

index 6802f6b..5b239ca 100644 (file)
@@ -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)
index edcfece..a442a72 100644 (file)
 #include <shlwapi.h>
 #include <uxtheme.h>
 
-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);
-
-            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 3:
-                    opts = balance_started ? &bqb.system_opts : &system_opts;
-                break;
-
-                default:
-                    return TRUE;
-            }
-
-            EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
-
-            devcb = GetDlgItem(hwndDlg, IDC_DEVID_COMBO);
-
-            if (!LoadStringW(module, IDS_DEVID_LIST, u, sizeof(u) / sizeof(WCHAR))) {
-                ShowError(hwndDlg, GetLastError());
-                return TRUE;
-            }
-
-            bd = devices;
-            while (TRUE) {
-                WCHAR t[255], v[255];
-
-                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 (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;
-                    }
-
-                    if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), v, bd->device_number, bd->partition_number) == STRSAFE_E_INSUFFICIENT_BUFFER)
-                        break;
-                }
-
-                if (StringCchPrintfW(t, sizeof(t) / sizeof(WCHAR), u, bd->dev_id, s) == STRSAFE_E_INSUFFICIENT_BUFFER)
+    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;
 
-                SendMessage(devcb, CB_ADDSTRING, NULL, (LPARAM)t);
-
-                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*)bd + bd->next_entry);
-                else
+                    case 2:
+                        opts = balance_started ? &bqb.metadata_opts : &metadata_opts;
                     break;
-            }
-
-            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());
+                    case 3:
+                        opts = balance_started ? &bqb.system_opts : &system_opts;
                     break;
+
+                    default:
+                        return true;
                 }
 
-                SendMessage(convcb, CB_ADDSTRING, NULL, (LPARAM)s);
+                EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
 
-                if (opts->convert == convtypes2[i])
-                    SendMessage(convcb, CB_SETCURSEL, i, 0);
+                devcb = GetDlgItem(hwndDlg, IDC_DEVID_COMBO);
 
-                i++;
+                if (!load_string(module, IDS_DEVID_LIST, u))
+                    throw last_error(GetLastError());
 
-                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;
-            }
+                bd = devices;
+                while (true) {
+                    wstring t, v;
 
-            // profiles
+                    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());
 
-            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);
+                        wstring_sprintf(s, v, bd->device_number);
+                    } else {
+                        if (!load_string(module, IDS_DISK_PART_NUM, v))
+                            throw last_error(GetLastError());
 
-            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);
+                        wstring_sprintf(s, v, bd->device_number, bd->partition_number);
+                    }
 
-            // usage
+                    wstring_sprintf(t, u, bd->dev_id, s.c_str());
 
-            CheckDlgButton(hwndDlg, IDC_USAGE, opts->flags & BTRFS_BALANCE_OPTS_USAGE ? BST_CHECKED : BST_UNCHECKED);
+                    SendMessage(devcb, CB_ADDSTRING, 0, (LPARAM)t.c_str());
 
-            _itow(opts->usage_start, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_USAGE_START, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_START_SPINNER), UDM_SETRANGE32, 0, 100);
+                    if (opts->devid == bd->dev_id)
+                        SendMessage(devcb, CB_SETCURSEL, num_devices, 0);
 
-            _itow(opts->usage_end, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_USAGE_END, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_USAGE_END_SPINNER), UDM_SETRANGE32, 0, 100);
+                    num_devices++;
 
-            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);
+                    if (!bd->readonly)
+                        num_writeable_devices++;
 
-            // devid
+                    if (bd->next_entry > 0)
+                        bd = (btrfs_device*)((uint8_t*)bd + bd->next_entry);
+                    else
+                        break;
+                }
 
-            if (num_devices < 2 || balance_started)
-                EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID), FALSE);
+                convcb = GetDlgItem(hwndDlg, IDC_CONVERT_COMBO);
 
-            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);
+                if (num_writeable_devices == 0)
+                    num_writeable_devices = num_devices;
 
-            // drange
+                i = 0;
+                while (convtypes[i] != 0) {
+                    if (!load_string(module, convtypes[i], s))
+                        throw last_error(GetLastError());
 
-            CheckDlgButton(hwndDlg, IDC_DRANGE, opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? BST_CHECKED : BST_UNCHECKED);
+                    SendMessage(convcb, CB_ADDSTRING, 0, (LPARAM)s.c_str());
 
-            _itow(opts->drange_start, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_DRANGE_START, s);
+                    if (opts->convert == convtypes2[i])
+                        SendMessage(convcb, CB_SETCURSEL, i, 0);
 
-            _itow(opts->drange_end, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_DRANGE_END, s);
+                    i++;
 
-            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);
+                    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;
+                }
 
-            // vrange
+                // profiles
 
-            CheckDlgButton(hwndDlg, IDC_VRANGE, opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? BST_CHECKED : BST_UNCHECKED);
+                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);
 
-            _itow(opts->vrange_start, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_VRANGE_START, s);
+                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);
 
-            _itow(opts->vrange_end, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_VRANGE_END, s);
+                // usage
 
-            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);
+                CheckDlgButton(hwndDlg, IDC_USAGE, opts->flags & BTRFS_BALANCE_OPTS_USAGE ? BST_CHECKED : BST_UNCHECKED);
 
-            // limit
+                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);
 
-            CheckDlgButton(hwndDlg, IDC_LIMIT, opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? BST_CHECKED : BST_UNCHECKED);
+                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);
 
-            _itow(opts->limit_start, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_LIMIT_START, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_START_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff);
+                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);
 
-            _itow(opts->limit_end, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_LIMIT_END, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_LIMIT_END_SPINNER), UDM_SETRANGE32, 0, 0x7fffffff);
+                // devid
 
-            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);
+                if (num_devices < 2 || balance_started)
+                    EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID), false);
 
-            // stripes
+                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);
 
-            CheckDlgButton(hwndDlg, IDC_STRIPES, opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? BST_CHECKED : BST_UNCHECKED);
+                // drange
 
-            _itow(opts->stripes_start, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_STRIPES_START, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_START_SPINNER), UDM_SETRANGE32, 0, 0xffff);
+                CheckDlgButton(hwndDlg, IDC_DRANGE, opts->flags & BTRFS_BALANCE_OPTS_DRANGE ? BST_CHECKED : BST_UNCHECKED);
 
-            _itow(opts->stripes_end, s, 10);
-            SetDlgItemTextW(hwndDlg, IDC_STRIPES_END, s);
-            SendMessageW(GetDlgItem(hwndDlg, IDC_STRIPES_END_SPINNER), UDM_SETRANGE32, 0, 0xffff);
+                s = to_wstring(opts->drange_start);
+                SetDlgItemTextW(hwndDlg, IDC_DRANGE_START, s.c_str());
 
-            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);
+                s = to_wstring(opts->drange_end);
+                SetDlgItemTextW(hwndDlg, IDC_DRANGE_END, s.c_str());
 
-            // convert
+                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);
 
-            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);
+                // vrange
 
-            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);
+                CheckDlgButton(hwndDlg, IDC_VRANGE, opts->flags & BTRFS_BALANCE_OPTS_VRANGE ? BST_CHECKED : BST_UNCHECKED);
 
-            break;
-        }
+                s = to_wstring(opts->vrange_start);
+                SetDlgItemTextW(hwndDlg, IDC_VRANGE_START, s.c_str());
 
-        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;
-                        }
+                s = to_wstring(opts->vrange_end);
+                SetDlgItemTextW(hwndDlg, IDC_VRANGE_END, s.c_str());
 
-                        case IDC_USAGE: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_USAGE) == BST_CHECKED ? TRUE : FALSE;
+                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);
 
-                            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;
-                        }
+                // limit
 
-                        case IDC_DEVID: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_DEVID) == BST_CHECKED ? TRUE : FALSE;
+                CheckDlgButton(hwndDlg, IDC_LIMIT, opts->flags & BTRFS_BALANCE_OPTS_LIMIT ? BST_CHECKED : BST_UNCHECKED);
 
-                            EnableWindow(GetDlgItem(hwndDlg, IDC_DEVID_COMBO), enabled);
-                            break;
-                        }
+                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);
 
-                        case IDC_DRANGE: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_DRANGE) == BST_CHECKED ? TRUE : FALSE;
+                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_DRANGE_START), enabled);
-                            EnableWindow(GetDlgItem(hwndDlg, IDC_DRANGE_END), enabled);
-                            break;
-                        }
+                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);
 
-                        case IDC_VRANGE: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_VRANGE) == BST_CHECKED ? TRUE : FALSE;
+                // stripes
 
-                            EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_START), enabled);
-                            EnableWindow(GetDlgItem(hwndDlg, IDC_VRANGE_END), enabled);
-                            break;
-                        }
+                CheckDlgButton(hwndDlg, IDC_STRIPES, opts->flags & BTRFS_BALANCE_OPTS_STRIPES ? BST_CHECKED : BST_UNCHECKED);
 
-                        case IDC_LIMIT: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_LIMIT) == BST_CHECKED ? TRUE : FALSE;
+                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);
 
-                            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;
-                        }
+                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);
 
-                        case IDC_STRIPES: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_STRIPES) == BST_CHECKED ? TRUE : FALSE;
+                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);
 
-                            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;
-                        }
+                // convert
 
-                        case IDC_CONVERT: {
-                            BOOL enabled = IsDlgButtonChecked(hwndDlg, IDC_CONVERT) == BST_CHECKED ? TRUE : FALSE;
+                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);
 
-                            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);
-
-            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);
-
-            if (readonly) {
-                EnableWindow(GetDlgItem(hwndDlg, IDC_START_BALANCE), FALSE);
-                EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_BALANCE), FALSE);
-                EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_BALANCE), FALSE);
-            }
+    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));
+
+                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);
+                }
 
-            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;
-        }
-
-        if (!NT_SUCCESS(Status)) {
-            CloseHandle(h);
-            ShowNtStatusError(hwndDlg, Status);
-            return;
-        }
+                    break;
+            }
 
-        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;
-
-    s = wcsstr(lpszCmdLine, L" ");
-    if (!s)
-        return;
+    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[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;
-
-    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
-        ShowError(hwnd, GetLastError());
-        return;
-    }
-
-    if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
-        ShowError(hwnd, GetLastError());
-        goto end;
+    try {
+        win_handle h, token;
+        TOKEN_PRIVILEGES tp;
+        LUID luid;
+
+        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());
     }
-
-    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;
-
-    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
-        ShowError(hwnd, GetLastError());
-        return;
-    }
-
-    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;
+    try {
+        win_handle h, token;
+        TOKEN_PRIVILEGES tp;
+        LUID luid;
+
+        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());
     }
-
-end:
-    CloseHandle(token);
 }
 
 #ifdef __REACTOS__
index 0c07de4..b623537 100644 (file)
 
 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;
 };
index a5769be..6e51a0f 100644 (file)
@@ -15,9 +15,6 @@
  * You should have received a copy of the GNU Lesser General Public Licence
  * along with WinBtrfs.  If not, see <http://www.gnu.org/licenses/>. */
 
-#ifndef __REACTOS__
-#define UNICODE
-#endif
 #include "shellext.h"
 #ifndef __REACTOS__
 #include <windows.h>
@@ -35,8 +32,8 @@
 #undef DeleteFile
 #endif
 #include <wincodec.h>
-#include <string>
 #include <sstream>
+#include <iostream>
 
 #define NO_SHLWAPI_STRFCNS
 #include <shlwapi.h>
@@ -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;
-
-                        StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn);
+                        wstring parpath;
 
-                        PathRemoveFileSpecW(parpath);
+                        {
+                            win_handle h2;
 
-                        h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+                            parpath = fn;
+                            path_remove_file(parpath);
 
-                        if (h2 != INVALID_HANDLE_VALUE)
-                            allow_snapshot = TRUE;
+                            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);
 
-                        CloseHandle(h2);
+                            if (h2 != INVALID_HANDLE_VALUE)
+                                allow_snapshot = true;
+                        }
 
-                        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];
+
+        if (!SHGetPathFromIDListW(pidlFolder, pathbuf))
+            return E_FAIL;
+
+        path = pathbuf;
+    }
 
-    // check we have permissions to create new subdirectory
+    {
+        // check we have permissions to create new subdirectory
 
-    h = CreateFileW(path, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+        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;
+        if (h == INVALID_HANDLE_VALUE)
+            return E_FAIL;
 
-    // check is Btrfs volume
+        // check is Btrfs volume
 
-    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);
-        return E_FAIL;
+        if (!NT_SUCCESS(Status))
+            return E_FAIL;
     }
 
-    CloseHandle(h);
-
-    ignore = FALSE;
-    bg = TRUE;
+    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;
-            }
-
-            StringCchCopyW(searchpath, sizeof(searchpath) / sizeof(WCHAR), parpath);
-            StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), L"\\");
-            pathend = wcslen(searchpath);
+            wstring_sprintf(name, temp1, subvolname.c_str(), time.wYear, time.wMonth, time.wDay);
+            nameorig = name;
 
-            StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), name);
+            searchpath = parpath + L"\\" + 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);
-
-                    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;
+#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 = 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));
-
-    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;
-    }
+    try {
+        memset(&bsii, 0, sizeof(btrfs_set_inode_info));
 
-    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;
-    }
+        bsii.flags_changed = true;
+        bsii.flags = bii.flags;
 
-    if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
-            HANDLE h;
-            WIN32_FIND_DATAW fff;
-            std::wstring qs;
+        if (bii.flags & BTRFS_INODE_COMPRESS) {
+            bsii.compression_type_changed = true;
+            bsii.compression_type = bii.compression_type;
+        }
 
-            qs = fn;
-            qs += L"\\*";
+        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);
 
-            h = FindFirstFileW(qs.c_str(), &fff);
-            if (h != INVALID_HANDLE_VALUE) {
-                do {
-                    std::wstring fn2;
+        if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+                fff_handle h;
+                WIN32_FIND_DATAW fff;
+                wstring qs;
 
-                    if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
-                        continue;
+                qs = fn;
+                qs += L"\\*";
 
-                    fn2 = fn;
-                    fn2 += L"\\";
-                    fn2 += fff.cFileName;
+                h = FindFirstFileW(qs.c_str(), &fff);
+                if (h != INVALID_HANDLE_VALUE) {
+                    do {
+                        wstring fn2;
 
-                    if (!reflink_copy(hwnd, fn2.c_str(), newpath.c_str()))
-                        goto end;
-                } while (FindNextFileW(h, &fff));
+                        if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
+                            continue;
 
-                FindClose(h);
-            }
-        }
+                        fn2 = fn;
+                        fn2 += L"\\";
+                        fn2 += fff.cFileName;
 
-        // 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) {
-                    ShowError(hwnd, GetLastError());
-                    goto end;
+                        reflink_copy(hwnd, fn2.c_str(), newpath.c_str());
+                    } while (FindNextFileW(h, &fff));
                 }
             }
 
-            rplen = sizeof(reparse_header) + rh.ReparseDataLength;
-            rp = (UINT8*)malloc(rplen);
+            // CreateDirectoryExW also copies streams, no need to do it here
+        } else {
+            WIN32_FIND_STREAM_DATA fsd;
 
-            if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, rp, rplen, &bytesret, NULL)) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+            if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+                reparse_header rh;
+                ULONG rplen;
+                uint8_t* rp;
 
-            if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, NULL, 0, &bytesret, NULL)) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
+                    if (GetLastError() != ERROR_MORE_DATA)
+                        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 offset, alloc_size;
-            ULONG maxdup;
-
-            if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                rplen = sizeof(reparse_header) + rh.ReparseDataLength;
+                rp = (uint8_t*)malloc(rplen);
 
-            if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, NULL, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, NULL)) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                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());
 
-            if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
-                if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, NULL, 0, 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_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), 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), nullptr, 0, &bytesret, nullptr))
+                    throw last_error(GetLastError());
 
-            feofi.EndOfFile = fsi.EndOfFile;
-            if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO))){
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                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;
+                ded.FileHandle = source;
+                maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
 
-            alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
+                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 = 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;
+                    offset += ded.ByteCount.QuadPart;
+                }
             }
-        }
 
-        h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0);
-        if (h != INVALID_HANDLE_VALUE) {
-            do {
-                std::wstring sn;
+            fff_handle h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0);
+            if (h != INVALID_HANDLE_VALUE) {
+                do {
+                    wstring sn;
 
-                sn = fsd.cStreamName;
+                    sn = fsd.cStreamName;
 
-                if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
-                    HANDLE stream;
-                    UINT8* data = NULL;
+                    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) {
-                        std::wstring fn2;
+                        if (fsd.StreamSize.QuadPart > 0) {
+                            wstring fn2;
 
-                        fn2 = fn;
-                        fn2 += sn;
+                            fn2 = fn;
+                            fn2 += sn;
 
-                        stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+                            stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
 
-                        if (stream == INVALID_HANDLE_VALUE) {
-                            ShowError(hwnd, GetLastError());
-                            FindClose(h);
-                            goto end;
-                        }
+                            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*)malloc(fsd.StreamSize.QuadPart);
+                            // 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, fsd.StreamSize.QuadPart, &bytesret, NULL)) {
-                            ShowError(hwnd, GetLastError());
-                            FindClose(h);
-                            free(data);
-                            CloseHandle(stream);
-                            goto end;
+                            if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
                         }
 
-                        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());
+                        stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
 
-                        FindClose(h);
-                        if (data) free(data);
+                        if (stream == INVALID_HANDLE_VALUE) {
+                            if (data) free(data);
+                            throw last_error(GetLastError());
+                        }
 
-                        goto end;
-                    }
+                        if (data) {
+                            if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
 
-                    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);
+                } while (FindNextStreamW(h, &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);
+        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, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, &bsxa, sizeof(btrfs_set_xattr));
+        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 = NULL, *xa2;
+        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);
+            do {
+                xalen += 1024;
 
-            Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, xa, xalen);
-        } while (Status == STATUS_BUFFER_OVERFLOW);
+                if (xa) free(xa);
+                xa = (btrfs_set_xattr*)malloc(xalen);
 
-        if (!NT_SUCCESS(Status)) {
-            free(xa);
-            ShowNtStatusError(hwnd, Status);
-            goto end;
-        }
+                Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
+            } while (Status == STATUS_BUFFER_OVERFLOW);
 
-        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);
             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;
-    }
-
-    ret = TRUE;
+            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];
+            }
 
-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());
-    }
-
-    CloseHandle(dest);
-    CloseHandle(source);
+            throw last_error(GetLastError());
 
-    return ret;
+        throw;
+    }
 }
 
 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);
+                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;
+                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;
 
-            GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
+                GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
 
-            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))) {
-                    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))) {
+                        t = L"\"";
+                        t += dll;
+                        t += L"\",SendSubvolGUI ";
+                        t += fn;
 
-                    WaitForSingleObject(sei.hProcess, INFINITE);
-                    CloseHandle(sei.hProcess);
-                }
-            }
+                        RtlZeroMemory(&sei, sizeof(sei));
 
-            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;
+                        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 (!LoadStringW(module, IDS_NEW_SUBVOL_FILENAME, name, MAX_PATH)) {
-                ShowError(pici->hwnd, GetLastError());
-                return E_FAIL;
-            }
+                        if (!ShellExecuteExW(&sei))
+                            throw last_error(GetLastError());
 
-            h = CreateFileW(path, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+                        WaitForSingleObject(sei.hProcess, INFINITE);
+                        CloseHandle(sei.hProcess);
+                    }
+                }
 
-            if (h == INVALID_HANDLE_VALUE) {
-                ShowError(pici->hwnd, GetLastError());
-                return E_FAIL;
+                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;
 
-            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);
+                if (!load_string(module, IDS_NEW_SUBVOL_FILENAME, name))
+                    throw last_error(GetLastError());
 
-            StringCchCatW(searchpath, searchpathlen, name);
+                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);
 
-            fff = FindFirstFileW(searchpath, &wfd);
+                if (h == INVALID_HANDLE_VALUE)
+                    throw last_error(GetLastError());
 
-            if (fff != INVALID_HANDLE_VALUE) {
-                ULONG i = wcslen(searchpath), num = 2;
+                searchpath = path + L"\\" + name;
+                nameorig = name;
 
-                do {
-                    FindClose(fff);
+                {
+                    fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
 
-                    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;
-                    }
+                    if (fff != INVALID_HANDLE_VALUE) {
+                        ULONG num = 2;
 
-                    fff = FindFirstFileW(searchpath, &wfd);
-                    num++;
-                } while (fff != INVALID_HANDLE_VALUE);
-            }
+                        do {
+#ifndef __REACTOS__
+                            name = nameorig + L" (" + to_wstring(num) + L")";
+#else
+                            {
+                                WCHAR buffer[32];
 
-            bcslen = offsetof(btrfs_create_subvol, name[0]) + (wcslen(&searchpath[pathend]) * sizeof(WCHAR));
-            bcs = (btrfs_create_subvol*)malloc(bcslen);
+                                swprintf(buffer, L"%d", num);
+                                name = nameorig + L" (" + buffer + L")";
+                            }
+#endif
+                            searchpath = path + L"\\" + name;
 
-            bcs->readonly = FALSE;
-            bcs->posix = FALSE;
-            bcs->namelen = wcslen(&searchpath[pathend]) * sizeof(WCHAR);
-            memcpy(bcs->name, &searchpath[pathend], bcs->namelen);
+                            fff = FindFirstFileW(searchpath.c_str(), &wfd);
+                            num++;
+                        } while (fff != INVALID_HANDLE_VALUE);
+                    }
+                }
 
-            Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0);
+                bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
+                bcs = (btrfs_create_subvol*)malloc(bcslen);
 
-            free(searchpath);
-            free(bcs);
+                bcs->readonly = false;
+                bcs->posix = false;
+                bcs->namelen = (uint16_t)(name.length() * sizeof(WCHAR));
+                memcpy(bcs->name, name.c_str(), name.length() * sizeof(WCHAR));
 
-            if (!NT_SUCCESS(Status)) {
-                CloseHandle(h);
-                ShowNtStatusError(pici->hwnd, Status);
-                return E_FAIL;
-            }
+                Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
 
-            CloseHandle(h);
+                free(bcs);
 
-            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;
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
-            GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
+                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;
 
-            t = L"\"";
-            t += dll;
-            t += L"\",RecvSubvolGUI ";
-            t += path;
+                GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
 
-            RtlZeroMemory(&sei, sizeof(sei));
+                t = L"\"";
+                t += dll;
+                t += L"\",RecvSubvolGUI ";
+                t += path;
 
-            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;
+                RtlZeroMemory(&sei, sizeof(sei));
 
-            if (!ShellExecuteExW(&sei)) {
-                ShowError(pici->hwnd, GetLastError());
-                return E_FAIL;
-            }
+                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;
 
-            WaitForSingleObject(sei.hProcess, INFINITE);
-            CloseHandle(sei.hProcess);
+                if (!ShellExecuteExW(&sei))
+                    throw last_error(GetLastError());
 
-            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;
+                WaitForSingleObject(sei.hProcess, INFINITE);
+                CloseHandle(sei.hProcess);
 
-            if (!IsClipboardFormatAvailable(CF_HDROP))
                 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 (!OpenClipboard(pici->hwnd)) {
-                ShowError(pici->hwnd, GetLastError());
-                return E_FAIL;
-            }
+                if (!IsClipboardFormatAvailable(CF_HDROP))
+                    return S_OK;
+
+                if (!OpenClipboard(pici->hwnd))
+                    throw last_error(GetLastError());
 
-            hdrop = (HDROP)GetClipboardData(CF_HDROP);
+                try {
+                    hdrop = (HDROP)GetClipboardData(CF_HDROP);
 
-            if (hdrop) {
-                HANDLE lh;
+                    if (hdrop) {
+                        HANDLE lh;
 
-                lh = GlobalLock(hdrop);
+                        lh = GlobalLock(hdrop);
 
-                if (lh) {
-                    ULONG num_files, i;
-                    WCHAR fn[MAX_PATH];
+                        if (lh) {
+                            try {
+                                ULONG num_files, i;
+                                WCHAR fn[MAX_PATH];
 
-                    num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, NULL, 0);
+                                num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0);
 
-                    for (i = 0; i < num_files; i++) {
-                        if (DragQueryFileW(hdrop, i, fn, sizeof(fn) / sizeof(WCHAR))) {
-                            if (!reflink_copy(pici->hwnd, fn, pici->lpDirectoryW)) {
+                                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);
-                                CloseClipboard();
-                                return E_FAIL;
+                                throw;
                             }
+
+                            GlobalUnlock(lh);
                         }
                     }
-
-                    GlobalUnlock(lh);
+                } catch (...) {
+                    CloseClipboard();
+                    throw;
                 }
-            }
 
-            CloseClipboard();
+                CloseClipboard();
 
-            return S_OK;
+                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;
-
-    if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
-            HANDLE h;
-            WIN32_FIND_DATAW fff;
-            std::wstring qs;
+    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);
 
-            qs = srcfn;
-            qs += L"\\*";
+        if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+                WIN32_FIND_DATAW fff;
+                wstring qs;
 
-            h = FindFirstFileW(qs.c_str(), &fff);
-            if (h != INVALID_HANDLE_VALUE) {
-                do {
-                    std::wstring fn2;
+                qs = srcfn;
+                qs += L"\\*";
 
-                    if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
-                        continue;
+                fff_handle h = FindFirstFileW(qs.c_str(), &fff);
+                if (h != INVALID_HANDLE_VALUE) {
+                    do {
+                        wstring fn2;
 
-                    fn2 = srcfn;
-                    fn2 += L"\\";
-                    fn2 += fff.cFileName;
+                        if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
+                            continue;
 
-                    reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName);
-                } while (FindNextFileW(h, &fff));
+                        fn2 = srcfn;
+                        fn2 += L"\\";
+                        fn2 += fff.cFileName;
 
-                FindClose(h);
+                        reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName);
+                    } while (FindNextFileW(h, &fff));
+                }
             }
-        }
 
-        // CreateDirectoryExW also copies streams, no need to do it here
-    } else {
-        HANDLE h;
-        WIN32_FIND_STREAM_DATA fsd;
+            // 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* rp;
+            if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+                reparse_header rh;
+                ULONG rplen;
+                uint8_t* rp;
 
-            if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, &rh, sizeof(reparse_header), &bytesret, NULL)) {
-                if (GetLastError() != ERROR_MORE_DATA)
-                    goto end;
-            }
+                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*)malloc(rplen);
+                rplen = sizeof(reparse_header) + rh.ReparseDataLength;
+                rp = (uint8_t*)malloc(rplen);
 
-            if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, rp, rplen, &bytesret, NULL))
-                goto end;
+                try {
+                    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, NULL, 0, &bytesret, NULL))
-                goto end;
+                    if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
+                        throw last_error(GetLastError());
+                } catch (...) {
+                    free(rp);
+                    throw;
+                }
 
-            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;
-            }
+                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), 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), nullptr, 0, &bytesret, nullptr))
+                    throw last_error(GetLastError());
 
-            feofi.EndOfFile = fsi.EndOfFile;
-            if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
-                goto end;
+                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;
+                ded.FileHandle = source;
+                maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
 
-            alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
+                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 = 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;
+                    offset += ded.ByteCount.QuadPart;
+                }
             }
-        }
 
-        h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0);
-        if (h != INVALID_HANDLE_VALUE) {
-            do {
-                std::wstring sn;
+            fff_handle h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0);
+            if (h != INVALID_HANDLE_VALUE) {
+                do {
+                    wstring sn;
 
-                sn = fsd.cStreamName;
+                    sn = fsd.cStreamName;
 
-                if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
-                    HANDLE stream;
-                    UINT8* data = NULL;
+                    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) {
-                        std::wstring fn2;
+                        if (fsd.StreamSize.QuadPart > 0) {
+                            wstring fn2;
+                            uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
 
-                        fn2 = srcfn;
-                        fn2 += sn;
+                            fn2 = srcfn;
+                            fn2 += sn;
 
-                        stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+                            stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
 
-                        if (stream == INVALID_HANDLE_VALUE)
-                            goto end;
+                            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*)malloc(fsd.StreamSize.QuadPart);
+                            // 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, fsd.StreamSize.QuadPart, &bytesret, NULL)) {
-                            free(data);
-                            CloseHandle(stream);
-                            goto end;
+                            if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
                         }
 
-                        CloseHandle(stream);
-                    }
+                        stream = CreateFileW((destdir + destname + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
 
-                    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);
+                            throw last_error(GetLastError());
+                        }
 
-                    if (stream == INVALID_HANDLE_VALUE) {
-                        if (data) free(data);
-                        goto end;
-                    }
+                        if (data) {
+                            if (!WriteFile(stream, data, (uint32_t)fsd.StreamSize.QuadPart, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
 
-                    if (data) {
-                        if (!WriteFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) {
                             free(data);
-                            CloseHandle(stream);
-                            goto end;
                         }
-
-                        free(data);
                     }
-
-                    CloseHandle(stream);
-                }
-            } while (FindNextStreamW(h, &fsd));
-
-            FindClose(h);
+                } while (FindNextStreamW(h, &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);
+        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, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, &bsxa, sizeof(btrfs_set_xattr));
+        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 = NULL, *xa2;
-
-        do {
-            xalen += 1024;
+        if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
+            ULONG xalen = 0;
+            btrfs_set_xattr *xa = nullptr, *xa2;
 
-            if (xa) free(xa);
-            xa = (btrfs_set_xattr*)malloc(xalen);
+            do {
+                xalen += 1024;
 
-            Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, xa, xalen);
-        } while (Status == STATUS_BUFFER_OVERFLOW);
+                if (xa) free(xa);
+                xa = (btrfs_set_xattr*)malloc(xalen);
 
-        if (!NT_SUCCESS(Status)) {
-            free(xa);
-            goto end;
-        }
+                Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
+            } while (Status == STATUS_BUFFER_OVERFLOW);
 
-        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);
             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;
 
-    ret = TRUE;
+            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];
+            }
 
-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<wstring> 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 (destdirh != INVALID_HANDLE_VALUE) {
+                BY_HANDLE_FILE_INFORMATION bhfi;
 
-            if (GetFileInformationByHandle(destdirh, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-                dest_is_dir = TRUE;
+                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"\\";
+                    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__
index 12779f4..fe48f9a 100644 (file)
@@ -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();
 };
index 8feb747..f2c297b 100644 (file)
@@ -27,8 +27,8 @@
 #include <setupapi.h>
 #include <strsafe.h>
 #include <mountmgr.h>
-#include <algorithm>
 #ifndef __REACTOS__
+#include <algorithm>
 #include "../btrfs.h"
 #else
 #include <ntddstor.h>
 
 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>* device_list) {
+static void find_devices(HWND hwnd, const GUID* guid, const nt_handle& mountmgr, vector<device>& 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 <algorithm> 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;
-            }
-        } while (Status == STATUS_BUFFER_OVERFLOW);
+            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;
 
-        if (bfs && bfs->num_devices == 0) { // no mounted filesystems found
-            free(bfs);
-            bfs = NULL;
-        }
-    }
-    NtClose(btrfsh);
+                do {
+                    bfssize += 1024;
 
-    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);
+                    if (bfs) free(bfs);
+                    bfs = (btrfs_filesystem*)malloc(bfssize);
 
-    NtClose(mountmgr);
+                    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);
 
-    std::sort(device_list.begin(), device_list.end(), sort_devices);
+                if (bfs && bfs->num_devices == 0) { // no mounted filesystems found
+                    free(bfs);
+                    bfs = nullptr;
+                }
+            }
+        }
+
+        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);
+    }
+
+#ifndef __REACTOS__ // Disabled because building with our <algorithm> 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 (!LoadStringW(module, IDS_CONFIRMATION_TITLE, title, sizeof(title) / sizeof(WCHAR))) {
-        ShowError(hwndDlg, GetLastError());
-        return;
+        if (!load_string(module, IDS_ADD_DEVICE_CONFIRMATION, mess))
+            throw last_error(GetLastError());
     }
 
-    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 (!load_string(module, IDS_CONFIRMATION_TITLE, title))
+        throw last_error(GetLastError());
 
-    if (h == INVALID_HANDLE_VALUE) {
-        ShowError(hwndDlg, GetLastError());
+    if (MessageBoxW(hwndDlg, mess.c_str(), title.c_str(), MB_YESNO) != IDYES)
         return;
-    }
 
-    vn.Length = vn.MaximumLength = sel->pnp_name.length() * sizeof(WCHAR);
-    vn.Buffer = (WCHAR*)sel->pnp_name.c_str();
+    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);
 
-    InitializeObjectAttributes(&attr, &vn, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
+    if (h == INVALID_HANDLE_VALUE)
+        throw last_error(GetLastError());
 
-    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;
-    }
+    {
+        nt_handle h2;
 
-    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;
-            }
+        vn.Length = vn.MaximumLength = (uint16_t)(sel->pnp_name.length() * sizeof(WCHAR));
+        vn.Buffer = (WCHAR*)sel->pnp_name.c_str();
 
-            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;
-            }
+        InitializeObjectAttributes(&attr, &vn, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, nullptr, nullptr);
 
-            MessageBoxW(hwndDlg, u, title, MB_ICONERROR);
+        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);
 
-            NtClose(h2);
-            CloseHandle(h);
-            return;
+        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, 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);
+        Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_ADD_DEVICE, &h2, sizeof(HANDLE), nullptr, 0);
         if (!NT_SUCCESS(Status))
-            ShowNtStatusError(hwndDlg, Status);
+            throw ntstatus_error(Status);
 
-        Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0);
-        if (!NT_SUCCESS(Status))
-            ShowNtStatusError(hwndDlg, 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);
 
-    NtClose(h2);
-    CloseHandle(h);
+            Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_UNLOCK_VOLUME, nullptr, 0, nullptr, 0);
+            if (!NT_SUCCESS(Status))
+                throw ntstatus_error(Status);
+        }
+    }
 
     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;
-
-                    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 WM_COMMAND:
+                switch (HIWORD(wParam)) {
+                    case BN_CLICKED:
+                        switch (LOWORD(wParam)) {
+                            case IDOK:
+                                AddDevice(hwndDlg);
+                            return true;
+
+                            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;
+        br.device = dev_id;
+        br.size = new_size;
 
-    Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESIZE, &br, sizeof(btrfs_resize), NULL, 0);
+        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)) {
-        ShowNtStatusError(hwndDlg, Status);
-        CloseHandle(h);
-        return;
+        if (Status != STATUS_MORE_PROCESSING_REQUIRED && !NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
     }
 
-    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];
-
-            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);
-
-            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) {
-                NTSTATUS Status;
-                IO_STATUS_BLOCK iosb;
-                btrfs_device *devices, *bd;
-                ULONG devsize;
-                BOOL found = FALSE;
-                HWND slider;
-
-                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;
+    try {
+        switch (uMsg) {
+            case WM_INITDIALOG:
+            {
+                win_handle h;
+                WCHAR s[255];
+                wstring t, u;
+
+                EnableThemeDialogTexture(hwndDlg, ETDT_ENABLETAB);
+
+                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.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;
+
+                    devsize = 1024;
+                    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) {
+                            devsize += 1024;
+
+                            free(devices);
+                            devices = (btrfs_device*)malloc(devsize);
+                        } else
+                            break;
+                    }
 
+                    if (!NT_SUCCESS(Status)) {
                         free(devices);
-                        devices = (btrfs_device*)malloc(devsize);
-                    } else
-                        break;
-                }
+                        return false;
+                    }
 
-                if (!NT_SUCCESS(Status)) {
-                    free(devices);
-                    CloseHandle(h);
-                    return FALSE;
-                }
+                    bd = devices;
 
-                bd = devices;
+                    while (true) {
+                        if (bd->dev_id == dev_id) {
+                            memcpy(&dev_info, bd, sizeof(btrfs_device));
+                            found = true;
+                            break;
+                        }
 
-                while (TRUE) {
-                    if (bd->dev_id == dev_id) {
-                        memcpy(&dev_info, bd, sizeof(btrfs_device));
-                        found = TRUE;
-                        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 (!found) {
+                        free(devices);
+                        return false;
+                    }
 
-                if (!found) {
                     free(devices);
-                    CloseHandle(h);
-                    return FALSE;
-                }
 
-                free(devices);
-                CloseHandle(h);
+                    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());
 
-                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;
 
-                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());
 
-                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, (LPARAM)(dev_info.max_size / 1048576));
+                    SendMessageW(slider, TBM_SETPOS, true, (LPARAM)(new_size / 1048576));
+                } else
+                    return false;
 
-                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;
-                    }
                 break;
             }
-        break;
 
-        case WM_HSCROLL:
-        {
-            WCHAR t[255], u[255];
+            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;
 
-            new_size = UInt32x32To64(SendMessageW(GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER), TBM_GETPOS, 0, 0), 1048576);
+            case WM_HSCROLL:
+            {
+                wstring t, u;
 
-            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);
+                new_size = UInt32x32To64(SendMessageW(GetDlgItem(hwndDlg, IDC_RESIZE_SLIDER), TBM_GETPOS, 0, 0), 1048576);
 
-            EnableWindow(GetDlgItem(hwndDlg, IDOK), new_size > 0 ? TRUE : FALSE);
+                format_size(new_size, u, true);
+                wstring_sprintf(t, new_size_text, u.c_str());
+                SetDlgItemTextW(hwndDlg, IDC_RESIZE_NEWSIZE, t.c_str());
 
-            break;
+                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(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;
-
-    if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
-        ShowError(hwnd, GetLastError());
-        goto end;
-    }
+        tp.PrivilegeCount = 1;
+        tp.Privileges[0].Luid = luid;
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
-    bda = new BtrfsDeviceAdd(hinst, hwnd, lpszCmdLine);
-    bda->ShowDialog();
-    delete bda;
+        if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
+            throw last_error(GetLastError());
 
-end:
-    CloseHandle(token);
+        BtrfsDeviceAdd bda(hinst, hwnd, lpszCmdLine);
+        bda.ShowDialog();
+    } catch (const exception& e) {
+        error_message(hwnd, e.what());
+    }
 }
 
 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;
-
-    set_dpi_aware();
-
-    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
-        ShowError(hwnd, GetLastError());
-        return;
-    }
+    try {
+        WCHAR *s, *vol, *dev;
+        uint64_t devid;
+        win_handle h, token;
+        TOKEN_PRIVILEGES tp;
+        LUID luid;
+        NTSTATUS Status;
+        IO_STATUS_BLOCK iosb;
 
-    if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
-        ShowError(hwnd, GetLastError());
-        goto end;
-    }
+        set_dpi_aware();
 
-    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 (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
+            throw last_error(GetLastError());
 
-    s = wcsstr(lpszCmdLine, L"|");
-    if (!s)
-        goto end;
+        if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
+            throw last_error(GetLastError());
 
-    s[0] = 0;
+        tp.PrivilegeCount = 1;
+        tp.Privileges[0].Luid = luid;
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
-    vol = lpszCmdLine;
-    dev = &s[1];
+        if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
+            throw last_error(GetLastError());
 
-    devid = _wtoi(dev);
-    if (devid == 0)
-        goto end;
+        s = wcsstr(lpszCmdLine, L"|");
+        if (!s)
+            return;
 
-    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);
+        s[0] = 0;
 
-    if (h == INVALID_HANDLE_VALUE) {
-        ShowError(hwnd, GetLastError());
-        goto end;
-    }
+        vol = lpszCmdLine;
+        dev = &s[1];
 
-    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;
-    }
+        devid = _wtoi(dev);
+        if (devid == 0)
+            return;
 
-    CloseHandle(h);
+        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);
 
-    bb = new BtrfsBalance(vol, TRUE);
+        if (h == INVALID_HANDLE_VALUE)
+            throw last_error(GetLastError());
 
-    bb->ShowBalance(hwnd);
+        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);
 
-    delete bb;
+            return;
+        }
 
-end:
-    CloseHandle(token);
+        BtrfsBalance bb(vol, true);
+        bb.ShowBalance(hwnd);
+    } catch (const exception& e) {
+        error_message(hwnd, e.what());
+    }
 }
 
 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;
-
-    set_dpi_aware();
+    try {
+        WCHAR *s, *vol, *dev;
+        uint64_t devid;
+        win_handle token;
+        TOKEN_PRIVILEGES tp;
+        LUID luid;
 
-    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
-        ShowError(hwnd, GetLastError());
-        return;
-    }
+        set_dpi_aware();
 
-    if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
-        ShowError(hwnd, GetLastError());
-        goto end;
-    }
+        if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
+            throw last_error(GetLastError());
 
-    tp.PrivilegeCount = 1;
-    tp.Privileges[0].Luid = luid;
-    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
+        if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
+            throw last_error(GetLastError());
 
-    if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
-        ShowError(hwnd, GetLastError());
-        goto end;
-    }
+        tp.PrivilegeCount = 1;
+        tp.Privileges[0].Luid = luid;
+        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
-    s = wcsstr(lpszCmdLine, L"|");
-    if (!s)
-        goto end;
+        if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
+            throw last_error(GetLastError());
 
-    s[0] = 0;
+        s = wcsstr(lpszCmdLine, L"|");
+        if (!s)
+            return;
 
-    vol = lpszCmdLine;
-    dev = &s[1];
+        s[0] = 0;
 
-    devid = _wtoi(dev);
-    if (devid == 0)
-        goto end;
+        vol = lpszCmdLine;
+        dev = &s[1];
 
-    bdr = new BtrfsDeviceResize;
-    bdr->ShowDialog(hwnd, vol, devid);
-    delete bdr;
+        devid = _wtoi(dev);
+        if (devid == 0)
+            return;
 
-end:
-    CloseHandle(token);
+        BtrfsDeviceResize bdr;
+        bdr.ShowDialog(hwnd, vol, devid);
+    } catch (const exception& e) {
+        error_message(hwnd, e.what());
+    }
 }
 
 #ifdef __cplusplus
index e6b949a..cc5724c 100644 (file)
@@ -28,8 +28,6 @@
 #include <ndk/iotypes.h>
 #endif
 #include <shlobj.h>
-#include <vector>
-#include <string>
 #ifndef __REACTOS__
 #include "../btrfsioctl.h"
 #else
 #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> device_list;
+    vector<device> 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;
 };
index 9008359..e5a5455 100644 (file)
@@ -27,7 +27,7 @@ HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
     if (iid == IID_IUnknown || iid == IID_IClassFactory) {
         *ppv = static_cast<IClassFactory*>(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;
 }
index cfc312c..6cfbe4b 100644 (file)
@@ -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;
 }
index a7ac6a2..92f4c5b 100644 (file)
@@ -20,6 +20,7 @@
 #include <commctrl.h>
 #include <strsafe.h>
 #include <stddef.h>
+#include <stdexcept>
 #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
+
+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
 
-STDAPI DllCanUnloadNow(void) {
+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);
-
-        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);
+    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, 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);
-
-    if (!write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, NULL, REG_SZ, (BYTE*)description, (wcslen(description) + 1) * sizeof(WCHAR)))
-        goto end;
+    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
 
-    GetModuleFileNameW(module, dllpath, sizeof(dllpath));
+        write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, nullptr, description);
 
-    if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, NULL, REG_SZ, (BYTE*)dllpath, (wcslen(dllpath) + 1) * sizeof(WCHAR)))
-        goto end;
+        GetModuleFileNameW(module, dllpath, sizeof(dllpath));
 
-    if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", REG_SZ, (BYTE*)L"Apartment", (wcslen(L"Apartment") + 1) * sizeof(WCHAR)))
-        goto end;
+        write_reg_key(HKEY_CLASSES_ROOT, inproc, nullptr, dllpath);
 
-    ret = TRUE;
+        write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", L"Apartment");
+    } catch (...) {
+        CoTaskMemFree(clsidstring);
+        throw;
+    }
 
-end:
     CoTaskMemFree(clsidstring);
-
-    return ret;
 }
 
-static BOOL unregister_clsid(const GUID clsid) {
+static void 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);
+    try {
+        WCHAR clsidkeyname[MAX_PATH];
 
-    if (l != ERROR_SUCCESS) {
-        WCHAR s[255];
-        wsprintfW(s, L"RegDeleteTree returned %08x", l);
-        MessageBoxW(0, s, NULL, MB_ICONERROR);
+        wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring);
 
-        ret = FALSE;
-    } else
-        ret = TRUE;
+        LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname);
 
-    CoTaskMemFree(clsidstring);
+        if (l != ERROR_SUCCESS)
+            throw string_error(IDS_REGDELETETREE_FAILED, l);
+    } catch (...) {
+        CoTaskMemFree(clsidstring);
+        throw;
+    }
 
-    return ret;
+    CoTaskMemFree(clsidstring);
 }
 
-static BOOL reg_icon_overlay(const GUID clsid, 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, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\");
-    wcscat(path, name);
-
-    if (!write_reg_key(HKEY_LOCAL_MACHINE, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR)))
-        goto end;
+    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
 
-    ret = TRUE;
+        write_reg_key(HKEY_LOCAL_MACHINE, path, nullptr, clsidstring);
+    } 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);
+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
 
-    if (l != ERROR_SUCCESS) {
-        WCHAR s[255];
-        wsprintfW(s, L"RegDeleteTree returned %08x", l);
-        MessageBoxW(0, s, NULL, MB_ICONERROR);
+    LONG l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path.c_str());
 
-        return FALSE;
-    } else
-        return TRUE;
+    if (l != ERROR_SUCCESS)
+        throw string_error(IDS_REGDELETETREE_FAILED, l);
 }
 
-static BOOL reg_context_menu_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\\ContextMenuHandlers\\");
-    wcscat(path, name);
-
-    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);
+    try {
+#ifndef __REACTOS__
+        wstring path = filetype + L"\\ShellEx\\ContextMenuHandlers\\"s + name;
+#else
+        wstring path = filetype + wstring(L"\\ShellEx\\ContextMenuHandlers\\") + name;
+#endif
 
-    return ret;
+        write_reg_key(HKEY_CLASSES_ROOT, path, nullptr, clsidstring);
+    } catch (...) {
+        CoTaskMemFree(clsidstring);
+        throw;
+    }
 }
 
-static BOOL unreg_context_menu_handler(const WCHAR* filetype, const WCHAR* name) {
-    WCHAR path[MAX_PATH];
-    LONG l;
-
-    wcscpy(path, filetype);
-    wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\");
-    wcscat(path, name);
-
-    l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path);
+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
 
-    if (l != ERROR_SUCCESS) {
-        WCHAR s[255];
-        wsprintfW(s, L"RegDeleteTree returned %08x", l);
-        MessageBoxW(0, s, NULL, MB_ICONERROR);
+    LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str());
 
-        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_prop_sheet_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);
-
-    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);
+    try {
+#ifndef __REACTOS__
+        wstring path = filetype + L"\\ShellEx\\PropertySheetHandlers\\"s + name;
+#else
+        wstring path = filetype + wstring(L"\\ShellEx\\PropertySheetHandlers\\") + name;
+#endif
 
-    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;
-
-    wcscpy(path, filetype);
-    wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\");
-    wcscat(path, name);
-
-    l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path);
+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 (l != ERROR_SUCCESS) {
-        WCHAR s[255];
-        wsprintfW(s, L"RegDeleteTree returned %08x", l);
-        MessageBoxW(0, s, NULL, MB_ICONERROR);
+    LONG l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path.c_str());
 
-        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;
-
-    if (!register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU))
-        return E_FAIL;
-
-    if (!register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET))
-        return E_FAIL;
-
-    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;
-    }
-
-    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;
-    }
-
-    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;
-    }
+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_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME)) {
-        MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR);
-        return E_FAIL;
-    }
+        reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME);
 
-    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;
-    }
+        reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME);
+        reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME);
 
-    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_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);
-
-    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))
+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);
+
+        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;
-
-    args = CommandLineToArgvW(lpszCmdLine, &num_args);
+extern "C" void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
+    vector<wstring> args;
 
-    if (!args)
-        return;
+    command_line_to_args(lpszCmdLine, args);
 
-    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);
+    NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
+}
+
+extern "C" void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
+    vector<wstring> args;
+
+    command_line_to_args(lpszCmdLine, args);
 
-    CloseHandle(h);
-    CloseHandle(src);
+    if (args.size() >= 2)
+        create_snapshot2(args[0], args[1]);
 }
 
-void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
-    LPWSTR* args;
+void command_line_to_args(LPWSTR cmdline, vector<wstring> args) {
+    LPWSTR* l;
     int num_args;
 
-    args = CommandLineToArgvW(lpszCmdLine, &num_args);
+    args.clear();
+
+    l = CommandLineToArgvW(cmdline, &num_args);
 
-    if (!args)
+    if (!l)
         return;
 
-    if (num_args >= 2)
-        create_snapshot2(args[0], args[1]);
+    try {
+        args.reserve(num_args);
+
+        for (unsigned int i = 0; i < (unsigned int)num_args; i++) {
+            args.push_back(l[i]);
+        }
+    } catch (...) {
+        LocalFree(l);
+        throw;
+    }
+
+    LocalFree(l);
+}
+
+#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
 
-    LocalFree(args);
+    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 __cplusplus
+#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
index d329e3c..4c3478f 100644 (file)
@@ -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;
-
-    memcpy(ss, fn, (wcslen(fn) + 1) * sizeof(WCHAR));
-    wcscat(ss, L"\\*");
+#ifndef __REACTOS__
+    ss = fn + L"\\*"s;
+#else
+    ss = fn + wstring(L"\\*");
+#endif
 
-    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));
-
-            memcpy(fn2, fn, (wcslen(fn) + 1) * sizeof(WCHAR));
-            wcscat(fn2, L"\\");
-            wcscat(fn2, ffd.cFileName);
+            wstring fn2;
 
-            if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-                add_to_search_list(fn2);
-            } else {
-                HANDLE fh;
+#ifndef __REACTOS__
+            fn2 = fn + L"\\"s + ffd.cFileName;
+#else
+            fn2 = fn + wstring(L"\\") + ffd.cFileName;
+#endif
 
-                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;
+
+                    memset(&bii2, 0, sizeof(bii2));
 
-                    Status = NtFsControlFile(fh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_INODE_INFO, NULL, 0, &bii2, sizeof(btrfs_inode_info));
+                    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;
+
+                    Status = NtQueryInformationFile(fh, &iosb, &fsi, sizeof(fsi), FileStandardInformation);
 
-                free(fn2);
+                    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));
 
-    if (NT_SUCCESS(Status) && !bii2.top) {
-        int j;
+    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) {
         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 (pidlFolder)
+            return E_FAIL;
 
-    if (!pdtobj)
-        return E_FAIL;
+        if (!pdtobj)
+            return E_FAIL;
 
-    stgm.tymed = TYMED_HGLOBAL;
+        stgm.tymed = TYMED_HGLOBAL;
 
-    if (FAILED(pdtobj->GetData(&format, &stgm)))
-        return E_INVALIDARG;
+        if (FAILED(pdtobj->GetData(&format, &stgm)))
+            return E_INVALIDARG;
 
-    stgm_set = TRUE;
+        stgm_set = true;
 
-    hdrop = (HDROP)GlobalLock(stgm.hGlobal);
+        hdrop = (HDROP)GlobalLock(stgm.hGlobal);
 
-    if (!hdrop) {
-        ReleaseStgMedium(&stgm);
-        stgm_set = FALSE;
-        return E_INVALIDARG;
-    }
+        if (!hdrop) {
+            ReleaseStgMedium(&stgm);
+            stgm_set = false;
+            return E_INVALIDARG;
+        }
 
-    hr = load_file_list();
-    if (FAILED(hr))
-        return hr;
+        try {
+            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 (search_list.size() > 0) {
+                thread = CreateThread(nullptr, 0, global_search_list_thread, this, 0, nullptr);
 
-        if (!thread)
-            ShowError(NULL, GetLastError());
-    }
+                if (!thread)
+                    throw last_error(GetLastError());
+            }
+        } catch (...) {
+            GlobalUnlock(hdrop);
+            throw;
+        }
 
-    GlobalUnlock(hdrop);
+        GlobalUnlock(hdrop);
+    } catch (const exception& e) {
+        error_message(nullptr, e.what());
+
+        return E_FAIL;
+    }
 
     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));
 
-    if (NT_SUCCESS(Status) && !bii2.top) {
-        int j;
+    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) {
         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;
-    }
+&nbs