Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/vfs windows thumbnails #4713

Merged
merged 1 commit into from
Jul 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions NEXTCLOUD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ if(WIN32)
# MSI Upgrade Code (without brackets)
set( WIN_MSI_UPGRADE_CODE "FD2FCCA9-BB8F-4485-8F70-A0621B84A7F4" )

# CfAPI Shell Extensions
set( CFAPI_SHELL_EXTENSIONS_LIB_NAME CfApiShellExtensions )

set( CFAPI_SHELLEXT_APPID_REG "{E314A650-DCA4-416E-974E-18EA37C213EA}")
set( CFAPI_SHELLEXT_APPID_DISPLAY_NAME "${APPLICATION_NAME} CfApi Shell Extensions" )

set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID "6FF9B5B6-389F-444A-9FDD-A286C36EA079" )
set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG "{${CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID}}" )
set( CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME "${APPLICATION_NAME} Thumbnail Handler" )

# Windows build options
option( BUILD_WIN_MSI "Build MSI scripts and helper DLL" OFF )
option( BUILD_WIN_TOOLS "Build Win32 migration tools" OFF )
Expand Down
3 changes: 2 additions & 1 deletion admin/win/msi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ endif()

set(MSI_INSTALLER_FILENAME "${APPLICATION_SHORTNAME}-${VERSION}${VERSION_SUFFIX}-${MSI_BUILD_ARCH}.msi")

