[SHELLBTRFS] Addendum to 1725ddf
[reactos.git] / dll / shellext / shellbtrfs / contextmenu.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 6e51a0f..bf4b5e9
@@ -323,7 +323,7 @@ void BtrfsContextMenu::get_uac_icon() {
 
                 hr = Create32BitHBITMAP(nullptr, &sz, (void**)&buf, &uacicon);
                 if (SUCCEEDED(hr)) {
-                    UINT stride = cx * sizeof(DWORD);
+                    UINT stride = (UINT)(cx * sizeof(DWORD));
                     UINT buflen = cy * stride;
                     bitmap->CopyPixels(nullptr, stride, buflen, buf);
                 }
@@ -462,8 +462,6 @@ static void create_snapshot(HWND hwnd, const wstring& fn) {
         if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) {
             wstring subvolname, parpath, searchpath, temp1, name, nameorig;
             win_handle h2;
-            btrfs_create_snapshot* bcs;
-            ULONG namelen;
             WIN32_FIND_DATAW wfd;
             SYSTEMTIME time;
 
@@ -511,16 +509,17 @@ static void create_snapshot(HWND hwnd, const wstring& fn) {
                 } while (fff != INVALID_HANDLE_VALUE);
             }
 
-            namelen = name.length() * sizeof(WCHAR);
+            size_t namelen = name.length() * sizeof(WCHAR);
 
-            bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
+            auto bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
             bcs->readonly = false;
             bcs->posix = false;
             bcs->subvol = h;
             bcs->namelen = (uint16_t)namelen;
             memcpy(bcs->name, name.c_str(), namelen);
 
-            Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen, nullptr, 0);
+            Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
+                                     (ULONG)(sizeof(btrfs_create_snapshot) - 1 + namelen), nullptr, 0);
 
             if (!NT_SUCCESS(Status))
                 throw ntstatus_error(Status);
@@ -542,7 +541,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
     wstring dirw, newpath;
     FILE_BASIC_INFO fbi;
     FILETIME atime, mtime;
-    btrfs_inode_info2 bii;
+    btrfs_inode_info bii;
     btrfs_set_inode_info bsii;
     ULONG bytesret;
     NTSTATUS Status;
@@ -575,7 +574,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
     if (source == INVALID_HANDLE_VALUE)
         throw last_error(GetLastError());
 
-    Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2));
+    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);
 
@@ -619,7 +618,8 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
         bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
         memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
 
-        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen, nullptr, 0);
+        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
+                                 (ULONG)(sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen), nullptr, 0);
 
         free(bcs);
 
@@ -629,19 +629,19 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
         return;
     }
 
-    if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
-        throw last_error(GetLastError());
+    Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
+    if (!NT_SUCCESS(Status))
+        throw ntstatus_error(Status);
 
     if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
         win_handle dirh;
-        ULONG bmnsize;
         btrfs_mknod* bmn;
 
         dirh = CreateFileW(dir, FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
         if (dirh == INVALID_HANDLE_VALUE)
             throw last_error(GetLastError());
 
-        bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
+        size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
         bmn = (btrfs_mknod*)malloc(bmnsize);
 
         bmn->inode = 0;
@@ -650,7 +650,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
         bmn->namelen = (uint16_t)(wcslen(name) * sizeof(WCHAR));
         memcpy(bmn->name, name, bmn->namelen);
 
-        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
+        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
         if (!NT_SUCCESS(Status)) {
             free(bmn);
             throw ntstatus_error(Status);
@@ -759,11 +759,8 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
 
             // CreateDirectoryExW also copies streams, no need to do it here
         } else {
-            WIN32_FIND_STREAM_DATA fsd;
-
             if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
                 reparse_header rh;
-                ULONG rplen;
                 uint8_t* rp;
 
                 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
@@ -771,13 +768,13 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
                         throw last_error(GetLastError());
                 }
 
-                rplen = sizeof(reparse_header) + rh.ReparseDataLength;
+                size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
                 rp = (uint8_t*)malloc(rplen);
 
-                if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
+                if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (ULONG)rplen, &bytesret, nullptr))
                     throw last_error(GetLastError());
 
-                if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
+                if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (ULONG)rplen, nullptr, 0, &bytesret, nullptr))
                     throw last_error(GetLastError());
 
                 free(rp);
@@ -790,8 +787,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
                 uint64_t offset, alloc_size;
                 ULONG maxdup;
 
-                if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
-                    throw last_error(GetLastError());
+                Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
                 if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
                     throw last_error(GetLastError());
