Import the BTRFS driver shell extension. It allows having a finer control on btrfs volumes.
Note that not everything works in ReactOS and its usage may lead to bugchecks...

CORE-10892

svn path=/trunk/; revision=73100
This commit is contained in:
Pierre Schweitzer 2016-11-02 19:36:59 +00:00
parent e9a079b458
commit 7f4d8362bf
16 changed files with 2798 additions and 1 deletions

View file

@ -6,5 +6,6 @@ add_subdirectory(devcpux)
add_subdirectory(fontext)
add_subdirectory(netshell)
add_subdirectory(ntobjshex)
add_subdirectory(shellbtrfs)
add_subdirectory(slayer)
add_subdirectory(stobject)
add_subdirectory(stobject)

View file

@ -0,0 +1,23 @@
set_cpp(WITH_RUNTIME WITH_EXCEPTIONS WITH_STL)
remove_definitions(-D_WIN32_WINNT=0x502)
add_definitions(-D_WIN32_WINNT=0x600)
spec2def(shellbtrfs.dll shellbtrfs.spec)
list(APPEND SOURCE
contextmenu.cpp
factory.cpp
iconoverlay.cpp
main.cpp
propsheet.cpp
${CMAKE_CURRENT_BINARY_DIR}/shellbtrfs.def)
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_cd_file(TARGET shellbtrfs DESTINATION reactos/system32 FOR all)

View file

@ -0,0 +1,473 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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 <strsafe.h>
#include <ndk/iofuncs.h>
#endif
#define NO_SHLWAPI_STRFCNS
#include <shlwapi.h>
#include "contextmenu.h"
#include "resource.h"
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "../../drivers/filesystems/btrfs/btrfsioctl.h"
#endif
#define NEW_SUBVOL_VERBA "newsubvol"
#define NEW_SUBVOL_VERBW L"newsubvol"
#define SNAPSHOT_VERBA "snapshot"
#define SNAPSHOT_VERBW L"snapshot"
#ifndef __REACTOS__
// FIXME - is there a way to link to the proper header files without breaking everything?
#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 (NTSTATUS)0x00000000
#endif
typedef struct _KEY_NAME_INFORMATION {
ULONG NameLength;
WCHAR Name[1];
} KEY_NAME_INFORMATION;
typedef ULONG (WINAPI *_RtlNtStatusToDosError)(NTSTATUS Status);
extern HMODULE module;
// FIXME - don't assume subvol's top inode is 0x100
HRESULT __stdcall BtrfsContextMenu::QueryInterface(REFIID riid, void **ppObj) {
if (riid == IID_IUnknown || riid == IID_IContextMenu) {
*ppObj = static_cast<IContextMenu*>(this);
AddRef();
return S_OK;
} else if (riid == IID_IShellExtInit) {
*ppObj = static_cast<IShellExtInit*>(this);
AddRef();
return S_OK;
}
*ppObj = NULL;
return E_NOINTERFACE;
}
HRESULT __stdcall BtrfsContextMenu::Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID) {
HANDLE h;
IO_STATUS_BLOCK iosb;
btrfs_get_file_ids bgfi;
NTSTATUS Status;
if (!pidlFolder) {
FORMATETC format = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
UINT num_files, i;
WCHAR fn[MAX_PATH];
HDROP hdrop;
if (!pdtobj)
return E_FAIL;
stgm.tymed = TYMED_HGLOBAL;
if (FAILED(pdtobj->GetData(&format, &stgm)))
return E_INVALIDARG;
stgm_set = TRUE;
hdrop = (HDROP)GlobalLock(stgm.hGlobal);
if (!hdrop) {
ReleaseStgMedium(&stgm);
stgm_set = FALSE;
return E_INVALIDARG;
}
num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0);
for (i = 0; i < num_files; i++) {
if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(MAX_PATH))) {
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h != INVALID_HANDLE_VALUE) {
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
if (Status == STATUS_SUCCESS && bgfi.inode == 0x100 && !bgfi.top) {
WCHAR parpath[MAX_PATH];
HANDLE h2;
StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn);
PathRemoveFileSpecW(parpath);
h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h2 == INVALID_HANDLE_VALUE) {
CloseHandle(h);
return E_FAIL;
}
ignore = FALSE;
bg = FALSE;
CloseHandle(h2);
CloseHandle(h);
return S_OK;
}
CloseHandle(h);
}
}
}
return S_OK;
}
if (!SHGetPathFromIDListW(pidlFolder, path))
return E_FAIL;
// check we have permissions to create new subdirectory
h = CreateFileW(path, 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 E_FAIL;
// check is Btrfs volume
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
if (Status != STATUS_SUCCESS) {
CloseHandle(h);
return E_FAIL;
}
CloseHandle(h);
ignore = FALSE;
bg = TRUE;
return S_OK;
}
HRESULT __stdcall BtrfsContextMenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) {
WCHAR str[256];
if (ignore)
return E_INVALIDARG;
if (uFlags & CMF_DEFAULTONLY)
return S_OK;
if (!bg) {
if (LoadStringW(module, IDS_CREATE_SNAPSHOT, str, sizeof(str) / sizeof(WCHAR)) == 0)
return E_FAIL;
if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str))
return E_FAIL;
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
}
if (LoadStringW(module, IDS_NEW_SUBVOL, str, sizeof(str) / sizeof(WCHAR)) == 0)
return E_FAIL;
if (!InsertMenuW(hmenu, indexMenu, MF_BYPOSITION, idCmdFirst, str))
return E_FAIL;
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
}
static 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 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 (!ntdll) {
MessageBoxW(hwnd, L"Error loading RtlNtStatusToDosError in ntdll.dll", L"Error", MB_ICONERROR);
FreeLibrary(ntdll);
return;
}
ShowError(hwnd, RtlNtStatusToDosError(Status));
FreeLibrary(ntdll);
}
static void create_snapshot(HWND hwnd, WCHAR* fn) {
HANDLE h;
NTSTATUS Status;
IO_STATUS_BLOCK iosb;
btrfs_get_file_ids bgfi;
h = CreateFileW(fn, FILE_TRAVERSE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h != INVALID_HANDLE_VALUE) {
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_GET_FILE_IDS, NULL, 0, &bgfi, sizeof(btrfs_get_file_ids));
if (Status == STATUS_SUCCESS && bgfi.inode == 0x100 && !bgfi.top) {
WCHAR parpath[MAX_PATH], subvolname[MAX_PATH], templ[MAX_PATH], name[MAX_PATH], searchpath[MAX_PATH];
HANDLE h2, fff;
btrfs_create_snapshot* bcs;
ULONG namelen, pathend;
WIN32_FIND_DATAW wfd;
SYSTEMTIME time;
StringCchCopyW(parpath, sizeof(parpath) / sizeof(WCHAR), fn);
PathRemoveFileSpecW(parpath);
StringCchCopyW(subvolname, sizeof(subvolname) / sizeof(WCHAR), fn);
PathStripPathW(subvolname);
h2 = CreateFileW(parpath, FILE_ADD_SUBDIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (h2 == INVALID_HANDLE_VALUE) {
ShowError(hwnd, GetLastError());
CloseHandle(h);
return;
}
if (!LoadStringW(module, IDS_SNAPSHOT_FILENAME, templ, MAX_PATH)) {
ShowError(hwnd, GetLastError());
CloseHandle(h);
CloseHandle(h2);
return;
}
GetLocalTime(&time);
if (StringCchPrintfW(name, sizeof(name) / sizeof(WCHAR), templ, subvolname, time.wYear, time.wMonth, time.wDay) == STRSAFE_E_INSUFFICIENT_BUFFER) {
MessageBoxW(hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR);
CloseHandle(h);
CloseHandle(h2);
return;
}
StringCchCopyW(searchpath, sizeof(searchpath) / sizeof(WCHAR), parpath);
StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), L"\\");
pathend = wcslen(searchpath);
StringCchCatW(searchpath, sizeof(searchpath) / sizeof(WCHAR), name);
fff = FindFirstFileW(searchpath, &wfd);
if (fff != INVALID_HANDLE_VALUE) {
ULONG i = wcslen(searchpath), num = 2;
do {
FindClose(fff);
searchpath[i] = 0;
if (StringCchPrintfW(searchpath, sizeof(searchpath) / sizeof(WCHAR), L"%s (%u)", searchpath, num) == STRSAFE_E_INSUFFICIENT_BUFFER) {
MessageBoxW(hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR);
CloseHandle(h);
CloseHandle(h2);
return;
}
fff = FindFirstFileW(searchpath, &wfd);
num++;
} while (fff != INVALID_HANDLE_VALUE);
}
namelen = wcslen(&searchpath[pathend]) * sizeof(WCHAR);
bcs = (btrfs_create_snapshot*)malloc(sizeof(btrfs_create_snapshot) - 1 + namelen);
bcs->subvol = h;
bcs->namelen = namelen;
memcpy(bcs->name, &searchpath[pathend], namelen);
Status = NtFsControlFile(h2, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SNAPSHOT, NULL, 0, bcs, sizeof(btrfs_create_snapshot) - 1 + namelen);
if (Status != STATUS_SUCCESS)
ShowNtStatusError(hwnd, Status);
CloseHandle(h2);
}
CloseHandle(h);
} else
ShowError(hwnd, GetLastError());
}
HRESULT __stdcall BtrfsContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici) {
if (ignore)
return E_INVALIDARG;
if (!bg) {
if ((IS_INTRESOURCE(pici->lpVerb) && pici->lpVerb == 0) || !strcmp(pici->lpVerb, SNAPSHOT_VERBA)) {
UINT num_files, i;
WCHAR fn[MAX_PATH];
if (!stgm_set)
return E_FAIL;
num_files = DragQueryFileW((HDROP)stgm.hGlobal, 0xFFFFFFFF, NULL, 0);
if (num_files == 0)
return E_FAIL;
for (i = 0; i < num_files; i++) {
if (DragQueryFileW((HDROP)stgm.hGlobal, i, fn, sizeof(fn) / sizeof(MAX_PATH))) {
create_snapshot(pici->hwnd, fn);
}
}
return S_OK;
}
return E_FAIL;
}
if ((IS_INTRESOURCE(pici->lpVerb) && pici->lpVerb == 0) || !strcmp(pici->lpVerb, NEW_SUBVOL_VERBA)) {
HANDLE h;
IO_STATUS_BLOCK iosb;
NTSTATUS Status;
ULONG pathlen, searchpathlen, pathend;
WCHAR name[MAX_PATH], *searchpath;
HANDLE fff;
WIN32_FIND_DATAW wfd;
if (!LoadStringW(module, IDS_NEW_SUBVOL_FILENAME, name, MAX_PATH)) {
ShowError(pici->hwnd, GetLastError());
return E_FAIL;
}
h = CreateFileW(path, 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) {
ShowError(pici->hwnd, GetLastError());
return E_FAIL;
}
pathlen = wcslen(path);
searchpathlen = pathlen + wcslen(name) + 10;
searchpath = (WCHAR*)malloc(searchpathlen * sizeof(WCHAR));
StringCchCopyW(searchpath, searchpathlen, path);
StringCchCatW(searchpath, searchpathlen, L"\\");
pathend = wcslen(searchpath);
StringCchCatW(searchpath, searchpathlen, name);
fff = FindFirstFileW(searchpath, &wfd);
if (fff != INVALID_HANDLE_VALUE) {
ULONG i = wcslen(searchpath), num = 2;
do {
FindClose(fff);
searchpath[i] = 0;
if (StringCchPrintfW(searchpath, searchpathlen, L"%s (%u)", searchpath, num) == STRSAFE_E_INSUFFICIENT_BUFFER) {
MessageBoxW(pici->hwnd, L"Filename too long.\n", L"Error", MB_ICONERROR);
CloseHandle(h);
return E_FAIL;
}
fff = FindFirstFileW(searchpath, &wfd);
num++;
} while (fff != INVALID_HANDLE_VALUE);
}
Status = NtFsControlFile(h, NULL, NULL, NULL, &iosb, FSCTL_BTRFS_CREATE_SUBVOL, NULL, 0, &searchpath[pathend], wcslen(&searchpath[pathend]) * sizeof(WCHAR));
free(searchpath);
if (Status != STATUS_SUCCESS) {
CloseHandle(h);
ShowNtStatusError(pici->hwnd, Status);
return E_FAIL;
}
CloseHandle(h);
return S_OK;
}
return E_FAIL;
}
HRESULT __stdcall BtrfsContextMenu::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax) {
if (ignore)
return E_INVALIDARG;
if (idCmd != 0)
return E_INVALIDARG;
switch (uFlags) {
case GCS_HELPTEXTA:
if (LoadStringA(module, bg ? IDS_NEW_SUBVOL_HELP_TEXT : IDS_CREATE_SNAPSHOT_HELP_TEXT, pszName, cchMax))
return S_OK;
else
return E_FAIL;
case GCS_HELPTEXTW:
if (LoadStringW(module, bg ? IDS_NEW_SUBVOL_HELP_TEXT : IDS_CREATE_SNAPSHOT_HELP_TEXT, (LPWSTR)pszName, cchMax))
return S_OK;
else
return E_FAIL;
case GCS_VALIDATEA:
case GCS_VALIDATEW:
return S_OK;
case GCS_VERBA:
return StringCchCopyA(pszName, cchMax, bg ? NEW_SUBVOL_VERBA : SNAPSHOT_VERBA);
case GCS_VERBW:
return StringCchCopyW((STRSAFE_LPWSTR)pszName, cchMax, bg ? NEW_SUBVOL_VERBW : SNAPSHOT_VERBW);
default:
return E_INVALIDARG;
}
}

View file

@ -0,0 +1,74 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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>
extern LONG objs_loaded;
class BtrfsContextMenu : public IShellExtInit, IContextMenu {
public:
BtrfsContextMenu() {
refcount = 0;
ignore = TRUE;
stgm_set = FALSE;
InterlockedIncrement(&objs_loaded);
}
virtual ~BtrfsContextMenu() {
if (stgm_set) {
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);
// 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 bg;
WCHAR path[MAX_PATH];
STGMEDIUM stgm;
BOOL stgm_set;
};

View file

@ -0,0 +1,82 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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>
#include "factory.h"
#include "iconoverlay.h"
#include "contextmenu.h"
#include "propsheet.h"
HRESULT __stdcall Factory::QueryInterface(const IID& iid, void** ppv) {
if (iid == IID_IUnknown || iid == IID_IClassFactory) {
*ppv = static_cast<IClassFactory*>(this);
} else {
*ppv = NULL;
return E_NOINTERFACE;
}
reinterpret_cast<IUnknown*>(*ppv)->AddRef();
return S_OK;
}
HRESULT __stdcall Factory::LockServer(BOOL bLock) {
return E_NOTIMPL;
}
HRESULT __stdcall Factory::CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv) {
if (pUnknownOuter)
return CLASS_E_NOAGGREGATION;
switch (type) {
case FactoryIconHandler:
if (iid == IID_IUnknown || iid == IID_IShellIconOverlayIdentifier) {
BtrfsIconOverlay* bio = new BtrfsIconOverlay;
if (!bio)
return E_OUTOFMEMORY;
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;
default:
break;
}
*ppv = NULL;
return E_NOINTERFACE;
}

View file

@ -0,0 +1,65 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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/>. */
extern LONG objs_loaded;
typedef enum {
FactoryUnknown,
FactoryIconHandler,
FactoryContextMenu,
FactoryPropSheet
} factory_type;
class Factory : public IClassFactory {
public:
Factory() {
refcount = 0;
type = FactoryUnknown;
InterlockedIncrement(&objs_loaded);
}
virtual ~Factory() {
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;
}
// IClassFactory
virtual HRESULT __stdcall CreateInstance(IUnknown* pUnknownOuter, const IID& iid, void** ppv);
virtual HRESULT __stdcall LockServer(BOOL bLock);
factory_type type;
private:
LONG refcount;
};

View file

@ -0,0 +1,109 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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>
#endif
#include "iconoverlay.h"
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "../../drivers/filesystems/btrfs/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);
AddRef();
return S_OK;
}
*ppObj = NULL;
return E_NOINTERFACE;
}
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))
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;
}
HRESULT __stdcall BtrfsIconOverlay::IsMemberOf(PCWSTR pwszPath, DWORD dwAttrib) {
HANDLE h;
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) {
CloseHandle(h);
return S_FALSE;
}
CloseHandle(h);
return (bgfi.inode == 0x100 && !bgfi.top) ? S_OK : S_FALSE;
}

