From 587c320f61e9aea6292dc3f5dcb83288a2acc47f Mon Sep 17 00:00:00 2001 From: jerry Date: Wed, 21 Aug 2013 13:30:46 +0000 Subject: [PATCH] - Added data handler shell extension project (synwinxt) which will output a dll file. - Removed misused comments in CServerProxy --- src/lib/CMakeLists.txt | 1 + src/lib/arch/CArchMiscWindows.cpp | 6 +- src/lib/client/CServerProxy.h | 5 - src/lib/synwinxt/CClassFactory.cpp | 87 ++++++++ src/lib/synwinxt/CClassFactory.h | 39 ++++ src/lib/synwinxt/CDataHandlerExtension.cpp | 77 +++++++ src/lib/synwinxt/CDataHandlerExtension.h | 57 +++++ src/lib/synwinxt/CMakeLists.txt | 54 +++++ src/lib/synwinxt/Main.cpp | 239 +++++++++++++++++++++ src/lib/synwinxt/synwinxt.def | 6 + 10 files changed, 562 insertions(+), 9 deletions(-) create mode 100644 src/lib/synwinxt/CClassFactory.cpp create mode 100644 src/lib/synwinxt/CClassFactory.h create mode 100644 src/lib/synwinxt/CDataHandlerExtension.cpp create mode 100644 src/lib/synwinxt/CDataHandlerExtension.h create mode 100644 src/lib/synwinxt/CMakeLists.txt create mode 100644 src/lib/synwinxt/Main.cpp create mode 100644 src/lib/synwinxt/synwinxt.def diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index c8bc7d87..86282414 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -28,4 +28,5 @@ add_subdirectory(synergy) if (WIN32) add_subdirectory(synwinhk) + add_subdirectory(synwinxt) endif() diff --git a/src/lib/arch/CArchMiscWindows.cpp b/src/lib/arch/CArchMiscWindows.cpp index 4f63c27e..3e61d75b 100644 --- a/src/lib/arch/CArchMiscWindows.cpp +++ b/src/lib/arch/CArchMiscWindows.cpp @@ -273,8 +273,7 @@ CArchMiscWindows::setValue(HKEY key, const TCHAR* name, const std::string& value) { assert(key != NULL); - assert(name != NULL); - if(key ==NULL || name==NULL) return; // TODO: throw exception + if(key ==NULL) return; // TODO: throw exception RegSetValueEx(key, name, 0, REG_SZ, reinterpret_cast(value.c_str()), (DWORD)value.size() + 1); @@ -284,8 +283,7 @@ void CArchMiscWindows::setValue(HKEY key, const TCHAR* name, DWORD value) { assert(key != NULL); - assert(name != NULL); - if(key ==NULL || name==NULL) return; // TODO: throw exception + if(key ==NULL) return; // TODO: throw exception RegSetValueEx(key, name, 0, REG_DWORD, reinterpret_cast(&value), sizeof(DWORD)); diff --git a/src/lib/client/CServerProxy.h b/src/lib/client/CServerProxy.h index 2bd6a527..b8976c59 100644 --- a/src/lib/client/CServerProxy.h +++ b/src/lib/client/CServerProxy.h @@ -54,14 +54,9 @@ public: //@} - //! @file transfer - //@{ - //! sending file chunk to server void fileChunkSending(UInt8 mark, char* data, size_t dataSize); - //@} - #ifdef TEST_ENV void handleDataForTest() { handleData(CEvent(), NULL); } #endif diff --git a/src/lib/synwinxt/CClassFactory.cpp b/src/lib/synwinxt/CClassFactory.cpp new file mode 100644 index 00000000..da50296b --- /dev/null +++ b/src/lib/synwinxt/CClassFactory.cpp @@ -0,0 +1,87 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CClassFactory.h" +#include "CDataHandlerExtension.h" +#include + +extern LONG g_refCount; + +CClassFactory::CClassFactory() +{ + InterlockedIncrement(&g_refCount); +} + +CClassFactory::~CClassFactory() +{ + InterlockedDecrement(&g_refCount); +} + +HRESULT STDMETHODCALLTYPE +CClassFactory::QueryInterface(REFIID riid, void **ppvObject) +{ + static const QITAB qit[] = + { + QITABENT(CClassFactory, IClassFactory), + { 0 }, + }; + return QISearch(this, qit, riid, ppvObject); +} + +ULONG STDMETHODCALLTYPE +CClassFactory::AddRef() +{ + return InterlockedIncrement(&m_refCount); +} + +ULONG STDMETHODCALLTYPE +CClassFactory::Release() +{ + LONG count = InterlockedDecrement(&m_refCount); + if (count == 0) { + delete this; + } + return count; +} + +HRESULT STDMETHODCALLTYPE +CClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) +{ + if (pUnkOuter != NULL) { + return CLASS_E_NOAGGREGATION; + } + + CDataHandlerExtension* pExtension = new CDataHandlerExtension(); + HRESULT hr = pExtension->QueryInterface(riid, ppvObject); + if (FAILED(hr)) { + delete pExtension; + } + + return hr; +} + +HRESULT STDMETHODCALLTYPE +CClassFactory::LockServer(BOOL fLock) +{ + if (fLock) { + InterlockedIncrement(&g_refCount); + } + else { + InterlockedDecrement(&g_refCount); + } + return S_OK; +} diff --git a/src/lib/synwinxt/CClassFactory.h b/src/lib/synwinxt/CClassFactory.h new file mode 100644 index 00000000..4f33cd3a --- /dev/null +++ b/src/lib/synwinxt/CClassFactory.h @@ -0,0 +1,39 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +class CClassFactory : public ::IClassFactory +{ +public: + CClassFactory(); + ~CClassFactory(); + + // IUnknown overrides + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IClassFactory overrides + HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject); + HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock); + +private: + LONG m_refCount; +}; diff --git a/src/lib/synwinxt/CDataHandlerExtension.cpp b/src/lib/synwinxt/CDataHandlerExtension.cpp new file mode 100644 index 00000000..c338939a --- /dev/null +++ b/src/lib/synwinxt/CDataHandlerExtension.cpp @@ -0,0 +1,77 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CDataHandlerExtension.h" +#include +#include + +extern LONG g_refCount; +extern GUID g_CLSID; +extern void outputDebugStringF(const char *str, ...); + +CDataHandlerExtension::CDataHandlerExtension() +{ + InterlockedIncrement(&g_refCount); +} + +CDataHandlerExtension::~CDataHandlerExtension() +{ + InterlockedDecrement(&g_refCount); +} + +HRESULT STDMETHODCALLTYPE +CDataHandlerExtension::QueryInterface(REFIID riid, void **ppvObject) +{ + static const QITAB qit[] = + { + QITABENT(CDataHandlerExtension, IPersistFile), + QITABENT(CDataHandlerExtension, IDataObject), + { 0 }, + }; + return QISearch(this, qit, riid, ppvObject); +} + +ULONG STDMETHODCALLTYPE +CDataHandlerExtension::AddRef() +{ + return InterlockedIncrement(&m_refCount); +} + +ULONG STDMETHODCALLTYPE +CDataHandlerExtension::Release() +{ + LONG count = InterlockedDecrement(&m_refCount); + if (count == 0) { + delete this; + } + return count; +} + +HRESULT STDMETHODCALLTYPE +CDataHandlerExtension::Load(__RPC__in LPCOLESTR pszFileName, DWORD dwMode) +{ + StringCchCopyW(m_selectedFileName, ARRAYSIZE(m_selectedFileName), pszFileName); + outputDebugStringF("DataHandlerDemo: CDataHandlerExtension::Load: m_selectedFileName=%ls", m_selectedFileName); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE +CDataHandlerExtension::GetClassID(__RPC__out CLSID *pClassID) +{ + *pClassID = g_CLSID; + return S_OK; +} diff --git a/src/lib/synwinxt/CDataHandlerExtension.h b/src/lib/synwinxt/CDataHandlerExtension.h new file mode 100644 index 00000000..2ecd4a27 --- /dev/null +++ b/src/lib/synwinxt/CDataHandlerExtension.h @@ -0,0 +1,57 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +class CDataHandlerExtension : public IDataObject, public IPersistFile +{ +public: + CDataHandlerExtension(); + ~CDataHandlerExtension(); + + // IUnknown overrides + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); + + // IDataObject overrides + HRESULT STDMETHODCALLTYPE GetData(FORMATETC *pformatetcIn, STGMEDIUM *pmedium) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetDataHere(FORMATETC *pformatetc, STGMEDIUM *pmedium) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE QueryGetData(__RPC__in_opt FORMATETC *pformatetc) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetCanonicalFormatEtc(__RPC__in_opt FORMATETC *pformatectIn, __RPC__out FORMATETC *pformatetcOut) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE SetData(FORMATETC *pformatetc, STGMEDIUM *pmedium, BOOL fRelease) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE EnumFormatEtc(DWORD dwDirection, __RPC__deref_out_opt IEnumFORMATETC **ppenumFormatEtc) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE DAdvise(__RPC__in FORMATETC *pformatetc, DWORD advf, __RPC__in_opt IAdviseSink *pAdvSink, __RPC__out DWORD *pdwConnection) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE DUnadvise(DWORD dwConnection) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE EnumDAdvise(__RPC__deref_out_opt IEnumSTATDATA **ppenumAdvise) { return E_NOTIMPL; } + + // IPersistFile overrides + HRESULT STDMETHODCALLTYPE IsDirty() { return E_NOTIMPL; }; + HRESULT STDMETHODCALLTYPE Load(__RPC__in LPCOLESTR pszFileName, DWORD dwMode); + HRESULT STDMETHODCALLTYPE Save(__RPC__in_opt LPCOLESTR pszFileName, BOOL fRemember) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE SaveCompleted(__RPC__in_opt LPCOLESTR pszFileName) { return E_NOTIMPL; } + HRESULT STDMETHODCALLTYPE GetCurFile(__RPC__deref_out_opt LPOLESTR *ppszFileName) { return E_NOTIMPL; } + + // IPersist overrides + HRESULT STDMETHODCALLTYPE GetClassID(__RPC__out CLSID *pClassID); + +private: + LONG m_refCount; + WCHAR m_selectedFileName[MAX_PATH]; +}; diff --git a/src/lib/synwinxt/CMakeLists.txt b/src/lib/synwinxt/CMakeLists.txt new file mode 100644 index 00000000..ea87f68d --- /dev/null +++ b/src/lib/synwinxt/CMakeLists.txt @@ -0,0 +1,54 @@ +# synergy -- mouse and keyboard sharing utility +# Copyright (C) 2013 Bolton Software Ltd. +# +# This package is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# found in the file COPYING that should have accompanied this file. +# +# This package 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. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(inc + CClassFactory.h + CDataHandlerExtension.h +) + +set(src + CClassFactory.cpp + CDataHandlerExtension.cpp + synwinxt.def + Main.cpp +) + +list(APPEND src + ${inc} +) + +set(inc + ../arch + ../base + ../common +) + +include_directories(${inc}) +add_library(synwinxt SHARED ${inc} ${src}) +target_link_libraries(synwinxt + arch base common ${libs}) + +# copy the dlls (and supporting files) from the lib dir to +# the bin dir, so that synergyc and synergys can easily find them. +# we should leave the other libraries compiling to the lib dir, +# so that the bin dir remains tidy. the path is relative to the +# build dir (in this case, that's: build\src\lib\platform). +add_custom_command( + TARGET synwinxt + POST_BUILD + COMMAND xcopy /Y /Q + ..\\..\\..\\..\\lib\\${CMAKE_CFG_INTDIR}\\synwinxt.* + ..\\..\\..\\..\\bin\\${CMAKE_CFG_INTDIR}\\ +) diff --git a/src/lib/synwinxt/Main.cpp b/src/lib/synwinxt/Main.cpp new file mode 100644 index 00000000..5f5659ac --- /dev/null +++ b/src/lib/synwinxt/Main.cpp @@ -0,0 +1,239 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2013 Bolton Software Ltd. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "CClassFactory.h" +#include "CArchMiscWindows.h" +#include +#include + +#pragma comment(lib, "Shlwapi.lib") + +// {1BE208B1-BC21-4E39-8BB6-A5DC3F51479E} +GUID g_CLSID = {0x1be208b1, 0xbc21, 0x4e39, {0x8b, 0xb6, 0xa5, 0xdc, 0x3f, 0x51, 0x47, 0x9e}}; +LONG g_refCount = 0; +HINSTANCE g_instance = NULL; + +HRESULT registerInprocServer(CHAR* module, const CLSID& clsid, CHAR* threadModel); +HRESULT registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid); +HRESULT unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid); +HRESULT unregisterInprocServer(const CLSID& clsid); +void outputDebugStringF(const char *str, ...); + +BOOL APIENTRY +DllMain(HMODULE module, DWORD reason, LPVOID reserved) +{ + switch (reason) { + case DLL_PROCESS_ATTACH: + g_instance = module; + DisableThreadLibraryCalls(module); + break; + + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + +STDAPI +DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppvObj) +{ + HRESULT hr = E_OUTOFMEMORY; + *ppvObj = NULL; + + CClassFactory *classFactory = new CClassFactory(); + if (classFactory != NULL) { + hr = classFactory->QueryInterface(riid, ppvObj); + classFactory->Release(); + } + return hr; +} + +STDAPI +DllCanUnloadNow() +{ + return g_refCount > 0 ? S_FALSE : S_OK; +} +STDAPI +DllRegisterServer() +{ + HRESULT hr; + + CHAR module[MAX_PATH]; + if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + // Register the component. + hr = registerInprocServer( + module, + g_CLSID, + "Apartment"); + + if (SUCCEEDED(hr)) { + hr = registerShellExtDataHandler( + "*", + g_CLSID); + } + + return hr; +} + +STDAPI +DllUnregisterServer() +{ + HRESULT hr = S_OK; + + CHAR module[MAX_PATH]; + if (GetModuleFileName(g_instance, module, ARRAYSIZE(module)) == 0) { + hr = HRESULT_FROM_WIN32(GetLastError()); + return hr; + } + + // Unregister the component. + hr = unregisterInprocServer(g_CLSID); + if (SUCCEEDED(hr)) { + // Unregister the context menu handler. + hr = unregisterShellExtDataHandler("*", g_CLSID); + } + + return hr; +} + +HRESULT +registerInprocServer(CHAR* module, const CLSID& clsid, CHAR* threadModel) +{ + if (module == NULL || threadModel == NULL) { + return E_INVALIDARG; + } + + HRESULT hr; + + WCHAR CLASSID[MAX_PATH]; + CHAR szCLSID[MAX_PATH]; + StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID)); + WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL); + + CHAR subkey[MAX_PATH]; + + // Create the HKCR\CLSID\{}\InprocServer32 key. + hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s\\InprocServer32", szCLSID); + + if (SUCCEEDED(hr)) { + // Set the default value of the InprocServer32 key to the + // path of the COM module. + HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey); + CArchMiscWindows::setValue(key, NULL, module); + + if (SUCCEEDED(hr)) { + // Set the threading model of the component. + CArchMiscWindows::setValue(key, "ThreadingModel", threadModel); + } + } + + return hr; +} + +HRESULT +unregisterInprocServer(const CLSID& clsid) +{ + HRESULT hr = S_OK; + + WCHAR CLASSID[MAX_PATH]; + CHAR szCLSID[MAX_PATH]; + StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID)); + WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL); + + CHAR subkey[MAX_PATH]; + + // Delete the HKCR\CLSID\{} key. + hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "CLSID\\%s", szCLSID); + if (SUCCEEDED(hr)) { + hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey)); + } + + return hr; +} + +HRESULT +registerShellExtDataHandler(CHAR* fileType, const CLSID& clsid) +{ + if (fileType == NULL) { + return E_INVALIDARG; + } + + HRESULT hr; + + WCHAR szCLSID[MAX_PATH]; + CHAR CLASSID[MAX_PATH]; + StringFromGUID2(clsid, szCLSID, ARRAYSIZE(szCLSID)); + WideCharToMultiByte(CP_ACP, 0, szCLSID, -1, CLASSID, MAX_PATH, NULL, NULL); + + CHAR subkey[MAX_PATH]; + + // Create the key HKCR\\shellex\DataHandler + hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), "%s\\shellex\\DataHandler", fileType); + if (SUCCEEDED(hr)) { + // Set the default value of the key. + HKEY key = CArchMiscWindows::addKey(HKEY_CLASSES_ROOT, subkey); + CArchMiscWindows::setValue(key, NULL, CLASSID); + } + + return hr; +} + +HRESULT +unregisterShellExtDataHandler(CHAR* fileType, const CLSID& clsid) +{ + if (fileType == NULL) { + return E_INVALIDARG; + } + + HRESULT hr; + + WCHAR CLASSID[MAX_PATH]; + CHAR szCLSID[MAX_PATH]; + StringFromGUID2(clsid, CLASSID, ARRAYSIZE(CLASSID)); + WideCharToMultiByte(CP_ACP, 0, CLASSID, -1, szCLSID, MAX_PATH, NULL, NULL); + + CHAR subkey[MAX_PATH]; + + // Remove the HKCR\\shellex\DataHandler key. + hr = StringCchPrintf(subkey, ARRAYSIZE(subkey), + "%s\\shellex\\DataHandler", fileType); + if (SUCCEEDED(hr)) { + hr = HRESULT_FROM_WIN32(RegDeleteTree(HKEY_CLASSES_ROOT, subkey)); + } + + return hr; +} + +void +outputDebugStringF(const char *str, ...) +{ + char buf[2048]; + + va_list ptr; + va_start(ptr,str); + vsprintf_s(buf,str,ptr); + + OutputDebugStringA(buf); +} diff --git a/src/lib/synwinxt/synwinxt.def b/src/lib/synwinxt/synwinxt.def new file mode 100644 index 00000000..718c0232 --- /dev/null +++ b/src/lib/synwinxt/synwinxt.def @@ -0,0 +1,6 @@ +LIBRARY "synwinxt" +EXPORTS + DllGetClassObject PRIVATE + DllCanUnloadNow PRIVATE + DllRegisterServer PRIVATE + DllUnregisterServer PRIVATE