diff --git a/desktop/Executable_unopkg.mk b/desktop/Executable_unopkg.mk index f1b6d6be6db9..28a753a570f5 100644 --- a/desktop/Executable_unopkg.mk +++ b/desktop/Executable_unopkg.mk @@ -21,7 +21,7 @@ $(eval $(call gb_Executable_use_system_win32_libs,unopkg,\ )) $(eval $(call gb_Executable_add_exception_objects,unopkg,\ - desktop/win32/source/guiloader/genericloader \ + desktop/win32/source/officeloader/unopkg_exe \ )) $(eval $(call gb_Executable_add_default_nativeres,unopkg)) diff --git a/desktop/Executable_unopkg_bin.mk b/desktop/Executable_unopkg_bin.mk index d2e1175be236..f66d5ec25e0f 100644 --- a/desktop/Executable_unopkg_bin.mk +++ b/desktop/Executable_unopkg_bin.mk @@ -9,7 +9,7 @@ $(eval $(call gb_Executable_Executable,unopkg_bin)) -$(eval $(call gb_Executable_set_targettype_gui,unopkg_bin,YES)) +$(eval $(call gb_Executable_set_targettype_gui,unopkg_bin,NO)) $(eval $(call gb_Executable_set_include,unopkg_bin,\ $$(INCLUDE) \ diff --git a/desktop/Executable_unopkg_com.mk b/desktop/Executable_unopkg_com.mk index 616a757a7fa8..022479f05bbc 100644 --- a/desktop/Executable_unopkg_com.mk +++ b/desktop/Executable_unopkg_com.mk @@ -11,8 +11,17 @@ $(eval $(call gb_Executable_Executable,unopkg_com)) $(eval $(call gb_Executable_set_targettype_gui,unopkg_com,NO)) +$(eval $(call gb_Executable_use_static_libraries,unopkg_com,\ + ooopathutils \ + winloader \ +)) + +$(eval $(call gb_Executable_use_system_win32_libs,unopkg_com,\ + shell32 \ +)) + $(eval $(call gb_Executable_add_exception_objects,unopkg_com,\ - desktop/win32/source/guistdio/unopkgio \ + desktop/win32/source/officeloader/unopkg_com \ )) $(eval $(call gb_Executable_add_default_nativeres,unopkg_com)) diff --git a/desktop/win32/source/guiloader/genericloader.cxx b/desktop/win32/source/guiloader/genericloader.cxx deleted file mode 100644 index be83ebe8effc..000000000000 --- a/desktop/win32/source/guiloader/genericloader.cxx +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#include -#include "../loader.hxx" - -static int GenericMain() -{ - WCHAR szTargetFileName[MAX_PATH]; - WCHAR szIniDirectory[MAX_PATH]; - STARTUPINFOW aStartupInfo; - - desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); - - ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); - aStartupInfo.cb = sizeof(aStartupInfo); - - GetStartupInfoW( &aStartupInfo ); - - DWORD dwExitCode = DWORD(-1); - - PROCESS_INFORMATION aProcessInfo; - - size_t iniDirLen = wcslen(szIniDirectory); - WCHAR cwd[MAX_PATH]; - DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); - if (cwdLen >= MAX_PATH) { - cwdLen = 0; - } - WCHAR redirect[MAX_PATH]; - DWORD dummy; - bool hasRedirect = - tools::buildPath( - redirect, szIniDirectory, szIniDirectory + iniDirLen, - MY_STRING(L"redirect.ini")) != nullptr && - (GetBinaryTypeW(redirect, &dummy) || // cheaper check for file existence? - GetLastError() != ERROR_FILE_NOT_FOUND); - LPWSTR cl1 = GetCommandLineW(); - WCHAR * cl2 = new WCHAR[ - wcslen(cl1) + - (hasRedirect - ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") + - iniDirLen + MY_LENGTH(L"redirect.ini\"")) - : 0) + - MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1]; - // 4 * cwdLen: each char preceded by backslash, each trailing backslash - // doubled - WCHAR * p = desktop_win32::commandLineAppend(cl2, cl1); - if (hasRedirect) { - p = desktop_win32::commandLineAppend( - p, MY_STRING(L" \"-env:INIFILENAME=vnd.sun.star.pathname:")); - p = desktop_win32::commandLineAppend(p, szIniDirectory); - p = desktop_win32::commandLineAppend(p, MY_STRING(L"redirect.ini\"")); - } - p = desktop_win32::commandLineAppend(p, MY_STRING(L" \"-env:OOO_CWD=")); - if (cwdLen == 0) { - p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); - } else { - p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); - p = desktop_win32::commandLineAppendEncoded(p, cwd); - } - desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); - - bool fSuccess = CreateProcessW( - szTargetFileName, - cl2, - nullptr, - nullptr, - TRUE, - 0, - nullptr, - szIniDirectory, - &aStartupInfo, - &aProcessInfo ); - - delete[] cl2; - - if ( fSuccess ) - { - DWORD dwWaitResult; - - do - { - // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so - // as if we where processing any messages - - dwWaitResult = MsgWaitForMultipleObjects( 1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS ); - - if ( WAIT_OBJECT_0 + 1 == dwWaitResult ) - { - MSG msg; - - PeekMessageW( &msg, nullptr, 0, 0, PM_REMOVE ); - } - } while ( WAIT_OBJECT_0 + 1 == dwWaitResult ); - - dwExitCode = 0; - GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); - - CloseHandle( aProcessInfo.hProcess ); - CloseHandle( aProcessInfo.hThread ); - } - - return dwExitCode; -} - -int WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int ) -{ - return GenericMain(); -} - -int __cdecl wmain() -{ - return GenericMain(); -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guistdio/guistdio.inc b/desktop/win32/source/guistdio/guistdio.inc deleted file mode 100644 index 9dd85d90f44b..000000000000 --- a/desktop/win32/source/guistdio/guistdio.inc +++ /dev/null @@ -1,437 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - -#define WIN32_LEAN_AND_MEAN -#include - -#include -#include -#include - -#include -#include - -#include - -#ifdef UNOPKG - -DWORD passOutputToConsole(HANDLE readPipe, HANDLE console) -{ - BYTE aBuffer[1024]; - DWORD dwRead = 0; - HANDLE hReadPipe = readPipe; - DWORD dwWritten; - - //Indicates that we read an odd number of bytes. That is, we only read half of the last - //wchar_t - bool bIncompleteWchar = false; - //fprintf, fwprintf will both send char data without the terminating zero. - //fwprintf converts the unicode string first. - //We expect here to receive unicode without the terminating zero. - //unopkg and the extension manager code MUST - //use dp_misc::writeConsole instead of using fprintf, etc. - - DWORD dwToRead = sizeof(aBuffer); - BYTE * pBuffer = aBuffer; - while ( ReadFile( hReadPipe, pBuffer, dwToRead, &dwRead, nullptr ) ) - { - //If the previous ReadFile call read an odd number of bytes, then the last one was - //put at the front of the buffer. We increase the number of read bytes by one to reflect - //that one byte. - if (bIncompleteWchar) - dwRead++; - //We must make sure that only complete wchar_t|s are written. WriteConsolse takes - //the number of wchar_t|s as argument. ReadFile, however, reads bytes. - bIncompleteWchar = (dwRead % 2) != 0; - if (bIncompleteWchar) - { - //To test this case, give aBuffer a small odd size, e.g. aBuffer[3] - //The last byte, which is the incomplete wchar_t (half of it), will not be written. - (void) WriteConsoleW( console, aBuffer, - (dwRead - 1) / 2, &dwWritten, nullptr ); - - //Move the last byte to the front of the buffer, so that it is the start of the - //next string - aBuffer[0] = aBuffer[dwRead - 1]; - - //Make sure that ReadFile does not overwrite the first byte the next time - dwToRead = sizeof(aBuffer) - 1; - pBuffer = aBuffer + 1; - - } - else - { //We have read an even number of bytes. Therefore, we do not put the last incomplete - //wchar_t at the front of the buffer. We will use the complete buffer the next time - //when ReadFile is called. - dwToRead = sizeof(aBuffer); - pBuffer = aBuffer; - (void) WriteConsoleW( console, - aBuffer, dwRead / 2, &dwWritten, nullptr ); - } - } - - return 0; -} - -#endif - -#ifdef UNOPKG -DWORD WINAPI OutputThread( LPVOID pParam ) -{ - return passOutputToConsole(static_cast(pParam), GetStdHandle( STD_OUTPUT_HANDLE )); -} - -#else -DWORD WINAPI OutputThread( LPVOID pParam ) -{ - BYTE aBuffer[256]; - DWORD dwRead = 0; - HANDLE hReadPipe = (HANDLE)pParam; - while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) - { - DWORD dwWritten; - - (void) WriteFile( GetStdHandle( STD_OUTPUT_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); - } - - return 0; -} -#endif - -// Thread that reads from child process standard error pipe - - -#ifdef UNOPKG -DWORD WINAPI ErrorThread( LPVOID pParam ) -{ - return passOutputToConsole(static_cast(pParam), GetStdHandle( STD_ERROR_HANDLE )); -} - -#else -DWORD WINAPI ErrorThread( LPVOID pParam ) -{ - BYTE aBuffer[256]; - DWORD dwRead = 0; - HANDLE hReadPipe = (HANDLE)pParam; - - while ( ReadFile( hReadPipe, &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) - { - DWORD dwWritten; - - (void) WriteFile( GetStdHandle( STD_ERROR_HANDLE ), aBuffer, dwRead, &dwWritten, NULL ); - } - - return 0; -} -#endif - -// Thread that writes to child process standard input pipe - -#ifdef UNOPKG - -DWORD WINAPI InputThread( LPVOID pParam ) -{ - DWORD dwRead = 0; - HANDLE hWritePipe = static_cast(pParam); - char* readBuf = nullptr; - try - { - //We need to read in the complete input until we encounter a new line before - //converting to Unicode. This is necessary because the input string can use - //characters of one, two, and more bytes. If the last character is not - //complete, then it will not be converted properly. - - //Find out how a new line (0xd 0xa) looks like with the used code page. - //Characters may have one or multiple bytes and different byte ordering - //can be used (little and big endian); - int cNewLine = WideCharToMultiByte( - GetConsoleCP(), 0, L"\r\n", 2, nullptr, 0, nullptr, nullptr); - auto mbBuff = std::make_unique(cNewLine); - WideCharToMultiByte( - GetConsoleCP(), 0, L"\r\n", 2, mbBuff.get(), cNewLine, nullptr, nullptr); - - const DWORD dwBufferSize = 256; - readBuf = static_cast(malloc(dwBufferSize)); - if (!readBuf) - throw std::bad_alloc(); - int readAll = 0; - DWORD curBufSize = dwBufferSize; - - while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), - readBuf + readAll, - curBufSize - readAll, &dwRead, nullptr ) ) - { - readAll += dwRead; - int lastBufSize = curBufSize; - //Grow the buffer if necessary - if (readAll > curBufSize * 0.7) - { - curBufSize *= 2; - if (auto p = static_cast(realloc(readBuf, curBufSize))) - readBuf = p; - else - { - throw std::bad_alloc(); - } - } - - //If the buffer was filled completely then - //there could be more input coming. But if we read from the console - //and the console input fits exactly in the buffer, then the next - //ReadFile would block until the users presses return, etc. - //Therefore we check if last character is a new line. - //To test this, set dwBufferSize to 4 and enter "no". This should produce - //4 bytes with most code pages. - if ( readAll == lastBufSize - && memcmp(readBuf + lastBufSize - cNewLine, mbBuff.get(), cNewLine) != 0) - { - //The buffer was completely filled and the last byte(s) are no - //new line, so there is more to come. - continue; - } - //Obtain the size of the buffer for the converted string. - int sizeWBuf = MultiByteToWideChar( - GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, nullptr, 0); - - auto wideBuf = std::make_unique(sizeWBuf); - - //Do the conversion. - MultiByteToWideChar( - GetConsoleCP(), MB_PRECOMPOSED, readBuf, readAll, wideBuf.get(), sizeWBuf); - - DWORD dwWritten; - (void)WriteFile( hWritePipe, wideBuf.get(), sizeWBuf * 2, &dwWritten, nullptr ); - - readAll = 0; - } - } - catch (...) - {} - free(readBuf); - return 0; -} -#else -DWORD WINAPI InputThread( LPVOID pParam ) -{ - BYTE aBuffer[256]; - DWORD dwRead = 0; - HANDLE hWritePipe = (HANDLE)pParam; - - while ( ReadFile( GetStdHandle( STD_INPUT_HANDLE ), &aBuffer, sizeof(aBuffer), &dwRead, NULL ) ) - { - DWORD dwWritten; - (void) WriteFile( hWritePipe, aBuffer, dwRead, &dwWritten, NULL ); - } - - return 0; -} -#endif - - -// Thread that waits until child process reached input idle - - -DWORD WINAPI WaitForUIThread( LPVOID pParam ) -{ -#ifndef UNOPKG - HANDLE hProcess = (HANDLE)pParam; - - if ( !wgetenv( L"UNOPKG" ) ) - WaitForInputIdle( hProcess, INFINITE ); -#else - (void) pParam; -#endif - - return 0; -} - - - -// Ctrl-Break handler that terminates the child process if Ctrl-C was pressed - - -HANDLE hTargetProcess = INVALID_HANDLE_VALUE; - -BOOL WINAPI CtrlBreakHandler( - DWORD // control signal type -) -{ - TerminateProcess( hTargetProcess, 255 ); - return TRUE; -} - -int wmain( int, wchar_t** ) -{ - WCHAR szTargetFileName[MAX_PATH] = L""; - STARTUPINFOW aStartupInfo; - PROCESS_INFORMATION aProcessInfo; - - ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); - aStartupInfo.cb = sizeof(aStartupInfo); - aStartupInfo.dwFlags = STARTF_USESTDHANDLES; - - // Create an output pipe where the write end is inheritable - - HANDLE hOutputRead, hOutputWrite; - - if ( CreatePipe( &hOutputRead, &hOutputWrite, nullptr, 0 ) ) - { - HANDLE hTemp; - - DuplicateHandle( GetCurrentProcess(), hOutputWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); - CloseHandle( hOutputWrite ); - hOutputWrite = hTemp; - - aStartupInfo.hStdOutput = hOutputWrite; - } - - // Create an error pipe where the write end is inheritable - - HANDLE hErrorRead, hErrorWrite; - - if ( CreatePipe( &hErrorRead, &hErrorWrite, nullptr, 0 ) ) - { - HANDLE hTemp; - - DuplicateHandle( GetCurrentProcess(), hErrorWrite, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); - CloseHandle( hErrorWrite ); - hErrorWrite = hTemp; - - aStartupInfo.hStdError = hErrorWrite; - } - - // Create an input pipe where the read end is inheritable - - HANDLE hInputRead, hInputWrite; - - if ( CreatePipe( &hInputRead, &hInputWrite, nullptr, 0 ) ) - { - HANDLE hTemp; - - DuplicateHandle( GetCurrentProcess(), hInputRead, GetCurrentProcess(), &hTemp, 0, TRUE, DUPLICATE_SAME_ACCESS ); - CloseHandle( hInputRead ); - hInputRead = hTemp; - - aStartupInfo.hStdInput = hInputRead; - } - - // Get image path with same name but with .exe extension - - WCHAR szModuleFileName[MAX_PATH]; - - GetModuleFileNameW( nullptr, szModuleFileName, MAX_PATH ); - WCHAR *lpLastDot = wcsrchr( szModuleFileName, '.' ); - if ( lpLastDot && 0 == wcsicmp( lpLastDot, L".COM" ) ) - { - size_t len = lpLastDot - szModuleFileName; - wcsncpy( szTargetFileName, szModuleFileName, len ); - wcsncpy( szTargetFileName + len, L".EXE", SAL_N_ELEMENTS(szTargetFileName) - len ); - } - - // Create process with same command line, environment and stdio handles which - // are directed to the created pipes - - bool fSuccess = CreateProcessW( - szTargetFileName, - GetCommandLineW(), - nullptr, - nullptr, - TRUE, - 0, - nullptr, - nullptr, - &aStartupInfo, - &aProcessInfo ); - - if ( fSuccess ) - { - // These pipe ends are inherited by the child process and no longer used - CloseHandle( hOutputWrite ); - CloseHandle( hErrorWrite ); - CloseHandle( hInputRead ); - - // Set the Ctrl-Break handler - hTargetProcess = aProcessInfo.hProcess; - SetConsoleCtrlHandler( CtrlBreakHandler, TRUE ); - - // Create threads that redirect remote pipe io to current process's console stdio - - DWORD dwOutputThreadId, dwErrorThreadId, dwInputThreadId; - - HANDLE hOutputThread = CreateThread( nullptr, 0, OutputThread, static_cast(hOutputRead), 0, &dwOutputThreadId ); - HANDLE hErrorThread = CreateThread( nullptr, 0, OutputThread, static_cast(hErrorRead), 0, &dwErrorThreadId ); - HANDLE hInputThread = CreateThread( nullptr, 0, InputThread, static_cast(hInputWrite), 0, &dwInputThreadId ); - - // Create thread that wait until child process entered input idle - - DWORD dwWaitForUIThreadId; - HANDLE hWaitForUIThread = CreateThread( nullptr, 0, WaitForUIThread, static_cast(aProcessInfo.hProcess), 0, &dwWaitForUIThreadId ); - - HANDLE hObjects[] = - { - hTargetProcess, - hWaitForUIThread, - hOutputThread, - hErrorThread - }; - - #ifdef UNOPKG - WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, TRUE, INFINITE ); - #else - bool bDetach = false; - int nOpenPipes = 2; - do - { - DWORD dwWaitResult = WaitForMultipleObjects( SAL_N_ELEMENTS(hObjects), hObjects, FALSE, INFINITE ); - - switch ( dwWaitResult ) - { - case WAIT_OBJECT_0: // The child process has terminated - case WAIT_OBJECT_0 + 1: // The child process entered input idle - bDetach = true; - break; - case WAIT_OBJECT_0 + 2: // The remote end of stdout pipe was closed - case WAIT_OBJECT_0 + 3: // The remote end of stderr pipe was closed - bDetach = --nOpenPipes <= 0; - break; - default: // Something went wrong - bDetach = true; - break; - } - } while( !bDetach ); - -#endif - - CloseHandle( hOutputThread ); - CloseHandle( hErrorThread ); - CloseHandle( hInputThread ); - CloseHandle( hWaitForUIThread ); - - DWORD dwExitCode = 0; - GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode ); - CloseHandle( aProcessInfo.hProcess ); - CloseHandle( aProcessInfo.hThread ); - - return dwExitCode; - } - - return -1; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/guistdio/unopkgio.cxx b/desktop/win32/source/guistdio/unopkgio.cxx deleted file mode 100644 index d7a7aff984ac..000000000000 --- a/desktop/win32/source/guistdio/unopkgio.cxx +++ /dev/null @@ -1,24 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - * - * This file incorporates work covered by the following license notice: - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed - * with this work for additional information regarding copyright - * ownership. The ASF licenses this file to you under the Apache - * License, Version 2.0 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.apache.org/licenses/LICENSE-2.0 . - */ - - -#define UNOPKG -#include "guistdio.inc" - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/loader.cxx b/desktop/win32/source/loader.cxx index 23706de032c9..3adf34aa3043 100644 --- a/desktop/win32/source/loader.cxx +++ b/desktop/win32/source/loader.cxx @@ -329,6 +329,104 @@ int officeloader_impl(bool bAllowConsole) return fSuccess ? dwExitCode : -1; } +int unopkgloader_impl(bool bAllowConsole) +{ + WCHAR szTargetFileName[MAX_PATH]; + WCHAR szIniDirectory[MAX_PATH]; + desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory); + + STARTUPINFOW aStartupInfo{}; + aStartupInfo.cb = sizeof(aStartupInfo); + GetStartupInfoW(&aStartupInfo); + + DWORD dwExitCode = DWORD(-1); + + size_t iniDirLen = wcslen(szIniDirectory); + WCHAR cwd[MAX_PATH]; + DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd); + if (cwdLen >= MAX_PATH) { + cwdLen = 0; + } + WCHAR redirect[MAX_PATH]; + DWORD dummy; + bool hasRedirect = + tools::buildPath( + redirect, szIniDirectory, szIniDirectory + iniDirLen, + MY_STRING(L"redirect.ini")) != nullptr && + (GetBinaryTypeW(redirect, &dummy) || // cheaper check for file existence? + GetLastError() != ERROR_FILE_NOT_FOUND); + LPWSTR cl1 = GetCommandLineW(); + WCHAR* cl2 = new WCHAR[ + wcslen(cl1) + + (hasRedirect + ? (MY_LENGTH(L" \"-env:INIFILENAME=vnd.sun.star.pathname:") + + iniDirLen + MY_LENGTH(L"redirect.ini\"")) + : 0) + + MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1]; + // 4 * cwdLen: each char preceded by backslash, each trailing backslash + // doubled + WCHAR* p = desktop_win32::commandLineAppend(cl2, cl1); + if (hasRedirect) { + p = desktop_win32::commandLineAppend( + p, MY_STRING(L" \"-env:INIFILENAME=vnd.sun.star.pathname:")); + p = desktop_win32::commandLineAppend(p, szIniDirectory); + p = desktop_win32::commandLineAppend(p, MY_STRING(L"redirect.ini\"")); + } + p = desktop_win32::commandLineAppend(p, MY_STRING(L" \"-env:OOO_CWD=")); + if (cwdLen == 0) { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"0")); + } + else { + p = desktop_win32::commandLineAppend(p, MY_STRING(L"2")); + p = desktop_win32::commandLineAppendEncoded(p, cwd); + } + desktop_win32::commandLineAppend(p, MY_STRING(L"\"")); + + PROCESS_INFORMATION aProcessInfo; + + bool fSuccess = CreateProcessW( + szTargetFileName, + cl2, + nullptr, + nullptr, + TRUE, + bAllowConsole ? 0 : DETACHED_PROCESS, + nullptr, + szIniDirectory, + &aStartupInfo, + &aProcessInfo); + + delete[] cl2; + + if (fSuccess) + { + DWORD dwWaitResult; + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWidth" so we have to do so + // as if we where processing any messages + + dwWaitResult = MsgWaitForMultipleObjects(1, &aProcessInfo.hProcess, FALSE, INFINITE, QS_ALLEVENTS); + + if (WAIT_OBJECT_0 + 1 == dwWaitResult) + { + MSG msg; + + PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE); + } + } while (WAIT_OBJECT_0 + 1 == dwWaitResult); + + dwExitCode = 0; + GetExitCodeProcess(aProcessInfo.hProcess, &dwExitCode); + + CloseHandle(aProcessInfo.hProcess); + CloseHandle(aProcessInfo.hThread); + } + + return dwExitCode; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/loader.hxx b/desktop/win32/source/loader.hxx index dfa8f0c971a0..aed76b168798 100644 --- a/desktop/win32/source/loader.hxx +++ b/desktop/win32/source/loader.hxx @@ -82,6 +82,9 @@ void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory); // Implementation of the process guarding soffice.bin int officeloader_impl(bool bAllowConsole); +// Implementation of the process guarding unopkg.bin +int unopkgloader_impl(bool bAllowConsole); + } #endif diff --git a/desktop/win32/source/officeloader/unopkg_com.cxx b/desktop/win32/source/officeloader/unopkg_com.cxx new file mode 100644 index 000000000000..a93ac60365e6 --- /dev/null +++ b/desktop/win32/source/officeloader/unopkg_com.cxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include "../loader.hxx" + +int main(int /*argc*/, char** /*argv*/) +{ + // let unopkg.bin use unopkg.com's console + return desktop_win32::unopkgloader_impl(true); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/officeloader/unopkg_exe.cxx b/desktop/win32/source/officeloader/unopkg_exe.cxx new file mode 100644 index 000000000000..40b1afa09280 --- /dev/null +++ b/desktop/win32/source/officeloader/unopkg_exe.cxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include "../loader.hxx" + +int WINAPI wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) +{ + // no console for unopkg.bin when started by unopkg.exe + return desktop_win32::unopkgloader_impl(false); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */