ReactOS 0.4.15-dev-8235-gcd88a97
contextmenu.cpp File Reference
#include "shellext.h"
#include <windows.h>
#include <strsafe.h>
#include <stddef.h>
#include <winternl.h>
#include <wincodec.h>
#include <sstream>
#include <iostream>
#include <shlwapi.h>
#include "contextmenu.h"
#include "resource.h"
#include "../btrfsioctl.h"
Include dependency graph for contextmenu.cpp:

Go to the source code of this file.

Classes

struct  reparse_header
 

Macros

#define NO_SHLWAPI_STRFCNS
 
#define NEW_SUBVOL_VERBA   "newsubvol"
 
#define NEW_SUBVOL_VERBW   L"newsubvol"
 
#define SNAPSHOT_VERBA   "snapshot"
 
#define SNAPSHOT_VERBW   L"snapshot"
 
#define REFLINK_VERBA   "reflink"
 
#define REFLINK_VERBW   L"reflink"
 
#define RECV_VERBA   "recvsubvol"
 
#define RECV_VERBW   L"recvsubvol"
 
#define SEND_VERBA   "sendsubvol"
 
#define SEND_VERBW   L"sendsubvol"
 

Functions

static void path_remove_file (wstring &path)
 
static bool get_volume_path_parent (const WCHAR *fn, WCHAR *volpath, ULONG volpathlen)
 
static bool show_reflink_paste (const wstring &path)
 
