aboutsummaryrefslogtreecommitdiff
path: root/libs/archive/src/unknown_impl.h
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-11 02:37:39 -0600
commit7ee008e150bc5bcf76082d726f719ee0fdfda982 (patch)
tree27fb39be241fdb5ac2734c574de678977d1856d0 /libs/archive/src/unknown_impl.h
Fluorine Manager: full Linux port of Mod Organizer 2
Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'libs/archive/src/unknown_impl.h')
-rw-r--r--libs/archive/src/unknown_impl.h191
1 files changed, 191 insertions, 0 deletions
diff --git a/libs/archive/src/unknown_impl.h b/libs/archive/src/unknown_impl.h
new file mode 100644
index 0000000..78e9f4a
--- /dev/null
+++ b/libs/archive/src/unknown_impl.h
@@ -0,0 +1,191 @@
+/*
+Mod Organizer archive handling
+
+Copyright (C) 2012 Sebastian Herbord, 2020 MO2 Team. All rights reserved.
+
+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 3 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
+*/
+
+#ifndef UNKNOWN_IMPL_H
+#define UNKNOWN_IMPL_H
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <Windows.h>
+#else
+#include <Common/MyWindows.h>
+#include <atomic>
+#endif
+
+/* This implements a common way of creating classes which implement one or more
+ * COM interfaces.
+ *
+ * Your implementaton should be something like this
+ *
+ * class MyImplementation :
+ * public interface1,
+ * public interface2 //etc to taste
+ * {
+ * UNKNOWN_1_INTERFACE(interface1);
+ * or UNKNOWN_2_INTERFACE(interface1, interface2); etc
+ *
+ * It would probably be possible to do something very magic with macros
+ * that allowed you to do
+ * class My_Implmentation : UNKNOWN_IMPL_n(interface1, ...)
+ *
+ * that did all the above for you, but I can't see how to maintain the braces
+ * in order to make the class declaration look nice.
+ *
+ * You might ask why I have e-implemented this from the 7-zip stuff (sort of).
+ *
+ * Well,
+ *
+ * Firstly, the 7zip macros are slightly buggy (they don't null the outpointer
+ * if the interface isn't found), and they aren't thread safe.
+ *
+ * Secondly, although 7-zip has a requirement to run on platforms other than
+ * windows, we don't. So I changed this to use the Com functionality supplied
+ * by windows, which (potentially) has better debugging facilities
+ *
+ * Thirdly, this removes a number of dependencies on 7-zip source which aren't
+ * really part of the API
+ */
+
+#ifdef _WIN32
+
+/* Do not use these macros, use the ones at the bottom */
+#define UNKNOWN__INTERFACE_BEGIN \
+public: \
+ STDMETHOD_(ULONG, AddRef)() \
+ { \
+ return ::InterlockedIncrement(&m_RefCount__); \
+ } \
+ \
+ STDMETHOD_(ULONG, Release)() \
+ { \
+ ULONG res = ::InterlockedDecrement(&m_RefCount__); \
+ if (res == 0) { \
+ delete this; \
+ } \
+ return res; \
+ } \
+ \
+ STDMETHOD(QueryInterface)(REFGUID iid, void** outObject) \
+ { \
+ if (iid == IID_IUnknown) {
+
+#define UNKNOWN__INTERFACE_UNKNOWN(interface) \
+ *outObject = static_cast<IUnknown*>(static_cast<interface*>(this)); \
+ }
+
+#define UNKNOWN__INTERFACE_NAME(interface) \
+ else if (iid == IID_##interface) \
+ { \
+ *outObject = static_cast<interface*>(this); \
+ }
+
+#define UNKNOWN__INTERFACE_END \
+ else \
+ { \
+ *outObject = nullptr; \
+ return E_NOINTERFACE; \
+ } \
+ AddRef(); \
+ return S_OK; \
+ } \
+ \
+private: \
+ ULONG m_RefCount__ = 0
+
+#else // Linux
+
+/* Do not use these macros, use the ones at the bottom */
+#define UNKNOWN__INTERFACE_BEGIN \
+public: \
+ STDMETHOD_(ULONG, AddRef)() \
+ { \
+ return ++m_RefCount__; \
+ } \
+ \
+ STDMETHOD_(ULONG, Release)() \
+ { \
+ ULONG res = --m_RefCount__; \
+ if (res == 0) { \
+ delete this; \
+ } \
+ return res; \
+ } \
+ \
+ STDMETHOD(QueryInterface)(REFGUID iid, void** outObject) \
+ { \
+ if (iid == IID_IUnknown) {
+
+#define UNKNOWN__INTERFACE_UNKNOWN(interface) \
+ *outObject = static_cast<IUnknown*>(static_cast<interface*>(this)); \
+ }
+
+#define UNKNOWN__INTERFACE_NAME(interface) \
+ else if (iid == IID_##interface) \
+ { \
+ *outObject = static_cast<interface*>(this); \
+ }
+
+#define UNKNOWN__INTERFACE_END \
+ else \
+ { \
+ *outObject = nullptr; \
+ return E_NOINTERFACE; \
+ } \
+ AddRef(); \
+ return S_OK; \
+ } \
+ \
+private: \
+ std::atomic<ULONG> m_RefCount__{0}
+
+#endif // _WIN32
+
+/* These are the macros you should be using */
+#define UNKNOWN_1_INTERFACE(interface) \
+ UNKNOWN__INTERFACE_BEGIN \
+ UNKNOWN__INTERFACE_UNKNOWN(interface) \
+ UNKNOWN__INTERFACE_NAME(interface) \
+ UNKNOWN__INTERFACE_END
+
+#define UNKNOWN_2_INTERFACE(interface1, interface2) \
+ UNKNOWN__INTERFACE_BEGIN \
+ UNKNOWN__INTERFACE_UNKNOWN(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface2) \
+ UNKNOWN__INTERFACE_END
+
+#define UNKNOWN_3_INTERFACE(interface1, interface2, interface3) \
+ UNKNOWN__INTERFACE_BEGIN \
+ UNKNOWN__INTERFACE_UNKNOWN(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface2) \
+ UNKNOWN__INTERFACE_NAME(interface3) \
+ UNKNOWN__INTERFACE_END
+
+#define UNKNOWN_4_INTERFACE(interface1, interface2, interface3, interface4) \
+ UNKNOWN__INTERFACE_BEGIN \
+ UNKNOWN__INTERFACE_UNKNOWN(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface1) \
+ UNKNOWN__INTERFACE_NAME(interface2) \
+ UNKNOWN__INTERFACE_NAME(interface3) \
+ UNKNOWN__INTERFACE_NAME(interface4) \
+ UNKNOWN__INTERFACE_END
+
+#endif // UNKNOWN_IMPL_H