ReactOS 0.4.16-dev-401-g45b008d
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
60typedef struct {
65
66static 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
89
90 if (!pidlFolder) {
91 FORMATETC format = { CF_HDROP, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
92 UINT num_files, i;
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
185static 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
205static 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) {
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}
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
265 ZeroMemory(pbmi, cbInfo);
269
273}
274
275static 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 = (UINT)(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 {
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
426static 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
440static 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
451static void create_snapshot(HWND hwnd, const wstring& fn) {
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}
530
532 if (n & (a - 1))
533 n = (n + a) & ~(a - 1);
534
535 return n;
536}
537
540 WCHAR* name, volpath1[255], volpath2[255];
541 wstring dirw, newpath;
542 FILE_BASIC_INFO fbi;
543 FILETIME atime, mtime;
546 ULONG bytesret;
549 btrfs_set_xattr bsxa;
550
551 // Thanks to 0xbadfca11, whose version of reflink for Windows provided a few pointers on what
552 // to do here - https://github.com/0xbadfca11/reflink
553
555
556 dirw = dir;
557
558 if (dir[0] != 0 && dir[wcslen(dir) - 1] != '\\')
559 dirw += L"\\";
560
561 newpath = dirw;
562 newpath += name;
563
564 if (!get_volume_path_parent(fn, volpath1, sizeof(volpath1) / sizeof(WCHAR)))
565 throw last_error(GetLastError());
566
567 if (!GetVolumePathNameW(dir, volpath2, sizeof(volpath2) / sizeof(WCHAR)))
568 throw last_error(GetLastError());
569
570 if (wcscmp(volpath1, volpath2)) // different filesystems
572
575 throw last_error(GetLastError());
576
577 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_INODE_INFO, nullptr, 0, &bii, sizeof(btrfs_inode_info));
578 if (!NT_SUCCESS(Status))
579 throw ntstatus_error(Status);
580
581 // if subvol, do snapshot instead
582 if (bii.inode == SUBVOL_ROOT_INODE) {
584 win_handle dirh;
585 wstring destname, search;
587 int num = 2;
588
590 if (dirh == INVALID_HANDLE_VALUE)
591 throw last_error(GetLastError());
592
593 search = dirw;
594 search += name;
595 destname = name;
596
597 fff_handle fff = FindFirstFileW(search.c_str(), &wfd);
598
599 if (fff != INVALID_HANDLE_VALUE) {
600 do {
602
603 ss << name;
604 ss << L" (";
605 ss << num;
606 ss << L")";
607 destname = ss.str();
608
609 search = dirw + destname;
610
611 fff = FindFirstFileW(search.c_str(), &wfd);
612 num++;
613 } while (fff != INVALID_HANDLE_VALUE);
614 }
615
616 bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - sizeof(WCHAR) + (destname.length() * sizeof(WCHAR)));
617 bcs->subvol = source;
618 bcs->namelen = (uint16_t)(destname.length() * sizeof(WCHAR));
619 memcpy(bcs->name, destname.c_str(), destname.length() * sizeof(WCHAR));
620
621 Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs,
622 (ULONG)(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 Status = NtQueryInformationFile(source, &iosb, &fbi, sizeof(FILE_BASIC_INFO), FileBasicInformation);
633 if (!NT_SUCCESS(Status))
634 throw ntstatus_error(Status);
635
637 win_handle dirh;
638 btrfs_mknod* bmn;
639
641 if (dirh == INVALID_HANDLE_VALUE)
642 throw last_error(GetLastError());
643
644 size_t 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, (ULONG)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)) {
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 if (fbi.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
764 uint8_t* rp;
765
766 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, &rh, sizeof(reparse_header), &bytesret, nullptr)) {
768 throw last_error(GetLastError());
769 }
770
771 size_t rplen = sizeof(reparse_header) + rh.ReparseDataLength;
772 rp = (uint8_t*)malloc(rplen);
773
774 if (!DeviceIoControl(source, FSCTL_GET_REPARSE_POINT, nullptr, 0, rp, (ULONG)rplen, &bytesret, nullptr))
775 throw last_error(GetLastError());
776
777 if (!DeviceIoControl(dest, FSCTL_SET_REPARSE_POINT, rp, (ULONG)rplen, nullptr, 0, &bytesret, nullptr))
778 throw last_error(GetLastError());
779
780 free(rp);
781 } else {
782 FILE_STANDARD_INFO fsi;
783 FILE_END_OF_FILE_INFO feofi;
787 uint64_t offset, alloc_size;
788 ULONG maxdup;
789
790 Status = NtQueryInformationFile(source, &iosb, &fsi, sizeof(FILE_STANDARD_INFO), FileStandardInformation);
791 if (!NT_SUCCESS(Status))
792 throw ntstatus_error(Status);
793
794 if (!DeviceIoControl(source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &fgiib, sizeof(FSCTL_GET_INTEGRITY_INFORMATION_BUFFER), &bytesret, nullptr))
795 throw last_error(GetLastError());
796
797 if (fbi.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) {
798 if (!DeviceIoControl(dest, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &bytesret, nullptr))
799 throw last_error(GetLastError());
800 }
801
803 fsiib.Reserved = 0;
804 fsiib.Flags = fgiib.Flags;
805 if (!DeviceIoControl(dest, FSCTL_SET_INTEGRITY_INFORMATION, &fsiib, sizeof(FSCTL_SET_INTEGRITY_INFORMATION_BUFFER), nullptr, 0, &bytesret, nullptr))
806 throw last_error(GetLastError());
807
808 feofi.EndOfFile = fsi.EndOfFile;
809 Status = NtSetInformationFile(dest, &iosb, &feofi, sizeof(FILE_END_OF_FILE_INFO), FileEndOfFileInformation);
810 if (!NT_SUCCESS(Status))
811 throw ntstatus_error(Status);
812
813 ded.FileHandle = source;
814 maxdup = 0xffffffff - fgiib.ClusterSizeInBytes + 1;
815
816 alloc_size = sector_align(fsi.EndOfFile.QuadPart, fgiib.ClusterSizeInBytes);
817
818 offset = 0;
819 while (offset < alloc_size) {
821 ded.ByteCount.QuadPart = maxdup < (alloc_size - offset) ? maxdup : (alloc_size - offset);
822 if (!DeviceIoControl(dest, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &ded, sizeof(DUPLICATE_EXTENTS_DATA), nullptr, 0, &bytesret, nullptr))
823 throw last_error(GetLastError());
824
826 }
827 }
828
829 ULONG streambufsize = 0;
830 vector<char> streambuf;
831
832 do {
833 streambufsize += 0x1000;
834 streambuf.resize(streambufsize);
835
836 memset(streambuf.data(), 0, streambufsize);
837
839 } while (Status == STATUS_BUFFER_OVERFLOW);
840
841 if (!NT_SUCCESS(Status))
842 throw ntstatus_error(Status);
843
844 auto fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(streambuf.data());
845
846 while (true) {
847 if (fsi->StreamNameLength > 0) {
848 wstring sn = wstring(fsi->StreamName, fsi->StreamNameLength / sizeof(WCHAR));
849
850 if (sn != L"::$DATA" && sn.length() > 6 && sn.substr(sn.length() - 6, 6) == L":$DATA") {
852 uint8_t* data = nullptr;
853 auto stream_size = (uint16_t)fsi->StreamSize.QuadPart;
854
855
856 if (stream_size > 0) {
857 wstring fn2;
858
859 fn2 = fn;
860 fn2 += sn;
861
862 stream = CreateFileW(fn2.c_str(), GENERIC_READ, 0, nullptr, OPEN_EXISTING, 0, nullptr);
863
865 throw last_error(GetLastError());
866
867 // We can get away with this because our streams are guaranteed to be below 64 KB -
868 // don't do this on NTFS!
870
871 if (!ReadFile(stream, data, stream_size, &bytesret, nullptr)) {
872 free(data);
873 throw last_error(GetLastError());
874 }
875 }
876
877 stream = CreateFileW((newpath + sn).c_str(), GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, nullptr);
878
880 if (data) free(data);
881 throw last_error(GetLastError());
882 }
883
884 if (data) {
885 if (!WriteFile(stream, data, stream_size, &bytesret, nullptr)) {
886 free(data);
887 throw last_error(GetLastError());
888 }
889
890 free(data);
891 }
892 }
893 }
894
895 if (fsi->NextEntryOffset == 0)
896 break;
897
898 fsi = reinterpret_cast<FILE_STREAM_INFORMATION*>(reinterpret_cast<char*>(fsi) + fsi->NextEntryOffset);
899 }
900 }
901
902 atime.dwLowDateTime = fbi.LastAccessTime.LowPart;
903 atime.dwHighDateTime = fbi.LastAccessTime.HighPart;
904 mtime.dwLowDateTime = fbi.LastWriteTime.LowPart;
905 mtime.dwHighDateTime = fbi.LastWriteTime.HighPart;
906 SetFileTime(dest, nullptr, &atime, &mtime);
907
908 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, &bsxa, sizeof(btrfs_set_xattr));
909
910 if (Status == STATUS_BUFFER_OVERFLOW || (NT_SUCCESS(Status) && bsxa.valuelen > 0)) {
911 ULONG xalen = 0;
912 btrfs_set_xattr *xa = nullptr, *xa2;
913
914 do {
915 xalen += 1024;
916
917 if (xa) free(xa);
918 xa = (btrfs_set_xattr*)malloc(xalen);
919
920 Status = NtFsControlFile(source, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_XATTRS, nullptr, 0, xa, xalen);
921 } while (Status == STATUS_BUFFER_OVERFLOW);
922
923 if (!NT_SUCCESS(Status)) {
924 free(xa);
925 throw ntstatus_error(Status);
926 }
927
928 xa2 = xa;
929 while (xa2->valuelen > 0) {
930 Status = NtFsControlFile(dest, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SET_XATTR, xa2,
931 (ULONG)(offsetof(btrfs_set_xattr, data[0]) + xa2->namelen + xa2->valuelen), nullptr, 0);
932 if (!NT_SUCCESS(Status)) {
933 free(xa);
934 throw ntstatus_error(Status);
935 }
936 xa2 = (btrfs_set_xattr*)&xa2->data[xa2->namelen + xa2->valuelen];
937 }
938
939 free(xa);
940 } else if (!NT_SUCCESS(Status))
941 throw ntstatus_error(Status);
942 } catch (...) {
943 FILE_DISPOSITION_INFO fdi;
944
945 fdi.DeleteFile = true;
946 Status = NtSetInformationFile(dest, &iosb, &fdi, sizeof(FILE_DISPOSITION_INFO), FileDispositionInformation);
947 if (!NT_SUCCESS(Status))
948 throw ntstatus_error(Status);
949
950 throw;
951 }
952}
953
956
957 try {
958 if (ignore)
959 return E_INVALIDARG;
960
961 if (!bg) {
962 if ((IS_INTRESOURCE(pici->lpVerb) && allow_snapshot && pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SNAPSHOT_VERBA))) {
963 UINT num_files, i;
965
966 if (!stgm_set)
967 return E_FAIL;
968
969 num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0);
970
971 if (num_files == 0)
972 return E_FAIL;
973
974 for (i = 0; i < num_files; i++) {
975 if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) {
976 create_snapshot(pici->hwnd, fn);
977 }
978 }
979
980 return S_OK;
981 } else if ((IS_INTRESOURCE(pici->lpVerb) && ((allow_snapshot && (ULONG_PTR)pici->lpVerb == 1) || (!allow_snapshot && (ULONG_PTR)pici->lpVerb == 0))) ||
982 (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, SEND_VERBA))) {
983 UINT num_files, i;
985 wstring t;
987
988 GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
989
990 if (!stgm_set)
991 return E_FAIL;
992
993 num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, nullptr, 0);
994
995 if (num_files == 0)
996 return E_FAIL;
997
998 for (i = 0; i < num_files; i++) {
999 if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(WCHAR))) {
1000 t = L"\"";
1001 t += dll;
1002 t += L"\",SendSubvolGUI ";
1003 t += fn;
1004
1005 RtlZeroMemory(&sei, sizeof(sei));
1006
1007 sei.cbSize = sizeof(sei);
1008 sei.hwnd = pici->hwnd;
1009 sei.lpVerb = L"runas";
1010 sei.lpFile = L"rundll32.exe";
1011 sei.lpParameters = t.c_str();
1012 sei.nShow = SW_SHOW;
1014
1015 if (!ShellExecuteExW(&sei))
1016 throw last_error(GetLastError());
1017
1019 CloseHandle(sei.hProcess);
1020 }
1021 }
1022
1023 return S_OK;
1024 }
1025 } else {
1026 if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 0) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, NEW_SUBVOL_VERBA))) {
1027 win_handle h;
1030 wstring name, nameorig, searchpath;
1032 WIN32_FIND_DATAW wfd;
1033
1035 throw last_error(GetLastError());
1036
1038
1039 if (h == INVALID_HANDLE_VALUE)
1040 throw last_error(GetLastError());
1041
1042 searchpath = path + L"\\" + name;
1043 nameorig = name;
1044
1045 {
1046 fff_handle fff = FindFirstFileW(searchpath.c_str(), &wfd);
1047
1048 if (fff != INVALID_HANDLE_VALUE) {
1049 ULONG num = 2;
1050
1051 do {
1052#ifndef __REACTOS__
1053 name = nameorig + L" (" + to_wstring(num) + L")";
1054#else
1055 {
1056 WCHAR buffer[32];
1057
1058 swprintf(buffer, L"%d", num);
1059 name = nameorig + L" (" + buffer + L")";
1060 }
1061#endif
1062 searchpath = path + L"\\" + name;
1063
1064 fff = FindFirstFileW(searchpath.c_str(), &wfd);
1065 num++;
1066 } while (fff != INVALID_HANDLE_VALUE);
1067 }
1068 }
1069
1070 size_t bcslen = offsetof(btrfs_create_subvol, name[0]) + (name.length() * sizeof(WCHAR));
1071 bcs = (btrfs_create_subvol*)malloc(bcslen);
1072
1073 bcs->readonly = false;
1074 bcs->posix = false;
1075 bcs->namelen = (uint16_t)(name.length() * sizeof(WCHAR));
1076 memcpy(bcs->name, name.c_str(), name.length() * sizeof(WCHAR));
1077
1078 Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, (ULONG)bcslen, nullptr, 0);
1079
1080 free(bcs);
1081
1082 if (!NT_SUCCESS(Status))
1083 throw ntstatus_error(Status);
1084
1085 return S_OK;
1086 } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 1) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, RECV_VERBA))) {
1088 wstring t;
1090
1091 GetModuleFileNameW(module, dll, sizeof(dll) / sizeof(WCHAR));
1092
1093 t = L"\"";
1094 t += dll;
1095 t += L"\",RecvSubvolGUI ";
1096 t += path;
1097
1098 RtlZeroMemory(&sei, sizeof(sei));
1099
1100 sei.cbSize = sizeof(sei);
1101 sei.hwnd = pici->hwnd;
1102 sei.lpVerb = L"runas";
1103 sei.lpFile = L"rundll32.exe";
1104 sei.lpParameters = t.c_str();
1105 sei.nShow = SW_SHOW;
1107
1108 if (!ShellExecuteExW(&sei))
1109 throw last_error(GetLastError());
1110
1112 CloseHandle(sei.hProcess);
1113
1114 return S_OK;
1115 } else if ((IS_INTRESOURCE(pici->lpVerb) && (ULONG_PTR)pici->lpVerb == 2) || (!IS_INTRESOURCE(pici->lpVerb) && !strcmp(pici->lpVerb, REFLINK_VERBA))) {
1116 HDROP hdrop;
1117
1119 return S_OK;
1120
1121 if (!OpenClipboard(pici->hwnd))
1122 throw last_error(GetLastError());
1123
1124 try {
1125 hdrop = (HDROP)GetClipboardData(CF_HDROP);
1126
1127 if (hdrop) {
1128 HANDLE lh;
1129
1130 lh = GlobalLock(hdrop);
1131
1132 if (lh) {
1133 try {
1134 ULONG num_files, i;
1135 WCHAR fn[MAX_PATH];
1136
1137 num_files = DragQueryFileW(hdrop, 0xFFFFFFFF, nullptr, 0);
1138
1139 for (i = 0; i < num_files; i++) {
1140 if (DragQueryFileW(hdrop, i, fn, sizeof(fn) / sizeof(WCHAR))) {
1141 reflink_copy(pici->hwnd, fn, pici->lpDirectoryW);
1142 }
1143 }
1144 } catch (...) {
1145 GlobalUnlock(lh);
1146 throw;
1147 }
1148
1149 GlobalUnlock(lh);
1150 }
1151 }
1152 } catch (...) {
1154 throw;
1155 }
1156
1158
1159 return S_OK;
1160 }
1161 }
1162 } catch (const exception& e) {
1163 error_message(pici->hwnd, e.what());
1164 }
1165
1166 return E_FAIL;
1167}
1168
1170 if (ignore)
1171 return E_INVALIDARG;
1172
1173 if (idCmd != 0)
1174 return E_INVALIDARG;
1175
1176 if (!bg) {
1177 if (idCmd == 0) {
1178 switch (uFlags) {
1179 case GCS_HELPTEXTA:
1181 return S_OK;
1182 else
1183 return E_FAIL;
1184
1185 case GCS_HELPTEXTW:
1187 return S_OK;
1188 else
1189 return E_FAIL;
1190
1191 case GCS_VALIDATEA:
1192 case GCS_VALIDATEW:
1193 return S_OK;
1194
1195 case GCS_VERBA:
1196 return StringCchCopyA(pszName, cchMax, SNAPSHOT_VERBA);
1197
1198 case GCS_VERBW:
1200
1201 default:
1202 return E_INVALIDARG;
1203 }
1204 } else if (idCmd == 1) {
1205 switch (uFlags) {
1206 case GCS_HELPTEXTA:
1208 return S_OK;
1209 else
1210 return E_FAIL;
1211
1212 case GCS_HELPTEXTW:
1214 return S_OK;
1215 else
1216 return E_FAIL;
1217
1218 case GCS_VALIDATEA:
1219 case GCS_VALIDATEW:
1220 return S_OK;
1221
1222 case GCS_VERBA:
1223 return StringCchCopyA(pszName, cchMax, SEND_VERBA);
1224
1225 case GCS_VERBW:
1227
1228 default:
1229 return E_INVALIDARG;
1230 }
1231 } else
1232 return E_INVALIDARG;
1233 } else {
1234 if (idCmd == 0) {
1235 switch (uFlags) {
1236 case GCS_HELPTEXTA:
1238 return S_OK;
1239 else
1240 return E_FAIL;
1241
1242 case GCS_HELPTEXTW:
1244 return S_OK;
1245 else
1246 return E_FAIL;
1247
1248 case GCS_VALIDATEA:
1249 case GCS_VALIDATEW:
1250 return S_OK;
1251
1252 case GCS_VERBA:
1253 return StringCchCopyA(pszName, cchMax, NEW_SUBVOL_VERBA);
1254
1255 case GCS_VERBW:
1257
1258 default:
1259 return E_INVALIDARG;
1260 }
1261 } else if (idCmd == 1) {
1262 switch (uFlags) {
1263 case GCS_HELPTEXTA:
1265 return S_OK;
1266 else
1267 return E_FAIL;
1268
1269 case GCS_HELPTEXTW:
1271 return S_OK;
1272 else
1273 return E_FAIL;
1274
1275 case GCS_VALIDATEA:
1276 case GCS_VALIDATEW:
1277 return S_OK;
1278
1279 case GCS_VERBA:
1280 return StringCchCopyA(pszName, cchMax, RECV_VERBA);
1281
1282 case GCS_VERBW:
1284
1285 default:
1286 return E_INVALIDARG;
1287 }
1288 } else if (idCmd == 2) {
1289 switch (uFlags) {
1290 case GCS_HELPTEXTA:
1292 return S_OK;
1293 else
1294 return E_FAIL;
1295
1296 case GCS_HELPTEXTW:
1298 return S_OK;
1299 else
1300 return E_FAIL;
1301
1302 case GCS_VALIDATEA:
1303 case GCS_VALIDATEW:
1304 return S_OK;
1305
1306 case GCS_VERBA:
1307 return StringCchCopyA(pszName, cchMax, REFLINK_VERBA);
1308
1309 case GCS_VERBW:
1311
1312 default:
1313 return E_INVALIDARG;
1314 }
1315 } else
1316 return E_INVALIDARG;
1317 }
1318}
1319
1320static void reflink_copy2(const wstring& srcfn, const wstring& destdir, const wstring& destname) {
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}
1645
1646extern "C" void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
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}
UINT cchMax
basic_streambuf< char, char_traits< char > > streambuf
Definition: _iosfwd.h:123
basic_ostream< _CharT, _Traits > &_STLP_CALL endl(basic_ostream< _CharT, _Traits > &__os)
Definition: _ostream.h:357
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
unsigned int dir
Definition: maze.c:112
LONG NTSTATUS
Definition: precomp.h:26
#define CF_HDROP
Definition: constants.h:410
const GUID IID_IUnknown
#define FSCTL_BTRFS_CREATE_SNAPSHOT
Definition: btrfsioctl.h:9
#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
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:8
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:7
STGMEDIUM stgm
Definition: contextmenu.h:79
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj)
Definition: contextmenu.cpp:70
virtual HRESULT __stdcall GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
virtual HRESULT __stdcall QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
virtual HRESULT __stdcall InvokeCommand(LPCMINVOKECOMMANDINFO pici)
void reflink_copy(HWND hwnd, const WCHAR *fn, const WCHAR *dir)
virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
Definition: contextmenu.cpp:85
ULONG __stdcall AddRef()
Definition: contextmenu.h:51
#define NEW_SUBVOL_VERBA
Definition: contextmenu.cpp:49
static void reflink_copy2(const wstring &srcfn, const wstring &destdir, const wstring &destname)
static void InitBitmapInfo(BITMAPINFO *pbmi, ULONG cbInfo, LONG cx, LONG cy, WORD bpp)
#define REFLINK_VERBW
Definition: contextmenu.cpp:54
#define NEW_SUBVOL_VERBW
Definition: contextmenu.cpp:50
#define RECV_VERBA
Definition: contextmenu.cpp:55
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
static void create_snapshot(HWND hwnd, const wstring &fn)
#define SNAPSHOT_VERBW
Definition: contextmenu.cpp:52
#define REFLINK_VERBA
Definition: contextmenu.cpp:53
#define SNAPSHOT_VERBA
Definition: contextmenu.cpp:51
static bool get_volume_path_parent(const WCHAR *fn, WCHAR *volpath, ULONG volpathlen)
#define RECV_VERBW
Definition: contextmenu.cpp:56
void CALLBACK ReflinkCopyW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow)
#define SEND_VERBA
Definition: contextmenu.cpp:57
static bool show_reflink_paste(const wstring &path)
static void path_strip_path(wstring &path)
static void path_remove_file(wstring &path)
#define SEND_VERBW
Definition: contextmenu.cpp:58
static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP *phBmp)
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
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 NT_SUCCESS(StatCode)
Definition: apphelp.c:33
DWORD bpp
Definition: surface.c:185
void error_message(HWND hwnd, const char *msg)
Definition: main.cpp:783
void wstring_sprintf(wstring &s, wstring fmt,...)
Definition: main.cpp:225
void command_line_to_args(LPWSTR cmdline, vector< wstring > &args)
Definition: main.cpp:645
#define IDS_RECV_SUBVOL
Definition: resource.h:130
#define IDS_CREATE_SNAPSHOT_HELP_TEXT
Definition: resource.h:12
#define IDS_NEW_SUBVOL_FILENAME
Definition: resource.h:9
#define IDS_SEND_SUBVOL
Definition: resource.h:176
#define IDS_SNAPSHOT_FILENAME
Definition: resource.h:14
#define IDS_CREATE_SNAPSHOT
Definition: resource.h:10
#define IDS_NEW_SUBVOL_HELP_TEXT
Definition: resource.h:6
#define IDS_REFLINK_PASTE_HELP
Definition: resource.h:129
#define IDS_RECV_SUBVOL_HELP
Definition: resource.h:131
#define IDS_CANT_REFLINK_DIFFERENT_FS
Definition: resource.h:204
#define IDS_SEND_SUBVOL_HELP
Definition: resource.h:177
#define IDS_REFLINK_PASTE
Definition: resource.h:128
#define IDS_NEW_SUBVOL
Definition: resource.h:7
UINT uFlags
Definition: api.c:59
#define CloseHandle
Definition: compat.h:739
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define CALLBACK
Definition: compat.h:35
#define FILE_SHARE_READ
Definition: compat.h:136
static const WCHAR *const ext[]
Definition: module.c:53
BOOL WINAPI CreateDirectoryExW(IN LPCWSTR lpTemplateDirectory, IN LPCWSTR lpNewDirectory, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:193
BOOL WINAPI GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation)
Definition: fileinfo.c:458
BOOL WINAPI SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:948
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
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
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
VOID WINAPI GetLocalTime(OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:286
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define swprintf
Definition: precomp.h:40
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
#define BI_RGB
Definition: precomp.h:56
#define INFINITE
Definition: serial.h:102
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
@ 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
Status
Definition: gdiplustypes.h:25
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble t
Definition: gl.h:2047
GLdouble n
Definition: glext.h:7729
GLsizei stride
Definition: glext.h:5848
GLuint buffer
Definition: glext.h:5915
GLint namelen
Definition: glext.h:7232
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLfloat GLfloat p
Definition: glext.h:8902
GLuint GLuint num
Definition: glext.h:9618
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLintptr offset
Definition: glext.h:5920
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:7723
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
LPVOID NTAPI GlobalLock(HGLOBAL hMem)
Definition: heapmem.c:755
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190
#define ss
Definition: i386-dis.c:441
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
REFIID riid
Definition: atlbase.h:39
struct IContextMenu::tagCMInvokeCommandInfoEx * LPCMINVOKECOMMANDINFOEX
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define cerr
Definition: iostream.cpp:39
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
if(dx< 0)
Definition: linetemp.h:194
static struct msdos_boot_sector bs
Definition: mkdosfs.c:539
__u16 time
Definition: mkdosfs.c:8
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
#define CREATE_NEW
Definition: disk.h:69
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HINSTANCE hinst
Definition: edit.c:551
static HDC
Definition: imagelist.c:88
static HICON
Definition: imagelist.c:80
static HMODULE dll
Definition: str.c:188
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
static char * dest
Definition: rtl.c:135
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
static short search(int val, const short *table, int size)
Definition: msg711.c:255
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
BYTE uint8_t
Definition: msvideo1.c:66
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: muireg.c:10
unsigned int UINT
Definition: ndis.h:50
#define uint16_t
Definition: nsiface.idl:60
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
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_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_ADD_FILE
Definition: nt_native.h:632
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)
_Must_inspect_result_ _Out_ LPSIZE psize
Definition: ntgdi.h:1569
_In_ HBITMAP _In_ UINT _In_ UINT _Inout_ LPBITMAPINFO pbmi
Definition: ntgdi.h:2780
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
wchar_t * STRSAFE_LPWSTR
Definition: ntstrsafe.h:53
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1454
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define REFIID
Definition: guiddef.h:118
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:746
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:747
#define FSCTL_SET_SPARSE
Definition: winioctl.h:749
const WCHAR * str
#define offsetof(TYPE, MEMBER)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
int const char int stream_size
Definition: zlib.h:814
#define memset(x, y, z)
Definition: compat.h:39
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define FileStandardInformation
Definition: propsheet.cpp:61
#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
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2428
HRESULT hr
Definition: shlfolder.c:183
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCchCopyA(STRSAFE_LPSTR pszDest, size_t cchDest, STRSAFE_LPCSTR pszSrc)
Definition: strsafe.h:145
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
LPCWSTR lpParameters
Definition: shellapi.h:334
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: match.c:390
int length
Definition: match.c:394
Definition: uimain.c:89
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
Definition: main.c:439
Definition: format.c:58
Definition: name.c:39
USHORT ReparseDataLength
Definition: contextmenu.cpp:62
Definition: parse.h:23
USHORT biBitCount
Definition: precomp.h:46
ULONG biCompression
Definition: precomp.h:47
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
LPWSTR dwTypeData
Definition: winuser.h:3272
LONG cx
Definition: windef.h:334
LONG cy
Definition: windef.h:335
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define __stdcall
Definition: typedefs.h:25
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
LONGLONG QuadPart
Definition: typedefs.h:114
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
static HMENU hmenu
Definition: win.c:66
#define ZeroMemory
Definition: winbase.h:1737
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define E_NOINTERFACE
Definition: winerror.h:2364
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define ERROR_FILE_EXISTS
Definition: winerror.h:165
#define DIB_RGB_COLORS
Definition: wingdi.h:367
int WINAPI ReleaseDC(_In_opt_ HWND, _In_ HDC)
#define MIIM_STRING
Definition: winuser.h:730
#define MIIM_ID
Definition: winuser.h:725
#define IMAGE_ICON
Definition: winuser.h:212
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
BOOL WINAPI InsertMenuW(_In_ HMENU, _In_ UINT, _In_ UINT, _In_ UINT_PTR, _In_opt_ LPCWSTR)
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE hInst, _In_ LPCWSTR name, _In_ UINT type, _In_ int cx, _In_ int cy, _In_ UINT fuLoad)
Definition: cursoricon.c:2289
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
#define SM_CYSMICON
Definition: winuser.h:1016
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPSTR lpBuffer, _In_ int cchBufferMax)
HANDLE WINAPI GetClipboardData(_In_ UINT)
#define SM_CXSMICON
Definition: winuser.h:1015
#define MIIM_BITMAP
Definition: winuser.h:731
#define MF_BYPOSITION
Definition: winuser.h:203
HDC WINAPI GetDC(_In_opt_ HWND)
#define LR_DEFAULTCOLOR
Definition: winuser.h:1090
#define SW_SHOW
Definition: winuser.h:778
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
int WINAPI GetSystemMetrics(_In_ int)
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
struct tagMENUITEMINFOW MENUITEMINFOW
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned char BYTE
Definition: xxhash.c:193