diff options
Diffstat (limited to 'source/creator')
-rw-r--r-- | source/creator/CMakeLists.txt | 11 | ||||
-rw-r--r-- | source/creator/blender-launcher.c | 92 |
2 files changed, 102 insertions, 1 deletions
diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c2893317924..baea3ad1f9b 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -285,6 +285,15 @@ if(WITH_PYTHON_MODULE) else() add_executable(blender ${EXETYPE} ${SRC}) + if(WIN32) + add_executable(blender-launcher WIN32 + blender-launcher.c + ${CMAKE_SOURCE_DIR}/release/windows/icons/winblender.rc + ${CMAKE_BINARY_DIR}/blender.exe.manifest + ) + target_compile_definitions (blender-launcher PRIVATE -D_UNICODE -DUNICODE) + target_link_libraries(blender-launcher Pathcch.lib) + endif() endif() if(WITH_BUILDINFO) @@ -1212,7 +1221,7 @@ endif() if(WIN32 AND NOT WITH_PYTHON_MODULE) install( - TARGETS blender + TARGETS blender blender-launcher COMPONENT Blender DESTINATION "." ) diff --git a/source/creator/blender-launcher.c b/source/creator/blender-launcher.c new file mode 100644 index 00000000000..86b0f4f3b97 --- /dev/null +++ b/source/creator/blender-launcher.c @@ -0,0 +1,92 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <Windows.h> +#include <strsafe.h> + +#include <PathCch.h> + +int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) +{ + STARTUPINFO siStartInfo = {0}; + PROCESS_INFORMATION procInfo; + wchar_t path[MAX_PATH]; + + siStartInfo.wShowWindow = SW_HIDE; + siStartInfo.dwFlags = STARTF_USESHOWWINDOW; + + /* Get the path to the currently running executable (blender-launcher.exe) */ + + DWORD nSize = GetModuleFileName(NULL, path, MAX_PATH); + if (!nSize) { + return -1; + } + + /* GetModuleFileName returns the number of characters written, but GetLastError needs to be + * called to see if it ran out of space or not. However where would we be without exceptions + * to the rule: "If the buffer is too small to hold the module name, the function returns nSize. + * The last error code remains ERROR_SUCCESS." - source: MSDN. */ + + if (GetLastError() == ERROR_SUCCESS && nSize == MAX_PATH) { + return -1; + } + + /* Remove the filename (blender-launcher.exe) from path. */ + if (PathCchRemoveFileSpec(path, MAX_PATH) != S_OK) { + return -1; + } + + /* Add blender.exe to path, resulting in the full path to the blender executable. */ + if (PathCchCombine(path, MAX_PATH, path, L"blender.exe") != S_OK) { + return -1; + } + + int required_size_chars = lstrlenW(path) + /* Module name */ + 3 + /* 2 quotes + Space */ + lstrlenW(pCmdLine) + /* Original command line */ + 1; /* Zero terminator */ + size_t required_size_bytes = required_size_chars * sizeof(wchar_t); + wchar_t *buffer = (wchar_t *)malloc(required_size_bytes); + if (!buffer) { + return -1; + } + + if (StringCbPrintfEx(buffer, + required_size_bytes, + NULL, + NULL, + STRSAFE_NULL_ON_FAILURE, + L"\"%s\" %s", + path, + pCmdLine) != S_OK) { + free(buffer); + return -1; + } + + BOOL success = CreateProcess( + path, buffer, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &siStartInfo, &procInfo); + + if (success) { + /* Handles in PROCESS_INFORMATION must be closed with CloseHandle when they are no longer + * needed - MSDN. Closing the handles will NOT terminate the thread/process that we just + * started. */ + CloseHandle(procInfo.hThread); + CloseHandle(procInfo.hProcess); + } + + free(buffer); + return success ? 0 : -1; +} |