View file

@ -0,0 +1,58 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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>
extern LONG objs_loaded;
class BtrfsIconOverlay : public IShellIconOverlayIdentifier {
public:
BtrfsIconOverlay() {
refcount = 0;
InterlockedIncrement(&objs_loaded);
}
virtual ~BtrfsIconOverlay() {
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;
}
// 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);
private:
LONG refcount;
};

View file

@ -0,0 +1,367 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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 <windows.h>
#include <commctrl.h>
#include "factory.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 } };
#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 ICON_OVERLAY_NAME L"WinBtrfs"
HMODULE module;
LONG objs_loaded = 0;
#ifdef __cplusplus
extern "C" {
#endif
STDAPI DllCanUnloadNow(void) {
return objs_loaded == 0 ? S_OK : S_FALSE;
}
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) {
if (rclsid == CLSID_ShellBtrfsIconHandler) {
Factory* fact = new Factory;
if (!fact)
return E_OUTOFMEMORY;
else {
fact->type = FactoryIconHandler;
return fact->QueryInterface(riid, ppv);
}
} else if (rclsid == CLSID_ShellBtrfsContextMenu) {
Factory* fact = new Factory;
if (!fact)
return E_OUTOFMEMORY;
else {
fact->type = FactoryContextMenu;
return fact->QueryInterface(riid, ppv);
}
} else if (rclsid == CLSID_ShellBtrfsPropSheet) {
Factory* fact = new Factory;
if (!fact)
return E_OUTOFMEMORY;
else {
fact->type = FactoryPropSheet;
return fact->QueryInterface(riid, ppv);
}
}
return CLASS_E_CLASSNOTAVAILABLE;
}
static BOOL write_reg_key(HKEY root, const WCHAR* keyname, const WCHAR* val, DWORD type, const BYTE* data, DWORD datasize) {
LONG l;
HKEY hk;
DWORD dispos;
l = RegCreateKeyExW(root, keyname, NULL, 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);
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;
}
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);
return ret;
}
static BOOL unregister_clsid(const GUID clsid) {
WCHAR* clsidstring;
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
ret = TRUE;
CoTaskMemFree(clsidstring);
return ret;
}
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);
return ret;
}
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
return TRUE;
}
static BOOL reg_context_menu_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) {
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);
return ret;
}
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
return TRUE;
}
static BOOL reg_prop_sheet_handler(const GUID clsid, const WCHAR* filetype, const WCHAR* name) {
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);
return ret;
}
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
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 (!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;
}
return S_OK;
}
STDAPI DllUnregisterServer(void) {
unreg_prop_sheet_handler(L"Folder", ICON_OVERLAY_NAME);
unreg_prop_sheet_handler(L"*", 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_ShellBtrfsPropSheet))
return E_FAIL;
if (!unregister_clsid(CLSID_ShellBtrfsContextMenu))
return E_FAIL;
if (!unregister_clsid(CLSID_ShellBtrfsIconHandler))
return E_FAIL;
return S_OK;
}
STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) {
if (bInstall)
return DllRegisterServer();
else
return DllUnregisterServer();
}
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, void* lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH)
module = (HMODULE)hModule;
return TRUE;
}
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,167 @@
/* Copyright (c) Mark Harmstone 2016
*
* 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>
#ifndef __REACTOS__
#include "../btrfsioctl.h"
#else
#include "../../drivers/filesystems/btrfs/btrfsioctl.h"
#endif
#ifndef S_IRUSR
#define S_IRUSR 0000400
#endif
#ifndef S_IWUSR
#define S_IWUSR 0000200
#endif
#ifndef S_IXUSR
#define S_IXUSR 0000100
#endif
#ifndef S_IRGRP
#define S_IRGRP (S_IRUSR >> 3)
#endif
#ifndef S_IWGRP
#define S_IWGRP (S_IWUSR >> 3)
#endif
#ifndef S_IXGRP
#define S_IXGRP (S_IXUSR >> 3)
#endif
#ifndef S_IROTH
#define S_IROTH (S_IRGRP >> 3)
#endif
#ifndef S_IWOTH
#define S_IWOTH (S_IWGRP >> 3)
#endif
#ifndef S_IXOTH
#define S_IXOTH (S_IXGRP >> 3)
#endif
#define BTRFS_INODE_NODATASUM 0x001
#define BTRFS_INODE_NODATACOW 0x002
#define BTRFS_INODE_READONLY 0x004
#define BTRFS_INODE_NOCOMPRESS 0x008
#define BTRFS_INODE_PREALLOC 0x010
#define BTRFS_INODE_SYNC 0x020
#define BTRFS_INODE_IMMUTABLE 0x040
#define BTRFS_INODE_APPEND 0x080
#define BTRFS_INODE_NODUMP 0x100
#define BTRFS_INODE_NOATIME 0x200
#define BTRFS_INODE_DIRSYNC 0x400
#define BTRFS_INODE_COMPRESS 0x800
extern LONG objs_loaded;
class BtrfsPropSheet : public IShellExtInit, IShellPropSheetExt {
public:
BtrfsPropSheet() {
refcount = 0;
ignore = TRUE;
stgm_set = FALSE;
readonly = FALSE;
flags_changed = FALSE;
perms_changed = FALSE;
uid_changed = FALSE;
gid_changed = FALSE;
can_change_perms = FALSE;
can_change_owner = FALSE;
thread = NULL;
mode = mode_set = 0;
flags = flags_set = 0;
sizes[0] = sizes[1] = sizes[2] = sizes[3] = 0;
totalsize = 0;
InterlockedIncrement(&objs_loaded);
}
virtual ~BtrfsPropSheet() {
if (stgm_set) {
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 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);
void change_gid(HWND hDlg, UINT32 gid);
void apply_changes(HWND hDlg);
void set_size_on_disk(HWND hwndDlg);
void add_to_search_list(WCHAR* fn);
DWORD search_list_thread();
void do_search(WCHAR* fn);
void update_size_details_dialog(HWND hDlg);
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;
UINT32 uid, gid;
BOOL various_subvols, various_inodes, various_types, various_uids, various_gids;
private:
LONG refcount;
BOOL ignore;
STGMEDIUM stgm;
BOOL stgm_set;
BOOL flags_changed, perms_changed, uid_changed, gid_changed;
UINT64 sizes[4], totalsize;
std::deque<WCHAR*> search_list;
};

View file

@ -0,0 +1,69 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by shellbtrfs.rc
//
#define IDI_ICON1 101
#define IDS_NEW_SUBVOL_HELP_TEXT 102
#define IDS_NEW_SUBVOL 103
#define IDD_SIZE_DETAILS 103
#define IDS_NEW_SUBVOL_FILENAME 104
#define IDS_CREATE_SNAPSHOT 105
#define IDS_CREATE_SNAPSHOT_HELP_TEXT 106
#define IDS_SNAPSHOT_FILENAME 107
#define IDD_PROP_SHEET 107
#define IDS_PROP_SHEET_TITLE 108
#define IDS_INODE_FILE 109
#define IDS_INODE_DIR 110
#define IDS_INODE_CHAR 111
#define IDS_INODE_BLOCK 112
#define IDS_INODE_FIFO 113
#define IDS_INODE_SOCKET 114
#define IDS_INODE_SYMLINK 115
#define IDS_INODE_UNKNOWN 116
#define IDS_SET_INODE_INFO_ERROR 117
#define IDS_SIZE_BYTE 118
#define IDS_SIZE_BYTES 119
#define IDS_SIZE_KB 120
#define IDS_SIZE_MB 121
#define IDS_SIZE_GB 122
#define IDS_SIZE_TB 123
#define IDS_SIZE_PB 124
#define IDS_SIZE_EB 125
#define IDS_VARIOUS 126
#define IDS_INODE_CHAR_SIMPLE 127
#define IDS_INODE_BLOCK_SIMPLE 128
#define IDS_SIZE_LARGE 130
#define IDC_UID 1001
#define IDC_GID 1002
#define IDC_USERR 1003
#define IDC_GROUPR 1004
#define IDC_OTHERR 1005
#define IDC_USERW 1006
#define IDC_GROUPW 1007
#define IDC_OTHERW 1008
#define IDC_USERX 1009
#define IDC_GROUPX 1010
#define IDC_OTHERX 1011
#define IDC_NODATACOW 1012
#define IDC_SUBVOL 1013
#define IDC_INODE 1014
#define IDC_TYPE 1015
#define IDC_COMPRESS 1016
#define IDC_SIZE_ON_DISK 1017
#define IDC_GROUP_INFORMATION 1018
#define IDC_SIZE_INLINE 1019
#define IDC_SIZE_UNCOMPRESSED 1020
#define IDC_SIZE_ZLIB 1021
#define IDC_SIZE_ZLIB2 1022
#define IDC_SIZE_LZO 1022
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 104
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1020
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="WinBtrfs.shellext" type="win32" />
<description>WinBtrfs shell extension</description>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" />
</dependentAssembly>
</dependency>
</assembly>

View file

@ -0,0 +1,251 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "afxres.h"
/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// English (U.K.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
#ifdef _WIN32
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK
#pragma code_page(1252)
#endif //_WIN32
#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//
1 TEXTINCLUDE
BEGIN
"resource.h\0"
END
2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Icon
//
// Icon with lowest ID value placed first to ensure application icon
// remains consistent on all systems.
IDI_ICON1 ICON "subvol.ico"
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x4L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "FileDescription", "WinBtrfs shell extension"
VALUE "FileVersion", "0.7"
VALUE "InternalName", "btrfs"
VALUE "LegalCopyright", "Copyright (c) Mark Harmstone 2016"
VALUE "OriginalFilename", "shellbtrfs.dll"
VALUE "ProductName", "WinBtrfs"
VALUE "ProductVersion", "0.7"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END
/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//
IDD_PROP_SHEET DIALOGEX 0, 0, 235, 245
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION
CAPTION "s"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
LTEXT "Subvolume:",IDC_STATIC,14,21,38,8
LTEXT "Inode:",IDC_STATIC,14,35,21,8
GROUPBOX "Information",IDC_GROUP_INFORMATION,7,7,221,71
LTEXT "Type:",IDC_STATIC,14,49,18,8
GROUPBOX "POSIX permissions",IDC_STATIC,7,82,221,102
LTEXT "User:",IDC_STATIC,14,97,17,8
LTEXT "Group:",IDC_STATIC,14,113,22,8
EDITTEXT IDC_UID,94,95,40,14,ES_AUTOHSCROLL | ES_NUMBER
EDITTEXT IDC_GID,94,111,40,14,ES_AUTOHSCROLL | ES_NUMBER
LTEXT "User",IDC_STATIC,14,144,15,8
LTEXT "Group",IDC_STATIC,14,156,20,8
LTEXT "Others",IDC_STATIC,14,168,22,8
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_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
CONTROL "",IDC_USERX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,147,16,10
CONTROL "",IDC_GROUPX,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,135,158,16,10
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_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
END
IDD_SIZE_DETAILS DIALOGEX 0, 0, 212, 85
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Size details"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
DEFPUSHBUTTON "OK",IDOK,81,64,50,14
LTEXT "Inline:",IDC_STATIC,7,7,21,8
LTEXT "Uncompressed:",IDC_STATIC,7,20,49,8
LTEXT "ZLIB:",IDC_STATIC,7,33,18,8
LTEXT "LZO:",IDC_STATIC,7,46,16,8
LTEXT "(blank)",IDC_SIZE_INLINE,63,7,142,8
LTEXT "(blank)",IDC_SIZE_UNCOMPRESSED,63,20,142,8
LTEXT "(blank)",IDC_SIZE_ZLIB,63,33,142,8
LTEXT "(blank)",IDC_SIZE_LZO,63,46,142,8
END
/////////////////////////////////////////////////////////////////////////////
//
// DESIGNINFO
//
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_PROP_SHEET, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 228
TOPMARGIN, 7
BOTTOMMARGIN, 238
END
IDD_SIZE_DETAILS, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 205
TOPMARGIN, 7
BOTTOMMARGIN, 78
END
END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// RT_MANIFEST
//
2 RT_MANIFEST "shellbtrfs.manifest"
/////////////////////////////////////////////////////////////////////////////
//
// String Table
//
STRINGTABLE
BEGIN
IDS_NEW_SUBVOL_HELP_TEXT "Creates a new Btrfs 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."
IDS_SNAPSHOT_FILENAME "Snapshot of %s (%04u-%02u-%02u)"
IDS_PROP_SHEET_TITLE "Btrfs properties"
IDS_INODE_FILE "File"
IDS_INODE_DIR "Directory"
IDS_INODE_CHAR "Character device (major %llu, minor %u)"
END
STRINGTABLE
BEGIN
IDS_INODE_BLOCK "Block device (major %llu, minor %u)"
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_SIZE_BYTE "%s byte"
IDS_SIZE_BYTES "%s bytes"
IDS_SIZE_KB "%1.1f KB"
IDS_SIZE_MB "%1.1f MB"
IDS_SIZE_GB "%1.1f GB"
IDS_SIZE_TB "%1.1f TB"
IDS_SIZE_PB "%1.1f PB"
IDS_SIZE_EB "%1.1f EB"
IDS_VARIOUS "(various)"
IDS_INODE_CHAR_SIMPLE "Character device"
END
STRINGTABLE
BEGIN
IDS_INODE_BLOCK_SIMPLE "Block device"
IDS_SIZE_LARGE "%s (%s)"
END
#endif // English (U.K.) resources
/////////////////////////////////////////////////////////////////////////////
#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View file

@ -0,0 +1,4 @@
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB