Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions common/include/err.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ enum Err {
ERR_INVALID_ARGUMENTS,
ERR_OUT_OF_MEMORY,
ERR_ALREADY_RUNNING,
ERR_CREATE_MUTEX,
ERR_MUTEX_TIMEOUT,
ERR_CREATE_FILE_MAPPING,
ERR_OPEN_FILE_MAPPING,
ERR_CREATE_EVENT,
Expand Down
2 changes: 1 addition & 1 deletion common/include/version.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#ifndef VERSION_HPP
#define VERSION_HPP

#define VERSION_STRING "0.5.0"
#define VERSION_STRING "0.5.1"

#endif /* VERSION_HPP */
6 changes: 5 additions & 1 deletion injector/hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,18 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK IMControl_WndProcHook(int nCod
LOG_ERROR("ERROR: GetCompartment(GUID_COMPARTMENT_KEYBOARD_INPUTMODE_CONVERSION) failed with 0x%0lx", hr);
}
if (SUCCEEDED(hr)) {
DWORD oldMode = varKeyboardInputModeConversion.lVal;
DWORD oldMode = 0;
if (varKeyboardInputModeConversion.vt == VT_I4 || varKeyboardInputModeConversion.vt == VT_UI4) {
oldMode = varKeyboardInputModeConversion.lVal;
}
DWORD newMode = oldMode;
if (*g_pSharedData->conversionModeNative) {
newMode |= TF_CONVERSIONMODE_NATIVE;
} else {
newMode &= ~TF_CONVERSIONMODE_NATIVE;
}
if (newMode != oldMode) {
varKeyboardInputModeConversion.vt = VT_I4;
varKeyboardInputModeConversion.lVal = newMode;
hr = keyboardInputModeConversionCompartment->SetValue(0, &varKeyboardInputModeConversion);
}
Expand Down
52 changes: 39 additions & 13 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,25 @@ int main(int argc, const char *argv[]) {

logInit("main");

// Open shared memory for data sharing, and also for ensuring only one instance is running.
// Use a named mutex for serialization (auto-released when process dies,
// unlike file mapping which can leak when hook DLL remains in target)
HANDLE hMutex = CreateMutexA(NULL, FALSE, "Local\\IMControlMutex");
if (hMutex == NULL) {
eprintln("%s: CreateMutex() failed with 0x%lx.", argv[0], GetLastError());
LOG_ERROR("CreateMutex() failed with 0x%lx", GetLastError());
err = ERR_CREATE_MUTEX;
}
if (!err) {
DWORD dwMutexResult = WaitForSingleObject(hMutex, 10000);
if (dwMutexResult != WAIT_OBJECT_0) {
eprintln("%s: Timed out waiting for mutex.", argv[0]);
LOG_ERROR("Timed out waiting for mutex");
CloseHandle(hMutex);
return ERR_MUTEX_TIMEOUT;
}
}

// Open shared memory for data sharing (no longer used as singleton guard)
HANDLE hMapFile = CreateFileMapping(INVALID_HANDLE_VALUE,
NULL,
PAGE_READWRITE,
Expand All @@ -179,12 +197,6 @@ int main(int argc, const char *argv[]) {
LOG_ERROR("CreateFileMapping failed with 0x%lx", GetLastError());
err = ERR_CREATE_FILE_MAPPING;
}
if (!err) {
if (GetLastError() == ERROR_ALREADY_EXISTS) {
CloseHandle(hMapFile);
return ERR_ALREADY_RUNNING;
}
}

SharedData* pSharedData = NULL;
if (!err) {
Expand All @@ -203,11 +215,16 @@ int main(int argc, const char *argv[]) {
}
}

HANDLE hEvent = CreateEventA(NULL, TRUE, FALSE, "Local\\IMControlDoneEvent");
if (hEvent == NULL) {
eprintln("%s: CreateEventA() failed with 0x%lx.", argv[0], GetLastError());
LOG_ERROR("CreateEventA() failed with 0x%lx", GetLastError());
err = ERR_CREATE_EVENT;
HANDLE hEvent = NULL;
if (!err) {
hEvent = CreateEventA(NULL, TRUE, FALSE, "Local\\IMControlDoneEvent");
if (hEvent == NULL) {
eprintln("%s: CreateEventA() failed with 0x%lx.", argv[0], GetLastError());
LOG_ERROR("CreateEventA() failed with 0x%lx", GetLastError());
err = ERR_CREATE_EVENT;
} else {
ResetEvent(hEvent);
}
}

HWND hForegroundWindow = NULL;
Expand Down Expand Up @@ -405,7 +422,7 @@ int main(int argc, const char *argv[]) {

if (!err) {
LOG_INFO("Waiting for injector to finish...");
DWORD dwWaitResult = WaitForSingleObject(hEvent, INFINITE);
DWORD dwWaitResult = WaitForSingleObject(hEvent, 10000);
switch (dwWaitResult) {
case WAIT_OBJECT_0:
LOG_INFO("Injector finished.");
Expand All @@ -415,6 +432,11 @@ int main(int argc, const char *argv[]) {
LOG_ERROR("injector exited with code %d", err);
}
break;
case WAIT_TIMEOUT:
eprintln("%s: Timed out waiting for injector (10s).", argv[0]);
LOG_ERROR("Timed out waiting for injector (10s)");
err = ERR_SEND_MESSAGE_TIMEOUT_TIMED_OUT;
break;
case WAIT_FAILED:
eprintln("%s: WaitForSingleObject() failed with 0x%lx.", argv[0], GetLastError());
LOG_ERROR("WaitForSingleObject() failed with 0x%lx", GetLastError());
Expand Down Expand Up @@ -470,6 +492,10 @@ int main(int argc, const char *argv[]) {
if (hMapFile != NULL) {
CloseHandle(hMapFile);
}
if (hMutex != NULL) {
ReleaseMutex(hMutex);
CloseHandle(hMutex);
}

LOG_INFO("Exiting with code %d", err);

Expand Down