Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion AppxManifest.xml.cmake
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
xmlns:desktop4="http://schemas.microsoft.com/appx/manifest/desktop/windows10/4"
xmlns:desktop5="http://schemas.microsoft.com/appx/manifest/desktop/windows10/5"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:uap3="http://schemas.microsoft.com/appx/manifest/uap/windows10/3"
IgnorableNamespaces="desktop uap uap3 rescap">
IgnorableNamespaces="com desktop desktop4 desktop5 rescap uap uap3">
<Identity Name="RiigiInfossteemiAmet.DigiDoc4client" ProcessorArchitecture="${PLATFORM}" Version="${PROJECT_VERSION}.0"
Publisher="CN=8BBBE4D8-620A-4884-A12A-72F1A2030D8B" />
<Properties>
Expand Down Expand Up @@ -54,6 +57,22 @@
</uap:SupportedFileTypes>
</uap3:FileTypeAssociation>
</uap3:Extension>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
<desktop4:FileExplorerContextMenus>
<desktop5:ItemType Type="*">
<desktop5:Verb Id="DigiDocSign" Clsid="4ef3a5aa-125c-45f5-b5fd-d4c478050afa"/>
<desktop5:Verb Id="DigiDocEnc" Clsid="bb67aa19-089b-4ec9-a059-13d985987cdc"/>
</desktop5:ItemType>
</desktop4:FileExplorerContextMenus>
</desktop4:Extension>
<com:Extension Category="windows.comServer">
<com:ComServer>
<com:SurrogateServer DisplayName="DigiDoc4 Shell Extension">
<com:Class Id="4ef3a5aa-125c-45f5-b5fd-d4c478050afa" Path="EsteidShellExtensionV2.dll" ThreadingModel="STA"/>
<com:Class Id="bb67aa19-089b-4ec9-a059-13d985987cdc" Path="EsteidShellExtensionV2.dll" ThreadingModel="STA"/>
</com:SurrogateServer>
</com:ComServer>
</com:Extension>
</Extensions>
</Application>
<Application Id="DigidocTool" Executable="digidoc-tool.exe" EntryPoint="Windows.FullTrustApplication">
Expand Down
1 change: 1 addition & 0 deletions client/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,7 @@ elseif(WIN32)
COMMAND ${CMAKE_COMMAND} -E make_directory appx
COMMAND ${CMAKE_COMMAND} -E copy AppxManifest.xml appx
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${PROJECT_NAME}> appx
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:EsteidShellExtensionV2> appx
COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/libcrypto-3${OPENSSL_SUFFIX}.dll appx
COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/libssl-3${OPENSSL_SUFFIX}.dll appx
COMMAND ${CMAKE_COMMAND} -E copy ${LIBS_PATH}/zlib$<$<CONFIG:Debug>:d>1.dll appx
Expand Down
28 changes: 25 additions & 3 deletions extensions/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
cmake_minimum_required(VERSION 3.16)
project(EsteidShellExtension VERSION 3.13.9)
add_library(${PROJECT_NAME} SHARED
dllmain.cpp
EsteidShellExtension.def
EsteidShlExt.cpp
EsteidShellExtension.cpp
EsteidShellExtension.rc
)
target_compile_definitions(${PROJECT_NAME} PRIVATE
Expand All @@ -19,7 +18,30 @@ set_target_properties(${PROJECT_NAME} PROPERTIES
INTERPROCEDURAL_OPTIMIZATION YES
COMPILE_OPTIONS "/guard:cf"
LINK_OPTIONS "/guard:cf"
LINK_LIBRARIES "uxtheme;RuntimeObject"
LINK_LIBRARIES "uxtheme;RuntimeObject;Shlwapi"
SKIP_AUTOMOC ON
)

add_library(${PROJECT_NAME}V2 SHARED
EsteidShellExtension.def
EsteidShellExtensionV2.cpp
EsteidShellExtension.rc
)
target_compile_definitions(${PROJECT_NAME}V2 PRIVATE
_UNICODE
UNICODE
_WINDLL
WIN32_LEAN_AND_MEAN
NO_ICON
VERSION=${PROJECT_VERSION_MAJOR},${PROJECT_VERSION_MINOR},${PROJECT_VERSION_PATCH},${BUILD_NUMBER}
VERSION_STR="${VERSION}"
)
set_target_properties(${PROJECT_NAME}V2 PROPERTIES
MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>"
INTERPROCEDURAL_OPTIMIZATION YES
COMPILE_OPTIONS "/guard:cf"
LINK_OPTIONS "/guard:cf"
LINK_LIBRARIES "uxtheme;RuntimeObject;Shlwapi"
SKIP_AUTOMOC ON
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,39 @@
// EsteidShlExt.cpp : Implementation of CEsteidShlExt
// http://msdn.microsoft.com/en-us/library/bb757020.aspx
/*
* EsteidShellExtension
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/

#include "EsteidShlExt.h"
#include "resource.h"

#include <unknwn.h>
#include <winrt/base.h>
#include <shellapi.h>
#include <ShlObj.h>
#include <shlwapi.h>
#include <uxtheme.h>

extern HINSTANCE instanceHandle;
#include <string>
#include <vector>

typedef DWORD ARGB;
extern "C" IMAGE_DOS_HEADER __ImageBase;

bool HasAlpha(ARGB *pargb, const SIZE &sizeImage, int cxRow)
using ARGB = DWORD;

static bool HasAlpha(ARGB *pargb, const SIZE &sizeImage, int cxRow)
{
ULONG cxDelta = cxRow - sizeImage.cx;
for(ULONG y = sizeImage.cy; y; --y)
Expand All @@ -27,18 +48,19 @@ bool HasAlpha(ARGB *pargb, const SIZE &sizeImage, int cxRow)
return false;
}

BITMAPINFO InitBitmapInfo(const SIZE &sizeImage)
static BITMAPINFO InitBitmapInfo(const SIZE &sizeImage)
{
BITMAPINFO pbmi{{sizeof(BITMAPINFOHEADER)}};
pbmi.bmiHeader.biPlanes = 1;
pbmi.bmiHeader.biCompression = BI_RGB;
pbmi.bmiHeader.biWidth = sizeImage.cx;
pbmi.bmiHeader.biHeight = sizeImage.cy;
pbmi.bmiHeader.biBitCount = 32;
return pbmi;
return {{
.biSize = sizeof(BITMAPINFOHEADER),
.biWidth = sizeImage.cx,
.biHeight = sizeImage.cy,
.biPlanes = 1,
.biBitCount = 32,
.biCompression = BI_RGB,
}};
}

HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeImage, int cxRow)
static HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeImage, int cxRow)
{
BITMAPINFO bmi = InitBitmapInfo(sizeImage);
HRESULT hr = E_OUTOFMEMORY;
Expand Down Expand Up @@ -68,7 +90,7 @@ HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeIma
return hr;
}

HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, const SIZE &sizeIcon)
static HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, const SIZE &sizeIcon)
{
RGBQUAD *prgbQuad;
int cxRow = 0;
Expand All @@ -91,10 +113,42 @@ HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon,
return hr;
}

struct
#ifdef _WIN64
__declspec(uuid("5606A547-759D-43DA-AEEB-D3BF1D1E816D"))
#else
__declspec(uuid("310AAB39-76FE-401B-8A7F-0F578C5F6AB5"))
#endif
CEsteidShlExt : public winrt::implements<CEsteidShlExt, IShellExtInit, IContextMenu>
{
CEsteidShlExt();
~CEsteidShlExt() override;

// IShellExtInit
STDMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj, HKEY hkeyProgID) final;

// IContextMenu
STDMETHODIMP QueryContextMenu(HMENU, UINT, UINT, UINT, UINT) final;
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO) final;
STDMETHODIMP GetCommandString(UINT_PTR, UINT, UINT *, LPSTR, UINT) final;

private:
enum : uint8_t {
MENU_SIGN = 0,
MENU_ENCRYPT = 1,
};

static bool WINAPI FindRegistryInstallPath(std::wstring &path);
STDMETHODIMP ExecuteDigidocclient(LPCMINVOKECOMMANDINFO pCmdInfo, bool crypto = false);

HBITMAP m_DigidocBmp = nullptr;
std::vector<std::wstring> m_Files;
};

CEsteidShlExt::CEsteidShlExt()
{
const SIZE sizeIcon { GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON) };
if(HICON hIcon = (HICON)LoadImage(instanceHandle, MAKEINTRESOURCE(IDB_DIGIDOCICO), IMAGE_ICON, sizeIcon.cx, sizeIcon.cy, LR_DEFAULTCOLOR|LR_CREATEDIBSECTION))
if(HICON hIcon = (HICON)LoadImage(reinterpret_cast<HMODULE>(&__ImageBase), MAKEINTRESOURCE(IDB_DIGIDOCICO), IMAGE_ICON, sizeIcon.cx, sizeIcon.cy, LR_DEFAULTCOLOR|LR_CREATEDIBSECTION))
{
if(HDC hdcDest = CreateCompatibleDC(nullptr))
{
Expand Down Expand Up @@ -211,9 +265,17 @@ STDMETHODIMP CEsteidShlExt::GetCommandString(
// supplied buffer.
if (uFlags & GCS_HELPTEXT) {
if (uFlags & GCS_UNICODE) {
LPCWSTR szText = idCmd == MENU_SIGN
? L"Allkirjasta valitud failid digitaalselt"
: L"Krüpteeri valitud failid";
LPCWSTR szText = idCmd == MENU_ENCRYPT ? L"Encrypt selected files" : L"Digitally sign selected files";
switch(PRIMARYLANGID(GetUserDefaultUILanguage()))
{
case LANG_ESTONIAN:
szText = idCmd == MENU_ENCRYPT ? L"Krüpteeri valitud failid" : L"Allkirjasta valitud failid digitaalselt";
break;
case LANG_RUSSIAN:
szText = idCmd == MENU_ENCRYPT ? L"Зашифровать выбранные файлы" : L"Цифровая подпись выбранных файлов";
break;
default: break;
}
// We need to cast pszName to a Unicode string, and then use the
// Unicode string copy API.
lstrcpynW(LPWSTR(pszName), szText, int(cchMax));
Expand Down Expand Up @@ -256,7 +318,7 @@ STDMETHODIMP CEsteidShlExt::ExecuteDigidocclient(LPCMINVOKECOMMANDINFO /* pCmdIn
// Read the location of the installation from registry
if (!FindRegistryInstallPath(path)) {
// .. and fall back to directory where shellext resides if not found from registry
GetModuleFileName(instanceHandle, path.data(), path.size());
GetModuleFileName(reinterpret_cast<HMODULE>(&__ImageBase), path.data(), path.size());
path.resize(path.find_last_of(L'\\') + 1);
}

Expand Down Expand Up @@ -291,3 +353,43 @@ STDMETHODIMP CEsteidShlExt::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo)
return E_INVALIDARG;
}
}

struct CEsteidShlExtFactory : winrt::implements<CEsteidShlExtFactory, IClassFactory>
{
STDMETHODIMP CreateInstance(
IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObject) noexcept final try {
if(!ppvObject)
return E_POINTER;
*ppvObject = nullptr;
if(pUnkOuter)
return CLASS_E_NOAGGREGATION;
return winrt::make<CEsteidShlExt>().as(riid, ppvObject);
} catch (...) {
return winrt::to_hresult();
}

STDMETHODIMP LockServer(BOOL /*fLock*/) noexcept final {
return S_OK;
}
};

// Used to determine whether the DLL can be unloaded by OLE
STDMETHODIMP DllCanUnloadNow()
{
if (winrt::get_module_lock())
return S_FALSE;
winrt::clear_factory_cache();
return S_OK;
}

// Returns a class factory to create an object of the requested type
//STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *result)
STDMETHODIMP DllGetClassObject(const GUID &clsid, const GUID &iid, LPVOID *result) try
{
*result = nullptr;
if (clsid == __uuidof(CEsteidShlExt))
return winrt::make<CEsteidShlExtFactory>().as(iid, result);
return winrt::hresult_class_not_available().to_abi();
} catch (...) {
return winrt::to_hresult();
}
Loading
Loading