1- // EsteidShlExt.cpp : Implementation of CEsteidShlExt
2- // http://msdn.microsoft.com/en-us/library/bb757020.aspx
1+ /*
2+ * EsteidShellExtension
3+ *
4+ * This library is free software; you can redistribute it and/or
5+ * modify it under the terms of the GNU Lesser General Public
6+ * License as published by the Free Software Foundation; either
7+ * version 2.1 of the License, or (at your option) any later version.
8+ *
9+ * This library is distributed in the hope that it will be useful,
10+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
11+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12+ * Lesser General Public License for more details.
13+ *
14+ * You should have received a copy of the GNU Lesser General Public
15+ * License along with this library; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ *
18+ */
319
4- #include " EsteidShlExt.h"
520#include " resource.h"
621
22+ #include < unknwn.h>
23+ #include < winrt/base.h>
724#include < shellapi.h>
25+ #include < ShlObj.h>
826#include < shlwapi.h>
927#include < uxtheme.h>
1028
11- extern HINSTANCE instanceHandle;
29+ #include < string>
30+ #include < vector>
1231
13- typedef DWORD ARGB ;
32+ extern " C " IMAGE_DOS_HEADER __ImageBase ;
1433
15- bool HasAlpha (ARGB *pargb, const SIZE &sizeImage, int cxRow)
34+ using ARGB = DWORD;
35+
36+ static bool HasAlpha (ARGB *pargb, const SIZE &sizeImage, int cxRow)
1637{
1738 ULONG cxDelta = cxRow - sizeImage.cx ;
1839 for (ULONG y = sizeImage.cy ; y; --y)
@@ -27,18 +48,19 @@ bool HasAlpha(ARGB *pargb, const SIZE &sizeImage, int cxRow)
2748 return false ;
2849}
2950
30- BITMAPINFO InitBitmapInfo (const SIZE &sizeImage)
51+ static BITMAPINFO InitBitmapInfo (const SIZE &sizeImage)
3152{
32- BITMAPINFO pbmi{{sizeof (BITMAPINFOHEADER)}};
33- pbmi.bmiHeader .biPlanes = 1 ;
34- pbmi.bmiHeader .biCompression = BI_RGB;
35- pbmi.bmiHeader .biWidth = sizeImage.cx ;
36- pbmi.bmiHeader .biHeight = sizeImage.cy ;
37- pbmi.bmiHeader .biBitCount = 32 ;
38- return pbmi;
53+ return {{
54+ .biSize = sizeof (BITMAPINFOHEADER),
55+ .biWidth = sizeImage.cx ,
56+ .biHeight = sizeImage.cy ,
57+ .biPlanes = 1 ,
58+ .biBitCount = 32 ,
59+ .biCompression = BI_RGB,
60+ }};
3961}
4062
41- HRESULT ConvertToPARGB32 (HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeImage, int cxRow)
63+ static HRESULT ConvertToPARGB32 (HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeImage, int cxRow)
4264{
4365 BITMAPINFO bmi = InitBitmapInfo (sizeImage);
4466 HRESULT hr = E_OUTOFMEMORY;
@@ -68,7 +90,7 @@ HRESULT ConvertToPARGB32(HDC hdc, ARGB *pargb, HBITMAP hbmp, const SIZE &sizeIma
6890 return hr;
6991}
7092
71- HRESULT ConvertBufferToPARGB32 (HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, const SIZE &sizeIcon)
93+ static HRESULT ConvertBufferToPARGB32 (HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon, const SIZE &sizeIcon)
7294{
7395 RGBQUAD *prgbQuad;
7496 int cxRow = 0 ;
@@ -91,10 +113,42 @@ HRESULT ConvertBufferToPARGB32(HPAINTBUFFER hPaintBuffer, HDC hdc, HICON hicon,
91113 return hr;
92114}
93115
116+ struct
117+ #ifdef _WIN64
118+ __declspec (uuid(" 5606A547-759D-43DA-AEEB-D3BF1D1E816D" ))
119+ #else
120+ __declspec (uuid(" 310AAB39-76FE-401B-8A7F-0F578C5F6AB5" ))
121+ #endif
122+ CEsteidShlExt : public winrt::implements<CEsteidShlExt, IShellExtInit, IContextMenu>
123+ {
124+ CEsteidShlExt ();
125+ ~CEsteidShlExt () override ;
126+
127+ // IShellExtInit
128+ STDMETHODIMP Initialize (LPCITEMIDLIST pidlFolder, LPDATAOBJECT pdtobj, HKEY hkeyProgID) final ;
129+
130+ // IContextMenu
131+ STDMETHODIMP QueryContextMenu (HMENU, UINT, UINT, UINT, UINT) final ;
132+ STDMETHODIMP InvokeCommand (LPCMINVOKECOMMANDINFO) final ;
133+ STDMETHODIMP GetCommandString (UINT_PTR, UINT, UINT *, LPSTR, UINT) final ;
134+
135+ private:
136+ enum : uint8_t {
137+ MENU_SIGN = 0 ,
138+ MENU_ENCRYPT = 1 ,
139+ };
140+
141+ static bool WINAPI FindRegistryInstallPath (std::wstring &path);
142+ STDMETHODIMP ExecuteDigidocclient (LPCMINVOKECOMMANDINFO pCmdInfo, bool crypto = false );
143+
144+ HBITMAP m_DigidocBmp = nullptr ;
145+ std::vector<std::wstring> m_Files;
146+ };
147+
94148CEsteidShlExt::CEsteidShlExt ()
95149{
96150 const SIZE sizeIcon { GetSystemMetrics (SM_CXSMICON), GetSystemMetrics (SM_CYSMICON) };
97- if (HICON hIcon = (HICON)LoadImage (instanceHandle , MAKEINTRESOURCE (IDB_DIGIDOCICO), IMAGE_ICON, sizeIcon.cx , sizeIcon.cy , LR_DEFAULTCOLOR|LR_CREATEDIBSECTION))
151+ if (HICON hIcon = (HICON)LoadImage (reinterpret_cast <HMODULE>(&__ImageBase) , MAKEINTRESOURCE (IDB_DIGIDOCICO), IMAGE_ICON, sizeIcon.cx , sizeIcon.cy , LR_DEFAULTCOLOR|LR_CREATEDIBSECTION))
98152 {
99153 if (HDC hdcDest = CreateCompatibleDC (nullptr ))
100154 {
@@ -211,9 +265,17 @@ STDMETHODIMP CEsteidShlExt::GetCommandString(
211265 // supplied buffer.
212266 if (uFlags & GCS_HELPTEXT) {
213267 if (uFlags & GCS_UNICODE) {
214- LPCWSTR szText = idCmd == MENU_SIGN
215- ? L" Allkirjasta valitud failid digitaalselt"
216- : L" Krüpteeri valitud failid" ;
268+ LPCWSTR szText = idCmd == MENU_ENCRYPT ? L" Encrypt selected files" : L" Digitally sign selected files" ;
269+ switch (PRIMARYLANGID (GetUserDefaultUILanguage ()))
270+ {
271+ case LANG_ESTONIAN:
272+ szText = idCmd == MENU_ENCRYPT ? L" Krüpteeri valitud failid" : L" Allkirjasta valitud failid digitaalselt" ;
273+ break ;
274+ case LANG_RUSSIAN:
275+ szText = idCmd == MENU_ENCRYPT ? L" Зашифровать выбранные файлы" : L" Цифровая подпись выбранных файлов" ;
276+ break ;
277+ default : break ;
278+ }
217279 // We need to cast pszName to a Unicode string, and then use the
218280 // Unicode string copy API.
219281 lstrcpynW (LPWSTR (pszName), szText, int (cchMax));
@@ -256,7 +318,7 @@ STDMETHODIMP CEsteidShlExt::ExecuteDigidocclient(LPCMINVOKECOMMANDINFO /* pCmdIn
256318 // Read the location of the installation from registry
257319 if (!FindRegistryInstallPath (path)) {
258320 // .. and fall back to directory where shellext resides if not found from registry
259- GetModuleFileName (instanceHandle , path.data (), path.size ());
321+ GetModuleFileName (reinterpret_cast <HMODULE>(&__ImageBase) , path.data (), path.size ());
260322 path.resize (path.find_last_of (L' \\ ' ) + 1 );
261323 }
262324
@@ -291,3 +353,43 @@ STDMETHODIMP CEsteidShlExt::InvokeCommand(LPCMINVOKECOMMANDINFO pCmdInfo)
291353 return E_INVALIDARG;
292354 }
293355}
356+
357+ struct CEsteidShlExtFactory : winrt::implements<CEsteidShlExtFactory, IClassFactory>
358+ {
359+ STDMETHODIMP CreateInstance (
360+ IUnknown *pUnkOuter, REFIID riid, LPVOID *ppvObject) noexcept final try {
361+ if (!ppvObject)
362+ return E_POINTER;
363+ *ppvObject = nullptr ;
364+ if (pUnkOuter)
365+ return CLASS_E_NOAGGREGATION;
366+ return winrt::make<CEsteidShlExt>().as (riid, ppvObject);
367+ } catch (...) {
368+ return winrt::to_hresult ();
369+ }
370+
371+ STDMETHODIMP LockServer (BOOL /* fLock*/ ) noexcept final {
372+ return S_OK;
373+ }
374+ };
375+
376+ // Used to determine whether the DLL can be unloaded by OLE
377+ STDMETHODIMP DllCanUnloadNow ()
378+ {
379+ if (winrt::get_module_lock ())
380+ return S_FALSE;
381+ winrt::clear_factory_cache ();
382+ return S_OK;
383+ }
384+
385+ // Returns a class factory to create an object of the requested type
386+ // STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *result)
387+ STDMETHODIMP DllGetClassObject (const GUID &clsid, const GUID &iid, LPVOID *result) try
388+ {
389+ *result = nullptr ;
390+ if (clsid == __uuidof (CEsteidShlExt))
391+ return winrt::make<CEsteidShlExtFactory>().as (iid, result);
392+ return winrt::hresult_class_not_available ().to_abi ();
393+ } catch (...) {
394+ return winrt::to_hresult ();
395+ }
0 commit comments