static void InitBitmapInfo (BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
 
static HRESULT Create32BitHBITMAP (HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP *phBmp)
 
static void path_strip_path (wstring &path)
 
static void create_snapshot (HWND hwnd, const wstring &fn)
 
static uint64_t __inline sector_align (uint64_t n, uint64_t a)
 
static void reflink_copy2 (const wstring &srcfn, const wstring &destdir, const wstring &destname)
 
void CALLBACK ReflinkCopyW (HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
 

Macro Definition Documentation

◆ NEW_SUBVOL_VERBA

#define NEW_SUBVOL_VERBA   "newsubvol"

Definition at line 49 of file contextmenu.cpp.

◆ NEW_SUBVOL_VERBW

#define NEW_SUBVOL_VERBW   L"newsubvol"

Definition at line 50 of file contextmenu.cpp.

◆ NO_SHLWAPI_STRFCNS

#define NO_SHLWAPI_STRFCNS

Definition at line 38 of file contextmenu.cpp.

◆ RECV_VERBA

#define RECV_VERBA   "recvsubvol"

Definition at line 55 of file contextmenu.cpp.

◆ RECV_VERBW

#define RECV_VERBW   L"recvsubvol"

Definition at line 56 of file contextmenu.cpp.

◆ REFLINK_VERBA

#define REFLINK_VERBA   "reflink"

Definition at line 53 of file contextmenu.cpp.

◆ REFLINK_VERBW

#define REFLINK_VERBW   L"reflink"

Definition at line 54 of file contextmenu.cpp.

◆ SEND_VERBA

#define SEND_VERBA   "sendsubvol"

Definition at line 57 of file contextmenu.cpp.

◆ SEND_VERBW

#define SEND_VERBW   L"sendsubvol"

Definition at line 58 of file contextmenu.cpp.

◆ SNAPSHOT_VERBA

#define SNAPSHOT_VERBA   "snapshot"

Definition at line 51 of file contextmenu.cpp.

◆ SNAPSHOT_VERBW

#define SNAPSHOT_VERBW   L"snapshot"

Definition at line 52 of file contextmenu.cpp.

Function Documentation

◆ Create32BitHBITMAP()

static HRESULT Create32BitHBITMAP ( HDC  hdc,
const SIZE psize,
void **  ppvBits,
HBITMAP phBmp 
)
static

Definition at line 275 of file contextmenu.cpp.

275 {
276 BITMAPINFO bmi;
277 HDC hdcUsed;
278
279 *phBmp = nullptr;
280
281 InitBitmapInfo(&bmi, sizeof(bmi), psize->cx, psize->cy, 32);
282
283 hdcUsed = hdc ? hdc : GetDC(nullptr);
284
285 if (hdcUsed) {
286 *phBmp = CreateDIBSection(hdcUsed, &bmi, DIB_RGB_COLORS, ppvBits, nullptr, 0);
287 if (hdc != hdcUsed)
288 ReleaseDC(nullptr, hdcUsed);
289 }
290
291 return !*phBmp ? E_OUTOFMEMORY : S_OK;
292}
static void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define S_OK
Definition: intsafe.h:52
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:92
_Must_inspect_result_ _Out_ LPSIZE psize
Definition: ntgdi.h:1569
LONG cx
Definition: windef.h:334
LONG cy
Definition: windef.h:335
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
#define DIB_RGB_COLORS
Definition: wingdi.h:367
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
HDC WINAPI GetDC(_In_opt_ HWND)

Referenced by BtrfsContextMenu::get_uac_icon().

◆ create_snapshot()

static void create_snapshot ( HWND  hwnd,
const wstring &  fn 
)
static

Definition at line 451 of file contextmenu.cpp.

451 {
456
458
459 if (h != INVALID_HANDLE_VALUE) {
460 Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
461
462 if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) {
463 wstring subvolname, parpath, searchpath, temp1, name, nameorig;
464 win_handle h2;
467
468 parpath = fn;
469 path_remove_file(parpath);
470
471 subvolname = fn;
472 path_strip_path(subvolname);
473
475
476 if (h2 == INVALID_HANDLE_VALUE)
477 throw last_error(GetLastError());
478
480 throw last_error(GetLastError());
481
483
484 wstring_sprintf(name, temp1, subvolname.c_str(), time.wYear, time.wMonth, time.wDay);
485 nameorig = name;
486
487 searchpath = parpath + L"\\" + name;
488
489 fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
490
491 if (fff != INVALID_HANDLE_VALUE) {
492 ULONG num = 2;
493
494 do {
495#ifndef __REACTOS__
496 name = nameorig + L" (" + to_wstring(num) + L")";
497#else
498 {
499 WCHAR buffer[32];
500
501 swprintf(buffer, L"%d", num);
502 name = nameorig + L" (" + buffer + L")";
503 }
504#endif
505 searchpath = parpath + L"\\" + name;
506
507 fff = FindFirstFileW(searchpath.c_str(), &wfd);
508 num++;
509 } while (fff != INVALID_HANDLE_VALUE);
510 }
511
512 size_t namelen = name.length() * sizeof(WCHAR);
513
514 auto bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
515 bcs->readonly = false;
516 bcs->posix = false;
517 bcs->subvol = h;
518 bcs->namelen = (uint16_t)namelen;
519 memcpy(bcs->name, name.c_str(), namelen);
520
521 Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
522 (ULONG)(sizeof(btrfs_create_snapshot) - 1 + namelen), nullptr, 0);
523
524 if (!NT_SUCCESS(Status))
525 throw ntstatus_error(Status);
526 }
527 } else
528 throw last_error(GetLastError());
529}
LONG NTSTATUS
Definition: precomp.h:26
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:9
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:7
static void path_strip_path(wstring &path)
static void path_remove_file(wstring &path)
#define malloc
Definition: debug_ros.c:4
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
void wstring_sprintf(wstring &s, wstring fmt,...)
Definition: main.cpp:225
#define IDS_SNAPSHOT_FILENAME
Definition: resource.h:14
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
#define swprintf
Definition: precomp.h:40
Status
Definition: gdiplustypes.h:25
GLuint buffer
Definition: glext.h:5915
GLint namelen
Definition: glext.h:7232
GLuint GLuint num
Definition: glext.h:9618
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: muireg.c:10
#define uint16_t
Definition: nsiface.idl:60
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define L(x)
Definition: ntvdm.h:50
Definition: name.c:39
uint32_t ULONG
Definition: typedefs.h:59
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by BtrfsContextMenu::InvokeCommand().

◆ get_volume_path_parent()

static bool get_volume_path_parent ( const WCHAR fn,
WCHAR volpath,
ULONG  volpathlen 
)
static

Definition at line 185 of file contextmenu.cpp.

185 {
186 WCHAR *f, *p;
187 bool b;
188
190
191 if (f == fn)
192 return GetVolumePathNameW(fn, volpath, volpathlen);
193
194 p = (WCHAR*)malloc((f - fn + 1) * sizeof(WCHAR));
195 memcpy(p, fn, (f - fn) * sizeof(WCHAR));
196 p[f - fn] = 0;
197
198 b = GetVolumePathNameW(p, volpath, volpathlen);
199
200 free(p);
201
202 return b;
203}
#define free
Definition: debug_ros.c:5
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
#define f
Definition: ke_i.h:83
#define b
Definition: ke_i.h:79

Referenced by BtrfsContextMenu::reflink_copy(), ReflinkCopyW(), and show_reflink_paste().

