mirror of
https://github.com/mumble-voip/mumble.git
synced 2025-03-14 20:53:06 +00:00

Keeping these up-to-date is just super tedious and they don't really fulfill any purpose these days.
194 lines
5.5 KiB
C++
194 lines
5.5 KiB
C++
// Copyright The Mumble Developers. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license
|
|
// that can be found in the LICENSE file at the root of the
|
|
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
|
|
|
|
#include <windows.h>
|
|
#include <shellapi.h>
|
|
#include <shlwapi.h>
|
|
#include <stdio.h>
|
|
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "../overlay.h"
|
|
#include "overlay_exe.h"
|
|
|
|
#define UNUSED(x) ((void) x)
|
|
|
|
typedef int (*OverlayHelperProcessMain)(unsigned int magic, HANDLE parent);
|
|
|
|
// Signal to the overlay DLL that it should not inject
|
|
// into this process.
|
|
extern "C" __declspec(dllexport) void mumbleSelfDetection(){};
|
|
|
|
// Alert shows a fatal error dialog and waits for the user to click OK.
|
|
static void Alert(LPCWSTR title, LPCWSTR msg) {
|
|
MessageBox(nullptr, msg, title, MB_OK | MB_ICONERROR);
|
|
}
|
|
|
|
// GetExecutableDirPath returns the directory that
|
|
// mumble_ol_helper.exe resides in.
|
|
static std::wstring GetExecutableDirPath() {
|
|
wchar_t path[MAX_PATH];
|
|
|
|
if (GetModuleFileNameW(nullptr, path, MAX_PATH) == 0)
|
|
return std::wstring();
|
|
|
|
if (!PathRemoveFileSpecW(path))
|
|
return std::wstring();
|
|
|
|
std::wstring exePath(path);
|
|
return exePath.append(L"\\");
|
|
}
|
|
|
|
// ConfigureEnvironment prepares mumble_ol_helper.exe's environment to
|
|
// run mumble_ol.dll's OverlayHelperProcessMain() function.
|
|
static bool ConfigureEnvironment() {
|
|
std::wstring exePath = GetExecutableDirPath();
|
|
|
|
// Remove the current directory from the DLL search path.
|
|
if (!SetDllDirectoryW(L""))
|
|
return false;
|
|
|
|
// Set mumble_ol_helper.exe's directory as the current working directory.
|
|
if (!SetCurrentDirectoryW(exePath.c_str()))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
// GetAbsoluteMumbleOverlayDllPath returns the absolute path to
|
|
// mumble_ol.dll - the DLL containing the Mumble overlay code.
|
|
static std::wstring GetAbsoluteMumbleOverlayDllPath() {
|
|
std::wstring exePath = GetExecutableDirPath();
|
|
if (exePath.empty())
|
|
return std::wstring();
|
|
|
|
std::wstring absDLLPath(exePath);
|
|
absDLLPath.append(L"\\");
|
|
absDLLPath.append(MUMBLE_OVERLAY_DLL_NAME);
|
|
return absDLLPath;
|
|
}
|
|
|
|
// GetCommandLineArgs returns the command line arguments
|
|
// passed to the process.
|
|
// If the returned vector has a length of 0, an unknown
|
|
// error occurred.
|
|
static std::vector< std::wstring > GetCommandLineArgs() {
|
|
std::vector< std::wstring > args;
|
|
|
|
LPWSTR cmdLine = GetCommandLine();
|
|
if (!cmdLine) {
|
|
return args;
|
|
}
|
|
|
|
int argc = 0;
|
|
LPWSTR *argv = CommandLineToArgvW(cmdLine, &argc);
|
|
if (!argv) {
|
|
return args;
|
|
}
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
args.push_back(std::wstring(argv[i]));
|
|
}
|
|
|
|
return args;
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
UNUSED(argc);
|
|
UNUSED(argv);
|
|
|
|
// Mumble passes the OVERLAY_MAGIC_NUMBER it was built
|
|
// with the first argument to this helper process.
|
|
//
|
|
// This is done for two reasons.
|
|
//
|
|
// The first reason is that we need to ensure
|
|
// compatibility between Mumble, the overlay helper,
|
|
// and the overlay itself.
|
|
//
|
|
// The second reason is that it is an easy way to catch
|
|
// users accidentally double-clicking on the overlay
|
|
// helper's EXE file. We can detect these non-Mumble
|
|
// initiated launches by checking if we were passed any
|
|
// arguments at all. If no parameters are passed, we
|
|
// display a nice alert dialog directing users to
|
|
// 'mumble.exe' instead.
|
|
unsigned int magic = 0;
|
|
HANDLE parent = 0;
|
|
{
|
|
std::vector< std::wstring > args = GetCommandLineArgs();
|
|
|
|
// If there is only a single argument, it's the program name.
|
|
// That probably means that a user has double-clicked
|
|
// the executable. Tell them to run 'mumble.exe' instead.
|
|
//
|
|
// This also handles the case where GetCommandLineArgs returns
|
|
// an empty vector (the error case).
|
|
if (args.size() <= 1) {
|
|
Alert(L"Mumble Overlay", L"This program is not meant to be run by itself. Run 'mumble.exe' instead.");
|
|
return OVERLAY_HELPER_ERROR_EXE_NO_ARGUMENTS;
|
|
}
|
|
|
|
// The Mumble process passes the overlay magic number,
|
|
// and a HANDLE in numeric form as its only two arguments.
|
|
// We must have both of them to continue.
|
|
if (args.size() < 3) {
|
|
return OVERLAY_HELPER_ERROR_TOO_FEW_ARGUMENTS;
|
|
}
|
|
|
|
std::wstring magicNumberStr = args[1];
|
|
std::wstring handleStr = args[2];
|
|
|
|
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 long passedInHandle = std::stoull(handleStr);
|
|
parent = reinterpret_cast< HANDLE >(passedInHandle & 0xFFFFFFFFULL);
|
|
} catch (std::exception &) {
|
|
return OVERLAY_HELPER_ERROR_EXE_INVALID_HANDLE_ARGUMENT;
|
|
}
|
|
}
|
|
|
|
if (magic != OVERLAY_MAGIC_NUMBER) {
|
|
return OVERLAY_HELPER_ERROR_EXE_MAGIC_MISMATCH;
|
|
}
|
|
|
|
if (!ConfigureEnvironment()) {
|
|
return OVERLAY_HELPER_ERROR_EXE_CONFIGURE_ENVIRONMENT;
|
|
}
|
|
|
|
std::wstring absDLLPath = GetAbsoluteMumbleOverlayDllPath();
|
|
if (absDLLPath.empty()) {
|
|
return OVERLAY_HELPER_ERROR_EXE_GET_DLL_PATH;
|
|
}
|
|
|
|
HMODULE dll = LoadLibraryExW(absDLLPath.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH);
|
|
if (!dll) {
|
|
return OVERLAY_HELPER_ERROR_EXE_LOAD_DLL;
|
|
}
|
|
|
|
OverlayHelperProcessMain entryPoint =
|
|
reinterpret_cast< OverlayHelperProcessMain >(GetProcAddress(dll, "OverlayHelperProcessMain"));
|
|
if (!entryPoint) {
|
|
return OVERLAY_HELPER_ERROR_EXE_LOOKUP_ENTRY_POINT;
|
|
}
|
|
|
|
return entryPoint(magic, parent);
|
|
}
|
|
|
|
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, wchar_t *cmdArg, int cmdShow) {
|
|
UNUSED(instance);
|
|
UNUSED(prevInstance);
|
|
UNUSED(cmdArg);
|
|
UNUSED(cmdShow);
|
|
|
|
return main(0, nullptr);
|
|
}
|