configure_file(RegistryCleanup.vbs.in ${CMAKE_CURRENT_BINARY_DIR}/RegistryCleanup.vbs)
configure_file(OEM.wxi.in ${CMAKE_CURRENT_BINARY_DIR}/OEM.wxi)
configure_file(collect-transform.xsl.in ${CMAKE_CURRENT_BINARY_DIR}/collect-transform.xsl)
configure_file(make-msi.bat.in ${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat)
Expand All @@ -26,7 +27,7 @@ install(FILES
${CMAKE_CURRENT_BINARY_DIR}/make-msi.bat
Platform.wxi
Nextcloud.wxs
RegistryCleanup.vbs
${CMAKE_CURRENT_BINARY_DIR}/RegistryCleanup.vbs
RegistryCleanupCustomAction.wxs
gui/banner.bmp
gui/dialog.bmp
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
On Error goto 0

Const HKEY_LOCAL_MACHINE = &H80000002
Const HKEY_CURRENT_USER = &H80000001

Const strObjRegistry = "winmgmts:\\.\root\default:StdRegProv"

Expand Down Expand Up @@ -49,6 +50,25 @@ Function RegistryCleanupSyncRootManager()
End If
End Function

Function RegistryCleanupCfApiShellExtensions()
Set objRegistry = GetObject(strObjRegistry)

strShellExtThumbnailHandlerAppId = "Software\Classes\AppID\@CFAPI_SHELLEXT_APPID_REG@"
strShellExtThumbnailHandlerClsId = "Software\Classes\CLSID\@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG@"

rootKey = HKEY_CURRENT_USER

If objRegistry.EnumKey(rootKey, strShellExtThumbnailHandlerAppId, arrSubKeys) = 0 Then
RegistryDeleteKeyRecursive rootKey, strShellExtThumbnailHandlerAppId
End If

If objRegistry.EnumKey(rootKey, strShellExtThumbnailHandlerClsId, arrSubKeys) = 0 Then
RegistryDeleteKeyRecursive rootKey, strShellExtThumbnailHandlerClsId
End If

End Function

Function RegistryCleanup()
RegistryCleanupSyncRootManager()
RegistryCleanupCfApiShellExtensions()
End Function
9 changes: 9 additions & 0 deletions config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,13 @@

#cmakedefine BUILD_UPDATER "@BUILD_UPDATER@"

#cmakedefine CFAPI_SHELLEXT_APPID_REG "@CFAPI_SHELLEXT_APPID_REG@"
#cmakedefine CFAPI_SHELLEXT_APPID_DISPLAY_NAME "@CFAPI_SHELLEXT_APPID_DISPLAY_NAME@"

#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID@"
#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_CLASS_ID_REG@"
#cmakedefine CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME "@CFAPI_SHELLEXT_THUMBNAIL_HANDLER_DISPLAY_NAME@"

#cmakedefine CFAPI_SHELL_EXTENSIONS_LIB_NAME "@CFAPI_SHELL_EXTENSIONS_LIB_NAME@"

#endif
2 changes: 1 addition & 1 deletion src/common/filesystembase.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <QFileInfo>
#include <QLoggingCategory>

#include <ocsynclib.h>
#include <csync/ocsynclib.h>

class QFile;

Expand Down
36 changes: 36 additions & 0 deletions src/common/shellextensionutils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#include "shellextensionutils.h"
#include <QJsonDocument>
#include <QLoggingCategory>

namespace VfsShellExtensions {

Q_LOGGING_CATEGORY(lcShellExtensionUtils, "nextcloud.gui.shellextensionutils", QtInfoMsg)

QString VfsShellExtensions::serverNameForApplicationName(const QString &applicationName)
{
return applicationName + QStringLiteral(":VfsShellExtensionsServer");
}

QString VfsShellExtensions::serverNameForApplicationNameDefault()
{
return serverNameForApplicationName(APPLICATION_NAME);
}
namespace Protocol {
QByteArray createJsonMessage(const QVariantMap &message)
{
QVariantMap messageCopy = message;
messageCopy[QStringLiteral("version")] = Version;
return QJsonDocument::fromVariant((messageCopy)).toJson(QJsonDocument::Compact);
}

bool validateProtocolVersion(const QVariantMap &message)
{
const auto valid = message.value(QStringLiteral("version")) == Version;
if (!valid) {
qCWarning(lcShellExtensionUtils) << "Invalid shell extensions IPC protocol: " << message.value(QStringLiteral("version")) << " vs " << Version;
}
Q_ASSERT(valid);
return valid;
}
}
}
35 changes: 35 additions & 0 deletions src/common/shellextensionutils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright (C) by Oleksandr Zolotov <alex@nextcloud.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License
* for more details.
*/

#pragma once
#include "config.h"
#include <QByteArray>
#include <QString>
#include <QVariantMap>

namespace VfsShellExtensions {
QString serverNameForApplicationName(const QString &applicationName);
QString serverNameForApplicationNameDefault();

namespace Protocol {
static constexpr auto ThumbnailProviderRequestKey = "thumbnailProviderRequest";
static constexpr auto ThumbnailProviderRequestFilePathKey = "filePath";
static constexpr auto ThumbnailProviderRequestFileSizeKey = "fileSize";
static constexpr auto ThumnailProviderDataKey = "thumbnailData";
static constexpr auto Version = "1.0";

QByteArray createJsonMessage(const QVariantMap &message);
bool validateProtocolVersion(const QVariantMap &message);
}
}
3 changes: 2 additions & 1 deletion src/common/utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define UTILITY_H


#include "ocsynclib.h"
#include "csync/ocsynclib.h"
#include <QString>
#include <QByteArray>
#include <QDateTime>
Expand Down Expand Up @@ -254,6 +254,7 @@ namespace Utility {
OCSYNC_EXPORT bool registryDeleteKeyTree(HKEY hRootKey, const QString &subKey);
OCSYNC_EXPORT bool registryDeleteKeyValue(HKEY hRootKey, const QString &subKey, const QString &valueName);
OCSYNC_EXPORT bool registryWalkSubKeys(HKEY hRootKey, const QString &subKey, const std::function<void(HKEY, const QString &)> &callback);
OCSYNC_EXPORT bool registryWalkValues(HKEY hRootKey, const QString &subKey, const std::function<void(const QString &, bool *)> &callback);
OCSYNC_EXPORT QRect getTaskbarDimensions();

// Possibly refactor to share code with UnixTimevalToFileTime in c_time.c
Expand Down
49 changes: 48 additions & 1 deletion src/common/utility_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@
#include <winbase.h>
#include <windows.h>
#include <winerror.h>

#include <QCoreApplication>
#include <QDir>
#include <QFile>
#include <QLibrary>
#include <QSettings>

extern Q_CORE_EXPORT int qt_ntfs_permission_lookup;

Expand Down Expand Up @@ -354,6 +357,50 @@ bool Utility::registryWalkSubKeys(HKEY hRootKey, const QString &subKey, const st
return retCode != ERROR_NO_MORE_ITEMS;
}

bool Utility::registryWalkValues(HKEY hRootKey, const QString &subKey, const std::function<void(const QString &, bool *)> &callback)
{
HKEY hKey;
REGSAM sam = KEY_QUERY_VALUE;
LONG result = RegOpenKeyEx(hRootKey, reinterpret_cast<LPCWSTR>(subKey.utf16()), 0, sam, &hKey);
ASSERT(result == ERROR_SUCCESS);
if (result != ERROR_SUCCESS) {
return false;
}

DWORD maxValueNameSize = 0;
result = RegQueryInfoKey(hKey, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, &maxValueNameSize, nullptr, nullptr, nullptr);
ASSERT(result == ERROR_SUCCESS);
if (result != ERROR_SUCCESS) {
RegCloseKey(hKey);
return false;
}

QString valueName;
valueName.reserve(maxValueNameSize + 1);

DWORD retCode = ERROR_SUCCESS;
bool done = false;
for (DWORD i = 0; retCode == ERROR_SUCCESS; ++i) {
Q_ASSERT(unsigned(valueName.capacity()) > maxValueNameSize);
valueName.resize(valueName.capacity());
DWORD valueNameSize = valueName.size();
retCode = RegEnumValue(hKey, i, reinterpret_cast<LPWSTR>(valueName.data()), &valueNameSize, nullptr, nullptr, nullptr, nullptr);

ASSERT(result == ERROR_SUCCESS || retCode == ERROR_NO_MORE_ITEMS);
if (retCode == ERROR_SUCCESS) {
valueName.resize(valueNameSize);
callback(valueName, &done);

if (done) {
break;
}
}
}

RegCloseKey(hKey);
return retCode != ERROR_NO_MORE_ITEMS;
}

DWORD Utility::convertSizeToDWORD(size_t &convertVar)
{
if( convertVar > UINT_MAX ) {
Expand Down
3 changes: 3 additions & 0 deletions src/common/vfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ struct OCSYNC_EXPORT VfsSetupParams
// Folder alias
QString alias;

// Folder registry navigation Pane CLSID
QString navigationPaneClsid;

/** The path to the synced folder on the account
*
* Always ends with /.
Expand Down
2 changes: 1 addition & 1 deletion src/gui/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ IF( NOT WIN32 AND NOT APPLE )
set(client_SRCS ${client_SRCS} folderwatcher_linux.cpp)
ENDIF()
IF( WIN32 )
set(client_SRCS ${client_SRCS} folderwatcher_win.cpp)
set(client_SRCS ${client_SRCS} folderwatcher_win.cpp shellextensionsserver.cpp ${CMAKE_SOURCE_DIR}/src/common/shellextensionutils.cpp)
ENDIF()
IF( APPLE )
list(APPEND client_SRCS folderwatcher_mac.cpp)
Expand Down
4 changes: 4 additions & 0 deletions src/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "accountmanager.h"
#include "creds/abstractcredentials.h"
#include "pushnotifications.h"
#include "shellextensionsserver.h"

#if defined(BUILD_UPDATER)
#include "updater/ocupdater.h"
Expand Down Expand Up @@ -319,6 +320,9 @@ Application::Application(int &argc, char **argv)
qCInfo(lcApplication) << "VFS suffix plugin is available";

_folderManager.reset(new FolderMan);
#ifdef Q_OS_WIN
_shellExtensionsServer.reset(new ShellExtensionsServer);
#endif

connect(this, &SharedTools::QtSingleApplication::messageReceived, this, &Application::slotParseMessage);

Expand Down
4 changes: 4 additions & 0 deletions src/gui/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcApplication)

class Theme;
class Folder;
class ShellExtensionsServer;
class SslErrorDialog;

/**
Expand Down Expand Up @@ -144,6 +145,9 @@ protected slots:
QScopedPointer<CrashReporter::Handler> _crashHandler;
#endif
QScopedPointer<FolderMan> _folderManager;
#ifdef Q_OS_WIN
QScopedPointer<ShellExtensionsServer> _shellExtensionsServer;
#endif
};

} // namespace OCC
Expand Down
1 change: 1 addition & 0 deletions src/gui/folder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ void Folder::startVfs()
vfsParams.filesystemPath = path();
vfsParams.displayName = shortGuiRemotePathOrAppName();
vfsParams.alias = alias();
vfsParams.navigationPaneClsid = navigationPaneClsid().toString();
vfsParams.remotePath = remotePathTrailingSlash();
vfsParams.account = _accountState->account();
vfsParams.journal = &_journal;
Expand Down
2 changes: 2 additions & 0 deletions src/gui/folderman.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "syncfileitem.h"

class TestFolderMan;
class TestCfApiShellExtensionsIPC;

namespace OCC {

Expand Down Expand Up @@ -362,6 +363,7 @@ private slots:
explicit FolderMan(QObject *parent = nullptr);
friend class OCC::Application;
friend class ::TestFolderMan;
friend class ::TestCfApiShellExtensionsIPC;
};

} // namespace OCC
Expand Down
Loading