◆ InitBitmapInfo()

static void InitBitmapInfo ( BITMAPINFO pbmi,
ULONG  cbInfo,
LONG  cx,
LONG  cy,
WORD  bpp 
)
static

Definition at line 264 of file contextmenu.cpp.

264 {
265 ZeroMemory(pbmi, cbInfo);
269
273}
DWORD bpp
Definition: surface.c:185
#define BI_RGB
Definition: precomp.h:56
_In_ HBITMAP _In_ UINT _In_ UINT _Inout_ LPBITMAPINFO pbmi
Definition: ntgdi.h:2780
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
USHORT biBitCount
Definition: precomp.h:46
ULONG biCompression
Definition: precomp.h:47
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
#define ZeroMemory
Definition: winbase.h:1712

Referenced by Create32BitHBITMAP().

◆ path_remove_file()

static void path_remove_file ( wstring &  path)
static

Definition at line 426 of file contextmenu.cpp.

426 {
427 size_t bs = path.rfind(L"\\");
428
429 if (bs == string::npos)
430 return;
431
432 if (bs == path.find(L"\\")) { // only one backslash
433 path = path.substr(0, bs + 1);
434 return;
435 }
436
437 path = path.substr(0, bs);
438}
static struct msdos_boot_sector bs
Definition: mkdosfs.c:539

Referenced by create_snapshot(), and BtrfsContextMenu::Initialize().

◆ path_strip_path()

static void path_strip_path ( wstring &  path)
static

Definition at line 440 of file contextmenu.cpp.

440 {
441 size_t bs = path.rfind(L"\\");
442
443 if (bs == string::npos) {
444 path = L"";
445 return;
446 }
447
448 path = path.substr(bs + 1);
449}

Referenced by create_snapshot().

◆ reflink_copy2()

static void reflink_copy2 ( const wstring &  srcfn,
const wstring &  destdir,
const wstring &  destname 
)
static

Definition at line 1320 of file contextmenu.cpp.

1320 {
1322 FILE_BASIC_INFO fbi;
1323 FILETIME atime, mtime;
1324 btrfs_inode_info bii;
1326 ULONG bytesret;
1329 btrfs_set_xattr bsxa;
1330
1333 throw last_error(GetLastError());
1334
1335 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info));
1336 if (!NT_SUCCESS(Status))
1337 throw ntstatus_error(Status);
1338
1339 // if subvol, do snapshot instead
1340 if (bii.inode == SUBVOL_ROOT_INODE) {
1342 win_handle dirh;
1343
1345 if (dirh == INVALID_HANDLE_VALUE)
1346 throw last_error(GetLastError());
1347
1348 size_t bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
1349 bcs = (btrfs_create_snapshot*)malloc(bcslen);
1350 bcs->subvol = source;
1351 bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
1352 memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
1353
1354 Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, (ULONG)bcslen, nullptr, 0);
1355 if (!NT_SUCCESS(Status)) {
1356 free(bcs);
1357 throw ntstatus_error(Status);
1358 }
1359
1360 free(bcs);
1361
1362 return;
1363 }
1364
1365 Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
1366 if (!NT_SUCCESS(Status))
1367 throw ntstatus_error(Status);
1368
1369 if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
1370 win_handle dirh;
1371 btrfs_mknod* bmn;
1372
1374 if (dirh == INVALID_HANDLE_VALUE)
1375 throw last_error(GetLastError());
1376
1377 size_t bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
1378 bmn = (btrfs_mknod*)malloc(bmnsize);
1379
1380 bmn->inode = 0;
1381 bmn->type = bii.type;
1382 bmn->st_rdev = bii.st_rdev;
1383 bmn->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
1384 memcpy(bmn->name, destname.c_str(), bmn->namelen);
1385
1386 Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, (ULONG)bmnsize, nullptr, 0);
1387 if (!NT_SUCCESS(Status)) {
1388 free(bmn);
1389 throw ntstatus_error(Status);
1390 }
1391
1392 free(bmn);
1393
1394 dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
1395 } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1396 if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), nullptr))
1398 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
1399 else
1401 } else
1402 dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source);
1403
1405 throw last_error(GetLastError());
1406
1407 memset(&bsii, 0, sizeof(btrfs_set_inode_info));
1408
1409 bsii.flags_changed = true;
1410 bsii.flags = bii.flags;
1411
1412 if (bii.flags & BTRFS_INODE_COMPRESS) {
1413 bsii.compression_type_changed = true;
1415 }
1416
1417 try {
1418 Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0);
1419 if (!NT_SUCCESS(Status))
1420 throw ntstatus_error(Status);
1421
1422 if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1423 if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1424 WIN32_FIND_DATAW fff;
1425 wstring qs;
1426
1427 qs = srcfn;
1428 qs += L"\\*";
1429
1430 fff_handle h = FindFirstFileW(qs.c_str(), &fff);
1431 if (h != INVALID_HANDLE_VALUE) {
1432 do {
1433 wstring fn2;
1434
1435 if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
1436 continue;
1437
1438 fn2 = srcfn;
1439 fn2 += L"\\";
1440 fn2 += fff.cFileName;
1441
1442 reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName);
1443 } while (FindNextFileW(h, &fff));
1444 }
1445 }
1446
1447 // CreateDirectoryExW also copies streams, no need to do it here
1448 } else {
1449 if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1450 reparse_header rh;
1451 uint8_t* rp;
1452
1453 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
1455 throw last_error(GetLastError());
1456 }
1457
1458 size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
1459 rp = (uint8_t*)malloc(rplen);
1460
1461 try {
1462 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (DWORD)rplen, &bytesret, nullptr))
1463 throw last_error(GetLastError());
1464
1465 if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (DWORD)rplen, nullptr, 0, &bytesret, nullptr))
1466 throw last_error(GetLastError());
1467 } catch (...) {
1468 free(rp);
1469 throw;
1470 }
1471
1472 free(rp);
1473 } else {
1474 FILE_STANDARD_INFO fsi;
1475 FILE_END_OF_FILE_INFO feofi;
1479 uint64_t offset, alloc_size;
1480 ULONG maxdup;
1481
1482 Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
1483 if (!NT_SUCCESS(Status))
1484 throw ntstatus_error(Status);
1485
1486 if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
1487 throw last_error(GetLastError());
1488
1489 if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
1490 if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr))
1491 throw last_error(GetLastError());
1492 }
1493
1495 fsiib.Reserved = 0;
1496 fsiib.Flags = fgiib.Flags;
1497 if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr))
1498 throw last_error(GetLastError());
1499
1500 feofi.EndOfFile = fsi.EndOfFile;
1501 Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
1502 if (!NT_SUCCESS(Status))
1503 throw ntstatus_error(Status);
1504
1505 ded.FileHandle = source;
1506 maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
1507
1508 alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
1509
1510 offset = 0;
1511 while (offset < alloc_size) {
1513 ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset);
1514 if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr))
1515 throw last_error(GetLastError());
1516
1517 offset += ded.ByteCount.QuadPart;
1518 }
1519 }
1520
1521 ULONG streambufsize = 0;
1523
1524 do {
1525 streambufsize += 0x1000;
1526 streambuf.resize(streambufsize);
1527
1528 memset(streambuf.data(), 0, streambufsize);
1529
1531 } while (Status == STATUS_BUFFER_OVERFLOW);
1532
1533 if (!NT_SUCCESS(Status))
1534 throw ntstatus_error(Status);
1535
1536 auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
1537
1538 while (true) {
1539 if (fsi->StreamNameLength > 0) {
1540 wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
1541
1542 if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
1544 uint8_t* data = nullptr;
1545 auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
1546
1547 if (stream_size > 0) {
1548 wstring fn2;
1549
1550 fn2 = srcfn;
1551 fn2 += sn;
1552
1553 stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
1554
1556 throw last_error(GetLastError());
1557
1558 // We can get away with this because our streams are guaranteed to be below 64 KB -
1559 // don't do this on NTFS!
1561
1562 if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
1563 free(data);
1564 throw last_error(GetLastError());
1565 }
1566 }
1567
1568 stream = CreateFileW((destdir + destname + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
1569
1571 if (data) free(data);
1572 throw last_error(GetLastError());
1573 }
1574
1575 if (data) {
1576 if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
1577 free(data);
1578 throw last_error(GetLastError());
1579 }
1580
1581 free(data);
1582 }
1583 }
1584
1585 }
1586
1587 if (fsi->NextEntryOffset == 0)
1588 break;
1589
1590 fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
1591 }
1592 }
1593
1594 atime.dwLowDateTime = fbi.LastAccessTime.LowPart;
1595 atime.dwHighDateTime = fbi.LastAccessTime.HighPart;
1596 mtime.dwLowDateTime = fbi.LastWriteTime.LowPart;
1597 mtime.dwHighDateTime = fbi.LastWriteTime.HighPart;
1598 SetFileTime(dest, nullptr, &atime, &mtime);
1599
1600 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr));
1601
1602 if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
1603 ULONG xalen = 0;
1604 btrfs_set_xattr *xa = nullptr, *xa2;
1605
1606 do {
1607 xalen += 1024;
1608
1609 if (xa) free(xa);
1610 xa = (btrfs_set_xattr*)malloc(xalen);
1611
1612 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
1613 } while (Status == STATUS_BUFFER_OVERFLOW);
1614
1615 if (!NT_SUCCESS(Status)) {
1616 free(xa);
1617 throw ntstatus_error(Status);
1618 }
1619
1620 xa2 = xa;
1621 while (xa2->valuelen > 0) {
1622 Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
1623 (ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
1624 if (!NT_SUCCESS(Status)) {
1625 free(xa);
1626 throw ntstatus_error(Status);
1627 }
1628 xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen];
1629 }
1630
1631 free(xa);
1632 } else if (!NT_SUCCESS(Status))
1633 throw ntstatus_error(Status);
1634 } catch (...) {
1635 FILE_DISPOSITION_INFO fdi;
1636
1637 fdi.DeleteFile = true;
1638 Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
1639 if (!NT_SUCCESS(Status))
1640 throw ntstatus_error(Status);
1641
1642 throw;
1643 }
1644}
#define FSCTL_BTRFS_SET_INODE_INFO
Definition: btrfsioctl.h:11
#define FSCTL_BTRFS_SET_XATTR
Definition: btrfsioctl.h:33
#define FSCTL_BTRFS_GET_XATTRS
Definition: btrfsioctl.h:32
#define FSCTL_BTRFS_MKNOD
Definition: btrfsioctl.h:30
#define FSCTL_BTRFS_GET_INODE_INFO
Definition: btrfsioctl.h:10
static void reflink_copy2(const wstring &srcfn, const wstring &destdir, const wstring &destname)
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define ERROR_MORE_DATA
Definition: dderror.h:13
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
UINT64 uint64_t
Definition: types.h:77
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define GENERIC_READ
Definition: compat.h:135
BOOL WINAPI CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory, IN LPCWSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:193
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:948
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
unsigned long DWORD
Definition: ntddk_ex.h:95
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileStreamInformation
Definition: from_kernel.h:83
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
if(dx< 0)
Definition: linetemp.h:194
#define CREATE_NEW
Definition: disk.h:69
static char * dest
Definition: rtl.c:135
BYTE uint8_t
Definition: msvideo1.c:66
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define FileStandardInformation
Definition: propsheet.cpp:61
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:736
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:737
#define FSCTL_SET_SPARSE
Definition: winioctl.h:739
#define offsetof(TYPE, MEMBER)
int const char int stream_size
Definition: zlib.h:814
#define memset(x, y, z)
Definition: compat.h:39
#define FSCTL_SET_INTEGRITY_INFORMATION
Definition: shellext.h:222
#define FSCTL_GET_INTEGRITY_INFORMATION
Definition: shellext.h:221
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE
Definition: shellext.h:205
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
LARGE_INTEGER ByteCount
Definition: shellext.h:202
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
uint64_t st_rdev
Definition: btrfsioctl.h:77
uint64_t flags
Definition: btrfsioctl.h:78
uint64_t inode
Definition: btrfsioctl.h:71
uint8_t compression_type
Definition: btrfsioctl.h:83
uint64_t inode
Definition: btrfsioctl.h:237
WCHAR name[1]
Definition: btrfsioctl.h:241
uint16_t namelen
Definition: btrfsioctl.h:240
uint64_t st_rdev
Definition: btrfsioctl.h:239
uint8_t type
Definition: btrfsioctl.h:238
uint8_t compression_type
Definition: btrfsioctl.h:98
BOOL compression_type_changed
Definition: btrfsioctl.h:99
USHORT ReparseDataLength
Definition: contextmenu.cpp:62
Definition: parse.h:23
LONGLONG QuadPart
Definition: typedefs.h:114

Referenced by reflink_copy2(), and ReflinkCopyW().

◆ ReflinkCopyW()

void CALLBACK ReflinkCopyW ( HWND  hwnd,
HINSTANCE  hinst,
LPWSTR  lpszCmdLine,
int  nCmdShow 
)

Definition at line 1646 of file contextmenu.cpp.

1646 {
1648
1649 command_line_to_args(lpszCmdLine, args);
1650
1651 if (args.size() >= 2) {
1652 bool dest_is_dir = false;
1653 wstring dest = args[args.size() - 1], destdir, destname;
1654 WCHAR volpath2[MAX_PATH];
1655
1656 {
1658 nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
1659
1660 if (destdirh != INVALID_HANDLE_VALUE) {
1662
1664 dest_is_dir = true;
1665
1666 destdir = dest;
1667 if (destdir.substr(destdir.length() - 1, 1) != L"\\")
1668 destdir += L"\\";
1669 }
1670 }
1671 }
1672
1673 if (!dest_is_dir) {
1674 size_t found = dest.rfind(L"\\");
1675
1676 if (found == wstring::npos) {
1677 destdir = L"";
1678 destname = dest;
1679 } else {
1680 destdir = dest.substr(0, found);
1681 destname = dest.substr(found + 1);
1682 }
1683 }
1684
1685 if (!GetVolumePathNameW(dest.c_str(), volpath2, sizeof(volpath2) / sizeof(WCHAR)))
1686 return;
1687
1688 for (unsigned int i = 0; i < args.size() - 1; i++) {
1689 WIN32_FIND_DATAW ffd;
1690
1691 fff_handle h = FindFirstFileW(args[i].c_str(), &ffd);
1692 if (h != INVALID_HANDLE_VALUE) {
1693 WCHAR volpath1[MAX_PATH];
1694 wstring path = args[i];
1695 size_t found = path.rfind(L"\\");
1696
1697 if (found == wstring::npos)
1698 path = L"";
1699 else
1700 path = path.substr(0, found);
1701
1702 path += L"\\";
1703
1704 if (get_volume_path_parent(path.c_str(), volpath1, sizeof(volpath1) / sizeof(WCHAR))) {
1705 if (!wcscmp(volpath1, volpath2)) {
1706 do {
1707 try {
1708 reflink_copy2(path + ffd.cFileName, destdir, dest_is_dir ? ffd.cFileName : destname);
1709 } catch (const exception& e) {
1710 cerr << "Error: " << e.what() << endl;
1711 }
1712 } while (FindNextFileW(h, &ffd));
1713 }
1714 }
1715 }
1716 }
1717 }
1718}
basic_ostream< _CharT, _Traits > &_STLP_CALL endl(basic_ostream< _CharT, _Traits > &__os)
Definition: _ostream.h:357
static bool get_volume_path_parent(const WCHAR *fn, WCHAR *volpath, ULONG volpathlen)
void command_line_to_args(LPWSTR cmdline, vector< wstring > &args)
Definition: main.cpp:645
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:458
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define cerr
Definition: iostream.cpp:39
#define e
Definition: ke_i.h:82
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
Definition: match.c:390
int length
Definition: match.c:394

◆ sector_align()

◆ show_reflink_paste()

static bool show_reflink_paste ( const wstring &  path)
static

Definition at line 205 of file contextmenu.cpp.

205 {
206 HDROP hdrop;
207 HANDLE lh;
208 ULONG num_files;
209 WCHAR fn[MAX_PATH], volpath1[255], volpath2[255];
210
212 return false;
213
214 if (!GetVolumePathNameW(path.c_str(), volpath1, sizeof(volpath1) / sizeof(WCHAR)))
215 return false;
216
217 if (!OpenClipboard(nullptr))
218 return false;
219
220 hdrop = (HDROP)GetClipboardData(CF_HDROP);
221
222 if (!hdrop) {
224 return false;
225 }
226
227 lh = GlobalLock(hdrop);
228
229 if (!lh) {
231 return false;
232 }
233
234 num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0);
235
236 if (num_files == 0) {
237 GlobalUnlock(lh);
239 return false;
240 }
241
242 if (!DragQueryFileW(hdrop, 0, fn, sizeof(fn) / sizeof(WCHAR))) {
243 GlobalUnlock(lh);
245 return false;
246 }
247
248 if (!get_volume_path_parent(fn, volpath2, sizeof(volpath2) / sizeof(WCHAR))) {
249 GlobalUnlock(lh);
251 return false;
252 }
253
254 GlobalUnlock(lh);
255
257
258 return !wcscmp(volpath1, volpath2);
259}
#define CF_HDROP
Definition: constants.h:410
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
HANDLE WINAPI GetClipboardData(_In_ UINT)
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)

Referenced by BtrfsContextMenu::QueryContextMenu().