implement "Immune Keys" which are keys that are ignored by
server-to-client key-forwarding. this feature is only implemented for servers running on windows machines.
This commit is contained in:
parent
b64512d65f
commit
faec8a2f84
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* barrier -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2018 Deuauche Open Source Group
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ImmuneKeysReader.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
const std::size_t AllocatedLineSize = 1024;
|
||||||
|
const char CommentChar = '#';
|
||||||
|
|
||||||
|
static void add_key(const char * const buffer, std::vector<DWORD> &keys)
|
||||||
|
{
|
||||||
|
const char *first;
|
||||||
|
// skip spaces. ignore blank lines and comment lines
|
||||||
|
for (first = buffer; *first == ' '; ++first);
|
||||||
|
if (*first != 0 && *first != CommentChar)
|
||||||
|
keys.emplace_back(std::stoul(first, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*static*/ bool ImmuneKeysReader::get_list(const char * const path, std::vector<DWORD> &keys, std::string &badline)
|
||||||
|
{
|
||||||
|
// default values for return params
|
||||||
|
keys.clear();
|
||||||
|
badline.clear();
|
||||||
|
std::ifstream stream(path, std::ios::in);
|
||||||
|
if (stream.is_open()) {
|
||||||
|
// size includes the null-terminator
|
||||||
|
char buffer[AllocatedLineSize];
|
||||||
|
while (stream.getline(&buffer[0], AllocatedLineSize)) {
|
||||||
|
try {
|
||||||
|
add_key(buffer, keys);
|
||||||
|
} catch (...) {
|
||||||
|
badline = buffer;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* barrier -- mouse and keyboard sharing utility
|
||||||
|
* Copyright (C) 2018 Deuauche Open Source Group
|
||||||
|
*
|
||||||
|
* This package is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* found in the file LICENSE that should have accompanied this file.
|
||||||
|
*
|
||||||
|
* This package 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
// let's not import all of Windows just to get this typedef
|
||||||
|
typedef unsigned long DWORD;
|
||||||
|
|
||||||
|
class ImmuneKeysReader
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static bool get_list(const char * const path, std::vector<DWORD> &keys, std::string &badLine);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// static class
|
||||||
|
explicit ImmuneKeysReader() {}
|
||||||
|
};
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "synwinhk/synwinhk.h"
|
#include "synwinhk/synwinhk.h"
|
||||||
#include "platform/MSWindowsScreen.h"
|
#include "platform/MSWindowsScreen.h"
|
||||||
|
#include "platform/ImmuneKeysReader.h"
|
||||||
#include "barrier/IScreenSaver.h"
|
#include "barrier/IScreenSaver.h"
|
||||||
#include "barrier/XScreen.h"
|
#include "barrier/XScreen.h"
|
||||||
#include "mt/Lock.h"
|
#include "mt/Lock.h"
|
||||||
|
@ -88,6 +89,17 @@
|
||||||
// enable; <unused>
|
// enable; <unused>
|
||||||
#define BARRIER_MSG_FAKE_INPUT BARRIER_HOOK_LAST_MSG + 12
|
#define BARRIER_MSG_FAKE_INPUT BARRIER_HOOK_LAST_MSG + 12
|
||||||
|
|
||||||
|
static const std::string ImmuneKeysPath = ArchFileWindows().getProfileDirectory() + "\\ImmuneKeys.txt";
|
||||||
|
|
||||||
|
static std::vector<DWORD> immune_keys_list()
|
||||||
|
{
|
||||||
|
std::vector<DWORD> keys;
|
||||||
|
std::string badLine;
|
||||||
|
if (!ImmuneKeysReader::get_list(ImmuneKeysPath.c_str(), keys, badLine))
|
||||||
|
LOG((CLOG_ERR "Reading immune keys stopped at: %s", badLine.c_str()));
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// MSWindowsDesks
|
// MSWindowsDesks
|
||||||
//
|
//
|
||||||
|
@ -114,6 +126,8 @@ MSWindowsDesks::MSWindowsDesks(
|
||||||
m_events(events),
|
m_events(events),
|
||||||
m_stopOnDeskSwitch(stopOnDeskSwitch)
|
m_stopOnDeskSwitch(stopOnDeskSwitch)
|
||||||
{
|
{
|
||||||
|
LOG((CLOG_DEBUG "Immune Keys Path: %s", ImmuneKeysPath));
|
||||||
|
|
||||||
if (hookLibrary != NULL)
|
if (hookLibrary != NULL)
|
||||||
queryHookLibrary(hookLibrary);
|
queryHookLibrary(hookLibrary);
|
||||||
|
|
||||||
|
@ -355,14 +369,17 @@ MSWindowsDesks::queryHookLibrary(HINSTANCE hookLibrary)
|
||||||
if (m_isPrimary && !m_noHooks) {
|
if (m_isPrimary && !m_noHooks) {
|
||||||
m_install = (InstallFunc)GetProcAddress(hookLibrary, "install");
|
m_install = (InstallFunc)GetProcAddress(hookLibrary, "install");
|
||||||
m_uninstall = (UninstallFunc)GetProcAddress(hookLibrary, "uninstall");
|
m_uninstall = (UninstallFunc)GetProcAddress(hookLibrary, "uninstall");
|
||||||
|
m_setImmuneKeys = (SetImmuneKeysFunc)GetProcAddress(hookLibrary, "setImmuneKeys");
|
||||||
m_installScreensaver =
|
m_installScreensaver =
|
||||||
(InstallScreenSaverFunc)GetProcAddress(
|
(InstallScreenSaverFunc)GetProcAddress(
|
||||||
hookLibrary, "installScreenSaver");
|
hookLibrary, "installScreenSaver");
|
||||||
m_uninstallScreensaver =
|
m_uninstallScreensaver =
|
||||||
(UninstallScreenSaverFunc)GetProcAddress(
|
(UninstallScreenSaverFunc)GetProcAddress(
|
||||||
hookLibrary, "uninstallScreenSaver");
|
hookLibrary, "uninstallScreenSaver");
|
||||||
|
|
||||||
if (m_install == NULL ||
|
if (m_install == NULL ||
|
||||||
m_uninstall == NULL ||
|
m_uninstall == NULL ||
|
||||||
|
m_setImmuneKeys == NULL ||
|
||||||
m_installScreensaver == NULL ||
|
m_installScreensaver == NULL ||
|
||||||
m_uninstallScreensaver == NULL) {
|
m_uninstallScreensaver == NULL) {
|
||||||
LOG((CLOG_ERR "Invalid hook library"));
|
LOG((CLOG_ERR "Invalid hook library"));
|
||||||
|
@ -372,6 +389,7 @@ MSWindowsDesks::queryHookLibrary(HINSTANCE hookLibrary)
|
||||||
else {
|
else {
|
||||||
m_install = NULL;
|
m_install = NULL;
|
||||||
m_uninstall = NULL;
|
m_uninstall = NULL;
|
||||||
|
m_setImmuneKeys = NULL;
|
||||||
m_installScreensaver = NULL;
|
m_installScreensaver = NULL;
|
||||||
m_uninstallScreensaver = NULL;
|
m_uninstallScreensaver = NULL;
|
||||||
}
|
}
|
||||||
|
@ -696,6 +714,10 @@ MSWindowsDesks::deskThread(void* vdesk)
|
||||||
m_uninstallScreensaver();
|
m_uninstallScreensaver();
|
||||||
m_installScreensaver();
|
m_installScreensaver();
|
||||||
}
|
}
|
||||||
|
// populate immune keys list in the DLL's shared memory
|
||||||
|
// before the hooks are activated
|
||||||
|
auto list = immune_keys_list();
|
||||||
|
m_setImmuneKeys(list.data(), list.size());
|
||||||
switch (m_install()) {
|
switch (m_install()) {
|
||||||
case kHOOK_FAILED:
|
case kHOOK_FAILED:
|
||||||
// we won't work on this desk
|
// we won't work on this desk
|
||||||
|
|
|
@ -286,6 +286,7 @@ private:
|
||||||
// hook library stuff
|
// hook library stuff
|
||||||
InstallFunc m_install;
|
InstallFunc m_install;
|
||||||
UninstallFunc m_uninstall;
|
UninstallFunc m_uninstall;
|
||||||
|
SetImmuneKeysFunc m_setImmuneKeys;
|
||||||
InstallScreenSaverFunc
|
InstallScreenSaverFunc
|
||||||
m_installScreensaver;
|
m_installScreensaver;
|
||||||
UninstallScreenSaverFunc
|
UninstallScreenSaverFunc
|
||||||
|
|
|
@ -85,6 +85,18 @@ typedef struct tagMOUSEHOOKSTRUCTWin2000 {
|
||||||
#define XBUTTON2 0x0002
|
#define XBUTTON2 0x0002
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// because all of our global data is shared between processes,
|
||||||
|
// allocating shared data on-the-fly is tricky. therefore let's
|
||||||
|
// store all of our immune keys in a pre-allocated array. the
|
||||||
|
// downside here is that we have to pick a maximum number of
|
||||||
|
// immune keys to store. who would ever want barrier to ignore
|
||||||
|
// more than 32 keys on their keyboard??
|
||||||
|
struct ImmuneKeys
|
||||||
|
{
|
||||||
|
static const std::size_t MaxKeys = 32;
|
||||||
|
DWORD list[MaxKeys];
|
||||||
|
std::size_t count;
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// globals
|
// globals
|
||||||
|
@ -121,6 +133,7 @@ static BYTE g_deadKeyState[256] = { 0 };
|
||||||
static BYTE g_keyState[256] = { 0 };
|
static BYTE g_keyState[256] = { 0 };
|
||||||
static DWORD g_hookThread = 0;
|
static DWORD g_hookThread = 0;
|
||||||
static bool g_fakeInput = false;
|
static bool g_fakeInput = false;
|
||||||
|
static ImmuneKeys g_immuneKeys{ {0}, 0 };
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma data_seg()
|
#pragma data_seg()
|
||||||
|
@ -445,10 +458,23 @@ doKeyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline static
|
||||||
|
bool is_immune_key(DWORD target)
|
||||||
|
{
|
||||||
|
for (std::size_t idx = 0; idx < g_immuneKeys.count; ++idx) {
|
||||||
|
if (g_immuneKeys.list[idx] == target)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
|
// allow all immune keys to pass without filtering
|
||||||
|
if (is_immune_key(static_cast<DWORD>(wParam)))
|
||||||
|
return false;
|
||||||
return doKeyboardHookHandler(wParam, lParam);
|
return doKeyboardHookHandler(wParam, lParam);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1123,4 +1149,17 @@ setMode(EHookMode mode)
|
||||||
g_mode = mode;
|
g_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// do not call this while the hooks are active!
|
||||||
|
void
|
||||||
|
setImmuneKeys(const DWORD *list, std::size_t size)
|
||||||
|
{
|
||||||
|
if (size > ImmuneKeys::MaxKeys)
|
||||||
|
size = ImmuneKeys::MaxKeys;
|
||||||
|
g_immuneKeys.count = size;
|
||||||
|
if (size > 0) {
|
||||||
|
for (std::size_t idx = 0; idx < size; ++idx)
|
||||||
|
g_immuneKeys.list[idx] = list[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,6 +76,7 @@ typedef int (*UninstallScreenSaverFunc)(void);
|
||||||
typedef void (*SetSidesFunc)(UInt32);
|
typedef void (*SetSidesFunc)(UInt32);
|
||||||
typedef void (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
|
typedef void (*SetZoneFunc)(SInt32, SInt32, SInt32, SInt32, SInt32);
|
||||||
typedef void (*SetModeFunc)(int);
|
typedef void (*SetModeFunc)(int);
|
||||||
|
typedef void (*SetImmuneKeysFunc)(const DWORD*, std::size_t);
|
||||||
|
|
||||||
CBARRIERHOOK_API int init(DWORD);
|
CBARRIERHOOK_API int init(DWORD);
|
||||||
CBARRIERHOOK_API int cleanup(void);
|
CBARRIERHOOK_API int cleanup(void);
|
||||||
|
@ -88,4 +89,7 @@ CBARRIERHOOK_API void setZone(SInt32 x, SInt32 y, SInt32 w, SInt32 h,
|
||||||
SInt32 jumpZoneSize);
|
SInt32 jumpZoneSize);
|
||||||
CBARRIERHOOK_API void setMode(EHookMode mode);
|
CBARRIERHOOK_API void setMode(EHookMode mode);
|
||||||
|
|
||||||
|
// do not call setImmuneKeys() while the hooks are active!
|
||||||
|
CBARRIERHOOK_API void setImmuneKeys(const DWORD *list, std::size_t size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue