diff options
Diffstat (limited to 'opentrack-compat')
-rw-r--r-- | opentrack-compat/CMakeLists.txt | 3 | ||||
-rw-r--r-- | opentrack-compat/camera-names.cpp | 113 | ||||
-rw-r--r-- | opentrack-compat/camera-names.hpp | 22 | ||||
-rw-r--r-- | opentrack-compat/compat-export.hpp | 15 | ||||
-rw-r--r-- | opentrack-compat/compat-import.hpp | 15 | ||||
-rw-r--r-- | opentrack-compat/export.hpp | 22 | ||||
-rw-r--r-- | opentrack-compat/import.hpp | 15 | ||||
-rw-r--r-- | opentrack-compat/options.cpp | 199 | ||||
-rw-r--r-- | opentrack-compat/options.hpp | 325 | ||||
-rw-r--r-- | opentrack-compat/shm.cpp | 121 | ||||
-rw-r--r-- | opentrack-compat/shm.h | 30 |
11 files changed, 845 insertions, 35 deletions
diff --git a/opentrack-compat/CMakeLists.txt b/opentrack-compat/CMakeLists.txt index a92f4f31..8dba67e2 100644 --- a/opentrack-compat/CMakeLists.txt +++ b/opentrack-compat/CMakeLists.txt @@ -1,4 +1,5 @@ -opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT) +opentrack_boilerplate(opentrack-compat NO-COMPAT NO-LINKER-SCRIPT LINKAGE) if(NOT WIN32 AND NOT APPLE) target_link_libraries(opentrack-compat rt) endif() +link_with_dinput8(opentrack-compat) diff --git a/opentrack-compat/camera-names.cpp b/opentrack-compat/camera-names.cpp new file mode 100644 index 00000000..72bcf41a --- /dev/null +++ b/opentrack-compat/camera-names.cpp @@ -0,0 +1,113 @@ +#include "camera-names.hpp" + +#if defined(OPENTRACK_API) && defined(_WIN32) +# define NO_DSHOW_STRSAFE +# include <windows.h> +# include <dshow.h> +#endif + +#if defined(OPENTRACK_API) && (defined(__unix) || defined(__linux) || defined(__APPLE__)) +# include <unistd.h> +#endif + +#ifdef __linux +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/videodev2.h> +#include <cerrno> +#endif + +#include <QDebug> + +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name) +{ + auto list = get_camera_names(); + int ret = list.indexOf(name); + if (ret < 0) + ret = 0; + return ret; +} + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names() { + QList<QString> ret; +#if defined(_WIN32) + // Create the System Device Enumerator. + HRESULT hr; + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); + if (FAILED(hr)) + qDebug() << "failed CoInitializeEx" << hr; + ICreateDevEnum *pSysDevEnum = NULL; + hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pSysDevEnum); + if (FAILED(hr)) + { + qDebug() << "failed CLSID_SystemDeviceEnum" << hr; + return ret; + } + // Obtain a class enumerator for the video compressor category. + IEnumMoniker *pEnumCat = NULL; + hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEnumCat, 0); + + if (hr == S_OK) { + // Enumerate the monikers. + IMoniker *pMoniker = NULL; + ULONG cFetched; + while (pEnumCat->Next(1, &pMoniker, &cFetched) == S_OK) { + IPropertyBag *pPropBag; + hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pPropBag); + if (SUCCEEDED(hr)) { + // To retrieve the filter's friendly name, do the following: + VARIANT varName; + VariantInit(&varName); + hr = pPropBag->Read(L"FriendlyName", &varName, 0); + if (SUCCEEDED(hr)) + { + // Display the name in your UI somehow. + QString str((QChar*)varName.bstrVal, wcslen(varName.bstrVal)); + ret.append(str); + } + VariantClear(&varName); + + ////// To create an instance of the filter, do the following: + ////IBaseFilter *pFilter; + ////hr = pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, + //// (void**)&pFilter); + // Now add the filter to the graph. + //Remember to release pFilter later. + pPropBag->Release(); + } + pMoniker->Release(); + } + pEnumCat->Release(); + } + else + qDebug() << "failed CLSID_VideoInputDeviceCategory" << hr; + + pSysDevEnum->Release(); +#endif +#ifdef __linux + for (int i = 0; i < 16; i++) { + char buf[128]; + sprintf(buf, "/dev/video%d", i); + if (access(buf, F_OK) == 0) + ret.append(buf); + else + continue; + + if (access(buf, R_OK | W_OK) == 0) { + int fd = open(buf, O_RDONLY); + if (fd == -1) + continue; + struct v4l2_capability video_cap; + if(ioctl(fd, VIDIOC_QUERYCAP, &video_cap) == -1) + { + qDebug() << "VIDIOC_QUERYCAP" << errno; + close(fd); + continue; + } + ret[ret.size()-1] = reinterpret_cast<const char*>(video_cap.card); + close(fd); + } + } +#endif + return ret; +}
\ No newline at end of file diff --git a/opentrack-compat/camera-names.hpp b/opentrack-compat/camera-names.hpp new file mode 100644 index 00000000..c2879000 --- /dev/null +++ b/opentrack-compat/camera-names.hpp @@ -0,0 +1,22 @@ +/* Copyright (c) 2014-2015, Stanislaw Halik <sthalik@misaki.pl> + + * Permission to use, copy, modify, and/or distribute this + * software for any purpose with or without fee is hereby granted, + * provided that the above copyright notice and this permission + * notice appear in all copies. + */ + +#pragma once + +#include <QList> +#include <QString> + +#ifdef BUILD_compat +# include "compat-export.hpp" +#else +# include "compat-import.hpp" +#endif + +OPENTRACK_COMPAT_EXPORT QList<QString> get_camera_names(); +OPENTRACK_COMPAT_EXPORT int camera_name_to_index(const QString &name); + diff --git a/opentrack-compat/compat-export.hpp b/opentrack-compat/compat-export.hpp new file mode 100644 index 00000000..2d6f1d3d --- /dev/null +++ b/opentrack-compat/compat-export.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +# ifdef _WIN32 +# define OPENTRACK_COMPAT_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_COMPAT_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +# else +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +# endif +#endif diff --git a/opentrack-compat/compat-import.hpp b/opentrack-compat/compat-import.hpp new file mode 100644 index 00000000..161ccc5d --- /dev/null +++ b/opentrack-compat/compat-import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_COMPAT_EXPORT +# ifdef _WIN32 +# define OPENTRACK_COMPAT_LINKAGE __declspec(dllimport) +# else +# define OPENTRACK_COMPAT_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_COMPAT_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_COMPAT_LINKAGE +# else +# define OPENTRACK_COMPAT_EXPORT OPENTRACK_COMPAT_LINKAGE +# endif +#endif diff --git a/opentrack-compat/export.hpp b/opentrack-compat/export.hpp index f0983b75..100950a0 100644 --- a/opentrack-compat/export.hpp +++ b/opentrack-compat/export.hpp @@ -1,13 +1,15 @@ #pragma once -#ifdef _WIN32 -# define OPENTRACK_LINKAGE __declspec(dllexport) -#else -# define OPENTRACK_LINKAGE -#endif +#ifndef OPENTRACK_EXPORT +# ifdef _WIN32 +# define OPENTRACK_LINKAGE __declspec(dllexport) +# else +# define OPENTRACK_LINKAGE +# endif -#ifndef _MSC_VER -# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE -#else -# define OPENTRACK_EXPORT OPENTRACK_LINKAGE -#endif
\ No newline at end of file +# ifndef _MSC_VER +# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +# else +# define OPENTRACK_EXPORT OPENTRACK_LINKAGE +# endif +#endif diff --git a/opentrack-compat/import.hpp b/opentrack-compat/import.hpp new file mode 100644 index 00000000..3747b141 --- /dev/null +++ b/opentrack-compat/import.hpp @@ -0,0 +1,15 @@ +#pragma once + +#ifndef OPENTRACK_EXPORT +# ifdef _WIN32 +# define OPENTRACK_LINKAGE __declspec(dllimport) +# else +# define OPENTRACK_LINKAGE +# endif + +# ifndef _MSC_VER +# define OPENTRACK_EXPORT __attribute__ ((visibility ("default"))) OPENTRACK_LINKAGE +# else +# define OPENTRACK_EXPORT OPENTRACK_LINKAGE +# endif +#endif diff --git a/opentrack-compat/options.cpp b/opentrack-compat/options.cpp new file mode 100644 index 00000000..550fec24 --- /dev/null +++ b/opentrack-compat/options.cpp @@ -0,0 +1,199 @@ +#include "options.hpp" + +namespace options +{ + +namespace detail +{ +OPENTRACK_COMPAT_EXPORT opt_singleton& singleton() +{ + static opt_singleton ret; + return ret; +} + +} + +group::group(const QString& name) : name(name) +{ + auto conf = ini_file(); + conf->beginGroup(name); + for (auto& k_ : conf->childKeys()) + { + auto tmp = k_.toUtf8(); + QString k(tmp); + kvs[k] = conf->value(k_); + } + conf->endGroup(); +} + +void group::save() +{ + auto s = ini_file(); + s->beginGroup(name); + for (auto& i : kvs) + s->setValue(i.first, i.second); + s->endGroup(); + s->sync(); +} + +void group::put(const QString &s, const QVariant &d) +{ + kvs[s] = d; +} + +bool group::contains(const QString &s) +{ + return kvs.count(s) != 0; +} + +QString group::ini_directory() +{ + const auto dirs = QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation); + if (dirs.size() == 0) + return ""; + if (QDir(dirs[0]).mkpath(OPENTRACK_ORG)) + return dirs[0] + "/" OPENTRACK_ORG; + return ""; +} + +QString group::ini_filename() +{ + QSettings settings(OPENTRACK_ORG); + return settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +QString group::ini_pathname() +{ + const auto dir = ini_directory(); + if (dir == "") + return ""; + QSettings settings(OPENTRACK_ORG); + return dir + "/" + settings.value(OPENTRACK_CONFIG_FILENAME_KEY, OPENTRACK_DEFAULT_CONFIG).toString(); +} + +const QStringList group::ini_list() +{ + const auto dirname = ini_directory(); + if (dirname == "") + return QStringList(); + QDir settings_dir(dirname); + return settings_dir.entryList( QStringList { "*.ini" } , QDir::Files, QDir::Name ); +} + +const mem<QSettings> group::ini_file() +{ + const auto pathname = ini_pathname(); + if (pathname != "") + return std::make_shared<QSettings>(ini_pathname(), QSettings::IniFormat); + return std::make_shared<QSettings>(); +} + +impl_bundle::impl_bundle(const QString &group_name) + : + mtx(QMutex::Recursive), + group_name(group_name), + saved(group_name), + transient(saved), + modified(false) +{} + +void impl_bundle::reload() +{ + { + QMutexLocker l(&mtx); + saved = group(group_name); + transient = saved; + modified = false; + } + emit reloading(); +} + +void impl_bundle::store_kv(const QString &name, const QVariant &datum) +{ + QMutexLocker l(&mtx); + + auto old = transient.get<QVariant>(name); + if (!transient.contains(name) || datum != old) + { + modified = true; + transient.put(name, datum); + } +} + +bool impl_bundle::contains(const QString &name) +{ + QMutexLocker l(&mtx); + return transient.contains(name); +} + +void impl_bundle::save() +{ + { + QMutexLocker l(&mtx); + modified = false; + saved = transient; + transient.save(); + } + emit saving(); +} + +bool impl_bundle::modifiedp() +{ + QMutexLocker l(&mtx); + return modified; +} + +namespace detail +{ + +pbundle opt_singleton::bundle(const opt_singleton::k &key) +{ + QMutexLocker l(&implsgl_mtx); + + if (implsgl_data.count(key) != 0) + { + auto shared = std::get<1>(implsgl_data[key]).lock(); + if (shared != nullptr) + return shared; + } + + qDebug() << "bundle +" << key; + + auto shr = std::make_shared<v>(key); + implsgl_data[key] = tt(cnt(1), shr); + return shr; +} + +void opt_singleton::bundle_decf(const opt_singleton::k &key) +{ + QMutexLocker l(&implsgl_mtx); + + if (--std::get<0>(implsgl_data[key]) == 0) + implsgl_data.erase(key); +} + +opt_singleton::opt_singleton() : implsgl_mtx(QMutex::Recursive) {} + +} + +opt_bundle::opt_bundle(const QString &group_name) + : impl_bundle(group_name) +{ +} + +opt_bundle::~opt_bundle() +{ + qDebug() << "bundle -" << group_name; + detail::singleton().bundle_decf(group_name); +} + +base_value::base_value(pbundle b, const QString &name) : b(b), self_name(name) {} + +opts::~opts() +{ + b->reload(); +} + +opts::opts(const QString &name) : b(bundle(name)) {} + +} diff --git a/opentrack-compat/options.hpp b/opentrack-compat/options.hpp new file mode 100644 index 00000000..a317a1f7 --- /dev/null +++ b/opentrack-compat/options.hpp @@ -0,0 +1,325 @@ +/* Copyright (c) 2013-2015 Stanislaw Halik + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#pragma once + +#include <memory> +#include <tuple> +#include <map> + +#include <QObject> +#include <QSettings> +#include <QString> +#include <QVariant> +#include <QMutex> +#include <QMutexLocker> +#include <QWidget> +#include <QComboBox> +#include <QCheckBox> +#include <QDoubleSpinBox> +#include <QSpinBox> +#include <QSlider> +#include <QLineEdit> +#include <QLabel> +#include <QTabWidget> +#include <QCoreApplication> +#include <QFileInfo> +#include <QDir> +#include <QStandardPaths> + +#include <cinttypes> + +#include <QDebug> + +#include <memory> + +#ifdef BUILD_compat +# include "compat-export.hpp" +#else +# include "compat-import.hpp" +#endif + +template<typename t> using mem = std::shared_ptr<t>; + +#define OPENTRACK_CONFIG_FILENAME_KEY "settings-filename" +#define OPENTRACK_DEFAULT_CONFIG "default.ini" +#define OPENTRACK_ORG "TrackHat opentrack-2.3" + +namespace options { + template<typename k, typename v> using map = std::map<k, v>; + + template<typename t> + // don't elide usages of the function, qvariant default implicit + // conversion results in nonsensical runtime behavior -sh + inline t qcruft_to_t (const QVariant& datum); + + template<> + inline int qcruft_to_t<int>(const QVariant& t) + { + return t.toInt(); + } + + template<> + inline QString qcruft_to_t<QString>(const QVariant& t) + { + return t.toString(); + } + + template<> + inline bool qcruft_to_t<bool>(const QVariant& t) + { + return t.toBool(); + } + + template<> + inline double qcruft_to_t<double>(const QVariant& t) + { + return t.toDouble(); + } + + template<> + inline QVariant qcruft_to_t<QVariant>(const QVariant& t) + { + return t; + } + + // snapshot of qsettings group at given time + class OPENTRACK_COMPAT_EXPORT group { + private: + map<QString, QVariant> kvs; + QString name; + public: + group(const QString& name); + void save(); + void put(const QString& s, const QVariant& d); + bool contains(const QString& s); + static QString ini_directory(); + static QString ini_filename(); + static QString ini_pathname(); + static const QStringList ini_list(); + static const mem<QSettings> ini_file(); + + template<typename t> + t get(const QString& k) + { + return qcruft_to_t<t>(kvs[k]); + } + }; + + class OPENTRACK_COMPAT_EXPORT impl_bundle : public QObject { + Q_OBJECT + protected: + QMutex mtx; + const QString group_name; + group saved; + group transient; + bool modified; + impl_bundle(const impl_bundle&) = delete; + impl_bundle& operator=(const impl_bundle&) = delete; + signals: + void reloading(); + void saving(); + public: + impl_bundle(const QString& group_name); + QString name() { return group_name; } + void reload(); + void store_kv(const QString& name, const QVariant& datum); + bool contains(const QString& name); + void save(); + bool modifiedp(); + + template<typename t> + t get(const QString& name) + { + QMutexLocker l(&mtx); + return transient.get<t>(name); + } + }; + + class opt_bundle; + + namespace detail + { + struct OPENTRACK_COMPAT_EXPORT opt_singleton + { + public: + using k = QString; + using v = opt_bundle; + using cnt = int; + using pbundle = std::shared_ptr<v>; + using tt = std::tuple<cnt, std::weak_ptr<v>>; + private: + QMutex implsgl_mtx; + map<k, tt> implsgl_data; + public: + opt_singleton(); + pbundle bundle(const k& key); + void bundle_decf(const k& key); + }; + + OPENTRACK_COMPAT_EXPORT opt_singleton& singleton(); + } + + using pbundle = std::shared_ptr<opt_bundle>; + + static inline pbundle bundle(const QString name) { return detail::singleton().bundle(name); } + + class OPENTRACK_COMPAT_EXPORT opt_bundle : public impl_bundle + { + public: + opt_bundle() : impl_bundle("i-have-no-name") {} + opt_bundle(const QString& group_name); + ~opt_bundle(); + }; + + class OPENTRACK_COMPAT_EXPORT base_value : public QObject + { + Q_OBJECT +#define DEFINE_SLOT(t) void setValue(t datum) { store(datum); } +#define DEFINE_SIGNAL(t) void valueChanged(t) + public: + QString name() { return self_name; } + base_value(pbundle b, const QString& name); + signals: + DEFINE_SIGNAL(double); + DEFINE_SIGNAL(int); + DEFINE_SIGNAL(bool); + DEFINE_SIGNAL(QString); + protected: + pbundle b; + QString self_name; + + template<typename t> + void store(const t& datum) + { + b->store_kv(self_name, datum); + emit valueChanged(static_cast<t>(datum)); + } + public slots: + DEFINE_SLOT(double) + DEFINE_SLOT(int) + DEFINE_SLOT(QString) + DEFINE_SLOT(bool) + public slots: + virtual void reload() = 0; + }; + + template<typename t> + class value : public base_value { + public: + t operator=(const t datum) + { + store(datum); + return datum; + } + static constexpr const Qt::ConnectionType DIRECT_CONNTYPE = Qt::DirectConnection; + static constexpr const Qt::ConnectionType SAFE_CONNTYPE = Qt::UniqueConnection; + value(pbundle b, const QString& name, t def) : base_value(b, name), def(def) + { + QObject::connect(b.get(), SIGNAL(reloading()), + this, SLOT(reload()), + DIRECT_CONNTYPE); + if (!b->contains(name) || b->get<QVariant>(name).type() == QVariant::Invalid) + *this = def; + } + value(pbundle b, const char* name, t def) : value(b, QString(name), def) {} + + operator t() const + { + return b->contains(self_name) ? b->get<t>(self_name) : def; + } + void reload() override { + *this = static_cast<t>(*this); + } + private: + t def; + }; + + struct OPENTRACK_COMPAT_EXPORT opts + { + pbundle b; + opts(const QString& name); + ~opts(); + }; + + template<typename t, typename q> + inline void tie_setting(value<t>&, q*); + + template<> + inline void tie_setting(value<int>& v, QComboBox* cb) + { + cb->setCurrentIndex(v); + v = cb->currentIndex(); + base_value::connect(cb, SIGNAL(currentIndexChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), cb, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<QString>& v, QComboBox* cb) + { + cb->setCurrentText(v); + v = cb->currentText(); + base_value::connect(cb, SIGNAL(currentTextChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(QString)), cb, SLOT(setCurrentText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<bool>& v, QCheckBox* cb) + { + cb->setChecked(v); + base_value::connect(cb, SIGNAL(toggled(bool)), &v, SLOT(setValue(bool)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(bool)), cb, SLOT(setChecked(bool)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<double>& v, QDoubleSpinBox* dsb) + { + dsb->setValue(v); + base_value::connect(dsb, SIGNAL(valueChanged(double)), &v, SLOT(setValue(double)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(double)), dsb, SLOT(setValue(double)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<int>& v, QSpinBox* sb) + { + sb->setValue(v); + base_value::connect(sb, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), sb, SLOT(setValue(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<int>& v, QSlider* sl) + { + sl->setValue(v); + v = sl->value(); + base_value::connect(sl, SIGNAL(valueChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), sl, SLOT(setValue(int)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<QString>& v, QLineEdit* le) + { + le->setText(v); + base_value::connect(le, SIGNAL(textChanged(QString)), &v, SLOT(setValue(QString)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(QString)),le, SLOT(setText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<QString>& v, QLabel* lb) + { + lb->setText(v); + base_value::connect(&v, SIGNAL(valueChanged(QString)), lb, SLOT(setText(QString)), v.SAFE_CONNTYPE); + } + + template<> + inline void tie_setting(value<int>& v, QTabWidget* t) + { + t->setCurrentIndex(v); + base_value::connect(t, SIGNAL(currentChanged(int)), &v, SLOT(setValue(int)), v.DIRECT_CONNTYPE); + base_value::connect(&v, SIGNAL(valueChanged(int)), t, SLOT(setCurrentIndex(int)), v.SAFE_CONNTYPE); + } +} diff --git a/opentrack-compat/shm.cpp b/opentrack-compat/shm.cpp index 029a4c95..55aa7a41 100644 --- a/opentrack-compat/shm.cpp +++ b/opentrack-compat/shm.cpp @@ -5,25 +5,140 @@ * copyright notice and this permission notice appear in all copies. */ -#include <cstring> #include "shm.h" #if defined(_WIN32) + +#include <cstring> +#include <stdio.h> + +#include <accctrl.h> +#include <aclapi.h> + +struct secattr +{ + bool success; + SECURITY_DESCRIPTOR* pSD; + SECURITY_ATTRIBUTES attrs; + PSID pEveryoneSID; + PACL pACL; + + void cleanup() + { + if (pEveryoneSID) + FreeSid(pEveryoneSID); + if (pACL) + LocalFree(pACL); + if (pSD) + LocalFree(pSD); + success = false; + pSD = nullptr; + pEveryoneSID = nullptr; + pACL = nullptr; + } + + secattr(DWORD perms) : success(true), pSD(nullptr), pEveryoneSID(nullptr), pACL(nullptr) + { + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY; + EXPLICIT_ACCESS ea; + + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &pEveryoneSID)) + { + fprintf(stderr, "AllocateAndInitializeSid: %d\n", (int) GetLastError()); + goto cleanup; + } + + memset(&ea, 0, sizeof(ea)); + + ea.grfAccessPermissions = perms; + ea.grfAccessMode = SET_ACCESS; + ea.grfInheritance = NO_INHERITANCE; + ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea.Trustee.ptstrName = (LPTSTR) pEveryoneSID; + + if (SetEntriesInAcl(1, &ea, NULL, &pACL) != ERROR_SUCCESS) + { + fprintf(stderr, "SetEntriesInAcl: %d\n", (int) GetLastError()); + goto cleanup; + } + + pSD = (SECURITY_DESCRIPTOR*) LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); + if (pSD == nullptr) + { + fprintf(stderr, "LocalAlloc: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!InitializeSecurityDescriptor(pSD, + SECURITY_DESCRIPTOR_REVISION)) + { + fprintf(stderr, "InitializeSecurityDescriptor: %d\n", (int) GetLastError()); + goto cleanup; + } + + if (!SetSecurityDescriptorDacl(pSD, + TRUE, + pACL, + FALSE)) + { + fprintf(stderr, "SetSecurityDescriptorDacl: %d\n", (int) GetLastError()); + goto cleanup; + } + + attrs.bInheritHandle = false; + attrs.lpSecurityDescriptor = pSD; + attrs.nLength = sizeof(SECURITY_ATTRIBUTES); + + fflush(stderr); + + return; +cleanup: + fflush(stderr); + cleanup(); + } + + ~secattr() + { + cleanup(); + } +}; + PortableLockedShm::PortableLockedShm(const char* shmName, const char* mutexName, int mapSize) { - hMutex = CreateMutexA(NULL, false, mutexName); + secattr sa(GENERIC_ALL|SYNCHRONIZE); + + hMutex = CreateMutexA(sa.success ? &sa.attrs : nullptr, false, mutexName); + if (!hMutex) + { + fprintf(stderr, "CreateMutexA: %d\n", (int) GetLastError()); + fflush(stderr); + } hMapFile = CreateFileMappingA( INVALID_HANDLE_VALUE, - NULL, + sa.success ? &sa.attrs : nullptr, PAGE_READWRITE, 0, mapSize, shmName); + if (!hMapFile) + { + fprintf(stderr, "CreateFileMappingA: %d\n", (int) GetLastError()); + fflush(stderr); + } mem = MapViewOfFile(hMapFile, FILE_MAP_WRITE, 0, 0, mapSize); + if (!mem) + { + fprintf(stderr, "MapViewOfFile: %d\n", (int) GetLastError()); + fflush(stderr); + } } PortableLockedShm::~PortableLockedShm() diff --git a/opentrack-compat/shm.h b/opentrack-compat/shm.h index c74534e7..3edb0080 100644 --- a/opentrack-compat/shm.h +++ b/opentrack-compat/shm.h @@ -19,32 +19,18 @@ #include <sys/types.h> #endif -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wattributes" - #ifdef __GNUC__ -# define COMPAT_GNUC_VISIBILITY __attribute__ ((visibility ("default"))) -#else -# define COMPAT_GNUC_VISIBILITY +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wattributes" #endif -#ifdef BUILD_opentrack_compat -# ifdef _WIN32 -# define COMPAT_WIN32_EXPORT __declspec(dllexport) -# else -# define COMPAT_WIN32_EXPORT -# endif +#ifdef BUILD_compat +# include "compat-export.hpp" #else -# ifdef _WIN32 -# define COMPAT_WIN32_EXPORT __declspec(dllimport) -# else -# define COMPAT_WIN32_EXPORT -# endif +# include "compat-import.hpp" #endif -#define COMPAT_EXPORT COMPAT_WIN32_EXPORT COMPAT_GNUC_VISIBILITY - -class COMPAT_EXPORT PortableLockedShm { +class OPENTRACK_COMPAT_EXPORT PortableLockedShm { public: PortableLockedShm(const char *shmName, const char *mutexName, int mapSize); ~PortableLockedShm(); @@ -61,4 +47,6 @@ private: #endif }; -#pragma GCC diagnostic pop +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif |