[SHELLBTRFS] Use again .data() method of vector class
[reactos.git] / dll / shellext / shellbtrfs / contextmenu.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 1e004ce..3fbca1c
@@ -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;
+                        wstring parpath;
 
-                        StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn);
+                        {
+                            win_handle h2;
 
-                        PathRemoveFileSpecW(parpath);
+                            parpath = fn;
+                            path_remove_file(parpath);
 
-                        h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+                            h2 = CreateFileW(parpath.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
+                                            OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
 
-                        if (h2 != INVALID_HANDLE_VALUE)
-                            allow_snapshot = TRUE;
-
-                        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];
 
-    // check we have permissions to create new subdirectory
+        if (!SHGetPathFromIDListW(pidlFolder, pathbuf))
+            return E_FAIL;
 
-    h = CreateFileW(path, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
+        path = pathbuf;
+    }
 
-    if (h == INVALID_HANDLE_VALUE)
-        return E_FAIL;
+    {
+        // check we have permissions to create new subdirectory
 
-    // check is Btrfs volume
+        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);
 
-    Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
+        if (h == INVALID_HANDLE_VALUE)
+            return E_FAIL;
 
-    if (!NT_SUCCESS(Status)) {
-        CloseHandle(h);
-        return E_FAIL;
-    }
+        // check is Btrfs volume
+
+        Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
 
-    CloseHandle(h);
+        if (!NT_SUCCESS(Status))
+            return E_FAIL;
+    }
 
-    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 stride = (UINT)(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,116 +423,122 @@ 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;
-            btrfs_create_snapshot* bcs;
-            ULONG namelen, pathend;
+            wstring subvolname, parpath, searchpath, temp1, name, nameorig;
+            win_handle h2;
             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);
+            size_t namelen = name.length() * sizeof(WCHAR);
 
-            bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
-            bcs->readonly = FALSE;
-            bcs->posix = FALSE;
+            auto bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
+            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,
+                                     (ULONG)(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;
@@ -555,58 +561,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_info));
+    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,86 +615,68 @@ 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,
+                                 (ULONG)(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;
-    }
+    Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
+    if (!NT_SUCCESS(Status))
+        throw ntstatus_error(Status);
 
     if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
-        HANDLE dirh;
-        ULONG bmnsize;
+        win_handle dirh;
         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));
+        size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
         bmn = (btrfs_mknod*)malloc(bmnsize);
 
         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, (ULONG)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,510 +699,468 @@ 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 {
+            if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+                reparse_header rh;
+                uint8_t* rp;
 
-            if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, NULL, 0, rp, rplen, &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());
+                }
 
-            if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, NULL, 0, &bytesret, NULL)) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
+                rp = (uint8_t*)malloc(rplen);
 
-            free(rp);
-        } else {
-            FILE_STANDARD_INFO fsi;
-            FILE_END_OF_FILE_INFO feofi;
-            FSCTL_GET_INTEGRITY_INFORMATION_BUFFER fgiib;
-            FSCTL_SET_INTEGRITY_INFORMATION_BUFFER fsiib;
-            DUPLICATE_EXTENTS_DATA ded;
-            UINT64 offset, alloc_size;
-            ULONG maxdup;
-
-            if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO))) {
-                ShowError(hwnd, GetLastError());
-                goto end;
-            }
+                if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (ULONG)rplen, &bytesret, nullptr))
+                    throw last_error(GetLastError());
 
-            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(dest, FSCTL_SET_REPARSE_POINT, rp, (ULONG)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;
+
+                Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
+
+                if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
+                    throw last_error(GetLastError());
+
+                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;
+                Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
-            ded.FileHandle = source;
-            maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
+                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) {
+            ULONG streambufsize = 0;
+            vector<char> streambuf;
+
             do {
-                std::wstring sn;
+                streambufsize += 0x1000;
+                streambuf.resize(streambufsize);
 
-                sn = fsd.cStreamName;
+                memset(streambuf.data(), 0, streambufsize);
 
-                if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
-                    HANDLE stream;
-                    UINT8* data = NULL;
+                Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
+            } while (Status == STATUS_BUFFER_OVERFLOW);
 
-                    if (fsd.StreamSize.QuadPart > 0) {
-                        std::wstring fn2;
+            if (!NT_SUCCESS(Status))
+                throw ntstatus_error(Status);
 
-                        fn2 = fn;
-                        fn2 += sn;
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
 
-                        stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+            while (true) {
+                if (fsi->StreamNameLength > 0) {
+                    wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
 
-                        if (stream == INVALID_HANDLE_VALUE) {
-                            ShowError(hwnd, GetLastError());
-                            goto end;
-                        }
+                    if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
+                        win_handle stream;
+                        uint8_t* data = nullptr;
+                        auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
 
-                        // We can get away with this because our streams are guaranteed to be below 64 KB -
-                        // don't do this on NTFS!
-                        data = (UINT8*)malloc(fsd.StreamSize.QuadPart);
 
-                        if (!ReadFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) {
-                            ShowError(hwnd, GetLastError());
-                            free(data);
-                            CloseHandle(stream);
-                            goto end;
-                        }
+                        if (stream_size > 0) {
+                            wstring fn2;
 
-                        CloseHandle(stream);
-                    }
+                            fn2 = fn;
+                            fn2 += sn;
 
-                    stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, NULL);
+                            stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
 
-                    if (stream == INVALID_HANDLE_VALUE) {
-                        ShowError(hwnd, GetLastError());
+                            if (stream == INVALID_HANDLE_VALUE)
+                                throw last_error(GetLastError());
 
-                        if (data) free(data);
+                            // 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);
 
-                        goto end;
-                    }
+                            if (!ReadFile(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());
-                            free(data);
-                            CloseHandle(stream);
-                            goto end;
+                        stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
+
+                        if (stream == INVALID_HANDLE_VALUE) {
+                            if (data) free(data);
+                            throw last_error(GetLastError());
                         }
 
-                        free(data);
-                    }
+                        if (data) {
+                            if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
 
-                    CloseHandle(stream);
+                            free(data);
+                        }
+                    }
                 }
-            } while (FindNextStreamW(h, &fsd));
 