@@ -808,8 +806,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
                     throw last_error(GetLastError());
 
                 feofi.EndOfFile = fsi.EndOfFile;
-                if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
-                    throw last_error(GetLastError());
+                Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
                 ded.FileHandle = source;
                 maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
@@ -827,19 +826,44 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
                 }
             }
 
-            fff_handle h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0);
-            if (h != INVALID_HANDLE_VALUE) {
-                do {
-                    wstring sn;
+            ULONG streambufsize = 0;
+            vector<char> streambuf;
 
-                    sn = fsd.cStreamName;
+            do {
+                streambufsize += 0x1000;
+                streambuf.resize(streambufsize);
+
+#ifndef __REACTOS__
+                memset(streambuf.data(), 0, streambufsize);
+
+                Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
+#else
+                memset(&streambuf[0], 0, streambufsize);
+
+                Status = NtQueryInformationFile(source, &iosb, &streambuf[0], streambufsize, FileStreamInformation);
+#endif
+            } while (Status == STATUS_BUFFER_OVERFLOW);
+
+            if (!NT_SUCCESS(Status))
+                throw ntstatus_error(Status);
+
+#ifndef __REACTOS__
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
+#else
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(&streambuf[0]);
+#endif
+
+            while (true) {
+                if (fsi->StreamNameLength > 0) {
+                    wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
 
                     if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
                         win_handle stream;
                         uint8_t* data = nullptr;
-                        uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
+                        auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
+
 
-                        if (fsd.StreamSize.QuadPart > 0) {
+                        if (stream_size > 0) {
                             wstring fn2;
 
                             fn2 = fn;
@@ -876,7 +900,12 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
                             free(data);
                         }
                     }
-                } while (FindNextStreamW(h, &fsd));
+                }
+
+                if (fsi->NextEntryOffset == 0)
+                    break;
+
+                fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
             }
         }
 
@@ -909,7 +938,7 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
             xa2 = xa;
             while (xa2->valuelen > 0) {
                 Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
-                                        offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
+                                         (ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
                 if (!NT_SUCCESS(Status)) {
                     free(xa);
                     throw ntstatus_error(Status);
@@ -924,8 +953,9 @@ void BtrfsContextMenu::reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir
         FILE_DISPOSITION_INFO fdi;
 
         fdi.DeleteFile = true;
-        if (!SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
-            throw last_error(GetLastError());
+        Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
+        if (!NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
 
         throw;
     }
@@ -1007,7 +1037,6 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
                 win_handle h;
                 IO_STATUS_BLOCK iosb;
                 NTSTATUS Status;
-                ULONG bcslen;
                 wstring name, nameorig, searchpath;
                 btrfs_create_subvol* bcs;
                 WIN32_FIND_DATAW wfd;
@@ -1048,7 +1077,7 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
                     }
                 }
 
-                bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
+                size_t bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
                 bcs = (btrfs_create_subvol*)malloc(bcslen);
 
                 bcs->readonly = false;
@@ -1056,7 +1085,7 @@ HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO picia) {
                 bcs->namelen = (uint16_t)(name.length() * sizeof(WCHAR));
                 memcpy(bcs->name, name.c_str(), name.length() * sizeof(WCHAR));
 
-                Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
+                Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
 
                 free(bcs);
 
@@ -1302,7 +1331,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
     win_handle source, dest;
     FILE_BASIC_INFO fbi;
     FILETIME atime, mtime;
-    btrfs_inode_info2 bii;
+    btrfs_inode_info bii;
     btrfs_set_inode_info bsii;
     ULONG bytesret;
     NTSTATUS Status;
@@ -1313,13 +1342,12 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
     if (source == INVALID_HANDLE_VALUE)
         throw last_error(GetLastError());
 
-    Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2));
+    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;
         win_handle dirh;
 
@@ -1327,13 +1355,13 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
         if (dirh == INVALID_HANDLE_VALUE)
             throw last_error(GetLastError());
 
-        bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
+        size_t bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
         bcs = (btrfs_create_snapshot*)malloc(bcslen);
         bcs->subvol = source;
         bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
         memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
 
-        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
+        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, (ULONG)bcslen, nullptr, 0);
         if (!NT_SUCCESS(Status)) {
             free(bcs);
             throw ntstatus_error(Status);
@@ -1344,19 +1372,19 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
         return;
     }
 
-    if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
-        throw last_error(GetLastError());
+    Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
+    if (!NT_SUCCESS(Status))
+        throw ntstatus_error(Status);
 
     if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
         win_handle dirh;
