Skip to content

Commit

Permalink
crash fix ; support inject to apps needing admin ; fix keys held upon…
Browse files Browse the repository at this point in the history
… window switch ; rest are mostly internal changes'
  • Loading branch information
thisismypassport committed Feb 20, 2023
1 parent 225cdd7 commit a405478
Show file tree
Hide file tree
Showing 39 changed files with 2,002 additions and 804 deletions.
45 changes: 24 additions & 21 deletions src/CfgMgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ static bool DeviceIDListFilterMatches(PCWSTR pszFilter, ULONG ulFlags) {
return true;
}

if (ulFlags == CM_GETIDLIST_FILTER_ENUMERATOR && pszFilter && wcscmp(pszFilter, L"ROOT") == 0) {
if (ulFlags == CM_GETIDLIST_FILTER_ENUMERATOR && pszFilter && wcseq(pszFilter, L"ROOT")) {
return true;
}

Expand Down Expand Up @@ -212,7 +212,7 @@ CONFIGRET WINAPI CM_Get_Device_ID_ListW_Hook(PCWSTR pszFilter, PZZWSTR buffer, U
static DEVINST LocateCustomDevNode(DEVINSTID_W pDeviceID) {
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
DeviceIntf *device = ImplGetDevice(i);
if (device && wcscmp(pDeviceID, device->DeviceInstName) == 0) {
if (device && wcseq(pDeviceID, device->DeviceInstName)) {
if (G.ApiDebug) {
LOG << "CM_Locate_DevNodeW " << pDeviceID << END;
}
Expand Down Expand Up @@ -469,7 +469,8 @@ struct FilterResult {

bool Matches(DeviceIntf *device, int xusb = -1) const {
return (User < 0 || User == device->UserIdx) &&
!(XUsb == (int)true && !device->IsXInput) &&
!(XUsb == (int)true && !device->IsXUsb) &&
!(XUsb == (int)false && !device->IsHid) &&
(xusb < 0 || XUsb < 0 || XUsb == xusb);
}
};
Expand All @@ -489,7 +490,7 @@ static bool DeviceInterfaceListFilterMatches(LPGUID clsGuid, DEVINSTID_W pDevice
if (pDeviceID && *pDeviceID) {
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
DeviceIntf *device = ImplGetDevice(i);
if (device && wcscmp(pDeviceID, device->DeviceInstName) == 0 &&
if (device && wcseq(pDeviceID, device->DeviceInstName) &&
filter.Matches(device)) {
filter.User = i;
*outFilter = filter;
Expand All @@ -516,10 +517,10 @@ CONFIGRET WINAPI CM_Get_Device_Interface_List_SizeW_Hook(PULONG pulLen, LPGUID c
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
DeviceIntf *device = ImplGetDevice(i);
if (device) {
if (filter.Matches(device, false)) {
if (device->IsHid && filter.Matches(device, false)) {
*pulLen += (ULONG)wcslen(device->DevicePathW) + 1;
}
if (device->IsXInput && filter.Matches(device, true)) {
if (device->IsXUsb && filter.Matches(device, true)) {
*pulLen += (ULONG)wcslen(device->XDevicePathW) + 1;
}
}
Expand Down Expand Up @@ -548,10 +549,10 @@ CONFIGRET WINAPI CM_Get_Device_Interface_ListW_Hook(LPGUID clsGuid, DEVINSTID_W
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
DeviceIntf *device = ImplGetDevice(i);
if (device) {
if (ok && filter.Matches(device, false)) {
if (ok && device->IsHid && filter.Matches(device, false)) {
ok = ZZWStrAppend(buffer, bufferLen, device->DevicePathW);
}
if (ok && device->IsXInput && filter.Matches(device, true)) {
if (ok && device->IsXUsb && filter.Matches(device, true)) {
ok = ZZWStrAppend(buffer, bufferLen, device->XDevicePathW);
}
}
Expand All @@ -576,8 +577,8 @@ CONFIGRET WINAPI CM_Get_Device_Interface_Property_KeysW_Hook(LPCWSTR pszIntf, DE
for (int i = 0; i < XUSER_MAX_COUNT; i++) {
DeviceIntf *device = ImplGetDevice(i);
if (device &&
(wcscmp(pszIntf, device->DevicePathW) == 0 ||
(device->IsXInput && wcscmp(pszIntf, device->XDevicePathW) == 0))) {
((device->IsHid && wcseq(pszIntf, device->DevicePathW)) ||
(device->IsXUsb && wcseq(pszIntf, device->XDevicePathW)))) {
ret = CMGetPropertyKeys(propKeys, propKeyCount, {
DEVPKEY_DeviceInterface_ClassGuid,
DEVPKEY_DeviceInterface_Enabled,
Expand Down Expand Up @@ -611,8 +612,8 @@ CONFIGRET WINAPI CM_Get_Device_Interface_PropertyW_Hook(LPCWSTR pszIntf, const D
DeviceIntf *device = ImplGetDevice(i);
bool isXUsb = false;
if (device &&
(wcscmp(pszIntf, device->DevicePathW) == 0 ||
(isXUsb = (device->IsXInput && wcscmp(pszIntf, device->XDevicePathW) == 0)))) {
((device->IsHid && wcseq(pszIntf, device->DevicePathW)) ||
(isXUsb = (device->IsXUsb && wcseq(pszIntf, device->XDevicePathW))))) {
if (*propKey == DEVPKEY_DeviceInterface_ClassGuid) {
ret = CMGetPropertyValue(propType, propBuf, propSize, isXUsb ? GUID_DEVINTERFACE_XUSB : GUID_DEVINTERFACE_HID);
} else if (*propKey == DEVPKEY_DeviceInterface_Enabled) {
Expand Down Expand Up @@ -654,17 +655,19 @@ CONFIGRET WINAPI CM_Register_Notification_Hook(PCM_NOTIFY_FILTER pFilter, PVOID
if (ret == CR_SUCCESS) {
HCMNOTIFICATION notify = *pNotifyContext;
GThreadPoolNotifications.Register(notify, [pContext, pCallback, notify](ImplUser *user, bool added) {
CM_NOTIFY_ACTION action = added ? CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL : CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL;
if (user->Device->IsHid) {
CM_NOTIFY_ACTION action = added ? CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL : CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL;

size_t size = sizeof(CM_NOTIFY_EVENT_DATA) + wcslen(user->Device->DevicePathW) * sizeof(wchar_t);
CM_NOTIFY_EVENT_DATA *event = (CM_NOTIFY_EVENT_DATA *)new byte[size];
ZeroMemory(event, sizeof(*event));
event->FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
event->u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID;
wcscpy(event->u.DeviceInterface.SymbolicLink, user->Device->DevicePathW);
size_t size = sizeof(CM_NOTIFY_EVENT_DATA) + wcslen(user->Device->DevicePathW) * sizeof(wchar_t);
CM_NOTIFY_EVENT_DATA *event = (CM_NOTIFY_EVENT_DATA *)new byte[size];
ZeroMemory(event, sizeof(*event));
event->FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
event->u.DeviceInterface.ClassGuid = GUID_DEVINTERFACE_HID;
wcscpy(event->u.DeviceInterface.SymbolicLink, user->Device->DevicePathW);

pCallback(notify, pContext, action, event, (int)size);
delete[] event;
pCallback(notify, pContext, action, event, (int)size);
delete[] event;
}
});
}
return ret;
Expand Down
153 changes: 101 additions & 52 deletions src/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ struct ConfigState {
unordered_set<wstring_view> LoadedFilesSet;
Path MainFile;
Path Directory;

unordered_map<string, int> CustomKeys;
unordered_map<string, function<void(const string &)>> CustomVars;
} GConfig;

bool ConfigLoadFrom(const wchar_t *filename);
Expand All @@ -34,7 +37,7 @@ string ConfigReadToken(const string &str, intptr_t *startPtr) {
return str.substr(start, end - start);
}

int ConfigReadKey(const string &str, bool output = false) {
int ConfigReadKey(const string &str, int *outUser, bool output = false) {
#define CONFIG_ON_KEY(vk, name, ...) \
if (strLow == name) \
return vk; \
Expand All @@ -57,6 +60,12 @@ int ConfigReadKey(const string &str, bool output = false) {
ENUMERATE_CMD_VKS(CONFIG_ON_KEY);
}

auto customKeyIter = GConfig.CustomKeys.find(strLow);
if (customKeyIter != GConfig.CustomKeys.end()) {
*outUser = customKeyIter->second;
return MY_VK_CUSTOM;
}

LOG << "ERROR: Invalid key: " << str << END;
return 0;
}
Expand Down Expand Up @@ -151,7 +160,7 @@ SharedPtr<ImplCond> ConfigReadCond(const string &line, intptr_t *idxPtr) {

cond->Key = condType ? condType : MY_VK_META_COND_AND;
} else {
cond->Key = ConfigReadKey(condStr);
cond->Key = ConfigReadKey(condStr, &cond->User);

if (GetKeyType(cond->Key).Pair) {
auto cond1 = SharedPtr<ImplCond>::New(*cond);
Expand Down Expand Up @@ -200,8 +209,8 @@ SharedPtr<ImplMapping> ConfigReadInputLine(const string &line) {
cfg->Toggle = true;
} else if (optStr == "add") {
cfg->Add = true;
} else if (optStr == "persistent") {
cfg->Persistent = true;
} else if (optStr == "reset") {
cfg->Reset = true;
} else {
LOG << "ERROR: Invalid option: " << optStr << END;
}
Expand All @@ -221,20 +230,22 @@ SharedPtr<ImplMapping> ConfigReadInputLine(const string &line) {
}
}

cfg->SrcKey = ConfigReadKey(inputStr);
cfg->DestKey = ConfigReadKey(outputStr, true);
cfg->SrcKey = ConfigReadKey(inputStr, &cfg->SrcUser);
cfg->DestKey = ConfigReadKey(outputStr, &cfg->DestUser, true);
cfg->Strength = ConfigReadStrength(strengthStr);
cfg->Rate = ConfigReadRate(rateStr);
cfg->User = ConfigReadUser(userStr);
if (cfg->DestKey != MY_VK_CUSTOM) {
cfg->DestUser = ConfigReadUser(userStr);
}

LOG << "Mapping " << inputStr << " to " << outputStr << " of player " << (cfg->User + 1) << " (strength " << cfg->Strength << ")" << END;
LOG << "Mapping " << inputStr << " to " << outputStr << " of player " << (cfg->DestUser + 1) << " (strength " << cfg->Strength << ")" << END;

return cfg;
}

void ConfigCreateResets(const SharedPtr<ImplMapping> &mapping, ImplCond *cond) {
do {
ImplInput *input = ImplGetInput(cond->Key);
ImplInput *input = ImplGetInput(cond->Key, cond->User);
if (input) {
auto reset = SharedPtr<ImplReset>::New();
reset->Mapping = mapping;
Expand Down Expand Up @@ -263,8 +274,6 @@ bool ConfigLoadInputLine(const string &line) {
cfg->SrcType.Pair = false;
}

int userIndex = cfg->User >= 0 ? cfg->User : 0;

if (cfg->SrcType.Relative && (cfg->Toggle || cfg->Turbo)) {
LOG << "ERROR: toggle & turbo aren't supported for relative input" << END;
cfg->Toggle = cfg->Turbo = false;
Expand All @@ -283,11 +292,11 @@ bool ConfigLoadInputLine(const string &line) {
nextCfg->SrcKey = nextSrcKey;
}

if (cfg->Conds && !cfg->Persistent) {
if (cfg->Conds && (!cfg->Add || cfg->Reset)) {
ConfigCreateResets(cfg, cfg->Conds);
}

ImplInput *input = ImplGetInput(cfg->SrcKey);
ImplInput *input = ImplGetInput(cfg->SrcKey, cfg->SrcUser);
if (input) {
if (!cfg->Replace) {
cfg->Next = input->Mappings;
Expand All @@ -300,8 +309,10 @@ bool ConfigLoadInputLine(const string &line) {
G.Mouse.IsMapped = true;
}

int destUserIdx = cfg->DestUser >= 0 ? cfg->DestUser : 0;

if (cfg->DestType.OfUser) {
G.Users[userIndex].Connected = true;
G.Users[destUserIdx].Connected = true;
}
}

Expand All @@ -324,6 +335,8 @@ void ConfigLoadDevice(const string &key, const string &type) {
device = new XDeviceIntf(userIdx);
} else if (typeLow == "ds4" || typeLow == "ps4") {
device = new Ds4DeviceIntf(userIdx);
} else if (typeLow == "none") {
device = new NoDeviceIntf(userIdx);
} else {
LOG << "ERROR: Invalid device: " << type << END;
}
Expand All @@ -349,26 +362,47 @@ void ConfigLoadInclude(const string &val) {
ConfigLoadFrom(filename);
}

void ConfigLoadExtraHook(const string &line, intptr_t idx) {
Path dllPath = PathFromStr(ConfigReadToken(line, &idx).c_str());
Path dllWait = PathFromStr(ConfigReadToken(line, &idx).c_str());
void ConfigLoadExtraHook(const string &val) {
int numArgs = 0;
LPWSTR *args = CommandLineToArgvW(PathFromStr(val.c_str()), &numArgs);

Path dllPath;
bool is32 = false, is64 = false;
for (int argI = 0; argI < numArgs; argI++) {
if (wcseq(args[argI], L"-32")) {
is32 = true;
} else if (wcseq(args[argI], L"-64")) {
is64 = true;
} else if (!dllPath && args[argI][0] != L'-') {
dllPath = args[argI];
} else {
LOG << "ERROR: Invalid argument to !ExtraHook: " << args[argI] << END;
}
}

if (*dllWait) {
dllWait = PathGetBaseNameWithoutExt(dllWait); // won't support non-dlls
if (!dllPath) {
LOG << "ERROR: dll path not supplied to !ExtraHook" << END;
return;
}

for (auto &delayedHook : G.ExtraDelayedHooks) {
if (delayedHook.WaitDll == dllWait) {
delayedHook.Hooks.push_back(move(dllPath));
return;
}
}
#ifdef _WIN64
if (is32) {
return;
}
#else
if (is64) {
return;
}
#endif

G.ExtraDelayedHooks.emplace_back();
auto &delayedHook = G.ExtraDelayedHooks.back();
delayedHook.WaitDll = move(dllWait);
delayedHook.Hooks.push_back(move(dllPath));
} else {
G.ExtraHooks.push_back(move(dllPath));
if (G.Debug) {
LOG << "Loading extra hook: " << dllPath << END;
}

// Load it immediately, to allow registering config extensions
// (note: this means calling dll load from dllmain, which is not legal but seems-ok)
if (!LoadLibraryExW(dllPath, nullptr, 0)) {
LOG << "Failed loading extra hook: " << dllPath << " due to: " << GetLastError() << END;
}
}

Expand All @@ -390,13 +424,13 @@ bool ConfigLoadVarLine(const string &line) {
string key = ConfigReadToken(line, &idx);
string keyLow = StrLowerCase(key);

intptr_t valIdx = idx;
if (ConfigReadToken(line, &idx) == "=") { // optional '='
valIdx = idx;
} else {
idx = valIdx;
}
intptr_t validx = idx;
string val = ConfigReadToken(line, &idx);
if (val == "=") // optional '='
{
validx = idx;
val = ConfigReadToken(line, &idx);
}

if (keyLow == "trace") {
G.Trace = ConfigReadBoolVar(val);
Expand Down Expand Up @@ -425,9 +459,14 @@ bool ConfigLoadVarLine(const string &line) {
} else if (keyLow == "include") {
ConfigLoadInclude(val);
} else if (keyLow == "extrahook") {
ConfigLoadExtraHook(line, valIdx);
ConfigLoadExtraHook(StrTrimmed(line.substr(validx)));
} else {
LOG << "ERROR: Invalid variable: " << key << END;
auto customIter = GConfig.CustomVars.find(keyLow);
if (customIter != GConfig.CustomVars.end()) {
customIter->second(StrTrimmed(line.substr(validx)));
} else {
LOG << "ERROR: Invalid variable: " << key << END;
}
}

return true;
Expand Down Expand Up @@ -480,18 +519,7 @@ bool ConfigLoadFrom(const wchar_t *filename) {
}

void ConfigReset() {
G.Trace = G.Debug = G.ApiTrace = G.ApiDebug = G.WaitDebugger = false;
G.Forward = G.Always = G.Disable = G.HideCursor = false;
G.InjectChildren = G.RumbleWindow = false;
G.Keyboard.IsMapped = G.Mouse.IsMapped = false;

for (int i = 0; i < IMPL_MAX_USERS; i++) {
G.Users[i].Connected = G.Users[i].DeviceSpecified = false;
}

G.Keyboard.Reset();
G.Mouse.Reset();
G.ActiveUser = 0;
G.Reset();

GConfig.LoadedFilesSet.clear();
GConfig.LoadedFiles.clear();
Expand Down Expand Up @@ -521,7 +549,7 @@ static bool ConfigReloadNoUpdate() {
return true;
}

bool ConfigLoad(Path &&path, Path &&name) {
bool ConfigInit(Path &&path, Path &&name) {
GConfig.Directory = move(path);
GConfig.MainFile = move(name);
return ConfigReloadNoUpdate();
Expand All @@ -534,3 +562,24 @@ void ConfigReload() {
ConfigSendGlobalEvents(true);
UpdateAll();
}

int ConfigRegisterCustomKey(const char *name, function<void(const InputValue &)> &&cb) {
int index = (int)G.CustomKeys.size();

auto custKey = UniquePtr<ImplCustomKey>::New();
custKey->Callback = move(cb);
G.CustomKeys.push_back(move(custKey));

string nameLow = name;
StrToLowerCase(nameLow);
StrReplaceAll(nameLow, ".", "");
GConfig.CustomKeys[nameLow] = index;

return index;
}

void ConfigRegisterCustomVar(const char *name, function<void(const string &)> &&cb) {
string nameLow = name;
StrToLowerCase(nameLow);
GConfig.CustomVars[nameLow] = move(cb);
}
Loading

0 comments on commit a405478

Please sign in to comment.