Page MenuHome GnuPG

No OneTemporary

diff --git a/src/gpga/CMakeLists.txt b/src/gpga/CMakeLists.txt
index 1e8e8c3..3502ad1 100644
--- a/src/gpga/CMakeLists.txt
+++ b/src/gpga/CMakeLists.txt
@@ -1,28 +1,29 @@
# Copyright (C) 2018 Andre Heinecke <aheinecke@gnupg.com>
#
# This file is Free Software under the GNU GPL (v>=2)
# and comes with ABSOLUTELY NO WARRANTY!
# See LICENSE.txt for details.
set(EXECUTABLE_NAME "gpga")
set(EXECUTABLE_SRC
flange.cpp
../util/debug.cpp
../util/w32-util.cpp
gpga.def
+ gpgshellfolder.cpp
)
add_library (${EXECUTABLE_NAME}
${EXECUTABLE_SRC}
)
target_link_libraries(${EXECUTABLE_NAME}
PRIVATE Gpgmepp
)
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "-municode")
set_target_properties(${EXECUTABLE_NAME} PROPERTIES PREFIX "")
install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)
diff --git a/src/gpga/flange.cpp b/src/gpga/flange.cpp
index b77d6e5..15c5144 100644
--- a/src/gpga/flange.cpp
+++ b/src/gpga/flange.cpp
@@ -1,271 +1,277 @@
/* Copyright (C) 2018 by Andre Heinecke <aheinecke@gnupg.com>
*
* This file is Free Software under the GNU GPL (v>=2)
* and comes with ABSOLUTELY NO WARRANTY!
* See LICENSE.txt for details.
*/
#include "flange.h"
#include "debug.h"
#include "comhelp.h"
#include "w32-util.h"
+#include "gpgshellfolder.h"
#include "shlobj.h"
/** @file Code to flange to the Windows explorer.
*
* This file contains the Windows and COM API requirements
* to properly work as an explorer extension.
*/
#ifndef INITGUID
/* Include every header that defines a GUID below this
macro. Otherwise the GUID's will only be declared and
not defined. */
#define INITGUID
#endif
#include <initguid.h>
#define MY_CLSID_STR "CCD955E4-5C16-4A33-AFDA-A8947A94946C"
DEFINE_GUID(MY_CLSID, 0xCCD955E4, 0x5C16, 0x4A33,
0xAF, 0xDA, 0xA8, 0x94, 0x7A, 0x94, 0x94, 0x6C);
#define MY_PROGID "GpgArchive"
static HINSTANCE s_hinst;
static FlangeFactory *s_factory;
static void init_logging()
{
static bool wasDone;
if (!wasDone) {
gpgrt_log_set_sink("c:\\tmp\\gpga.txt", nullptr, -1);
wasDone = true;
}
}
/* Here we go */
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
init_logging ();
- log_debug ("Get class object for clsid'" GUID_FMT "'",
- GUID_ARG(riid));
if (!ppv) {
return E_POINTER;
}
*ppv = nullptr;
if (rclsid == MY_CLSID) {
return FlangeFactory::instance()->QueryInterface(riid, ppv);
}
+ log_debug ("Get class object for nonimp clsid'" GUID_FMT "'",
+ GUID_ARG(riid));
+
return CLASS_E_CLASSNOTAVAILABLE;
}
STDMETHODIMP FlangeFactory::LockServer (BOOL lock)
{
if (lock) {
AddRef();
} else {
Release();
}
return S_OK;
}
-STDMETHODIMP FlangeFactory::CreateInstance (LPUNKNOWN unknown,
+STDMETHODIMP FlangeFactory::CreateInstance (LPUNKNOWN,
REFIID riid,
LPVOID* ppvObj)
{
- log_debug ("CreateInstance with id '" GUID_FMT "'",
- GUID_ARG(riid));
+ if (riid == IID_IShellFolder) {
+ auto folder = new GpgShellFolder();
+ return folder->QueryInterface (riid, ppvObj);
+ }
+ log_debug ("CreateInstance with unimplemented id '" GUID_FMT "'",
+ GUID_ARG(riid));
return E_NOINTERFACE;
}
STDMETHODIMP FlangeFactory::QueryInterface (REFIID riid, void **ppv)
{
- log_debug ("QueryInterface:'" GUID_FMT "'",
- GUID_ARG(riid));
-
if (!ppv) {
return E_POINTER;
}
*ppv = nullptr;
/* The static casts ensure that the virtual function table
layout of the returned object is correct. */
- if (riid == IID_IUnknown)
+ if (riid == IID_IUnknown) {
*ppv = static_cast<IUnknown *> (this);
- else if (riid == IID_IClassFactory)
+ } else if (riid == IID_IClassFactory) {
*ppv = static_cast<IClassFactory *> (this);
- else
+ } else {
+ log_debug("QueryInterface with unknwon interface: '" GUID_FMT "'",
+ GUID_ARG(riid));
return E_NOINTERFACE;
+ }
reinterpret_cast<IUnknown *>(*ppv)->AddRef ();
return S_OK;
}
FlangeFactory *FlangeFactory::instance()
{
if (!s_factory) {
s_factory = new FlangeFactory();
}
return s_factory;
}
STDMETHODIMP_(ULONG) FlangeFactory::Release()
{
ULONG lCount = --m_lRef;
if (!lCount) {
delete this;
}
return lCount;
}
FlangeFactory::~FlangeFactory()
{
s_factory = nullptr;
}
STDAPI DllCanUnloadNow()
{
return s_factory == nullptr;
}
STDAPI DllUnregisterServer()
{
HKEY root_key;
if (W32::isElevated()) {
root_key = HKEY_LOCAL_MACHINE;
} else {
root_key = HKEY_CURRENT_USER;
}
log_debug("Un Registering shell extension.");
RegDeleteKeyA(root_key, "Software\\Classes\\.gpga");
RegDeleteKeyA(root_key, "Software\\Classes\\GPGArchive");
RegDeleteKeyA(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}");
}
STDAPI DllRegisterServer()
{
const char *root_key;
const auto gpg4windir = W32::getGpg4winDir();
init_logging ();
log_debug ("Debug");
if (gpg4windir.empty()) {
STRANGEPOINT;
return FALSE;
}
char module_path[MAX_PATH + 1];
if (!s_hinst || GetModuleFileNameA (s_hinst, module_path,
MAX_PATH) == MAX_PATH) {
STRANGEPOINT;
return FALSE;
}
if (W32::isElevated()) {
root_key = "HKEY_LOCAL_MACHINE";
} else {
root_key = "HKEY_CURRENT_USER";
}
log_debug("Registering shell extension.");
/* Tar file is: {2B3256E4-49AA-11D3-8229-0050AE509054} */
/* Register File extension */
if (!W32::writeRegStr(root_key, "Software\\Classes\\.gpga",
nullptr, MY_PROGID)) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\GPGArchive",
nullptr, "GnuPG Archive Extension")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\GPGArchive",
"FriendlyTypeName", "GnuPG Archive")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\GPGArchive\\ShellEx",
nullptr, "")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\GPGArchive\\CLSID",
nullptr, "{" MY_CLSID_STR "}")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\GPGArchive\\CLSID",
nullptr, "{" MY_CLSID_STR "}")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}",
nullptr, "GnuPG Archive Extension")) {
STRANGEPOINT;
return FALSE;
}
std::string iconPath = gpg4windir + "\\share\\gpg4win\\file-ext.ico";
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}",
"Default Icon", iconPath.c_str())) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}\\InprocServer32",
nullptr, module_path)) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}\\InprocServer32",
"ThreadingModel", "Apartment")) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}\\ProgID",
nullptr, MY_PROGID)) {
STRANGEPOINT;
return FALSE;
}
if (!W32::writeRegStr(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}\\Implemented Categories\\"
"{00021490-0000-0000-C000-000000000046}",
nullptr, "Browsable Shell Extension")) {
STRANGEPOINT;
return FALSE;
}
/* See: https://msdn.microsoft.com/en-us/library/windows/desktop/cc144093(v=vs.85).aspx */
if (!W32::writeRegDword(root_key, "Software\\Classes\\CLSID\\{" MY_CLSID_STR "}\\ShellFolder",
"Attributes", SFGAO_FOLDER | SFGAO_CANRENAME | SFGAO_CANDELETE)) {
STRANGEPOINT;
return FALSE;
}
/* Notify the shell about the change. */
SHChangeNotify (SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
}
STDAPI DllMain (HINSTANCE hinst, DWORD reason, LPVOID)
{
if (reason == DLL_PROCESS_ATTACH) {
s_hinst = hinst;
// Do init of GPGME
init_logging ();
} else if (reason == DLL_PROCESS_DETACH) {
log_debug ("Detached");
}
return TRUE;
}
diff --git a/src/gpga/gpgshellfolder.cpp b/src/gpga/gpgshellfolder.cpp
new file mode 100644
index 0000000..17caeb7
--- /dev/null
+++ b/src/gpga/gpgshellfolder.cpp
@@ -0,0 +1,146 @@
+/* Copyright (C) 2018 by Andre Heinecke <aheinecke@gnupg.com>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include "gpgshellfolder.h"
+#include "debug.h"
+
+GpgShellFolder::~GpgShellFolder()
+{
+}
+
+STDMETHODIMP GpgShellFolder::QueryInterface (REFIID riid, void **ppv)
+{
+ if (!ppv) {
+ return E_POINTER;
+ }
+
+ *ppv = nullptr;
+
+ /* The static casts ensure that the virtual function table
+ layout of the returned object is correct. */
+ if (riid == IID_IUnknown) {
+ *ppv = static_cast<IUnknown *> (this);
+ } else if (riid == IID_IShellFolder) {
+ *ppv = static_cast<IShellFolder*> (this);
+ } else {
+ log_debug("QueryInterface with unknwon interface: '" GUID_FMT "'",
+ GUID_ARG(riid));
+ return E_NOINTERFACE;
+ }
+
+ reinterpret_cast<IUnknown *>(*ppv)->AddRef ();
+
+ return S_OK;
+}
+
+ULONG STDMETHODCALLTYPE GpgShellFolder::Release()
+{
+ ULONG lCount = --m_lRef;
+ if (!lCount) {
+ delete this;
+ }
+ return lCount;
+}
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::ParseDisplayName(HWND hwnd,
+ IBindCtx *pbc,
+ LPWSTR pszDisplayName,
+ ULONG *pchEaten,
+ PIDLIST_RELATIVE *ppidl,
+ ULONG *pdwAttributes)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::EnumObjects(HWND hwnd,
+ SHCONTF grfFlags,
+ IEnumIDList **ppenumIDList)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::BindToObject(PCUIDLIST_RELATIVE pidl,
+ IBindCtx *pbc,
+ REFIID riid,
+ void **ppv)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::BindToStorage(PCUIDLIST_RELATIVE pidl,
+ IBindCtx *pbc,
+ REFIID riid,
+ void **ppv)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::CompareIDs(LPARAM lParam,
+ PCUIDLIST_RELATIVE pidl1,
+ PCUIDLIST_RELATIVE pidl2)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::CreateViewObject(HWND hwndOwner,
+ REFIID riid,
+ void **ppv)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::GetAttributesOf(UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
+ SFGAOF *rgfInOut)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::GetUIObjectOf(HWND hwndOwner,
+ UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
+ REFIID riid,
+ UINT *rgfReserved,
+ void **ppv)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::GetDisplayNameOf(PCUITEMID_CHILD pidl,
+ SHGDNF uFlags,
+ STRRET *pName)
+{
+ TRACEPOINT;
+ return S_OK;
+}
+
+
+HRESULT STDMETHODCALLTYPE GpgShellFolder::SetNameOf(HWND hwnd,
+ PCUITEMID_CHILD pidl,
+ LPCWSTR pszName,
+ SHGDNF uFlags,
+ PITEMID_CHILD *ppidlOut)
+{
+ TRACEPOINT;
+ return S_OK;
+}
diff --git a/src/gpga/gpgshellfolder.h b/src/gpga/gpgshellfolder.h
new file mode 100644
index 0000000..4e3ad22
--- /dev/null
+++ b/src/gpga/gpgshellfolder.h
@@ -0,0 +1,77 @@
+#ifndef GPGSHELLFOLDER_H
+#define GPGSHELLFOLDER_H
+/* Copyright (C) 2018 by Andre Heinecke <aheinecke@gnupg.com>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+#include <windows.h>
+#include <shlobj.h>
+
+class GpgShellFolder: public IShellFolder
+{
+public:
+ GpgShellFolder(): m_lRef(0) {}
+
+ virtual ~GpgShellFolder();
+
+ /* IUnknown */
+ STDMETHODIMP QueryInterface (REFIID riid, LPVOID* ppvObj);
+ STDMETHODIMP_(ULONG) AddRef() { ++m_lRef; return m_lRef; };
+ STDMETHODIMP_(ULONG) Release();
+
+ /* IShellFolder*/
+ HRESULT STDMETHODCALLTYPE ParseDisplayName(HWND hwnd,
+ IBindCtx *pbc,
+ LPWSTR pszDisplayName,
+ ULONG *pchEaten,
+ PIDLIST_RELATIVE *ppidl,
+ ULONG *pdwAttributes);
+
+ HRESULT STDMETHODCALLTYPE EnumObjects(HWND hwnd,
+ SHCONTF grfFlags,
+ IEnumIDList **ppenumIDList);
+
+ HRESULT STDMETHODCALLTYPE BindToObject(PCUIDLIST_RELATIVE pidl,
+ IBindCtx *pbc,
+ REFIID riid,
+ void **ppv);
+
+ HRESULT STDMETHODCALLTYPE BindToStorage(PCUIDLIST_RELATIVE pidl,
+ IBindCtx *pbc,
+ REFIID riid,
+ void **ppv);
+
+ HRESULT STDMETHODCALLTYPE CompareIDs(LPARAM lParam,
+ PCUIDLIST_RELATIVE pidl1,
+ PCUIDLIST_RELATIVE pidl2);
+
+ HRESULT STDMETHODCALLTYPE CreateViewObject(HWND hwndOwner,
+ REFIID riid,
+ void **ppv);
+
+ HRESULT STDMETHODCALLTYPE GetAttributesOf(UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
+ SFGAOF *rgfInOut);
+
+ HRESULT STDMETHODCALLTYPE GetUIObjectOf(HWND hwndOwner,
+ UINT cidl,
+ PCUITEMID_CHILD_ARRAY apidl,
+ REFIID riid,
+ UINT *rgfReserved,
+ void **ppv);
+
+ HRESULT STDMETHODCALLTYPE GetDisplayNameOf(PCUITEMID_CHILD pidl,
+ SHGDNF uFlags,
+ STRRET *pName);
+
+ HRESULT STDMETHODCALLTYPE SetNameOf(HWND hwnd,
+ PCUITEMID_CHILD pidl,
+ LPCWSTR pszName,
+ SHGDNF uFlags,
+ PITEMID_CHILD *ppidlOut);
+private:
+ ULONG m_lRef;
+};
+#endif // GPGSHELLFOLDER_H
diff --git a/src/util/debug.h b/src/util/debug.h
index e68fca4..5d6257a 100644
--- a/src/util/debug.h
+++ b/src/util/debug.h
@@ -1,29 +1,31 @@
#ifndef GPG4WIN_DEBUG_H
#define GPG4WIN_DEBUG_H
/* Copyright (C) 2018 by Andre Heinecke <aheinecke@gnupg.com>
*
* This file is Free Software under the GNU GPL (v>=2)
* and comes with ABSOLUTELY NO WARRANTY!
* See LICENSE.txt for details.
*/
#include <gpg-error.h>
const char *log_srcname (const char *s);
#define SRCNAME log_srcname (__FILE__)
#define log_debug(format, ...) \
gpgrt_log_debug("%s:%s: " format, SRCNAME, __func__, ##__VA_ARGS__)
#define STRANGEPOINT log_debug ("%s:%s:%d:UNEXPECTED", \
__LINE__);
+#define TRACEPOINT log_debug ("%s:%s:%d:TRACE");
+
#define GUID_FMT "{%08lX-%04hX-%04hX-%02hX%02hX-%02hX%02hX%02hX%02hX%02hX%02hX}"
#define GUID_ARG(x) (x).Data1, (x).Data2, (x).Data3, (x).Data4[0], \
(x).Data4[1], (x).Data4[2], (x).Data4[3], (x).Data4[4], \
(x).Data4[5], (x).Data4[6], (x).Data4[7]
#endif // GPG4WIN_DEBUG_H

File Metadata

Mime Type
text/x-diff
Expires
Fri, Dec 5, 5:50 PM (1 d, 20 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
21/fa/9cbcbfc575901ffac6f42a10acd9

Event Timeline