Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2015-01-23 20:02:55 +0300
committerOlivier Goffart <ogoffart@woboq.com>2015-01-23 20:02:55 +0300
commitfb79211514c11eb6ec8813dbb4201fce1f309716 (patch)
tree5cb9f8b83695d2945df77fc1361fd805fd01177f /shell_integration
parent502e7081cf959273e77ea1e6104f5290e922c2be (diff)
parent0af97156c974d6aba22bb8bcb8ba0d536d628d1c (diff)
Merge remote-tracking branch 'remotes/origin/win_context_menu'
Diffstat (limited to 'shell_integration')
-rw-r--r--shell_integration/windows/OCContextMenu/OCClientInterface.cpp80
-rw-r--r--shell_integration/windows/OCContextMenu/OCClientInterface.h50
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.cpp267
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.def6
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.h64
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj148
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj.filters65
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenuFactory.cpp91
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenuFactory.h43
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.cpp217
-rw-r--r--shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.h38
-rw-r--r--shell_integration/windows/OCContextMenu/ReadMe.txt40
-rw-r--r--shell_integration/windows/OCContextMenu/dllmain.cpp108
-rw-r--r--shell_integration/windows/OCContextMenu/stdafx.cpp8
-rw-r--r--shell_integration/windows/OCContextMenu/stdafx.h16
-rw-r--r--shell_integration/windows/OCContextMenu/targetver.h8
-rw-r--r--shell_integration/windows/OCShellExtensions.sln15
-rw-r--r--shell_integration/windows/OCUtil/CommunicationSocket.cpp13
-rw-r--r--shell_integration/windows/OCUtil/CommunicationSocket.h2
19 files changed, 1270 insertions, 9 deletions
diff --git a/shell_integration/windows/OCContextMenu/OCClientInterface.cpp b/shell_integration/windows/OCContextMenu/OCClientInterface.cpp
new file mode 100644
index 000000000..d2d9ae8e9
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCClientInterface.cpp
@@ -0,0 +1,80 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+
+
+#include "OCClientInterface.h"
+
+#include "CommunicationSocket.h"
+#include "StringUtil.h"
+
+#include <shlobj.h>
+
+#include <Strsafe.h>
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+#include <iterator>
+#include <unordered_set>
+#include <cassert>
+
+using namespace std;
+
+#define PIPE_TIMEOUT 5*1000 //ms
+#define SOCK_BUFFER 4096
+
+std::vector<std::wstring> OCClientInterface::WatchedDirectories()
+{
+ auto pipename = std::wstring(L"\\\\.\\pipe\\");
+ pipename += L"ownCloud";
+
+ CommunicationSocket socket;
+ if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
+ return std::vector<std::wstring>();
+ }
+ if (!socket.Connect(pipename)) {
+ return std::vector<std::wstring>();
+ }
+ std::vector<std::wstring> watchedDirectories;
+ std::wstring response;
+ Sleep(50);
+ while (socket.ReadLine(&response)) {
+ if (StringUtil::begins_with(response, wstring(L"REGISTER_PATH:"))) {
+ wstring responsePath = response.substr(14); // length of REGISTER_PATH
+ watchedDirectories.push_back(responsePath);
+ }
+ }
+ return watchedDirectories;
+}
+
+void OCClientInterface::ShareObject(const std::wstring &path)
+{
+ auto pipename = std::wstring(L"\\\\.\\pipe\\");
+ pipename += L"ownCloud";
+
+ CommunicationSocket socket;
+ if (!WaitNamedPipe(pipename.data(), PIPE_TIMEOUT)) {
+ return;
+ }
+ if (!socket.Connect(pipename)) {
+ return;
+ }
+
+ wchar_t msg[SOCK_BUFFER] = { 0 };
+ if (SUCCEEDED(StringCchPrintf(msg, SOCK_BUFFER, L"SHARE:%s\n", path.c_str())))
+ {
+ socket.SendMsg(msg);
+ }
+}
diff --git a/shell_integration/windows/OCContextMenu/OCClientInterface.h b/shell_integration/windows/OCContextMenu/OCClientInterface.h
new file mode 100644
index 000000000..7356d1e28
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCClientInterface.h
@@ -0,0 +1,50 @@
+/**
+* Copyright (c) 2015 ownCloud, Inc. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; version 2.1 of the License
+*
+* This library 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 License for more
+* details.
+*/
+
+/**
+* Copyright (c) 2014 ownCloud, Inc. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; version 2.1 of the License
+*
+* This library 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 License for more
+* details.
+*/
+
+#ifndef AbstractSocketHandler_H
+#define AbstractSocketHandler_H
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <queue>
+#include <thread>
+#include <mutex>
+#include <atomic>
+#include <condition_variable>
+
+class CommunicationSocket;
+
+class OCClientInterface
+{
+public:
+ static std::vector<std::wstring> WatchedDirectories();
+ static void ShareObject(const std::wstring &path);
+};
+
+#endif //ABSTRACTSOCKETHANDLER_H
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.cpp b/shell_integration/windows/OCContextMenu/OCContextMenu.cpp
new file mode 100644
index 000000000..4a612a9ca
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.cpp
@@ -0,0 +1,267 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+#include "stdafx.h"
+
+#include "OCContextMenu.h"
+#include "OCClientInterface.h"
+
+#include <shobjidl.h>
+#include <shlwapi.h>
+#include <shellapi.h>
+#include <StringUtil.h>
+
+extern HINSTANCE g_hInst;
+extern long g_cDllRef;
+
+#define IDM_SHARE 0
+
+
+
+OCContextMenu::OCContextMenu(void)
+ : m_cRef(1)
+ , m_pszMenuText(L"&Share")
+ , m_pszVerb("ocshare")
+ , m_pwszVerb(L"ocshare")
+ , m_pszVerbCanonicalName("OCShareViaOC")
+ , m_pwszVerbCanonicalName(L"OCShareViaOC")
+ , m_pszVerbHelpText("Share via ownCloud")
+ , m_pwszVerbHelpText(L"Share via ownCloud")
+{
+ InterlockedIncrement(&g_cDllRef);
+}
+
+OCContextMenu::~OCContextMenu(void)
+{
+ InterlockedDecrement(&g_cDllRef);
+}
+
+
+void OCContextMenu::OnVerbDisplayFileName(HWND hWnd)
+{
+ OCClientInterface::ShareObject(std::wstring(m_szSelectedFile));
+}
+
+
+#pragma region IUnknown
+
+// Query to the interface the component supported.
+IFACEMETHODIMP OCContextMenu::QueryInterface(REFIID riid, void **ppv)
+{
+ static const QITAB qit[] =
+ {
+ QITABENT(OCContextMenu, IContextMenu),
+ QITABENT(OCContextMenu, IShellExtInit),
+ { 0 },
+ };
+ return QISearch(this, qit, riid, ppv);
+}
+
+// Increase the reference count for an interface on an object.
+IFACEMETHODIMP_(ULONG) OCContextMenu::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+// Decrease the reference count for an interface on an object.
+IFACEMETHODIMP_(ULONG) OCContextMenu::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (0 == cRef) {
+ delete this;
+ }
+
+ return cRef;
+}
+
+#pragma endregion
+
+
+#pragma region IShellExtInit
+
+// Initialize the context menu handler.
+IFACEMETHODIMP OCContextMenu::Initialize(
+ LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
+{
+ if (!pDataObj) {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr = E_FAIL;
+
+ FORMATETC fe = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stm;
+
+ if (SUCCEEDED(pDataObj->GetData(&fe, &stm))) {
+ // Get an HDROP handle.
+ HDROP hDrop = static_cast<HDROP>(GlobalLock(stm.hGlobal));
+ if (hDrop) {
+ // Ignore multi-selections
+ UINT nFiles = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0);
+ if (nFiles == 1) {
+ // Get the path of the file.
+ if (0 != DragQueryFile(hDrop, 0, m_szSelectedFile, ARRAYSIZE(m_szSelectedFile)))
+ {
+ hr = S_OK;
+ }
+ }
+
+ GlobalUnlock(stm.hGlobal);
+ }
+
+ ReleaseStgMedium(&stm);
+ }
+
+ // If any value other than S_OK is returned from the method, the context
+ // menu item is not displayed.
+ return hr;
+}
+
+#pragma endregion
+
+
+#pragma region IContextMenu
+
+void InsertSeperator(HMENU hMenu, UINT indexMenu)
+{
+ // Add a separator.
+ MENUITEMINFO sep = { sizeof(sep) };
+ sep.fMask = MIIM_TYPE;
+ sep.fType = MFT_SEPARATOR;
+ InsertMenuItem(hMenu, indexMenu, TRUE, &sep);
+}
+
+IFACEMETHODIMP OCContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
+{
+ // If uFlags include CMF_DEFAULTONLY then we should not do anything.
+ if (CMF_DEFAULTONLY & uFlags)
+ {
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
+ }
+
+ bool skip = true;
+ for (const std::wstring path : OCClientInterface::WatchedDirectories()) {
+ if (StringUtil::begins_with(std::wstring(m_szSelectedFile), path)) {
+ skip = false;
+ break;
+ }
+ }
+
+ if (skip) {
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
+ }
+
+ InsertSeperator(hMenu, indexMenu);
+ indexMenu++;
+
+ MENUITEMINFO mii = { sizeof(mii) };
+ mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
+ mii.wID = idCmdFirst + IDM_SHARE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = m_pszMenuText;
+ mii.fState = MFS_ENABLED;
+ if (!InsertMenuItem(hMenu, indexMenu, TRUE, &mii))
+ {
+ return HRESULT_FROM_WIN32(GetLastError());
+ }
+
+ indexMenu++;
+ InsertSeperator(hMenu, indexMenu);
+
+
+ // Return an HRESULT value with the severity set to SEVERITY_SUCCESS.
+ // Set the code value to the offset of the largest command identifier
+ // that was assigned, plus one (1).
+ return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_SHARE + 1));
+}
+
+IFACEMETHODIMP OCContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
+{
+
+ // For the Unicode case, if the high-order word is not zero, the
+ // command's verb string is in lpcmi->lpVerbW.
+ if (HIWORD(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW))
+ {
+ // Is the verb supported by this context menu extension?
+ if (StrCmpIW(((CMINVOKECOMMANDINFOEX*)pici)->lpVerbW, m_pwszVerb) == 0)
+ {
+ OnVerbDisplayFileName(pici->hwnd);
+ }
+ else
+ {
+ // If the verb is not recognized by the context menu handler, it
+ // must return E_FAIL to allow it to be passed on to the other
+ // context menu handlers that might implement that verb.
+ return E_FAIL;
+ }
+ }
+
+ // If the command cannot be identified through the verb string, then
+ // check the identifier offset.
+ else
+ {
+ // Is the command identifier offset supported by this context menu
+ // extension?
+ if (LOWORD(pici->lpVerb) == IDM_SHARE)
+ {
+ OnVerbDisplayFileName(pici->hwnd);
+ }
+ else
+ {
+ // If the verb is not recognized by the context menu handler, it
+ // must return E_FAIL to allow it to be passed on to the other
+ // context menu handlers that might implement that verb.
+ return E_FAIL;
+ }
+ }
+
+ return S_OK;
+}
+
+IFACEMETHODIMP OCContextMenu::GetCommandString(UINT_PTR idCommand,
+ UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
+{
+ HRESULT hr = E_INVALIDARG;
+
+ if (idCommand == IDM_SHARE)
+ {
+ switch (uFlags)
+ {
+ case GCS_HELPTEXTW:
+ // Only useful for pre-Vista versions of Windows that have a
+ // Status bar.
+ hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
+ m_pwszVerbHelpText);
+ break;
+
+ case GCS_VERBW:
+ // GCS_VERBW is an optional feature that enables a caller to
+ // discover the canonical name for the verb passed in through
+ // idCommand.
+ hr = StringCchCopy(reinterpret_cast<PWSTR>(pszName), cchMax,
+ m_pwszVerbCanonicalName);
+ break;
+
+ default:
+ hr = S_OK;
+ }
+ }
+
+ // If the command (idCommand) is not supported by this context menu
+ // extension handler, return E_INVALIDARG.
+
+ return hr;
+}
+
+#pragma endregion \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.def b/shell_integration/windows/OCContextMenu/OCContextMenu.def
new file mode 100644
index 000000000..8cde2bd02
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.def
@@ -0,0 +1,6 @@
+LIBRARY
+EXPORTS
+ DllGetClassObject PRIVATE
+ DllCanUnloadNow PRIVATE
+ DllRegisterServer PRIVATE
+ DllUnregisterServer PRIVATE \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.h b/shell_integration/windows/OCContextMenu/OCContextMenu.h
new file mode 100644
index 000000000..dab468a14
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.h
@@ -0,0 +1,64 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+#ifndef OCCONTEXTMENU_H
+#define OCCONTEXTMENU_H
+
+#pragma once
+
+#include <windows.h>
+#include <shlobj.h> // For IShellExtInit and IContextMenu
+#include <memory>
+
+class OCContextMenu : public IShellExtInit, public IContextMenu
+{
+public:
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
+ IFACEMETHODIMP_(ULONG) AddRef();
+ IFACEMETHODIMP_(ULONG) Release();
+
+ // IShellExtInit
+ IFACEMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID);
+
+ // IContextMenu
+ IFACEMETHODIMP QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
+ IFACEMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
+ IFACEMETHODIMP GetCommandString(UINT_PTR idCommand, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax);
+
+ OCContextMenu();
+
+protected:
+ ~OCContextMenu();
+
+private:
+ // Reference count of component.
+ long m_cRef;
+
+ // The name of the selected file.
+ wchar_t m_szSelectedFile[MAX_PATH];
+
+ // The method that handles the "display" verb.
+ void OnVerbDisplayFileName(HWND hWnd);
+
+ PWSTR m_pszMenuText;
+ PCSTR m_pszVerb;
+ PCWSTR m_pwszVerb;
+ PCSTR m_pszVerbCanonicalName;
+ PCWSTR m_pwszVerbCanonicalName;
+ PCSTR m_pszVerbHelpText;
+ PCWSTR m_pwszVerbHelpText;
+};
+
+#endif //OCCONTEXTMENU_H
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj b/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj
new file mode 100644
index 000000000..d81b75638
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{FF34851F-1346-4809-A68A-B1188D7DFF32}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>OCContextMenu</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120_xp</PlatformToolset>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <PlatformToolset>v120</PlatformToolset>
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Label="Configuration" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <PlatformToolset>v120</PlatformToolset>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LinkIncremental>true</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LinkIncremental>false</LinkIncremental>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <OutDir>$(SolutionDir)$(Configuration)\$(Platform)\</OutDir>
+ <IntDir>$(Configuration)\$(Platform)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;OCCONTEXTMENU_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;OCCONTEXTMENU_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <SDLCheck>true</SDLCheck>
+ </ClCompile>
+ <Link>
+ <SubSystem>Windows</SubSystem>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <Link>
+ <AdditionalLibraryDirectories>..\$(Configuration)\$(Platform);</AdditionalLibraryDirectories>
+ <ModuleDefinitionFile>OCContextMenu.def</ModuleDefinitionFile>
+ <AdditionalDependencies>OCUtil_x64.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ </Link>
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\OCUtil</AdditionalIncludeDirectories>
+ <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <PrecompiledHeader />
+ </ClCompile>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="OCClientInterface.h" />
+ <ClInclude Include="OCContextMenuFactory.h" />
+ <ClInclude Include="OCContextMenuRegHandler.h" />
+ <ClInclude Include="OCContextMenu.h" />
+ <ClInclude Include="stdafx.h" />
+ <ClInclude Include="targetver.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="dllmain.cpp">
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ </PrecompiledHeader>
+ <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</CompileAsManaged>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ </PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="OCClientInterface.cpp" />
+ <ClCompile Include="OCContextMenu.cpp" />
+ <ClCompile Include="OCContextMenuRegHandler.cpp" />
+ <ClCompile Include="OCContextMenuFactory.cpp" />
+ <ClCompile Include="stdafx.cpp">
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="OCContextMenu.def" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj.filters b/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj.filters
new file mode 100644
index 000000000..227536ed1
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenu.vcxproj.filters
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <Text Include="ReadMe.txt" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="stdafx.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="targetver.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OCContextMenu.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OCContextMenuRegHandler.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OCContextMenuFactory.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="OCClientInterface.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="stdafx.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OCContextMenu.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OCContextMenuRegHandler.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OCContextMenuFactory.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="OCClientInterface.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="OCContextMenu.def">
+ <Filter>Source Files</Filter>
+ </None>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenuFactory.cpp b/shell_integration/windows/OCContextMenu/OCContextMenuFactory.cpp
new file mode 100644
index 000000000..07f61f852
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenuFactory.cpp
@@ -0,0 +1,91 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+#include "stdafx.h"
+
+#include "OCContextMenuFactory.h"
+#include "OCContextMenu.h"
+#include <new>
+#include <Shlwapi.h>
+#pragma comment(lib, "shlwapi.lib")
+
+
+extern long g_cDllRef;
+
+
+OCContextMenuFactory::OCContextMenuFactory() : m_cRef(1)
+{
+ InterlockedIncrement(&g_cDllRef);
+}
+
+OCContextMenuFactory::~OCContextMenuFactory()
+{
+ InterlockedDecrement(&g_cDllRef);
+}
+
+
+// IUnknown methods
+
+IFACEMETHODIMP OCContextMenuFactory::QueryInterface(REFIID riid, void **ppv)
+{
+ static const QITAB qit[] = { QITABENT(OCContextMenuFactory, IClassFactory), { 0 }, };
+ return QISearch(this, qit, riid, ppv);
+}
+
+IFACEMETHODIMP_(ULONG) OCContextMenuFactory::AddRef()
+{
+ return InterlockedIncrement(&m_cRef);
+}
+
+IFACEMETHODIMP_(ULONG) OCContextMenuFactory::Release()
+{
+ ULONG cRef = InterlockedDecrement(&m_cRef);
+ if (0 == cRef) {
+ delete this;
+ }
+ return cRef;
+}
+
+
+// IClassFactory methods
+
+IFACEMETHODIMP OCContextMenuFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv)
+{
+ HRESULT hr = CLASS_E_NOAGGREGATION;
+
+ // pUnkOuter is used for aggregation. We do not support it in the sample.
+ if (pUnkOuter == NULL) {
+ hr = E_OUTOFMEMORY;
+
+ // Create the COM component.
+ OCContextMenu *pExt = new (std::nothrow) OCContextMenu();
+ if (pExt) {
+ // Query the specified interface.
+ hr = pExt->QueryInterface(riid, ppv);
+ pExt->Release();
+ }
+ }
+
+ return hr;
+}
+
+IFACEMETHODIMP OCContextMenuFactory::LockServer(BOOL fLock)
+{
+ if (fLock) {
+ InterlockedIncrement(&g_cDllRef);
+ } else {
+ InterlockedDecrement(&g_cDllRef);
+ }
+ return S_OK;
+} \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenuFactory.h b/shell_integration/windows/OCContextMenu/OCContextMenuFactory.h
new file mode 100644
index 000000000..44840fe4c
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenuFactory.h
@@ -0,0 +1,43 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+
+#ifndef OCCONTEXTMENUFACTORY_H
+#define OCCONTEXTMENUFACTORY_H
+
+#pragma once
+
+#include <unknwn.h> // For IClassFactory
+#include <minwindef.h>
+
+class OCContextMenuFactory : public IClassFactory
+{
+public:
+ // IUnknown
+ IFACEMETHODIMP QueryInterface(REFIID riid, void **ppv);
+ IFACEMETHODIMP_(ULONG) AddRef();
+ IFACEMETHODIMP_(ULONG) Release();
+
+ // IClassFactory
+ IFACEMETHODIMP CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppv);
+ IFACEMETHODIMP LockServer(BOOL fLock);
+
+ OCContextMenuFactory();
+
+private:
+ ~OCContextMenuFactory();
+ long m_cRef;
+};
+
+#endif //OCCONTEXTMENUFACTORY_H \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.cpp b/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.cpp
new file mode 100644
index 000000000..20af1245e
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.cpp
@@ -0,0 +1,217 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+#include "stdafx.h"
+
+#include "OCContextMenuRegHandler.h"
+#include <strsafe.h>
+#include <objbase.h>
+
+namespace {
+
+HRESULT SetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PCWSTR pszData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Creates the specified registry key. If the key already exists, the
+ // function opens it.
+ hr = HRESULT_FROM_WIN32(RegCreateKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
+ NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, NULL));
+
+ if (SUCCEEDED(hr))
+ {
+ if (pszData != NULL)
+ {
+ // Set the specified value of the key.
+ DWORD cbData = lstrlen(pszData) * sizeof(*pszData);
+ hr = HRESULT_FROM_WIN32(RegSetValueEx(hKey, pszValueName, 0,
+ REG_SZ, reinterpret_cast<const BYTE *>(pszData), cbData));
+ }
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+HRESULT GetHKCRRegistryKeyAndValue(PCWSTR pszSubKey, PCWSTR pszValueName, PWSTR pszData, DWORD cbData)
+{
+ HRESULT hr;
+ HKEY hKey = NULL;
+
+ // Try to open the specified registry key.
+ hr = HRESULT_FROM_WIN32(RegOpenKeyEx(HKEY_CLASSES_ROOT, pszSubKey, 0,
+ KEY_READ, &hKey));
+
+ if (SUCCEEDED(hr))
+ {
+ // Get the data for the specified value name.
+ hr = HRESULT_FROM_WIN32(RegQueryValueEx(hKey, pszValueName, NULL,
+ NULL, reinterpret_cast<LPBYTE>(pszData), &cbData));
+
+ RegCloseKey(hKey);
+ }
+
+ return hr;
+}
+
+}
+
+HRESULT OCContextMenuRegHandler::RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel)
+{
+ if (pszModule == NULL || pszThreadModel == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Create the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszFriendlyName);
+
+ // Create the HKCR\CLSID\{<CLSID>}\InprocServer32 key.
+ if (SUCCEEDED(hr))
+ {
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ L"CLSID\\%s\\InprocServer32", szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the InprocServer32 key to the
+ // path of the COM module.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, pszModule);
+ if (SUCCEEDED(hr))
+ {
+ // Set the threading model of the component.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey,
+ L"ThreadingModel", pszThreadModel);
+ }
+ }
+ }
+ }
+
+ return hr;
+}
+
+HRESULT OCContextMenuRegHandler::UnregisterInprocServer(const CLSID& clsid)
+{
+ HRESULT hr = S_OK;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // Delete the HKCR\CLSID\{<CLSID>} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey), L"CLSID\\%s", szCLSID);
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, szSubkey));
+ }
+
+ return hr;
+}
+
+
+HRESULT OCContextMenuRegHandler::RegisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szCLSID[MAX_PATH];
+ StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID));
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Create the key HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName>}
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
+ if (SUCCEEDED(hr))
+ {
+ // Set the default value of the key.
+ hr = SetHKCRRegistryKeyAndValue(szSubkey, NULL, szCLSID);
+ }
+
+ return hr;
+}
+
+HRESULT OCContextMenuRegHandler::UnregisterShellExtContextMenuHandler(
+ PCWSTR pszFileType, PCWSTR pszFriendlyName)
+{
+ if (pszFileType == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ HRESULT hr;
+
+ wchar_t szSubkey[MAX_PATH];
+
+ // If pszFileType starts with '.', try to read the default value of the
+ // HKCR\<File Type> key which contains the ProgID to which the file type
+ // is linked.
+ if (*pszFileType == L'.')
+ {
+ wchar_t szDefaultVal[260];
+ hr = GetHKCRRegistryKeyAndValue(pszFileType, NULL, szDefaultVal,
+ sizeof(szDefaultVal));
+
+ // If the key exists and its default value is not empty, use the
+ // ProgID as the file type.
+ if (SUCCEEDED(hr) && szDefaultVal[0] != L'\0')
+ {
+ pszFileType = szDefaultVal;
+ }
+ }
+
+ // Remove the HKCR\<File Type>\shellex\ContextMenuHandlers\{friendlyName} key.
+ hr = StringCchPrintf(szSubkey, ARRAYSIZE(szSubkey),
+ L"%s\\shellex\\ContextMenuHandlers\\%s", pszFileType, pszFriendlyName);
+ if (SUCCEEDED(hr))
+ {
+ hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, szSubkey));
+ }
+
+ return hr;
+} \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.h b/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.h
new file mode 100644
index 000000000..b73db2fa4
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/OCContextMenuRegHandler.h
@@ -0,0 +1,38 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+
+#ifndef OCCONTEXTMENUREGHANDLER_H
+#define OCCONTEXTMENUREGHANDLER_H
+
+#pragma once
+
+#include "stdafx.h"
+
+class __declspec(dllexport) OCContextMenuRegHandler
+{
+public:
+ static HRESULT MakeRegistryEntries(const CLSID& clsid, PCWSTR fileType);
+ static HRESULT RegisterCOMObject(PCWSTR modulePath, PCWSTR friendlyName, const CLSID& clsid);
+ static HRESULT RemoveRegistryEntries(PCWSTR friendlyName);
+ static HRESULT UnregisterCOMObject(const CLSID& clsid);
+
+ static HRESULT RegisterInprocServer(PCWSTR pszModule, const CLSID& clsid, PCWSTR pszFriendlyName, PCWSTR pszThreadModel);
+ static HRESULT UnregisterInprocServer(const CLSID& clsid);
+
+ static HRESULT RegisterShellExtContextMenuHandler(PCWSTR pszFileType, const CLSID& clsid, PCWSTR pszFriendlyName);
+ static HRESULT UnregisterShellExtContextMenuHandler(PCWSTR pszFileType, PCWSTR pszFriendlyName);
+};
+
+#endif //OCCONTEXTMENUREGHANDLER_H \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/ReadMe.txt b/shell_integration/windows/OCContextMenu/ReadMe.txt
new file mode 100644
index 000000000..9b4563b70
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/ReadMe.txt
@@ -0,0 +1,40 @@
+========================================================================
+ DYNAMIC LINK LIBRARY : OCContextMenu Project Overview
+========================================================================
+
+AppWizard has created this OCContextMenu DLL for you.
+
+This file contains a summary of what you will find in each of the files that
+make up your OCContextMenu application.
+
+
+OCContextMenu.vcxproj
+ This is the main project file for VC++ projects generated using an Application Wizard.
+ It contains information about the version of Visual C++ that generated the file, and
+ information about the platforms, configurations, and project features selected with the
+ Application Wizard.
+
+OCContextMenu.vcxproj.filters
+ This is the filters file for VC++ projects generated using an Application Wizard.
+ It contains information about the association between the files in your project
+ and the filters. This association is used in the IDE to show grouping of files with
+ similar extensions under a specific node (for e.g. ".cpp" files are associated with the
+ "Source Files" filter).
+
+OCContextMenu.cpp
+ This is the main DLL source file.
+
+/////////////////////////////////////////////////////////////////////////////
+Other standard files:
+
+StdAfx.h, StdAfx.cpp
+ These files are used to build a precompiled header (PCH) file
+ named OCContextMenu.pch and a precompiled types file named StdAfx.obj.
+
+/////////////////////////////////////////////////////////////////////////////
+Other notes:
+
+AppWizard uses "TODO:" comments to indicate parts of the source code you
+should add to or customize.
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/shell_integration/windows/OCContextMenu/dllmain.cpp b/shell_integration/windows/OCContextMenu/dllmain.cpp
new file mode 100644
index 000000000..088dea767
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/dllmain.cpp
@@ -0,0 +1,108 @@
+/**
+* Copyright (c) 2015 Daniel Molkentin <danimo@owncloud.com>. All rights reserved.
+*
+* This library is free software; you can redistribute it and/or modify it under
+* the terms of the GNU Lesser General Public License as published by the Free
+* Software Foundation; either version 2.1 of the License, or (at your option)
+* any later version.
+*
+* This library 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 License for more
+* details.
+*/
+
+#include "stdafx.h"
+
+#include <windows.h>
+#include <Guiddef.h>
+#include "OCContextMenuRegHandler.h"
+#include "OCContextMenuFactory.h"
+
+// {841A0AAD-AA11-4B50-84D9-7F8E727D77D7}
+static const GUID CLSID_FileContextMenuExt = { 0x841a0aad, 0xaa11, 0x4b50, { 0x84, 0xd9, 0x7f, 0x8e, 0x72, 0x7d, 0x77, 0xd7 } };
+
+HINSTANCE g_hInst = NULL;
+long g_cDllRef = 0;
+
+BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
+{
+ switch (dwReason)
+ {
+ case DLL_PROCESS_ATTACH:
+ // Hold the instance of this DLL module, we will use it to get the
+ // path of the DLL to register the component.
+ g_hInst = hModule;
+ DisableThreadLibraryCalls(hModule);
+ break;
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+ case DLL_PROCESS_DETACH:
+ break;
+ }
+ return TRUE;
+}
+
+STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
+{
+ HRESULT hr = CLASS_E_CLASSNOTAVAILABLE;
+
+ if (IsEqualCLSID(CLSID_FileContextMenuExt, rclsid)) {
+ hr = E_OUTOFMEMORY;
+
+ OCContextMenuFactory *pClassFactory = new OCContextMenuFactory();
+ if (pClassFactory) {
+ hr = pClassFactory->QueryInterface(riid, ppv);
+ pClassFactory->Release();
+ }
+ }
+
+ return hr;
+}
+
+STDAPI DllCanUnloadNow(void)
+{
+ return g_cDllRef > 0 ? S_FALSE : S_OK;
+}
+
+STDAPI DllRegisterServer(void)
+{
+ HRESULT hr;
+
+ wchar_t szModule[MAX_PATH];
+ if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+
+ // Register the component.
+ hr = OCContextMenuRegHandler::RegisterInprocServer(szModule, CLSID_FileContextMenuExt,
+ L"OCContextMenuHandler Class", L"Apartment");
+ if (SUCCEEDED(hr)) {
+ // Register the context menu handler. The context menu handler is
+ // associated with the .cpp file class.
+ hr = OCContextMenuRegHandler::RegisterShellExtContextMenuHandler(L"AllFileSystemObjects", CLSID_FileContextMenuExt, L"OCContextMenuHandler");
+ }
+
+ return hr;
+}
+
+STDAPI DllUnregisterServer(void)
+{
+ HRESULT hr = S_OK;
+
+ wchar_t szModule[MAX_PATH];
+ if (GetModuleFileName(g_hInst, szModule, ARRAYSIZE(szModule)) == 0) {
+ hr = HRESULT_FROM_WIN32(GetLastError());
+ return hr;
+ }
+
+ // Unregister the component.
+ hr = OCContextMenuRegHandler::UnregisterInprocServer(CLSID_FileContextMenuExt);
+ if (SUCCEEDED(hr)) {
+ // Unregister the context menu handler.
+ hr = OCContextMenuRegHandler::UnregisterShellExtContextMenuHandler(L"AllFileSystemObjects", L"OCContextMenuHandler");
+ }
+
+ return hr;
+} \ No newline at end of file
diff --git a/shell_integration/windows/OCContextMenu/stdafx.cpp b/shell_integration/windows/OCContextMenu/stdafx.cpp
new file mode 100644
index 000000000..2a649474d
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/stdafx.cpp
@@ -0,0 +1,8 @@
+// stdafx.cpp : source file that includes just the standard includes
+// OCContextMenu.pch will be the pre-compiled header
+// stdafx.obj will contain the pre-compiled type information
+
+#include "stdafx.h"
+
+// TODO: reference any additional headers you need in STDAFX.H
+// and not in this file
diff --git a/shell_integration/windows/OCContextMenu/stdafx.h b/shell_integration/windows/OCContextMenu/stdafx.h
new file mode 100644
index 000000000..87d219020
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/stdafx.h
@@ -0,0 +1,16 @@
+// stdafx.h : include file for standard system include files,
+// or project specific include files that are used frequently, but
+// are changed infrequently
+//
+
+#pragma once
+
+#include "targetver.h"
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+#include <strsafe.h>
+
+
+// TODO: reference additional headers your program requires here
diff --git a/shell_integration/windows/OCContextMenu/targetver.h b/shell_integration/windows/OCContextMenu/targetver.h
new file mode 100644
index 000000000..87c0086de
--- /dev/null
+++ b/shell_integration/windows/OCContextMenu/targetver.h
@@ -0,0 +1,8 @@
+#pragma once
+
+// Including SDKDDKVer.h defines the highest available Windows platform.
+
+// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
+// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
+
+#include <SDKDDKVer.h>
diff --git a/shell_integration/windows/OCShellExtensions.sln b/shell_integration/windows/OCShellExtensions.sln
index 1bfbbf3ed..4b1395433 100644
--- a/shell_integration/windows/OCShellExtensions.sln
+++ b/shell_integration/windows/OCShellExtensions.sln
@@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013
-VisualStudioVersion = 12.0.30501.0
+VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCOverlays", "OCOverlays\OCOverlays.vcxproj", "{42EFEC79-5ACA-4F76-955F-15CE4340F6BC}"
ProjectSection(ProjectDependencies) = postProject
@@ -10,6 +10,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCOverlays", "OCOverlays\OC
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCUtil", "OCUtil\OCUtil.vcxproj", "{E4F63E19-808D-4234-8DF0-69C5F47C9CD3}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OCContextMenu", "OCContextMenu\OCContextMenu.vcxproj", "{FF34851F-1346-4809-A68A-B1188D7DFF32}"
+ ProjectSection(ProjectDependencies) = postProject
+ {E4F63E19-808D-4234-8DF0-69C5F47C9CD3} = {E4F63E19-808D-4234-8DF0-69C5F47C9CD3}
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@@ -34,6 +39,14 @@ Global
{E4F63E19-808D-4234-8DF0-69C5F47C9CD3}.Release|Win32.Build.0 = Release|Win32
{E4F63E19-808D-4234-8DF0-69C5F47C9CD3}.Release|x64.ActiveCfg = Release|x64
{E4F63E19-808D-4234-8DF0-69C5F47C9CD3}.Release|x64.Build.0 = Release|x64
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Debug|Win32.ActiveCfg = Debug|Win32
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Debug|Win32.Build.0 = Debug|Win32
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Debug|x64.ActiveCfg = Debug|x64
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Debug|x64.Build.0 = Debug|x64
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Release|Win32.ActiveCfg = Release|Win32
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Release|Win32.Build.0 = Release|Win32
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Release|x64.ActiveCfg = Release|x64
+ {FF34851F-1346-4809-A68A-B1188D7DFF32}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/shell_integration/windows/OCUtil/CommunicationSocket.cpp b/shell_integration/windows/OCUtil/CommunicationSocket.cpp
index dec2970f6..5403e4869 100644
--- a/shell_integration/windows/OCUtil/CommunicationSocket.cpp
+++ b/shell_integration/windows/OCUtil/CommunicationSocket.cpp
@@ -60,10 +60,11 @@ bool CommunicationSocket::Connect(const std::wstring &pipename)
if (_pipe == INVALID_HANDLE_VALUE) {
return false;
}
+
return true;
}
-bool CommunicationSocket::SendMsg(const wchar_t* message)
+bool CommunicationSocket::SendMsg(const wchar_t* message) const
{
auto utf8_msg = StringUtil::toUtf8(message);
@@ -73,7 +74,7 @@ bool CommunicationSocket::SendMsg(const wchar_t* message)
if (result) {
return true;
} else {
- Close();
+ const_cast<CommunicationSocket*>(this)->Close();
return false;
}
@@ -91,7 +92,6 @@ bool CommunicationSocket::ReadLine(wstring* response)
return false;
}
-
while (true) {
int lbPos = 0;
auto it = std::find(_buffer.begin() + lbPos, _buffer.end(), '\n');
@@ -104,8 +104,8 @@ bool CommunicationSocket::ReadLine(wstring* response)
std::array<char, 128> resp_utf8;
DWORD numBytesRead = 0;
DWORD totalBytesAvailable = 0;
- auto result = PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0);
- if (!result) {
+
+ if (!PeekNamedPipe(_pipe, NULL, 0, 0, &totalBytesAvailable, 0)) {
Close();
return false;
}
@@ -113,8 +113,7 @@ bool CommunicationSocket::ReadLine(wstring* response)
return false;
}
- result = ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL);
- if (!result) {
+ if (!ReadFile(_pipe, resp_utf8.data(), DWORD(resp_utf8.size()), &numBytesRead, NULL)) {
Close();
return false;
}
diff --git a/shell_integration/windows/OCUtil/CommunicationSocket.h b/shell_integration/windows/OCUtil/CommunicationSocket.h
index d29d86333..312f47006 100644
--- a/shell_integration/windows/OCUtil/CommunicationSocket.h
+++ b/shell_integration/windows/OCUtil/CommunicationSocket.h
@@ -32,7 +32,7 @@ public:
bool Connect(const std::wstring& pipename);
bool Close();
- bool SendMsg(const wchar_t*);
+ bool SendMsg(const wchar_t*) const;
bool ReadLine(std::wstring*);
HANDLE Event() { return _pipe; }