aboutsummaryrefslogtreecommitdiff
path: root/libs/usvfs/src/usvfs_dll/hookcontext.h
diff options
context:
space:
mode:
Diffstat (limited to 'libs/usvfs/src/usvfs_dll/hookcontext.h')
-rw-r--r--libs/usvfs/src/usvfs_dll/hookcontext.h224
1 files changed, 224 insertions, 0 deletions
diff --git a/libs/usvfs/src/usvfs_dll/hookcontext.h b/libs/usvfs/src/usvfs_dll/hookcontext.h
new file mode 100644
index 0000000..c9f6eb1
--- /dev/null
+++ b/libs/usvfs/src/usvfs_dll/hookcontext.h
@@ -0,0 +1,224 @@
+/*
+Userspace Virtual Filesystem
+
+Copyright (C) 2015 Sebastian Herbord. All rights reserved.
+
+This file is part of usvfs.
+
+usvfs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+usvfs 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 General Public License
+along with usvfs. If not, see <http://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "dllimport.h"
+#include "redirectiontree.h"
+#include "semaphore.h"
+#include "tree_container.h"
+#include <directory_tree.h>
+#include <exceptionex.h>
+#include <usvfsparameters.h>
+#include <usvfsparametersprivate.h>
+#include <winapi.h>
+
+namespace usvfs
+{
+
+class DLLEXPORT SharedParameters;
+
+/**
+ * @brief context available to hooks. This is protected by a many-reader
+ * single-writer mutex
+ */
+class HookContext
+{
+
+public:
+ typedef std::unique_ptr<const HookContext, void (*)(const HookContext*)> ConstPtr;
+ typedef std::unique_ptr<HookContext, void (*)(HookContext*)> Ptr;
+ typedef unsigned int DataIDT;
+
+public:
+ HookContext(const usvfsParameters& params, HMODULE module);
+
+ HookContext(const HookContext& reference) = delete;
+
+ DLLEXPORT ~HookContext();
+
+ HookContext& operator=(const HookContext& reference) = delete;
+
+ static void remove(const char* instance);
+
+ /**
+ * @brief get read access to the context.
+ * @return smart ptr to the context. mutex will automatically be released when
+ * this leaves scope
+ */
+ static ConstPtr readAccess(const char* source);
+
+ /**
+ * @brief get write access to the context.
+ * @return smart ptr to the context. mutex will automatically be released when
+ * this leaves scope
+ */
+ static Ptr writeAccess(const char* source);
+
+ /**
+ * @return table containing file redirection information
+ */
+ RedirectionTreeContainer& redirectionTable() { return m_Tree; }
+
+ /**
+ * @return table containing file redirection information
+ */
+ const RedirectionTreeContainer& redirectionTable() const { return m_Tree; }
+
+ RedirectionTreeContainer& inverseTable() { return m_InverseTree; }
+
+ const RedirectionTreeContainer& inverseTable() const { return m_InverseTree; }
+
+ /**
+ * @return the parameters passed in on dll initialisation
+ */
+ usvfsParameters callParameters() const;
+
+ /**
+ * @return path to the calling library itself
+ */
+ std::wstring dllPath() const;
+
+ /**
+ * @brief get access to custom data
+ * @note the caller gains write access to the data, independent on the lock on
+ * the context
+ * as a whole. The caller himself has to ensure thread safety
+ */
+ template <typename T>
+ T& customData(DataIDT id) const
+ {
+ auto iter = m_CustomData.find(id);
+ if (iter == m_CustomData.end()) {
+ iter = m_CustomData.insert(std::make_pair(id, T())).first;
+ }
+ // std::map is supposed to not invalidate any iterators when elements are
+ // added
+ // so it should be safe to return a pointer here
+ T* res = boost::any_cast<T>(&iter->second);
+ return *res;
+ }
+
+ void registerProcess(DWORD pid);
+ void unregisterCurrentProcess();
+ std::vector<DWORD> registeredProcesses() const;
+
+ void blacklistExecutable(const std::wstring& executableName);
+ void clearExecutableBlacklist();
+ BOOL executableBlacklisted(LPCWSTR lpApplicationName, LPCWSTR lpCommandLine) const;
+
+ void addSkipFileSuffix(const std::wstring& fileSuffix);
+ void clearSkipFileSuffixes();
+ std::vector<std::string> skipFileSuffixes() const;
+
+ void addSkipDirectory(const std::wstring& directory);
+ void clearSkipDirectories();
+ std::vector<std::string> skipDirectories() const;
+
+ void forceLoadLibrary(const std::wstring& processName,
+ const std::wstring& libraryPath);
+ void clearLibraryForceLoads();
+ std::vector<std::wstring> librariesToForceLoad(const std::wstring& processName);
+
+ void setDebugParameters(LogLevel level, CrashDumpsType dumpType,
+ const std::string& dumpPath,
+ std::chrono::milliseconds delayProcess);
+
+ void updateParameters() const;
+
+ void registerDelayed(std::future<int> delayed);
+
+ std::vector<std::future<int>>& delayed();
+
+private:
+ static void unlock(HookContext* instance);
+ static void unlockShared(const HookContext* instance);
+
+ SharedParameters* retrieveParameters(const usvfsParameters& params);
+
+private:
+ static HookContext* s_Instance;
+
+ shared::SharedMemoryT m_ConfigurationSHM;
+ SharedParameters* m_Parameters{nullptr};
+ RedirectionTreeContainer m_Tree;
+ RedirectionTreeContainer m_InverseTree;
+
+ std::vector<std::future<int>> m_Futures;
+
+ mutable std::map<DataIDT, boost::any> m_CustomData;
+
+ HMODULE m_DLLModule;
+
+ // mutable std::recursive_mutex m_Mutex;
+ mutable RecursiveBenaphore m_Mutex;
+};
+
+} // namespace usvfs
+
+extern "C" DLLEXPORT usvfs::HookContext* WINAPI
+usvfsCreateHookContext(const usvfsParameters& params, HMODULE module);
+
+class PreserveGetLastError
+{
+public:
+ PreserveGetLastError() : m_err(GetLastError()) {}
+ ~PreserveGetLastError() { SetLastError(m_err); }
+
+private:
+ DWORD m_err;
+};
+
+// declare an identifier that is guaranteed to be unique across the application
+#define DATA_ID(name) static const usvfs::HookContext::DataIDT name = __COUNTER__
+
+// set of macros. These ensure a call context is created but most of all these
+// ensure exceptions are caught.
+
+#define READ_CONTEXT() HookContext::readAccess(__MYFUNC__)
+#define WRITE_CONTEXT() HookContext::writeAccess(__MYFUNC__)
+
+#define HOOK_START_GROUP(group) \
+ try { \
+ HookCallContext callContext(group);
+
+#define HOOK_START \
+ try { \
+ HookCallContext callContext;
+
+#define HOOK_END \
+ } \
+ catch (const std::exception& e) \
+ { \
+ spdlog::get("usvfs")->error("exception in {0}: {1}", __MYFUNC__, e.what()); \
+ logExtInfo(e); \
+ }
+
+#define HOOK_ENDP(param) \
+ } \
+ catch (const std::exception& e) \
+ { \
+ spdlog::get("usvfs")->error("exception in {0} ({1}): {2}", __MYFUNC__, param, \
+ e.what()); \
+ logExtInfo(e); \
+ }
+
+#define PRE_REALCALL callContext.restoreLastError();
+#define POST_REALCALL callContext.updateLastError();