mirror of
https://github.com/ApfelTeeSaft/reactos.git
synced 2026-09-02 04:13:34 +00:00
[SHELLBTRFS]
Sync the btrfs shell extension to 1.0 CORE-13763 svn path=/trunk/; revision=75793
This commit is contained in:
@@ -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
@@ -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
@@ -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();
|
||||
};
|
||||
|
||||
Executable
+1081
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
+1618
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;
|
||||
};
|
||||
@@ -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/
|
||||
|
||||
Reference in New Issue
Block a user