diff options
author | Mikkel Krautz <mikkel@krautz.dk> | 2015-02-27 20:34:44 +0300 |
---|---|---|
committer | Mikkel Krautz <mikkel@krautz.dk> | 2015-04-22 22:03:53 +0300 |
commit | 6c446e4ead44a66b5706a95b410f5429e7890b9f (patch) | |
tree | f429fc5a3d33bbe7c57e5b608148dc143f499623 /overlay/overlay_exe | |
parent | b1880294df43d16ff03e927fba1572a027dac6aa (diff) |
Ensure overlay helpers exit when the Mumble process terminates.
Normally, Mumble itself will terminate the helper processes.
But if Mumble crashes, or is manually killed by the user, it
will not be able to terminate the helper processes itself.
In order to fix this, we create a way for the helpers to know
when their parent process has terminated.
This is implemented by creating an inheritable process handle
in Mumble, and passing its value to the helpers.
The helpers then WaitForSingleObject() on the parent handle, and
exits with status code 0 if it the WaitForSingleObject() call
returns successfully.
Diffstat (limited to 'overlay/overlay_exe')
-rw-r--r-- | overlay/overlay_exe/overlay_exe.cpp | 32 | ||||
-rw-r--r-- | overlay/overlay_exe/overlay_exe.h | 19 |
2 files changed, 44 insertions, 7 deletions
diff --git a/overlay/overlay_exe/overlay_exe.cpp b/overlay/overlay_exe/overlay_exe.cpp index be9dbc653..bee53bdf7 100644 --- a/overlay/overlay_exe/overlay_exe.cpp +++ b/overlay/overlay_exe/overlay_exe.cpp @@ -40,7 +40,7 @@ #define UNUSED(x) ((void)x) -typedef int (*OverlayHelperProcessMain)(unsigned int magic); +typedef int (*OverlayHelperProcessMain)(unsigned int magic, HANDLE parent); // Signal to the overlay DLL that it should not inject // into this process. @@ -116,6 +116,7 @@ int main(int argc, char **argv) { // display a nice alert dialog directing users to // 'mumble.exe' instead. unsigned int magic = 0; + HANDLE parent = 0; { std::wstring commandLine(GetCommandLine()); @@ -123,21 +124,40 @@ int main(int argc, char **argv) { // if the program was passed any arguments. If we don't // find them, it probably means that a user has double-clicked // the executable. Tell them to run 'mumble.exe' instead. - size_t sep = commandLine.find(std::wstring(L" ")); + std::wstring doubleSpace = std::wstring(L" "); + size_t sep = commandLine.find(doubleSpace); if (sep == std::string::npos) { Alert(L"Mumble Overlay", L"This program is not meant to be run by itself. Run 'mumble.exe' instead."); return OVERLAY_HELPER_ERROR_EXE_MISSING_MAGIC_ARGUMENT; } - // We expect that the Mumble process passes the overlay - // magic number that it is built with to us. - std::wstring magicNumberStr = commandLine.substr(sep); + // The Mumble process passes the overlay magic number, + // and a HANDLE in numeric form as its only two arguments. + // Let's try to parse the command line to extract them... + std::wstring args = commandLine.substr(sep + doubleSpace.length()); + sep = args.find(std::wstring(L" ")); + if (sep == std::string::npos) { + return OVERLAY_HELPER_ERROR_TOO_FEW_ARGUMENTS; + } + if (args.length() <= sep + 1) { + return OVERLAY_HELPER_ERROR_TOO_FEW_ARGUMENTS; + } + std::wstring magicNumberStr = args.substr(0, sep); + std::wstring handleStr = args.substr(sep+1); + try { unsigned long passedInMagic = std::stoul(magicNumberStr); magic = static_cast<unsigned int>(passedInMagic); } catch (std::exception &) { return OVERLAY_HELPER_ERROR_EXE_INVALID_MAGIC_ARGUMENT; } + + try { + unsigned long passedInHandle = std::stoul(handleStr); + parent = reinterpret_cast<HANDLE>(passedInHandle & 0xFFFFFFFFUL); + } catch(std::exception &) { + return OVERLAY_HELPER_ERROR_EXE_INVALID_HANDLE_ARGUMENT; + } } if (magic != OVERLAY_MAGIC_NUMBER) { @@ -163,7 +183,7 @@ int main(int argc, char **argv) { return OVERLAY_HELPER_ERROR_EXE_LOOKUP_ENTRY_POINT; } - return entryPoint(magic); + return entryPoint(magic, parent); } int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, wchar_t *cmdArg, int cmdShow) { diff --git a/overlay/overlay_exe/overlay_exe.h b/overlay/overlay_exe/overlay_exe.h index bbd9d2e20..e950aeed9 100644 --- a/overlay/overlay_exe/overlay_exe.h +++ b/overlay/overlay_exe/overlay_exe.h @@ -64,14 +64,27 @@ enum OverlayHelperError { /// the 'OverlayHelperProcessMain' entry point in the
/// overlay DLL.
OVERLAY_HELPER_ERROR_EXE_LOOKUP_ENTRY_POINT = -7,
+ /// The overlay helper process was uanble to parse
+ /// the commandline arguments it was passed.
+ /// The helper process exepcts two arguments, and this
+ /// error occurs if it only finds one.
+ OVERLAY_HELPER_ERROR_TOO_FEW_ARGUMENTS = -8,
+ /// The magic number on the command line of the overlay
+ /// helper process could not be converted to a HANDLE.
+ OVERLAY_HELPER_ERROR_EXE_INVALID_HANDLE_ARGUMENT = -9,
- /// The magic number passed to the overlay DLL's
+ /// The magic number passed to the overlay DLL's
/// OverlayHelperProcessMain function did not match
/// the overlay DLL's built-in magic number.
OVERLAY_HELPER_ERROR_DLL_MAGIC_MISMATCH = -1000,
/// The overlay helper process exited due to an error
/// in the Windows message loop.
OVERLAY_HELPER_ERROR_DLL_MESSAGE_LOOP = -1001,
+ /// The parent death thread could not be created.
+ OVERLAY_HELPER_ERROR_DLL_PDEATH_THREAD_ERROR = -1002,
+ /// The helper's WaitForSingleObject call on its parent
+ /// process failed unexpectedly.
+ OVERLAY_HELPER_ERROR_DLL_PDEATH_WAIT_FAIL = -1003,
};
/// OverlayHelperErrorToString converts an OverlayHelperError value
@@ -86,8 +99,12 @@ static inline const char *OverlayHelperErrorToString(OverlayHelperError err) { OHE(OVERLAY_HELPER_ERROR_EXE_GET_DLL_PATH);
OHE(OVERLAY_HELPER_ERROR_EXE_LOAD_DLL);
OHE(OVERLAY_HELPER_ERROR_EXE_LOOKUP_ENTRY_POINT);
+ OHE(OVERLAY_HELPER_ERROR_TOO_FEW_ARGUMENTS);
+ OHE(OVERLAY_HELPER_ERROR_EXE_INVALID_HANDLE_ARGUMENT);
OHE(OVERLAY_HELPER_ERROR_DLL_MAGIC_MISMATCH);
OHE(OVERLAY_HELPER_ERROR_DLL_MESSAGE_LOOP);
+ OHE(OVERLAY_HELPER_ERROR_DLL_PDEATH_THREAD_ERROR);
+ OHE(OVERLAY_HELPER_ERROR_DLL_PDEATH_WAIT_FAIL);
}
return NULL;
}
|