ReactOS 0.4.15-dev-7953-g1f49173
BtrfsContextMenu Class Reference

#include <contextmenu.h>

Inheritance diagram for BtrfsContextMenu:
Collaboration diagram for BtrfsContextMenu:

Public Member Functions

 BtrfsContextMenu ()
 
virtual ~BtrfsContextMenu ()
 
HRESULT __stdcall QueryInterface (REFIID riid, void **ppObj)
 
ULONG __stdcall AddRef ()
 
ULONG __stdcall Release ()
 
virtual HRESULT __stdcall Initialize (PCIDLIST_ABSOLUTE pidlFolder, IDataObject *pdtobj, HKEY hkeyProgID)
 
virtual HRESULT __stdcall QueryContextMenu (HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
 
virtual HRESULT __stdcall InvokeCommand (LPCMINVOKECOMMANDINFO pici)
 
virtual HRESULT __stdcall GetCommandString (UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
 
HRESULT Initialize ([in] PCIDLIST_ABSOLUTE pidlFolder, [in] IDataObject *pdtobj, [in] HKEY hkeyProgID)
 
HRESULT QueryInterface ([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
 
ULONG AddRef ()
 
ULONG Release ()
 

Private Member Functions

void reflink_copy (HWND hwnd, const WCHAR *fn, const WCHAR *dir)
 
void get_uac_icon ()
 
HRESULT QueryContextMenu ([in] HMENU hmenu, [in] UINT indexMenu, [in] UINT idCmdFirst, [in] UINT idCmdLast, [in] UINT uFlags)
 
HRESULT InvokeCommand ([in] LPCMINVOKECOMMANDINFO lpici)
 
HRESULT GetCommandString ([in] UINT_PTR idCmd, [in] UINT uType, [out] UINT *pwReserved, [out, size_is(cchMax)] LPSTR pszName, [in] UINT cchMax)
 
HRESULT QueryInterface ([in] REFIID riid, [out, iid_is(riid)] void **ppvObject)
 
ULONG AddRef ()
 
ULONG Release ()
 

Private Attributes

LONG refcount
 
bool ignore
 
bool allow_snapshot
 
bool bg
 
wstring path
 
STGMEDIUM stgm
 
bool stgm_set
 
HBITMAP uacicon
 

Additional Inherited Members

- Public Types inherited from IShellExtInit
typedef IShellExtInitLPSHELLEXTINIT
 
- Public Types inherited from IUnknown
typedef IUnknownLPUNKNOWN
 
- Private Types inherited from IContextMenu
typedef IContextMenuLPCONTEXTMENU
 
typedef struct IContextMenu::tagCMINVOKECOMMANDINFO CMINVOKECOMMANDINFO
 
typedef struct IContextMenu::tagCMINVOKECOMMANDINFOLPCMINVOKECOMMANDINFO
 
typedef struct IContextMenu::tagCMInvokeCommandInfoEx CMINVOKECOMMANDINFOEX
 
typedef struct IContextMenu::tagCMInvokeCommandInfoExLPCMINVOKECOMMANDINFOEX
 
- Private Types inherited from IUnknown
typedef IUnknownLPUNKNOWN
 
- Static Private Attributes inherited from IContextMenu
static const WCHAR CMDSTR_NEWFOLDERW [] = {'N','e','w','F','o','l','d','e','r',0}
 
static const WCHAR CMDSTR_VIEWLISTW [] = {'V','i','e','w','L','i','s','t',0}
 
static const WCHAR CMDSTR_VIEWDETAILSW [] = {'V','i','e','w','D','e','t','a','i','l','s',0}
 

Detailed Description

Definition at line 24 of file contextmenu.h.

Constructor & Destructor Documentation

◆ BtrfsContextMenu()

BtrfsContextMenu::BtrfsContextMenu ( )
inline

Definition at line 26 of file contextmenu.h.

26 {
27 refcount = 0;
28 ignore = true;
29 stgm_set = false;
30 uacicon = nullptr;
31 allow_snapshot = false;
33 }
#define InterlockedIncrement
Definition: armddk.h:53
LONG objs_loaded
Definition: main.cpp:48

◆ ~BtrfsContextMenu()

virtual BtrfsContextMenu::~BtrfsContextMenu ( )
inlinevirtual

Definition at line 35 of file contextmenu.h.

35 {
36 if (stgm_set) {
37 GlobalUnlock(stgm.hGlobal);
39 }
40
41 if (uacicon)
43
45 }
#define InterlockedDecrement
Definition: armddk.h:52
STGMEDIUM stgm
Definition: contextmenu.h:79
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
pKey DeleteObject()
BOOL NTAPI GlobalUnlock(HGLOBAL hMem)
Definition: heapmem.c:1190

Member Function Documentation

◆ AddRef()

ULONG __stdcall BtrfsContextMenu::AddRef ( void  )
inline

Implements IUnknown.

Definition at line 51 of file contextmenu.h.

51 {
53 }

Referenced by QueryInterface().

◆ get_uac_icon()

void BtrfsContextMenu::get_uac_icon ( )
private

Definition at line 294 of file contextmenu.cpp.

294 {
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}
static HRESULT Create32BitHBITMAP(HDC hdc, const SIZE *psize, void **ppvBits, HBITMAP *phBmp)
HMODULE WINAPI GetModuleHandleW(LPCWSTR lpModuleName)
Definition: loader.c:838
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizei stride
Definition: glext.h:5848
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
#define SUCCEEDED(hr)
Definition: intsafe.h:50
static HICON
Definition: imagelist.c:84
unsigned int UINT
Definition: ndis.h:50
#define L(x)
Definition: ntvdm.h:50
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
HRESULT hr
Definition: shlfolder.c:183
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: uimain.c:89
Definition: main.c:439
#define IMAGE_ICON
Definition: winuser.h:212
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:2203
#define SM_CYSMICON
Definition: winuser.h:1013
#define SM_CXSMICON
Definition: winuser.h:1012
#define LR_DEFAULTCOLOR
Definition: winuser.h:1087
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
int WINAPI GetSystemMetrics(_In_ int)
unsigned char BYTE
Definition: xxhash.c:193

Referenced by QueryContextMenu().

◆ GetCommandString()

HRESULT __stdcall BtrfsContextMenu::GetCommandString ( UINT_PTR  idCmd,
UINT  uFlags,
UINT pwReserved,
LPSTR  pszName,
UINT  cchMax 
)
virtual

Implements IContextMenu.

Definition at line 1169 of file contextmenu.cpp.

1169 {
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}
UINT cchMax
#define NEW_SUBVOL_VERBA
Definition: contextmenu.cpp:49
#define REFLINK_VERBW
Definition: contextmenu.cpp:54
#define NEW_SUBVOL_VERBW
Definition: contextmenu.cpp:50
#define RECV_VERBA
Definition: contextmenu.cpp:55
#define SNAPSHOT_VERBW
Definition: contextmenu.cpp:52
#define REFLINK_VERBA
Definition: contextmenu.cpp:53
#define SNAPSHOT_VERBA
Definition: contextmenu.cpp:51
#define RECV_VERBW
Definition: contextmenu.cpp:56
#define SEND_VERBA
Definition: contextmenu.cpp:57
#define SEND_VERBW
Definition: contextmenu.cpp:58
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_FAIL
Definition: ddrawi.h:102
#define IDS_CREATE_SNAPSHOT_HELP_TEXT
Definition: resource.h:12
#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_SEND_SUBVOL_HELP
Definition: resource.h:177
UINT uFlags
Definition: api.c:59
#define S_OK
Definition: intsafe.h:52
wchar_t * STRSAFE_LPWSTR
Definition: ntstrsafe.h:53
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
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int WINAPI LoadStringA(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPSTR lpBuffer, _In_ int cchBufferMax)
WCHAR * LPWSTR
Definition: xmlstorage.h:184

◆ Initialize()

HRESULT __stdcall BtrfsContextMenu::Initialize ( PCIDLIST_ABSOLUTE  pidlFolder,
IDataObject pdtobj,
HKEY  hkeyProgID 
)
virtual

Implements IShellExtInit.

Definition at line 85 of file contextmenu.cpp.

85 {
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}
LONG NTSTATUS
Definition: precomp.h:26
#define CF_HDROP
Definition: constants.h:410
#define FSCTL_BTRFS_GET_FILE_IDS
Definition: btrfsioctl.h:7
static void path_remove_file(wstring &path)
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define OPEN_EXISTING
Definition: compat.h:775
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
#define CreateFileW
Definition: compat.h:741
#define FILE_SHARE_READ
Definition: compat.h:136
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
Status
Definition: gdiplustypes.h:25
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
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
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
#define FAILED(hr)
Definition: intsafe.h:51
#define FILE_FLAG_BACKUP_SEMANTICS
Definition: disk.h:41
static PIO_STATUS_BLOCK iosb
Definition: file.c:98
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_DELETE
Definition: nt_native.h:682
#define FILE_TRAVERSE
Definition: nt_native.h:643
#define FILE_ADD_SUBDIRECTORY
Definition: nt_native.h:635
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1353
static GLenum _GLUfuncptr fn
Definition: wgl_font.c:159
__wchar_t WCHAR
Definition: xmlstorage.h:180

◆ InvokeCommand()

HRESULT __stdcall BtrfsContextMenu::InvokeCommand ( LPCMINVOKECOMMANDINFO  pici)
virtual

Implements IContextMenu.

Definition at line 954 of file contextmenu.cpp.

954 {
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}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define FSCTL_BTRFS_CREATE_SUBVOL
Definition: btrfsioctl.h:8
void reflink_copy(HWND hwnd, const WCHAR *fn, const WCHAR *dir)
static void create_snapshot(HWND hwnd, const wstring &fn)
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
void error_message(HWND hwnd, const char *msg)
Definition: main.cpp:783
#define IDS_NEW_SUBVOL_FILENAME
Definition: resource.h:9
#define CloseHandle
Definition: compat.h:739
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
DWORD WINAPI GetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize)
Definition: loader.c:600
#define swprintf
Definition: precomp.h:40
#define INFINITE
Definition: serial.h:102
GLdouble GLdouble t
Definition: gl.h:2047
GLuint buffer
Definition: glext.h:5915
GLuint GLuint num
Definition: glext.h:9618
struct IContextMenu::tagCMInvokeCommandInfoEx * LPCMINVOKECOMMANDINFOEX
#define e
Definition: ke_i.h:82
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static HMODULE dll
Definition: str.c:188
static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
Definition: muireg.c:10
#define uint16_t
Definition: nsiface.idl:60
#define offsetof(TYPE, MEMBER)
#define SEE_MASK_NOCLOSEPROCESS
Definition: shellapi.h:31
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2391
LPCWSTR lpParameters
Definition: shellapi.h:333
Definition: name.c:39
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define IS_INTRESOURCE(i)
Definition: winuser.h:580
BOOL WINAPI CloseClipboard(void)
Definition: ntwrapper.h:178
BOOL WINAPI OpenClipboard(_In_opt_ HWND)
HANDLE WINAPI GetClipboardData(_In_ UINT)
#define SW_SHOW
Definition: winuser.h:775
BOOL WINAPI IsClipboardFormatAvailable(_In_ UINT)

◆ QueryContextMenu()

HRESULT __stdcall BtrfsContextMenu::QueryContextMenu ( HMENU  hmenu,
UINT  indexMenu,
UINT  idCmdFirst,
UINT  idCmdLast,
UINT  uFlags 
)
virtual

Implements IContextMenu.

Definition at line 339 of file contextmenu.cpp.

339 {
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}
static bool show_reflink_paste(const wstring &path)
#define IDS_RECV_SUBVOL
Definition: resource.h:130
#define IDS_SEND_SUBVOL
Definition: resource.h:176
#define IDS_CREATE_SNAPSHOT
Definition: resource.h:10
#define IDS_REFLINK_PASTE
Definition: resource.h:128
#define IDS_NEW_SUBVOL
Definition: resource.h:7
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
const WCHAR * str
#define memset(x, y, z)
Definition: compat.h:39
LPWSTR dwTypeData
Definition: winuser.h:3269
static HMENU hmenu
Definition: win.c:66
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define MIIM_STRING
Definition: winuser.h:727
#define MIIM_ID
Definition: winuser.h:722
BOOL WINAPI InsertMenuW(_In_ HMENU, _In_ UINT, _In_ UINT, _In_ UINT_PTR, _In_opt_ LPCWSTR)
#define MIIM_BITMAP
Definition: winuser.h:728
#define MF_BYPOSITION
Definition: winuser.h:203
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
struct tagMENUITEMINFOW MENUITEMINFOW

◆ QueryInterface()

HRESULT __stdcall BtrfsContextMenu::QueryInterface ( REFIID  riid,
void **  ppObj 
)

Implements IUnknown.

Definition at line 70 of file contextmenu.cpp.

70 {
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}
const GUID IID_IUnknown
ULONG __stdcall AddRef()
Definition: contextmenu.h:51
REFIID riid
Definition: atlbase.h:39
#define E_NOINTERFACE
Definition: winerror.h:2364

Referenced by Factory::CreateInstance().

◆ reflink_copy()

void BtrfsContextMenu::reflink_copy ( HWND  hwnd,
const WCHAR fn,
const WCHAR dir 
)
private

Definition at line 538 of file contextmenu.cpp.

538 {
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;
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}
unsigned int dir
Definition: maze.c:112
#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
static uint64_t __inline sector_align(uint64_t n, uint64_t a)
static bool get_volume_path_parent(const WCHAR *fn, WCHAR *volpath, ULONG volpathlen)
#define ERROR_MORE_DATA
Definition: dderror.h:13
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
UINT64 uint64_t
Definition: types.h:77
#define IDS_CANT_REFLINK_DIFFERENT_FS
Definition: resource.h:204
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define GENERIC_READ
Definition: compat.h:135
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 SetFileTime(IN HANDLE hFile, CONST FILETIME *lpCreationTime OPTIONAL, CONST FILETIME *lpLastAccessTime OPTIONAL, CONST FILETIME *lpLastWriteTime OPTIONAL)
Definition: fileinfo.c:948
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
BOOL WINAPI GetVolumePathNameW(IN LPCWSTR lpszFileName, IN LPWSTR lpszVolumePathName, IN DWORD cchBufferLength)
Definition: volume.c:815
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
@ FileEndOfFileInformation
Definition: from_kernel.h:81
@ FileStreamInformation
Definition: from_kernel.h:83
@ FileBasicInformation
Definition: from_kernel.h:65
@ FileDispositionInformation
Definition: from_kernel.h:74
#define FILE_OPEN_REPARSE_POINT
Definition: from_kernel.h:46
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLintptr offset
Definition: glext.h:5920
#define ss
Definition: i386-dis.c:441
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
if(dx< 0)
Definition: linetemp.h:194
#define ERROR_ALREADY_EXISTS
Definition: disk.h:80
#define CREATE_NEW
Definition: disk.h:69
static char * dest
Definition: rtl.c:135
static short search(int val, const short *table, int size)
Definition: msg711.c:255
BYTE uint8_t
Definition: msvideo1.c:66
NTSYSAPI NTSTATUS NTAPI NtSetInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
Definition: iofunc.c:3096
NTSYSAPI NTSTATUS NTAPI NtQueryInformationFile(IN HANDLE hFile, OUT PIO_STATUS_BLOCK pIoStatusBlock, OUT PVOID FileInformationBuffer, IN ULONG FileInformationBufferLength, IN FILE_INFORMATION_CLASS FileInfoClass)
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define DELETE
Definition: nt_native.h:57
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_ADD_FILE
Definition: nt_native.h:632
#define FILE_ATTRIBUTE_SPARSE_FILE
Definition: ntifs_ex.h:380
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define SUBVOL_ROOT_INODE
Definition: propsheet.cpp:42
#define FileStandardInformation
Definition: propsheet.cpp:61
#define BTRFS_INODE_COMPRESS
Definition: propsheet.h:87
#define FSCTL_GET_REPARSE_POINT
Definition: winioctl.h:97
#define FSCTL_SET_REPARSE_POINT
Definition: winioctl.h:98
#define FSCTL_SET_SPARSE
Definition: winioctl.h:100
_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 FSCTL_SET_INTEGRITY_INFORMATION
Definition: shellext.h:222
#define FSCTL_GET_INTEGRITY_INFORMATION
Definition: shellext.h:221
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE
Definition: shellext.h:205
#define BTRFS_TYPE_SOCKET
Definition: shellext.h:90
#define BTRFS_TYPE_FIFO
Definition: shellext.h:89
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
#define BTRFS_TYPE_CHARDEV
Definition: shellext.h:87
#define BTRFS_TYPE_BLOCKDEV
Definition: shellext.h:88
LARGE_INTEGER ByteCount
Definition: shellext.h:202
LARGE_INTEGER SourceFileOffset
Definition: shellext.h:200
LARGE_INTEGER TargetFileOffset
Definition: shellext.h:201
DWORD dwHighDateTime
Definition: mapidefs.h:66
DWORD dwLowDateTime
Definition: mapidefs.h:65
uint64_t st_rdev
Definition: btrfsioctl.h:77
uint64_t flags
Definition: btrfsioctl.h:78
uint64_t inode
Definition: btrfsioctl.h:71
uint8_t compression_type
Definition: btrfsioctl.h:83
uint64_t inode
Definition: btrfsioctl.h:237
WCHAR name[1]
Definition: btrfsioctl.h:241
uint16_t namelen
Definition: btrfsioctl.h:240
uint64_t st_rdev
Definition: btrfsioctl.h:239
uint8_t type
Definition: btrfsioctl.h:238
uint8_t compression_type
Definition: btrfsioctl.h:98
BOOL compression_type_changed
Definition: btrfsioctl.h:99
USHORT ReparseDataLength
Definition: contextmenu.cpp:62
Definition: parse.h:23
LONGLONG QuadPart
Definition: typedefs.h:114
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
#define ERROR_FILE_EXISTS
Definition: winerror.h:165

Referenced by InvokeCommand(), and reflink_copy().

◆ Release()

ULONG __stdcall BtrfsContextMenu::Release ( void  )
inline

Implements IUnknown.

Definition at line 55 of file contextmenu.h.

55 {
57
58 if (rc == 0)
59 delete this;
60
61 return rc;
62 }
long LONG
Definition: pedump.c:60

Member Data Documentation

◆ allow_snapshot

bool BtrfsContextMenu::allow_snapshot
private

Definition at line 76 of file contextmenu.h.

Referenced by BtrfsContextMenu(), Initialize(), InvokeCommand(), and QueryContextMenu().

◆ bg

bool BtrfsContextMenu::bg
private

Definition at line 77 of file contextmenu.h.

Referenced by GetCommandString(), Initialize(), InvokeCommand(), and QueryContextMenu().

◆ ignore

bool BtrfsContextMenu::ignore
private

◆ path

wstring BtrfsContextMenu::path
private

Definition at line 78 of file contextmenu.h.

Referenced by InvokeCommand().

◆ refcount

LONG BtrfsContextMenu::refcount
private

Definition at line 75 of file contextmenu.h.

Referenced by AddRef(), BtrfsContextMenu(), and Release().

◆ stgm

STGMEDIUM BtrfsContextMenu::stgm
private

Definition at line 79 of file contextmenu.h.

Referenced by Initialize(), InvokeCommand(), and ~BtrfsContextMenu().

◆ stgm_set

bool BtrfsContextMenu::stgm_set
private

Definition at line 80 of file contextmenu.h.

Referenced by BtrfsContextMenu(), Initialize(), InvokeCommand(), and ~BtrfsContextMenu().

◆ uacicon

HBITMAP BtrfsContextMenu::uacicon
private

Definition at line 81 of file contextmenu.h.

Referenced by BtrfsContextMenu(), get_uac_icon(), QueryContextMenu(), and ~BtrfsContextMenu().


The documentation for this class was generated from the following files: