[SHELLBTRFS]

Sync the btrfs shell extension to 1.0

CORE-13763

svn path=/trunk/; revision=75793
This commit is contained in:
Pierre Schweitzer
2017-09-08 11:59:42 +00:00
parent 31328a8e2d
commit c032d89e77
27 changed files with 12358 additions and 1081 deletions
+12 -2
View File
@@ -1,23 +1,33 @@
set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
add_definitions(-D_WIN32_WINNT=0x603)
spec2def(shellbtrfs.dll shellbtrfs.spec)
list(APPEND SOURCE
balance.cpp
contextmenu.cpp
devices.cpp
factory.cpp
iconoverlay.cpp
main.cpp
propsheet.cpp
reactos.cpp
recv.cpp
scrub.cpp
send.cpp
volpropsheet.cpp
${CMAKE_CURRENT_BINARY_DIR}/shellbtrfs.def)
include_directories(
${REACTOS_SOURCE_DIR}/drivers/filesystems/btrfs)
file(GLOB shellbtrfs_rc_deps *.ico)
add_rc_deps(shellbtrfs.rc ${shellbtrfs_rc_deps})
add_library(shellbtrfs SHARED ${SOURCE} shellbtrfs.rc)
set_module_type(shellbtrfs win32dll UNICODE)
target_link_libraries(shellbtrfs uuid)
add_importlibs(shellbtrfs advapi32 advapi32_vista ole32 shell32 shlwapi user32 comctl32 uxtheme msvcrt kernel32 ntdll)
add_importlibs(shellbtrfs advapi32 advapi32_vista ole32 shell32 shlwapi user32 comctl32 uxtheme setupapi comdlg32 gdi32 msvcrt kernel32_vista kernel32 ntdll)
add_cd_file(TARGET shellbtrfs DESTINATION reactos/system32 FOR all)
File diff suppressed because it is too large Load Diff
+58
View File
@@ -0,0 +1,58 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <windows.h>
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "btrfsioctl.h"
#endif
class BtrfsBalance {
public:
BtrfsBalance(WCHAR* drive, BOOL RemoveDevice = FALSE, BOOL ShrinkDevice = FALSE) {
removing = FALSE;
devices = NULL;
called_from_RemoveDevice = RemoveDevice;
called_from_ShrinkDevice = ShrinkDevice;
wcscpy(fn, drive);
}
void ShowBalance(HWND hwndDlg);
INT_PTR CALLBACK BalanceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
INT_PTR CALLBACK BalanceOptsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
void ShowBalanceOptions(HWND hwndDlg, UINT8 type);
void SaveBalanceOpts(HWND hwndDlg);
void StartBalance(HWND hwndDlg);
void RefreshBalanceDlg(HWND hwndDlg, BOOL first);
void PauseBalance(HWND hwndDlg);
void StopBalance(HWND hwndDlg);
UINT32 balance_status;
btrfs_balance_opts data_opts, metadata_opts, system_opts;
UINT8 opts_type;
btrfs_query_balance bqb;
BOOL cancelling;
BOOL removing;
BOOL shrinking;
WCHAR fn[MAX_PATH];
btrfs_device* devices;
BOOL readonly;
BOOL called_from_RemoveDevice, called_from_ShrinkDevice;
};
File diff suppressed because it is too large Load Diff
+24 -15
View File
@@ -1,17 +1,17 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
@@ -25,6 +25,8 @@ public:
refcount = 0;
ignore = TRUE;
stgm_set = FALSE;
uacicon = NULL;
allow_snapshot = FALSE;
InterlockedIncrement(&objs_loaded);
}
@@ -33,42 +35,49 @@ public:
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
if (uacicon)
DeleteObject(uacicon);
InterlockedDecrement(&objs_loaded);
}
// IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
ULONG __stdcall AddRef() {
return InterlockedIncrement(&refcount);
}
ULONG __stdcall Release() {
LONG rc = InterlockedDecrement(&refcount);
if (rc == 0)
delete this;
return rc;
}
// IShellExtInit
virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID);
// IContextMenu
virtual HRESULT __stdcall QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
virtual HRESULT __stdcall InvokeCommand(LPCMINVOKECOMMANDINFO pici);
virtual HRESULT __stdcall GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax);
private:
LONG refcount;
BOOL ignore;
BOOL ignore, allow_snapshot;
BOOL bg;
WCHAR path[MAX_PATH];
STGMEDIUM stgm;
BOOL stgm_set;
HBITMAP uacicon;
BOOL reflink_copy(HWND hwnd, const WCHAR* fn, const WCHAR* dir);
void get_uac_icon();
};
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef __REACTOS__
#include <windows.h>
#include <winternl.h>
#else
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <ndk/iofuncs.h>
#include <ndk/iotypes.h>
#endif
#include <shlobj.h>
#include <vector>
#include <string>
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "btrfsioctl.h"
#endif
typedef struct {
std::wstring pnp_name;
std::wstring friendly_name;
std::wstring drive;
std::wstring fstype;
ULONG disk_num;
ULONG part_num;
UINT64 size;
BOOL has_parts;
BTRFS_UUID fs_uuid;
BTRFS_UUID dev_uuid;
BOOL ignore;
BOOL multi_device;
BOOL is_disk;
} device;
typedef struct {
const WCHAR* name;
const char* magic;
ULONG magiclen;
UINT32 sboff;
UINT32 kboff;
} fs_identifier;
// This list is compiled from information in libblkid, part of util-linux
// and likewise under the LGPL. Thanks!
const static fs_identifier fs_ident[] = {
{ L"BeFS", "BFS1", 4, 0x20, 0 },
{ L"BeFS", "1SFB", 4, 0x20, 0 },
{ L"BeFS", "BFS1", 4, 0x220, 0 },
{ L"BeFS", "1SFB", 4, 0x220, 0 },
{ L"BFS", "\xce\xfa\xad\x1b", 4, 0, 0 },
{ L"RomFS", "-rom1fs-", 8, 0, 0 },
{ L"SquashFS", "hsqs", 4, 0, 0 },
{ L"SquashFS", "sqsh", 4, 0, 0 },
{ L"SquashFS", "hsqs", 4, 0, 0 },
{ L"UBIFS", "\x31\x18\x10\x06", 4, 0, 0 },
{ L"XFS", "XFSB", 4, 0, 0 },
{ L"ext2", "\123\357", 2, 0x38, 1 },
{ L"F2FS", "\x10\x20\xF5\xF2", 4, 0, 1 },
{ L"HFS", "BD", 2, 0, 1 },
{ L"HFS", "BD", 2, 0, 1 },
{ L"HFS", "H+", 2, 0, 1 },
{ L"HFS", "HX", 2, 0, 1 },
{ L"Minix", "\177\023", 2, 0x10, 1 },
{ L"Minix", "\217\023", 2, 0x10, 1 },
{ L"Minix", "\023\177", 2, 0x10, 1 },
{ L"Minix", "\023\217", 2, 0x10, 1 },
{ L"Minix", "\150\044", 2, 0x10, 1 },
{ L"Minix", "\170\044", 2, 0x10, 1 },
{ L"Minix", "\044\150", 2, 0x10, 1 },
{ L"Minix", "\044\170", 2, 0x10, 1 },
{ L"Minix", "\132\115", 2, 0x10, 1 },
{ L"Minix", "\115\132", 2, 0x10, 1 },
{ L"OCFS", "OCFSV2", 6, 0, 1 },
{ L"SysV", "\x2b\x55\x44", 3, 0x400, 1 },
{ L"SysV", "\x44\x55\x2b", 3, 0x400, 1 },
{ L"VXFS", "\365\374\001\245", 4, 0, 1 },
{ L"OCFS", "OCFSV2", 6, 0, 2 },
{ L"ExFAT", "EXFAT ", 8, 3 },
{ L"NTFS", "NTFS ", 8, 3 },
{ L"NetWare", "SPB5", 4, 0, 4 },
{ L"OCFS", "OCFSV2", 6, 0, 4 },
{ L"HPFS", "\x49\xe8\x95\xf9", 4, 0, 8 },
{ L"OCFS", "OracleCFS", 9, 0, 8 },
{ L"OCFS", "OCFSV2", 6, 0, 8 },
{ L"ReFS", "\000\000\000ReFS\000", 8 },
{ L"ReiserFS", "ReIsErFs", 8, 0x34, 8 },
{ L"ReiserFS", "ReIsErFs", 8, 20, 8 },
{ L"ISO9660", "CD001", 5, 1, 32, },
{ L"ISO9660", "CDROM", 5, 9, 32, },
{ L"JFS", "JFS1", 4, 0, 32 },
{ L"OCFS", "ORCLDISK", 8, 32 },
{ L"UDF", "BEA01", 5, 1, 32 },
{ L"UDF", "BOOT2", 5, 1, 32 },
{ L"UDF", "CD001", 5, 1, 32 },
{ L"UDF", "CDW02", 5, 1, 32 },
{ L"UDF", "NSR02", 5, 1, 32 },
{ L"UDF", "NSR03", 5, 1, 32 },
{ L"UDF", "TEA01", 5, 1, 32 },
{ L"Btrfs", "_BHRfS_M", 8, 0x40, 64 },
{ L"GFS", "\x01\x16\x19\x70", 4, 0, 64 },
{ L"GFS", "\x01\x16\x19\x70", 4, 0, 64 },
{ L"ReiserFS", "ReIsEr2Fs", 9, 0x34, 64 },
{ L"ReiserFS", "ReIsEr3Fs", 9, 0x34, 64 },
{ L"ReiserFS", "ReIsErFs", 8, 0x34, 64 },
{ L"ReiserFS", "ReIsEr4", 7, 0, 64 },
{ L"VMFS", "\x0d\xd0\x01\xc0", 4, 0, 1024 },
{ L"VMFS", "\x5e\xf1\xab\x2f", 4, 0, 2048 },
{ L"FAT", "MSWIN", 5, 0x52, 0 },
{ L"FAT", "FAT32 ", 8, 0x52, 0 },
{ L"FAT", "MSDOS", 5, 0x36, 0 },
{ L"FAT", "FAT16 ", 8, 0x36, 0 },
{ L"FAT", "FAT12 ", 8, 0x36, 0 },
{ L"FAT", "FAT ", 8, 0x36, 0 },
{ L"FAT", "\353", 1, 0, 0 },
{ L"FAT", "\351", 1, 0, 0},
{ L"FAT", "\125\252", 2, 0x1fe, 0 },
{ NULL, 0, 0, 0 }
};
class BtrfsDeviceAdd {
public:
INT_PTR CALLBACK DeviceAddDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ShowDialog();
void AddDevice(HWND hwndDlg);
BtrfsDeviceAdd(HINSTANCE hinst, HWND hwnd, WCHAR* cmdline);
private:
void populate_device_tree(HWND tree);
HINSTANCE hinst;
HWND hwnd;
WCHAR* cmdline;
device* sel;
std::vector<device> device_list;
};
class BtrfsDeviceResize {
public:
INT_PTR CALLBACK DeviceResizeDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ShowDialog(HWND hwnd, WCHAR* fn, UINT64 dev_id);
private:
void do_resize(HWND hwndDlg);
UINT64 dev_id, new_size;
WCHAR fn[MAX_PATH], new_size_text[255];
btrfs_device dev_info;
};
+24 -12
View File
@@ -1,27 +1,29 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "shellext.h"
#include <windows.h>
#include "factory.h"
#include "iconoverlay.h"
#include "contextmenu.h"
#include "propsheet.h"
#include "volpropsheet.h"
HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
if (iid == IID_IUnknown || iid == IID_IClassFactory) {
*ppv = static_cast<IClassFactory*>(this);
} else {
@@ -52,31 +54,41 @@ HRESULT __stdcall Factory::CreateInstance(IUnknown* pUnknownOuter, const IID& ii
return bio->QueryInterface(iid, ppv);
}
break;
case FactoryContextMenu:
if (iid == IID_IUnknown || iid == IID_IContextMenu || iid == IID_IShellExtInit) {
BtrfsContextMenu* bcm = new BtrfsContextMenu;
if (!bcm)
return E_OUTOFMEMORY;
return bcm->QueryInterface(iid, ppv);
}
break;
case FactoryPropSheet:
if (iid == IID_IUnknown || iid == IID_IShellPropSheetExt || iid == IID_IShellExtInit) {
BtrfsPropSheet* bps = new BtrfsPropSheet;
if (!bps)
return E_OUTOFMEMORY;
return bps->QueryInterface(iid, ppv);
}
break;
case FactoryVolPropSheet:
if (iid == IID_IUnknown || iid == IID_IShellPropSheetExt || iid == IID_IShellExtInit) {
BtrfsVolPropSheet* bps = new BtrfsVolPropSheet;
if (!bps)
return E_OUTOFMEMORY;
return bps->QueryInterface(iid, ppv);
}
break;
default:
break;
}
*ppv = NULL;
return E_NOINTERFACE;
}
+13 -12
View File
@@ -1,17 +1,17 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
@@ -21,7 +21,8 @@ typedef enum {
FactoryUnknown,
FactoryIconHandler,
FactoryContextMenu,
FactoryPropSheet
FactoryPropSheet,
FactoryVolPropSheet
} factory_type;
class Factory : public IClassFactory {
@@ -37,27 +38,27 @@ public:
}
// IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
ULONG __stdcall AddRef() {
return InterlockedIncrement(&refcount);
}
ULONG __stdcall Release() {
LONG rc = InterlockedDecrement(&refcount);
if (rc == 0)
delete this;
return rc;
}
// IClassFactory
virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
factory_type type;
private:
+23 -35
View File
@@ -1,20 +1,21 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "shellext.h"
#ifndef __REACTOS__
#include <windows.h>
#include <winternl.h>
@@ -28,25 +29,12 @@
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "../../drivers/filesystems/btrfs/btrfsioctl.h"
#include "btrfsioctl.h"
#endif
#ifndef __REACTOS__
#ifdef __cplusplus
extern "C" {
#endif
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
#ifdef __cplusplus
}
#endif
#define STATUS_SUCCESS 0
#endif
extern HMODULE module;
HRESULT __stdcall BtrfsIconOverlay::QueryInterface(REFIID riid, void **ppObj) {
if (riid == IID_IUnknown || riid == IID_IShellIconOverlayIdentifier) {
*ppObj = static_cast<IShellIconOverlayIdentifier*>(this);
*ppObj = static_cast<IShellIconOverlayIdentifier*>(this);
AddRef();
return S_OK;
}
@@ -57,31 +45,31 @@ HRESULT __stdcall BtrfsIconOverlay::QueryInterface(REFIID riid, void **ppObj) {
HRESULT __stdcall BtrfsIconOverlay::GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags) {
WCHAR dllpath[MAX_PATH];
GetModuleFileNameW(module, dllpath, sizeof(dllpath));
if (cchMax < (int)wcslen(dllpath))
if ((size_t)cchMax < wcslen(dllpath))
return E_INVALIDARG;
if (!pIndex)
return E_INVALIDARG;
if (!pdwFlags)
return E_INVALIDARG;
wcscpy(pwszIconFile, dllpath);
*pIndex = 0;
*pdwFlags = ISIOI_ICONFILE | ISIOI_ICONINDEX;
return S_OK;
}
HRESULT __stdcall BtrfsIconOverlay::GetPriority(int *pPriority) {
if (!pPriority)
return E_INVALIDARG;
*pPriority = 0;
return S_OK;
}
@@ -90,20 +78,20 @@ HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib)
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
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);
if (h == INVALID_HANDLE_VALUE)
return S_FALSE;
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
if (Status != STATUS_SUCCESS) {
if (!NT_SUCCESS(Status)) {
CloseHandle(h);
return S_FALSE;
}
CloseHandle(h);
return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE;
}
+10 -10
View File
@@ -1,17 +1,17 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
@@ -31,24 +31,24 @@ public:
}
// IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
ULONG __stdcall AddRef() {
return InterlockedIncrement(&refcount);
}
ULONG __stdcall Release() {
LONG rc = InterlockedDecrement(&refcount);
if (rc == 0)
delete this;
return rc;
}
// IShellIconOverlayIdentifier
virtual HRESULT __stdcall GetOverlayInfo(PWSTR pwszIconFile, int cchMax, int* pIndex, DWORD* pdwFlags);
virtual HRESULT __stdcall GetPriority(int *pPriority);
virtual HRESULT __stdcall IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib);
+445 -73
View File
@@ -1,40 +1,284 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#ifndef __REACTOS__
#define _WIN32_WINNT 0x0600
#endif
#include "shellext.h"
#include <windows.h>
#include <commctrl.h>
#include <strsafe.h>
#include <stddef.h>
#include "factory.h"
#include "resource.h"
static const GUID CLSID_ShellBtrfsIconHandler = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf0 } };
static const GUID CLSID_ShellBtrfsContextMenu = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf1 } };
static const GUID CLSID_ShellBtrfsPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf2 } };
static const GUID CLSID_ShellBtrfsVolPropSheet = { 0x2690b74f, 0xf353, 0x422d, { 0xbb, 0x12, 0x40, 0x15, 0x81, 0xee, 0xf8, 0xf3 } };
#define COM_DESCRIPTION_ICON_HANDLER L"WinBtrfs shell extension (icon handler)"
#define COM_DESCRIPTION_CONTEXT_MENU L"WinBtrfs shell extension (context menu)"
#define COM_DESCRIPTION_PROP_SHEET L"WinBtrfs shell extension (property sheet)"
#define COM_DESCRIPTION_VOL_PROP_SHEET L"WinBtrfs shell extension (volume property sheet)"
#define ICON_OVERLAY_NAME L"WinBtrfs"
typedef enum _PROCESS_DPI_AWARENESS {
PROCESS_DPI_UNAWARE,
PROCESS_SYSTEM_DPI_AWARE,
PROCESS_PER_MONITOR_DPI_AWARE
} PROCESS_DPI_AWARENESS;
typedef ULONG (WINAPI *_RtlNtStatusToDosError)(NTSTATUS Status);
typedef HRESULT (WINAPI *_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS value);
HMODULE module;
LONG objs_loaded = 0;
void ShowError(HWND hwnd, ULONG err) {
WCHAR* buf;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
err, 0, (WCHAR*)&buf, 0, NULL) == 0) {
MessageBoxW(hwnd, L"FormatMessage failed", L"Error", MB_ICONERROR);
return;
}
MessageBoxW(hwnd, buf, L"Error", MB_ICONERROR);
LocalFree(buf);
}
void ShowStringError(HWND hwndDlg, int num, ...) {
WCHAR title[255], s[1024], t[1024];
va_list ap;
if (!LoadStringW(module, IDS_ERROR, title, sizeof(title) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
return;
}
if (!LoadStringW(module, num, s, sizeof(s) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
return;
}
va_start(ap, num);
#ifndef __REACTOS__
vswprintf(t, sizeof(t) / sizeof(WCHAR), s, ap);
#else
vsnwprintf(t, sizeof(t) / sizeof(WCHAR), s, ap);
#endif
MessageBoxW(hwndDlg, t, title, MB_ICONERROR);
va_end(ap);
}
void ShowNtStatusError(HWND hwnd, NTSTATUS Status) {
_RtlNtStatusToDosError RtlNtStatusToDosError;
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
if (!ntdll) {
MessageBoxW(hwnd, L"Error loading ntdll.dll", L"Error", MB_ICONERROR);
return;
}
RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError");
if (!RtlNtStatusToDosError) {
MessageBoxW(hwnd, L"Error loading RtlNtStatusToDosError in ntdll.dll", L"Error", MB_ICONERROR);
FreeLibrary(ntdll);
return;
}
ShowError(hwnd, RtlNtStatusToDosError(Status));
FreeLibrary(ntdll);
}
void set_dpi_aware() {
_SetProcessDpiAwareness SetProcessDpiAwareness;
HMODULE shcore = LoadLibraryW(L"shcore.dll");
if (!shcore)
return;
SetProcessDpiAwareness = (_SetProcessDpiAwareness)GetProcAddress(shcore, "SetProcessDpiAwareness");
if (!SetProcessDpiAwareness)
return;
SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE);
}
void format_size(UINT64 size, WCHAR* s, ULONG len, BOOL show_bytes) {
WCHAR nb[255], nb2[255], t[255], bytes[255];
WCHAR kb[255];
ULONG sr;
float f;
NUMBERFMTW fmt;
WCHAR thou[4], grouping[64], *c;
_i64tow(size, nb, 10);
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, thou, sizeof(thou) / sizeof(WCHAR));
fmt.NumDigits = 0;
fmt.LeadingZero = 1;
fmt.lpDecimalSep = (LPWSTR)L"."; // not used
fmt.lpThousandSep = thou;
fmt.NegativeOrder = 0;
// Grouping code copied from dlls/shlwapi/string.c in Wine - thank you
fmt.Grouping = 0;
GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SGROUPING, grouping, sizeof(grouping) / sizeof(WCHAR));
c = grouping;
while (*c) {
if (*c >= '0' && *c < '9') {
fmt.Grouping *= 10;
fmt.Grouping += *c - '0';
}
c++;
}
if (fmt.Grouping % 10 == 0)
fmt.Grouping /= 10;
else
fmt.Grouping *= 10;
GetNumberFormatW(LOCALE_USER_DEFAULT, 0, nb, &fmt, nb2, sizeof(nb2) / sizeof(WCHAR));
if (size < 1024) {
if (!LoadStringW(module, size == 1 ? IDS_SIZE_BYTE : IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(NULL, GetLastError());
return;
}
if (StringCchPrintfW(s, len, t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) {
ShowError(NULL, ERROR_INSUFFICIENT_BUFFER);
return;
}
return;
}
if (show_bytes) {
if (!LoadStringW(module, IDS_SIZE_BYTES, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(NULL, GetLastError());
return;
}
if (StringCchPrintfW(bytes, sizeof(bytes) / sizeof(WCHAR), t, nb2) == STRSAFE_E_INSUFFICIENT_BUFFER) {
ShowError(NULL, ERROR_INSUFFICIENT_BUFFER);
return;
}
}
if (size >= 1152921504606846976) {
sr = IDS_SIZE_EB;
f = (float)size / 1152921504606846976.0f;
} else if (size >= 1125899906842624) {
sr = IDS_SIZE_PB;
f = (float)size / 1125899906842624.0f;
} else if (size >= 1099511627776) {
sr = IDS_SIZE_TB;
f = (float)size / 1099511627776.0f;
} else if (size >= 1073741824) {
sr = IDS_SIZE_GB;
f = (float)size / 1073741824.0f;
} else if (size >= 1048576) {
sr = IDS_SIZE_MB;
f = (float)size / 1048576.0f;
} else {
sr = IDS_SIZE_KB;
f = (float)size / 1024.0f;
}
if (!LoadStringW(module, sr, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(NULL, GetLastError());
return;
}
if (show_bytes) {
if (StringCchPrintfW(kb, sizeof(kb) / sizeof(WCHAR), t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) {
ShowError(NULL, ERROR_INSUFFICIENT_BUFFER);
return;
}
if (!LoadStringW(module, IDS_SIZE_LARGE, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(NULL, GetLastError());
return;
}
if (StringCchPrintfW(s, len, t, kb, bytes) == STRSAFE_E_INSUFFICIENT_BUFFER) {
ShowError(NULL, ERROR_INSUFFICIENT_BUFFER);
return;
}
} else {
if (StringCchPrintfW(s, len, t, f) == STRSAFE_E_INSUFFICIENT_BUFFER) {
ShowError(NULL, ERROR_INSUFFICIENT_BUFFER);
return;
}
}
}
std::wstring format_message(ULONG last_error) {
WCHAR* buf;
std::wstring s;
if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
last_error, 0, (WCHAR*)&buf, 0, NULL) == 0) {
return L"(error retrieving message)";
}
s = buf;
LocalFree(buf);
// remove trailing newline
while (s.length() > 0 && (s.substr(s.length() - 1, 1) == L"\r" || s.substr(s.length() - 1, 1) == L"\n"))
s = s.substr(0, s.length() - 1);
return s;
}
std::wstring format_ntstatus(NTSTATUS Status) {
_RtlNtStatusToDosError RtlNtStatusToDosError;
std::wstring s;
HMODULE ntdll = LoadLibraryW(L"ntdll.dll");
if (!ntdll)
return L"(error loading ntdll.dll)";
RtlNtStatusToDosError = (_RtlNtStatusToDosError)GetProcAddress(ntdll, "RtlNtStatusToDosError");
if (!RtlNtStatusToDosError) {
FreeLibrary(ntdll);
return L"(error loading RtlNtStatusToDosError)";
}
s = format_message(RtlNtStatusToDosError(Status));
FreeLibrary(ntdll);
return s;
}
#ifdef __cplusplus
extern "C" {
#endif
@@ -50,7 +294,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
return E_OUTOFMEMORY;
else {
fact->type = FactoryIconHandler;
return fact->QueryInterface(riid, ppv);
}
} else if (rclsid == CLSID_ShellBtrfsContextMenu) {
@@ -59,7 +303,7 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
return E_OUTOFMEMORY;
else {
fact->type = FactoryContextMenu;
return fact->QueryInterface(riid, ppv);
}
} else if (rclsid == CLSID_ShellBtrfsPropSheet) {
@@ -68,7 +312,16 @@ STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
return E_OUTOFMEMORY;
else {
fact->type = FactoryPropSheet;
return fact->QueryInterface(riid, ppv);
}
} else if (rclsid == CLSID_ShellBtrfsVolPropSheet) {
Factory* fact = new Factory;
if (!fact)
return E_OUTOFMEMORY;
else {
fact->type = FactoryVolPropSheet;
return fact->QueryInterface(riid, ppv);
}
}
@@ -80,34 +333,34 @@ static BOOL write_reg_key(HKEY root, const WCHAR* keyname, const WCHAR* val, DWO
LONG l;
HKEY hk;
DWORD dispos;
l = RegCreateKeyExW(root, keyname, NULL, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dispos);
l = RegCreateKeyExW(root, keyname, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hk, &dispos);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegCreateKey returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
}
l = RegSetValueExW(hk, val, NULL, type, data, datasize);
l = RegSetValueExW(hk, val, 0, type, data, datasize);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegSetValueEx returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
}
l = RegCloseKey(hk);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegCloseKey returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
}
return TRUE;
}
@@ -115,26 +368,26 @@ static BOOL register_clsid(const GUID clsid, const WCHAR* description) {
WCHAR* clsidstring;
WCHAR inproc[MAX_PATH], progid[MAX_PATH], clsidkeyname[MAX_PATH], dllpath[MAX_PATH];
BOOL ret = FALSE;
StringFromCLSID(clsid, &clsidstring);
wsprintfW(inproc, L"CLSID\\%s\\InprocServer32", clsidstring);
wsprintfW(progid, L"CLSID\\%s\\ProgId", clsidstring);
wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring);
if (!write_reg_key(HKEY_CLASSES_ROOT, clsidkeyname, NULL, REG_SZ, (BYTE*)description, (wcslen(description) + 1) * sizeof(WCHAR)))
goto end;
GetModuleFileNameW(module, dllpath, sizeof(dllpath));
if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, NULL, REG_SZ, (BYTE*)dllpath, (wcslen(dllpath) + 1) * sizeof(WCHAR)))
goto end;
if (!write_reg_key(HKEY_CLASSES_ROOT, inproc, L"ThreadingModel", REG_SZ, (BYTE*)L"Apartment", (wcslen(L"Apartment") + 1) * sizeof(WCHAR)))
goto end;
ret = TRUE;
end:
CoTaskMemFree(clsidstring);
@@ -146,21 +399,21 @@ static BOOL unregister_clsid(const GUID clsid) {
WCHAR clsidkeyname[MAX_PATH];
BOOL ret = FALSE;
LONG l;
StringFromCLSID(clsid, &clsidstring);
wsprintfW(clsidkeyname, L"CLSID\\%s", clsidstring);
l = RegDeleteTreeW(HKEY_CLASSES_ROOT, clsidkeyname);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegDeleteTree returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
ret = FALSE;
} else
} else
ret = TRUE;
CoTaskMemFree(clsidstring);
return ret;
@@ -170,17 +423,17 @@ static BOOL reg_icon_overlay(const GUID clsid, const WCHAR* name) {
WCHAR path[MAX_PATH];
WCHAR* clsidstring;
BOOL ret = FALSE;
StringFromCLSID(clsid, &clsidstring);
wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\");
wcscat(path, name);
if (!write_reg_key(HKEY_LOCAL_MACHINE, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR)))
goto end;
ret = TRUE;
end:
CoTaskMemFree(clsidstring);
@@ -190,19 +443,19 @@ end:
static BOOL unreg_icon_overlay(const WCHAR* name) {
WCHAR path[MAX_PATH];
LONG l;
wcscpy(path, L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\ShellIconOverlayIdentifiers\\");
wcscat(path, name);
l = RegDeleteTreeW(HKEY_LOCAL_MACHINE, path);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegDeleteTree returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
} else
} else
return TRUE;
}
@@ -210,18 +463,18 @@ static BOOL reg_context_menu_handler(const GUID clsid, const WCHAR* filetype, co
WCHAR path[MAX_PATH];
WCHAR* clsidstring;
BOOL ret = FALSE;
StringFromCLSID(clsid, &clsidstring);
wcscpy(path, filetype);
wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\");
wcscat(path, name);
if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR)))
goto end;
ret = TRUE;
end:
CoTaskMemFree(clsidstring);
@@ -231,20 +484,20 @@ end:
static BOOL unreg_context_menu_handler(const WCHAR* filetype, const WCHAR* name) {
WCHAR path[MAX_PATH];
LONG l;
wcscpy(path, filetype);
wcscat(path, L"\\ShellEx\\ContextMenuHandlers\\");
wcscat(path, name);
l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegDeleteTree returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
} else
} else
return TRUE;
}
@@ -252,18 +505,18 @@ static BOOL reg_prop_sheet_handler(const GUID clsid, const WCHAR* filetype, cons
WCHAR path[MAX_PATH];
WCHAR* clsidstring;
BOOL ret = FALSE;
StringFromCLSID(clsid, &clsidstring);
wcscpy(path, filetype);
wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\");
wcscat(path, name);
if (!write_reg_key(HKEY_CLASSES_ROOT, path, NULL, REG_SZ, (BYTE*)clsidstring, (wcslen(clsidstring) + 1) * sizeof(WCHAR)))
goto end;
ret = TRUE;
end:
CoTaskMemFree(clsidstring);
@@ -273,74 +526,86 @@ end:
static BOOL unreg_prop_sheet_handler(const WCHAR* filetype, const WCHAR* name) {
WCHAR path[MAX_PATH];
LONG l;
wcscpy(path, filetype);
wcscat(path, L"\\ShellEx\\PropertySheetHandlers\\");
wcscat(path, name);
l = RegDeleteTreeW(HKEY_CLASSES_ROOT, path);
if (l != ERROR_SUCCESS) {
WCHAR s[255];
wsprintfW(s, L"RegDeleteTree returned %08x", l);
MessageBoxW(0, s, NULL, MB_ICONERROR);
return FALSE;
} else
} else
return TRUE;
}
STDAPI DllRegisterServer(void) {
if (!register_clsid(CLSID_ShellBtrfsIconHandler, COM_DESCRIPTION_ICON_HANDLER))
return E_FAIL;
if (!register_clsid(CLSID_ShellBtrfsContextMenu, COM_DESCRIPTION_CONTEXT_MENU))
return E_FAIL;
if (!register_clsid(CLSID_ShellBtrfsPropSheet, COM_DESCRIPTION_PROP_SHEET))
return E_FAIL;
if (!register_clsid(CLSID_ShellBtrfsVolPropSheet, COM_DESCRIPTION_VOL_PROP_SHEET))
return E_FAIL;
if (!reg_icon_overlay(CLSID_ShellBtrfsIconHandler, ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register icon overlay.", NULL, MB_ICONERROR);
return E_FAIL;
}
if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Directory\\Background", ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR);
return E_FAIL;
}
if (!reg_context_menu_handler(CLSID_ShellBtrfsContextMenu, L"Folder", ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register context menu handler.", NULL, MB_ICONERROR);
return E_FAIL;
}
if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"Folder", ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR);
return E_FAIL;
}
if (!reg_prop_sheet_handler(CLSID_ShellBtrfsPropSheet, L"*", ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register property sheet handler.", NULL, MB_ICONERROR);
return E_FAIL;
}
if (!reg_prop_sheet_handler(CLSID_ShellBtrfsVolPropSheet, L"Drive", ICON_OVERLAY_NAME)) {
MessageBoxW(0, L"Failed to register volume property sheet handler.", NULL, MB_ICONERROR);
return E_FAIL;
}
return S_OK;
}
STDAPI DllUnregisterServer(void) {
unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME);
unreg_prop_sheet_handler(L"*", ICON_OVERLAY_NAME);
unreg_prop_sheet_handler(L"Drive", ICON_OVERLAY_NAME);
unreg_context_menu_handler(L"Folder", ICON_OVERLAY_NAME);
unreg_context_menu_handler(L"Directory\\Background", ICON_OVERLAY_NAME);
unreg_icon_overlay(ICON_OVERLAY_NAME);
if (!unregister_clsid(CLSID_ShellBtrfsVolPropSheet))
return E_FAIL;
if (!unregister_clsid(CLSID_ShellBtrfsPropSheet))
return E_FAIL;
if (!unregister_clsid(CLSID_ShellBtrfsContextMenu))
return E_FAIL;
if (!unregister_clsid(CLSID_ShellBtrfsIconHandler))
return E_FAIL;
@@ -357,10 +622,117 @@ STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) {
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH)
module = (HMODULE)hModule;
return TRUE;
}
static void create_subvol(std::wstring fn) {
size_t found = fn.rfind(L"\\");
std::wstring path, file;
HANDLE h;
ULONG bcslen;
btrfs_create_subvol* bcs;
IO_STATUS_BLOCK iosb;
if (found == std::wstring::npos) {
path = L"";
file = fn;
} else {
path = fn.substr(0, found);
file = fn.substr(found + 1);
}
path += L"\\";
h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE)
return;
bcslen = offsetof(btrfs_create_subvol, name[0]) + (file.length() * sizeof(WCHAR));
bcs = (btrfs_create_subvol*)malloc(bcslen);
bcs->readonly = FALSE;
bcs->posix = FALSE;
bcs->namelen = file.length() * sizeof(WCHAR);
memcpy(bcs->name, file.c_str(), bcs->namelen);
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, bcs, bcslen, NULL, 0);
CloseHandle(h);
}
void CALLBACK CreateSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
LPWSTR* args;
int num_args;
args = CommandLineToArgvW(lpszCmdLine, &num_args);
if (!args)
return;
if (num_args >= 1)
create_subvol(args[0]);
LocalFree(args);
}
static void create_snapshot2(std::wstring source, std::wstring fn) {
size_t found = fn.rfind(L"\\");
std::wstring path, file;
HANDLE h, src;
ULONG bcslen;
btrfs_create_snapshot* bcs;
IO_STATUS_BLOCK iosb;
if (found == std::wstring::npos) {
path = L"";
file = fn;
} else {
path = fn.substr(0, found);
file = fn.substr(found + 1);
}
path += L"\\";
src = CreateFileW(source.c_str(), FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (src == INVALID_HANDLE_VALUE)
return;
h = CreateFileW(path.c_str(), FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
CloseHandle(src);
return;
}
bcslen = offsetof(btrfs_create_snapshot, name[0]) + (file.length() * sizeof(WCHAR));
bcs = (btrfs_create_snapshot*)malloc(bcslen);
bcs->readonly = FALSE;
bcs->posix = FALSE;
bcs->namelen = file.length() * sizeof(WCHAR);
memcpy(bcs->name, file.c_str(), bcs->namelen);
bcs->subvol = src;
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, bcs, bcslen, NULL, 0);
CloseHandle(h);
CloseHandle(src);
}
void CALLBACK CreateSnapshotW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
LPWSTR* args;
int num_args;
args = CommandLineToArgvW(lpszCmdLine, &num_args);
if (!args)
return;
if (num_args >= 2)
create_snapshot2(args[0], args[1]);
LocalFree(args);
}
#ifdef __cplusplus
}
File diff suppressed because it is too large Load Diff
+49 -24
View File
@@ -1,26 +1,27 @@
/* Copyright (c) Mark Harmstone 2016
*
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <shlobj.h>
#include <deque>
#include <string>
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "../../drivers/filesystems/btrfs/btrfsioctl.h"
#include "btrfsioctl.h"
#endif
#ifndef S_IRUSR
@@ -59,6 +60,18 @@
#define S_IXOTH (S_IXGRP >> 3)
#endif
#ifndef S_ISUID
#define S_ISUID 0004000
#endif
#ifndef S_ISGID
#define S_ISGID 0002000
#endif
#ifndef S_ISVTX
#define S_ISVTX 0001000
#endif
#define BTRFS_INODE_NODATASUM 0x001
#define BTRFS_INODE_NODATACOW 0x002
#define BTRFS_INODE_READONLY 0x004
@@ -85,15 +98,19 @@ public:
perms_changed = FALSE;
uid_changed = FALSE;
gid_changed = FALSE;
compress_type_changed = FALSE;
ro_changed = FALSE;
can_change_perms = FALSE;
can_change_owner = FALSE;
show_admin_button = FALSE;
thread = NULL;
mode = mode_set = 0;
flags = flags_set = 0;
has_subvols = FALSE;
filename = L"";
sizes[0] = sizes[1] = sizes[2] = sizes[3] = 0;
totalsize = 0;
InterlockedIncrement(&objs_loaded);
}
@@ -102,36 +119,37 @@ public:
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
InterlockedDecrement(&objs_loaded);
}
// IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
ULONG __stdcall AddRef() {
return InterlockedIncrement(&refcount);
}
ULONG __stdcall Release() {
LONG rc = InterlockedDecrement(&refcount);
if (rc == 0)
delete this;
return rc;
}
// IShellExtInit
virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID);
// IShellPropSheetExt
virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
void init_propsheet(HWND hwndDlg);
void change_inode_flag(HWND hDlg, UINT64 flag, UINT state);
void change_perm_flag(HWND hDlg, ULONG perm, UINT state);
void change_uid(HWND hDlg, UINT32 uid);
@@ -142,20 +160,22 @@ public:
DWORD search_list_thread();
void do_search(WCHAR* fn);
void update_size_details_dialog(HWND hDlg);
void open_as_admin(HWND hwndDlg);
void set_cmdline(std::wstring cmdline);
BOOL readonly;
BOOL can_change_perms;
BOOL can_change_owner;
BOOL can_change_nocow;
WCHAR size_format[255];
HANDLE thread;
UINT32 min_mode, max_mode, mode, mode_set;
UINT64 min_flags, max_flags, flags, flags_set;
UINT64 subvol, inode, rdev;
UINT8 type;
UINT8 type, min_compression_type, max_compression_type, compress_type;
UINT32 uid, gid;
BOOL various_subvols, various_inodes, various_types, various_uids, various_gids;
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;
private:
LONG refcount;
BOOL ignore;
@@ -164,4 +184,9 @@ private:
BOOL flags_changed, perms_changed, uid_changed, gid_changed;
UINT64 sizes[4], totalsize;
std::deque<WCHAR*> search_list;
std::wstring filename;
void apply_changes_file(HWND hDlg, std::wstring fn);
HRESULT check_file(std::wstring fn, UINT i, UINT num_files, UINT* sv);
HRESULT load_file_list();
};
+207
View File
@@ -0,0 +1,207 @@
#include "shellext.h"
#include <initguid.h>
#include <ntddstor.h>
#include <ndk/rtlfuncs.h>
#ifdef __cplusplus
extern "C" {
#endif
/* So that we can link */
DEFINE_GUID(CLSID_WICImagingFactory, 0xcacaf262,0x9370,0x4615,0xa1,0x3b,0x9f,0x55,0x39,0xda,0x4c,0x0a);
/* Copied from ntoskrnl_vista */
NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR uni_dest, ULONG uni_bytes_max,
PULONG uni_bytes_written,
PCCH utf8_src, ULONG utf8_bytes)
{
NTSTATUS status;
ULONG i, j;
ULONG written;
ULONG ch;
ULONG utf8_trail_bytes;
WCHAR utf16_ch[3];
ULONG utf16_ch_len;
if (!utf8_src)
return STATUS_INVALID_PARAMETER_4;
if (!uni_bytes_written)
return STATUS_INVALID_PARAMETER;
written = 0;
status = STATUS_SUCCESS;
for (i = 0; i < utf8_bytes; i++)
{
/* read UTF-8 lead byte */
ch = (BYTE)utf8_src[i];
utf8_trail_bytes = 0;
if (ch >= 0xf5)
{
ch = 0xfffd;
status = STATUS_SOME_NOT_MAPPED;
}
else if (ch >= 0xf0)
{
ch &= 0x07;
utf8_trail_bytes = 3;
}
else if (ch >= 0xe0)
{
ch &= 0x0f;
utf8_trail_bytes = 2;
}
else if (ch >= 0xc2)
{
ch &= 0x1f;
utf8_trail_bytes = 1;
}
else if (ch >= 0x80)
{
/* overlong or trail byte */
ch = 0xfffd;
status = STATUS_SOME_NOT_MAPPED;
}
/* read UTF-8 trail bytes */
if (i + utf8_trail_bytes < utf8_bytes)
{
for (j = 0; j < utf8_trail_bytes; j++)
{
if ((utf8_src[i + 1] & 0xc0) == 0x80)
{
ch <<= 6;
ch |= utf8_src[i + 1] & 0x3f;
i++;
}
else
{
ch = 0xfffd;
utf8_trail_bytes = 0;
status = STATUS_SOME_NOT_MAPPED;
break;
}
}
}
else
{
ch = 0xfffd;
utf8_trail_bytes = 0;
status = STATUS_SOME_NOT_MAPPED;
i = utf8_bytes;
}
/* encode ch as UTF-16 */
if ((ch > 0x10ffff) ||
(ch >= 0xd800 && ch <= 0xdfff) ||
(utf8_trail_bytes == 2 && ch < 0x00800) ||
(utf8_trail_bytes == 3 && ch < 0x10000))
{
/* invalid codepoint or overlong encoding */
utf16_ch[0] = 0xfffd;
utf16_ch[1] = 0xfffd;
utf16_ch[2] = 0xfffd;
utf16_ch_len = utf8_trail_bytes;
status = STATUS_SOME_NOT_MAPPED;
}
else if (ch >= 0x10000)
{
/* surrogate pair */
ch -= 0x010000;
utf16_ch[0] = 0xd800 + (ch >> 10 & 0x3ff);
utf16_ch[1] = 0xdc00 + (ch >> 0 & 0x3ff);
utf16_ch_len = 2;
}
else
{
/* single unit */
utf16_ch[0] = ch;
utf16_ch_len = 1;
}
if (!uni_dest)
{
written += utf16_ch_len;
continue;
}
for (j = 0; j < utf16_ch_len; j++)
{
if (uni_bytes_max >= sizeof(WCHAR))
{
*uni_dest++ = utf16_ch[j];
uni_bytes_max -= sizeof(WCHAR);
written++;
}
else
{
uni_bytes_max = 0;
status = STATUS_BUFFER_TOO_SMALL;
}
}
}
*uni_bytes_written = written * sizeof(WCHAR);
return status;
}
/* Quick and dirty table for conversion */
FILE_INFORMATION_CLASS ConvertToFileInfo[MaximumFileInfoByHandlesClass] =
{
FileBasicInformation, FileStandardInformation, FileNameInformation, FileRenameInformation,
FileDispositionInformation, FileAllocationInformation, FileEndOfFileInformation, FileStreamInformation,
FileCompressionInformation, FileAttributeTagInformation, FileIdBothDirectoryInformation, (FILE_INFORMATION_CLASS)-1,
FileIoPriorityHintInformation, FileRemoteProtocolInformation
};
/* Taken from kernel32 */
DWORD
BaseSetLastNTError(IN NTSTATUS Status)
{
DWORD dwErrCode;
dwErrCode = RtlNtStatusToDosError(Status);
SetLastError(dwErrCode);
return dwErrCode;
}
/* Quick implementation, still going farther than Wine implementation */
BOOL
WINAPI
SetFileInformationByHandle(HANDLE hFile,
FILE_INFO_BY_HANDLE_CLASS FileInformationClass,
LPVOID lpFileInformation,
DWORD dwBufferSize)
{
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
FILE_INFORMATION_CLASS FileInfoClass;
FileInfoClass = (FILE_INFORMATION_CLASS)-1;
/* Attempt to convert the class */
if (FileInformationClass < MaximumFileInfoByHandlesClass)
{
FileInfoClass = ConvertToFileInfo[FileInformationClass];
}
/* If wrong, bail out */
if (FileInfoClass == -1)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* And set the information */
Status = NtSetInformationFile(hFile, &IoStatusBlock, lpFileInformation,
dwBufferSize, FileInfoClass);
if (!NT_SUCCESS(Status))
{
BaseSetLastNTError(Status);
return FALSE;
}
return TRUE;
}
#ifdef __cplusplus
}
#endif
File diff suppressed because it is too large Load Diff
+88
View File
@@ -0,0 +1,88 @@
/* Copyright (c) Mark Harmstone 2017
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <shlobj.h>
#include <string>
#include <vector>
#ifndef __REACTOS__
#include "../btrfs.h"
#else
#include "btrfs.h"
#endif
extern LONG objs_loaded;
typedef struct {
BTRFS_UUID uuid;
UINT64 transid;
std::wstring path;
} subvol_cache;
class BtrfsRecv {
public:
BtrfsRecv() {
thread = NULL;
master = INVALID_HANDLE_VALUE;
dir = INVALID_HANDLE_VALUE;
running = FALSE;
cancelling = FALSE;
stransid = 0;
num_received = 0;
hwnd = NULL;
cache.clear();
}
virtual ~BtrfsRecv() {
cache.clear();
}
void Open(HWND hwnd, WCHAR* file, WCHAR* path, BOOL quiet);
DWORD recv_thread();
INT_PTR CALLBACK RecvProgressDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
BOOL cmd_subvol(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_snapshot(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_mkfile(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_rename(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_link(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_unlink(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_rmdir(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_setxattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_removexattr(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_write(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_clone(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_truncate(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_chmod(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_chown(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
BOOL cmd_utimes(HWND hwnd, btrfs_send_command* cmd, UINT8* data);
void add_cache_entry(BTRFS_UUID* uuid, UINT64 transid, std::wstring path);
BOOL utf8_to_utf16(HWND hwnd, char* utf8, ULONG utf8len, std::wstring* utf16);
void ShowRecvError(int resid, ...);
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;
HWND hwnd;
std::wstring streamfile, dirpath, subvolpath, lastwritepath;
DWORD lastwriteatt;
ULONG num_received;
UINT64 stransid;
BTRFS_UUID subvol_uuid;
BOOL running, cancelling;
std::vector<subvol_cache> cache;
};
+265 -2
View File
@@ -8,12 +8,17 @@
#define IDD_SIZE_DETAILS 103
#define IDS_NEW_SUBVOL_FILENAME 104
#define IDS_CREATE_SNAPSHOT 105
#define IDD_VOL_PROP_SHEET 105
#define IDS_CREATE_SNAPSHOT_HELP_TEXT 106
#define IDD_VOL_USAGE 106
#define IDS_SNAPSHOT_FILENAME 107
#define IDD_PROP_SHEET 107
#define IDS_PROP_SHEET_TITLE 108
#define IDD_BALANCE_OPTIONS 108
#define IDS_INODE_FILE 109
#define IDD_BALANCE 109
#define IDS_INODE_DIR 110
#define IDD_DEVICES 110
#define IDS_INODE_CHAR 111
#define IDS_INODE_BLOCK 112
#define IDS_INODE_FIFO 113
@@ -21,6 +26,7 @@
#define IDS_INODE_SYMLINK 115
#define IDS_INODE_UNKNOWN 116
#define IDS_SET_INODE_INFO_ERROR 117
#define IDS_CANNOT_FIND_DEVICE 117
#define IDS_SIZE_BYTE 118
#define IDS_SIZE_BYTES 119
#define IDS_SIZE_KB 120
@@ -32,7 +38,164 @@
#define IDS_VARIOUS 126
#define IDS_INODE_CHAR_SIMPLE 127
#define IDS_INODE_BLOCK_SIMPLE 128
#define IDS_VOL_PROP_SHEET_TITLE 129
#define IDS_SIZE_LARGE 130
#define IDS_SINGLE 131
#define IDS_DUP 132
#define IDS_RAID0 133
#define IDS_RAID1 134
#define IDS_RAID10 135
#define IDS_RAID5 136
#define IDS_RAID6 137
#define IDS_USAGE_DATA 138
#define IDS_USAGE_MIXED 139
#define IDS_USAGE_METADATA 140
#define IDS_USAGE_SYSTEM 141
#define IDS_USAGE_UNALLOC 142
#define IDS_UNKNOWN_DEVICE 143
#define IDS_USAGE_DEV_SIZE 144
#define IDS_USAGE_DEV_ALLOC 145
#define IDS_USAGE_DEV_UNALLOC 146
#define IDS_USAGE_DATA_RATIO 147
#define IDS_USAGE_METADATA_RATIO 148
#define IDS_NO_BALANCE 149
#define IDS_SINGLE2 150
#define IDS_DEVID_LIST 151
#define IDS_BALANCE_RUNNING 152
#define IDS_DRANGE_END_BEFORE_START 153
#define IDS_VRANGE_END_BEFORE_START 154
#define IDS_LIMIT_END_BEFORE_START 155
#define IDS_STRIPES_END_BEFORE_START 156
#define IDS_USAGE_END_BEFORE_START 157
#define IDS_ERROR 158
#define IDS_BALANCE_COMPLETE 159
#define IDS_BALANCE_PAUSED 160
#define IDS_BALANCE_CANCELLED 161
#define IDS_DEVLIST_ID 162
#define IDS_DEVLIST_DESC 163
#define IDS_DEVLIST_READONLY 164
#define IDS_DEVLIST_SIZE 165
#define IDS_DEVLIST_READONLY_YES 166
#define IDS_DEVLIST_READONLY_NO 167
#define IDD_DEVICE_ADD 167
#define IDS_DEVLIST_ALLOC 168
#define IDD_SCRUB 168
#define IDS_DEVLIST_ALLOC_PC 169
#define IDD_DEVICE_STATS 169
#define IDS_BALANCE_RUNNING_REMOVAL 170
#define IDD_RECV_PROGRESS 170
#define IDS_BALANCE_PAUSED_REMOVAL 171
#define IDD_SEND_SUBVOL 171
#define IDS_BALANCE_CANCELLED_REMOVAL 172
#define IDD_RESIZE 172
#define IDS_BALANCE_COMPLETE_REMOVAL 173
#define IDS_PARTITION 174
#define IDS_WHOLE_DISK 175
#define IDS_CANNOT_REMOVE_RAID 176
#define IDS_REMOVE_DEVICE_CONFIRMATION 177
#define IDS_CONFIRMATION_TITLE 178
#define IDS_ADD_DEVICE_CONFIRMATION 179
#define IDS_ADD_DEVICE_CONFIRMATION_FS 180
#define IDS_BALANCE_FAILED 181
#define IDS_BALANCE_FAILED_REMOVAL 182
#define IDS_DISK_NUM 183
#define IDS_DISK_PART_NUM 184
#define IDS_NO_SCRUB 185
#define IDS_SCRUB_RUNNING 186
#define IDS_SCRUB_FINISHED 187
#define IDS_SCRUB_PAUSED 188
#define IDS_SCRUB_MSG_STARTED 189
#define IDS_SCRUB_MSG_RECOVERABLE_DATA 190
#define IDS_SCRUB_MSG_RECOVERABLE_METADATA 191
#define IDS_SCRUB_MSG_UNRECOVERABLE_DATA 192
#define IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL 193
#define IDS_SCRUB_MSG_UNRECOVERABLE_METADATA 194
#define IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM 195
#define IDS_SCRUB_MSG_FINISHED 196
#define IDS_SCRUB_MSG_SUMMARY 197
#define IDS_BALANCE_SCRUB_RUNNING 198
#define IDS_SCRUB_BALANCE_RUNNING 199
#define IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE 200
#define IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE 201
#define IDS_SCRUB_FAILED 202
#define IDS_LOCK_FAILED 203
#define IDS_SCRUB_MSG_RECOVERABLE_PARITY 204
#define IDS_COMPRESS_ANY 205
#define IDS_COMPRESS_ZLIB 206
#define IDS_COMPRESS_LZO 207
#define IDS_STANDALONE_PROPSHEET_TITLE 208
#define IDS_REFLINK_PASTE 209
#define IDS_REFLINK_PASTE_HELP 210
#define IDS_RECV_SUBVOL 211
#define IDS_RECV_SUBVOL_HELP 212
#define IDS_RECV_CANT_OPEN_FILE 213
#define IDS_RECV_READFILE_FAILED 214
#define IDS_OUT_OF_MEMORY 215
#define IDS_RECV_UNKNOWN_COMMAND 216
#define IDS_RECV_CANT_OPEN_PATH 217
#define IDS_RECV_RTLUTF8TOUNICODEN_FAILED 218
#define IDS_RECV_CREATE_SUBVOL_FAILED 219
#define IDS_RECV_MISSING_PARAM 220
#define IDS_RECV_SHORT_PARAM 221
#define IDS_RECV_MKNOD_FAILED 222
#define IDS_RECV_SET_REPARSE_POINT_FAILED 223
#define IDS_RECV_MOVEFILE_FAILED 224
#define IDS_RECV_SETFILEPOINTER_FAILED 225
#define IDS_RECV_WRITEFILE_FAILED 226
#define IDS_RECV_CREATEHARDLINK_FAILED 227
#define IDS_RECV_SETENDOFFILE_FAILED 228
#define IDS_RECV_CANT_CREATE_FILE 229
#define IDS_RECV_SETFILEINFO_FAILED 230
#define IDS_RECV_SETINODEINFO_FAILED 231
#define IDS_RECV_SUCCESS 232
#define IDS_RECV_BUTTON_OK 233
#define IDS_RECV_SETFILEATTRIBUTES_FAILED 234
#define IDS_RECV_GETFILEATTRIBUTES_FAILED 235
#define IDS_RECV_CSUM_ERROR 236
#define IDS_RECV_NOT_A_SEND_STREAM 237
#define IDS_RECV_UNSUPPORTED_VERSION 238
#define IDS_RECV_SETEAFILE_FAILED 239
#define IDS_RECV_RECEIVED_SUBVOL_FAILED 240
#define IDS_RECV_SETSECURITYOBJECT_FAILED 241
#define IDS_RECV_SETXATTR_FAILED 242
#define IDS_RECV_CREATETHREAD_FAILED 243
#define IDS_RECV_FILE_TRUNCATED 244
#define IDS_RECV_RESERVE_SUBVOL_FAILED 245
#define IDS_RECV_CANCELLED 246
#define IDS_RECV_CANT_FIND_PARENT_SUBVOL 247
#define IDS_RECV_FIND_SUBVOL_FAILED 248
#define IDS_RECV_CREATE_SNAPSHOT_FAILED 249
#define IDS_RECV_GETVOLUMEPATHNAME_FAILED 250
#define IDS_RECV_DELETEFILE_FAILED 251
#define IDS_RECV_REMOVEDIRECTORY_FAILED 252
#define IDS_RECV_CANT_FIND_CLONE_SUBVOL 253
#define IDS_RECV_GETFILESIZEEX_FAILED 254
#define IDS_RECV_DUPLICATE_EXTENTS_FAILED 255
#define IDS_RECV_SUCCESS_PLURAL 256
#define IDS_SEND_SUBVOL 257
#define IDS_SEND_SUBVOL_HELP 258
#define IDS_SEND_CANT_OPEN_FILE 259
#define IDS_SEND_CANT_OPEN_DIR 260
#define IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED 261
#define IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED 262
#define IDS_SEND_SUCCESS 263
#define IDS_SEND_WRITEFILE_FAILED 264
#define IDS_SEND_GET_FILE_INFO_FAILED 265
#define IDS_SEND_NOT_READONLY 266
#define IDS_NOT_SUBVOL 267
#define IDS_GET_FILE_IDS_FAILED 268
#define IDS_SHPARSEDISPLAYNAME_FAILED 269
#define IDS_SHGETPATHFROMIDLIST_FAILED 270
#define IDS_SEND_PARENT_NOT_READONLY 271
#define IDS_SEND_CANCEL 272
#define IDS_SEND_WRITING 273
#define IDS_MISSING 274
#define IDS_RESIZE_SUCCESSFUL 275
#define IDS_BALANCE_RUNNING_SHRINK 276
#define IDS_BALANCE_PAUSED_SHRINK 277
#define IDS_BALANCE_CANCELLED_SHRINK 278
#define IDS_BALANCE_COMPLETE_SHRINK 279
#define IDS_BALANCE_FAILED_SHRINK 280
#define IDC_UID 1001
#define IDC_GID 1002
#define IDC_USERR 1003
@@ -52,18 +215,118 @@
#define IDC_SIZE_ON_DISK 1017
#define IDC_GROUP_INFORMATION 1018
#define IDC_SIZE_INLINE 1019
#define IDC_SETUID 1019
#define IDC_SIZE_UNCOMPRESSED 1020
#define IDC_USAGE_BOX 1020
#define IDC_SETGID 1020
#define IDC_SIZE_ZLIB 1021
#define IDC_USAGE_REFRESH 1021
#define IDC_STICKY 1021
#define IDC_SIZE_ZLIB2 1022
#define IDC_SIZE_LZO 1022
#define IDC_VOL_SHOW_USAGE 1022
#define IDC_VOL_BALANCE 1023
#define IDC_PROFILES 1024
#define IDC_PROFILES_SINGLE 1025
#define IDC_PROFILES_DUP 1026
#define IDC_VOL_DEVICES 1026
#define IDC_PROFILES_RAID0 1027
#define IDC_VOL_DEVICES2 1027
#define IDC_VOL_SCRUB 1027
#define IDC_PROFILES_RAID1 1028
#define IDC_PROFILES_RAID10 1029
#define IDC_PROFILES_RAID5 1030
#define IDC_PROFILES_RAID6 1031
#define IDC_USAGE 1032
#define IDC_USAGE_START_SPINNER 1033
#define IDC_USAGE_START 1034
#define IDC_USAGE_END_SPINNER 1035
#define IDC_USAGE_END 1036
#define IDC_DEVID 1037
#define IDC_DEVID_COMBO 1038
#define IDC_DRANGE_START 1039
#define IDC_DRANGE 1040
#define IDC_PROGRESS1 1040
#define IDC_BALANCE_PROGRESS 1040
#define IDC_RECV_PROGRESS 1040
#define IDC_DRANGE_END 1041
#define IDC_DATA 1041
#define IDC_LIMIT 1042
#define IDC_METADATA 1042
#define IDC_VRANGE 1043
#define IDC_SYSTEM 1043
#define IDC_LIMIT_START_SPINNER 1044
#define IDC_BUTTON1 1044
#define IDC_DATA_OPTIONS 1044
#define IDC_DEVICE_ADD 1044
#define IDC_RESET_STATS 1044
#define IDC_OPEN_ADMIN 1044
#define IDC_BROWSE 1044
#define IDC_LIMIT_START 1045
#define IDC_BUTTON2 1045
#define IDC_METADATA_OPTIONS 1045
#define IDC_DEVICE_REFRESH 1045
#define IDC_PARENT_BROWSE 1045
#define IDC_VRANGE_END 1046
#define IDC_BUTTON3 1046
#define IDC_SYSTEM_OPTIONS 1046
#define IDC_DEVICE_REMOVE 1046
#define IDC_CLONE_ADD 1046
#define IDC_VRANGE_START 1047
#define IDC_BALANCE_STATUS 1047
#define IDC_DEVICE_SHOW_STATS 1047
#define IDC_CLONE_REMOVE 1047
#define IDC_LIMIT_END_SPINNER 1048
#define IDC_START_BALANCE 1048
#define IDC_DEVICE_RESIZE 1048
#define IDC_LIMIT_END 1049
#define IDC_PAUSE_BALANCE 1049
#define IDC_STRIPES 1050
#define IDC_BUTTON6 1050
#define IDC_CANCEL_BALANCE 1050
#define IDC_STRIPES_START_SPINNER 1051
#define IDC_STRIPES_START 1052
#define IDC_DEVLIST 1052
#define IDC_STRIPES_END_SPINNER 1053
#define IDC_DEVICE_TREE 1053
#define IDC_STRIPES_END 1054
#define IDC_UUID 1054
#define IDC_CONVERT 1055
#define IDC_SCRUB_INFO 1055
#define IDC_CONVERT_COMBO 1056
#define IDC_START_SCRUB 1056
#define IDC_SOFT 1057
#define IDC_PAUSE_SCRUB 1057
#define IDC_CANCEL_SCRUB 1058
#define IDC_SCRUB_PROGRESS 1059
#define IDC_SCRUB_STATUS 1060
#define IDC_COMPRESS_TYPE 1061
#define IDC_CHECK1 1062
#define IDC_SUBVOL_RO 1062
#define IDC_INCREMENTAL 1062
#define IDC_DEVICE_ID 1063
#define IDC_WRITE_ERRS 1064
#define IDC_READ_ERRS 1065
#define IDC_RECV_MSG 1065
#define IDC_FLUSH_ERRS 1066
#define IDC_STREAM_DEST 1066
#define IDC_CORRUPTION_ERRS 1067
#define IDC_SEND_STATUS 1067
#define IDC_GENERATION_ERRS 1068
#define IDC_PARENT_SUBVOL 1068
#define IDC_CLONE_LIST 1069
#define IDC_RESIZE_DEVICE_ID 1070
#define IDC_RESIZE_CURSIZE 1071
#define IDC_RESIZE_SLIDER 1072
#define IDC_RESIZE_NEWSIZE 1073
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_RESOURCE_VALUE 173
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_CONTROL_VALUE 1073
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+692
View File
@@ -0,0 +1,692 @@
/* Copyright (c) Mark Harmstone 2017
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "shellext.h"
#include "scrub.h"
#include "resource.h"
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "btrfsioctl.h"
#endif
#include <shlobj.h>
#include <uxtheme.h>
#include <stdio.h>
#ifndef __REACTOS__
#include <strsafe.h>
#include <winternl.h>
#else
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <strsafe.h>
#include <ndk/iofuncs.h>
#include <ndk/iotypes.h>
#endif
#include <string>
#define NO_SHLWAPI_STRFCNS
#include <shlwapi.h>
#include <uxtheme.h>
void BtrfsScrub::UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs) {
btrfs_query_scrub* bqs2 = NULL;
BOOL alloc_bqs2 = FALSE;
NTSTATUS Status;
std::wstring s;
WCHAR t[255], u[255], dt[255], tm[255];
FILETIME filetime;
SYSTEMTIME systime;
UINT64 recoverable_errors = 0, unrecoverable_errors = 0;
if (bqs->num_errors > 0) {
HANDLE h;
IO_STATUS_BLOCK iosb;
ULONG len;
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) {
ShowError(hwndDlg, GetLastError());
return;
}
len = 0;
do {
len += 1024;
if (bqs2)
free(bqs2);
bqs2 = (btrfs_query_scrub*)malloc(len);
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, bqs2, len);
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
free(bqs2);
return;
}
} while (Status == STATUS_BUFFER_OVERFLOW);
alloc_bqs2 = TRUE;
CloseHandle(h);
} else
bqs2 = bqs;
s[0] = 0;
// "scrub started"
if (bqs2->start_time.QuadPart > 0) {
filetime.dwLowDateTime = bqs2->start_time.LowPart;
filetime.dwHighDateTime = bqs2->start_time.HighPart;
if (!FileTimeToSystemTime(&filetime, &systime)) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!LoadStringW(module, IDS_SCRUB_MSG_STARTED, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
s += u;
s += L"\r\n";
}
// errors
if (bqs2->num_errors > 0) {
btrfs_scrub_error* bse = &bqs2->errors;
do {
if (bse->recovered)
recoverable_errors++;
else
unrecoverable_errors++;
if (bse->parity) {
if (!LoadStringW(module, IDS_SCRUB_MSG_RECOVERABLE_PARITY, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
} else if (bse->is_metadata) {
int message;
if (bse->recovered)
message = IDS_SCRUB_MSG_RECOVERABLE_METADATA;
else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0)
message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA;
else
message = IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM;
if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (bse->recovered) {
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
} else if (bse->metadata.firstitem.obj_id == 0 && bse->metadata.firstitem.obj_type == 0 && bse->metadata.firstitem.offset == 0) {
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device,
bse->metadata.root, bse->metadata.level) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
} 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 {
int message;
if (bse->recovered)
message = IDS_SCRUB_MSG_RECOVERABLE_DATA;
else if (bse->data.subvol != 0)
message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL;
else
message = IDS_SCRUB_MSG_UNRECOVERABLE_DATA;
if (!LoadStringW(module, message, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (bse->recovered) {
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, bse->address, bse->device) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
} else if (bse->data.subvol != 0) {
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) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
} else {
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 += L"\r\n";
if (bse->next_entry == 0)
break;
else
bse = (btrfs_scrub_error*)((UINT8*)bse + bse->next_entry);
} while (TRUE);
}
if (bqs2->finish_time.QuadPart > 0) {
WCHAR d1[255], d2[255];
float speed;
// "scrub finished"
filetime.dwLowDateTime = bqs2->finish_time.LowPart;
filetime.dwHighDateTime = bqs2->finish_time.HighPart;
if (!FileTimeToSystemTime(&filetime, &systime)) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!SystemTimeToTzSpecificLocalTime(NULL, &systime, &systime)) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!LoadStringW(module, IDS_SCRUB_MSG_FINISHED, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!GetDateFormatW(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &systime, NULL, dt, sizeof(dt) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (!GetTimeFormatW(LOCALE_USER_DEFAULT, 0, &systime, NULL, tm, sizeof(tm) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, dt, tm) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
s += u;
s += L"\r\n";
// summary
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
format_size(bqs2->data_scrubbed, d1, sizeof(d1) / sizeof(WCHAR), FALSE);
speed = (float)bqs2->data_scrubbed / ((float)bqs2->duration / 10000000.0f);
format_size((UINT64)speed, d2, sizeof(d2) / sizeof(WCHAR), FALSE);
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, d1, bqs2->duration / 10000000, d2) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
s += u;
s += L"\r\n";
// recoverable errors
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, recoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
s += u;
s += L"\r\n";
// unrecoverable errors
if (!LoadStringW(module, IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
goto end;
}
if (StringCchPrintfW(u, sizeof(u) / sizeof(WCHAR), t, unrecoverable_errors) == STRSAFE_E_INSUFFICIENT_BUFFER)
goto end;
s += u;
s += L"\r\n";
}
SetWindowTextW(GetDlgItem(hwndDlg, IDC_SCRUB_INFO), s.c_str());
end:
if (alloc_bqs2)
free(bqs2);
}
void BtrfsScrub::RefreshScrubDlg(HWND hwndDlg, BOOL first_time) {
HANDLE h;
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);
if (h != INVALID_HANDLE_VALUE) {
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub));
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
return;
}
CloseHandle(h);
} else {
ShowError(hwndDlg, GetLastError());
return;
}
if (first_time || status != bqs.status || chunks_left != bqs.chunks_left) {
WCHAR s[255];
if (bqs.status == BTRFS_SCRUB_STOPPED) {
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), TRUE);
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_SCRUB), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_CANCEL_SCRUB), FALSE);
if (bqs.error != STATUS_SUCCESS) {
WCHAR t[255];
if (!LoadStringW(module, IDS_SCRUB_FAILED, t, sizeof(t) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
return;
}
if (StringCchPrintfW(s, sizeof(s) / sizeof(WCHAR), t, bqs.error) == STRSAFE_E_INSUFFICIENT_BUFFER)
return;
} else {
if (!LoadStringW(module, bqs.total_chunks == 0 ? IDS_NO_SCRUB : IDS_SCRUB_FINISHED, s, sizeof(s) / sizeof(WCHAR))) {
ShowError(hwndDlg, GetLastError());
return;
}
}
} else {
WCHAR t[255];
float pc;
EnableWindow(GetDlgItem(hwndDlg, IDC_START_SCRUB), FALSE);
EnableWindow(GetDlgItem(hwndDlg, IDC_PAUSE_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))) {
ShowError(hwndDlg, GetLastError());
return;
}
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)
return;
}
SetDlgItemTextW(hwndDlg, IDC_SCRUB_STATUS, s);
if (first_time || status != bqs.status) {
EnableWindow(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), bqs.status != BTRFS_SCRUB_STOPPED);
if (bqs.status != BTRFS_SCRUB_STOPPED) {
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETRANGE32, 0, (LPARAM)bqs.total_chunks);
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETPOS, (WPARAM)(bqs.total_chunks - bqs.chunks_left), 0);
if (bqs.status == BTRFS_SCRUB_PAUSED)
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETSTATE, PBST_PAUSED, 0);
else
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETSTATE, PBST_NORMAL, 0);
} else {
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETRANGE32, 0, 0);
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETPOS, 0, 0);
}
chunks_left = bqs.chunks_left;
}
}
if (bqs.status != BTRFS_SCRUB_STOPPED && chunks_left != bqs.chunks_left) {
SendMessageW(GetDlgItem(hwndDlg, IDC_SCRUB_PROGRESS), PBM_SETPOS, (WPARAM)(bqs.total_chunks - bqs.chunks_left), 0);
chunks_left = bqs.chunks_left;
}
if (first_time || status != bqs.status || num_errors != bqs.num_errors) {
UpdateTextBox(hwndDlg, &bqs);
num_errors = bqs.num_errors;
}
status = bqs.status;
}
void BtrfsScrub::StartScrub(HWND hwndDlg) {
HANDLE h;
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) {
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0);
if (Status == STATUS_DEVICE_NOT_READY) {
btrfs_query_balance bqb;
NTSTATUS Status2;
Status2 = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_BALANCE, NULL, 0, &bqb, sizeof(btrfs_query_balance));
if (NT_SUCCESS(Status2) && bqb.status & (BTRFS_BALANCE_RUNNING | BTRFS_BALANCE_PAUSED)) {
ShowStringError(hwndDlg, IDS_SCRUB_BALANCE_RUNNING);
CloseHandle(h);
return;
}
}
if (!NT_SUCCESS(Status)) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
return;
}
RefreshScrubDlg(hwndDlg, TRUE);
CloseHandle(h);
} else {
ShowError(hwndDlg, GetLastError());
return;
}
}
void BtrfsScrub::PauseScrub(HWND hwndDlg) {
HANDLE h;
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);
if (h != INVALID_HANDLE_VALUE) {
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_QUERY_SCRUB, NULL, 0, &bqs, sizeof(btrfs_query_scrub));
if (!NT_SUCCESS(Status) && Status != STATUS_BUFFER_OVERFLOW) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
return;
}
if (bqs.status == BTRFS_SCRUB_PAUSED)
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_RESUME_SCRUB, NULL, 0, NULL, 0);
else
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_PAUSE_SCRUB, NULL, 0, NULL, 0);
if (!NT_SUCCESS(Status)) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
return;
}
CloseHandle(h);
} else {
ShowError(hwndDlg, GetLastError());
return;
}
}
void BtrfsScrub::StopScrub(HWND hwndDlg) {
HANDLE h;
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) {
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0);
if (!NT_SUCCESS(Status)) {
ShowNtStatusError(hwndDlg, Status);
CloseHandle(h);
return;
}
CloseHandle(h);
} else {
ShowError(hwndDlg, GetLastError());
return;
}
}
INT_PTR CALLBACK BtrfsScrub::ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
RefreshScrubDlg(hwndDlg, TRUE);
SetTimer(hwndDlg, 1, 1000, NULL);
break;
case WM_COMMAND:
switch (HIWORD(wParam)) {
case BN_CLICKED:
switch (LOWORD(wParam)) {
case IDOK:
case IDCANCEL:
EndDialog(hwndDlg, 0);
return TRUE;
case IDC_START_SCRUB:
StartScrub(hwndDlg);
return TRUE;
case IDC_PAUSE_SCRUB:
PauseScrub(hwndDlg);
return TRUE;
case IDC_CANCEL_SCRUB:
StopScrub(hwndDlg);
return TRUE;
}
break;
}
break;
case WM_TIMER:
RefreshScrubDlg(hwndDlg, FALSE);
break;
}
return FALSE;
}
static INT_PTR CALLBACK stub_ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
BtrfsScrub* bs;
if (uMsg == WM_INITDIALOG) {
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam);
bs = (BtrfsScrub*)lParam;
} else {
bs = (BtrfsScrub*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
}
if (bs)
return bs->ScrubDlgProc(hwndDlg, uMsg, wParam, lParam);
else
return FALSE;
}
void CALLBACK ShowScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
HANDLE token;
TOKEN_PRIVILEGES tp;
LUID luid;
BtrfsScrub* scrub;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
ShowError(hwnd, GetLastError());
return;
}
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
ShowError(hwnd, GetLastError());
goto end;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
ShowError(hwnd, GetLastError());
goto end;
}
set_dpi_aware();
scrub = new BtrfsScrub(lpszCmdLine);
DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SCRUB), hwnd, stub_ScrubDlgProc, (LPARAM)scrub);
delete scrub;
end:
CloseHandle(token);
}
void CALLBACK StartScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
LPWSTR* args;
int num_args;
args = CommandLineToArgvW(lpszCmdLine, &num_args);
if (!args)
return;
if (num_args >= 1) {
HANDLE h, token;
LUID luid;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
goto end;
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid))
goto end;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
goto end;
CloseHandle(token);
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) {
IO_STATUS_BLOCK iosb;
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_START_SCRUB, NULL, 0, NULL, 0);
CloseHandle(h);
}
}
end:
LocalFree(args);
}
void CALLBACK StopScrubW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
LPWSTR* args;
int num_args;
args = CommandLineToArgvW(lpszCmdLine, &num_args);
if (!args)
return;
if (num_args >= 1) {
HANDLE h, token;
LUID luid;
TOKEN_PRIVILEGES tp;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
goto end;
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid))
goto end;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
goto end;
CloseHandle(token);
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) {
IO_STATUS_BLOCK iosb;
NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_STOP_SCRUB, NULL, 0, NULL, 0);
CloseHandle(h);
}
}
end:
LocalFree(args);
}
+46
View File
@@ -0,0 +1,46 @@
/* Copyright (c) Mark Harmstone 2017
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <windows.h>
#ifndef __REACTOS__
#include "../btrfs.h"
#include "../btrfsioctl.h"
#else
#include "btrfs.h"
#include "btrfsioctl.h"
#endif
class BtrfsScrub {
public:
BtrfsScrub(WCHAR* drive) {
wcscpy(fn, drive);
}
INT_PTR CALLBACK ScrubDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
private:
void RefreshScrubDlg(HWND hwndDlg, BOOL first_time);
void UpdateTextBox(HWND hwndDlg, btrfs_query_scrub* bqs);
void StartScrub(HWND hwndDlg);
void PauseScrub(HWND hwndDlg);
void StopScrub(HWND hwndDlg);
WCHAR fn[MAX_PATH];
UINT32 status;
UINT64 chunks_left;
UINT32 num_errors;
};
+755
View File
@@ -0,0 +1,755 @@
/* Copyright (c) Mark Harmstone 2017
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include "shellext.h"
#include "send.h"
#include "resource.h"
#include <stddef.h>
#include <shlobj.h>
#ifdef __REACTOS__
#undef DeleteFile
#endif
#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() {
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
btrfs_send_subvol* bss;
btrfs_send_header header;
btrfs_send_command end;
BOOL success = FALSE;
ULONG bss_size, i;
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);
if (dirh == INVALID_HANDLE_VALUE) {
ShowSendError(IDS_SEND_CANT_OPEN_DIR, subvol.c_str(), GetLastError(), format_message(GetLastError()).c_str());
goto end3;
}
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
bss = (btrfs_send_subvol*)malloc(bss_size);
memset(bss, 0, bss_size);
if (incremental) {
WCHAR parent[MAX_PATH];
HANDLE parenth;
parent[0] = 0;
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);
if (parenth == INVALID_HANDLE_VALUE) {
ShowSendError(IDS_SEND_CANT_OPEN_DIR, parent, GetLastError(), format_message(GetLastError()).c_str());
goto end2;
}
bss->parent = parenth;
} else
bss->parent = NULL;
bss->num_clones = clones.size();
for (i = 0; i < bss->num_clones; i++) {
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);
if (h == INVALID_HANDLE_VALUE) {
ULONG j;
ShowSendError(IDS_SEND_CANT_OPEN_DIR, clones[i].c_str(), GetLastError(), format_message(GetLastError()).c_str());
for (j = 0; j < i; j++) {
CloseHandle(bss->clones[j]);
}
if (bss->parent) CloseHandle(bss->parent);
goto end2;
}
bss->clones[i] = h;
}
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0);
for (i = 0; i < bss->num_clones; i++) {
CloseHandle(bss->clones[i]);
}
if (!NT_SUCCESS(Status)) {
if (Status == (NTSTATUS)STATUS_INVALID_PARAMETER) {
BY_HANDLE_FILE_INFORMATION fileinfo;
if (!GetFileInformationByHandle(dirh, &fileinfo)) {
ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
if (bss->parent) CloseHandle(bss->parent);
goto end2;
}
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
ShowSendError(IDS_SEND_NOT_READONLY);
if (bss->parent) CloseHandle(bss->parent);
goto end2;
}
if (bss->parent) {
if (!GetFileInformationByHandle(bss->parent, &fileinfo)) {
ShowSendError(IDS_SEND_GET_FILE_INFO_FAILED, GetLastError(), format_message(GetLastError()).c_str());
CloseHandle(bss->parent);
goto end2;
}
if (!(fileinfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) {
ShowSendError(IDS_SEND_PARENT_NOT_READONLY);
CloseHandle(bss->parent);
goto end2;
}
}
}
ShowSendError(IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED, Status, format_ntstatus(Status).c_str());
if (bss->parent) CloseHandle(bss->parent);
goto end2;
}
if (bss->parent) CloseHandle(bss->parent);
stream = CreateFileW(file, FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (stream == INVALID_HANDLE_VALUE) {
ShowSendError(IDS_SEND_CANT_OPEN_FILE, file, GetLastError(), format_message(GetLastError()).c_str());
goto end2;
}
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(BTRFS_SEND_MAGIC));
header.version = 1;
if (!WriteFile(stream, &header, sizeof(header), NULL, NULL)) {
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
goto end;
}
do {
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN);
if (NT_SUCCESS(Status)) {
if (!WriteFile(stream, buf, iosb.Information, NULL, NULL))
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
}
} while (NT_SUCCESS(Status));
if (Status != STATUS_END_OF_FILE) {
ShowSendError(IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED, Status, format_ntstatus(Status).c_str());
goto end;
}
end.length = 0;
end.cmd = BTRFS_SEND_CMD_END;
end.csum = 0x9dc96c50;
if (!WriteFile(stream, &end, sizeof(end), NULL, NULL)) {
ShowSendError(IDS_SEND_WRITEFILE_FAILED, GetLastError(), format_message(GetLastError()).c_str());
goto end;
}
SetEndOfFile(stream);
ShowSendError(IDS_SEND_SUCCESS);
success = TRUE;
end:
if (!success) {
FILE_DISPOSITION_INFO fdi;
fdi.DeleteFile = TRUE;
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
}
CloseHandle(stream);
stream = INVALID_HANDLE_VALUE;
end2:
CloseHandle(dirh);
dirh = INVALID_HANDLE_VALUE;
end3:
free(buf);
buf = NULL;
started = FALSE;
SetDlgItemTextW(hwnd, IDCANCEL, closetext);
EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE);
return 0;
}
static DWORD WINAPI send_thread(LPVOID lpParameter) {
BtrfsSend* bs = (BtrfsSend*)lpParameter;
return bs->Thread();
}
void BtrfsSend::StartSend(HWND hwnd) {
WCHAR s[255];
HWND cl;
ULONG num_clones;
if (started)
return;
GetDlgItemTextW(hwnd, IDC_STREAM_DEST, file, sizeof(file) / sizeof(WCHAR));
if (file[0] == 0)
return;
if (incremental) {
WCHAR parent[MAX_PATH];
GetDlgItemTextW(hwnd, IDC_PARENT_SUBVOL, parent, sizeof(parent) / sizeof(WCHAR));
if (parent[0] == 0)
return;
}
started = TRUE;
ShowSendError(IDS_SEND_WRITING);
LoadStringW(module, IDS_SEND_CANCEL, s, sizeof(s) / sizeof(WCHAR));
SetDlgItemTextW(hwnd, IDCANCEL, s);
EnableWindow(GetDlgItem(hwnd, IDOK), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), FALSE);
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), FALSE);
clones.clear();
cl = GetDlgItem(hwnd, IDC_CLONE_LIST);
num_clones = SendMessageW(cl, LB_GETCOUNT, 0, 0);
if ((LRESULT)num_clones != LB_ERR) {
ULONG i;
for (i = 0; i < num_clones; i++) {
WCHAR* s;
ULONG len;
len = SendMessageW(cl, LB_GETTEXTLEN, i, 0);
s = (WCHAR*)malloc((len + 1) * sizeof(WCHAR));
SendMessageW(cl, LB_GETTEXT, i, (LPARAM)s);
clones.push_back(s);
free(s);
}
}
thread = CreateThread(NULL, 0, send_thread, this, 0, NULL);
if (!thread)
ShowError(NULL, GetLastError());
}
void BtrfsSend::Browse(HWND hwnd) {
OPENFILENAMEW ofn;
file[0] = 0;
memset(&ofn, 0, sizeof(OPENFILENAMEW));
ofn.lStructSize = sizeof(OPENFILENAMEW);
ofn.hwndOwner = hwnd;
ofn.hInstance = module;
ofn.lpstrFile = file;
ofn.nMaxFile = sizeof(file) / sizeof(WCHAR);
if (!GetSaveFileNameW(&ofn))
return;
SetDlgItemTextW(hwnd, IDC_STREAM_DEST, file);
}
void BtrfsSend::BrowseParent(HWND hwnd) {
BROWSEINFOW bi;
PIDLIST_ABSOLUTE root, pidl;
HRESULT hr;
WCHAR parent[MAX_PATH], volpathw[MAX_PATH];
HANDLE h;
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
btrfs_get_file_ids bgfi;
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) {
ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
return;
}
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
if (FAILED(hr)) {
ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED);
return;
}
memset(&bi, 0, sizeof(BROWSEINFOW));
bi.hwndOwner = hwnd;
bi.pidlRoot = root;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON;
pidl = SHBrowseForFolderW(&bi);
if (!pidl)
return;
if (!SHGetPathFromIDListW(pidl, parent)) {
ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED);
return;
}
h = CreateFileW(parent, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
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);
}
void BtrfsSend::AddClone(HWND hwnd) {
BROWSEINFOW bi;
PIDLIST_ABSOLUTE root, pidl;
HRESULT hr;
WCHAR path[MAX_PATH], volpathw[MAX_PATH];
HANDLE h;
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
btrfs_get_file_ids bgfi;
if (!GetVolumePathNameW(subvol.c_str(), volpathw, (sizeof(volpathw) / sizeof(WCHAR)) - 1)) {
ShowStringError(hwnd, IDS_RECV_GETVOLUMEPATHNAME_FAILED, GetLastError(), format_message(GetLastError()).c_str());
return;
}
hr = SHParseDisplayName(volpathw, 0, &root, 0, 0);
if (FAILED(hr)) {
ShowStringError(hwnd, IDS_SHPARSEDISPLAYNAME_FAILED);
return;
}
memset(&bi, 0, sizeof(BROWSEINFOW));
bi.hwndOwner = hwnd;
bi.pidlRoot = root;
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_USENEWUI | BIF_NONEWFOLDERBUTTON;
pidl = SHBrowseForFolderW(&bi);
if (!pidl)
return;
if (!SHGetPathFromIDListW(pidl, path)) {
ShowStringError(hwnd, IDS_SHGETPATHFROMIDLIST_FAILED);
return;
}
h = CreateFileW(path, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h == INVALID_HANDLE_VALUE) {
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);
}
void BtrfsSend::RemoveClone(HWND hwnd) {
LRESULT sel;
HWND cl = GetDlgItem(hwnd, IDC_CLONE_LIST);
sel = SendMessageW(cl, LB_GETCURSEL, 0, 0);
if (sel == LB_ERR)
return;
SendMessageW(cl, LB_DELETESTRING, sel, 0);
if (SendMessageW(cl, LB_GETCURSEL, 0, 0) == LB_ERR)
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), FALSE);
}
INT_PTR BtrfsSend::SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_INITDIALOG:
this->hwnd = hwndDlg;
GetDlgItemTextW(hwndDlg, IDCANCEL, closetext, sizeof(closetext) / sizeof(WCHAR));
break;
case WM_COMMAND:
switch (HIWORD(wParam)) {
case BN_CLICKED:
switch (LOWORD(wParam)) {
case IDOK:
StartSend(hwndDlg);
return TRUE;
case IDCANCEL:
if (started) {
TerminateThread(thread, 0);
if (stream != INVALID_HANDLE_VALUE) {
FILE_DISPOSITION_INFO fdi;
fdi.DeleteFile = TRUE;
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
CloseHandle(stream);
}
if (dirh != INVALID_HANDLE_VALUE)
CloseHandle(dirh);
started = FALSE;
SetDlgItemTextW(hwndDlg, IDCANCEL, closetext);
EnableWindow(GetDlgItem(hwnd, IDOK), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_STREAM_DEST), TRUE);
EnableWindow(GetDlgItem(hwnd, IDC_BROWSE), TRUE);
} else
EndDialog(hwndDlg, 1);
return TRUE;
case IDC_BROWSE:
Browse(hwndDlg);
return TRUE;
case IDC_INCREMENTAL:
incremental = IsDlgButtonChecked(hwndDlg, LOWORD(wParam));
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_SUBVOL), incremental);
EnableWindow(GetDlgItem(hwnd, IDC_PARENT_BROWSE), incremental);
return TRUE;
case IDC_PARENT_BROWSE:
BrowseParent(hwndDlg);
return TRUE;
case IDC_CLONE_ADD:
AddClone(hwndDlg);
return TRUE;
case IDC_CLONE_REMOVE:
RemoveClone(hwndDlg);
return TRUE;
}
break;
case LBN_SELCHANGE:
switch (LOWORD(wParam)) {
case IDC_CLONE_LIST:
EnableWindow(GetDlgItem(hwnd, IDC_CLONE_REMOVE), TRUE);
return TRUE;
}
break;
}
break;
}
return FALSE;
}
static INT_PTR CALLBACK stub_SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
BtrfsSend* bs;
if (uMsg == WM_INITDIALOG) {
SetWindowLongPtr(hwndDlg, GWLP_USERDATA, (LONG_PTR)lParam);
bs = (BtrfsSend*)lParam;
} else
bs = (BtrfsSend*)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
if (bs)
return bs->SendDlgProc(hwndDlg, uMsg, wParam, lParam);
else
return FALSE;
}
void BtrfsSend::Open(HWND hwnd, LPWSTR path) {
subvol = path;
if (DialogBoxParamW(module, MAKEINTRESOURCEW(IDD_SEND_SUBVOL), hwnd, stub_SendDlgProc, (LPARAM)this) <= 0)
ShowError(hwnd, GetLastError());
}
void CALLBACK SendSubvolGUIW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
HANDLE token;
TOKEN_PRIVILEGES tp;
LUID luid;
BtrfsSend* bs;
set_dpi_aware();
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token)) {
ShowError(hwnd, GetLastError());
return;
}
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid)) {
ShowError(hwnd, GetLastError());
return;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) {
ShowError(hwnd, GetLastError());
return;
}
bs = new BtrfsSend;
bs->Open(hwnd, lpszCmdLine);
delete bs;
CloseHandle(token);
}
static void send_subvol(std::wstring subvol, std::wstring file, std::wstring parent, std::vector<std::wstring> clones) {
char* buf;
HANDLE dirh, stream;
ULONG bss_size, i;
btrfs_send_subvol* bss;
IO_STATUS_BLOCK iosb;
NTSTATUS Status;
btrfs_send_header header;
btrfs_send_command end;
BOOL success = FALSE;
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);
if (dirh == INVALID_HANDLE_VALUE)
goto end3;
stream = CreateFileW(file.c_str(), FILE_WRITE_DATA | DELETE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (stream == INVALID_HANDLE_VALUE) {
CloseHandle(dirh);
goto end3;
}
bss_size = offsetof(btrfs_send_subvol, clones[0]) + (clones.size() * sizeof(HANDLE));
bss = (btrfs_send_subvol*)malloc(bss_size);
memset(bss, 0, bss_size);
if (parent != L"") {
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);
if (parenth == INVALID_HANDLE_VALUE)
goto end2;
bss->parent = parenth;
} else
bss->parent = NULL;
bss->num_clones = clones.size();
for (i = 0; i < bss->num_clones; i++) {
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);
if (h == INVALID_HANDLE_VALUE) {
ULONG j;
for (j = 0; j < i; j++) {
CloseHandle(bss->clones[j]);
}
if (bss->parent) CloseHandle(bss->parent);
goto end2;
}
bss->clones[i] = h;
}
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_SEND_SUBVOL, bss, bss_size, NULL, 0);
for (i = 0; i < bss->num_clones; i++) {
CloseHandle(bss->clones[i]);
}
if (bss->parent) CloseHandle(bss->parent);
if (!NT_SUCCESS(Status))
goto end2;
memcpy(header.magic, BTRFS_SEND_MAGIC, sizeof(BTRFS_SEND_MAGIC));
header.version = 1;
if (!WriteFile(stream, &header, sizeof(header), NULL, NULL))
goto end2;
do {
Status = NtFsControlFile(dirh, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_READ_SEND_BUFFER, NULL, 0, buf, SEND_BUFFER_LEN);
if (NT_SUCCESS(Status))
WriteFile(stream, buf, iosb.Information, NULL, NULL);
} while (NT_SUCCESS(Status));
if (Status != STATUS_END_OF_FILE)
goto end2;
end.length = 0;
end.cmd = BTRFS_SEND_CMD_END;
end.csum = 0x9dc96c50;
if (!WriteFile(stream, &end, sizeof(end), NULL, NULL))
goto end2;
SetEndOfFile(stream);
success = TRUE;
end2:
if (!success) {
FILE_DISPOSITION_INFO fdi;
fdi.DeleteFile = TRUE;
SetFileInformationByHandle(stream, FileDispositionInfo, &fdi, sizeof(FILE_DISPOSITION_INFO));
}
CloseHandle(dirh);
CloseHandle(stream);
end3:
free(buf);
}
void CALLBACK SendSubvolW(HWND hwnd, HINSTANCE hinst, LPWSTR lpszCmdLine, int nCmdShow) {
LPWSTR* args;
int num_args;
std::wstring subvol = L"", parent = L"", file = L"";
std::vector<std::wstring> clones;
args = CommandLineToArgvW(lpszCmdLine, &num_args);
if (!args)
return;
if (num_args >= 2) {
HANDLE token;
TOKEN_PRIVILEGES tp;
LUID luid;
int i;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
goto end;
if (!LookupPrivilegeValueW(NULL, L"SeManageVolumePrivilege", &luid))
goto end;
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (!AdjustTokenPrivileges(token, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
goto end;
CloseHandle(token);
for (i = 0; i < num_args; i++) {
if (args[i][0] == '-') {
if (args[i][2] == 0 && i < num_args - 1) {
if (args[i][1] == 'p') {
parent = args[i+1];
i++;
} else if (args[i][1] == 'c') {
clones.push_back(args[i+1]);
i++;
}
}
} else {
if (subvol == L"")
subvol = args[i];
else if (file == L"")
file = args[i];
}
}
if (subvol != L"" && file != L"")
send_subvol(subvol, file, parent, clones);
}
end:
LocalFree(args);
}
+64
View File
@@ -0,0 +1,64 @@
/* Copyright (c) Mark Harmstone 2017
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#ifdef __REACTOS__
#include "btrfs.h"
#include <stdlib.h>
#else
#include "../btrfs.h"
#endif
#include <string>
#include <vector>
class BtrfsSend {
public:
BtrfsSend() {
started = FALSE;
file[0] = 0;
dirh = INVALID_HANDLE_VALUE;
stream = INVALID_HANDLE_VALUE;
subvol = L"";
buf = NULL;
incremental = FALSE;
}
~BtrfsSend() {
if (buf)
free(buf);
}
void Open(HWND hwnd, WCHAR* path);
INT_PTR SendDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
DWORD Thread();
private:
void StartSend(HWND hwnd);
void Browse(HWND hwnd);
void BrowseParent(HWND hwnd);
void AddClone(HWND hwnd);
void RemoveClone(HWND hwnd);
void ShowSendError(UINT msg, ...);
BOOL started;
BOOL incremental;
WCHAR file[MAX_PATH], closetext[255];
HANDLE thread, dirh, stream;
HWND hwnd;
std::wstring subvol;
char* buf;
std::vector <std::wstring> clones;
};
+536 -22
View File
@@ -7,7 +7,7 @@
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
#include "winres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
@@ -27,18 +27,18 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
// TEXTINCLUDE
//
1 TEXTINCLUDE
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"#include ""winres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
@@ -79,12 +79,12 @@ BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "WinBtrfs shell extension"
VALUE "FileVersion", "0.7"
VALUE "FileVersion", "1.0"
VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016-17"
VALUE "OriginalFilename", "shellbtrfs.dll"
VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "0.7"
VALUE "ProductVersion", "1.0"
END
END
BLOCK "VarFileInfo"
@@ -101,7 +101,7 @@ END
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 245
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
CAPTION "s"
CAPTION "Inode property sheet"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
LTEXT "Subvolume:",IDC_STATIC,14,21,38,8
@@ -119,9 +119,9 @@ BEGIN
LTEXT "Read",IDC_STATIC,50,134,17,8
LTEXT "Write",IDC_STATIC,89,134,18,8
LTEXT "Execute",IDC_STATIC,129,134,30,8
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,146,16,10
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,157,16,10
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,167,16,10
CONTROL "",IDC_USERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,147,16,10
CONTROL "",IDC_GROUPR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,158,16,10
CONTROL "",IDC_OTHERR,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,54,168,16,10
CONTROL "",IDC_USERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,147,16,10
CONTROL "",IDC_GROUPW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,158,16,10
CONTROL "",IDC_OTHERW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,168,16,10
@@ -130,12 +130,18 @@ BEGIN
CONTROL "",IDC_OTHERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,168,16,10
GROUPBOX "Flags",IDC_STATIC,7,190,221,48
CONTROL "Disable Copy-on-Write",IDC_NODATACOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,204,86,10
LTEXT "(blank)",IDC_SUBVOL,78,21,99,8
LTEXT "(blank)",IDC_INODE,78,35,100,8
LTEXT "(blank)",IDC_INODE,78,35,70,8
LTEXT "(blank)",IDC_TYPE,78,49,116,8
CONTROL "Compress",IDC_COMPRESS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,218,46,10
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
COMBOBOX IDC_COMPRESS_TYPE,63,217,48,13,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
CONTROL "Readonly subvolume",IDC_SUBVOL_RO,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,124,204,80,10
LTEXT "(blank)",IDC_SUBVOL,78,21,70,8
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 GID",IDC_SETGID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,158,40,10
CONTROL "Sticky",IDC_STICKY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,177,168,34,10
END
IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 85
@@ -154,6 +160,207 @@ BEGIN
LTEXT "(blank)",IDC_SIZE_LZO,63,46,142,8
END
IDD_VOL_PROP_SHEET DIALOGEX 0, 0, 235, 251
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
CAPTION "s"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
PUSHBUTTON "Show &usage...",IDC_VOL_SHOW_USAGE,154,47,67,19
PUSHBUTTON "&Balance...",IDC_VOL_BALANCE,154,105,67,19
PUSHBUTTON "&Devices...",IDC_VOL_DEVICES,154,162,67,19
LTEXT "UUID:",IDC_STATIC,7,15,20,8
LTEXT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",IDC_UUID,32,15,294,8
GROUPBOX "Usage",IDC_STATIC,7,31,221,53
LTEXT "Show detailed information about internal filesystem usage. This is the equivalent to the command ""btrfs fi usage"" on Linux.",IDC_STATIC,14,44,131,33
GROUPBOX "Balance",IDC_STATIC,7,87,221,53
LTEXT "Balancing reads and rewrites data and metadata. It can be used to consolidate free space, as well as to convert between different RAID types.",IDC_STATIC,15,98,131,39
GROUPBOX "Devices",IDC_STATIC,7,146,221,45
LTEXT "Allows you to add disks or partitions to this filesystem, or remove those already present.",IDC_STATIC,14,159,131,30
GROUPBOX "Scrub",IDC_STATIC,7,199,221,45
LTEXT "Scrubbing verifies the data and metadata of a filesystem, and where possible will correct any errors.",IDC_STATIC,15,212,131,27
PUSHBUTTON "&Scrub...",IDC_VOL_SCRUB,154,215,67,19
END
IDD_VOL_USAGE DIALOGEX 0, 0, 235, 242
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Volume usage"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,62,221,50,14
PUSHBUTTON "&Refresh",IDC_USAGE_REFRESH,124,221,50,14
EDITTEXT IDC_USAGE_BOX,7,7,221,208,ES_MULTILINE | ES_AUTOHSCROLL | ES_READONLY | WS_VSCROLL
END
IDD_BALANCE_OPTIONS DIALOGEX 0, 0, 303, 138
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Balance options"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,91,117,50,14
PUSHBUTTON "Cancel",IDCANCEL,161,117,50,14
CONTROL "&Profiles:",IDC_PROFILES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,6,41,10
CONTROL "Single",IDC_PROFILES_SINGLE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,19,35,10
CONTROL "DUP",IDC_PROFILES_DUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,30,29,10
CONTROL "RAID0",IDC_PROFILES_RAID0,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,41,36,10
CONTROL "RAID1",IDC_PROFILES_RAID1,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,52,36,10
CONTROL "RAID10",IDC_PROFILES_RAID10,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,19,39,10
CONTROL "RAID5",IDC_PROFILES_RAID5,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,30,36,10
CONTROL "RAID6",IDC_PROFILES_RAID6,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,52,41,36,10
CONTROL "&Usage:",IDC_USAGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,80,37,10
EDITTEXT IDC_USAGE_START,7,94,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_USAGE_START_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,25,94,11,14
EDITTEXT IDC_USAGE_END,58,94,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_USAGE_END_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,77,94,11,14
LTEXT "% to",IDC_STATIC,39,97,16,8
CONTROL "&Device:",IDC_DEVID,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,6,34,10
COMBOBOX IDC_DEVID_COMBO,141,6,155,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
LTEXT "%",IDC_STATIC,91,97,8,8
CONTROL "Device &range:",IDC_DRANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,19,59,10
EDITTEXT IDC_DRANGE_END,159,32,40,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "to",IDC_STATIC,148,34,8,8
EDITTEXT IDC_DRANGE_START,104,32,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "&Virtual range:",IDC_VRANGE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,49,59,10
EDITTEXT IDC_VRANGE_END,160,62,40,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "to",IDC_STATIC,148,64,8,8
EDITTEXT IDC_VRANGE_START,104,62,40,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "&Limit:",IDC_LIMIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,104,80,33,10
EDITTEXT IDC_LIMIT_START,104,94,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_LIMIT_START_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,123,94,11,14
EDITTEXT IDC_LIMIT_END,150,94,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_LIMIT_END_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,169,94,11,14
LTEXT "to",IDC_STATIC,139,97,8,8
CONTROL "&Stripes:",IDC_STRIPES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,19,40,10
EDITTEXT IDC_STRIPES_START,210,32,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_STRIPES_START_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,228,32,11,14
EDITTEXT IDC_STRIPES_END,253,32,19,14,ES_AUTOHSCROLL | ES_NUMBER
CONTROL "",IDC_STRIPES_END_SPINNER,"msctls_updown32",UDS_SETBUDDYINT | UDS_AUTOBUDDY | UDS_ARROWKEYS,272,32,11,14
LTEXT "to",IDC_STATIC,242,35,8,8
CONTROL "&Convert:",IDC_CONVERT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,49,36,10
COMBOBOX IDC_CONVERT_COMBO,248,49,48,30,CBS_DROPDOWN | WS_VSCROLL | WS_TABSTOP
CONTROL "So&ft",IDC_SOFT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,210,64,28,10
END
IDD_BALANCE DIALOGEX 0, 0, 254, 167
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Balance"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,102,146,50,14
CONTROL "",IDC_BALANCE_PROGRESS,"msctls_progress32",WS_BORDER,7,95,240,14
CONTROL "&Data",IDC_DATA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,7,30,10
CONTROL "&Metadata",IDC_METADATA,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,28,45,10
CONTROL "&System",IDC_SYSTEM,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,51,38,10
PUSHBUTTON "Options...",IDC_DATA_OPTIONS,70,6,50,14
PUSHBUTTON "Options...",IDC_METADATA_OPTIONS,70,26,50,14
PUSHBUTTON "Options...",IDC_SYSTEM_OPTIONS,70,47,50,14
LTEXT "Status",IDC_BALANCE_STATUS,8,80,239,8
PUSHBUTTON "&Start balance",IDC_START_BALANCE,13,117,69,14
PUSHBUTTON "&Pause / resume",IDC_PAUSE_BALANCE,93,117,69,14
PUSHBUTTON "&Cancel balance",IDC_CANCEL_BALANCE,173,117,69,14
END
IDD_DEVICES DIALOGEX 0, 0, 318, 203
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Devices"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,207,182,50,14
PUSHBUTTON "Cancel",IDCANCEL,261,182,50,14
CONTROL "",IDC_DEVLIST,"SysListView32",LVS_REPORT | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,7,7,304,144
PUSHBUTTON "&Add device...",IDC_DEVICE_ADD,7,182,76,14
PUSHBUTTON "&Refresh",IDC_DEVICE_REFRESH,7,159,76,14
PUSHBUTTON "Remove &device",IDC_DEVICE_REMOVE,93,182,76,14
PUSHBUTTON "Show &stats...",IDC_DEVICE_SHOW_STATS,235,159,76,14,WS_DISABLED
PUSHBUTTON "Re&size...",IDC_DEVICE_RESIZE,149,159,76,14,WS_DISABLED
END
IDD_DEVICE_ADD DIALOGEX 0, 0, 261, 185
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Add device"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,66,164,50,14
PUSHBUTTON "Cancel",IDCANCEL,145,164,50,14
CONTROL "",IDC_DEVICE_TREE,"SysTreeView32",TVS_HASBUTTONS | TVS_HASLINES | TVS_SHOWSELALWAYS | WS_BORDER | WS_HSCROLL | WS_TABSTOP,7,7,247,148
END
IDD_SCRUB DIALOGEX 0, 0, 254, 162
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Scrub"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,102,141,50,14
CONTROL "",IDC_SCRUB_PROGRESS,"msctls_progress32",WS_BORDER,7,95,240,14
LTEXT "Status",IDC_SCRUB_STATUS,8,81,239,8
PUSHBUTTON "&Start scrub",IDC_START_SCRUB,13,117,69,14
PUSHBUTTON "&Pause / resume",IDC_PAUSE_SCRUB,93,117,69,14
PUSHBUTTON "&Cancel scrub",IDC_CANCEL_SCRUB,173,117,69,14
EDITTEXT IDC_SCRUB_INFO,7,7,240,69,ES_MULTILINE | ES_READONLY | WS_VSCROLL
END
IDD_DEVICE_STATS DIALOGEX 0, 0, 159, 113
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Device stats"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,24,91,50,14
LTEXT "Device %llx:",IDC_DEVICE_ID,7,7,40,8
LTEXT "Write errors:",IDC_STATIC,7,21,79,8
LTEXT "Read errors:",IDC_STATIC,7,34,79,8
LTEXT "Flush errors:",IDC_STATIC,7,47,79,8
LTEXT "Corruption errors:",IDC_STATIC,7,60,79,8
LTEXT "Generation errors:",IDC_STATIC,7,73,79,8
RTEXT "%llu",IDC_WRITE_ERRS,87,21,65,8
RTEXT "%llu",IDC_READ_ERRS,87,34,65,8
RTEXT "%llu",IDC_FLUSH_ERRS,87,47,65,8
RTEXT "%llu",IDC_CORRUPTION_ERRS,87,60,65,8
RTEXT "%llu",IDC_GENERATION_ERRS,87,73,65,8
PUSHBUTTON "&Reset",IDC_RESET_STATS,85,91,50,14
END
IDD_RECV_PROGRESS DIALOGEX 0, 0, 311, 83
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Receiving subvolume"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON "Cancel",IDCANCEL,130,62,50,14
CONTROL "",IDC_RECV_PROGRESS,"msctls_progress32",WS_BORDER,7,33,297,24
LTEXT "Receiving subvolume...",IDC_RECV_MSG,7,7,297,18
END
IDD_SEND_SUBVOL DIALOGEX 0, 0, 288, 149
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Send subvolume"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "&Write",IDOK,83,128,50,14
PUSHBUTTON "&Close",IDCANCEL,156,128,50,14
EDITTEXT IDC_STREAM_DEST,57,7,166,14,ES_AUTOHSCROLL
LTEXT "Stream:",IDC_STATIC,7,11,26,8
PUSHBUTTON "&Browse...",IDC_BROWSE,231,7,50,14
LTEXT "Select a destination for the subvolume stream.",IDC_SEND_STATUS,7,93,274,22
CONTROL "Incremental",IDC_INCREMENTAL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,32,54,10
EDITTEXT IDC_PARENT_SUBVOL,69,29,154,14,ES_AUTOHSCROLL | WS_DISABLED
PUSHBUTTON "&Browse...",IDC_PARENT_BROWSE,231,29,50,14,WS_DISABLED
LTEXT "Clone sources:",IDC_STATIC,7,52,46,8
LISTBOX IDC_CLONE_LIST,69,50,154,36,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "&Add...",IDC_CLONE_ADD,231,50,50,14
PUSHBUTTON "&Remove",IDC_CLONE_REMOVE,231,69,50,14,WS_DISABLED
END
IDD_RESIZE DIALOGEX 0, 0, 279, 133
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Resize device"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,81,112,50,14
PUSHBUTTON "Cancel",IDCANCEL,148,112,50,14
LTEXT "Device %llx:",IDC_RESIZE_DEVICE_ID,18,21,238,8
LTEXT "Current size: %s",IDC_RESIZE_CURSIZE,18,37,238,8
CONTROL "",IDC_RESIZE_SLIDER,"msctls_trackbar32",TBS_BOTH | TBS_NOTICKS | WS_TABSTOP,7,74,265,24
LTEXT "New size: %s",IDC_RESIZE_NEWSIZE,18,53,238,8
END
/////////////////////////////////////////////////////////////////////////////
//
@@ -161,7 +368,7 @@ END
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
GUIDELINES DESIGNINFO
BEGIN
IDD_PROP_SHEET, DIALOG
BEGIN
@@ -178,6 +385,94 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 78
END
IDD_VOL_PROP_SHEET, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 244
END
IDD_VOL_USAGE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 235
END
IDD_BALANCE_OPTIONS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 296
TOPMARGIN, 7
BOTTOMMARGIN, 131
END
IDD_BALANCE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 247
TOPMARGIN, 7
BOTTOMMARGIN, 160
END
IDD_DEVICES, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 311
TOPMARGIN, 7
BOTTOMMARGIN, 196
END
IDD_DEVICE_ADD, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 254
TOPMARGIN, 7
BOTTOMMARGIN, 178
END
IDD_SCRUB, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 247
TOPMARGIN, 7
BOTTOMMARGIN, 155
END
IDD_DEVICE_STATS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 152
TOPMARGIN, 7
BOTTOMMARGIN, 105
END
IDD_RECV_PROGRESS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 304
TOPMARGIN, 7
BOTTOMMARGIN, 76
END
IDD_SEND_SUBVOL, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 281
TOPMARGIN, 7
BOTTOMMARGIN, 142
END
IDD_RESIZE, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 272
TOPMARGIN, 7
BOTTOMMARGIN, 126
END
END
#endif // APSTUDIO_INVOKED
@@ -194,10 +489,10 @@ END
// String Table
//
STRINGTABLE
STRINGTABLE
BEGIN
IDS_NEW_SUBVOL_HELP_TEXT "Creates a new Btrfs subvolume."
IDS_NEW_SUBVOL "New subvolume"
IDS_NEW_SUBVOL "&New subvolume"
IDS_NEW_SUBVOL_FILENAME "New subvolume"
IDS_CREATE_SNAPSHOT "Create snapshot"
IDS_CREATE_SNAPSHOT_HELP_TEXT "Creates a snapshot of a Btrfs subvolume."
@@ -205,17 +500,17 @@ BEGIN
IDS_PROP_SHEET_TITLE "Btrfs properties"
IDS_INODE_FILE "File"
IDS_INODE_DIR "Directory"
IDS_INODE_CHAR "Character device (major %llu, minor %u)"
IDS_INODE_CHAR "Character device (major %llu, minor %llu)"
END
STRINGTABLE
STRINGTABLE
BEGIN
IDS_INODE_BLOCK "Block device (major %llu, minor %u)"
IDS_INODE_BLOCK "Block device (major %llu, minor %llu)"
IDS_INODE_FIFO "FIFO"
IDS_INODE_SOCKET "Socket"
IDS_INODE_SYMLINK "Symbolic link"
IDS_INODE_UNKNOWN "Unknown inode type %x"
IDS_SET_INODE_INFO_ERROR "FSCTL_BTRFS_SET_INODE_INFO returned %08x"
IDS_CANNOT_FIND_DEVICE "Cannot find device."
IDS_SIZE_BYTE "%s byte"
IDS_SIZE_BYTES "%s bytes"
IDS_SIZE_KB "%1.1f KB"
@@ -228,10 +523,229 @@ BEGIN
IDS_INODE_CHAR_SIMPLE "Character device"
END
STRINGTABLE
STRINGTABLE
BEGIN
IDS_INODE_BLOCK_SIMPLE "Block device"
IDS_VOL_PROP_SHEET_TITLE "Btrfs"
IDS_SIZE_LARGE "%s (%s)"
IDS_SINGLE "single"
IDS_DUP "DUP"
IDS_RAID0 "RAID0"
IDS_RAID1 "RAID1"
IDS_RAID10 "RAID10"
IDS_RAID5 "RAID5"
IDS_RAID6 "RAID6"
IDS_USAGE_DATA "Data, %s: size: %s, used: %s"
IDS_USAGE_MIXED "Data / metadata, %s: size: %s, used: %s"
IDS_USAGE_METADATA "Metadata, %s: size: %s, used: %s"
IDS_USAGE_SYSTEM "System, %s: size: %s, used: %s"
IDS_USAGE_UNALLOC "Unallocated:"
IDS_UNKNOWN_DEVICE "(unknown device %llu)"
END
STRINGTABLE
BEGIN
IDS_USAGE_DEV_SIZE "Device size:\t\t%s"
IDS_USAGE_DEV_ALLOC "Device allocated:\t\t%s"
IDS_USAGE_DEV_UNALLOC "Device unallocated:\t\t%s"
IDS_USAGE_DATA_RATIO "Data ratio:\t\t%1.2f"
IDS_USAGE_METADATA_RATIO "Metadata ratio:\t\t%1.2f"
IDS_NO_BALANCE "No balance is currently running."
IDS_SINGLE2 "Single"
IDS_DEVID_LIST "%llu: %s"
IDS_BALANCE_RUNNING "Balance is currently running (%llu out of %llu chunks processed, %1.1f%%)"
IDS_DRANGE_END_BEFORE_START "Device range end is before start."
IDS_VRANGE_END_BEFORE_START "Virtual range end is before start."
IDS_LIMIT_END_BEFORE_START "Limit end is before start."
IDS_STRIPES_END_BEFORE_START "Stripes end is before start."
IDS_USAGE_END_BEFORE_START "Usage end is before start."
IDS_ERROR "Error"
IDS_BALANCE_COMPLETE "Balance completed successfully."
END
STRINGTABLE
BEGIN
IDS_BALANCE_PAUSED "Balance is currently paused (%llu out of %llu chunks processed, %1.1f%%)"
IDS_BALANCE_CANCELLED "Balance cancelled."
IDS_DEVLIST_ID "ID"
IDS_DEVLIST_DESC "Description"
IDS_DEVLIST_READONLY "Read-only"
IDS_DEVLIST_SIZE "Size"
IDS_DEVLIST_READONLY_YES "Yes"
IDS_DEVLIST_READONLY_NO "No"
IDS_DEVLIST_ALLOC "Allocated"
IDS_DEVLIST_ALLOC_PC "%"
IDS_BALANCE_RUNNING_REMOVAL
"Currently removing device %llu (%llu out of %llu chunks processed, %1.1f%%)"
IDS_BALANCE_PAUSED_REMOVAL
"Removal of device %llu paused (%llu out of %llu chunks processed, %1.1f%%)"
IDS_BALANCE_CANCELLED_REMOVAL "Device removal cancelled."
IDS_BALANCE_COMPLETE_REMOVAL "Device removal completed successfully."
IDS_PARTITION "Partition %u"
IDS_WHOLE_DISK "Whole disk"
END
STRINGTABLE
BEGIN
IDS_CANNOT_REMOVE_RAID "The current RAID levels do not allow this device to be removed. You must do a conversion balance before you will be able to proceed."
IDS_REMOVE_DEVICE_CONFIRMATION
"Are you sure that you want to remove device %s, %s?"
IDS_CONFIRMATION_TITLE "Confirmation"
IDS_ADD_DEVICE_CONFIRMATION
"Are you sure that you want to add this device?"
IDS_ADD_DEVICE_CONFIRMATION_FS
"Are you sure that you want to add this device? It already appears to contain a filesystem (%s)."
IDS_BALANCE_FAILED "Balance failed (error %08x, %s)"
IDS_BALANCE_FAILED_REMOVAL "Device removal failed (error %08x, %s)"
IDS_DISK_NUM "Disk %u"
IDS_DISK_PART_NUM "Disk %u, partition %u"
IDS_NO_SCRUB "Scrub not running."
IDS_SCRUB_RUNNING "Scrub currently running (%llu out of %llu chunks processed, %1.1f%%)"
IDS_SCRUB_FINISHED "Scrub finished."
IDS_SCRUB_PAUSED "Scrub paused (%llu out of %llu chunks processed, %1.1f%%)"
IDS_SCRUB_MSG_STARTED "Scrub started at %s %s."
IDS_SCRUB_MSG_RECOVERABLE_DATA
"Recovered from data checksum error at %llx on device %llx."
IDS_SCRUB_MSG_RECOVERABLE_METADATA
"Recovered from metadata checksum error at %llx on device %llx."
END
STRINGTABLE
BEGIN
IDS_SCRUB_MSG_UNRECOVERABLE_DATA
"Unrecoverable data checksum error at %llx on device %llx (%.*s, offset %llx)"
IDS_SCRUB_MSG_UNRECOVERABLE_DATA_SUBVOL
"Unrecoverable data checksum error at %llx on device %llx (subvol %llx, %.*s, offset %llx)"
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA
"Unrecoverable metadata checksum error at %llx on device %llx (root %llx, level %x)"
IDS_SCRUB_MSG_UNRECOVERABLE_METADATA_FIRSTITEM
"Unrecoverable metadata checksum error at %llx on device %llx (root %llx, level %x, first item %llx,%x,%llx)"
IDS_SCRUB_MSG_FINISHED "Scrub finished at %s %s."
IDS_SCRUB_MSG_SUMMARY "Scrubbed %s in %llu seconds (%s/s)."
IDS_BALANCE_SCRUB_RUNNING "Cannot start balance while scrub running."
IDS_SCRUB_BALANCE_RUNNING "Cannot start scrub while balance running."
IDS_SCRUB_MSG_SUMMARY_ERRORS_RECOVERABLE "Recovered from %llu error(s)."
IDS_SCRUB_MSG_SUMMARY_ERRORS_UNRECOVERABLE
"%llu unrecoverable error(s) found."
IDS_SCRUB_FAILED "Scrub failed with error %08x."
IDS_LOCK_FAILED "Unable to lock volume: error %08x. Make sure that there are no files open, and that you have closed any Explorer windows."
IDS_SCRUB_MSG_RECOVERABLE_PARITY
"Recovered from parity error at %llx on device %llx."
IDS_COMPRESS_ANY "(any)"
IDS_COMPRESS_ZLIB "Zlib"
IDS_COMPRESS_LZO "LZO"
END
STRINGTABLE
BEGIN
IDS_STANDALONE_PROPSHEET_TITLE "Inode property sheet"
IDS_REFLINK_PASTE "Ref&link Paste"
IDS_REFLINK_PASTE_HELP "Do a lightweight copy of files using reference counting."
IDS_RECV_SUBVOL "Re&ceive subvolume..."
IDS_RECV_SUBVOL_HELP "Recreate a previously exported subvolume."
IDS_RECV_CANT_OPEN_FILE "%S: Couldn't open %s (error %u, %s)."
IDS_RECV_READFILE_FAILED "ReadFile failed (error %u, %s)."
IDS_OUT_OF_MEMORY "Out of memory."
IDS_RECV_UNKNOWN_COMMAND "Unrecognized command %u encountered."
IDS_RECV_CANT_OPEN_PATH "Couldn't open path %s (error %u, %s)."
IDS_RECV_RTLUTF8TOUNICODEN_FAILED "RtlUTF8ToUnicodeN returned %08x (%s)."
IDS_RECV_CREATE_SUBVOL_FAILED
"FSCTL_BTRFS_CREATE_SUBVOL returned %08x (%s)."
IDS_RECV_MISSING_PARAM "%S: could not find %s parameter."
IDS_RECV_SHORT_PARAM "%S: length of parameter %s was %u, expected %u."
IDS_RECV_MKNOD_FAILED "FSCTL_BTRFS_MKNOD returned %08x (%s)."
IDS_RECV_SET_REPARSE_POINT_FAILED
"FSCTL_SET_REPARSE_POINT returned %08x (%s)."
END
STRINGTABLE
BEGIN
IDS_RECV_MOVEFILE_FAILED "MoveFile (%s -> %s) failed (error %u, %s)."
IDS_RECV_SETFILEPOINTER_FAILED "SetFilePointer failed (error %u, %s)."
IDS_RECV_WRITEFILE_FAILED "WriteFile failed (error %u, %s)."
IDS_RECV_CREATEHARDLINK_FAILED
"CreateHardLink (%s -> %s) failed (error %u, %s)."
IDS_RECV_SETENDOFFILE_FAILED "SetEndOfFile failed (error %u, %s)."
IDS_RECV_CANT_CREATE_FILE "Couldn't create %s (error %u, %s)."
IDS_RECV_SETFILEINFO_FAILED
"SetFileInformationByHandle failed (error %u, %s)."
IDS_RECV_SETINODEINFO_FAILED
"FSCTL_BTRFS_SET_INODE_INFO returned %08x (%s)."
IDS_RECV_SUCCESS "Received 1 subvolume successfully."
IDS_RECV_BUTTON_OK "OK"
IDS_RECV_SETFILEATTRIBUTES_FAILED
"SetFileAttributes failed (error %u, %s)."
IDS_RECV_GETFILEATTRIBUTES_FAILED
"GetFileAttributes failed (error %u, %s)."
IDS_RECV_CSUM_ERROR "Checksum error."
IDS_RECV_NOT_A_SEND_STREAM "File was not a send stream."
IDS_RECV_UNSUPPORTED_VERSION "Unsupported version %u."
IDS_RECV_SETEAFILE_FAILED "NtSetEaFile returned %08x (%s)."
END
STRINGTABLE
BEGIN
IDS_RECV_RECEIVED_SUBVOL_FAILED
"FSCTL_BTRFS_RECEIVED_SUBVOL returned %08x (%s)."
IDS_RECV_SETSECURITYOBJECT_FAILED
"NtSetSecurityObject returned %08x (%s)."
IDS_RECV_SETXATTR_FAILED "FSCTL_BTRFS_SET_XATTR returned %08x (%s)."
IDS_RECV_CREATETHREAD_FAILED "CreateThread failed (error %u, %s)."
IDS_RECV_FILE_TRUNCATED "File was truncated."
IDS_RECV_RESERVE_SUBVOL_FAILED
"FSCTL_BTRFS_RESERVE_SUBVOL returned %08x (%s)."
IDS_RECV_CANCELLED "Receiving cancelled."
IDS_RECV_CANT_FIND_PARENT_SUBVOL "Could not find parent subvolume."
IDS_RECV_FIND_SUBVOL_FAILED "FSCTL_BTRFS_FIND_SUBVOL returned %08x (%s)."
IDS_RECV_CREATE_SNAPSHOT_FAILED
"FSCTL_BTRFS_CREATE_SNAPSHOT returned %08x (%s)."
IDS_RECV_GETVOLUMEPATHNAME_FAILED
"GetVolumePathName failed (error %u, %s)."
IDS_RECV_DELETEFILE_FAILED "DeleteFile failed for %s (error %u, %s)."
IDS_RECV_REMOVEDIRECTORY_FAILED
"RemoveDirectory failed for %s (error %u, %s)."
IDS_RECV_CANT_FIND_CLONE_SUBVOL "Could not find clone subvolume."
IDS_RECV_GETFILESIZEEX_FAILED "GetFileSizeEx failed (error %u, %s)."
IDS_RECV_DUPLICATE_EXTENTS_FAILED
"FSCTL_DUPLICATE_EXTENTS_TO_FILE returned %08x (%s)."
END
STRINGTABLE
BEGIN
IDS_RECV_SUCCESS_PLURAL "Received %u subvolumes successfully."
IDS_SEND_SUBVOL "&Send subvolume..."
IDS_SEND_SUBVOL_HELP "Exports a subvolume so that it can be recreated on another volume."
IDS_SEND_CANT_OPEN_FILE "Error opening file %s (error %u, %s)."
IDS_SEND_CANT_OPEN_DIR "Error opening directory %s (error %u, %s)."
IDS_SEND_FSCTL_BTRFS_SEND_SUBVOL_FAILED
"FSCTL_BTRFS_SEND_SUBVOL returned error %08x (%s)."
IDS_SEND_FSCTL_BTRFS_READ_SEND_BUFFER_FAILED
"FSCTL_BTRFS_READ_SEND_BUFFER returned error %08x (%s)."
IDS_SEND_SUCCESS "Stream written successfully."
IDS_SEND_WRITEFILE_FAILED "Writing to file failed (error %u, %s)."
IDS_SEND_GET_FILE_INFO_FAILED
"GetFileInformationByHandle failed (error %u, %s)."
IDS_SEND_NOT_READONLY "Subvolume not readonly."
IDS_NOT_SUBVOL "Directory was not a subvolume."
IDS_GET_FILE_IDS_FAILED "FSCTL_BTRFS_GET_FILE_IDS returned error %08x (%s)."
IDS_SHPARSEDISPLAYNAME_FAILED "SHParseDisplayName failed."
IDS_SHGETPATHFROMIDLIST_FAILED "SHGetPathFromIDList failed."
IDS_SEND_PARENT_NOT_READONLY "Parent subvolume not readonly."
END
STRINGTABLE
BEGIN
IDS_SEND_CANCEL "&Cancel"
IDS_SEND_WRITING "Writing..."
IDS_MISSING "(missing)"
IDS_RESIZE_SUCCESSFUL "Device %llx successfully resized to %s."
IDS_BALANCE_RUNNING_SHRINK
"Currently shrinking device %llu (%llu out of %llu chunks processed, %1.1f%%)"
IDS_BALANCE_PAUSED_SHRINK
"Shrinking of device %llu paused (%llu out of %llu chunks processed, %1.1f%%)"
IDS_BALANCE_CANCELLED_SHRINK "Device shrinking cancelled."
IDS_BALANCE_COMPLETE_SHRINK "Device successfully shrunk."
IDS_BALANCE_FAILED_SHRINK "Device shrinking failed (error %08x, %s)"
END
#endif // English (U.K.) resources
+185
View File
@@ -0,0 +1,185 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#define ISOLATION_AWARE_ENABLED 1
#define STRSAFE_NO_DEPRECATE
#ifndef __REACTOS__
#define WINVER 0x0A00 // Windows 10
#define _WIN32_WINNT 0x0A00
#endif
#ifndef __REACTOS__
#include <windows.h>
#include <winternl.h>
#else
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
#include <strsafe.h>
#include <ndk/iofuncs.h>
#endif
#include <string>
#ifndef __REACTOS__
#include "../btrfs.h"
#include "../btrfsioctl.h"
#else
#include "btrfs.h"
#include "btrfsioctl.h"
#endif
#ifndef __REACTOS__
#define STATUS_SUCCESS (NTSTATUS)0x00000000
#define STATUS_BUFFER_OVERFLOW (NTSTATUS)0x80000005
#define STATUS_END_OF_FILE (NTSTATUS)0xc0000011
#define STATUS_MORE_PROCESSING_REQUIRED (NTSTATUS)0xc0000016
#define STATUS_BUFFER_TOO_SMALL (NTSTATUS)0xc0000023
#define STATUS_DEVICE_NOT_READY (NTSTATUS)0xc00000a3
#define STATUS_CANNOT_DELETE (NTSTATUS)0xc0000121
#define STATUS_NOT_FOUND (NTSTATUS)0xc0000225
#endif
#define BLOCK_FLAG_DATA 0x001
#define BLOCK_FLAG_SYSTEM 0x002
#define BLOCK_FLAG_METADATA 0x004
#define BLOCK_FLAG_RAID0 0x008
#define BLOCK_FLAG_RAID1 0x010
#define BLOCK_FLAG_DUPLICATE 0x020
#define BLOCK_FLAG_RAID10 0x040
#define BLOCK_FLAG_RAID5 0x080
#define BLOCK_FLAG_RAID6 0x100
#define BTRFS_TYPE_FILE 1
#define BTRFS_TYPE_DIRECTORY 2
#define BTRFS_TYPE_CHARDEV 3
#define BTRFS_TYPE_BLOCKDEV 4
#define BTRFS_TYPE_FIFO 5
#define BTRFS_TYPE_SOCKET 6
#define BTRFS_TYPE_SYMLINK 7
#ifdef _MSC_VER
#define funcname __FUNCTION__
#else
#define funcname __func__
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __REACTOS__
NTSYSCALLAPI NTSTATUS NTAPI NtFsControlFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock, ULONG FsControlCode, PVOID InputBuffer, ULONG InputBufferLength,
PVOID OutputBuffer, ULONG OutputBufferLength);
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer,
ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key);
#endif
NTSTATUS WINAPI RtlUTF8ToUnicodeN(PWSTR UnicodeStringDestination, ULONG UnicodeStringMaxWCharCount,
PULONG UnicodeStringActualWCharCount, PCCH UTF8StringSource,
ULONG UTF8StringByteCount);
#ifndef __REACTOS__
NTSTATUS WINAPI NtSetEaFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length);
NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR SecurityDescriptor);
NTSTATUS NTAPI NtQueryInformationFile(HANDLE hFile, PIO_STATUS_BLOCK io, PVOID ptr, ULONG len, FILE_INFORMATION_CLASS FileInformationClass);
#ifdef __cplusplus
}
#endif
#else
BOOL
WINAPI
SetFileInformationByHandle(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
BOOL
WINAPI
GetFileInformationByHandleEx(HANDLE hFile, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, LPVOID lpFileInformation, DWORD dwBufferSize);
#ifdef __cplusplus
}
#endif
#endif
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
#define SYMLINK_FLAG_RELATIVE 1
#ifndef FILE_SUPPORTS_BLOCK_REFCOUNTING
typedef struct _DUPLICATE_EXTENTS_DATA {
HANDLE FileHandle;
LARGE_INTEGER SourceFileOffset;
LARGE_INTEGER TargetFileOffset;
LARGE_INTEGER ByteCount;
} DUPLICATE_EXTENTS_DATA, *PDUPLICATE_EXTENTS_DATA;
#define FSCTL_DUPLICATE_EXTENTS_TO_FILE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 209, METHOD_BUFFERED, FILE_WRITE_ACCESS)
typedef struct _FSCTL_GET_INTEGRITY_INFORMATION_BUFFER {
WORD ChecksumAlgorithm;
WORD Reserved;
DWORD Flags;
DWORD ChecksumChunkSizeInBytes;
DWORD ClusterSizeInBytes;
} FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_GET_INTEGRITY_INFORMATION_BUFFER;
typedef struct _FSCTL_SET_INTEGRITY_INFORMATION_BUFFER {
WORD ChecksumAlgorithm;
WORD Reserved;
DWORD Flags;
} FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, *PFSCTL_SET_INTEGRITY_INFORMATION_BUFFER;
#define FSCTL_GET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 159, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define FSCTL_SET_INTEGRITY_INFORMATION CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 160, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
#endif
extern HMODULE module;
void ShowError(HWND hwnd, ULONG err);
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();
std::wstring format_message(ULONG last_error);
std::wstring format_ntstatus(NTSTATUS Status);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,110 @@
/* Copyright (c) Mark Harmstone 2016-17
*
* This file is part of WinBtrfs.
*
* WinBtrfs is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public Licence as published by
* the Free Software Foundation, either version 3 of the Licence, or
* (at your option) any later version.
*
* WinBtrfs is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public Licence for more details.
*
* You should have received a copy of the GNU Lesser General Public Licence
* along with WinBtrfs. If not, see <http://www.gnu.org/licenses/>. */
#include <shlobj.h>
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#include "../btrfs.h"
#else
#include "btrfsioctl.h"
#include "btrfs.h"
#endif
#include "balance.h"
#include "scrub.h"
extern LONG objs_loaded;
class BtrfsVolPropSheet : public IShellExtInit, IShellPropSheetExt {
public:
BtrfsVolPropSheet() {
refcount = 0;
ignore = TRUE;
stgm_set = FALSE;
devices = NULL;
InterlockedIncrement(&objs_loaded);
balance = NULL;
}
virtual ~BtrfsVolPropSheet() {
if (stgm_set) {
GlobalUnlock(stgm.hGlobal);
ReleaseStgMedium(&stgm);
}
if (devices)
free(devices);
InterlockedDecrement(&objs_loaded);
if (balance)
delete balance;
}
// IUnknown
HRESULT __stdcall QueryInterface(REFIID riid, void **ppObj);
ULONG __stdcall AddRef() {
return InterlockedIncrement(&refcount);
}
ULONG __stdcall Release() {
LONG rc = InterlockedDecrement(&refcount);
if (rc == 0)
delete this;
return rc;
}
// IShellExtInit
virtual HRESULT __stdcall Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID);
// IShellPropSheetExt
virtual HRESULT __stdcall AddPages(LPFNADDPROPSHEETPAGE pfnAddPage, LPARAM lParam);
virtual HRESULT __stdcall ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE pfnReplacePage, LPARAM lParam);
void FormatUsage(HWND hwndDlg, WCHAR* s, ULONG size, btrfs_usage* usage);
void RefreshUsage(HWND hwndDlg);
void ShowUsage(HWND hwndDlg);
INT_PTR CALLBACK UsageDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void RefreshDevList(HWND devlist);
INT_PTR CALLBACK DeviceDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ShowDevices(HWND hwndDlg);
void ShowScrub(HWND hwndDlg);
INT_PTR CALLBACK StatsDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
void ShowStats(HWND hwndDlg, UINT64 devid);
void ResetStats(HWND hwndDlg);
btrfs_device* devices;
BOOL readonly;
BtrfsBalance* balance;
BTRFS_UUID uuid;
BOOL uuid_set;
private:
LONG refcount;
BOOL ignore;
STGMEDIUM stgm;
BOOL stgm_set;
WCHAR fn[MAX_PATH];
UINT64 stats_dev;
};
+1 -1
View File
@@ -4,7 +4,7 @@
The following FSD are shared with: https://github.com/maharmstone/btrfs.
reactos/drivers/filesystems/btrfs # Synced to 1.0
reactos/dll/shellext/shellbtrfs # Synced to 0.7
reactos/dll/shellext/shellbtrfs # Synced to 1.0
reactos/sdk/lib/fslib/btrfslib # Synced to 0.8
The following FSD are shared with: http://www.ext2fsd.com/