-            FindClose(h);
+                if (fsi->NextEntryOffset == 0)
+                    break;
+
+                fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
+            }
         }
-    }
 
-    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;
+            do {
+                xalen += 1024;
 
-            if (xa) free(xa);
-            xa = (btrfs_set_xattr*)malloc(xalen);
+                if (xa) free(xa);
+                xa = (btrfs_set_xattr*)malloc(xalen);
 
-            Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, xa, xalen);
-        } while (Status == STATUS_BUFFER_OVERFLOW);
+                Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
+            } while (Status == STATUS_BUFFER_OVERFLOW);
 
-        if (!NT_SUCCESS(Status)) {
-            free(xa);
-            ShowNtStatusError(hwnd, Status);
-            goto end;
-        }
-
-        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,
+                                         (ULONG)(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;
-        if (!SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
-            ShowError(hwnd, GetLastError());
-    }
-
-    CloseHandle(dest);
-    CloseHandle(source);
+        fdi.DeleteFile = true;
+        Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
+        if (!NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
 
-    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;
+                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));
+                if (!load_string(module, IDS_NEW_SUBVOL_FILENAME, name))
+                    throw last_error(GetLastError());
 
-            StringCchCopyW(searchpath, searchpathlen, path);
-            StringCchCatW(searchpath, searchpathlen, L"\\");
-            pathend = wcslen(searchpath);
+                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);
 
-            StringCchCatW(searchpath, searchpathlen, name);
+                if (h == INVALID_HANDLE_VALUE)
+                    throw last_error(GetLastError());
 
-            fff = FindFirstFileW(searchpath, &wfd);
+                searchpath = path + L"\\" + name;
+                nameorig = name;
 
-            if (fff != INVALID_HANDLE_VALUE) {
-                ULONG i = wcslen(searchpath), num = 2;
+                {
+                    fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
 
-                do {
-                    FindClose(fff);
+                    if (fff != INVALID_HANDLE_VALUE) {
+                        ULONG num = 2;
 
-                    searchpath[i] = 0;
-                    if (StringCchPrintfW(searchpath, searchpathlen, L"%s (%u)", searchpath, num) == STRSAFE_E_INSUFFICIENT_BUFFER) {
-                        MessageBoxW(pici->hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR);
-                        CloseHandle(h);
-                        return E_FAIL;
-                    }
-
-                    fff = FindFirstFileW(searchpath, &wfd);
-                    num++;
-                } while (fff != INVALID_HANDLE_VALUE);
-            }
+                        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);
+                size_t 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, (ULONG)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;
@@ -1385,9 +1317,8 @@ 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;
@@ -1397,357 +1328,356 @@ static void reflink_copy2(std::wstring srcfn, std::wstring destdir, std::wstring
     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_info));
+    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));
+        size_t 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, (ULONG)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;
-    }
+    Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
+    if (!NT_SUCCESS(Status))
+        throw ntstatus_error(Status);
 
     if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
-        HANDLE dirh;
-        ULONG bmnsize;
+        win_handle dirh;
         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));
+        size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
         bmn = (btrfs_mknod*)malloc(bmnsize);
 
         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, (ULONG)bmnsize, nullptr, 0);
         if (!NT_SUCCESS(Status)) {
-            CloseHandle(dirh);
-            CloseHandle(source);
             free(bmn);
-            return;
+            throw ntstatus_error(Status);
         }
 
-        CloseHandle(dirh);
         free(bmn);
 
-        dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, OPEN_EXISTING, 0, NULL);
+        dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
     } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), NULL))
+        if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), nullptr))
             dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
-                               NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
-            else
-                dest = INVALID_HANDLE_VALUE;
+                               nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
+        else
+            dest = INVALID_HANDLE_VALUE;
     } else
-        dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, NULL, CREATE_NEW, 0, source);
+        dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source);
 
-    if (dest == INVALID_HANDLE_VALUE) {
-        CloseHandle(source);
-        return;
-    }
+    if (dest == INVALID_HANDLE_VALUE)
+        throw last_error(GetLastError());
 
     memset(&bsii, 0, sizeof(btrfs_set_inode_info));
 
-    bsii.flags_changed = TRUE;
+    bsii.flags_changed = true;
     bsii.flags = bii.flags;
 
     if (bii.flags & BTRFS_INODE_COMPRESS) {
-        bsii.compression_type_changed = TRUE;
+        bsii.compression_type_changed = true;
         bsii.compression_type = bii.compression_type;
     }
 
-    Status = NtFsControlFile(dest, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), NULL, 0);
-    if (!NT_SUCCESS(Status))
-        goto end;
+    try {
+        Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0);
+        if (!NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
 
-    if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
-        if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
-            HANDLE h;
-            WIN32_FIND_DATAW fff;
-            std::wstring qs;
+        if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
+            if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
+                WIN32_FIND_DATAW fff;
+                wstring qs;
 
-            qs = srcfn;
-            qs += L"\\*";
+                qs = srcfn;
+                qs += L"\\*";
 
-            h = FindFirstFileW(qs.c_str(), &fff);
-            if (h != INVALID_HANDLE_VALUE) {
-                do {
-                    std::wstring fn2;
-
-                    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;
-
-        if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
-            reparse_header rh;
-            ULONG rplen;
-            UINT8* rp;
+            // CreateDirectoryExW also copies streams, no need to do it here
+        } else {
+            if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
+                reparse_header rh;
+                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);
+                size_t 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, (DWORD)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, (DWORD)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;
+
+                Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
+
+                if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
+                    throw last_error(GetLastError());
+
+                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;
+                Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
-            ded.FileHandle = source;
-            maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
+                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) {
+            ULONG streambufsize = 0;
+            vector<char> streambuf;
+
             do {
-                std::wstring sn;
+                streambufsize += 0x1000;
+                streambuf.resize(streambufsize);
 
-                sn = fsd.cStreamName;
+                memset(streambuf.data(), 0, streambufsize);
 
-                if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
-                    HANDLE stream;
-                    UINT8* data = NULL;
+                Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
+            } while (Status == STATUS_BUFFER_OVERFLOW);
 
-                    if (fsd.StreamSize.QuadPart > 0) {
-                        std::wstring fn2;
+            if (!NT_SUCCESS(Status))
+                throw ntstatus_error(Status);
 
-                        fn2 = srcfn;
-                        fn2 += sn;
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
 
-                        stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
+            while (true) {
+                if (fsi->StreamNameLength > 0) {
+                    wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
 
-                        if (stream == INVALID_HANDLE_VALUE)
-                            goto end;
+                    if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
+                        win_handle stream;
+                        uint8_t* data = nullptr;
+                        auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
 
-                        // We can get away with this because our streams are guaranteed to be below 64 KB -
-                        // don't do this on NTFS!
-                        data = (UINT8*)malloc(fsd.StreamSize.QuadPart);
+                        if (stream_size > 0) {
+                            wstring fn2;
 
-                        if (!ReadFile(stream, data, fsd.StreamSize.QuadPart, &bytesret, NULL)) {
-                            free(data);
-                            CloseHandle(stream);
-                            goto end;
+                            fn2 = srcfn;
+                            fn2 += sn;
+
+                            stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
+
+                            if (stream == INVALID_HANDLE_VALUE)
+                                throw last_error(GetLastError());
+
+                            // We can get away with this because our streams are guaranteed to be below 64 KB -
+                            // don't do this on NTFS!
+                            data = (uint8_t*)malloc(stream_size);
+
+                            if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
+                                free(data);
+                                throw last_error(GetLastError());
+                            }
                         }
 
-                        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, stream_size, &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);
-        }
-    }
+                if (fsi->NextEntryOffset == 0)
+                    break;
 
-    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);
+                fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
+            }
+        }
 
-    Status = NtFsControlFile(source, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_XATTRS, NULL, 0, &bsxa, sizeof(btrfs_set_xattr));
+        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);
 
-    if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
-        ULONG xalen = 0;
-        btrfs_set_xattr *xa = NULL, *xa2;
+        Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr));
 
-        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,
+                                         (ULONG)(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;
-        SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
-    }
+        fdi.DeleteFile = true;
+        Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
+        if (!NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
 
-    CloseHandle(dest);
-    CloseHandle(source);
+        throw;
+    }
 }
 
-void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
-    LPWSTR* args;
-    int num_args;
+#ifdef __REACTOS__
+extern "C" {
+#endif
 
-    args = CommandLineToArgvW(lpszCmdLine, &num_args);
+void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
+    vector<wstring> args;
 
-    if (!args)
-        return;
+    command_line_to_args(lpszCmdLine, args);
 
-    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 {
@@ -1757,19 +1687,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);
@@ -1779,16 +1708,19 @@ 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__
+} /* extern "C" */
+#endif