-        ULONG bmnsize;
         btrfs_mknod* bmn;
 
         dirh = CreateFileW(destdir.c_str(), FILE_ADD_FILE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
         if (dirh == INVALID_HANDLE_VALUE)
             throw last_error(GetLastError());
 
-        bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
+        size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
         bmn = (btrfs_mknod*)malloc(bmnsize);
 
         bmn->inode = 0;
@@ -1365,7 +1393,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
         bmn->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
         memcpy(bmn->name, destname.c_str(), bmn->namelen);
 
-        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
+        Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
         if (!NT_SUCCESS(Status)) {
             free(bmn);
             throw ntstatus_error(Status);
@@ -1428,11 +1456,8 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
 
             // CreateDirectoryExW also copies streams, no need to do it here
         } else {
-            WIN32_FIND_STREAM_DATA fsd;
-
             if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
                 reparse_header rh;
-                ULONG rplen;
                 uint8_t* rp;
 
                 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
@@ -1440,14 +1465,14 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                         throw last_error(GetLastError());
                 }
 
-                rplen = sizeof(reparse_header) + rh.ReparseDataLength;
+                size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
                 rp = (uint8_t*)malloc(rplen);
 
                 try {
-                    if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
+                    if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (DWORD)rplen, &bytesret, nullptr))
                         throw last_error(GetLastError());
 
-                    if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
+                    if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (DWORD)rplen, nullptr, 0, &bytesret, nullptr))
                         throw last_error(GetLastError());
                 } catch (...) {
                     free(rp);
@@ -1464,8 +1489,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                 uint64_t offset, alloc_size;
                 ULONG maxdup;
 
-                if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
-                    throw last_error(GetLastError());
+                Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
                 if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
                     throw last_error(GetLastError());
@@ -1482,8 +1508,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                     throw last_error(GetLastError());
 
                 feofi.EndOfFile = fsi.EndOfFile;
-                if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
-                    throw last_error(GetLastError());
+                Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
+                if (!NT_SUCCESS(Status))
+                    throw ntstatus_error(Status);
 
                 ded.FileHandle = source;
                 maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
@@ -1501,20 +1528,44 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                 }
             }
 
-            fff_handle h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0);
-            if (h != INVALID_HANDLE_VALUE) {
-                do {
-                    wstring sn;
+            ULONG streambufsize = 0;
+            vector<char> streambuf;
 
-                    sn = fsd.cStreamName;
+            do {
+                streambufsize += 0x1000;
+                streambuf.resize(streambufsize);
+
+#ifndef __REACTOS__
+                memset(streambuf.data(), 0, streambufsize);
+
+                Status = NtQueryInformationFile(source, &iosb, streambuf.data(), streambufsize, FileStreamInformation);
+#else
+                memset(&streambuf[0], 0, streambufsize);
+
+                Status = NtQueryInformationFile(source, &iosb, &streambuf[0], streambufsize, FileStreamInformation);
+#endif
+            } while (Status == STATUS_BUFFER_OVERFLOW);
+
+            if (!NT_SUCCESS(Status))
+                throw ntstatus_error(Status);
+
+#ifndef __REACTOS__
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
+#else
+            auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(&streambuf[0]);
+#endif
+
+            while (true) {
+                if (fsi->StreamNameLength > 0) {
+                    wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
 
                     if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
                         win_handle stream;
                         uint8_t* data = nullptr;
+                        auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
 
-                        if (fsd.StreamSize.QuadPart > 0) {
+                        if (stream_size > 0) {
                             wstring fn2;
-                            uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
 
                             fn2 = srcfn;
                             fn2 += sn;
@@ -1542,7 +1593,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                         }
 
                         if (data) {
-                            if (!WriteFile(stream, data, (uint32_t)fsd.StreamSize.QuadPart, &bytesret, nullptr)) {
+                            if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
                                 free(data);
                                 throw last_error(GetLastError());
                             }
@@ -1550,7 +1601,13 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
                             free(data);
                         }
                     }
-                } while (FindNextStreamW(h, &fsd));
+
+                }
+
+                if (fsi->NextEntryOffset == 0)
+                    break;
+
+                fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
             }
         }
 
@@ -1583,7 +1640,7 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
             xa2 = xa;
             while (xa2->valuelen > 0) {
                 Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
-                                        offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
+                                         (ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
                 if (!NT_SUCCESS(Status)) {
                     free(xa);
                     throw ntstatus_error(Status);
@@ -1598,7 +1655,9 @@ static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const ws
         FILE_DISPOSITION_INFO fdi;
 
         fdi.DeleteFile = true;
-        SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
+        Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
+        if (!NT_SUCCESS(Status))
+            throw ntstatus_error(Status);
 
         throw;
     }