feat: initiale Version 0.1.0 des MSTSC Script Hooks
- Native x64 MSTSC-DVC-Erweiterung für lokalen Programmstart - Automatischer Script-/Programmstart bei RDP-Verbindungsaufbau - Separater Programmstart über Trigger innerhalb der RDP-Sitzung - Bidirektionaler DVC zur Ermittlung des lokalen Client-Hostnamens - SIOMIN-Trigger zur Anbindung lokaler Sidexis-Installationen - SIOMIN-Datensatzlängen und Hostname-Felder bytegenau angepasst - Temporäre SIOMIN-Einträge nach erfolgreicher Übernahme bereinigt - Native Win32-Konfigurationsoberfläche ohne .NET-Abhängigkeit - Mehrfachstartschutz und optionaler unsichtbarer Programmstart - Debug- und Plugin-Logging ergänzt - RemoteVDDS-Anwendungsfall integriert - Installer/Registrierung des MSTSC-Plugins über Client-Konfigurator - Techniker-, Entwickler- und Projektdokumentation ergänzt - Proprietäre Lizenz für Copyright Patrick Gniza hinzugefügt
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
#include "Config.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
DWORD ReadDword(HKEY key, const wchar_t* name, DWORD defaultValue)
|
||||
{
|
||||
DWORD value = defaultValue;
|
||||
DWORD size = sizeof(value);
|
||||
DWORD type = 0;
|
||||
if (RegQueryValueExW(key, name, nullptr, &type, reinterpret_cast<BYTE*>(&value), &size) != ERROR_SUCCESS ||
|
||||
type != REG_DWORD)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
std::wstring ReadStringRaw(HKEY key, const wchar_t* name)
|
||||
{
|
||||
DWORD type = 0;
|
||||
DWORD size = 0;
|
||||
if (RegQueryValueExW(key, name, nullptr, &type, nullptr, &size) != ERROR_SUCCESS ||
|
||||
(type != REG_SZ && type != REG_EXPAND_SZ) || size == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<wchar_t> buffer((size / sizeof(wchar_t)) + 1, L'\0');
|
||||
if (RegQueryValueExW(key, name, nullptr, &type, reinterpret_cast<BYTE*>(buffer.data()), &size) != ERROR_SUCCESS)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
return std::wstring(buffer.data());
|
||||
}
|
||||
|
||||
bool WriteDword(HKEY key, const wchar_t* name, bool value, std::wstring& error)
|
||||
{
|
||||
DWORD data = value ? 1u : 0u;
|
||||
LONG result = RegSetValueExW(key, name, 0, REG_DWORD, reinterpret_cast<const BYTE*>(&data), sizeof(data));
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
error = L"Registry-Wert konnte nicht geschrieben werden: " + std::wstring(name) + L" (Fehler " + std::to_wstring(result) + L")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteString(HKEY key, const wchar_t* name, const std::wstring& value, DWORD type, std::wstring& error)
|
||||
{
|
||||
const DWORD bytes = static_cast<DWORD>((value.size() + 1) * sizeof(wchar_t));
|
||||
LONG result = RegSetValueExW(
|
||||
key,
|
||||
name,
|
||||
0,
|
||||
type,
|
||||
reinterpret_cast<const BYTE*>(value.c_str()),
|
||||
bytes);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
error = L"Registry-Wert konnte nicht geschrieben werden: " + std::wstring(name) + L" (Fehler " + std::to_wstring(result) + L")";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
namespace config
|
||||
{
|
||||
std::wstring ExpandEnvironment(const std::wstring& value)
|
||||
{
|
||||
if (value.empty())
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
DWORD needed = ExpandEnvironmentStringsW(value.c_str(), nullptr, 0);
|
||||
if (needed == 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> buffer(needed, L'\0');
|
||||
if (ExpandEnvironmentStringsW(value.c_str(), buffer.data(), needed) == 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return std::wstring(buffer.data());
|
||||
}
|
||||
|
||||
HookConfig Load()
|
||||
{
|
||||
HookConfig value;
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, kConfigKey, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
value.enabled = ReadDword(key, L"Enabled", 1) != 0;
|
||||
value.enableLogging = ReadDword(key, L"EnableLogging", 1) != 0;
|
||||
|
||||
value.scriptPath = ReadStringRaw(key, L"ScriptPath");
|
||||
value.arguments = ReadStringRaw(key, L"Arguments");
|
||||
value.workingDirectory = ReadStringRaw(key, L"WorkingDirectory");
|
||||
value.startOnConnect = ReadDword(key, L"StartOnConnect", 1) != 0;
|
||||
value.stopOnDisconnect = ReadDword(key, L"StopOnDisconnect", 0) != 0;
|
||||
value.hidden = ReadDword(key, L"Hidden", 1) != 0;
|
||||
value.preventDuplicates = ReadDword(key, L"PreventDuplicates", 1) != 0;
|
||||
|
||||
value.triggerEnabled = ReadDword(key, L"TriggerEnabled", 0) != 0;
|
||||
value.triggerProgramPath = ReadStringRaw(key, L"TriggerProgramPath");
|
||||
value.triggerArguments = ReadStringRaw(key, L"TriggerArguments");
|
||||
value.triggerWorkingDirectory = ReadStringRaw(key, L"TriggerWorkingDirectory");
|
||||
value.triggerHidden = ReadDword(key, L"TriggerHidden", 1) != 0;
|
||||
value.triggerPreventDuplicates = ReadDword(key, L"TriggerPreventDuplicates", 1) != 0;
|
||||
|
||||
RegCloseKey(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool Save(const HookConfig& value, std::wstring& error)
|
||||
{
|
||||
HKEY key = nullptr;
|
||||
DWORD disposition = 0;
|
||||
LONG result = RegCreateKeyExW(
|
||||
HKEY_CURRENT_USER,
|
||||
kConfigKey,
|
||||
0,
|
||||
nullptr,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_SET_VALUE,
|
||||
nullptr,
|
||||
&key,
|
||||
&disposition);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
error = L"Konfigurationsschlüssel konnte nicht erstellt werden (Fehler " + std::to_wstring(result) + L").";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok =
|
||||
WriteDword(key, L"Enabled", value.enabled, error) &&
|
||||
WriteDword(key, L"EnableLogging", value.enableLogging, error) &&
|
||||
WriteString(key, L"ScriptPath", value.scriptPath, REG_EXPAND_SZ, error) &&
|
||||
WriteString(key, L"Arguments", value.arguments, REG_SZ, error) &&
|
||||
WriteString(key, L"WorkingDirectory", value.workingDirectory, REG_EXPAND_SZ, error) &&
|
||||
WriteDword(key, L"StartOnConnect", value.startOnConnect, error) &&
|
||||
WriteDword(key, L"StopOnDisconnect", value.stopOnDisconnect, error) &&
|
||||
WriteDword(key, L"Hidden", value.hidden, error) &&
|
||||
WriteDword(key, L"PreventDuplicates", value.preventDuplicates, error) &&
|
||||
WriteDword(key, L"TriggerEnabled", value.triggerEnabled, error) &&
|
||||
WriteString(key, L"TriggerProgramPath", value.triggerProgramPath, REG_EXPAND_SZ, error) &&
|
||||
WriteString(key, L"TriggerArguments", value.triggerArguments, REG_SZ, error) &&
|
||||
WriteString(key, L"TriggerWorkingDirectory", value.triggerWorkingDirectory, REG_EXPAND_SZ, error) &&
|
||||
WriteDword(key, L"TriggerHidden", value.triggerHidden, error) &&
|
||||
WriteDword(key, L"TriggerPreventDuplicates", value.triggerPreventDuplicates, error);
|
||||
|
||||
RegCloseKey(key);
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::wstring GetRegisteredPluginPath()
|
||||
{
|
||||
HKEY key = nullptr;
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER, kAddInKey, 0, KEY_QUERY_VALUE, &key) != ERROR_SUCCESS)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
std::wstring value = ReadStringRaw(key, L"Name");
|
||||
RegCloseKey(key);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool RegisterPlugin(const std::wstring& dllPath, std::wstring& error)
|
||||
{
|
||||
HKEY key = nullptr;
|
||||
DWORD disposition = 0;
|
||||
LONG result = RegCreateKeyExW(
|
||||
HKEY_CURRENT_USER,
|
||||
kAddInKey,
|
||||
0,
|
||||
nullptr,
|
||||
REG_OPTION_NON_VOLATILE,
|
||||
KEY_SET_VALUE,
|
||||
nullptr,
|
||||
&key,
|
||||
&disposition);
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
error = L"MSTSC AddIn-Schlüssel konnte nicht erstellt werden (Fehler " + std::to_wstring(result) + L").";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok = WriteString(key, L"Name", dllPath, REG_SZ, error);
|
||||
RegCloseKey(key);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool UnregisterPlugin(std::wstring& error)
|
||||
{
|
||||
LONG result = RegDeleteTreeW(HKEY_CURRENT_USER, kAddInKey);
|
||||
if (result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND || result == ERROR_PATH_NOT_FOUND)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
error = L"MSTSC-Plugin-Registrierung konnte nicht entfernt werden (Fehler " + std::to_wstring(result) + L").";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user