ReactOS  0.4.13-dev-259-g5ca9c9c
contextmenu.cpp
Go to the documentation of this file.
1 /* Copyright (c) Mark Harmstone 2016-17
2  *
3  * This file is part of WinBtrfs.
4  *
5  * WinBtrfs is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public Licence as published by
7  * the Free Software Foundation, either version 3 of the Licence, or
8  * (at your option) any later version.
9  *
10  * WinBtrfs is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public Licence for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public Licence
16  * along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
17 
18 #include "shellext.h"
19 #ifndef __REACTOS__
20 #include <windows.h>
21 #include <strsafe.h>
22 #include <stddef.h>
23 #include <winternl.h>
24 #else
25 #define WIN32_NO_STATUS
26 #include <windef.h>
27 #include <winbase.h>
28 #include <strsafe.h>
29 #include <shellapi.h>
30 #include <winioctl.h>
31 #include <ndk/iofuncs.h>
32 #undef DeleteFile
33 #endif
34 #include <wincodec.h>
35 #include <sstream>
36 #include <iostream>
37 
38 #define NO_SHLWAPI_STRFCNS
39 #include <shlwapi.h>
40 
41 #include "contextmenu.h"
42 #include "resource.h"
43 #ifndef __REACTOS__
44 #include "../btrfsioctl.h"
45 #else
46 #include "btrfsioctl.h"
47 #endif
48 
49 #define NEW_SUBVOL_VERBA "newsubvol"
50 #define NEW_SUBVOL_VERBW L"newsubvol"
51 #define SNAPSHOT_VERBA "snapshot"
52 #define SNAPSHOT_VERBW L"snapshot"
53 #define REFLINK_VERBA "reflink"
54 #define REFLINK_VERBW L"reflink"
55 #define RECV_VERBA "recvsubvol"
56 #define RECV_VERBW L"recvsubvol"
57 #define SEND_VERBA "sendsubvol"
58 #define SEND_VERBW L"sendsubvol"
59 
60 typedef struct {
65 
66 static void path_remove_file(wstring& path);
67 
68 // FIXME - don't assume subvol's top inode is 0x100
69 
71  if (riid == IID_IUnknown || riid == IID_IContextMenu) {
72  *ppObj = static_cast<IContextMenu*>(this);
73  AddRef();
74  return S_OK;
75  } else if (riid == IID_IShellExtInit) {
76  *ppObj = static_cast<IShellExtInit*>(this);
77  AddRef();
78  return S_OK;
79  }
80 
81  *ppObj = nullptr;
82  return E_NOINTERFACE;
83 }
84 
87  btrfs_get_file_ids bgfi;
89 
90  if (!pidlFolder) {
91  FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
92  UINT num_files, i;
93  WCHAR fn[MAX_PATH];
94  HDROP hdrop;
95 
96  if (!pdtobj)
97  return E_FAIL;
98 
99  stgm.tymed = TYMED_HGLOBAL;
100 
101  if (FAILED(pdtobj->GetData(&format, &stgm)))
102  return E_INVALIDARG;
103 
104  stgm_set = true;
105 
106  hdrop = (HDROP)GlobalLock(stgm.hGlobal);
107 
108  if (!hdrop) {
110  stgm_set = false;
111  return E_INVALIDARG;
112  }
113 
114  num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0);
115 
116  for (i = 0; i < num_files; i++) {
117  if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) {
119 
120  if (h != INVALID_HANDLE_VALUE) {
121  Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
122 
123  if (NT_SUCCESS(Status) && bgfi.inode == 0x100 && !bgfi.top) {
124  wstring parpath;
125 
126  {
127  win_handle h2;
128 
129  parpath = fn;
130  path_remove_file(parpath);
131 
134 
135  if (h2 != INVALID_HANDLE_VALUE)
136  allow_snapshot = true;
137  }
138 
139  ignore = false;
140  bg = false;
141 
142  GlobalUnlock(hdrop);
143  return S_OK;
144  }
145  }
146  }
147  }
148 
149  GlobalUnlock(hdrop);
150 
151  return S_OK;
152  }
153 
154  {
155  WCHAR pathbuf[MAX_PATH];
156 
157  if (!SHGetPathFromIDListW(pidlFolder, pathbuf))
158  return E_FAIL;
159 
160  path = pathbuf;
161  }
162 
163  {
164  // check we have permissions to create new subdirectory
165 
167 
168  if (h == INVALID_HANDLE_VALUE)
169  return E_FAIL;
170 
171  // check is Btrfs volume
172 
173  Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
174 
175  if (!NT_SUCCESS(Status))
176  return E_FAIL;
177  }
178 
179  ignore = false;
180  bg = true;
181 
182  return S_OK;
183 }
184 
185 static bool get_volume_path_parent(const WCHAR* fn, WCHAR* volpath, ULONG volpathlen) {
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 }
204 
205 static bool show_reflink_paste(const wstring& path) {
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) {
223  CloseClipboard();
224  return false;
225  }
226 
227  lh = GlobalLock(hdrop);
228 
229  if (!lh) {
230  CloseClipboard();
231  return false;
232  }
233 
234  num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0);
235 
236  if (num_files == 0) {
237  GlobalUnlock(lh);
238  CloseClipboard();
239  return false;
240  }
241 
242  if (!DragQueryFileW(hdrop, 0, fn, sizeof(fn) / sizeof(WCHAR))) {
243  GlobalUnlock(lh);
244  CloseClipboard();
245  return false;
246  }
247 
248  if (!get_volume_path_parent(fn, volpath2, sizeof(volpath2) / sizeof(WCHAR))) {
249  GlobalUnlock(lh);
250  CloseClipboard();
251  return false;
252  }
253 
254  GlobalUnlock(lh);
255 
256  CloseClipboard();
257 
258  return !wcscmp(volpath1, volpath2);
259 }
260 
261 // The code for putting an icon against a menu item comes from:
262 // http://web.archive.org/web/20070208005514/http://shellrevealed.com/blogs/shellblog/archive/2007/02/06/Vista-Style-Menus_2C00_-Part-1-_2D00_-Adding-icons-to-standard-menus.aspx
263 
264 static void InitBitmapInfo(BITMAPINFO* pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp) {
265  ZeroMemory(pbmi, cbInfo);
267  pbmi->bmiHeader.biPlanes = 1;
269 
273 }
274 
275 static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP* phBmp) {
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 }
293 
295  IWICImagingFactory* factory = nullptr;
297  HRESULT hr;
298 
299 #ifdef __REACTOS__
300  hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_IWICImagingFactory, (void **)&factory);
301 #else
302  hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));
303 #endif
304 
305  if (SUCCEEDED(hr)) {
306  HANDLE icon;
307 
308  // We can't use IDI_SHIELD, as that will only give us the full-size icon
309  icon = LoadImageW(GetModuleHandleW(L"user32.dll"), MAKEINTRESOURCEW(106)/* UAC shield */, IMAGE_ICON,
311 
312  hr = factory->CreateBitmapFromHICON((HICON)icon, &bitmap);
313  if (SUCCEEDED(hr)) {
314  UINT cx, cy;
315 
316  hr = bitmap->GetSize(&cx, &cy);
317  if (SUCCEEDED(hr)) {
318  SIZE sz;
319  BYTE* buf;
320 
321  sz.cx = (int)cx;
322  sz.cy = -(int)cy;
323 
324  hr = Create32BitHBITMAP(nullptr, &sz, (void**)&buf, &uacicon);
325  if (SUCCEEDED(hr)) {
326  UINT stride = cx * sizeof(DWORD);
327  UINT buflen = cy * stride;
328  bitmap->CopyPixels(nullptr, stride, buflen, buf);
329  }
330  }
331 
332  bitmap->Release();
333  }
334 
335  factory->Release();
336  }
337 }
338 
340  wstring str;
341  ULONG entries = 0;
342 
343  if (ignore)
344  return E_INVALIDARG;
345 
346  if (uFlags & CMF_DEFAULTONLY)
347  return S_OK;
348 
349  if (!bg) {
350  if (allow_snapshot) {
352  return E_FAIL;
353 
354  if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str.c_str()))
355  return E_FAIL;
356 
357  entries = 1;
358  }
359 
360  if (idCmdFirst + entries <= idCmdLast) {
361  MENUITEMINFOW mii;
362 
364  return E_FAIL;
365 
366  if (!uacicon)
367  get_uac_icon();
368 
369  memset(&mii, 0, sizeof(MENUITEMINFOW));
370  mii.cbSize = sizeof(MENUITEMINFOW);
372  mii.dwTypeData = (WCHAR*)str.c_str();
373  mii.wID = idCmdFirst + entries;
374  mii.hbmpItem = uacicon;
375 
376  if (!InsertMenuItemW(hmenu, indexMenu + entries, true, &mii))
377  return E_FAIL;
378 
379  entries++;
380  }
381  } else {
382  if (load_string(module, IDS_NEW_SUBVOL, str) == 0)
383  return E_FAIL;
384 
385  if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str.c_str()))
386  return E_FAIL;
387 
388  entries = 1;
389 
390  if (idCmdFirst + 1 <= idCmdLast) {
391  MENUITEMINFOW mii;
392 
394  return E_FAIL;
395 
396  if (!uacicon)
397  get_uac_icon();
398 
399  memset(&mii, 0, sizeof(MENUITEMINFOW));
400  mii.cbSize = sizeof(MENUITEMINFOW);
402  mii.dwTypeData = (WCHAR*)str.c_str();
403  mii.wID = idCmdFirst + 1;
404  mii.hbmpItem = uacicon;
405 
406  if (!InsertMenuItemW(hmenu, indexMenu + 1, true, &mii))
407  return E_FAIL;
408 
409  entries++;
410  }
411 
412  if (idCmdFirst + 2 <= idCmdLast && show_reflink_paste(path)) {
414  return E_FAIL;
415 
416  if (!InsertMenuW(hmenu, indexMenu + 2, MF_BYPOSITION, idCmdFirst + 2, str.c_str()))
417  return E_FAIL;
418 
419  entries++;
420  }
421  }
422 
423  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, entries);
424 }
425 
426 static void path_remove_file(wstring& path) {
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 }
439 
440 static void path_strip_path(wstring& path) {
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 }
450 
451 static void create_snapshot(HWND hwnd, const wstring& fn) {
452  win_handle h;
455  btrfs_get_file_ids bgfi;
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;
466  ULONG namelen;
467  WIN32_FIND_DATAW wfd;
469 
470  parpath = fn;
471  path_remove_file(parpath);
472 
473  subvolname = fn;
474  path_strip_path(subvolname);
475 
477 
478  if (h2 == INVALID_HANDLE_VALUE)
479  throw last_error(GetLastError());
480 
482  throw last_error(GetLastError());
483 
484  GetLocalTime(&time);
485 
486  wstring_sprintf(name, temp1, subvolname.c_str(), time.wYear, time.wMonth, time.wDay);
487  nameorig = name;
488 
489  searchpath = parpath + L"\\" + name;
490 
491  fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
492 
493  if (fff != INVALID_HANDLE_VALUE) {
494  ULONG num = 2;
495 
496  do {
497 #ifndef __REACTOS__
498  name = nameorig + L" (" + to_wstring(num) + L")";
499 #else
500  {
501  WCHAR buffer[32];
502 
503  swprintf(buffer, L"%d", num);
504  name = nameorig + L" (" + buffer + L")";
505  }
506 #endif
507  searchpath = parpath + L"\\" + name;
508 
509  fff = FindFirstFileW(searchpath.c_str(), &wfd);
510  num++;
511  } while (fff != INVALID_HANDLE_VALUE);
512  }
513 
514  namelen = name.length() * sizeof(WCHAR);
515 
517  bcs->readonly = false;
518  bcs->posix = false;
519  bcs->subvol = h;
520  bcs->namelen = (uint16_t)namelen;
521  memcpy(bcs->name, name.c_str(), namelen);
522 
523  Status = NtFsControlFile(h2, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen, nullptr, 0);
524 
525  if (!NT_SUCCESS(Status))
526  throw ntstatus_error(Status);
527  }
528  } else
529  throw last_error(GetLastError());
530 }
531 
533  if (n & (a - 1))
534  n = (n + a) & ~(a - 1);
535 
536  return n;
537 }
538 
541  WCHAR* name, volpath1[255], volpath2[255];
542  wstring dirw, newpath;
543  FILE_BASIC_INFO fbi;
544  FILETIME atime, mtime;
545  btrfs_inode_info2 bii;
547  ULONG bytesret;
550  btrfs_set_xattr bsxa;
551 
552  // Thanks to 0xbadfca11, whose version of reflink for Windows provided a few pointers on what
553  // to do here - https://github.com/0xbadfca11/reflink
554 
556 
557  dirw = dir;
558 
559  if (dir[0] != 0 && dir[wcslen(dir) - 1] != '\\')
560  dirw += L"\\";
561 
562  newpath = dirw;
563  newpath += name;
564 
565  if (!get_volume_path_parent(fn, volpath1, sizeof(volpath1) / sizeof(WCHAR)))
566  throw last_error(GetLastError());
567 
568  if (!GetVolumePathNameW(dir, volpath2, sizeof(volpath2) / sizeof(WCHAR)))
569  throw last_error(GetLastError());
570 
571  if (wcscmp(volpath1, volpath2)) // different filesystems
573 
576  throw last_error(GetLastError());
577 
578  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2));
579  if (!NT_SUCCESS(Status))
580  throw ntstatus_error(Status);
581 
582  // if subvol, do snapshot instead
583  if (bii.inode == SUBVOL_ROOT_INODE) {
585  win_handle dirh;
586  wstring destname, search;
587  WIN32_FIND_DATAW wfd;
588  int num = 2;
589 
591  if (dirh == INVALID_HANDLE_VALUE)
592  throw last_error(GetLastError());
593 
594  search = dirw;
595  search += name;
596  destname = name;
597 
598  fff_handle fff = FindFirstFileW(search.c_str(), &wfd);
599 
600  if (fff != INVALID_HANDLE_VALUE) {
601  do {
603 
604  ss << name;
605  ss << L" (";
606  ss << num;
607  ss << L")";
608  destname = ss.str();
609 
610  search = dirw + destname;
611 
612  fff = FindFirstFileW(search.c_str(), &wfd);
613  num++;
614  } while (fff != INVALID_HANDLE_VALUE);
615  }
616 
617  bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + (destname.length() * sizeof(WCHAR)));
618  bcs->subvol = source;
619  bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
620  memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
621 
622  Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + bcs->namelen, nullptr, 0);
623 
624  free(bcs);
625 
626  if (!NT_SUCCESS(Status))
627  throw ntstatus_error(Status);
628 
629  return;
630  }
631 
632  if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
633  throw last_error(GetLastError());
634 
635  if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
636  win_handle dirh;
637  ULONG bmnsize;
638  btrfs_mknod* bmn;
639 
641  if (dirh == INVALID_HANDLE_VALUE)
642  throw last_error(GetLastError());
643 
644  bmnsize = offsetof(btrfs_mknod, name[0]) + (wcslen(name) * sizeof(WCHAR));
645  bmn = (btrfs_mknod*)malloc(bmnsize);
646 
647  bmn->inode = 0;
648  bmn->type = bii.type;
649  bmn->st_rdev = bii.st_rdev;
650  bmn->namelen = (uint16_t)(wcslen(name) * sizeof(WCHAR));
651  memcpy(bmn->name, name, bmn->namelen);
652 
653  Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
654  if (!NT_SUCCESS(Status)) {
655  free(bmn);
656  throw ntstatus_error(Status);
657  }
658 
659  free(bmn);
660 
661  dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
662  } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
663  if (CreateDirectoryExW(fn, newpath.c_str(), nullptr))
665  nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
666  else
668  } else
669  dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source);
670 
671  if (dest == INVALID_HANDLE_VALUE) {
672  int num = 2;
673 
674  if (GetLastError() != ERROR_FILE_EXISTS && GetLastError() != ERROR_ALREADY_EXISTS && wcscmp(fn, newpath.c_str()))
675  throw last_error(GetLastError());
676 
677  do {
678  WCHAR* ext;
680 
682 
683  ss << dirw;
684 
685  if (*ext == 0) {
686  ss << name;
687  ss << L" (";
688  ss << num;
689  ss << L")";
690  } else {
691  wstring namew = name;
692 
693  ss << namew.substr(0, ext - name);
694  ss << L" (";
695  ss << num;
696  ss << L")";
697  ss << ext;
698  }
699 
700  newpath = ss.str();
701  if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
702  if (CreateDirectoryExW(fn, newpath.c_str(), nullptr))
703  dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
704  else
706  } else
707  dest = CreateFileW(newpath.c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source);
708 
709  if (dest == INVALID_HANDLE_VALUE) {
711  throw last_error(GetLastError());
712 
713  num++;
714  } else
715  break;
716  } while (true);
717  }
718 
719  try {
720  memset(&bsii, 0, sizeof(btrfs_set_inode_info));
721 
722  bsii.flags_changed = true;
723  bsii.flags = bii.flags;
724 
725  if (bii.flags & BTRFS_INODE_COMPRESS) {
726  bsii.compression_type_changed = true;
728  }
729 
730  Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0);
731  if (!NT_SUCCESS(Status))
732  throw ntstatus_error(Status);
733 
734  if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
735  if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
736  fff_handle h;
737  WIN32_FIND_DATAW fff;
738  wstring qs;
739 
740  qs = fn;
741  qs += L"\\*";
742 
743  h = FindFirstFileW(qs.c_str(), &fff);
744  if (h != INVALID_HANDLE_VALUE) {
745  do {
746  wstring fn2;
747 
748  if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
749  continue;
750 
751  fn2 = fn;
752  fn2 += L"\\";
753  fn2 += fff.cFileName;
754 
755  reflink_copy(hwnd, fn2.c_str(), newpath.c_str());
756  } while (FindNextFileW(h, &fff));
757  }
758  }
759 
760  // CreateDirectoryExW also copies streams, no need to do it here
761  } else {
762  WIN32_FIND_STREAM_DATA fsd;
763 
764  if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
765  reparse_header rh;
766  ULONG rplen;
767  uint8_t* rp;
768 
769  if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
770  if (GetLastError() != ERROR_MORE_DATA)
771  throw last_error(GetLastError());
772  }
773 
774  rplen = sizeof(reparse_header) + rh.ReparseDataLength;
775  rp = (uint8_t*)malloc(rplen);
776 
777  if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
778  throw last_error(GetLastError());
779 
780  if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
781  throw last_error(GetLastError());
782 
783  free(rp);
784  } else {
785  FILE_STANDARD_INFO fsi;
786  FILE_END_OF_FILE_INFO feofi;
790  uint64_t offset, alloc_size;
791  ULONG maxdup;
792 
793  if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
794  throw last_error(GetLastError());
795 
796  if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
797  throw last_error(GetLastError());
798 
799  if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
800  if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr))
801  throw last_error(GetLastError());
802  }
803 
804  fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm;
805  fsiib.Reserved = 0;
806  fsiib.Flags = fgiib.Flags;
807  if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr))
808  throw last_error(GetLastError());
809 
810  feofi.EndOfFile = fsi.EndOfFile;
811  if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
812  throw last_error(GetLastError());
813 
814  ded.FileHandle = source;
815  maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
816 
817  alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
818 
819  offset = 0;
820  while (offset < alloc_size) {
822  ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset);
823  if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr))
824  throw last_error(GetLastError());
825 
826  offset += ded.ByteCount.QuadPart;
827  }
828  }
829 
830  fff_handle h = FindFirstStreamW(fn, FindStreamInfoStandard, &fsd, 0);
831  if (h != INVALID_HANDLE_VALUE) {
832  do {
833  wstring sn;
834 
835  sn = fsd.cStreamName;
836 
837  if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
839  uint8_t* data = nullptr;
840  uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
841 
842  if (fsd.StreamSize.QuadPart > 0) {
843  wstring fn2;
844 
845  fn2 = fn;
846  fn2 += sn;
847 
848  stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
849 
851  throw last_error(GetLastError());
852 
853  // We can get away with this because our streams are guaranteed to be below 64 KB -
854  // don't do this on NTFS!
856 
857  if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
858  free(data);
859  throw last_error(GetLastError());
860  }
861  }
862 
863  stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
864 
865  if (stream == INVALID_HANDLE_VALUE) {
866  if (data) free(data);
867  throw last_error(GetLastError());
868  }
869 
870  if (data) {
871  if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
872  free(data);
873  throw last_error(GetLastError());
874  }
875 
876  free(data);
877  }
878  }
879  } while (FindNextStreamW(h, &fsd));
880  }
881  }
882 
883  atime.dwLowDateTime = fbi.LastAccessTime.LowPart;
884  atime.dwHighDateTime = fbi.LastAccessTime.HighPart;
885  mtime.dwLowDateTime = fbi.LastWriteTime.LowPart;
886  mtime.dwHighDateTime = fbi.LastWriteTime.HighPart;
887  SetFileTime(dest, nullptr, &atime, &mtime);
888 
889  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr));
890 
891  if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
892  ULONG xalen = 0;
893  btrfs_set_xattr *xa = nullptr, *xa2;
894 
895  do {
896  xalen += 1024;
897 
898  if (xa) free(xa);
899  xa = (btrfs_set_xattr*)malloc(xalen);
900 
901  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
902  } while (Status == STATUS_BUFFER_OVERFLOW);
903 
904  if (!NT_SUCCESS(Status)) {
905  free(xa);
906  throw ntstatus_error(Status);
907  }
908 
909  xa2 = xa;
910  while (xa2->valuelen > 0) {
911  Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
912  offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
913  if (!NT_SUCCESS(Status)) {
914  free(xa);
915  throw ntstatus_error(Status);
916  }
917  xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen];
918  }
919 
920  free(xa);
921  } else if (!NT_SUCCESS(Status))
922  throw ntstatus_error(Status);
923  } catch (...) {
924  FILE_DISPOSITION_INFO fdi;
925 
926  fdi.DeleteFile = true;
927  if (!SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO)))
928  throw last_error(GetLastError());
929 
930  throw;
931  }
932 }
933 
936 
937  try {
938  if (ignore)
939  return E_INVALIDARG;
940 
941  if (!bg) {
942  if ((IS_INTRESOURCE(pici->lpVerb) && allow_snapshot && pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SNAPSHOT_VERBA))) {
943  UINT num_files, i;
944  WCHAR fn[MAX_PATH];
945 
946  if (!stgm_set)
947  return E_FAIL;
948 
949  num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0);
950 
951  if (num_files == 0)
952  return E_FAIL;
953 
954  for (i = 0; i < num_files; i++) {
955  if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) {
956  create_snapshot(pici->hwnd, fn);
957  }
958  }
959 
960  return S_OK;
961  } else if ((IS_INTRESOURCE(pici->lpVerb) && ((allow_snapshot && (ULONG_PTR)pici->lpVerb == 1) || (!allow_snapshot && (ULONG_PTR)pici->lpVerb == 0))) ||
962  (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SEND_VERBA))) {
963  UINT num_files, i;
965  wstring t;
966  SHELLEXECUTEINFOW sei;
967 
968  GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
969 
970  if (!stgm_set)
971  return E_FAIL;
972 
973  num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0);
974 
975  if (num_files == 0)
976  return E_FAIL;
977 
978  for (i = 0; i < num_files; i++) {
979  if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) {
980  t = L"\"";
981  t += dll;
982  t += L"\",SendSubvolGUI ";
983  t += fn;
984 
985  RtlZeroMemory(&sei, sizeof(sei));
986 
987  sei.cbSize = sizeof(sei);
988  sei.hwnd = pici->hwnd;
989  sei.lpVerb = L"runas";
990  sei.lpFile = L"rundll32.exe";
991  sei.lpParameters = t.c_str();
992  sei.nShow = SW_SHOW;
994 
995  if (!ShellExecuteExW(&sei))
996  throw last_error(GetLastError());
997 
999  CloseHandle(sei.hProcess);
1000  }
1001  }
1002 
1003  return S_OK;
1004  }
1005  } else {
1006  if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, NEW_SUBVOL_VERBA))) {
1007  win_handle h;
1009  NTSTATUS Status;
1010  ULONG bcslen;
1011  wstring name, nameorig, searchpath;
1012  btrfs_create_subvol* bcs;
1013  WIN32_FIND_DATAW wfd;
1014 
1016  throw last_error(GetLastError());
1017 
1019 
1020  if (h == INVALID_HANDLE_VALUE)
1021  throw last_error(GetLastError());
1022 
1023  searchpath = path + L"\\" + name;
1024  nameorig = name;
1025 
1026  {
1027  fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
1028 
1029  if (fff != INVALID_HANDLE_VALUE) {
1030  ULONG num = 2;
1031 
1032  do {
1033 #ifndef __REACTOS__
1034  name = nameorig + L" (" + to_wstring(num) + L")";
1035 #else
1036  {
1037  WCHAR buffer[32];
1038 
1039  swprintf(buffer, L"%d", num);
1040  name = nameorig + L" (" + buffer + L")";
1041  }
1042 #endif
1043  searchpath = path + L"\\" + name;
1044 
1045  fff = FindFirstFileW(searchpath.c_str(), &wfd);
1046  num++;
1047  } while (fff != INVALID_HANDLE_VALUE);
1048  }
1049  }
1050 
1051  bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
1052  bcs = (btrfs_create_subvol*)malloc(bcslen);
1053 
1054  bcs->readonly = false;
1055  bcs->posix = false;
1056  bcs->namelen = (uint16_t)(name.length() * sizeof(WCHAR));
1057  memcpy(bcs->name, name.c_str(), name.length() * sizeof(WCHAR));
1058 
1059  Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, nullptr, 0);
1060 
1061  free(bcs);
1062 
1063  if (!NT_SUCCESS(Status))
1064  throw ntstatus_error(Status);
1065 
1066  return S_OK;
1067  } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 1) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, RECV_VERBA))) {
1068  WCHAR dll[MAX_PATH];
1069  wstring t;
1070  SHELLEXECUTEINFOW sei;
1071 
1072  GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
1073 
1074  t = L"\"";
1075  t += dll;
1076  t += L"\",RecvSubvolGUI ";
1077  t += path;
1078 
1079  RtlZeroMemory(&sei, sizeof(sei));
1080 
1081  sei.cbSize = sizeof(sei);
1082  sei.hwnd = pici->hwnd;
1083  sei.lpVerb = L"runas";
1084  sei.lpFile = L"rundll32.exe";
1085  sei.lpParameters = t.c_str();
1086  sei.nShow = SW_SHOW;
1088 
1089  if (!ShellExecuteExW(&sei))
1090  throw last_error(GetLastError());
1091 
1093  CloseHandle(sei.hProcess);
1094 
1095  return S_OK;
1096  } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 2) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, REFLINK_VERBA))) {
1097  HDROP hdrop;
1098 
1100  return S_OK;
1101 
1102  if (!OpenClipboard(pici->hwnd))
1103  throw last_error(GetLastError());
1104 
1105  try {
1106  hdrop = (HDROP)GetClipboardData(CF_HDROP);
1107 
1108  if (hdrop) {
1109  HANDLE lh;
1110 
1111  lh = GlobalLock(hdrop);
1112 
1113  if (lh) {
1114  try {
1115  ULONG num_files, i;
1116  WCHAR fn[MAX_PATH];
1117 
1118  num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0);
1119 
1120  for (i = 0; i < num_files; i++) {
1121  if (DragQueryFileW(hdrop, i, fn, sizeof(fn) / sizeof(WCHAR))) {
1122  reflink_copy(pici->hwnd, fn, pici->lpDirectoryW);
1123  }
1124  }
1125  } catch (...) {
1126  GlobalUnlock(lh);
1127  throw;
1128  }
1129 
1130  GlobalUnlock(lh);
1131  }
1132  }
1133  } catch (...) {
1134  CloseClipboard();
1135  throw;
1136  }
1137 
1138  CloseClipboard();
1139 
1140  return S_OK;
1141  }
1142  }
1143  } catch (const exception& e) {
1144  error_message(pici->hwnd, e.what());
1145  }
1146 
1147  return E_FAIL;
1148 }
1149 
1151  if (ignore)
1152  return E_INVALIDARG;
1153 
1154  if (idCmd != 0)
1155  return E_INVALIDARG;
1156 
1157  if (!bg) {
1158  if (idCmd == 0) {
1159  switch (uFlags) {
1160  case GCS_HELPTEXTA:
1162  return S_OK;
1163  else
1164  return E_FAIL;
1165 
1166  case GCS_HELPTEXTW:
1168  return S_OK;
1169  else
1170  return E_FAIL;
1171 
1172  case GCS_VALIDATEA:
1173  case GCS_VALIDATEW:
1174  return S_OK;
1175 
1176  case GCS_VERBA:
1177  return StringCchCopyA(pszName, cchMax, SNAPSHOT_VERBA);
1178 
1179  case GCS_VERBW:
1181 
1182  default:
1183  return E_INVALIDARG;
1184  }
1185  } else if (idCmd == 1) {
1186  switch (uFlags) {
1187  case GCS_HELPTEXTA:
1189  return S_OK;
1190  else
1191  return E_FAIL;
1192 
1193  case GCS_HELPTEXTW:
1195  return S_OK;
1196  else
1197  return E_FAIL;
1198 
1199  case GCS_VALIDATEA:
1200  case GCS_VALIDATEW:
1201  return S_OK;
1202 
1203  case GCS_VERBA:
1204  return StringCchCopyA(pszName, cchMax, SEND_VERBA);
1205 
1206  case GCS_VERBW:
1207  return StringCchCopyW((STRSAFE_LPWSTR)pszName, cchMax, SEND_VERBW);
1208 
1209  default:
1210  return E_INVALIDARG;
1211  }
1212  } else
1213  return E_INVALIDARG;
1214  } else {
1215  if (idCmd == 0) {
1216  switch (uFlags) {
1217  case GCS_HELPTEXTA:
1219  return S_OK;
1220  else
1221  return E_FAIL;
1222 
1223  case GCS_HELPTEXTW:
1225  return S_OK;
1226  else
1227  return E_FAIL;
1228 
1229  case GCS_VALIDATEA:
1230  case GCS_VALIDATEW:
1231  return S_OK;
1232 
1233  case GCS_VERBA:
1234  return StringCchCopyA(pszName, cchMax, NEW_SUBVOL_VERBA);
1235 
1236  case GCS_VERBW:
1238 
1239  default:
1240  return E_INVALIDARG;
1241  }
1242  } else if (idCmd == 1) {
1243  switch (uFlags) {
1244  case GCS_HELPTEXTA:
1246  return S_OK;
1247  else
1248  return E_FAIL;
1249 
1250  case GCS_HELPTEXTW:
1252  return S_OK;
1253  else
1254  return E_FAIL;
1255 
1256  case GCS_VALIDATEA:
1257  case GCS_VALIDATEW:
1258  return S_OK;
1259 
1260  case GCS_VERBA:
1261  return StringCchCopyA(pszName, cchMax, RECV_VERBA);
1262 
1263  case GCS_VERBW:
1264  return StringCchCopyW((STRSAFE_LPWSTR)pszName, cchMax, RECV_VERBW);
1265 
1266  default:
1267  return E_INVALIDARG;
1268  }
1269  } else if (idCmd == 2) {
1270  switch (uFlags) {
1271  case GCS_HELPTEXTA:
1273  return S_OK;
1274  else
1275  return E_FAIL;
1276 
1277  case GCS_HELPTEXTW:
1279  return S_OK;
1280  else
1281  return E_FAIL;
1282 
1283  case GCS_VALIDATEA:
1284  case GCS_VALIDATEW:
1285  return S_OK;
1286 
1287  case GCS_VERBA:
1288  return StringCchCopyA(pszName, cchMax, REFLINK_VERBA);
1289 
1290  case GCS_VERBW:
1292 
1293  default:
1294  return E_INVALIDARG;
1295  }
1296  } else
1297  return E_INVALIDARG;
1298  }
1299 }
1300 
1301 static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const wstring& destname) {
1303  FILE_BASIC_INFO fbi;
1304  FILETIME atime, mtime;
1305  btrfs_inode_info2 bii;
1306  btrfs_set_inode_info bsii;
1307  ULONG bytesret;
1308  NTSTATUS Status;
1310  btrfs_set_xattr bsxa;
1311 
1314  throw last_error(GetLastError());
1315 
1316  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info2));
1317  if (!NT_SUCCESS(Status))
1318  throw ntstatus_error(Status);
1319 
1320  // if subvol, do snapshot instead
1321  if (bii.inode == SUBVOL_ROOT_INODE) {
1322  ULONG bcslen;
1323  btrfs_create_snapshot* bcs;
1324  win_handle dirh;
1325 
1327  if (dirh == INVALID_HANDLE_VALUE)
1328  throw last_error(GetLastError());
1329 
1330  bcslen = offsetof(btrfs_create_snapshot, name[0]) + (destname.length() * sizeof(WCHAR));
1331  bcs = (btrfs_create_snapshot*)malloc(bcslen);
1332  bcs->subvol = source;
1333  bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
1334  memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
1335 
1336  Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, nullptr, 0);
1337  if (!NT_SUCCESS(Status)) {
1338  free(bcs);
1339  throw ntstatus_error(Status);
1340  }
1341 
1342  free(bcs);
1343 
1344  return;
1345  }
1346 
1347  if (!GetFileInformationByHandleEx(source, FileBasicInfo, &fbi, sizeof(FILE_BASIC_INFO)))
1348  throw last_error(GetLastError());
1349 
1350  if (bii.type == BTRFS_TYPE_CHARDEV || bii.type == BTRFS_TYPE_BLOCKDEV || bii.type == BTRFS_TYPE_FIFO || bii.type == BTRFS_TYPE_SOCKET) {
1351  win_handle dirh;
1352  ULONG bmnsize;
1353  btrfs_mknod* bmn;
1354 
1356  if (dirh == INVALID_HANDLE_VALUE)
1357  throw last_error(GetLastError());
1358 
1359  bmnsize = offsetof(btrfs_mknod, name[0]) + (destname.length() * sizeof(WCHAR));
1360  bmn = (btrfs_mknod*)malloc(bmnsize);
1361 
1362  bmn->inode = 0;
1363  bmn->type = bii.type;
1364  bmn->st_rdev = bii.st_rdev;
1365  bmn->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
1366  memcpy(bmn->name, destname.c_str(), bmn->namelen);
1367 
1368  Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_MKNOD, bmn, bmnsize, nullptr, 0);
1369  if (!NT_SUCCESS(Status)) {
1370  free(bmn);
1371  throw ntstatus_error(Status);
1372  }
1373 
1374  free(bmn);
1375 
1376  dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
1377  } else if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1378  if (CreateDirectoryExW(srcfn.c_str(), (destdir + destname).c_str(), nullptr))
1380  nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
1381  else
1383  } else
1384  dest = CreateFileW((destdir + destname).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source);
1385 
1386  if (dest == INVALID_HANDLE_VALUE)
1387  throw last_error(GetLastError());
1388 
1389  memset(&bsii, 0, sizeof(btrfs_set_inode_info));
1390 
1391  bsii.flags_changed = true;
1392  bsii.flags = bii.flags;
1393 
1394  if (bii.flags & BTRFS_INODE_COMPRESS) {
1395  bsii.compression_type_changed = true;
1397  }
1398 
1399  try {
1400  Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_INODE_INFO, &bsii, sizeof(btrfs_set_inode_info), nullptr, 0);
1401  if (!NT_SUCCESS(Status))
1402  throw ntstatus_error(Status);
1403 
1404  if (fbi.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1405  if (!(fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) {
1406  WIN32_FIND_DATAW fff;
1407  wstring qs;
1408 
1409  qs = srcfn;
1410  qs += L"\\*";
1411 
1412  fff_handle h = FindFirstFileW(qs.c_str(), &fff);
1413  if (h != INVALID_HANDLE_VALUE) {
1414  do {
1415  wstring fn2;
1416 
1417  if (fff.cFileName[0] == '.' && (fff.cFileName[1] == 0 || (fff.cFileName[1] == '.' && fff.cFileName[2] == 0)))
1418  continue;
1419 
1420  fn2 = srcfn;
1421  fn2 += L"\\";
1422  fn2 += fff.cFileName;
1423 
1424  reflink_copy2(fn2, destdir + destname + L"\\", fff.cFileName);
1425  } while (FindNextFileW(h, &fff));
1426  }
1427  }
1428 
1429  // CreateDirectoryExW also copies streams, no need to do it here
1430  } else {
1431  WIN32_FIND_STREAM_DATA fsd;
1432 
1433  if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
1434  reparse_header rh;
1435  ULONG rplen;
1436  uint8_t* rp;
1437 
1438  if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
1439  if (GetLastError() != ERROR_MORE_DATA)
1440  throw last_error(GetLastError());
1441  }
1442 
1443  rplen = sizeof(reparse_header) + rh.ReparseDataLength;
1444  rp = (uint8_t*)malloc(rplen);
1445 
1446  try {
1447  if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, rplen, &bytesret, nullptr))
1448  throw last_error(GetLastError());
1449 
1450  if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, rplen, nullptr, 0, &bytesret, nullptr))
1451  throw last_error(GetLastError());
1452  } catch (...) {
1453  free(rp);
1454  throw;
1455  }
1456 
1457  free(rp);
1458  } else {
1459  FILE_STANDARD_INFO fsi;
1460  FILE_END_OF_FILE_INFO feofi;
1464  uint64_t offset, alloc_size;
1465  ULONG maxdup;
1466 
1467  if (!GetFileInformationByHandleEx(source, FileStandardInfo, &fsi, sizeof(FILE_STANDARD_INFO)))
1468  throw last_error(GetLastError());
1469 
1470  if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
1471  throw last_error(GetLastError());
1472 
1473  if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
1474  if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr))
1475  throw last_error(GetLastError());
1476  }
1477 
1478  fsiib.ChecksumAlgorithm = fgiib.ChecksumAlgorithm;
1479  fsiib.Reserved = 0;
1480  fsiib.Flags = fgiib.Flags;
1481  if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr))
1482  throw last_error(GetLastError());
1483 
1484  feofi.EndOfFile = fsi.EndOfFile;
1485  if (!SetFileInformationByHandle(dest, FileEndOfFileInfo, &feofi, sizeof(FILE_END_OF_FILE_INFO)))
1486  throw last_error(GetLastError());
1487 
1488  ded.FileHandle = source;
1489  maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
1490 
1491  alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
1492 
1493  offset = 0;
1494  while (offset < alloc_size) {
1496  ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset);
1497  if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr))
1498  throw last_error(GetLastError());
1499 
1500  offset += ded.ByteCount.QuadPart;
1501  }
1502  }
1503 
1504  fff_handle h = FindFirstStreamW(srcfn.c_str(), FindStreamInfoStandard, &fsd, 0);
1505  if (h != INVALID_HANDLE_VALUE) {
1506  do {
1507  wstring sn;
1508 
1509  sn = fsd.cStreamName;
1510 
1511  if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
1513  uint8_t* data = nullptr;
1514 
1515  if (fsd.StreamSize.QuadPart > 0) {
1516  wstring fn2;
1517  uint16_t stream_size = (uint16_t)fsd.StreamSize.QuadPart;
1518 
1519  fn2 = srcfn;
1520  fn2 += sn;
1521 
1522  stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
1523 
1525  throw last_error(GetLastError());
1526 
1527  // We can get away with this because our streams are guaranteed to be below 64 KB -
1528  // don't do this on NTFS!
1530 
1531  if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
1532  free(data);
1533  throw last_error(GetLastError());
1534  }
1535  }
1536 
1537  stream = CreateFileW((destdir + destname + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
1538 
1539  if (stream == INVALID_HANDLE_VALUE) {
1540  if (data) free(data);
1541  throw last_error(GetLastError());
1542  }
1543 
1544  if (data) {
1545  if (!WriteFile(stream, data, (uint32_t)fsd.StreamSize.QuadPart, &bytesret, nullptr)) {
1546  free(data);
1547  throw last_error(GetLastError());
1548  }
1549 
1550  free(data);
1551  }
1552  }
1553  } while (FindNextStreamW(h, &fsd));
1554  }
1555  }
1556 
1557  atime.dwLowDateTime = fbi.LastAccessTime.LowPart;
1558  atime.dwHighDateTime = fbi.LastAccessTime.HighPart;
1559  mtime.dwLowDateTime = fbi.LastWriteTime.LowPart;
1560  mtime.dwHighDateTime = fbi.LastWriteTime.HighPart;
1561  SetFileTime(dest, nullptr, &atime, &mtime);
1562 
1563  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr));
1564 
1565  if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
1566  ULONG xalen = 0;
1567  btrfs_set_xattr *xa = nullptr, *xa2;
1568 
1569  do {
1570  xalen += 1024;
1571 
1572  if (xa) free(xa);
1573  xa = (btrfs_set_xattr*)malloc(xalen);
1574 
1575  Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
1576  } while (Status == STATUS_BUFFER_OVERFLOW);
1577 
1578  if (!NT_SUCCESS(Status)) {
1579  free(xa);
1580  throw ntstatus_error(Status);
1581  }
1582 
1583  xa2 = xa;
1584  while (xa2->valuelen > 0) {
1585  Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
1586  offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen, nullptr, 0);
1587  if (!NT_SUCCESS(Status)) {
1588  free(xa);
1589  throw ntstatus_error(Status);
1590  }
1591  xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen];
1592  }
1593 
1594  free(xa);
1595  } else if (!NT_SUCCESS(Status))
1596  throw ntstatus_error(Status);
1597  } catch (...) {
1598  FILE_DISPOSITION_INFO fdi;
1599 
1600  fdi.DeleteFile = true;
1601  SetFileInformationByHandle(dest, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
1602 
1603  throw;
1604  }
1605 }
1606 
1607 #ifdef __REACTOS__
1608 extern "C" {
1609 #endif
1610 
1611 void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
1613 
1614  command_line_to_args(lpszCmdLine, args);
1615 
1616  if (args.size() >= 2) {
1617  bool dest_is_dir = false;
1618  wstring dest = args[args.size() - 1], destdir, destname;
1619  WCHAR volpath2[MAX_PATH];
1620 
1621  {
1623  nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
1624 
1625  if (destdirh != INVALID_HANDLE_VALUE) {
1627 
1628  if (GetFileInformationByHandle(destdirh, &bhfi) && bhfi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1629  dest_is_dir = true;
1630 
1631  destdir = dest;
1632  if (destdir.substr(destdir.length() - 1, 1) != L"\\")
1633  destdir += L"\\";
1634  }
1635  }
1636  }
1637 
1638  if (!dest_is_dir) {
1639  size_t found = dest.rfind(L"\\");
1640 
1641  if (found == wstring::npos) {
1642  destdir = L"";
1643  destname = dest;
1644  } else {
1645  destdir = dest.substr(0, found);
1646  destname = dest.substr(found + 1);
1647  }
1648  }
1649 
1650  if (!GetVolumePathNameW(dest.c_str(), volpath2, sizeof(volpath2) / sizeof(WCHAR)))
1651  return;
1652 
1653  for (unsigned int i = 0; i < args.size() - 1; i++) {
1654  WIN32_FIND_DATAW ffd;
1655 
1656  fff_handle h = FindFirstFileW(args[i].c_str(), &ffd);
1657  if (h != INVALID_HANDLE_VALUE) {
1658  WCHAR volpath1[MAX_PATH];
1659  wstring path = args[i];
1660  size_t found = path.rfind(L"\\");
1661 
1662  if (found == wstring::npos)
1663  path = L"";
1664  else
1665  path = path.substr(0, found);
1666 
1667  path += L"\\";
1668 
1669  if (get_volume_path_parent(path.c_str(), volpath1, sizeof(volpath1) / sizeof(WCHAR))) {
1670  if (!wcscmp(volpath1, volpath2)) {
1671  do {
1672  try {
1673  reflink_copy2(path + ffd.cFileName, destdir, dest_is_dir ? ffd.cFileName : destname);
1674  } catch (const exception& e) {
1675  cerr << "Error: " << e.what() << endl;
1676  }
1677  } while (FindNextFileW(h, &ffd));
1678  }
1679  }
1680  }
1681  }
1682  }
1683 }
1684 
1685 #ifdef __REACTOS__
1686 } /* extern "C" */
1687 #endif
#define FSCTL_SET_SPARSE
Definition: winioctl.h:100
static short search(int val, const short *table, int size)
Definition: msg711.c:255
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:607
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
const DOCKBAR PVOID HWND HWND * hwnd
Definition: tooldock.h:22
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
static HICON
Definition: imagelist.c:84
#define REFIID
Definition: guiddef.h:113
#define CloseHandle
Definition: compat.h:398
ULONG __stdcall AddRef()
Definition: contextmenu.h:51
#define E_NOINTERFACE
Definition: winerror.h:2364
#define IMAGE_ICON
Definition: winuser.h:212
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
_Must_inspect_result_ _Out_ LPSIZE psize
Definition: ntgdi.h:1569
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1454
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:85
HRESULT hr
Definition: shlfolder.c:183
static HMENU hmenu
Definition: win.c:66
virtual HRESULT __stdcall QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
UINT8 compression_type
Definition: btrfsioctl.h:97
BOOL WINAPI InsertMenuW(_In_ HMENU, _In_ UINT, _In_ UINT, _In_ UINT_PTR, _In_opt_ LPCWSTR)
#define SEND_VERBW
Definition: contextmenu.cpp:58
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2036
HDC WINAPI GetDC(_In_opt_ HWND)
#define NEW_SUBVOL_VERBW
Definition: contextmenu.cpp:50
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
virtual HRESULT __stdcall GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:83
REFIID riid
Definition: precomp.h:44
_In_ HBITMAP _In_ UINT _In_ UINT _Inout_ LPBITMAPINFO pbmi
Definition: ntgdi.h:2780
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
struct tagBITMAPINFOHEADER BITMAPINFOHEADER
#define free
Definition: debug_ros.c:5
int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPSTR lpBuffer, _In_ int cchBufferMax)
#define IDS_SNAPSHOT_FILENAME
Definition: resource.h:14
LONG NTSTATUS
Definition: precomp.h:26
UINT64 st_rdev
Definition: btrfsioctl.h:252
#define BTRFS_TYPE_FIFO
Definition: shellext.h:84
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1280
static HDC
Definition: imagelist.c:92
GLintptr offset
Definition: glext.h:5920
#define CALLBACK
Definition: compat.h:27
static const size_t npos
Definition: _string_npos.h:26
static void create_snapshot(HWND hwnd, const wstring &fn)
GLdouble n
Definition: glext.h:7729
GLdouble GLdouble t
Definition: gl.h:2047
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define ZeroMemory
Definition: winbase.h:1635
GLuint buffer
Definition: glext.h:5915
#define SM_CYSMICON
Definition: winuser.h:1003
#define RECV_VERBW
Definition: contextmenu.cpp:56
LPWSTR dwTypeData
Definition: winuser.h:3211
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength)
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
wchar_t * STRSAFE_LPWSTR
Definition: ntstrsafe.h:63
__u16 time
Definition: mkdosfs.c:366
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
unsigned short int uint16_t
Definition: acefiex.h:54
UINT uFlags
Definition: api.c:60
#define uint16_t
Definition: nsiface.idl:60
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:82
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
char * LPSTR
Definition: xmlstorage.h:182
#define E_FAIL
Definition: ddrawi.h:102
GLint namelen
Definition: glext.h:7232
Definition: match.c:390
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
#define DWORD
Definition: nt_native.h:44
void reflink_copy(HWND hwnd, const WCHAR *fn, const WCHAR *dir)
#define IDS_RECV_SUBVOL_HELP
Definition: resource.h:130
#define MIIM_BITMAP
Definition: winuser.h:723
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define SEND_VERBA
Definition: contextmenu.cpp:57
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
#define FILE_SHARE_READ
Definition: compat.h:125
#define SNAPSHOT_VERBA
Definition: contextmenu.cpp:51
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
virtual HRESULT __stdcall InvokeCommand(LPCMINVOKECOMMANDINFO pici)
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:1098
UINT16 namelen
Definition: btrfsioctl.h:253
uint32_t ULONG_PTR
Definition: typedefs.h:63
UINT8 type
Definition: btrfsioctl.h:251
static HMODULE dll
Definition: str.c:188
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define FILE_TRAVERSE
Definition: nt_native.h:643
DWORD dwHighDateTime
Definition: mapidefs.h:66
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
void error_message(HWND hwnd, const char *msg)
Definition: main.cpp:738
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
basic_ostream< _CharT, _Traits > &_STLP_CALL endl(basic_ostream< _CharT, _Traits > &__os)
Definition: _ostream.h:357
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define IDS_SEND_SUBVOL_HELP
Definition: resource.h:176
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:10
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_ UINT, _In_ int, _In_ int, _In_ UINT)
Definition: cursoricon.c:2172
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
long LONG
Definition: pedump.c:60
Definition: main.c:440
#define a
Definition: ke_i.h:78
#define e
Definition: ke_i.h:82
#define MF_BYPOSITION
Definition: winuser.h:203
#define GENERIC_WRITE
Definition: nt_native.h:90
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
int length
Definition: match.c:394
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
DWORD biCompression
Definition: amvideo.idl:35
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:570
#define IDS_NEW_SUBVOL_HELP_TEXT
Definition: resource.h:6
#define E_INVALIDARG
Definition: ddrawi.h:101
const WCHAR * str
#define offsetof(TYPE, MEMBER)
char ext[3]
Definition: mkdosfs.c:358
#define CF_HDROP
Definition: constants.h:410
LONG cx
Definition: windef.h:319
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:389
#define IDS_CREATE_SNAPSHOT
Definition: resource.h:10
int const char int stream_size
Definition: zlib.h:813
#define RECV_VERBA
Definition: contextmenu.cpp:55
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2225
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:276
unsigned int dir
Definition: maze.c:112
#define SW_SHOW
Definition: winuser.h:769
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:442
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define OPEN_EXISTING
Definition: compat.h:426
USHORT ReparseDataLength
Definition: contextmenu.cpp:62
#define b
Definition: ke_i.h:79
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:9
#define MIIM_ID
Definition: winuser.h:717
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define IDS_REFLINK_PASTE_HELP
Definition: resource.h:128
STGMEDIUM stgm
Definition: contextmenu.h:79
void wstring_sprintf(wstring &s, wstring fmt,...)
Definition: main.cpp:225
static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP *phBmp)
Definition: uimain.c:88
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:176
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLsizei stride
Definition: glext.h:5848
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:608
if(!(yy_init))
Definition: macro.lex.yy.c:714
static bool show_reflink_paste(const wstring &path)
virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
Definition: contextmenu.cpp:85
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_STLP_DECLSPEC _Stl_aligned_buffer< ostream > cerr
Definition: iostream.cpp:102
static bool get_volume_path_parent(const WCHAR *fn, WCHAR *volpath, ULONG volpathlen)
LONG HRESULT
Definition: typedefs.h:77
const GUID IID_IUnknown
#define REFLINK_VERBA
Definition: contextmenu.cpp:53
#define MAX_PATH
Definition: compat.h:26
#define swprintf(buf, format,...)
Definition: sprintf.c:56
unsigned short WORD
Definition: ntddk_ex.h:93
int WINAPI GetSystemMetrics(_In_ int)
GLuint GLuint num
Definition: glext.h:9618
BOOL WINAPI GetFileInformationByHandleEx(HANDLE handle, FILE_INFO_BY_HANDLE_CLASS class, LPVOID info, DWORD size)
#define FSCTL_BTRFS_GET_XATTRS
Definition: btrfsioctl.h:33
#define __stdcall
Definition: typedefs.h:25
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
UINT64 inode
Definition: btrfsioctl.h:250
UINT cchMax
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
#define SM_CXSMICON
Definition: winuser.h:1002
#define IDS_RECV_SUBVOL
Definition: resource.h:129
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
static const WCHAR L[]
Definition: oid.c:1250
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
#define FSCTL_BTRFS_MKNOD
Definition: btrfsioctl.h:31
Definition: parse.h:22
#define SNAPSHOT_VERBW
Definition: contextmenu.cpp:52
HDC hdc
Definition: main.c:9
GLuint GLuint stream
Definition: glext.h:7522
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
unsigned char BYTE
Definition: mem.h:68
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:8
#define IDS_SEND_SUBVOL
Definition: resource.h:175
#define GENERIC_READ
Definition: compat.h:124
#define FSCTL_BTRFS_SET_INODE_INFO
Definition: btrfsioctl.h:12
#define ERROR_MORE_DATA
Definition: dderror.h:13
BYTE uint8_t
Definition: msvideo1.c:66
Status
Definition: gdiplustypes.h:24
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3234
static void path_remove_file(wstring &path)
#define MIIM_STRING
Definition: winuser.h:722
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
HANDLE WINAPI FindFirstStreamW(IN LPCWSTR lpFileName, IN STREAM_INFO_LEVELS InfoLevel, OUT LPVOID lpFindStreamData, IN DWORD dwFlags)
Definition: find.c:957
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
#define NEW_SUBVOL_VERBA
Definition: contextmenu.cpp:49
#define S_OK
Definition: intsafe.h:59
struct IContextMenu::tagCMInvokeCommandInfoEx * LPCMINVOKECOMMANDINFOEX
UINT64 uint64_t
Definition: types.h:77
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
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
unsigned short USHORT
Definition: pedump.c:61
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
LPCWSTR lpParameters
Definition: shellapi.h:331
#define FSCTL_BTRFS_GET_INODE_INFO
Definition: btrfsioctl.h:11
#define f
Definition: ke_i.h:83
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:197
Definition: services.c:325
static void path_strip_path(wstring &path)
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
BOOL WINAPI CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory, IN LPCWSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:193
unsigned int UINT
Definition: ndis.h:50
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:177
void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: muireg.c:10
UINT32 uint32_t
Definition: types.h:75
static void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
HANDLE WINAPI GetClipboardData(_In_ UINT)
BOOL WINAPI FindNextStreamW(IN HANDLE hFindStream, OUT LPVOID lpFindStreamData)
Definition: find.c:1115
#define IDS_CANT_REFLINK_DIFFERENT_FS
Definition: resource.h:205
#define CreateFileW
Definition: compat.h:400
#define FSCTL_GET_INTEGRITY_INFORMATION
Definition: shellext.h:197
_Out_opt_ int * cx
Definition: commctrl.h:570
BOOL WINAPI SetFileInformationByHandle(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize)
Definition: reactos.cpp:177
Definition: name.c:36
#define REFLINK_VERBW
Definition: contextmenu.cpp:54
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
static void reflink_copy2(const wstring &srcfn, const wstring &destdir, const wstring &destname)
WCHAR name[1]
Definition: btrfsioctl.h:254
#define IDS_NEW_SUBVOL
Definition: resource.h:7
#define FSCTL_BTRFS_SET_XATTR
Definition: btrfsioctl.h:34
unsigned int ULONG
Definition: retypes.h:1
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:845
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
static HINSTANCE hinst
Definition: edit.c:551
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define malloc
Definition: debug_ros.c:4
DWORD bpp
Definition: surface.c:181
static HBITMAP bitmap
Definition: clipboard.c:1344
static char * dest
Definition: rtl.c:135
#define FSCTL_SET_INTEGRITY_INFORMATION
Definition: shellext.h:198
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj)
Definition: contextmenu.cpp:70
#define IDS_NEW_SUBVOL_FILENAME
Definition: resource.h:9
#define CREATE_NEW
Definition: disk.h:69
static HBITMAP
Definition: button.c:44
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:98
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define DIB_RGB_COLORS
Definition: wingdi.h:366
#define ss
Definition: i386-dis.c:432
#define INFINITE
Definition: serial.h:102
static struct msdos_boot_sector bs
Definition: mkdosfs.c:539
#define LR_DEFAULTCOLOR
Definition: winuser.h:1077
BOOL WINAPI ReadFile(IN HANDLE hFile, IN LPVOID lpBuffer, IN DWORD nNumberOfBytesToRead, OUT LPDWORD lpNumberOfBytesRead OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:123
#define memset(x, y, z)
Definition: compat.h:39
#define args
Definition: format.c:66
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:60
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:627
LONG cy
Definition: windef.h:320
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
#define BI_RGB
Definition: precomp.h:35
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
#define IDS_REFLINK_PASTE
Definition: resource.h:127
LARGE_INTEGER ByteCount
Definition: shellext.h:178
struct tagMENUITEMINFOW MENUITEMINFOW
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
DWORD dwLowDateTime
Definition: mapidefs.h:65
#define SUCCEEDED(hr)
Definition: intsafe.h:57
#define IDS_CREATE_SNAPSHOT_HELP_TEXT
Definition: resource.h:12
#define DELETE
Definition: nt_native.h:57
LONGLONG QuadPart
Definition: typedefs.h:112
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE
Definition: shellext.h:181
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
void command_line_to_args(LPWSTR cmdline, vector< wstring > args)
Definition: main.cpp:610
GLuint const GLchar * name
Definition: glext.h:6031