diff --git a/docs/dev/TheMumbleSourceCode.md b/docs/dev/TheMumbleSourceCode.md index 23389c9f274..c6a2b9c9d4b 100644 --- a/docs/dev/TheMumbleSourceCode.md +++ b/docs/dev/TheMumbleSourceCode.md @@ -41,7 +41,6 @@ When cloning the repo, the source tree should look something like this: ├── src │   ├── crypto │   ├── mumble -│   ├── mumble_exe │   ├── murmur │   └── tests └── themes @@ -81,11 +80,8 @@ mainly occupied by various scripts used throughout various tasks surrounding Mum default configuration file for the Mumble server. Your main focus should lie on the `src` directory as this is where the bulk of Mumble's source code is living. Directly in `src/` are shared sources -that are used by the Mumble client as well as by the server that live in `src/mumble` and `src/murmur` respectively. The `src/mumble_exe` direcrtory -contains code for the Windows-specific executable. In order to make sense of that you have to know that on Windows we are currently using a bit of an -odd system: The main application is packaged inside a DLL that is loaded by the main executable. This is a historic artifact and currently only -serves to create problems every now and then. In any case though, the mentioned "main executable" whose sole job is loading of that DLL lives in -`mumble_exe`. Generally you don't have to worry about it. The remaining directories within `src` should be somewhat self-explanatory. +that are used by the Mumble client as well as by the server that live in `src/mumble` and `src/murmur` respectively. The remaining directories within +`src` should be somewhat self-explanatory. The `themes` directory contains all built-in themes that are currently shipped with Mumble. At this point there is only one theme available: the `Default` theme (note that it contains the Lite and the Dark theme variant). If you want to customize any kind of icons within Mumble, this is the diff --git a/installer/ClientInstaller.cs b/installer/ClientInstaller.cs index d95c7ff42c5..778ea6845b7 100644 --- a/installer/ClientInstaller.cs +++ b/installer/ClientInstaller.cs @@ -89,7 +89,6 @@ public ClientInstaller(string version, string arch, Features features) { "rnnoise.dll", "speexdsp.dll", "mumble.exe", - "mumble_app.dll", }; if (features.overlay) { @@ -109,7 +108,6 @@ public ClientInstaller(string version, string arch, Features features) { "rnnoise.dll", "speexdsp.dll", "mumble.exe", - "mumble_app.dll", }; if (features.overlay) { diff --git a/src/mumble/CMakeLists.txt b/src/mumble/CMakeLists.txt index dbbbada4f46..be7d539c8b1 100644 --- a/src/mumble/CMakeLists.txt +++ b/src/mumble/CMakeLists.txt @@ -11,7 +11,6 @@ set(MUMBLE_ICON "${CMAKE_SOURCE_DIR}/icons/mumble.ico") set(MUMBLE_ICNS "${CMAKE_SOURCE_DIR}/icons/mumble.icns") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mumble.rc.in" "${MUMBLE_RC}") -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mumble_dll.rc.in" "${MUMBLE_DLL_RC}") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/mumble.plist.in" "${MUMBLE_PLIST}") include(qt-utils) @@ -333,42 +332,31 @@ list(APPEND MUMBLE_SOURCES "${CMAKE_BINARY_DIR}/mumble_flags.qrc") add_library(mumble_client_object_lib OBJECT ${MUMBLE_SOURCES}) -if(static AND WIN32) - # On Windows, building a static client means building the main app into a DLL. - add_library(mumble SHARED "main.cpp") - target_compile_definitions(mumble_client_object_lib PUBLIC "MUMBLEAPP_DLL") - - set_target_properties(mumble PROPERTIES OUTPUT_NAME "mumble_app") - if(MINGW) - # Remove "lib" prefix. - set_target_properties(mumble PROPERTIES PREFIX "") - endif() - - target_sources(mumble_client_object_lib PRIVATE "${MUMBLE_DLL_RC}") - - add_subdirectory("${SHARED_SOURCE_DIR}/mumble_exe" "${CMAKE_BINARY_DIR}/mumble_exe") +if(WIN32 AND NOT CMAKE_BUILD_TYPE STREQUAL "Debug") + # We don't want the console to appear in release builds. + add_executable(mumble WIN32 "main.cpp") else() add_executable(mumble "main.cpp") +endif() - if(WIN32) - target_sources(mumble_client_object_lib - PRIVATE - "${CMAKE_SOURCE_DIR}/auxiliary_files/mumble.appcompat.manifest" - "${MUMBLE_RC}" - ) +if(WIN32) + target_sources(mumble_client_object_lib + PRIVATE + "${CMAKE_SOURCE_DIR}/auxiliary_files/mumble.appcompat.manifest" + "${MUMBLE_RC}" + ) - if(elevation) - set_property(TARGET mumble APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level=\'asInvoker\' uiAccess=\'true\'\"") - endif() - elseif(APPLE) - set_target_properties(mumble - PROPERTIES - OUTPUT_NAME "Mumble" - MACOSX_BUNDLE TRUE - RESOURCE ${MUMBLE_ICNS} - MACOSX_BUNDLE_INFO_PLIST ${MUMBLE_PLIST} - ) + if(elevation) + set_property(TARGET mumble APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level=\'asInvoker\' uiAccess=\'true\'\"") endif() +elseif(APPLE) + set_target_properties(mumble + PROPERTIES + OUTPUT_NAME "Mumble" + MACOSX_BUNDLE TRUE + RESOURCE ${MUMBLE_ICNS} + MACOSX_BUNDLE_INFO_PLIST ${MUMBLE_PLIST} + ) endif() add_custom_command( @@ -1144,3 +1132,44 @@ endif() target_include_directories(${TARGET_NAME} INTERFACE $ ) + +if(packaging) + set(overlay ON) + set(plugins ON) + + if(translations) + list(APPEND installer_vars "--all-languages") + endif() + + + list(APPEND installer_vars + "--version" ${PROJECT_VERSION} + "--arch" "${MUMBLE_TARGET_ARCH}" + ) + + if(overlay) + list(APPEND installer_vars + "--overlay" + ) + endif() + + if(g15) + list(APPEND installer_vars + "--g15" + ) + endif() + + file(COPY + ${CMAKE_SOURCE_DIR}/installer/MumbleInstall.cs + ${CMAKE_SOURCE_DIR}/installer/ClientInstaller.cs + DESTINATION + ${CMAKE_BINARY_DIR}/installer/client + ) + + add_custom_command(TARGET mumble + POST_BUILD + COMMAND cscs.exe -cd MumbleInstall.cs + COMMAND cscs.exe ClientInstaller.cs ${installer_vars} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/installer/client + ) +endif() diff --git a/src/mumble/Overlay_win.cpp b/src/mumble/Overlay_win.cpp index 203b7dda00a..0f67bd5b0fb 100644 --- a/src/mumble/Overlay_win.cpp +++ b/src/mumble/Overlay_win.cpp @@ -17,10 +17,6 @@ #include "../../overlay/overlay_exe/overlay_exe.h" // Used by the overlay to detect whether we injected into ourselves. -// -// A similar declaration can be found in mumble_exe's Overlay.cpp, -// for the overlay's self-detection checks to continue working in a -// mumble_app.dll world. extern "C" __declspec(dllexport) void mumbleSelfDetection(){}; // Determine if the current Mumble client is able to host diff --git a/src/mumble/main.cpp b/src/mumble/main.cpp index 1688f5f2a30..9daee17ef8f 100644 --- a/src/mumble/main.cpp +++ b/src/mumble/main.cpp @@ -132,11 +132,7 @@ extern int os_early_init(); extern HWND mumble_mw_hwnd; #endif // Q_OS_WIN -#if defined(Q_OS_WIN) && !defined(MUMBLEAPP_DLL) -extern "C" __declspec(dllexport) int main(int argc, char **argv) { -#else int main(int argc, char **argv) { -#endif int res = 0; #if defined(Q_OS_WIN) @@ -958,31 +954,3 @@ int main(int argc, char **argv) { } return res; } - -#if defined(Q_OS_WIN) && defined(MUMBLEAPP_DLL) -extern "C" __declspec(dllexport) int MumbleMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdArg, int cmdShow) { - Q_UNUSED(instance) - Q_UNUSED(prevInstance) - Q_UNUSED(cmdArg) - Q_UNUSED(cmdShow) - - int argc; - wchar_t **argvW = CommandLineToArgvW(GetCommandLineW(), &argc); - if (!argvW) { - return -1; - } - - QVector< QByteArray > argvS; - argvS.reserve(argc); - - QVector< char * > argvV(argc, nullptr); - for (int i = 0; i < argc; ++i) { - argvS.append(QString::fromWCharArray(argvW[i]).toLocal8Bit()); - argvV[i] = argvS.back().data(); - } - - LocalFree(argvW); - - return main(argc, argvV.data()); -} -#endif diff --git a/src/mumble/mumble_dll.rc.in b/src/mumble/mumble_dll.rc.in deleted file mode 100755 index 33a62444f3b..00000000000 --- a/src/mumble/mumble_dll.rc.in +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2005-2020 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 . - -#include - -#ifndef DEBUG -#define VER_DEBUG 0L -#else -#define VER_DEBUG VS_FF_DEBUG -#endif - -#ifdef SNAPSHOT_BUILD -#define VER_RELEASE VS_FF_SPECIALBUILD|VS_FF_PRERELEASE -#else -#define VER_RELEASE 0L -#endif - -VS_VERSION_INFO VERSIONINFO - FILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@ - PRODUCTVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VERSION_MINOR@,@PROJECT_VERSION_PATCH@ - FILEFLAGSMASK VS_FFI_FILEFLAGSMASK - FILEFLAGS (VER_DEBUG|VER_RELEASE) - FILEOS VOS_NT_WINDOWS32 - FILETYPE VFT_DLL - FILESUBTYPE 0L - BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904E4" - BEGIN - VALUE "CompanyName", "The Mumble Developers" - VALUE "FileDescription", "Mumble - Low-latency VoIP client" - VALUE "FileVersion", "@PROJECT_VERSION@" - VALUE "ProductVersion", "@PROJECT_VERSION@" - VALUE "LegalCopyright", "Copyright (c) 2005-@MUMBLE_BUILD_YEAR@ The Mumble Developers" - VALUE "OriginalFilename", "mumble_app.dll" - VALUE "ProductName", "Mumble" -#ifdef SNAPSHOT_BUILD - VALUE "SpecialBuild", "Snapshot development release" -#endif - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1252 - END - END diff --git a/src/mumble_exe/CMakeLists.txt b/src/mumble_exe/CMakeLists.txt deleted file mode 100644 index d81974292c4..00000000000 --- a/src/mumble_exe/CMakeLists.txt +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright 2020-2023 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 . - -add_executable(mumble_exe WIN32) - -target_include_directories(mumble_exe PRIVATE "${SHARED_SOURCE_DIR}") - -configure_file("${SHARED_SOURCE_DIR}/mumble/mumble.rc.in" "${CMAKE_CURRENT_BINARY_DIR}/mumble.rc") - -target_sources(mumble_exe PRIVATE - "mumble_exe.cpp" - "Overlay.cpp" - - "${CMAKE_SOURCE_DIR}/auxiliary_files/mumble.appcompat.manifest" - "${MUMBLE_RC}" -) - -set_target_properties(mumble_exe - PROPERTIES - OUTPUT_NAME "mumble" - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} -) - -if(MINGW) - target_link_options(mumble_exe PRIVATE "-municode") -endif() - -if(MSVC) - # Set "/MT" for release builds and "/MTd" for debug ones. - set_target_properties(mumble_exe PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") -endif() - -if(elevation) - set_property(TARGET mumble_exe APPEND_STRING PROPERTY LINK_FLAGS " /MANIFESTUAC:\"level=\'asInvoker\' uiAccess=\'true\'\"") -endif() - -add_dependencies(mumble_exe mumble) - -if(overlay) - add_dependencies(mumble_exe overlay_exe) -endif() - -target_link_libraries(mumble_exe PRIVATE shlwapi.lib) - -install(TARGETS mumble_exe RUNTIME DESTINATION "${MUMBLE_INSTALL_EXECUTABLEDIR}" COMPONENT mumble_client) - -if(packaging) - set(overlay ON) - set(plugins ON) - - if(translations) - list(APPEND installer_vars "--all-languages") - endif() - - - list(APPEND installer_vars - "--version" ${PROJECT_VERSION} - "--arch" "${MUMBLE_TARGET_ARCH}" - ) - - if(overlay) - list(APPEND installer_vars - "--overlay" - ) - endif() - - if(g15) - list(APPEND installer_vars - "--g15" - ) - endif() - - file(COPY - ${CMAKE_SOURCE_DIR}/installer/MumbleInstall.cs - ${CMAKE_SOURCE_DIR}/installer/ClientInstaller.cs - DESTINATION - ${CMAKE_BINARY_DIR}/installer/client - ) - - add_custom_command(TARGET mumble_exe - POST_BUILD - COMMAND cscs.exe -cd MumbleInstall.cs - COMMAND cscs.exe ClientInstaller.cs ${installer_vars} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/installer/client - ) -endif() diff --git a/src/mumble_exe/Overlay.cpp b/src/mumble_exe/Overlay.cpp deleted file mode 100644 index d3908905701..00000000000 --- a/src/mumble_exe/Overlay.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013-2023 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 . - -// Used by the overlay to detect whether we injected into ourselves. -// -// This code also lives in Overlay_win.cpp, where it serves the same purpose. -// -// When running in "mumble_app.dll"-mode, it's convenient for this symbol to be -// defined here in mumble.exe (alongside the symbol in mumble_app.dll) because that -// allows older versions of mumble_ol.dll that are not "mumble_app.dll"-aware at all -// to continue to work in that world. -extern "C" __declspec(dllexport) void mumbleSelfDetection(){}; diff --git a/src/mumble_exe/mumble_exe.cpp b/src/mumble_exe/mumble_exe.cpp deleted file mode 100644 index a59fcf408ef..00000000000 --- a/src/mumble_exe/mumble_exe.cpp +++ /dev/null @@ -1,223 +0,0 @@ -// Copyright 2013-2023 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 . - -#include "win.h" - -#include -#include - -#include - -typedef int (*DLL_MAIN)(HINSTANCE, HINSTANCE, LPSTR, int); -#ifdef DEBUG -typedef int (*DLL_DEBUG_MAIN)(int, char **); -#endif - -// 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); -} - -// Get the current Mumble version built into this executable. -// If no version is available, this function returns an empty -// string. -static const std::wstring GetMumbleVersion() { -#ifdef MUMBLE_VERSION -# define MUMXTEXT(X) L# X -# define MUMTEXT(X) MUMXTEXT(X) - const std::wstring version(MUMTEXT(MUMBLE_VERSION)); - return version; -#else - return std::wstring(); -#endif -} - -// GetExecutableDirPath returns the directory that -// mumble.exe resides in. -static const 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 exe_path(path); - return exe_path.append(L"\\"); -} - -// GetVersionedRootPath returns the versioned root path if -// Mumble is configured to work with versioned paths. -// If Mumble is not configured for versioned paths, this -// function returns an empty string. -static const std::wstring GetVersionedRootPath() { - const std::wstring versionedRootPath = GetExecutableDirPath(); - if (versionedRootPath.empty()) { - return std::wstring(); - } - - const std::wstring version = GetMumbleVersion(); - if (version.length() > 0) { - return versionedRootPath + L"Versions\\" + version; - } - - return std::wstring(); -} - -// ConfigureEnvironment prepares mumble.exe's environment to -// run mumble_app.dll. -static bool ConfigureEnvironment() { - // Remove the current directory from the DLL search path. - if (!SetDllDirectoryW(L"")) - return false; - - // Set the versioned root as the working directory if one is available. - // If not, use the directory containing mumble.exe as the working directory. - // - // We use the versioned root as the working directory because of an odd - // interaction between the UCRT's forward exports and LoadLibraryEx. - // Most likely a bug in older Windows versions (Windows 10 is unaffected). - // - // In Mumble, mumble_app.dll is loaded via - // - // LoadLibraryEx(..., ..., LOAD_WITH_ALTERED_SEARCH_PATH). - // - // This works on Windows 10, but is broken on Windows 7. On Windows 7, it - // seems like the forward exports from api-win-ms*.dll to ucrtbase.dll cause - // ucrtbase.dll to be loaded WITHOUT LOAD_WITH_ALTERED_SEARCH_PATH, but instead - // using Standard Search Order For Desktop Applications. - // - // It looks for ucrtbase.dll in the following locations: - // - // 1. Next to the .exe - // 2. 32-bit system directory - // 3. 16-bit system directory - // 4. Windows folder - // 5. CWD - // 6. %PATH% (seemingly)... - // - // But the application doesn't run, since it doesn't even try to load - // ucrtbase.dll in the directory containing mumble_app.dll as it should, - // because we've loaded mumble_app.dll with LOAD_WITH_ALTERED_SEARCH_PATH. - // - // Our workaround is to use the mumble_app.dll's directory as the working - // directory. This causes the program to successfully load, even when - // ucrtbase.dll is loaded using the Standard Search Order For Desktop. - // - // See https://github.com/mumble-voip/mumble/issues/2837 for more information. - std::wstring cwd = GetVersionedRootPath(); - if (cwd.empty()) { - cwd = GetExecutableDirPath(); - } - if (!SetCurrentDirectoryW(cwd.c_str())) - return false; - - return true; -} - -// GetAbsoluteMumbleAppDllPath returns the absolute path to -// mumble_app.dll - the DLL containing the Mumble client -// application code. -static const std::wstring GetAbsoluteMumbleAppDllPath(std::wstring suggested_base_dir) { - std::wstring base_dir = suggested_base_dir; - - if (base_dir.empty()) { - base_dir = GetExecutableDirPath(); - } - - if (base_dir.empty()) { - return std::wstring(); - } - - return base_dir + L"\\mumble_app.dll"; -} - -#ifdef DEBUG -int main(int argc, char **argv) { - if (!ConfigureEnvironment()) { - Alert(L"Mumble Launcher Error -1", L"Unable to configure environment."); - return -1; - } - - std::wstring versioned_root_path = GetVersionedRootPath(); - - bool ok = false; - if (!versioned_root_path.empty()) { - if (PathFileExists(versioned_root_path.c_str())) { - _wputenv_s(L"MUMBLE_VERSION_ROOT", versioned_root_path.c_str()); - ok = true; - } - } - if (!ok) { - _wputenv_s(L"MUMBLE_VERSION_ROOT", L""); - } - - std::wstring abs_dll_path = GetAbsoluteMumbleAppDllPath(ok ? versioned_root_path : std::wstring()); - if (abs_dll_path.empty()) { - Alert(L"Mumble Launcher Error -2", L"Unable to find the absolute path of mumble_app.dll."); - return -2; - } - - HMODULE dll = LoadLibraryExW(abs_dll_path.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!dll) { - Alert(L"Mumble Launcher Error -3", L"Failed to load mumble_app.dll."); - return -3; - } - - DLL_DEBUG_MAIN entry_point = reinterpret_cast< DLL_DEBUG_MAIN >(GetProcAddress(dll, "main")); - if (!entry_point) { - Alert(L"Mumble Launcher Error -4", L"Unable to find expected entry point ('main') in mumble_app.dll."); - return -4; - } - - int rc = entry_point(argc, argv); - - return rc; -} -#endif // DEBUG - -int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE prevInstance, wchar_t *cmdArg, int cmdShow) { - if (!ConfigureEnvironment()) { - Alert(L"Mumble Launcher Error -1", L"Unable to configure environment."); - return -1; - } - - std::wstring versioned_root_path = GetVersionedRootPath(); - - bool ok = false; - if (!versioned_root_path.empty()) { - if (PathFileExists(versioned_root_path.c_str())) { - _wputenv_s(L"MUMBLE_VERSION_ROOT", versioned_root_path.c_str()); - ok = true; - } - } - if (!ok) { - _wputenv_s(L"MUMBLE_VERSION_ROOT", L""); - } - - std::wstring abs_dll_path = GetAbsoluteMumbleAppDllPath(ok ? versioned_root_path : std::wstring()); - if (abs_dll_path.empty()) { - Alert(L"Mumble Launcher Error -2", L"Unable to find the absolute path of mumble_app.dll."); - return -2; - } - - HMODULE dll = LoadLibraryExW(abs_dll_path.c_str(), nullptr, LOAD_WITH_ALTERED_SEARCH_PATH); - if (!dll) { - Alert(L"Mumble Launcher Error -3", L"Failed to load mumble_app.dll."); - return -3; - } - - DLL_MAIN entry_point = reinterpret_cast< DLL_MAIN >(GetProcAddress(dll, "MumbleMain")); - if (!entry_point) { - Alert(L"Mumble Launcher Error -4", L"Unable to find expected entry point ('MumbleMain') in mumble_app.dll."); - return -4; - } - - (void) cmdArg; - int rc = entry_point(instance, prevInstance, nullptr, cmdShow); - - return rc; -}