mirror of
https://github.com/reactos/reactos.git
synced 2024-07-02 18:54:25 +00:00
[BTRFS]
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:
parent
e9a079b458
commit
7f4d8362bf
|
@ -6,5 +6,6 @@ add_subdirectory(devcpux)
|
||||||
add_subdirectory(fontext)
|
add_subdirectory(fontext)
|
||||||
add_subdirectory(netshell)
|
add_subdirectory(netshell)
|
||||||
add_subdirectory(ntobjshex)
|
add_subdirectory(ntobjshex)
|
||||||
|
add_subdirectory(shellbtrfs)
|
||||||
add_subdirectory(slayer)
|
add_subdirectory(slayer)
|
||||||
add_subdirectory(stobject)
|
add_subdirectory(stobject)
|
23
reactos/dll/shellext/shellbtrfs/CMakeLists.txt
Normal file
23
reactos/dll/shellext/shellbtrfs/CMakeLists.txt
Normal 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)
|
473
reactos/dll/shellext/shellbtrfs/contextmenu.cpp
Normal file
473
reactos/dll/shellext/shellbtrfs/contextmenu.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
74
reactos/dll/shellext/shellbtrfs/contextmenu.h
Normal file
74
reactos/dll/shellext/shellbtrfs/contextmenu.h
Normal 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;
|
||||||
|
};
|
82
reactos/dll/shellext/shellbtrfs/factory.cpp
Normal file
82
reactos/dll/shellext/shellbtrfs/factory.cpp
Normal 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;
|
||||||
|
}
|
65
reactos/dll/shellext/shellbtrfs/factory.h
Normal file
65
reactos/dll/shellext/shellbtrfs/factory.h
Normal 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;
|
||||||
|
};
|
109
reactos/dll/shellext/shellbtrfs/iconoverlay.cpp
Normal file
109
reactos/dll/shellext/shellbtrfs/iconoverlay.cpp
Normal 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;
|
||||||
|
}
|
58
reactos/dll/shellext/shellbtrfs/iconoverlay.h
Normal file
58
reactos/dll/shellext/shellbtrfs/iconoverlay.h
Normal 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;
|
||||||
|
};
|
367
reactos/dll/shellext/shellbtrfs/main.cpp
Normal file
367
reactos/dll/shellext/shellbtrfs/main.cpp
Normal 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
|
1044
reactos/dll/shellext/shellbtrfs/propsheet.cpp
Executable file
1044
reactos/dll/shellext/shellbtrfs/propsheet.cpp
Executable file
File diff suppressed because it is too large
Load diff
167
reactos/dll/shellext/shellbtrfs/propsheet.h
Normal file
167
reactos/dll/shellext/shellbtrfs/propsheet.h
Normal 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;
|
||||||
|
};
|
69
reactos/dll/shellext/shellbtrfs/resource.h
Normal file
69
reactos/dll/shellext/shellbtrfs/resource.h
Normal 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
|
10
reactos/dll/shellext/shellbtrfs/shellbtrfs.manifest
Executable file
10
reactos/dll/shellext/shellbtrfs/shellbtrfs.manifest
Executable 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>
|
251
reactos/dll/shellext/shellbtrfs/shellbtrfs.rc
Normal file
251
reactos/dll/shellext/shellbtrfs/shellbtrfs.rc
Normal 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
|
||||||
|
|
4
reactos/dll/shellext/shellbtrfs/shellbtrfs.spec
Normal file
4
reactos/dll/shellext/shellbtrfs/shellbtrfs.spec
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
@ stdcall -private DllCanUnloadNow()
|
||||||
|
@ stdcall -private DllGetClassObject(ptr ptr ptr)
|
||||||
|
@ stdcall -private DllRegisterServer()
|
||||||
|
@ stdcall -private DllUnregisterServer()
|
BIN
reactos/dll/shellext/shellbtrfs/subvol.ico
Normal file
BIN
reactos/dll/shellext/shellbtrfs/subvol.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
Loading…
Reference in a new issue