Skip to content

Commit

Permalink
moved SharedParameters to its own file
Browse files Browse the repository at this point in the history
made members private, added functions
added logging when changing parameters
  • Loading branch information
isanae committed Nov 1, 2019
1 parent 4c50507 commit 7e21b40
Show file tree
Hide file tree
Showing 11 changed files with 468 additions and 187 deletions.
103 changes: 103 additions & 0 deletions include/sharedparameters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#pragma once

#include "usvfsparameters.h"
#include "dllimport.h"
#include <shared_memory.h>

#include <string>
#include <boost/interprocess/containers/string.hpp>
#include <boost/interprocess/containers/flat_set.hpp>
#include <boost/interprocess/containers/slist.hpp>

namespace usvfs
{

class ForcedLibrary
{
public:
ForcedLibrary(
const std::string& processName, const std::string& libraryPath,
const shared::VoidAllocatorT &allocator);

std::string processName() const;
std::string libraryPath() const;

private:
shared::StringT m_processName;
shared::StringT m_libraryPath;
};


class DLLEXPORT SharedParameters
{
public:
SharedParameters() = delete;
SharedParameters(const SharedParameters &reference) = delete;
SharedParameters &operator=(const SharedParameters &reference) = delete;

SharedParameters(const usvfsParameters& reference,
const shared::VoidAllocatorT &allocator);

usvfsParameters makeLocal() const;

std::string instanceName() const;
std::string currentSHMName() const;
std::string currentInverseSHMName() const;
void setSHMNames(const std::string& current, const std::string& inverse);

void setDebugParameters(
LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath,
std::chrono::milliseconds delayProcess);

std::size_t userConnected();
std::size_t userDisconnected();
std::size_t userCount();

std::size_t registeredProcessCount() const;
std::vector<DWORD> registeredProcesses() const;
void registerProcess(DWORD pid);
void unregisterProcess(DWORD pid);

void blacklistExecutable(const std::string& name);
void clearExecutableBlacklist();
bool executableBlacklisted(const std::string& app, const std::string& cmd) const;

void addForcedLibrary(const std::string& process, const std::string& path);
std::vector<std::string> forcedLibraries(const std::string& processName);
void clearForcedLibraries();

private:
using StringAllocatorT =
shared::VoidAllocatorT::rebind<shared::StringT>::other;

using DWORDAllocatorT = shared::VoidAllocatorT::rebind<DWORD>::other;

using ForcedLibraryAllocatorT =
shared::VoidAllocatorT::rebind<ForcedLibrary>::other;


using ProcessBlacklist = boost::container::flat_set<
shared::StringT, std::less<shared::StringT>, StringAllocatorT>;

using ProcessList = boost::container::flat_set<
DWORD, std::less<DWORD>, DWORDAllocatorT>;

using ForcedLibraries = boost::container::slist<
ForcedLibrary, ForcedLibraryAllocatorT>;


shared::StringT m_instanceName;
shared::StringT m_currentSHMName;
shared::StringT m_currentInverseSHMName;
bool m_debugMode;
LogLevel m_logLevel;
CrashDumpsType m_crashDumpsType;
shared::StringT m_crashDumpsPath;
std::chrono::milliseconds m_delayProcess;
uint32_t m_userCount;
ProcessBlacklist m_processBlacklist;
ProcessList m_processList;
ForcedLibraries m_forcedLibraries;
};

} // namespace
3 changes: 1 addition & 2 deletions include/usvfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,7 @@ DLLEXPORT void WINAPI USVFSInitParameters(USVFSParameters *parameters,
[[deprecated("deprecated, use usvfsUpdateParameters()")]]
DLLEXPORT void WINAPI USVFSUpdateParams(LogLevel level, CrashDumpsType type);

// the only information used from the parameters are the crash dump type, log
// level and process delay
// the instance and shm names are not updated
//
DLLEXPORT void WINAPI usvfsUpdateParameters(usvfsParameters* p);

Expand Down
3 changes: 3 additions & 0 deletions include/usvfsparameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,7 @@ DLLEXPORT void usvfsSetCrashDumpType(usvfsParameters* p, CrashDumpsType type);
DLLEXPORT void usvfsSetCrashDumpPath(usvfsParameters* p, const char* path);
DLLEXPORT void usvfsSetProcessDelay(usvfsParameters* p, int milliseconds);

DLLEXPORT const char* usvfsLogLevelToString(LogLevel lv);
DLLEXPORT const char* usvfsCrashDumpTypeToString(CrashDumpsType t);

}
171 changes: 75 additions & 96 deletions src/usvfs_dll/hookcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ along with usvfs. If not, see <http://www.gnu.org/licenses/>.
#include "usvfs.h"
#include "hookcallcontext.h"
#include <winapi.h>
#include <sharedparameters.h>
#include <usvfsparameters.h>
#include <shared_memory.h>
#include "loghelpers.h"
#include <boost/algorithm/string/predicate.hpp>

namespace bi = boost::interprocess;
using usvfs::shared::SharedMemoryT;
Expand Down Expand Up @@ -56,35 +56,24 @@ void printBuffer(const char *buffer, size_t size)
}


usvfsParameters SharedParameters::makeLocal() const
{
return usvfsParameters(
instanceName.c_str(),
currentSHMName.c_str(),
currentInverseSHMName.c_str(),
debugMode, logLevel, crashDumpsType,
crashDumpsPath.c_str(),
delayProcess.count());
}


HookContext::HookContext(const usvfsParameters& params, HMODULE module)
: m_ConfigurationSHM(bi::open_or_create, params.instanceName, 8192)
, m_Parameters(retrieveParameters(params))
, m_Tree(m_Parameters->currentSHMName.c_str(), 65536)
, m_InverseTree(m_Parameters->currentInverseSHMName.c_str(), 65536)
, m_Tree(m_Parameters->currentSHMName(), 65536)
, m_InverseTree(m_Parameters->currentInverseSHMName(), 65536)
, m_DebugMode(params.debugMode)
, m_DLLModule(module)
{
if (s_Instance != nullptr) {
throw std::runtime_error("singleton duplicate instantiation (HookContext)");
}

++m_Parameters->userCount;
const auto userCount = m_Parameters->userConnected();

spdlog::get("usvfs")->debug("context current shm: {0} (now {1} connections)",
m_Parameters->currentSHMName.c_str(),
m_Parameters->userCount);
spdlog::get("usvfs")->debug(
"context current shm: {0} (now {1} connections)",
m_Parameters->currentSHMName(), userCount);

s_Instance = this;

Expand All @@ -102,34 +91,41 @@ void HookContext::remove(const char *instanceName)
HookContext::~HookContext()
{
spdlog::get("usvfs")->info("releasing hook context");

s_Instance = nullptr;
const auto userCount = m_Parameters->userDisconnected();

if (--m_Parameters->userCount == 0) {
spdlog::get("usvfs")
->info("removing tree {}", m_Parameters->instanceName.c_str());
bi::shared_memory_object::remove(m_Parameters->instanceName.c_str());
if (userCount == 0) {
spdlog::get("usvfs")->info("removing tree {}", m_Parameters->instanceName());
bi::shared_memory_object::remove(m_Parameters->instanceName().c_str());
} else {
spdlog::get("usvfs")->info("{} users left", m_Parameters->userCount);
spdlog::get("usvfs")->info("{} users left", userCount);
}
}

SharedParameters *HookContext::retrieveParameters(const usvfsParameters& params)
{
std::pair<SharedParameters *, SharedMemoryT::size_type> res
= m_ConfigurationSHM.find<SharedParameters>("parameters");

if (res.first == nullptr) {
// not configured yet
spdlog::get("usvfs")->info("create config in {}", ::GetCurrentProcessId());

res.first = m_ConfigurationSHM.construct<SharedParameters>("parameters")(
params, VoidAllocatorT(m_ConfigurationSHM.get_segment_manager()));

if (res.first == nullptr) {
USVFS_THROW_EXCEPTION(bi::bad_alloc());
}
} else {
spdlog::get("usvfs")
->info("access existing config in {}", ::GetCurrentProcessId());
spdlog::get("usvfs")->info(
"access existing config in {}", ::GetCurrentProcessId());
}
spdlog::get("usvfs")->info("{} processes - {}", res.first->processList.size(), (int)res.first->logLevel);

spdlog::get("usvfs")->info(
"{} processes", res.first->registeredProcessCount());

return res.first;
}

Expand All @@ -150,25 +146,17 @@ HookContext::Ptr HookContext::writeAccess(const char*)
return Ptr(s_Instance, unlock);
}

void HookContext::setLogLevel(LogLevel level)
{
m_Parameters->logLevel = level;
}

void HookContext::setCrashDumpsType(CrashDumpsType type)
void HookContext::setDebugParameters(
LogLevel level, CrashDumpsType dumpType, const std::string& dumpPath,
std::chrono::milliseconds delayProcess)
{
m_Parameters->crashDumpsType = type;
}

void HookContext::setDelayProcess(std::chrono::milliseconds delay)
{
m_Parameters->delayProcess = delay;
m_Parameters->setDebugParameters(level, dumpType, dumpPath, delayProcess);
}

void HookContext::updateParameters() const
{
m_Parameters->currentSHMName = m_Tree.shmName().c_str();
m_Parameters->currentInverseSHMName = m_InverseTree.shmName().c_str();
m_Parameters->setSHMNames(m_Tree.shmName(), m_InverseTree.shmName());
}

usvfsParameters HookContext::callParameters() const
Expand All @@ -185,90 +173,81 @@ std::wstring HookContext::dllPath() const

void HookContext::registerProcess(DWORD pid)
{
m_Parameters->processList.insert(pid);
m_Parameters->registerProcess(pid);
}

void HookContext::unregisterCurrentProcess()
{
m_Parameters->unregisterProcess(::GetCurrentProcessId());
}

std::vector<DWORD> HookContext::registeredProcesses() const
{
return m_Parameters->registeredProcesses();
}

void HookContext::blacklistExecutable(const std::wstring &executableName)
void HookContext::blacklistExecutable(const std::wstring& wexe)
{
m_Parameters->processBlacklist.insert(shared::StringT(
shared::string_cast<std::string>(executableName, shared::CodePage::UTF8)
.c_str(),
m_Parameters->processBlacklist.get_allocator()));
const auto exe = shared::string_cast<std::string>(
wexe, shared::CodePage::UTF8);

spdlog::get("usvfs")->debug("blacklisting '{}'", exe);
m_Parameters->blacklistExecutable(exe);
}

void HookContext::clearExecutableBlacklist()
{
m_Parameters->processBlacklist.clear();
spdlog::get("usvfs")->debug("clearing blacklist");
m_Parameters->clearExecutableBlacklist();
}

BOOL HookContext::executableBlacklisted(LPCWSTR lpApplicationName, LPCWSTR lpCommandLine) const
BOOL HookContext::executableBlacklisted(LPCWSTR wapp, LPCWSTR wcmd) const
{
BOOL blacklisted = FALSE;

if (lpApplicationName) {
std::string appName = ush::string_cast<std::string>(lpApplicationName, ush::CodePage::UTF8);
for (shared::StringT item : m_Parameters->processBlacklist) {
if (boost::algorithm::iends_with(appName, std::string(item.data(), item.size()))) {
spdlog::get("usvfs")->info("application {} is blacklisted", appName);
blacklisted = TRUE;
break;
}
}
std::string app;
if (wapp) {
app = ush::string_cast<std::string>(wapp, ush::CodePage::UTF8);
}

if (lpCommandLine) {
std::string cmdLine = ush::string_cast<std::string>(lpCommandLine, ush::CodePage::UTF8);
for (shared::StringT item : m_Parameters->processBlacklist) {
if (boost::algorithm::icontains(cmdLine, std::string(item.data(), item.size()))) {
spdlog::get("usvfs")->info("command line {} is blacklisted", cmdLine);
blacklisted = TRUE;
break;
}
}
std::string cmd;
if (wcmd) {
cmd = ush::string_cast<std::string>(wcmd, ush::CodePage::UTF8);
}

return blacklisted;
return m_Parameters->executableBlacklisted(app, cmd);
}

void HookContext::forceLoadLibrary(const std::wstring &processName, const std::wstring &libraryPath)
void HookContext::forceLoadLibrary(
const std::wstring& wprocess, const std::wstring& wpath)
{
m_Parameters->forcedLibraries.push_front(ForcedLibrary(
shared::string_cast<std::string>(processName, shared::CodePage::UTF8).c_str(),
shared::string_cast<std::string>(libraryPath, shared::CodePage::UTF8).c_str(),
m_Parameters->forcedLibraries.get_allocator()));
const auto process = shared::string_cast<std::string>(
wprocess, shared::CodePage::UTF8);

const auto path = shared::string_cast<std::string>(
wpath, shared::CodePage::UTF8);

spdlog::get("usvfs")->debug(
"adding forced library '{}' for process '{}'", path, process);

m_Parameters->addForcedLibrary(process, path);
}

void HookContext::clearLibraryForceLoads()
{
m_Parameters->forcedLibraries.clear();
spdlog::get("usvfs")->debug("clearing forced libraries");
m_Parameters->clearForcedLibraries();
}

std::vector<std::wstring> HookContext::librariesToForceLoad(const std::wstring &processName)
{
std::vector<std::wstring> results;
for (auto library : m_Parameters->forcedLibraries) {
std::string processNameString = shared::string_cast<std::string>(processName, shared::CodePage::UTF8);
if (stricmp(processNameString.c_str(), library.processName.c_str()) == 0) {
std::wstring libraryPathString = shared::string_cast<std::wstring>(library.libraryPath.c_str(), shared::CodePage::UTF8);
results.push_back(libraryPathString);
}
}
return results;
}
const auto v = m_Parameters->forcedLibraries(
shared::string_cast<std::string>(processName, shared::CodePage::UTF8));

void HookContext::unregisterCurrentProcess()
{
auto iter = m_Parameters->processList.find(::GetCurrentProcessId());
m_Parameters->processList.erase(iter);
}

std::vector<DWORD> HookContext::registeredProcesses() const
{
std::vector<DWORD> result;
for (DWORD procId : m_Parameters->processList) {
result.push_back(procId);
std::vector<std::wstring> wv;
for (const auto& s : v) {
wv.push_back(shared::string_cast<std::wstring>(s, shared::CodePage::UTF8));
}
return result;

return wv;
}

void HookContext::registerDelayed(std::future<int> delayed)
Expand Down
Loading

0 comments on commit 7e21b40

Please sign in to comment.