Index: src/chext/DropMenuExt.cpp =================================================================== diff -u -N -r2fe97a93f21771d75901d4b6559057d1ea055104 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision 2fe97a93f21771d75901d4b6559057d1ea055104) +++ src/chext/DropMenuExt.cpp (.../DropMenuExt.cpp) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -19,21 +19,25 @@ #include "stdafx.h" #include "chext.h" #include "DropMenuExt.h" -#include "chext-utils.h" #include "../Common/ipcstructs.h" #include "../libchcore/TTaskDefinition.h" #include #include "ShellPathsHelpers.h" #include "../common/TShellExtMenuConfig.h" #include "../libchcore/TSharedMemory.h" +#include "TLogger.h" +#include "ShellExtensionVerifier.h" ///////////////////////////////////////////////////////////////////////////// // CDropMenuExt CDropMenuExt::CDropMenuExt() : m_piShellExtControl(NULL) { - CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); + HRESULT hResult = CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); + + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::CDropMenuExt(): hResult=" << hResult << ", m_piShellExtControl=" << m_piShellExtControl; } CDropMenuExt::~CDropMenuExt() @@ -47,50 +51,50 @@ STDMETHODIMP CDropMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) { - ATLTRACE(_T("[CDropMenuExt::Initialize] CDropMenuExt::Initialize()\n")); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::Initialize()"; // When called: // 1. R-click on a directory // 2. R-click on a directory background // 3. Pressed Ctrl+C, Ctrl+X on a specified file/directory if(!pidlFolder && !piDataObject) + { + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::Initialize(): Missing both pointers."; return E_FAIL; + } if(!pidlFolder || !piDataObject) - _ASSERTE(!_T("Missing at least one parameter - it's unexpected.")); + BOOST_LOG_SEV(rLogger, warning) << L"CDropMenuExt::Initialize(): Missing at least one parameter - it's unexpected."; if(!piDataObject) + { + BOOST_LOG_SEV(rLogger, error) << L"CDropMenuExt::Initialize(): Missing piDataObject."; return E_FAIL; + } // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(hWnd == NULL) return E_FAIL; - hResult = ReadShellConfig(); + HRESULT hResult = ReadShellConfig(); if(SUCCEEDED(hResult)) hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::Initialize(): hResult=" << hResult; + return hResult; } STDMETHODIMP CDropMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { - ATLTRACE(_T("CDropMenuExt::QueryContextMenu()\n")); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::QueryContextMenu()"; // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find CH's window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(!hWnd) return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, 0); @@ -108,18 +112,17 @@ TShellMenuItemPtr spRootMenuItem = m_tShellExtMenuConfig.GetCommandRoot(); m_tContextMenuHandler.Init(spRootMenuItem, hMenu, idCmdFirst, indexMenu, m_tShellExtData, m_tShellExtMenuConfig.GetShowShortcutIcons(), bIntercept); - return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); + HRESULT hResult = MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, m_tContextMenuHandler.GetLastCommandID() - idCmdFirst + 1); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::QueryContextMenu(): hResult=" << hResult; + return hResult; } STDMETHODIMP CDropMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { - ATLTRACE(_T("CDropMenuExt::InvokeCommand()\n")); - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return E_FAIL; // required to process other InvokeCommand handlers. + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::InvokeCommand()"; - // find window - HWND hWnd=::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(hWnd == NULL) return E_FAIL; @@ -166,13 +169,16 @@ STDMETHODIMP CDropMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CDropMenuExt::GetCommandString()"; + memset(pszName, 0, cchMax); if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) return S_OK; // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult)) return hResult; else if(hResult == S_FALSE) @@ -218,7 +224,7 @@ { try { - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(hWnd == NULL) return E_FAIL; Index: src/chext/GuidFormatter.cpp =================================================================== diff -u -N --- src/chext/GuidFormatter.cpp (revision 0) +++ src/chext/GuidFormatter.cpp (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,33 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "GuidFormatter.h" + +std::wstring GuidFormatter::FormatGuid(const GUID& rGuid) +{ + const size_t stBufferSize = 64; + wchar_t szData[ stBufferSize ]; + + _snwprintf_s(szData, stBufferSize, L"{%08lX-%04hX-%04hX-%02hhX%02hhX-%02hhX%02hhX%02hhX%02hhX%02hhX%02hhX}", + rGuid.Data1, rGuid.Data2, rGuid.Data3, + rGuid.Data4[ 0 ], rGuid.Data4[ 1 ], rGuid.Data4[ 2 ], rGuid.Data4[ 3 ], + rGuid.Data4[ 4 ], rGuid.Data4[ 5 ], rGuid.Data4[ 6 ], rGuid.Data4[ 7 ]); + + return szData; +} Index: src/chext/GuidFormatter.h =================================================================== diff -u -N --- src/chext/GuidFormatter.h (revision 0) +++ src/chext/GuidFormatter.h (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,31 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __GUIDFORMATTER_H__ +#define __GUIDFORMATTER_H__ + +#include +#include + +class GuidFormatter +{ +public: + static std::wstring FormatGuid(const GUID& rGuid); +}; + +#endif Index: src/chext/MenuExt.cpp =================================================================== diff -u -N -r2fe97a93f21771d75901d4b6559057d1ea055104 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision 2fe97a93f21771d75901d4b6559057d1ea055104) +++ src/chext/MenuExt.cpp (.../MenuExt.cpp) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -22,13 +22,14 @@ #include "..\common\ipcstructs.h" #include "stdio.h" #include "memory.h" -#include "chext-utils.h" #include #include "ShellPathsHelpers.h" #include "../common/TShellExtMenuConfig.h" #include "../libchcore/TSharedMemory.h" #include "../libchcore/TTaskDefinition.h" #include +#include "ShellExtensionVerifier.h" +#include "TLogger.h" // globals static void CutAmpersands(LPTSTR lpszString) @@ -51,7 +52,9 @@ CMenuExt::CMenuExt() : m_piShellExtControl(NULL) { - CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); + HRESULT hResult = CoCreateInstance(CLSID_CShellExtControl, NULL, CLSCTX_ALL, IID_IShellExtControl, (void**)&m_piShellExtControl); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::CMenuExt(): hResult=" << hResult << ", m_piShellExtControl=" << m_piShellExtControl; } CMenuExt::~CMenuExt() @@ -65,40 +68,36 @@ STDMETHODIMP CMenuExt::Initialize(LPCITEMIDLIST pidlFolder, IDataObject* piDataObject, HKEY /*hkeyProgID*/) { - ATLTRACE(_T("[CMenuExt::Initialize] CMenuExt::Initialize(pidlFolder = 0x%p, piDataObject=0x%p)\n"), pidlFolder, piDataObject); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::Initialize()"; if(!pidlFolder && !piDataObject) + { + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::Initialize(): Missing both pointers."; return E_INVALIDARG; + } // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find ch window - // find ch window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(!hWnd) return S_OK; - hResult = ReadShellConfig(); + HRESULT hResult = ReadShellConfig(); if(SUCCEEDED(hResult)) hResult = m_tShellExtData.GatherDataFromInitialize(pidlFolder, piDataObject); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::Initialize(): hResult=" << hResult; + return hResult; } STDMETHODIMP CMenuExt::QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT /*idCmdLast*/, UINT /*uFlags*/) { - ATLTRACE(_T("CMenuExt::QueryContextMenu()\n")); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::QueryContextMenu()"; // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return hResult; - - // find ch window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(!hWnd) return S_OK; @@ -151,19 +150,15 @@ STDMETHODIMP CMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO lpici) { - ATLTRACE(_T("CMenuExt::InvokeCommand()\n")); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::InvokeCommand()"; // textual verbs are not supported by this extension if(HIWORD(lpici->lpVerb) != 0) return E_FAIL; // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); - if(FAILED(hResult) || hResult == S_FALSE) - return E_FAIL; // required to process other InvokeCommand handlers. - - // find window - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(hWnd == NULL) return E_FAIL; @@ -215,7 +210,8 @@ HRESULT CMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM /*wParam*/, LPARAM lParam, LRESULT* /*plResult*/) { - ATLTRACE(_T("CMenuExt::HandleMenuMsg2()\n")); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::HandleMenuMsg2()"; switch(uMsg) { @@ -273,6 +269,9 @@ HRESULT CMenuExt::DrawMenuItem(LPDRAWITEMSTRUCT lpdis) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::DrawMenuItem()"; + if(!lpdis) return E_FAIL; @@ -332,13 +331,16 @@ STDMETHODIMP CMenuExt::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT* /*pwReserved*/, LPSTR pszName, UINT cchMax) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CMenuExt::GetCommandString()"; + memset(pszName, 0, cchMax); if(uFlags != GCS_HELPTEXTW && uFlags != GCS_HELPTEXTA) return S_OK; // check options - HRESULT hResult = IsShellExtEnabled(m_piShellExtControl); + HRESULT hResult = ShellExtensionVerifier::IsShellExtEnabled(m_piShellExtControl); if(FAILED(hResult)) return hResult; else if(hResult == S_FALSE) @@ -371,7 +373,7 @@ { try { - HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + HWND hWnd = ShellExtensionVerifier::VerifyShellExt(m_piShellExtControl); if(hWnd == NULL) return E_FAIL; Index: src/chext/ShellExtControl.cpp =================================================================== diff -u -N -rb2ffd219ea82ca63f9cf51c24a4b63a4f61b8ae8 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision b2ffd219ea82ca63f9cf51c24a4b63a4f61b8ae8) +++ src/chext/ShellExtControl.cpp (.../ShellExtControl.cpp) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -21,34 +21,49 @@ #include #include "ShellExtControl.h" #include "../common/version.h" +#include "TLogger.h" CShellExtControl::CShellExtControl() : m_pShellExtData(NULL), m_hMemory(NULL), m_hMutex(NULL) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"CShellExtControl::CShellExtControl()"; + // create protection mutex m_hMutex = ::CreateMutex(NULL, FALSE, _T("CHShellExtControlDataMutex")); if(!m_hMutex) + { + BOOST_LOG_SEV(rLogger, error) << L"Cannot create mutex."; return; + } DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); if(dwRes != WAIT_OBJECT_0) + { + BOOST_LOG_SEV(rLogger, error) << L"Timeout or fail waiting for mutex."; + ReleaseMutex(m_hMutex); return; + } // memory mapped file + DWORD dwLastError = ERROR_SUCCESS; + m_hMemory = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(SHELLEXT_DATA), _T("CHShellExtControlData")); // name of map object - if(!m_hMemory) + if(!m_hMemory) { + dwLastError = GetLastError(); + BOOST_LOG_SEV(rLogger, error) << L"Cannot create file mapping. Error code=" << dwLastError; ReleaseMutex(m_hMutex); CloseHandle(m_hMutex); return; } - DWORD dwLastError = GetLastError(); m_pShellExtData = (SHELLEXT_DATA*)MapViewOfFile(m_hMemory, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); if(!m_pShellExtData) { + BOOST_LOG_SEV(rLogger, error) << L"Cannot map view of file."; ReleaseMutex(m_hMutex); CloseHandle(m_hMutex); CloseHandle(m_hMemory); @@ -58,6 +73,7 @@ if(dwLastError != ERROR_ALREADY_EXISTS) { + BOOST_LOG_SEV(rLogger, debug) << L"Copy Handler is not running. Disabling shell extension."; m_pShellExtData->m_lFlags = 0; m_pShellExtData->m_lID = GetTickCount(); } @@ -81,44 +97,78 @@ STDMETHODIMP CShellExtControl::GetVersion(LONG* plVersion, BSTR* pbstrVersion) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::GetVersion()"; + if(!plVersion || !pbstrVersion || (*pbstrVersion)) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::GetVersion(): Invalid arguments."; return E_INVALIDARG; + } (*plVersion) = PRODUCT_VERSION1 << 24 | PRODUCT_VERSION2 << 16 | PRODUCT_VERSION3 << 8 | PRODUCT_VERSION4; _bstr_t strVer(SHELLEXT_PRODUCT_FULL_VERSION); *pbstrVersion = strVer.Detach(); + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::GetVersion(): *plVersion=" << *plVersion << ", pbstrVersion=" << *pbstrVersion; + return S_OK; } STDMETHODIMP CShellExtControl::SetFlags(LONG lFlags, LONG lMask) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::SetFlags(lFlags=" << lFlags << ", lMask=" << lMask << ")"; + if(!m_hMutex || !m_pShellExtData) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::SetFlags(): Wrong internal state."; return E_FAIL; + } DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); if(dwRes != WAIT_OBJECT_0) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::SetFlags(): Failed waiting for mutex."; return E_FAIL; + } m_pShellExtData->m_lFlags = (m_pShellExtData->m_lFlags & ~lMask) | (lFlags & lMask); + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::SetFlags(): New flags=" << m_pShellExtData->m_lFlags; + ReleaseMutex(m_hMutex); return S_OK; } STDMETHODIMP CShellExtControl::GetFlags(LONG* plFlags) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::GetFlags()"; + if(!m_hMutex || !m_pShellExtData) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::GetFlags(): wrong internal state."; return E_FAIL; + } + if(!plFlags) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::GetFlags(): invalid argument."; return E_INVALIDARG; + } DWORD dwRes = WaitForSingleObject(m_hMutex, 10000); if(dwRes != WAIT_OBJECT_0) + { + BOOST_LOG_SEV(rLogger, error) << "CShellExtControl::GetFlags(): failed waiting for mutex."; return E_FAIL; + } (*plFlags) = m_pShellExtData->m_lFlags; + BOOST_LOG_SEV(rLogger, debug) << "CShellExtControl::GetFlags(): returning flags=" << m_pShellExtData->m_lFlags; + ReleaseMutex(m_hMutex); return S_OK; Index: src/chext/ShellExtensionVerifier.cpp =================================================================== diff -u -N --- src/chext/ShellExtensionVerifier.cpp (revision 0) +++ src/chext/ShellExtensionVerifier.cpp (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,59 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "ShellExtensionVerifier.h" +#include "TLogger.h" + +HWND ShellExtensionVerifier::VerifyShellExt(IShellExtControl* piShellExtControl) +{ + TLogger& rLogger = Logger::get(); + + HRESULT hResult = IsShellExtEnabled(piShellExtControl); + if(FAILED(hResult) || hResult == S_FALSE) + { + BOOST_LOG_SEV(rLogger, debug) << L"Shell extension is disabled."; + return NULL; + } + + // find CH's window + HWND hWnd = ::FindWindow(_T("Copy Handler Wnd Class"), _T("Copy handler")); + if(!hWnd) + { + BOOST_LOG_SEV(rLogger, debug) << L"Cannot find Copy Handler's window."; + return NULL; + } + + return hWnd; +} + +HRESULT ShellExtensionVerifier::IsShellExtEnabled(IShellExtControl* piShellExtControl) +{ + if(!piShellExtControl) + return E_FAIL; + + LONG lFlags = eShellExt_None; + HRESULT hResult = piShellExtControl->GetFlags(&lFlags); + if(FAILED(hResult)) + return hResult; + + if(lFlags & eShellExt_Enabled) + return S_OK; + else + return S_FALSE; +} Index: src/chext/ShellExtensionVerifier.h =================================================================== diff -u -N --- src/chext/ShellExtensionVerifier.h (revision 0) +++ src/chext/ShellExtensionVerifier.h (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,31 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __SHELLEXTENSIONVERIFIER_H__ +#define __SHELLEXTENSIONVERIFIER_H__ + +#include "chext.h" + +class ShellExtensionVerifier +{ +public: + static HWND VerifyShellExt(IShellExtControl* piShellExtControl); + static HRESULT IsShellExtEnabled(IShellExtControl* piShellExtControl); +}; + +#endif Index: src/chext/TLogger.cpp =================================================================== diff -u -N --- src/chext/TLogger.cpp (revision 0) +++ src/chext/TLogger.cpp (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,126 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#include "stdafx.h" +#include "TLogger.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace logging = boost::log; +namespace src = boost::log::sources; +namespace sinks = boost::log::sinks; +namespace keywords = boost::log::keywords; +namespace expr = boost::log::expressions; +namespace attrs = boost::log::attributes; + +namespace +{ + struct LoggerInfo + { + std::wstring strLogPath; + DWORD dwMinLogLevel = 0; + }; + + bool ReadLoggerConfig(LoggerInfo& rInfo) + { + HKEY hKeyShellExt = NULL; + LSTATUS lStatus = RegOpenKeyEx(HKEY_CURRENT_USER, _T("SOFTWARE\\CopyHandler\\ShellExtension"), 0, KEY_QUERY_VALUE, &hKeyShellExt); + if(lStatus != ERROR_SUCCESS) + return false; + + // log path + DWORD dwType = REG_SZ; + const DWORD stMaxBuffer = 1024; + std::unique_ptr buf(new wchar_t[stMaxBuffer]); + + DWORD dwCount = stMaxBuffer; + lStatus = RegQueryValueEx(hKeyShellExt, L"LogPath", NULL, &dwType, (BYTE*)buf.get(), &dwCount); + if(lStatus != ERROR_SUCCESS) + { + RegCloseKey(hKeyShellExt); + return false; + } + + buf[ dwCount / 2 ] = L'\0'; + rInfo.strLogPath = buf.get(); + + // log level + dwType = REG_DWORD; + dwCount = sizeof(DWORD); + DWORD dwValue = 0; + lStatus = RegQueryValueEx(hKeyShellExt, L"MinLogLevel", NULL, &dwType, (BYTE*)&dwValue, &dwCount); + if(lStatus != ERROR_SUCCESS) + { + RegCloseKey(hKeyShellExt); + return false; + } + + rInfo.dwMinLogLevel = dwValue; + + RegCloseKey(hKeyShellExt); + + return true; + } +} + +BOOST_LOG_GLOBAL_LOGGER_INIT(Logger, TLogger) +{ + LoggerInfo li; + if(ReadLoggerConfig(li)) + { + DWORD dwProcessId = GetProcessId(GetCurrentProcess()); + boost::replace_all(li.strLogPath, L"%pid%", boost::lexical_cast(dwProcessId)); + + logging::add_common_attributes(); + logging::core::get()->add_global_attribute("Scope", attrs::named_scope()); + + logging::add_file_log( + keywords::file_name = li.strLogPath, + keywords::rotation_size = 10 * 1024 * 1024, + keywords::open_mode = (std::ios::out | std::ios::app), + keywords::format = + ( + expr::stream + << expr::format_date_time< boost::posix_time::ptime >("TimeStamp", "[%Y-%m-%d %H:%M:%S]") + << "[" << logging::trivial::severity << "]: " + //<< expr::format_named_scope("Scopes", "%n") + //<< ":" + << expr::wmessage + ) + ); + + severity_level eSeverity = (severity_level)li.dwMinLogLevel; + logging::core::get()->set_filter( + severity >= eSeverity + ); + } + + boost::log::sources::wseverity_logger_mt lg; + return lg; +} Index: src/chext/TLogger.h =================================================================== diff -u -N --- src/chext/TLogger.h (revision 0) +++ src/chext/TLogger.h (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -0,0 +1,33 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __TLOGGER_H__ +#define __TLOGGER_H__ + +#include +#include +#include + +// ugly way to include severity_level in the global namespace +using namespace boost::log::trivial; + +typedef boost::log::sources::wseverity_logger_mt TLogger; + +BOOST_LOG_GLOBAL_LOGGER(Logger, TLogger) + +#endif Index: src/chext/chext-utils.h =================================================================== diff -u -N --- src/chext/chext-utils.h (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/chext/chext-utils.h (revision 0) @@ -1,38 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2001-2008 by J�zef Starosczyk * -* ixen@copyhandler.com * -* * -* This program is free software; you can redistribute it and/or modify * -* it under the terms of the GNU Library General Public License * -* (version 2) as published by the Free Software Foundation; * -* * -* 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. * -* * -* You should have received a copy of the GNU Library General Public * -* License along with this program; if not, write to the * -* Free Software Foundation, Inc., * -* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef __CHEXT_UTILS_H__ -#define __CHEXT_UTILS_H__ - -inline HRESULT IsShellExtEnabled(IShellExtControl* piShellExtControl) -{ - if(!piShellExtControl) - return E_FAIL; - - LONG lFlags = eShellExt_None; - HRESULT hResult = piShellExtControl->GetFlags(&lFlags); - if(FAILED(hResult)) - return hResult; - - if(lFlags & eShellExt_Enabled) - return S_OK; - else - return S_FALSE; -} - -#endif Index: src/chext/chext.cpp =================================================================== diff -u -N -rc435ab507c8b8280264188b49e9ada56d46c0261 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/chext.cpp (.../chext.cpp) (revision c435ab507c8b8280264188b49e9ada56d46c0261) +++ src/chext/chext.cpp (.../chext.cpp) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -24,70 +24,96 @@ #include "resource.h" #include "chext.h" #include "dllmain.h" -//#include +#include "TLogger.h" +#include "GuidFormatter.h" ///////////////////////////////////////////////////////////////////////////// // Used to determine whether the DLL can be unloaded by OLE -STDAPI DllCanUnloadNow(void) +STDAPI DllCanUnloadNow() { - return _AtlModule.DllCanUnloadNow(); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"DllCanUnloadNow()"; + + HRESULT hResult = _AtlModule.DllCanUnloadNow(); + + BOOST_LOG_SEV(rLogger, debug) << L"DllCanUnloadNow: hResult = " << hResult; + + return hResult; } ///////////////////////////////////////////////////////////////////////////// // Returns a class factory to create an object of the requested type STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { - return _AtlModule.DllGetClassObject(rclsid, riid, ppv); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"DllGetClassObject()"; + + HRESULT hResult = _AtlModule.DllGetClassObject(rclsid, riid, ppv); + + BOOST_LOG_SEV(rLogger, debug) << L"DllGetClassObject(clsid=" << GuidFormatter::FormatGuid(rclsid) << ", riid=" << GuidFormatter::FormatGuid(riid) << ", ppv=" << ppv << "): hResult=" << hResult; + + return hResult; } ///////////////////////////////////////////////////////////////////////////// // DllRegisterServer - Adds entries to the system registry STDAPI DllRegisterServer() { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"DllRegisterServer()"; + // registers object, typelib and all interfaces in typelib - return _AtlModule.DllRegisterServer(); + HRESULT hResult = _AtlModule.DllRegisterServer(); + + BOOST_LOG_SEV(rLogger, debug) << L"DllRegisterServer(): hResult=" << hResult; + + return hResult; } ///////////////////////////////////////////////////////////////////////////// // DllUnregisterServer - Removes entries from the system registry -STDAPI DllUnregisterServer(void) +STDAPI DllUnregisterServer() { - return _AtlModule.DllUnregisterServer(); + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"DllUnregisterServer()"; + + HRESULT hResult = _AtlModule.DllUnregisterServer(); + + BOOST_LOG_SEV(rLogger, debug) << L"DllUnregisterServer(): hResult=" << hResult; + + return hResult; } // DllInstall - Adds/Removes entries to the system registry per user // per machine. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine) { + TLogger& rLogger = Logger::get(); + BOOST_LOG_SEV(rLogger, debug) << L"DllInstall()"; + HRESULT hr = E_FAIL; static const wchar_t szUserSwitch[] = _T("user"); if (pszCmdLine != NULL) { if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0) - { AtlSetPerUserRegistration(true); - } } if (bInstall) - { + { hr = DllRegisterServer(); if (FAILED(hr)) - { DllUnregisterServer(); - } } else - { hr = DllUnregisterServer(); - } + BOOST_LOG_SEV(rLogger, debug) << L"DllInstall(bInstall=" << bInstall << ", pszCmdLine: " << pszCmdLine << L"): hResult=" << hr; + return hr; } - - Index: src/chext/chext.vc140.vcxproj =================================================================== diff -u -N -rd6c3523b8a96c26c0c448dc35964d172661e9be5 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/chext.vc140.vcxproj (.../chext.vc140.vcxproj) (revision d6c3523b8a96c26c0c448dc35964d172661e9be5) +++ src/chext/chext.vc140.vcxproj (.../chext.vc140.vcxproj) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -202,6 +202,7 @@ true EditAndContinue true + 4714;4503 _DEBUG;%(PreprocessorDefinitions) @@ -233,6 +234,7 @@ EditAndContinue true ..\..\ext\gmock\include + 4714;4503 _DEBUG;%(PreprocessorDefinitions) @@ -293,6 +295,7 @@ ProgramDatabase false true + 4714;4503 _DEBUG;%(PreprocessorDefinitions) @@ -326,6 +329,7 @@ false true ..\..\ext\gmock\include + 4714;4503 _DEBUG;%(PreprocessorDefinitions) @@ -386,6 +390,7 @@ true ProgramDatabase true + 4714;4503 NDEBUG;%(PreprocessorDefinitions) @@ -419,6 +424,7 @@ ProgramDatabase true ..\..\ext\gmock\include + 4714;4503 NDEBUG;%(PreprocessorDefinitions) @@ -480,6 +486,7 @@ true ProgramDatabase true + 4714;4503 NDEBUG;%(PreprocessorDefinitions) @@ -514,6 +521,7 @@ ProgramDatabase true ..\..\ext\gmock\include + 4714;4503 NDEBUG;%(PreprocessorDefinitions) @@ -574,10 +582,13 @@ NotUsing + + + @@ -613,10 +624,13 @@ + + + Index: src/chext/chext.vc140.vcxproj.filters =================================================================== diff -u -N -r7972b0944e0a947144fbdb93262f7d73ac528dc7 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/chext.vc140.vcxproj.filters (.../chext.vc140.vcxproj.filters) (revision 7972b0944e0a947144fbdb93262f7d73ac528dc7) +++ src/chext/chext.vc140.vcxproj.filters (.../chext.vc140.vcxproj.filters) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -65,6 +65,15 @@ Tests + + Source Files\Tools + + + Source Files\Tools + + + Source Files\Tools + @@ -103,6 +112,15 @@ Resource Files + + Source Files\Tools + + + Source Files\Tools + + + Source Files\Tools + Index: src/chext/dllmain.cpp =================================================================== diff -u -N -r633a533cb6e741d44fe28aa56339e1d2709b1b27 -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/dllmain.cpp (.../dllmain.cpp) (revision 633a533cb6e741d44fe28aa56339e1d2709b1b27) +++ src/chext/dllmain.cpp (.../dllmain.cpp) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -1,12 +1,11 @@ #include "stdafx.h" #include "resource.h" #include "chext.h" - #include "dllmain.h" - #include "MenuExt.h" #include "DropMenuExt.h" #include "ShellExtControl.h" +#include "TLogger.h" CCHExtModule _AtlModule; @@ -20,10 +19,15 @@ if (dwReason == DLL_PROCESS_ATTACH) { DisableThreadLibraryCalls(hInstance); + + TLogger lg; + BOOST_LOG_SEV(lg, debug) << L"DllMain - attaching to process: " << hInstance << L", " << dwReason << L", " << lpReserved; } else if (dwReason == DLL_PROCESS_DETACH) { + TLogger lg; + BOOST_LOG_SEV(lg, debug) << L"DllMain - detaching from process: " << hInstance << L", " << dwReason << L", " << lpReserved; } return _AtlModule.DllMain(dwReason, lpReserved); -} \ No newline at end of file +} Index: src/chext/dllmain.h =================================================================== diff -u -N -rd5c3edd0d167db9b5d47d04248820fda49499a5e -rb79aca0d66b1084f230022efe39cc89307482e6d --- src/chext/dllmain.h (.../dllmain.h) (revision d5c3edd0d167db9b5d47d04248820fda49499a5e) +++ src/chext/dllmain.h (.../dllmain.h) (revision b79aca0d66b1084f230022efe39cc89307482e6d) @@ -1,3 +1,23 @@ +// ============================================================================ +// Copyright (C) 2001-2015 by Jozef Starosczyk +// ixen@copyhandler.com +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU Library General Public License +// (version 2) as published by the Free Software Foundation; +// +// 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. +// +// You should have received a copy of the GNU Library General Public +// License along with this program; if not, write to the +// Free Software Foundation, Inc., +// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +// ============================================================================ +#ifndef __DLLMAIN_H__ +#define __DLLMAIN_H__ class CCHExtModule : public CAtlDllModuleT { @@ -7,3 +27,5 @@ }; extern class CCHExtModule _AtlModule; + +#endif Index: tools/ShellExtLogging.reg =================================================================== diff -u -N Binary files differ