mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 02:10:07 +00:00
[SHELLBTRFS] Upgrade to 1.1
CORE-15452
This commit is contained in:
parent
eb7fbc253f
commit
7b718d3627
|
@ -3,6 +3,10 @@ set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
|
||||||
remove_definitions(-D_WIN32_WINNT=0x502)
|
remove_definitions(-D_WIN32_WINNT=0x502)
|
||||||
add_definitions(-D_WIN32_WINNT=0x603)
|
add_definitions(-D_WIN32_WINNT=0x603)
|
||||||
|
|
||||||
|
if(NOT MSVC)
|
||||||
|
add_compile_flags_language("-std=c++11" "CXX")
|
||||||
|
endif()
|
||||||
|
|
||||||
include_directories(${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs)
|
include_directories(${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs)
|
||||||
|
|
||||||
spec2def(shellbtrfs.dll shellbtrfs.spec)
|
spec2def(shellbtrfs.dll shellbtrfs.spec)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,12 +26,12 @@
|
||||||
|
|
||||||
class BtrfsBalance {
|
class BtrfsBalance {
|
||||||
public:
|
public:
|
||||||
BtrfsBalance(WCHAR* drive, BOOL RemoveDevice = FALSE, BOOL ShrinkDevice = FALSE) {
|
BtrfsBalance(const wstring& drive, bool RemoveDevice = false, bool ShrinkDevice = false) {
|
||||||
removing = FALSE;
|
removing = false;
|
||||||
devices = NULL;
|
devices = nullptr;
|
||||||
called_from_RemoveDevice = RemoveDevice;
|
called_from_RemoveDevice = RemoveDevice;
|
||||||
called_from_ShrinkDevice = ShrinkDevice;
|
called_from_ShrinkDevice = ShrinkDevice;
|
||||||
wcscpy(fn, drive);
|
fn = drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowBalance(HWND hwndDlg);
|
void ShowBalance(HWND hwndDlg);
|
||||||
|
@ -39,22 +39,22 @@ public:
|
||||||
INT_PTR CALLBACK BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ShowBalanceOptions(HWND hwndDlg, UINT8 type);
|
void ShowBalanceOptions(HWND hwndDlg, uint8_t type);
|
||||||
void SaveBalanceOpts(HWND hwndDlg);
|
void SaveBalanceOpts(HWND hwndDlg);
|
||||||
void StartBalance(HWND hwndDlg);
|
void StartBalance(HWND hwndDlg);
|
||||||
void RefreshBalanceDlg(HWND hwndDlg, BOOL first);
|
void RefreshBalanceDlg(HWND hwndDlg, bool first);
|
||||||
void PauseBalance(HWND hwndDlg);
|
void PauseBalance(HWND hwndDlg);
|
||||||
void StopBalance(HWND hwndDlg);
|
void StopBalance(HWND hwndDlg);
|
||||||
|
|
||||||
UINT32 balance_status;
|
uint32_t balance_status;
|
||||||
btrfs_balance_opts data_opts, metadata_opts, system_opts;
|
btrfs_balance_opts data_opts, metadata_opts, system_opts;
|
||||||
UINT8 opts_type;
|
uint8_t opts_type;
|
||||||
btrfs_query_balance bqb;
|
btrfs_query_balance bqb;
|
||||||
BOOL cancelling;
|
bool cancelling;
|
||||||
BOOL removing;
|
bool removing;
|
||||||
BOOL shrinking;
|
bool shrinking;
|
||||||
WCHAR fn[MAX_PATH];
|
wstring fn;
|
||||||
btrfs_device* devices;
|
btrfs_device* devices;
|
||||||
BOOL readonly;
|
bool readonly;
|
||||||
BOOL called_from_RemoveDevice, called_from_ShrinkDevice;
|
bool called_from_RemoveDevice, called_from_ShrinkDevice;
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,10 +25,10 @@ class BtrfsContextMenu : public IShellExtInit, IContextMenu {
|
||||||
public:
|
public:
|
||||||
BtrfsContextMenu() {
|
BtrfsContextMenu() {
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
ignore = TRUE;
|
ignore = true;
|
||||||
stgm_set = FALSE;
|
stgm_set = false;
|
||||||
uacicon = NULL;
|
uacicon = nullptr;
|
||||||
allow_snapshot = FALSE;
|
allow_snapshot = false;
|
||||||
InterlockedIncrement(&objs_loaded);
|
InterlockedIncrement(&objs_loaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,13 +73,13 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
BOOL ignore, allow_snapshot;
|
bool ignore, allow_snapshot;
|
||||||
BOOL bg;
|
bool bg;
|
||||||
WCHAR path[MAX_PATH];
|
wstring path;
|
||||||
STGMEDIUM stgm;
|
STGMEDIUM stgm;
|
||||||
BOOL stgm_set;
|
bool stgm_set;
|
||||||
HBITMAP uacicon;
|
HBITMAP uacicon;
|
||||||
|
|
||||||
BOOL reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir);
|
void reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir);
|
||||||
void get_uac_icon();
|
void get_uac_icon();
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -28,8 +28,6 @@
|
||||||
#include <ndk/iotypes.h>
|
#include <ndk/iotypes.h>
|
||||||
#endif
|
#endif
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
#include "../btrfsioctl.h"
|
#include "../btrfsioctl.h"
|
||||||
#else
|
#else
|
||||||
|
@ -37,27 +35,27 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
std::wstring pnp_name;
|
wstring pnp_name;
|
||||||
std::wstring friendly_name;
|
wstring friendly_name;
|
||||||
std::wstring drive;
|
wstring drive;
|
||||||
std::wstring fstype;
|
wstring fstype;
|
||||||
ULONG disk_num;
|
ULONG disk_num;
|
||||||
ULONG part_num;
|
ULONG part_num;
|
||||||
UINT64 size;
|
uint64_t size;
|
||||||
BOOL has_parts;
|
bool has_parts;
|
||||||
BTRFS_UUID fs_uuid;
|
BTRFS_UUID fs_uuid;
|
||||||
BTRFS_UUID dev_uuid;
|
BTRFS_UUID dev_uuid;
|
||||||
BOOL ignore;
|
bool ignore;
|
||||||
BOOL multi_device;
|
bool multi_device;
|
||||||
BOOL is_disk;
|
bool is_disk;
|
||||||
} device;
|
} device;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const WCHAR* name;
|
const WCHAR* name;
|
||||||
const char* magic;
|
const char* magic;
|
||||||
ULONG magiclen;
|
ULONG magiclen;
|
||||||
UINT32 sboff;
|
uint32_t sboff;
|
||||||
UINT32 kboff;
|
uint32_t kboff;
|
||||||
} fs_identifier;
|
} fs_identifier;
|
||||||
|
|
||||||
// This list is compiled from information in libblkid, part of util-linux
|
// This list is compiled from information in libblkid, part of util-linux
|
||||||
|
@ -135,7 +133,7 @@ const static fs_identifier fs_ident[] = {
|
||||||
{ L"FAT", "\353", 1, 0, 0 },
|
{ L"FAT", "\353", 1, 0, 0 },
|
||||||
{ L"FAT", "\351", 1, 0, 0},
|
{ L"FAT", "\351", 1, 0, 0},
|
||||||
{ L"FAT", "\125\252", 2, 0x1fe, 0 },
|
{ L"FAT", "\125\252", 2, 0x1fe, 0 },
|
||||||
{ NULL, 0, 0, 0 }
|
{ nullptr, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
class BtrfsDeviceAdd {
|
class BtrfsDeviceAdd {
|
||||||
|
@ -152,18 +150,19 @@ private:
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
WCHAR* cmdline;
|
WCHAR* cmdline;
|
||||||
device* sel;
|
device* sel;
|
||||||
std::vector<device> device_list;
|
vector<device> device_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BtrfsDeviceResize {
|
class BtrfsDeviceResize {
|
||||||
public:
|
public:
|
||||||
INT_PTR CALLBACK DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
void ShowDialog(HWND hwnd, WCHAR* fn, UINT64 dev_id);
|
void ShowDialog(HWND hwnd, const wstring& fn, uint64_t dev_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void do_resize(HWND hwndDlg);
|
void do_resize(HWND hwndDlg);
|
||||||
|
|
||||||
UINT64 dev_id, new_size;
|
uint64_t dev_id, new_size;
|
||||||
WCHAR fn[MAX_PATH], new_size_text[255];
|
wstring fn;
|
||||||
|
WCHAR new_size_text[255];
|
||||||
btrfs_device dev_info;
|
btrfs_device dev_info;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,7 +27,7 @@ HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
|
||||||
if (iid == IID_IUnknown || iid == IID_IClassFactory) {
|
if (iid == IID_IUnknown || iid == IID_IClassFactory) {
|
||||||
*ppv = static_cast<IClassFactory*>(this);
|
*ppv = static_cast<IClassFactory*>(this);
|
||||||
} else {
|
} else {
|
||||||
*ppv = NULL;
|
*ppv = nullptr;
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +89,6 @@ HRESULT __stdcall Factory::CreateInstance(IUnknown* pUnknownOuter, const IID& ii
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppv = NULL;
|
*ppv = nullptr;
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,17 +39,16 @@ HRESULT __stdcall BtrfsIconOverlay::QueryInterface(REFIID riid, void **ppObj) {
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
*ppObj = NULL;
|
*ppObj = nullptr;
|
||||||
return E_NOINTERFACE;
|
return E_NOINTERFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) {
|
HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) {
|
||||||
WCHAR dllpath[MAX_PATH];
|
if (GetModuleFileNameW(module, pwszIconFile, cchMax) == 0)
|
||||||
|
return E_FAIL;
|
||||||
|
|
||||||
GetModuleFileNameW(module, dllpath, sizeof(dllpath));
|
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
|
||||||
|
return E_FAIL;
|
||||||
if ((size_t)cchMax < wcslen(dllpath))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (!pIndex)
|
if (!pIndex)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
@ -57,7 +56,6 @@ HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMa
|
||||||
if (!pdwFlags)
|
if (!pdwFlags)
|
||||||
return E_INVALIDARG;
|
return E_INVALIDARG;
|
||||||
|
|
||||||
wcscpy(pwszIconFile, dllpath);
|
|
||||||
*pIndex = 0;
|
*pIndex = 0;
|
||||||
*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
|
*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
|
||||||
|
|
||||||
|
@ -74,24 +72,20 @@ HRESULT __stdcall BtrfsIconOverlay::GetPriority(int *pPriority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) {
|
HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) {
|
||||||
HANDLE h;
|
win_handle h;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
btrfs_get_file_ids bgfi;
|
btrfs_get_file_ids bgfi;
|
||||||
|
|
||||||
h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
h = CreateFileW(pwszPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
|
|
||||||
if (h == INVALID_HANDLE_VALUE)
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status))
|
||||||
CloseHandle(h);
|
|
||||||
return S_FALSE;
|
return S_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
|
|
||||||
return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE;
|
return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE;
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <string>
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
#include "../btrfsioctl.h"
|
#include "../btrfsioctl.h"
|
||||||
#else
|
#else
|
||||||
|
@ -93,25 +92,27 @@ class BtrfsPropSheet : public IShellExtInit, IShellPropSheetExt {
|
||||||
public:
|
public:
|
||||||
BtrfsPropSheet() {
|
BtrfsPropSheet() {
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
ignore = TRUE;
|
ignore = true;
|
||||||
stgm_set = FALSE;
|
stgm_set = false;
|
||||||
readonly = FALSE;
|
readonly = false;
|
||||||
flags_changed = FALSE;
|
flags_changed = false;
|
||||||
perms_changed = FALSE;
|
perms_changed = false;
|
||||||
uid_changed = FALSE;
|
uid_changed = false;
|
||||||
gid_changed = FALSE;
|
gid_changed = false;
|
||||||
compress_type_changed = FALSE;
|
compress_type_changed = false;
|
||||||
ro_changed = FALSE;
|
ro_changed = false;
|
||||||
can_change_perms = FALSE;
|
can_change_perms = false;
|
||||||
show_admin_button = FALSE;
|
show_admin_button = false;
|
||||||
thread = NULL;
|
thread = nullptr;
|
||||||
mode = mode_set = 0;
|
mode = mode_set = 0;
|
||||||
flags = flags_set = 0;
|
flags = flags_set = 0;
|
||||||
has_subvols = FALSE;
|
has_subvols = false;
|
||||||
filename = L"";
|
filename = L"";
|
||||||
|
|
||||||
sizes[0] = sizes[1] = sizes[2] = sizes[3] = 0;
|
sizes[0] = sizes[1] = sizes[2] = sizes[3] = sizes[4] = 0;
|
||||||
totalsize = 0;
|
totalsize = allocsize = sparsesize = 0;
|
||||||
|
size_format[0] = 0;
|
||||||
|
cr_format[0] = 0;
|
||||||
|
|
||||||
InterlockedIncrement(&objs_loaded);
|
InterlockedIncrement(&objs_loaded);
|
||||||
}
|
}
|
||||||
|
@ -152,43 +153,42 @@ public:
|
||||||
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
|
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
|
||||||
|
|
||||||
void init_propsheet(HWND hwndDlg);
|
void init_propsheet(HWND hwndDlg);
|
||||||
void change_inode_flag(HWND hDlg, UINT64 flag, UINT state);
|
void change_inode_flag(HWND hDlg, uint64_t flag, UINT state);
|
||||||
void change_perm_flag(HWND hDlg, ULONG perm, UINT state);
|
void change_perm_flag(HWND hDlg, ULONG perm, UINT state);
|
||||||
void change_uid(HWND hDlg, UINT32 uid);
|
void change_uid(HWND hDlg, uint32_t uid);
|
||||||
void change_gid(HWND hDlg, UINT32 gid);
|
void change_gid(HWND hDlg, uint32_t gid);
|
||||||
void apply_changes(HWND hDlg);
|
void apply_changes(HWND hDlg);
|
||||||
void set_size_on_disk(HWND hwndDlg);
|
void set_size_on_disk(HWND hwndDlg);
|
||||||
void add_to_search_list(WCHAR* fn);
|
|
||||||
DWORD search_list_thread();
|
DWORD search_list_thread();
|
||||||
void do_search(WCHAR* fn);
|
void do_search(const wstring& fn);
|
||||||
void update_size_details_dialog(HWND hDlg);
|
void update_size_details_dialog(HWND hDlg);
|
||||||
void open_as_admin(HWND hwndDlg);
|
void open_as_admin(HWND hwndDlg);
|
||||||
void set_cmdline(std::wstring cmdline);
|
void set_cmdline(const wstring& cmdline);
|
||||||
|
|
||||||
BOOL readonly;
|
bool readonly;
|
||||||
BOOL can_change_perms;
|
bool can_change_perms;
|
||||||
BOOL can_change_nocow;
|
bool can_change_nocow;
|
||||||
WCHAR size_format[255];
|
WCHAR size_format[255], cr_format[255];
|
||||||
HANDLE thread;
|
HANDLE thread;
|
||||||
UINT32 min_mode, max_mode, mode, mode_set;
|
uint32_t min_mode, max_mode, mode, mode_set;
|
||||||
UINT64 min_flags, max_flags, flags, flags_set;
|
uint64_t min_flags, max_flags, flags, flags_set;
|
||||||
UINT64 subvol, inode, rdev;
|
uint64_t subvol, inode, rdev;
|
||||||
UINT8 type, min_compression_type, max_compression_type, compress_type;
|
uint8_t type, min_compression_type, max_compression_type, compress_type;
|
||||||
UINT32 uid, gid;
|
uint32_t uid, gid;
|
||||||
BOOL various_subvols, various_inodes, various_types, various_uids, various_gids, compress_type_changed, has_subvols,
|
bool various_subvols, various_inodes, various_types, various_uids, various_gids, compress_type_changed, has_subvols,
|
||||||
ro_subvol, various_ro, ro_changed, show_admin_button;
|
ro_subvol, various_ro, ro_changed, show_admin_button;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
BOOL ignore;
|
bool ignore;
|
||||||
STGMEDIUM stgm;
|
STGMEDIUM stgm;
|
||||||
BOOL stgm_set;
|
bool stgm_set;
|
||||||
BOOL flags_changed, perms_changed, uid_changed, gid_changed;
|
bool flags_changed, perms_changed, uid_changed, gid_changed;
|
||||||
UINT64 sizes[4], totalsize;
|
uint64_t sizes[5], totalsize, allocsize, sparsesize;
|
||||||
std::deque<WCHAR*> search_list;
|
deque<wstring> search_list;
|
||||||
std::wstring filename;
|
wstring filename;
|
||||||
|
|
||||||
void apply_changes_file(HWND hDlg, std::wstring fn);
|
void apply_changes_file(HWND hDlg, const wstring& fn);
|
||||||
HRESULT check_file(std::wstring fn, UINT i, UINT num_files, UINT* sv);
|
HRESULT check_file(const wstring& fn, UINT i, UINT num_files, UINT* sv);
|
||||||
HRESULT load_file_list();
|
HRESULT load_file_list();
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,8 +18,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
#include "../btrfs.h"
|
#include "../btrfs.h"
|
||||||
#else
|
#else
|
||||||
|
@ -30,21 +28,21 @@ extern LONG objs_loaded;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BTRFS_UUID uuid;
|
BTRFS_UUID uuid;
|
||||||
UINT64 transid;
|
uint64_t transid;
|
||||||
std::wstring path;
|
wstring path;
|
||||||
} subvol_cache;
|
} subvol_cache;
|
||||||
|
|
||||||
class BtrfsRecv {
|
class BtrfsRecv {
|
||||||
public:
|
public:
|
||||||
BtrfsRecv() {
|
BtrfsRecv() {
|
||||||
thread = NULL;
|
thread = nullptr;
|
||||||
master = INVALID_HANDLE_VALUE;
|
master = INVALID_HANDLE_VALUE;
|
||||||
dir = INVALID_HANDLE_VALUE;
|
dir = INVALID_HANDLE_VALUE;
|
||||||
running = FALSE;
|
running = false;
|
||||||
cancelling = FALSE;
|
cancelling = false;
|
||||||
stransid = 0;
|
stransid = 0;
|
||||||
num_received = 0;
|
num_received = 0;
|
||||||
hwnd = NULL;
|
hwnd = nullptr;
|
||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,39 +50,37 @@ public:
|
||||||
cache.clear();
|
cache.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Open(HWND hwnd, WCHAR* file, WCHAR* path, BOOL quiet);
|
void Open(HWND hwnd, const wstring& file, const wstring& path, bool quiet);
|
||||||
DWORD recv_thread();
|
DWORD recv_thread();
|
||||||
INT_PTR CALLBACK RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL cmd_subvol(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_subvol(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent);
|
||||||
BOOL cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, uint8_t* data, const win_handle& parent);
|
||||||
BOOL cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_rename(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_rename(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_link(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_link(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_unlink(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_unlink(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_write(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_write(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_clone(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_truncate(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_truncate(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_chmod(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_chmod(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_chown(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_chown(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
BOOL cmd_utimes(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
|
void cmd_utimes(HWND hwnd, btrfs_send_command* cmd, uint8_t* data);
|
||||||
void add_cache_entry(BTRFS_UUID* uuid, UINT64 transid, std::wstring path);
|
void add_cache_entry(BTRFS_UUID* uuid, uint64_t transid, const wstring& path);
|
||||||
BOOL utf8_to_utf16(HWND hwnd, char* utf8, ULONG utf8len, std::wstring* utf16);
|
bool find_tlv(uint8_t* data, ULONG datalen, uint16_t type, void** value, ULONG* len);
|
||||||
void ShowRecvError(int resid, ...);
|
void do_recv(const win_handle& f, uint64_t* pos, uint64_t size, const win_handle& parent);
|
||||||
BOOL find_tlv(UINT8* data, ULONG datalen, UINT16 type, void** value, ULONG* len);
|
|
||||||
BOOL do_recv(HANDLE f, UINT64* pos, UINT64 size);
|
|
||||||
|
|
||||||
HANDLE dir, parent, master, thread, lastwritefile;
|
HANDLE dir, master, thread, lastwritefile;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
std::wstring streamfile, dirpath, subvolpath, lastwritepath;
|
wstring streamfile, dirpath, subvolpath, lastwritepath;
|
||||||
DWORD lastwriteatt;
|
DWORD lastwriteatt;
|
||||||
ULONG num_received;
|
ULONG num_received;
|
||||||
UINT64 stransid;
|
uint64_t stransid;
|
||||||
BTRFS_UUID subvol_uuid;
|
BTRFS_UUID subvol_uuid;
|
||||||
BOOL running, cancelling;
|
bool running, cancelling;
|
||||||
std::vector<subvol_cache> cache;
|
vector<subvol_cache> cache;
|
||||||
};
|
};
|
||||||
|
|
|
@ -196,6 +196,17 @@
|
||||||
#define IDS_BALANCE_CANCELLED_SHRINK 278
|
#define IDS_BALANCE_CANCELLED_SHRINK 278
|
||||||
#define IDS_BALANCE_COMPLETE_SHRINK 279
|
#define IDS_BALANCE_COMPLETE_SHRINK 279
|
||||||
#define IDS_BALANCE_FAILED_SHRINK 280
|
#define IDS_BALANCE_FAILED_SHRINK 280
|
||||||
|
#define IDS_COMPRESS_ZSTD 281
|
||||||
|
#define IDS_RECV_RTLUNICODETOUTF8N_FAILED 282
|
||||||
|
#define IDS_REGCREATEKEY_FAILED 283
|
||||||
|
#define IDS_REGSETVALUEEX_FAILED 284
|
||||||
|
#define IDS_REGCLOSEKEY_FAILED 285
|
||||||
|
#define IDS_REGDELETETREE_FAILED 286
|
||||||
|
#define IDS_CANT_REFLINK_DIFFERENT_FS 287
|
||||||
|
#define IDS_INITCOMMONCONTROLSEX_FAILED 288
|
||||||
|
#define IDS_CANT_OPEN_MOUNTMGR 289
|
||||||
|
#define IDS_TVM_INSERTITEM_FAILED 290
|
||||||
|
#define IDS_RECV_PATH_TOO_LONG 291
|
||||||
#define IDC_UID 1001
|
#define IDC_UID 1001
|
||||||
#define IDC_GID 1002
|
#define IDC_GID 1002
|
||||||
#define IDC_USERR 1003
|
#define IDC_USERR 1003
|
||||||
|
@ -226,6 +237,8 @@
|
||||||
#define IDC_SIZE_LZO 1022
|
#define IDC_SIZE_LZO 1022
|
||||||
#define IDC_VOL_SHOW_USAGE 1022
|
#define IDC_VOL_SHOW_USAGE 1022
|
||||||
#define IDC_VOL_BALANCE 1023
|
#define IDC_VOL_BALANCE 1023
|
||||||
|
#define IDC_SIZE_ZSTD 1023
|
||||||
|
#define IDC_COMPRESSION_RATIO 1023
|
||||||
#define IDC_PROFILES 1024
|
#define IDC_PROFILES 1024
|
||||||
#define IDC_PROFILES_SINGLE 1025
|
#define IDC_PROFILES_SINGLE 1025
|
||||||
#define IDC_PROFILES_DUP 1026
|
#define IDC_PROFILES_DUP 1026
|
||||||
|
@ -324,7 +337,7 @@
|
||||||
//
|
//
|
||||||
#ifdef APSTUDIO_INVOKED
|
#ifdef APSTUDIO_INVOKED
|
||||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||||
#define _APS_NEXT_RESOURCE_VALUE 173
|
#define _APS_NEXT_RESOURCE_VALUE 175
|
||||||
#define _APS_NEXT_COMMAND_VALUE 40001
|
#define _APS_NEXT_COMMAND_VALUE 40001
|
||||||
#define _APS_NEXT_CONTROL_VALUE 1073
|
#define _APS_NEXT_CONTROL_VALUE 1073
|
||||||
#define _APS_NEXT_SYMED_VALUE 101
|
#define _APS_NEXT_SYMED_VALUE 101
|
||||||
|
|
|
@ -37,94 +37,82 @@
|
||||||
#include <ndk/iofuncs.h>
|
#include <ndk/iofuncs.h>
|
||||||
#include <ndk/iotypes.h>
|
#include <ndk/iotypes.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#define NO_SHLWAPI_STRFCNS
|
#define NO_SHLWAPI_STRFCNS
|
||||||
#include <shlwapi.h>
|
#include <shlwapi.h>
|
||||||
#include <uxtheme.h>
|
#include <uxtheme.h>
|
||||||
|
|
||||||
void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
btrfs_query_scrub* bqs2 = NULL;
|
btrfs_query_scrub* bqs2 = nullptr;
|
||||||
BOOL alloc_bqs2 = FALSE;
|
bool alloc_bqs2 = false;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
std::wstring s;
|
wstring s, t, u;
|
||||||
WCHAR t[255], u[255], dt[255], tm[255];
|
WCHAR dt[255], tm[255];
|
||||||
FILETIME filetime;
|
FILETIME filetime;
|
||||||
SYSTEMTIME systime;
|
SYSTEMTIME systime;
|
||||||
UINT64 recoverable_errors = 0, unrecoverable_errors = 0;
|
uint64_t recoverable_errors = 0, unrecoverable_errors = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
if (bqs->num_errors > 0) {
|
if (bqs->num_errors > 0) {
|
||||||
HANDLE h;
|
win_handle h;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
ULONG len;
|
ULONG len;
|
||||||
|
|
||||||
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
do {
|
do {
|
||||||
len += 1024;
|
len += 1024;
|
||||||
|
|
||||||
if (bqs2)
|
if (bqs2) {
|
||||||
free(bqs2);
|
free(bqs2);
|
||||||
|
bqs2 = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
bqs2 = (btrfs_query_scrub*)malloc(len);
|
bqs2 = (btrfs_query_scrub*)malloc(len);
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, bqs2, len);
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, bqs2, len);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
|
||||||
free(bqs2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} while (Status == STATUS_BUFFER_OVERFLOW);
|
} while (Status == STATUS_BUFFER_OVERFLOW);
|
||||||
|
} catch (...) {
|
||||||
|
if (bqs2)
|
||||||
|
free(bqs2);
|
||||||
|
|
||||||
alloc_bqs2 = TRUE;
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(h);
|
alloc_bqs2 = true;
|
||||||
} else
|
} else
|
||||||
bqs2 = bqs;
|
bqs2 = bqs;
|
||||||
|
|
||||||
s[0] = 0;
|
|
||||||
|
|
||||||
// "scrub started"
|
// "scrub started"
|
||||||
if (bqs2->start_time.QuadPart > 0) {
|
if (bqs2->start_time.QuadPart > 0) {
|
||||||
filetime.dwLowDateTime = bqs2->start_time.LowPart;
|
filetime.dwLowDateTime = bqs2->start_time.LowPart;
|
||||||
filetime.dwHighDateTime = bqs2->start_time.HighPart;
|
filetime.dwHighDateTime = bqs2->start_time.HighPart;
|
||||||
|
|
||||||
if (!FileTimeToSystemTime(&filetime, &systime)) {
|
if (!FileTimeToSystemTime(&filetime, &systime))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) {
|
if (!SystemTimeToTzSpecificLocalTime(nullptr, &systime, &systime))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_STARTED, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_STARTED, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) {
|
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, nullptr, dt, sizeof(dt) / sizeof(WCHAR)))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) {
|
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, nullptr, tm, sizeof(tm) / sizeof(WCHAR)))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, dt, tm);
|
||||||
goto end;
|
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
s += L"\r\n";
|
s += L"\r\n";
|
||||||
|
@ -141,13 +129,10 @@ void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
unrecoverable_errors++;
|
unrecoverable_errors++;
|
||||||
|
|
||||||
if (bse->parity) {
|
if (bse->parity) {
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_RECOVERABLE_PARITY, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_RECOVERABLE_PARITY, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, bse->address, bse->device);
|
||||||
goto end;
|
|
||||||
} else if (bse->is_metadata) {
|
} else if (bse->is_metadata) {
|
||||||
int message;
|
int message;
|
||||||
|
|
||||||
|
@ -158,24 +143,16 @@ void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
else
|
else
|
||||||
message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM;
|
message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM;
|
||||||
|
|
||||||
if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, message, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bse->recovered) {
|
if (bse->recovered)
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, bse->address, bse->device);
|
||||||
goto end;
|
else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0)
|
||||||
} else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) {
|
wstring_sprintf(u, t, bse->address, bse->device, bse->metadata.root, bse->metadata.level);
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device,
|
else
|
||||||
bse->metadata.root, bse->metadata.level) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, bse->address, bse->device, bse->metadata.root, bse->metadata.level, bse->metadata.firstitem.obj_id,
|
||||||
goto end;
|
bse->metadata.firstitem.obj_type, bse->metadata.firstitem.offset);
|
||||||
} else {
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device,
|
|
||||||
bse->metadata.root, bse->metadata.level, bse->metadata.firstitem.obj_id, bse->metadata.firstitem.obj_type,
|
|
||||||
bse->metadata.firstitem.offset) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
int message;
|
int message;
|
||||||
|
|
||||||
|
@ -186,23 +163,17 @@ void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
else
|
else
|
||||||
message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA;
|
message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA;
|
||||||
|
|
||||||
if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, message, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bse->recovered) {
|
if (bse->recovered)
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, bse->address, bse->device);
|
||||||
goto end;
|
else if (bse->data.subvol != 0)
|
||||||
} else if (bse->data.subvol != 0) {
|
wstring_sprintf(u, t, bse->address, bse->device, bse->data.subvol,
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, bse->data.subvol,
|
bse->data.filename_length / sizeof(WCHAR), bse->data.filename, bse->data.offset);
|
||||||
bse->data.filename_length / sizeof(WCHAR), bse->data.filename, bse->data.offset) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
else
|
||||||
goto end;
|
wstring_sprintf(u, t, bse->address, bse->device, bse->data.filename_length / sizeof(WCHAR),
|
||||||
} else {
|
bse->data.filename, bse->data.offset);
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device, bse->data.filename_length / sizeof(WCHAR),
|
|
||||||
bse->data.filename, bse->data.offset) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
|
@ -211,12 +182,12 @@ void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
if (bse->next_entry == 0)
|
if (bse->next_entry == 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
bse = (btrfs_scrub_error*)((UINT8*)bse + bse->next_entry);
|
bse = (btrfs_scrub_error*)((uint8_t*)bse + bse->next_entry);
|
||||||
} while (TRUE);
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bqs2->finish_time.QuadPart > 0) {
|
if (bqs2->finish_time.QuadPart > 0) {
|
||||||
WCHAR d1[255], d2[255];
|
wstring d1, d2;
|
||||||
float speed;
|
float speed;
|
||||||
|
|
||||||
// "scrub finished"
|
// "scrub finished"
|
||||||
|
@ -224,158 +195,129 @@ void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
|
||||||
filetime.dwLowDateTime = bqs2->finish_time.LowPart;
|
filetime.dwLowDateTime = bqs2->finish_time.LowPart;
|
||||||
filetime.dwHighDateTime = bqs2->finish_time.HighPart;
|
filetime.dwHighDateTime = bqs2->finish_time.HighPart;
|
||||||
|
|
||||||
if (!FileTimeToSystemTime(&filetime, &systime)) {
|
if (!FileTimeToSystemTime(&filetime, &systime))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) {
|
if (!SystemTimeToTzSpecificLocalTime(nullptr, &systime, &systime))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_FINISHED, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_FINISHED, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) {
|
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, nullptr, dt, sizeof(dt) / sizeof(WCHAR)))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) {
|
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, nullptr, tm, sizeof(tm) / sizeof(WCHAR)))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, dt, tm);
|
||||||
goto end;
|
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
s += L"\r\n";
|
s += L"\r\n";
|
||||||
|
|
||||||
// summary
|
// summary
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_SUMMARY, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
format_size(bqs2->data_scrubbed, d1, sizeof(d1) / sizeof(WCHAR), FALSE);
|
format_size(bqs2->data_scrubbed, d1, false);
|
||||||
|
|
||||||
speed = (float)bqs2->data_scrubbed / ((float)bqs2->duration / 10000000.0f);
|
speed = (float)bqs2->data_scrubbed / ((float)bqs2->duration / 10000000.0f);
|
||||||
|
|
||||||
format_size((UINT64)speed, d2, sizeof(d2) / sizeof(WCHAR), FALSE);
|
format_size((uint64_t)speed, d2, false);
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, d1, bqs2->duration / 10000000, d2) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, d1.c_str(), bqs2->duration / 10000000, d2.c_str());
|
||||||
goto end;
|
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
s += L"\r\n";
|
s += L"\r\n";
|
||||||
|
|
||||||
// recoverable errors
|
// recoverable errors
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, recoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, recoverable_errors);
|
||||||
goto end;
|
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
s += L"\r\n";
|
s += L"\r\n";
|
||||||
|
|
||||||
// unrecoverable errors
|
// unrecoverable errors
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, unrecoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(u, t, unrecoverable_errors);
|
||||||
goto end;
|
|
||||||
|
|
||||||
s += u;
|
s += u;
|
||||||
s += L"\r\n";
|
s += L"\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
SetWindowTextW(GetDlgItem(hwndDlg, IDC_SCRUB_INFO), s.c_str());
|
SetWindowTextW(GetDlgItem(hwndDlg, IDC_SCRUB_INFO), s.c_str());
|
||||||
|
} catch (...) {
|
||||||
|
if (alloc_bqs2)
|
||||||
|
free(bqs2);
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
if (alloc_bqs2)
|
if (alloc_bqs2)
|
||||||
free(bqs2);
|
free(bqs2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, BOOL first_time) {
|
void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, bool first_time) {
|
||||||
HANDLE h;
|
|
||||||
btrfs_query_scrub bqs;
|
btrfs_query_scrub bqs;
|
||||||
|
|
||||||
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
{
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub));
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, &bqs, sizeof(btrfs_query_scrub));
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
} else
|
||||||
return;
|
throw last_error(GetLastError());
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
} else {
|
|
||||||
ShowError(hwndDlg, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first_time || status != bqs.status || chunks_left != bqs.chunks_left) {
|
if (first_time || status != bqs.status || chunks_left != bqs.chunks_left) {
|
||||||
WCHAR s[255];
|
wstring s;
|
||||||
|
|
||||||
if (bqs.status == BTRFS_SCRUB_STOPPED) {
|
if (bqs.status == BTRFS_SCRUB_STOPPED) {
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), TRUE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), true);
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), FALSE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), false);
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), FALSE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), false);
|
||||||
|
|
||||||
if (bqs.error != STATUS_SUCCESS) {
|
if (bqs.error != STATUS_SUCCESS) {
|
||||||
WCHAR t[255];
|
wstring t;
|
||||||
|
|
||||||
if (!LoadStringW(module, IDS_SCRUB_FAILED, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, IDS_SCRUB_FAILED, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, bqs.error) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(s, t, bqs.error);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
if (!LoadStringW(module, bqs.total_chunks == 0 ? IDS_NO_SCRUB : IDS_SCRUB_FINISHED, s, sizeof(s) / sizeof(WCHAR))) {
|
if (!load_string(module, bqs.total_chunks == 0 ? IDS_NO_SCRUB : IDS_SCRUB_FINISHED, s))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WCHAR t[255];
|
wstring t;
|
||||||
float pc;
|
float pc;
|
||||||
|
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), FALSE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), false);
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), TRUE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), true);
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), TRUE);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), true);
|
||||||
|
|
||||||
if (!LoadStringW(module, bqs.status == BTRFS_SCRUB_PAUSED ? IDS_SCRUB_PAUSED : IDS_SCRUB_RUNNING, t, sizeof(t) / sizeof(WCHAR))) {
|
if (!load_string(module, bqs.status == BTRFS_SCRUB_PAUSED ? IDS_SCRUB_PAUSED : IDS_SCRUB_RUNNING, t))
|
||||||
ShowError(hwndDlg, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pc = ((float)(bqs.total_chunks - bqs.chunks_left) / (float)bqs.total_chunks) * 100.0f;
|
pc = ((float)(bqs.total_chunks - bqs.chunks_left) / (float)bqs.total_chunks) * 100.0f;
|
||||||
|
|
||||||
if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, bqs.total_chunks - bqs.chunks_left, bqs.total_chunks, pc) == STRSAFE_E_INSUFFICIENT_BUFFER)
|
wstring_sprintf(s, t, bqs.total_chunks - bqs.chunks_left, bqs.total_chunks, pc);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDlgItemTextW(hwndDlg, IDC_SCRUB_STATUS, s);
|
SetDlgItemTextW(hwndDlg, IDC_SCRUB_STATUS, s.c_str());
|
||||||
|
|
||||||
if (first_time || status != bqs.status) {
|
if (first_time || status != bqs.status) {
|
||||||
EnableWindow(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), bqs.status != BTRFS_SCRUB_STOPPED);
|
EnableWindow(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), bqs.status != BTRFS_SCRUB_STOPPED);
|
||||||
|
@ -412,109 +354,81 @@ void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, BOOL first_time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsScrub::StartScrub(HWND hwndDlg) {
|
void BtrfsScrub::StartScrub(HWND hwndDlg) {
|
||||||
HANDLE h;
|
win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
|
|
||||||
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0);
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_START_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
if (Status == STATUS_DEVICE_NOT_READY) {
|
if (Status == STATUS_DEVICE_NOT_READY) {
|
||||||
btrfs_query_balance bqb;
|
btrfs_query_balance bqb;
|
||||||
NTSTATUS Status2;
|
NTSTATUS Status2;
|
||||||
|
|
||||||
Status2 = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb, sizeof(btrfs_query_balance));
|
Status2 = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_BALANCE, nullptr, 0, &bqb, sizeof(btrfs_query_balance));
|
||||||
|
|
||||||
if (NT_SUCCESS(Status2) && bqb.status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) {
|
if (NT_SUCCESS(Status2) && bqb.status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED))
|
||||||
ShowStringError(hwndDlg, IDS_SCRUB_BALANCE_RUNNING);
|
throw string_error(IDS_SCRUB_BALANCE_RUNNING);
|
||||||
CloseHandle(h);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status))
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefreshScrubDlg(hwndDlg, TRUE);
|
RefreshScrubDlg(hwndDlg, true);
|
||||||
|
} else
|
||||||
CloseHandle(h);
|
throw last_error(GetLastError());
|
||||||
} else {
|
|
||||||
ShowError(hwndDlg, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsScrub::PauseScrub(HWND hwndDlg) {
|
void BtrfsScrub::PauseScrub(HWND hwndDlg) {
|
||||||
HANDLE h;
|
|
||||||
btrfs_query_scrub bqs;
|
btrfs_query_scrub bqs;
|
||||||
|
|
||||||
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub));
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_QUERY_SCRUB, nullptr, 0, &bqs, sizeof(btrfs_query_scrub));
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
|
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW)
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bqs.status == BTRFS_SCRUB_PAUSED)
|
if (bqs.status == BTRFS_SCRUB_PAUSED)
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESUME_SCRUB, NULL, 0, NULL, 0);
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_RESUME_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
else
|
else
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_PAUSE_SCRUB, NULL, 0, NULL, 0);
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_PAUSE_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status))
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
} else
|
||||||
return;
|
throw last_error(GetLastError());
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
} else {
|
|
||||||
ShowError(hwndDlg, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsScrub::StopScrub(HWND hwndDlg) {
|
void BtrfsScrub::StopScrub(HWND hwndDlg) {
|
||||||
HANDLE h;
|
win_handle h = CreateFileW(fn.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
|
|
||||||
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0);
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_STOP_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
if (!NT_SUCCESS(Status))
|
||||||
ShowNtStatusError(hwndDlg, Status);
|
throw ntstatus_error(Status);
|
||||||
CloseHandle(h);
|
} else
|
||||||
return;
|
throw last_error(GetLastError());
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
} else {
|
|
||||||
ShowError(hwndDlg, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR CALLBACK BtrfsScrub::ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
INT_PTR CALLBACK BtrfsScrub::ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
try {
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
RefreshScrubDlg(hwndDlg, TRUE);
|
RefreshScrubDlg(hwndDlg, true);
|
||||||
SetTimer(hwndDlg, 1, 1000, NULL);
|
SetTimer(hwndDlg, 1, 1000, nullptr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_COMMAND:
|
case WM_COMMAND:
|
||||||
|
@ -524,30 +438,33 @@ INT_PTR CALLBACK BtrfsScrub::ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam
|
||||||
case IDOK:
|
case IDOK:
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
EndDialog(hwndDlg, 0);
|
EndDialog(hwndDlg, 0);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_START_SCRUB:
|
case IDC_START_SCRUB:
|
||||||
StartScrub(hwndDlg);
|
StartScrub(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_PAUSE_SCRUB:
|
case IDC_PAUSE_SCRUB:
|
||||||
PauseScrub(hwndDlg);
|
PauseScrub(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_CANCEL_SCRUB:
|
case IDC_CANCEL_SCRUB:
|
||||||
StopScrub(hwndDlg);
|
StopScrub(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_TIMER:
|
case WM_TIMER:
|
||||||
RefreshScrubDlg(hwndDlg, FALSE);
|
RefreshScrubDlg(hwndDlg, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch (const exception& e) {
|
||||||
|
error_message(hwndDlg, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
@ -563,7 +480,7 @@ static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam
|
||||||
if (bs)
|
if (bs)
|
||||||
return bs->ScrubDlgProc(hwndDlg, uMsg, wParam, lParam);
|
return bs->ScrubDlgProc(hwndDlg, uMsg, wParam, lParam);
|
||||||
else
|
else
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
@ -571,132 +488,104 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||||
HANDLE token;
|
try {
|
||||||
|
win_handle token;
|
||||||
TOKEN_PRIVILEGES tp;
|
TOKEN_PRIVILEGES tp;
|
||||||
LUID luid;
|
LUID luid;
|
||||||
BtrfsScrub* scrub;
|
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
|
if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
tp.Privileges[0].Luid = luid;
|
tp.Privileges[0].Luid = luid;
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
|
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_dpi_aware();
|
set_dpi_aware();
|
||||||
|
|
||||||
scrub = new BtrfsScrub(lpszCmdLine);
|
BtrfsScrub scrub(lpszCmdLine);
|
||||||
|
|
||||||
DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SCRUB), hwnd, stub_ScrubDlgProc, (LPARAM)scrub);
|
DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SCRUB), hwnd, stub_ScrubDlgProc, (LPARAM)&scrub);
|
||||||
|
} catch (const exception& e) {
|
||||||
delete scrub;
|
error_message(hwnd, e.what());
|
||||||
|
}
|
||||||
end:
|
|
||||||
CloseHandle(token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||||
LPWSTR* args;
|
vector<wstring> args;
|
||||||
int num_args;
|
|
||||||
|
|
||||||
args = CommandLineToArgvW(lpszCmdLine, &num_args);
|
command_line_to_args(lpszCmdLine, args);
|
||||||
|
|
||||||
if (!args)
|
if (args.size() >= 1) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (num_args >= 1) {
|
|
||||||
HANDLE h, token;
|
|
||||||
LUID luid;
|
LUID luid;
|
||||||
TOKEN_PRIVILEGES tp;
|
TOKEN_PRIVILEGES tp;
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
{
|
||||||
goto end;
|
win_handle token;
|
||||||
|
|
||||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
CloseHandle(token);
|
return;
|
||||||
goto end;
|
|
||||||
}
|
if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
|
||||||
|
return;
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
tp.Privileges[0].Luid = luid;
|
tp.Privileges[0].Luid = luid;
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
|
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
|
||||||
CloseHandle(token);
|
return;
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(token);
|
win_handle h = CreateFileW(args[0].c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
h = CreateFileW(args[0], FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0);
|
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_START_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
LocalFree(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||||
LPWSTR* args;
|
vector<wstring> args;
|
||||||
int num_args;
|
|
||||||
|
|
||||||
args = CommandLineToArgvW(lpszCmdLine, &num_args);
|
command_line_to_args(lpszCmdLine, args);
|
||||||
|
|
||||||
if (!args)
|
if (args.size() >= 1) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (num_args >= 1) {
|
|
||||||
HANDLE h, token;
|
|
||||||
LUID luid;
|
LUID luid;
|
||||||
TOKEN_PRIVILEGES tp;
|
TOKEN_PRIVILEGES tp;
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
{
|
||||||
goto end;
|
win_handle token;
|
||||||
|
|
||||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid))
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
goto end;
|
return;
|
||||||
|
|
||||||
|
if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
|
||||||
|
return;
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
tp.Privileges[0].Luid = luid;
|
tp.Privileges[0].Luid = luid;
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
|
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
|
||||||
goto end;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(token);
|
win_handle h = CreateFileW(args[0].c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr,
|
||||||
|
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr);
|
||||||
h = CreateFileW(args[0], FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL,
|
|
||||||
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
|
|
||||||
if (h != INVALID_HANDLE_VALUE) {
|
if (h != INVALID_HANDLE_VALUE) {
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
|
|
||||||
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0);
|
NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_STOP_SCRUB, nullptr, 0, nullptr, 0);
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
LocalFree(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
|
|
@ -28,21 +28,21 @@
|
||||||
|
|
||||||
class BtrfsScrub {
|
class BtrfsScrub {
|
||||||
public:
|
public:
|
||||||
BtrfsScrub(WCHAR* drive) {
|
BtrfsScrub(const wstring& drive) {
|
||||||
wcscpy(fn, drive);
|
fn = drive;
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR CALLBACK ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RefreshScrubDlg(HWND hwndDlg, BOOL first_time);
|
void RefreshScrubDlg(HWND hwndDlg, bool first_time);
|
||||||
void UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs);
|
void UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs);
|
||||||
void StartScrub(HWND hwndDlg);
|
void StartScrub(HWND hwndDlg);
|
||||||
void PauseScrub(HWND hwndDlg);
|
void PauseScrub(HWND hwndDlg);
|
||||||
void StopScrub(HWND hwndDlg);
|
void StopScrub(HWND hwndDlg);
|
||||||
|
|
||||||
WCHAR fn[MAX_PATH];
|
wstring fn;
|
||||||
UINT32 status;
|
uint32_t status;
|
||||||
UINT64 chunks_left;
|
uint64_t chunks_left;
|
||||||
UINT32 num_errors;
|
uint32_t num_errors;
|
||||||
};
|
};
|
||||||
|
|
|
@ -23,47 +23,27 @@
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
#undef DeleteFile
|
#undef DeleteFile
|
||||||
#endif
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define SEND_BUFFER_LEN 1048576
|
#define SEND_BUFFER_LEN 1048576
|
||||||
|
|
||||||
void BtrfsSend::ShowSendError(UINT msg, ...) {
|
|
||||||
WCHAR s[1024], t[1024];
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
if (!LoadStringW(module, msg, s, sizeof(s) / sizeof(WCHAR))) {
|
|
||||||
ShowError(hwnd, GetLastError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
va_start(ap, msg);
|
|
||||||
#ifndef __REACTOS__
|
|
||||||
vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap);
|
|
||||||
#else
|
|
||||||
vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SetDlgItemTextW(hwnd, IDC_SEND_STATUS, t);
|
|
||||||
|
|
||||||
va_end(ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
DWORD BtrfsSend::Thread() {
|
DWORD BtrfsSend::Thread() {
|
||||||
|
try {
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
btrfs_send_subvol* bss;
|
btrfs_send_subvol* bss;
|
||||||
btrfs_send_header header;
|
btrfs_send_header header;
|
||||||
btrfs_send_command end;
|
btrfs_send_command end;
|
||||||
BOOL success = FALSE;
|
|
||||||
ULONG bss_size, i;
|
ULONG bss_size, i;
|
||||||
|
|
||||||
buf = (char*)malloc(SEND_BUFFER_LEN);
|
buf = (char*)malloc(SEND_BUFFER_LEN);
|
||||||
|
|
||||||
dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
try {
|
||||||
if (dirh == INVALID_HANDLE_VALUE) {
|
dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
ShowSendError(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
if (dirh == INVALID_HANDLE_VALUE)
|
||||||
goto end3;
|
throw string_error(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||||
bss = (btrfs_send_subvol*)malloc(bss_size);
|
bss = (btrfs_send_subvol*)malloc(bss_size);
|
||||||
memset(bss, 0, bss_size);
|
memset(bss, 0, bss_size);
|
||||||
|
@ -76,39 +56,37 @@ DWORD BtrfsSend::Thread() {
|
||||||
|
|
||||||
GetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent, sizeof(parent) / sizeof(WCHAR));
|
GetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent, sizeof(parent) / sizeof(WCHAR));
|
||||||
|
|
||||||
parenth = CreateFileW(parent, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
parenth = CreateFileW(parent, FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (parenth == INVALID_HANDLE_VALUE) {
|
if (parenth == INVALID_HANDLE_VALUE)
|
||||||
ShowSendError(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
goto end2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bss->parent = parenth;
|
bss->parent = parenth;
|
||||||
} else
|
} else
|
||||||
bss->parent = NULL;
|
bss->parent = nullptr;
|
||||||
|
|
||||||
bss->num_clones = clones.size();
|
bss->num_clones = clones.size();
|
||||||
|
|
||||||
for (i = 0; i < bss->num_clones; i++) {
|
for (i = 0; i < bss->num_clones; i++) {
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
|
||||||
h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
auto le = GetLastError();
|
||||||
ULONG j;
|
ULONG j;
|
||||||
|
|
||||||
ShowSendError(IDS_SEND_CANT_OPEN_DIR, clones[i].c_str(), GetLastError(), format_message(GetLastError()).c_str());
|
|
||||||
|
|
||||||
for (j = 0; j < i; j++) {
|
for (j = 0; j < i; j++) {
|
||||||
CloseHandle(bss->clones[j]);
|
CloseHandle(bss->clones[j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
goto end2;
|
|
||||||
|
throw string_error(IDS_SEND_CANT_OPEN_DIR, clones[i].c_str(), le, format_message(le).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bss->clones[i] = h;
|
bss->clones[i] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0);
|
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0);
|
||||||
|
|
||||||
for (i = 0; i < bss->num_clones; i++) {
|
for (i = 0; i < bss->num_clones; i++) {
|
||||||
CloseHandle(bss->clones[i]);
|
CloseHandle(bss->clones[i]);
|
||||||
|
@ -118,107 +96,129 @@ DWORD BtrfsSend::Thread() {
|
||||||
if (Status == (NTSTATUS)STATUS_INVALID_PARAMETER) {
|
if (Status == (NTSTATUS)STATUS_INVALID_PARAMETER) {
|
||||||
BY_HANDLE_FILE_INFORMATION fileinfo;
|
BY_HANDLE_FILE_INFORMATION fileinfo;
|
||||||
if (!GetFileInformationByHandle(dirh, &fileinfo)) {
|
if (!GetFileInformationByHandle(dirh, &fileinfo)) {
|
||||||
ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
auto le = GetLastError();
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
goto end2;
|
throw string_error(IDS_SEND_GET_FILE_INFO_FAILED, le, format_message(le).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
||||||
ShowSendError(IDS_SEND_NOT_READONLY);
|
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
goto end2;
|
throw string_error(IDS_SEND_NOT_READONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bss->parent) {
|
if (bss->parent) {
|
||||||
if (!GetFileInformationByHandle(bss->parent, &fileinfo)) {
|
if (!GetFileInformationByHandle(bss->parent, &fileinfo)) {
|
||||||
ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
auto le = GetLastError();
|
||||||
CloseHandle(bss->parent);
|
CloseHandle(bss->parent);
|
||||||
goto end2;
|
throw string_error(IDS_SEND_GET_FILE_INFO_FAILED, le, format_message(le).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
|
||||||
ShowSendError(IDS_SEND_PARENT_NOT_READONLY);
|
|
||||||
CloseHandle(bss->parent);
|
CloseHandle(bss->parent);
|
||||||
goto end2;
|
throw string_error(IDS_SEND_PARENT_NOT_READONLY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ShowSendError(IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
|
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
goto end2;
|
throw string_error(IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
|
|
||||||
stream = CreateFileW(file, FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
stream = CreateFileW(file, FILE_WRITE_DATA | DELETE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (stream == INVALID_HANDLE_VALUE) {
|
if (stream == INVALID_HANDLE_VALUE)
|
||||||
ShowSendError(IDS_SEND_CANT_OPEN_FILE, file, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_SEND_CANT_OPEN_FILE, file, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
goto end2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic));
|
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic));
|
||||||
header.version = 1;
|
header.version = 1;
|
||||||
|
|
||||||
if (!WriteFile(stream, &header, sizeof(header), NULL, NULL)) {
|
if (!WriteFile(stream, &header, sizeof(header), nullptr, nullptr))
|
||||||
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN);
|
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, nullptr, 0, buf, SEND_BUFFER_LEN);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status)) {
|
if (NT_SUCCESS(Status)) {
|
||||||
if (!WriteFile(stream, buf, iosb.Information, NULL, NULL))
|
if (!WriteFile(stream, buf, iosb.Information, nullptr, nullptr))
|
||||||
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
}
|
}
|
||||||
} while (NT_SUCCESS(Status));
|
} while (NT_SUCCESS(Status));
|
||||||
|
|
||||||
if (Status != STATUS_END_OF_FILE) {
|
if (Status != STATUS_END_OF_FILE)
|
||||||
ShowSendError(IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED, Status, format_ntstatus(Status).c_str());
|
throw string_error(IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED, Status, format_ntstatus(Status).c_str());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
end.length = 0;
|
end.length = 0;
|
||||||
end.cmd = BTRFS_SEND_CMD_END;
|
end.cmd = BTRFS_SEND_CMD_END;
|
||||||
end.csum = 0x9dc96c50;
|
end.csum = 0x9dc96c50;
|
||||||
|
|
||||||
if (!WriteFile(stream, &end, sizeof(end), NULL, NULL)) {
|
if (!WriteFile(stream, &end, sizeof(end), nullptr, nullptr))
|
||||||
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetEndOfFile(stream);
|
SetEndOfFile(stream);
|
||||||
|
} catch (...) {
|
||||||
ShowSendError(IDS_SEND_SUCCESS);
|
|
||||||
success = TRUE;
|
|
||||||
|
|
||||||
end:
|
|
||||||
if (!success) {
|
|
||||||
FILE_DISPOSITION_INFO fdi;
|
FILE_DISPOSITION_INFO fdi;
|
||||||
|
|
||||||
fdi.DeleteFile = TRUE;
|
fdi.DeleteFile = true;
|
||||||
|
|
||||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(stream);
|
CloseHandle(stream);
|
||||||
stream = INVALID_HANDLE_VALUE;
|
stream = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
end2:
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(stream);
|
||||||
|
stream = INVALID_HANDLE_VALUE;
|
||||||
|
} catch (...) {
|
||||||
CloseHandle(dirh);
|
CloseHandle(dirh);
|
||||||
dirh = INVALID_HANDLE_VALUE;
|
dirh = INVALID_HANDLE_VALUE;
|
||||||
|
|
||||||
end3:
|
throw;
|
||||||
free(buf);
|
}
|
||||||
buf = NULL;
|
|
||||||
|
|
||||||
started = FALSE;
|
CloseHandle(dirh);
|
||||||
|
dirh = INVALID_HANDLE_VALUE;
|
||||||
|
} catch (...) {
|
||||||
|
free(buf);
|
||||||
|
buf = nullptr;
|
||||||
|
|
||||||
|
started = false;
|
||||||
|
|
||||||
SetDlgItemTextW(hwnd, IDCANCEL, closetext);
|
SetDlgItemTextW(hwnd, IDCANCEL, closetext);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDOK), true);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true);
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} catch (const exception& e) {
|
||||||
|
wstring msg;
|
||||||
|
|
||||||
|
utf8_to_utf16(e.what(), msg);
|
||||||
|
|
||||||
|
SetDlgItemTextW(hwnd, IDC_SEND_STATUS, msg.c_str());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
buf = nullptr;
|
||||||
|
|
||||||
|
started = false;
|
||||||
|
|
||||||
|
SetDlgItemTextW(hwnd, IDCANCEL, closetext);
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDOK), true);
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true);
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true);
|
||||||
|
|
||||||
|
wstring success;
|
||||||
|
|
||||||
|
load_string(module, IDS_SEND_SUCCESS, success);
|
||||||
|
|
||||||
|
SetDlgItemTextW(hwnd, IDC_SEND_STATUS, success.c_str());
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,7 @@ static DWORD WINAPI send_thread(LPVOID lpParameter) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsSend::StartSend(HWND hwnd) {
|
void BtrfsSend::StartSend(HWND hwnd) {
|
||||||
WCHAR s[255];
|
wstring s;
|
||||||
HWND cl;
|
HWND cl;
|
||||||
ULONG num_clones;
|
ULONG num_clones;
|
||||||
|
|
||||||
|
@ -251,15 +251,20 @@ void BtrfsSend::StartSend(HWND hwnd) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
started = TRUE;
|
started = true;
|
||||||
ShowSendError(IDS_SEND_WRITING);
|
|
||||||
|
|
||||||
LoadStringW(module, IDS_SEND_CANCEL, s, sizeof(s) / sizeof(WCHAR));
|
wstring writing;
|
||||||
SetDlgItemTextW(hwnd, IDCANCEL, s);
|
|
||||||
|
|
||||||
EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
|
load_string(module, IDS_SEND_WRITING, writing);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), FALSE);
|
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE);
|
SetDlgItemTextW(hwnd, IDC_SEND_STATUS, writing.c_str());
|
||||||
|
|
||||||
|
load_string(module, IDS_SEND_CANCEL, s);
|
||||||
|
SetDlgItemTextW(hwnd, IDCANCEL, s.c_str());
|
||||||
|
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDOK), false);
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), false);
|
||||||
|
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), false);
|
||||||
|
|
||||||
clones.clear();
|
clones.clear();
|
||||||
|
|
||||||
|
@ -270,24 +275,24 @@ void BtrfsSend::StartSend(HWND hwnd) {
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
|
||||||
for (i = 0; i < num_clones; i++) {
|
for (i = 0; i < num_clones; i++) {
|
||||||
WCHAR* s;
|
WCHAR* t;
|
||||||
ULONG len;
|
ULONG len;
|
||||||
|
|
||||||
len = SendMessageW(cl, LB_GETTEXTLEN, i, 0);
|
len = SendMessageW(cl, LB_GETTEXTLEN, i, 0);
|
||||||
s = (WCHAR*)malloc((len + 1) * sizeof(WCHAR));
|
t = (WCHAR*)malloc((len + 1) * sizeof(WCHAR));
|
||||||
|
|
||||||
SendMessageW(cl, LB_GETTEXT, i, (LPARAM)s);
|
SendMessageW(cl, LB_GETTEXT, i, (LPARAM)t);
|
||||||
|
|
||||||
clones.push_back(s);
|
clones.push_back(t);
|
||||||
|
|
||||||
free(s);
|
free(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thread = CreateThread(NULL, 0, send_thread, this, 0, NULL);
|
thread = CreateThread(nullptr, 0, send_thread, this, 0, nullptr);
|
||||||
|
|
||||||
if (!thread)
|
if (!thread)
|
||||||
ShowError(NULL, GetLastError());
|
throw last_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsSend::Browse(HWND hwnd) {
|
void BtrfsSend::Browse(HWND hwnd) {
|
||||||
|
@ -313,21 +318,16 @@ void BtrfsSend::BrowseParent(HWND hwnd) {
|
||||||
PIDLIST_ABSOLUTE root, pidl;
|
PIDLIST_ABSOLUTE root, pidl;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
WCHAR parent[MAX_PATH], volpathw[MAX_PATH];
|
WCHAR parent[MAX_PATH], volpathw[MAX_PATH];
|
||||||
HANDLE h;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
btrfs_get_file_ids bgfi;
|
btrfs_get_file_ids bgfi;
|
||||||
|
|
||||||
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) {
|
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1))
|
||||||
ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
|
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr))
|
||||||
ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED);
|
throw string_error(IDS_SHPARSEDISPLAYNAME_FAILED);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&bi, 0, sizeof(BROWSEINFOW));
|
memset(&bi, 0, sizeof(BROWSEINFOW));
|
||||||
|
|
||||||
|
@ -340,30 +340,21 @@ void BtrfsSend::BrowseParent(HWND hwnd) {
|
||||||
if (!pidl)
|
if (!pidl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!SHGetPathFromIDListW(pidl, parent)) {
|
if (!SHGetPathFromIDListW(pidl, parent))
|
||||||
ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED);
|
throw string_error(IDS_SHGETPATHFROMIDLIST_FAILED);
|
||||||
return;
|
|
||||||
|
{
|
||||||
|
win_handle h = CreateFileW(parent, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
throw string_error(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
|
|
||||||
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
throw string_error(IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
h = CreateFileW(parent, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
if (bgfi.inode != 0x100 || bgfi.top)
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
throw string_error(IDS_NOT_SUBVOL);
|
||||||
ShowStringError(hwnd, IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
ShowStringError(hwnd, IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str());
|
|
||||||
CloseHandle(h);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
|
|
||||||
if (bgfi.inode != 0x100 || bgfi.top) {
|
|
||||||
ShowStringError(hwnd, IDS_NOT_SUBVOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent);
|
SetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent);
|
||||||
}
|
}
|
||||||
|
@ -373,21 +364,16 @@ void BtrfsSend::AddClone(HWND hwnd) {
|
||||||
PIDLIST_ABSOLUTE root, pidl;
|
PIDLIST_ABSOLUTE root, pidl;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
WCHAR path[MAX_PATH], volpathw[MAX_PATH];
|
WCHAR path[MAX_PATH], volpathw[MAX_PATH];
|
||||||
HANDLE h;
|
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
btrfs_get_file_ids bgfi;
|
btrfs_get_file_ids bgfi;
|
||||||
|
|
||||||
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) {
|
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1))
|
||||||
ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
throw string_error(IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
|
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr))
|
||||||
ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED);
|
throw string_error(IDS_SHPARSEDISPLAYNAME_FAILED);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&bi, 0, sizeof(BROWSEINFOW));
|
memset(&bi, 0, sizeof(BROWSEINFOW));
|
||||||
|
|
||||||
|
@ -400,30 +386,21 @@ void BtrfsSend::AddClone(HWND hwnd) {
|
||||||
if (!pidl)
|
if (!pidl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!SHGetPathFromIDListW(pidl, path)) {
|
if (!SHGetPathFromIDListW(pidl, path))
|
||||||
ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED);
|
throw string_error(IDS_SHGETPATHFROMIDLIST_FAILED);
|
||||||
return;
|
|
||||||
|
{
|
||||||
|
win_handle h = CreateFileW(path, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
|
if (h == INVALID_HANDLE_VALUE)
|
||||||
|
throw string_error(IDS_SEND_CANT_OPEN_DIR, path, GetLastError(), format_message(GetLastError()).c_str());
|
||||||
|
|
||||||
|
Status = NtFsControlFile(h, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_GET_FILE_IDS, nullptr, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
||||||
|
if (!NT_SUCCESS(Status))
|
||||||
|
throw string_error(IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
h = CreateFileW(path, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
if (bgfi.inode != 0x100 || bgfi.top)
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
throw string_error(IDS_NOT_SUBVOL);
|
||||||
ShowStringError(hwnd, IDS_SEND_CANT_OPEN_DIR, path, GetLastError(), format_message(GetLastError()).c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
|
|
||||||
if (!NT_SUCCESS(Status)) {
|
|
||||||
ShowStringError(hwnd, IDS_GET_FILE_IDS_FAILED, Status, format_ntstatus(Status).c_str());
|
|
||||||
CloseHandle(h);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CloseHandle(h);
|
|
||||||
|
|
||||||
if (bgfi.inode != 0x100 || bgfi.top) {
|
|
||||||
ShowStringError(hwnd, IDS_NOT_SUBVOL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendMessageW(GetDlgItem(hwnd, IDC_CLONE_LIST), LB_ADDSTRING, 0, (LPARAM)path);
|
SendMessageW(GetDlgItem(hwnd, IDC_CLONE_LIST), LB_ADDSTRING, 0, (LPARAM)path);
|
||||||
}
|
}
|
||||||
|
@ -440,10 +417,11 @@ void BtrfsSend::RemoveClone(HWND hwnd) {
|
||||||
SendMessageW(cl, LB_DELETESTRING, sel, 0);
|
SendMessageW(cl, LB_DELETESTRING, sel, 0);
|
||||||
|
|
||||||
if (SendMessageW(cl, LB_GETCURSEL, 0, 0) == LB_ERR)
|
if (SendMessageW(cl, LB_GETCURSEL, 0, 0) == LB_ERR)
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), FALSE);
|
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
try {
|
||||||
switch (uMsg) {
|
switch (uMsg) {
|
||||||
case WM_INITDIALOG:
|
case WM_INITDIALOG:
|
||||||
this->hwnd = hwndDlg;
|
this->hwnd = hwndDlg;
|
||||||
|
@ -457,7 +435,7 @@ INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
switch (LOWORD(wParam)) {
|
switch (LOWORD(wParam)) {
|
||||||
case IDOK:
|
case IDOK:
|
||||||
StartSend(hwndDlg);
|
StartSend(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDCANCEL:
|
case IDCANCEL:
|
||||||
if (started) {
|
if (started) {
|
||||||
|
@ -466,7 +444,7 @@ INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
if (stream != INVALID_HANDLE_VALUE) {
|
if (stream != INVALID_HANDLE_VALUE) {
|
||||||
FILE_DISPOSITION_INFO fdi;
|
FILE_DISPOSITION_INFO fdi;
|
||||||
|
|
||||||
fdi.DeleteFile = TRUE;
|
fdi.DeleteFile = true;
|
||||||
|
|
||||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||||
CloseHandle(stream);
|
CloseHandle(stream);
|
||||||
|
@ -475,54 +453,57 @@ INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lP
|
||||||
if (dirh != INVALID_HANDLE_VALUE)
|
if (dirh != INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(dirh);
|
CloseHandle(dirh);
|
||||||
|
|
||||||
started = FALSE;
|
started = false;
|
||||||
|
|
||||||
SetDlgItemTextW(hwndDlg, IDCANCEL, closetext);
|
SetDlgItemTextW(hwndDlg, IDCANCEL, closetext);
|
||||||
|
|
||||||
EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDOK), true);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), true);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), true);
|
||||||
} else
|
} else
|
||||||
EndDialog(hwndDlg, 1);
|
EndDialog(hwndDlg, 1);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_BROWSE:
|
case IDC_BROWSE:
|
||||||
Browse(hwndDlg);
|
Browse(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_INCREMENTAL:
|
case IDC_INCREMENTAL:
|
||||||
incremental = IsDlgButtonChecked(hwndDlg, LOWORD(wParam));
|
incremental = IsDlgButtonChecked(hwndDlg, LOWORD(wParam));
|
||||||
|
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_SUBVOL), incremental);
|
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_SUBVOL), incremental);
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_BROWSE), incremental);
|
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_BROWSE), incremental);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_PARENT_BROWSE:
|
case IDC_PARENT_BROWSE:
|
||||||
BrowseParent(hwndDlg);
|
BrowseParent(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_CLONE_ADD:
|
case IDC_CLONE_ADD:
|
||||||
AddClone(hwndDlg);
|
AddClone(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
|
|
||||||
case IDC_CLONE_REMOVE:
|
case IDC_CLONE_REMOVE:
|
||||||
RemoveClone(hwndDlg);
|
RemoveClone(hwndDlg);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LBN_SELCHANGE:
|
case LBN_SELCHANGE:
|
||||||
switch (LOWORD(wParam)) {
|
switch (LOWORD(wParam)) {
|
||||||
case IDC_CLONE_LIST:
|
case IDC_CLONE_LIST:
|
||||||
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), TRUE);
|
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), true);
|
||||||
return TRUE;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} catch (const exception& e) {
|
||||||
|
error_message(hwnd, e.what());
|
||||||
|
}
|
||||||
|
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
|
||||||
|
@ -537,14 +518,14 @@ static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam,
|
||||||
if (bs)
|
if (bs)
|
||||||
return bs->SendDlgProc(hwndDlg, uMsg, wParam, lParam);
|
return bs->SendDlgProc(hwndDlg, uMsg, wParam, lParam);
|
||||||
else
|
else
|
||||||
return FALSE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BtrfsSend::Open(HWND hwnd, LPWSTR path) {
|
void BtrfsSend::Open(HWND hwnd, LPWSTR path) {
|
||||||
subvol = path;
|
subvol = path;
|
||||||
|
|
||||||
if (DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SEND_SUBVOL), hwnd, stub_SendDlgProc, (LPARAM)this) <= 0)
|
if (DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SEND_SUBVOL), hwnd, stub_SendDlgProc, (LPARAM)this) <= 0)
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
@ -552,70 +533,60 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||||
HANDLE token;
|
try {
|
||||||
|
win_handle token;
|
||||||
TOKEN_PRIVILEGES tp;
|
TOKEN_PRIVILEGES tp;
|
||||||
LUID luid;
|
LUID luid;
|
||||||
BtrfsSend* bs;
|
|
||||||
|
|
||||||
set_dpi_aware();
|
set_dpi_aware();
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
|
if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
CloseHandle(token);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
tp.Privileges[0].Luid = luid;
|
tp.Privileges[0].Luid = luid;
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
|
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
|
||||||
ShowError(hwnd, GetLastError());
|
throw last_error(GetLastError());
|
||||||
CloseHandle(token);
|
|
||||||
return;
|
BtrfsSend bs;
|
||||||
|
|
||||||
|
bs.Open(hwnd, lpszCmdLine);
|
||||||
|
} catch (const exception& e) {
|
||||||
|
error_message(hwnd, e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
bs = new BtrfsSend;
|
|
||||||
|
|
||||||
bs->Open(hwnd, lpszCmdLine);
|
|
||||||
|
|
||||||
delete bs;
|
|
||||||
|
|
||||||
CloseHandle(token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void send_subvol(std::wstring subvol, std::wstring file, std::wstring parent, std::vector<std::wstring> clones) {
|
static void send_subvol(const wstring& subvol, const wstring& file, const wstring& parent, const vector<wstring>& clones) {
|
||||||
char* buf;
|
char* buf;
|
||||||
HANDLE dirh, stream;
|
win_handle dirh, stream;
|
||||||
ULONG bss_size, i;
|
ULONG bss_size, i;
|
||||||
btrfs_send_subvol* bss;
|
btrfs_send_subvol* bss;
|
||||||
IO_STATUS_BLOCK iosb;
|
IO_STATUS_BLOCK iosb;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
btrfs_send_header header;
|
btrfs_send_header header;
|
||||||
btrfs_send_command end;
|
btrfs_send_command end;
|
||||||
BOOL success = FALSE;
|
|
||||||
|
|
||||||
buf = (char*)malloc(SEND_BUFFER_LEN);
|
buf = (char*)malloc(SEND_BUFFER_LEN);
|
||||||
|
|
||||||
dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
try {
|
||||||
|
dirh = CreateFileW(subvol.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (dirh == INVALID_HANDLE_VALUE)
|
if (dirh == INVALID_HANDLE_VALUE)
|
||||||
goto end3;
|
throw last_error(GetLastError());
|
||||||
|
|
||||||
stream = CreateFileW(file.c_str(), FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
stream = CreateFileW(file.c_str(), FILE_WRITE_DATA | DELETE, 0, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
if (stream == INVALID_HANDLE_VALUE) {
|
if (stream == INVALID_HANDLE_VALUE)
|
||||||
CloseHandle(dirh);
|
throw last_error(GetLastError());
|
||||||
goto end3;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
|
||||||
bss = (btrfs_send_subvol*)malloc(bss_size);
|
bss = (btrfs_send_subvol*)malloc(bss_size);
|
||||||
memset(bss, 0, bss_size);
|
memset(bss, 0, bss_size);
|
||||||
|
@ -623,21 +594,22 @@ static void send_subvol(std::wstring subvol, std::wstring file, std::wstring par
|
||||||
if (parent != L"") {
|
if (parent != L"") {
|
||||||
HANDLE parenth;
|
HANDLE parenth;
|
||||||
|
|
||||||
parenth = CreateFileW(parent.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
parenth = CreateFileW(parent.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (parenth == INVALID_HANDLE_VALUE)
|
if (parenth == INVALID_HANDLE_VALUE)
|
||||||
goto end2;
|
throw last_error(GetLastError());
|
||||||
|
|
||||||
bss->parent = parenth;
|
bss->parent = parenth;
|
||||||
} else
|
} else
|
||||||
bss->parent = NULL;
|
bss->parent = nullptr;
|
||||||
|
|
||||||
bss->num_clones = clones.size();
|
bss->num_clones = clones.size();
|
||||||
|
|
||||||
for (i = 0; i < bss->num_clones; i++) {
|
for (i = 0; i < bss->num_clones; i++) {
|
||||||
HANDLE h;
|
HANDLE h;
|
||||||
|
|
||||||
h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
h = CreateFileW(clones[i].c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
|
||||||
if (h == INVALID_HANDLE_VALUE) {
|
if (h == INVALID_HANDLE_VALUE) {
|
||||||
|
auto le = GetLastError();
|
||||||
ULONG j;
|
ULONG j;
|
||||||
|
|
||||||
for (j = 0; j < i; j++) {
|
for (j = 0; j < i; j++) {
|
||||||
|
@ -645,13 +617,14 @@ static void send_subvol(std::wstring subvol, std::wstring file, std::wstring par
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
goto end2;
|
|
||||||
|
throw last_error(le);
|
||||||
}
|
}
|
||||||
|
|
||||||
bss->clones[i] = h;
|
bss->clones[i] = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0);
|
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, nullptr, 0);
|
||||||
|
|
||||||
for (i = 0; i < bss->num_clones; i++) {
|
for (i = 0; i < bss->num_clones; i++) {
|
||||||
CloseHandle(bss->clones[i]);
|
CloseHandle(bss->clones[i]);
|
||||||
|
@ -660,48 +633,46 @@ static void send_subvol(std::wstring subvol, std::wstring file, std::wstring par
|
||||||
if (bss->parent) CloseHandle(bss->parent);
|
if (bss->parent) CloseHandle(bss->parent);
|
||||||
|
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
goto end2;
|
throw ntstatus_error(Status);
|
||||||
|
|
||||||
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic));
|
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(header.magic));
|
||||||
header.version = 1;
|
header.version = 1;
|
||||||
|
|
||||||
if (!WriteFile(stream, &header, sizeof(header), NULL, NULL))
|
if (!WriteFile(stream, &header, sizeof(header), nullptr, nullptr))
|
||||||
goto end2;
|
throw last_error(GetLastError());
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN);
|
Status = NtFsControlFile(dirh, nullptr, nullptr, nullptr, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, nullptr, 0, buf, SEND_BUFFER_LEN);
|
||||||
|
|
||||||
if (NT_SUCCESS(Status))
|
if (NT_SUCCESS(Status))
|
||||||
WriteFile(stream, buf, iosb.Information, NULL, NULL);
|
WriteFile(stream, buf, iosb.Information, nullptr, nullptr);
|
||||||
} while (NT_SUCCESS(Status));
|
} while (NT_SUCCESS(Status));
|
||||||
|
|
||||||
if (Status != STATUS_END_OF_FILE)
|
if (Status != STATUS_END_OF_FILE)
|
||||||
goto end2;
|
throw ntstatus_error(Status);
|
||||||
|
|
||||||
end.length = 0;
|
end.length = 0;
|
||||||
end.cmd = BTRFS_SEND_CMD_END;
|
end.cmd = BTRFS_SEND_CMD_END;
|
||||||
end.csum = 0x9dc96c50;
|
end.csum = 0x9dc96c50;
|
||||||
|
|
||||||
if (!WriteFile(stream, &end, sizeof(end), NULL, NULL))
|
if (!WriteFile(stream, &end, sizeof(end), nullptr, nullptr))
|
||||||
goto end2;
|
throw last_error(GetLastError());
|
||||||
|
|
||||||
SetEndOfFile(stream);
|
SetEndOfFile(stream);
|
||||||
|
} catch (...) {
|
||||||
success = TRUE;
|
|
||||||
|
|
||||||
end2:
|
|
||||||
if (!success) {
|
|
||||||
FILE_DISPOSITION_INFO fdi;
|
FILE_DISPOSITION_INFO fdi;
|
||||||
|
|
||||||
fdi.DeleteFile = TRUE;
|
fdi.DeleteFile = true;
|
||||||
|
|
||||||
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
|
||||||
|
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
} catch (...) {
|
||||||
|
free(buf);
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
CloseHandle(dirh);
|
|
||||||
CloseHandle(stream);
|
|
||||||
|
|
||||||
end3:
|
|
||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,40 +681,36 @@ extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
|
||||||
LPWSTR* args;
|
vector<wstring> args;
|
||||||
int num_args;
|
wstring subvol = L"", parent = L"", file = L"";
|
||||||
std::wstring subvol = L"", parent = L"", file = L"";
|
vector<wstring> clones;
|
||||||
std::vector<std::wstring> clones;
|
|
||||||
|
|
||||||
args = CommandLineToArgvW(lpszCmdLine, &num_args);
|
command_line_to_args(lpszCmdLine, args);
|
||||||
|
|
||||||
if (!args)
|
if (args.size() >= 2) {
|
||||||
return;
|
|
||||||
|
|
||||||
if (num_args >= 2) {
|
|
||||||
HANDLE token;
|
|
||||||
TOKEN_PRIVILEGES tp;
|
TOKEN_PRIVILEGES tp;
|
||||||
LUID luid;
|
LUID luid;
|
||||||
int i;
|
|
||||||
|
{
|
||||||
|
win_handle token;
|
||||||
|
|
||||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||||
goto end;
|
return;
|
||||||
|
|
||||||
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid))
|
if (!LookupPrivilegeValueW(nullptr, L"SeManageVolumePrivilege", &luid))
|
||||||
goto end;
|
return;
|
||||||
|
|
||||||
tp.PrivilegeCount = 1;
|
tp.PrivilegeCount = 1;
|
||||||
tp.Privileges[0].Luid = luid;
|
tp.Privileges[0].Luid = luid;
|
||||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||||
|
|
||||||
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
|
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr))
|
||||||
goto end;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(token);
|
for (unsigned int i = 0; i < args.size(); i++) {
|
||||||
|
|
||||||
for (i = 0; i < num_args; i++) {
|
|
||||||
if (args[i][0] == '-') {
|
if (args[i][0] == '-') {
|
||||||
if (args[i][2] == 0 && i < num_args - 1) {
|
if (args[i][2] == 0 && i < args.size() - 1) {
|
||||||
if (args[i][1] == 'p') {
|
if (args[i][1] == 'p') {
|
||||||
parent = args[i+1];
|
parent = args[i+1];
|
||||||
i++;
|
i++;
|
||||||
|
@ -760,12 +727,14 @@ void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nC
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subvol != L"" && file != L"")
|
if (subvol != L"" && file != L"") {
|
||||||
|
try {
|
||||||
send_subvol(subvol, file, parent, clones);
|
send_subvol(subvol, file, parent, clones);
|
||||||
|
} catch (const exception& e) {
|
||||||
|
cerr << "Error: " << e.what() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
|
||||||
LocalFree(args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
|
|
|
@ -19,23 +19,20 @@
|
||||||
|
|
||||||
#ifdef __REACTOS__
|
#ifdef __REACTOS__
|
||||||
#include "btrfs.h"
|
#include "btrfs.h"
|
||||||
#include <stdlib.h>
|
|
||||||
#else
|
#else
|
||||||
#include "../btrfs.h"
|
#include "../btrfs.h"
|
||||||
#endif
|
#endif
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class BtrfsSend {
|
class BtrfsSend {
|
||||||
public:
|
public:
|
||||||
BtrfsSend() {
|
BtrfsSend() {
|
||||||
started = FALSE;
|
started = false;
|
||||||
file[0] = 0;
|
file[0] = 0;
|
||||||
dirh = INVALID_HANDLE_VALUE;
|
dirh = INVALID_HANDLE_VALUE;
|
||||||
stream = INVALID_HANDLE_VALUE;
|
stream = INVALID_HANDLE_VALUE;
|
||||||
subvol = L"";
|
subvol = L"";
|
||||||
buf = NULL;
|
buf = nullptr;
|
||||||
incremental = FALSE;
|
incremental = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BtrfsSend() {
|
~BtrfsSend() {
|
||||||
|
@ -53,14 +50,13 @@ private:
|
||||||
void BrowseParent(HWND hwnd);
|
void BrowseParent(HWND hwnd);
|
||||||
void AddClone(HWND hwnd);
|
void AddClone(HWND hwnd);
|
||||||
void RemoveClone(HWND hwnd);
|
void RemoveClone(HWND hwnd);
|
||||||
void ShowSendError(UINT msg, ...);
|
|
||||||
|
|
||||||
BOOL started;
|
bool started;
|
||||||
BOOL incremental;
|
bool incremental;
|
||||||
WCHAR file[MAX_PATH], closetext[255];
|
WCHAR file[MAX_PATH], closetext[255];
|
||||||
HANDLE thread, dirh, stream;
|
HANDLE thread, dirh, stream;
|
||||||
HWND hwnd;
|
HWND hwnd;
|
||||||
std::wstring subvol;
|
wstring subvol;
|
||||||
char* buf;
|
char* buf;
|
||||||
std::vector <std::wstring> clones;
|
vector <wstring> clones;
|
||||||
};
|
};
|
||||||
|
|
|
@ -61,8 +61,8 @@ IDI_ICON1 ICON "subvol.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 1,0,2,0
|
FILEVERSION 1,1,0,0
|
||||||
PRODUCTVERSION 1,0,2,0
|
PRODUCTVERSION 1,1,0,0
|
||||||
FILEFLAGSMASK 0x17L
|
FILEFLAGSMASK 0x17L
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -78,12 +78,12 @@ BEGIN
|
||||||
BLOCK "080904b0"
|
BLOCK "080904b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "FileDescription", "WinBtrfs shell extension"
|
VALUE "FileDescription", "WinBtrfs shell extension"
|
||||||
VALUE "FileVersion", "1.0.2"
|
VALUE "FileVersion", "1.1"
|
||||||
VALUE "InternalName", "btrfs"
|
VALUE "InternalName", "btrfs"
|
||||||
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18"
|
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-18"
|
||||||
VALUE "OriginalFilename", "shellbtrfs.dll"
|
VALUE "OriginalFilename", "shellbtrfs.dll"
|
||||||
VALUE "ProductName", "WinBtrfs"
|
VALUE "ProductName", "WinBtrfs"
|
||||||
VALUE "ProductVersion", "1.0.2"
|
VALUE "ProductVersion", "1.1"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
@ -98,57 +98,59 @@ END
|
||||||
// Dialog
|
// Dialog
|
||||||
//
|
//
|
||||||
|
|
||||||
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 245
|
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 257
|
||||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
|
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
|
||||||
CAPTION "Inode property sheet"
|
CAPTION "Inode property sheet"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
FONT 8, "MS Shell Dlg", 400, 0, 0x0
|
||||||
BEGIN
|
BEGIN
|
||||||
LTEXT "Subvolume:",IDC_STATIC,14,21,38,8
|
LTEXT "Subvolume:",IDC_STATIC,14,21,38,8
|
||||||
LTEXT "Inode:",IDC_STATIC,14,35,21,8
|
LTEXT "Inode:",IDC_STATIC,14,35,21,8
|
||||||
GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,71
|
GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,85
|
||||||
LTEXT "Type:",IDC_STATIC,14,49,18,8
|
LTEXT "Type:",IDC_STATIC,14,49,18,8
|
||||||
GROUPBOX "POSIX permissions",IDC_STATIC,7,82,221,102
|
GROUPBOX "POSIX permissions",IDC_STATIC,7,96,221,102
|
||||||
LTEXT "User:",IDC_STATIC,14,97,17,8
|
LTEXT "User:",IDC_STATIC,14,111,17,8
|
||||||
LTEXT "Group:",IDC_STATIC,14,113,22,8
|
LTEXT "Group:",IDC_STATIC,14,127,22,8
|
||||||
EDITTEXT IDC_UID,94,95,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
EDITTEXT IDC_UID,94,109,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||||
EDITTEXT IDC_GID,94,111,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
EDITTEXT IDC_GID,94,125,40,14,ES_AUTOHSCROLL | ES_NUMBER
|
||||||
LTEXT "User",IDC_STATIC,14,144,15,8
|
LTEXT "User",IDC_STATIC,14,158,15,8
|
||||||
LTEXT "Group",IDC_STATIC,14,156,20,8
|
LTEXT "Group",IDC_STATIC,14,168,20,8
|
||||||
LTEXT "Others",IDC_STATIC,14,168,22,8
|
LTEXT "Others",IDC_STATIC,14,182,22,8
|
||||||
LTEXT "Read",IDC_STATIC,50,134,17,8
|
LTEXT "Read",IDC_STATIC,50,148,17,8
|
||||||
LTEXT "Write",IDC_STATIC,89,134,18,8
|
LTEXT "Write",IDC_STATIC,89,148,18,8
|
||||||
LTEXT "Execute",IDC_STATIC,129,134,30,8
|
LTEXT "Execute",IDC_STATIC,129,148,30,8
|
||||||
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,147,16,10
|
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,161,16,10
|
||||||
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,158,16,10
|
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,172,16,10
|
||||||
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,168,16,10
|
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,182,16,10
|
||||||
CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,147,16,10
|
CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,161,16,10
|
||||||
CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,158,16,10
|
CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,172,16,10
|
||||||
CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,168,16,10
|
CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,182,16,10
|
||||||
CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,147,16,10
|
CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,161,16,10
|
||||||
CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,158,16,10
|
CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,172,16,10
|
||||||
CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,168,16,10
|
CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,182,16,10
|
||||||
GROUPBOX "Flags",IDC_STATIC,7,190,221,48
|
GROUPBOX "Flags",IDC_STATIC,7,204,221,48
|
||||||
CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,204,86,10
|
CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,218,86,10
|
||||||
LTEXT "(blank)",IDC_INODE,78,35,70,8
|
LTEXT "(blank)",IDC_INODE,78,35,70,8
|
||||||
LTEXT "(blank)",IDC_TYPE,78,49,116,8
|
LTEXT "(blank)",IDC_TYPE,78,49,116,8
|
||||||
CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,218,46,10
|
CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,232,46,10
|
||||||
LTEXT "Size on disk:",IDC_STATIC,14,63,61,8
|
LTEXT "Size on disk:",IDC_STATIC,14,63,61,8
|
||||||
CONTROL "%s (<a>Details</a>)",IDC_SIZE_ON_DISK,"SysLink",WS_TABSTOP,78,63,142,8
|
CONTROL "%s (<a>Details</a>)",IDC_SIZE_ON_DISK,"SysLink",WS_TABSTOP,78,63,142,8
|
||||||
COMBOBOX IDC_COMPRESS_TYPE,63,217,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
COMBOBOX IDC_COMPRESS_TYPE,63,231,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
|
||||||
CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,204,80,10
|
CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,218,80,10
|
||||||
LTEXT "(blank)",IDC_SUBVOL,78,21,70,8
|
LTEXT "(blank)",IDC_SUBVOL,78,21,70,8
|
||||||
PUSHBUTTON "&Open as Admin",IDC_OPEN_ADMIN,151,21,70,14
|
PUSHBUTTON "&Open as Admin",IDC_OPEN_ADMIN,151,21,70,14
|
||||||
CONTROL "Set UID",IDC_SETUID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,147,40,10
|
CONTROL "Set UID",IDC_SETUID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,161,40,10
|
||||||
CONTROL "Set GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,158,40,10
|
CONTROL "Set GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,172,40,10
|
||||||
CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,168,34,10
|
CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,182,34,10
|
||||||
|
LTEXT "Compression ratio:",IDC_STATIC,14,77,61,8
|
||||||
|
LTEXT "%1.1f%%",IDC_COMPRESSION_RATIO,78,77,116,8
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 85
|
IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 98
|
||||||
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
|
||||||
CAPTION "Size details"
|
CAPTION "Size details"
|
||||||
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
FONT 8, "MS Shell Dlg", 400, 0, 0x1
|
||||||
BEGIN
|
BEGIN
|
||||||
DEFPUSHBUTTON "OK",IDOK,81,64,50,14
|
DEFPUSHBUTTON "OK",IDOK,81,77,50,14
|
||||||
LTEXT "Inline:",IDC_STATIC,7,7,21,8
|
LTEXT "Inline:",IDC_STATIC,7,7,21,8
|
||||||
LTEXT "Uncompressed:",IDC_STATIC,7,20,49,8
|
LTEXT "Uncompressed:",IDC_STATIC,7,20,49,8
|
||||||
LTEXT "ZLIB:",IDC_STATIC,7,33,18,8
|
LTEXT "ZLIB:",IDC_STATIC,7,33,18,8
|
||||||
|
@ -157,6 +159,8 @@ BEGIN
|
||||||
LTEXT "(blank)",IDC_SIZE_UNCOMPRESSED,63,20,142,8
|
LTEXT "(blank)",IDC_SIZE_UNCOMPRESSED,63,20,142,8
|
||||||
LTEXT "(blank)",IDC_SIZE_ZLIB,63,33,142,8
|
LTEXT "(blank)",IDC_SIZE_ZLIB,63,33,142,8
|
||||||
LTEXT "(blank)",IDC_SIZE_LZO,63,46,142,8
|
LTEXT "(blank)",IDC_SIZE_LZO,63,46,142,8
|
||||||
|
LTEXT "Zstd:",IDC_STATIC,7,59,16,8
|
||||||
|
LTEXT "(blank)",IDC_SIZE_ZSTD,63,59,142,8
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 251
|
IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 251
|
||||||
|
@ -382,7 +386,7 @@ BEGIN
|
||||||
LEFTMARGIN, 7
|
LEFTMARGIN, 7
|
||||||
RIGHTMARGIN, 205
|
RIGHTMARGIN, 205
|
||||||
TOPMARGIN, 7
|
TOPMARGIN, 7
|
||||||
BOTTOMMARGIN, 78
|
BOTTOMMARGIN, 93
|
||||||
END
|
END
|
||||||
|
|
||||||
IDD_VOL_PROP_SHEET, DIALOG
|
IDD_VOL_PROP_SHEET, DIALOG
|
||||||
|
@ -484,6 +488,22 @@ END
|
||||||
2 RT_MANIFEST "shellbtrfs.manifest"
|
2 RT_MANIFEST "shellbtrfs.manifest"
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// AFX_DIALOG_LAYOUT
|
||||||
|
//
|
||||||
|
|
||||||
|
IDD_SIZE_DETAILS AFX_DIALOG_LAYOUT
|
||||||
|
BEGIN
|
||||||
|
0
|
||||||
|
END
|
||||||
|
|
||||||
|
IDD_PROP_SHEET AFX_DIALOG_LAYOUT
|
||||||
|
BEGIN
|
||||||
|
0
|
||||||
|
END
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// String Table
|
// String Table
|
||||||
|
@ -746,6 +766,22 @@ BEGIN
|
||||||
IDS_BALANCE_CANCELLED_SHRINK "Device shrinking cancelled."
|
IDS_BALANCE_CANCELLED_SHRINK "Device shrinking cancelled."
|
||||||
IDS_BALANCE_COMPLETE_SHRINK "Device successfully shrunk."
|
IDS_BALANCE_COMPLETE_SHRINK "Device successfully shrunk."
|
||||||
IDS_BALANCE_FAILED_SHRINK "Device shrinking failed (error %08x, %s)"
|
IDS_BALANCE_FAILED_SHRINK "Device shrinking failed (error %08x, %s)"
|
||||||
|
IDS_COMPRESS_ZSTD "Zstd"
|
||||||
|
IDS_RECV_RTLUNICODETOUTF8N_FAILED "RtlUnicodeToUTF8N returned %08x (%s)."
|
||||||
|
IDS_REGCREATEKEY_FAILED "RegCreateKey returned %08x"
|
||||||
|
IDS_REGSETVALUEEX_FAILED "RegSetValueEx returned %08x"
|
||||||
|
IDS_REGCLOSEKEY_FAILED "RegCloseKey returned %08x"
|
||||||
|
IDS_REGDELETETREE_FAILED "RegDeleteTree returned %08x"
|
||||||
|
IDS_CANT_REFLINK_DIFFERENT_FS
|
||||||
|
"Cannot create a reflink between two different filesystems."
|
||||||
|
END
|
||||||
|
|
||||||
|
STRINGTABLE
|
||||||
|
BEGIN
|
||||||
|
IDS_INITCOMMONCONTROLSEX_FAILED "InitCommonControlsEx failed."
|
||||||
|
IDS_CANT_OPEN_MOUNTMGR "Could not get a handle to mount manager."
|
||||||
|
IDS_TVM_INSERTITEM_FAILED "TVM_INSERTITEM failed."
|
||||||
|
IDS_RECV_PATH_TOO_LONG "%S: path was too long."
|
||||||
END
|
END
|
||||||
|
|
||||||
#endif // English (United Kingdom) resources
|
#endif // English (United Kingdom) resources
|
||||||
|
|
|
@ -34,8 +34,11 @@
|
||||||
#include <winbase.h>
|
#include <winbase.h>
|
||||||
#include <strsafe.h>
|
#include <strsafe.h>
|
||||||
#include <ndk/iofuncs.h>
|
#include <ndk/iofuncs.h>
|
||||||
|
#include <ndk/obfuncs.h>
|
||||||
#endif
|
#endif
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
#include "../btrfs.h"
|
#include "../btrfs.h"
|
||||||
#include "../btrfsioctl.h"
|
#include "../btrfsioctl.h"
|
||||||
|
@ -44,6 +47,8 @@
|
||||||
#include "btrfsioctl.h"
|
#include "btrfsioctl.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
#define STATUS_SUCCESS (NTSTATUS)0x00000000
|
#define STATUS_SUCCESS (NTSTATUS)0x00000000
|
||||||
#define STATUS_BUFFER_OVERFLOW (NTSTATUS)0x80000005
|
#define STATUS_BUFFER_OVERFLOW (NTSTATUS)0x80000005
|
||||||
|
@ -79,6 +84,10 @@
|
||||||
#define funcname __func__
|
#define funcname __func__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable: 4800)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
@ -95,6 +104,10 @@ NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR UnicodeStringDestination, ULONG UnicodeS
|
||||||
PULONG UnicodeStringActualWCharCount, PCCH UTF8StringSource,
|
PULONG UnicodeStringActualWCharCount, PCCH UTF8StringSource,
|
||||||
ULONG UTF8StringByteCount);
|
ULONG UTF8StringByteCount);
|
||||||
|
|
||||||
|
NTSTATUS NTAPI RtlUnicodeToUTF8N(PCHAR UTF8StringDestination, ULONG UTF8StringMaxByteCount,
|
||||||
|
PULONG UTF8StringActualByteCount, PCWCH UnicodeStringSource,
|
||||||
|
ULONG UnicodeStringByteCount);
|
||||||
|
|
||||||
#ifndef __REACTOS__
|
#ifndef __REACTOS__
|
||||||
NTSTATUS WINAPI NtSetEaFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length);
|
NTSTATUS WINAPI NtSetEaFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length);
|
||||||
|
|
||||||
|
@ -179,11 +192,163 @@ typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
class win_handle {
|
||||||
|
public:
|
||||||
|
win_handle() {
|
||||||
|
}
|
||||||
|
|
||||||
|
win_handle(HANDLE nh) {
|
||||||
|
h = nh;
|
||||||
|
}
|
||||||
|
|
||||||
|
~win_handle() {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator HANDLE() const {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
win_handle& operator=(const HANDLE nh) {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(h);
|
||||||
|
|
||||||
|
h = nh;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE* operator&() {
|
||||||
|
return &h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class fff_handle {
|
||||||
|
public:
|
||||||
|
fff_handle() {
|
||||||
|
}
|
||||||
|
|
||||||
|
fff_handle(HANDLE nh) {
|
||||||
|
h = nh;
|
||||||
|
}
|
||||||
|
|
||||||
|
~fff_handle() {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator HANDLE() const {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
fff_handle& operator=(const HANDLE nh) {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
FindClose(h);
|
||||||
|
|
||||||
|
h = nh;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE* operator&() {
|
||||||
|
return &h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class nt_handle {
|
||||||
|
public:
|
||||||
|
nt_handle() {
|
||||||
|
}
|
||||||
|
|
||||||
|
nt_handle(HANDLE nh) {
|
||||||
|
h = nh;
|
||||||
|
}
|
||||||
|
|
||||||
|
~nt_handle() {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
NtClose(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator HANDLE() const {
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
nt_handle& operator=(const HANDLE nh) {
|
||||||
|
if (h != INVALID_HANDLE_VALUE)
|
||||||
|
NtClose(h);
|
||||||
|
|
||||||
|
h = nh;
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE* operator&() {
|
||||||
|
return &h;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
HANDLE h = INVALID_HANDLE_VALUE;
|
||||||
|
};
|
||||||
|
|
||||||
|
class string_error : public exception {
|
||||||
|
public:
|
||||||
|
string_error(int resno, ...);
|
||||||
|
|
||||||
|
const char* what() const noexcept {
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class last_error : public exception {
|
||||||
|
public:
|
||||||
|
last_error(DWORD errnum);
|
||||||
|
|
||||||
|
const char* what() const noexcept {
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ntstatus_error : public exception {
|
||||||
|
public:
|
||||||
|
ntstatus_error(NTSTATUS Status);
|
||||||
|
|
||||||
|
const char* what() const noexcept {
|
||||||
|
return msg.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
string msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef __REACTOS__
|
||||||
|
inline wstring to_wstring(uint8_t a) { WCHAR buffer[16]; swprintf(buffer, L"%d", a); return wstring(buffer); }
|
||||||
|
inline wstring to_wstring(uint16_t a) { WCHAR buffer[16]; swprintf(buffer, L"%d", a); return wstring(buffer); }
|
||||||
|
inline wstring to_wstring(uint32_t a) { WCHAR buffer[32]; swprintf(buffer, L"%ld", a); return wstring(buffer); }
|
||||||
|
inline wstring to_wstring(uint64_t a) { WCHAR buffer[64]; swprintf(buffer, L"%I64d", a); return wstring(buffer); }
|
||||||
|
#endif
|
||||||
|
|
||||||
extern HMODULE module;
|
extern HMODULE module;
|
||||||
void ShowError(HWND hwnd, ULONG err);
|
void format_size(uint64_t size, wstring& s, bool show_bytes);
|
||||||
void ShowNtStatusError(HWND hwnd, NTSTATUS Status);
|
|
||||||
void ShowStringError(HWND hwndDlg, int num, ...);
|
|
||||||
void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes);
|
|
||||||
void set_dpi_aware();
|
void set_dpi_aware();
|
||||||
std::wstring format_message(ULONG last_error);
|
wstring format_message(ULONG last_error);
|
||||||
std::wstring format_ntstatus(NTSTATUS Status);
|
wstring format_ntstatus(NTSTATUS Status);
|
||||||
|
bool load_string(HMODULE module, UINT id, wstring& s);
|
||||||
|
void wstring_sprintf(wstring& s, wstring fmt, ...);
|
||||||
|
void command_line_to_args(LPWSTR cmdline, vector<wstring> args);
|
||||||
|
void utf8_to_utf16(const string& utf8, wstring& utf16);
|
||||||
|
void utf16_to_utf8(const wstring& utf16, string& utf8);
|
||||||
|
void error_message(HWND hwnd, const char* msg);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -34,13 +34,13 @@ class BtrfsVolPropSheet : public IShellExtInit, IShellPropSheetExt {
|
||||||
public:
|
public:
|
||||||
BtrfsVolPropSheet() {
|
BtrfsVolPropSheet() {
|
||||||
refcount = 0;
|
refcount = 0;
|
||||||
ignore = TRUE;
|
ignore = true;
|
||||||
stgm_set = FALSE;
|
stgm_set = false;
|
||||||
devices = NULL;
|
devices = nullptr;
|
||||||
|
|
||||||
InterlockedIncrement(&objs_loaded);
|
InterlockedIncrement(&objs_loaded);
|
||||||
|
|
||||||
balance = NULL;
|
balance = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~BtrfsVolPropSheet() {
|
virtual ~BtrfsVolPropSheet() {
|
||||||
|
@ -84,7 +84,7 @@ public:
|
||||||
virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
|
virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
|
||||||
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
|
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
|
||||||
|
|
||||||
void FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_usage* usage);
|
void FormatUsage(HWND hwndDlg, wstring& s, btrfs_usage* usage);
|
||||||
void RefreshUsage(HWND hwndDlg);
|
void RefreshUsage(HWND hwndDlg);
|
||||||
void ShowUsage(HWND hwndDlg);
|
void ShowUsage(HWND hwndDlg);
|
||||||
INT_PTR CALLBACK UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
|
@ -93,20 +93,20 @@ public:
|
||||||
void ShowDevices(HWND hwndDlg);
|
void ShowDevices(HWND hwndDlg);
|
||||||
void ShowScrub(HWND hwndDlg);
|
void ShowScrub(HWND hwndDlg);
|
||||||
INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
|
||||||
void ShowStats(HWND hwndDlg, UINT64 devid);
|
void ShowStats(HWND hwndDlg, uint64_t devid);
|
||||||
void ResetStats(HWND hwndDlg);
|
void ResetStats(HWND hwndDlg);
|
||||||
|
|
||||||
btrfs_device* devices;
|
btrfs_device* devices;
|
||||||
BOOL readonly;
|
bool readonly;
|
||||||
BtrfsBalance* balance;
|
BtrfsBalance* balance;
|
||||||
BTRFS_UUID uuid;
|
BTRFS_UUID uuid;
|
||||||
BOOL uuid_set;
|
bool uuid_set;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
BOOL ignore;
|
bool ignore;
|
||||||
STGMEDIUM stgm;
|
STGMEDIUM stgm;
|
||||||
BOOL stgm_set;
|
bool stgm_set;
|
||||||
WCHAR fn[MAX_PATH];
|
wstring fn;
|
||||||
UINT64 stats_dev;
|
uint64_t stats_dev;
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
The following FSD are shared with: https://github.com/maharmstone/btrfs.
|
||||||
|
|
||||||
reactos/drivers/filesystems/btrfs # Synced to 1.1
|
reactos/drivers/filesystems/btrfs # Synced to 1.1
|
||||||
reactos/dll/shellext/shellbtrfs # Synced to 1.0.2
|
reactos/dll/shellext/shellbtrfs # Synced to 1.1
|
||||||
reactos/sdk/lib/fslib/btrfslib # Synced to 1.0.2
|
reactos/sdk/lib/fslib/btrfslib # Synced to 1.0.2
|
||||||
|
|
||||||
The following FSD are shared with: http://www.ext2fsd.com/
|
The following FSD are shared with: http://www.ext2fsd.com/
|
||||||
|
|
Loading…
Reference in a new issue