summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Repository.mk3
-rw-r--r--RepositoryFixes.mk3
-rw-r--r--desktop/Executable_soffice.mk31
-rw-r--r--desktop/Executable_soffice_bin.mk4
-rw-r--r--desktop/Executable_soffice_com.mk29
-rw-r--r--desktop/Executable_soffice_exe.mk29
-rw-r--r--desktop/Executable_unopkg.mk4
-rw-r--r--desktop/Module_desktop.mk3
-rw-r--r--desktop/source/app/cmdlinehelp.cxx79
-rw-r--r--desktop/win32/source/loader.cxx193
-rw-r--r--desktop/win32/source/loader.hxx4
-rw-r--r--desktop/win32/source/officeloader/officeloader.cxx221
-rw-r--r--desktop/win32/source/officeloader/soffice_com.cxx19
-rw-r--r--desktop/win32/source/officeloader/soffice_exe.cxx19
-rw-r--r--scp2/source/ooo/folderitem_ooo.scp12
15 files changed, 326 insertions, 327 deletions
diff --git a/Repository.mk b/Repository.mk
index 36b35b7a4262..d23d93aaa9f5 100644
--- a/Repository.mk
+++ b/Repository.mk
@@ -145,7 +145,8 @@ $(eval $(call gb_Helper_register_executables_for_install,OOO,brand, \
soffice_bin \
$(if $(filter DESKTOP,$(BUILD_TYPE)),unopkg_bin) \
$(if $(filter WNT,$(OS)), \
- soffice \
+ soffice_exe \
+ soffice_com \
unoinfo \
unopkg \
unopkg_com \
diff --git a/RepositoryFixes.mk b/RepositoryFixes.mk
index 82c0701e59dd..55c69ef11dba 100644
--- a/RepositoryFixes.mk
+++ b/RepositoryFixes.mk
@@ -37,6 +37,9 @@ else
gb_Executable_FILENAMES := $(patsubst soffice_bin:soffice_bin%,soffice_bin:soffice.bin,$(gb_Executable_FILENAMES))
endif
+gb_Executable_FILENAMES := $(patsubst soffice_exe:soffice_exe%,soffice_exe:soffice.exe,$(gb_Executable_FILENAMES))
+gb_Executable_FILENAMES := $(patsubst soffice_com:soffice_com%,soffice_com:soffice.com,$(gb_Executable_FILENAMES))
+
gb_Executable_FILENAMES_FOR_BUILD := $(subst $(gb_Executable_EXT),$(gb_Executable_EXT_for_build),$(gb_Executable_FILENAMES))
# fixes for .jnilibs on Mac OS X that are not also needed as .dylibs:
diff --git a/desktop/Executable_soffice.mk b/desktop/Executable_soffice.mk
deleted file mode 100644
index d1847d7bf76a..000000000000
--- a/desktop/Executable_soffice.mk
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
-#
-# 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/.
-#
-
-$(eval $(call gb_Executable_Executable,soffice))
-
-$(eval $(call gb_Executable_set_targettype_gui,soffice,YES))
-
-$(eval $(call gb_Executable_use_system_win32_libs,soffice,\
- advapi32 \
- shell32 \
- shlwapi \
-))
-
-$(eval $(call gb_Executable_use_static_libraries,soffice,\
- ooopathutils \
- winloader \
-))
-
-$(eval $(call gb_Executable_add_exception_objects,soffice,\
- desktop/win32/source/officeloader/officeloader \
-))
-
-$(eval $(call gb_Executable_add_nativeres,soffice,soffice/launcher))
-
-# vim: set ts=4 sw=4 et:
diff --git a/desktop/Executable_soffice_bin.mk b/desktop/Executable_soffice_bin.mk
index 6db3c110cc1f..d8084cddeb1f 100644
--- a/desktop/Executable_soffice_bin.mk
+++ b/desktop/Executable_soffice_bin.mk
@@ -9,8 +9,6 @@
$(eval $(call gb_Executable_Executable,soffice_bin))
-$(eval $(call gb_Executable_set_targettype_gui,soffice_bin,YES))
-
$(eval $(call gb_Executable_set_include,soffice_bin,\
$$(INCLUDE) \
-I$(SRCDIR)/desktop/source/inc \
@@ -35,7 +33,7 @@ endif
ifeq ($(OS),WNT)
-$(eval $(call gb_Executable_set_targettype_gui,soffice_bin,YES))
+$(eval $(call gb_Executable_set_targettype_gui,soffice_bin,NO))
$(eval $(call gb_Executable_add_nativeres,soffice_bin,sofficebin/officeloader))
diff --git a/desktop/Executable_soffice_com.mk b/desktop/Executable_soffice_com.mk
new file mode 100644
index 000000000000..8b4da6b9d94b
--- /dev/null
+++ b/desktop/Executable_soffice_com.mk
@@ -0,0 +1,29 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_Executable_Executable,soffice_com))
+
+$(eval $(call gb_Executable_set_targettype_gui,soffice_com,NO))
+
+$(eval $(call gb_Executable_use_system_win32_libs,soffice_com,\
+ shell32 \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,soffice_com,\
+ ooopathutils \
+ winloader \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,soffice_com,\
+ desktop/win32/source/officeloader/soffice_com \
+))
+
+$(eval $(call gb_Executable_add_nativeres,soffice_com,soffice/launcher))
+
+# vim: set ts=4 sw=4 et:
diff --git a/desktop/Executable_soffice_exe.mk b/desktop/Executable_soffice_exe.mk
new file mode 100644
index 000000000000..87becbd911ee
--- /dev/null
+++ b/desktop/Executable_soffice_exe.mk
@@ -0,0 +1,29 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_Executable_Executable,soffice_exe))
+
+$(eval $(call gb_Executable_set_targettype_gui,soffice_exe,YES))
+
+$(eval $(call gb_Executable_use_system_win32_libs,soffice_exe,\
+ shell32 \
+))
+
+$(eval $(call gb_Executable_use_static_libraries,soffice_exe,\
+ ooopathutils \
+ winloader \
+))
+
+$(eval $(call gb_Executable_add_exception_objects,soffice_exe,\
+ desktop/win32/source/officeloader/soffice_exe \
+))
+
+$(eval $(call gb_Executable_add_nativeres,soffice_exe,soffice/launcher))
+
+# vim: set ts=4 sw=4 et:
diff --git a/desktop/Executable_unopkg.mk b/desktop/Executable_unopkg.mk
index 674edfdd6c08..c5b341521b9f 100644
--- a/desktop/Executable_unopkg.mk
+++ b/desktop/Executable_unopkg.mk
@@ -16,6 +16,10 @@ $(eval $(call gb_Executable_use_static_libraries,unopkg,\
winloader \
))
+$(eval $(call gb_Executable_use_system_win32_libs,unopkg,\
+ shell32 \
+))
+
$(eval $(call gb_Executable_add_exception_objects,unopkg,\
desktop/win32/source/guiloader/genericloader \
))
diff --git a/desktop/Module_desktop.mk b/desktop/Module_desktop.mk
index 9cce8f03c71f..34612712e6a0 100644
--- a/desktop/Module_desktop.mk
+++ b/desktop/Module_desktop.mk
@@ -78,7 +78,8 @@ $(eval $(call gb_Module_add_targets,desktop,\
Executable_sdraw \
Executable_simpress \
Executable_smath \
- Executable_soffice \
+ Executable_soffice_exe \
+ Executable_soffice_com \
Executable_sweb \
Executable_swriter \
Executable_unoinfo \
diff --git a/desktop/source/app/cmdlinehelp.cxx b/desktop/source/app/cmdlinehelp.cxx
index 656835082c59..5d9a941c50c4 100644
--- a/desktop/source/app/cmdlinehelp.cxx
+++ b/desktop/source/app/cmdlinehelp.cxx
@@ -183,43 +183,26 @@ namespace desktop
" Used only in unit tests and should have two arguments. \n\n";
#ifdef _WIN32
namespace{
+ // This class is only used to create a console when soffice.bin is run without own console
+ // (like using soffice.exe launcher as opposed to soffice.com), and either --version or
+ // --help command line options were specified, or an error in a command line option was
+ // detected, which requires to output strings to user.
class lcl_Console {
- enum eConsoleMode { unknown, attached, allocated };
public:
explicit lcl_Console(short nBufHeight)
- : mConsoleMode(unknown)
+ : m_bOwnConsole(AllocConsole() != FALSE)
{
- if (GetStdHandle(STD_OUTPUT_HANDLE) == nullptr) // application does not have associated standard handles
+ if (m_bOwnConsole)
{
- STARTUPINFOW aStartupInfo;
- aStartupInfo.cb = sizeof(aStartupInfo);
- GetStartupInfoW(&aStartupInfo);
- if ((aStartupInfo.dwFlags & STARTF_USESTDHANDLES) == STARTF_USESTDHANDLES)
- {
- // If standard handles had been passed to this process, use them
- SetStdHandle(STD_INPUT_HANDLE, aStartupInfo.hStdInput);
- SetStdHandle(STD_OUTPUT_HANDLE, aStartupInfo.hStdOutput);
- SetStdHandle(STD_ERROR_HANDLE, aStartupInfo.hStdError);
- }
- else
- {
- // Try to attach parent console; on error try to create new.
- // If this process already has its console, these will simply fail.
- if (AttachConsole(ATTACH_PARENT_PROCESS) != FALSE)
- mConsoleMode = attached;
- else if (AllocConsole() != FALSE)
- mConsoleMode = allocated;
-
- HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
+ HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
- // Ensure that console buffer is enough to hold required data
- CONSOLE_SCREEN_BUFFER_INFO cinfo;
- GetConsoleScreenBufferInfo(hOut, &cinfo);
- if (cinfo.dwSize.Y < nBufHeight)
- {
- cinfo.dwSize.Y = nBufHeight;
- SetConsoleScreenBufferSize(hOut, cinfo.dwSize);
- }
+ // Ensure that console buffer is enough to hold required data
+ CONSOLE_SCREEN_BUFFER_INFO cinfo;
+ GetConsoleScreenBufferInfo(hOut, &cinfo);
+ if (cinfo.dwSize.Y < nBufHeight)
+ {
+ cinfo.dwSize.Y = nBufHeight;
+ SetConsoleScreenBufferSize(hOut, cinfo.dwSize);
}
(void)freopen("CON", "r", stdin);
@@ -227,47 +210,21 @@ namespace desktop
(void)freopen("CON", "w", stderr);
std::ios::sync_with_stdio(true);
-
- // In case we use parent's console, emit an empty string
- // to avoid output on a line with command prompt
- if (mConsoleMode == attached)
- fprintf(stdout, "\n");
}
}
~lcl_Console()
{
- fflush(stdout);
- switch (mConsoleMode) {
- case unknown:
- // Don't free the console
- return;
- case attached:
+ if (m_bOwnConsole)
{
- // Put Enter keypress to console input buffer to emit next command prompt after the command
- INPUT_RECORD ir;
- ir.EventType = KEY_EVENT;
- KEY_EVENT_RECORD& ke = ir.Event.KeyEvent;
- ke.bKeyDown = TRUE;
- ke.wRepeatCount = 1;
- ke.wVirtualKeyCode = VK_RETURN;
- ke.wVirtualScanCode = MapVirtualKeyW(VK_RETURN, MAPVK_VK_TO_VSC);
- ke.uChar.UnicodeChar = L'\r';
- ke.dwControlKeyState = 0;
- DWORD nEvents;
- WriteConsoleInputW(GetStdHandle(STD_INPUT_HANDLE), &ir, 1, &nEvents);
- break;
- }
- case allocated:
+ fflush(stdout);
fprintf(stdout, "Press Enter to continue...");
fgetc(stdin);
- break;
+ FreeConsole();
}
-
- FreeConsole();
}
private:
- eConsoleMode mConsoleMode;
+ bool m_bOwnConsole;
};
}
#endif
diff --git a/desktop/win32/source/loader.cxx b/desktop/win32/source/loader.cxx
index 4425c1e697d9..3960dd2c6f1c 100644
--- a/desktop/win32/source/loader.cxx
+++ b/desktop/win32/source/loader.cxx
@@ -17,9 +17,14 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <tools/pathutils.hxx>
#include "loader.hxx"
#include <cassert>
+#include <systools/win32/uwinapi.h>
+#include <stdlib.h>
+#include <string>
+#include <vector>
+#include <desktop/exithelper.h>
+#include <tools/pathutils.hxx>
namespace {
@@ -34,6 +39,40 @@ void fail()
TerminateProcess(GetCurrentProcess(), 255);
}
+LPWSTR* GetCommandArgs(int* pArgc) { return CommandLineToArgvW(GetCommandLineW(), pArgc); }
+
+// tdf#120249: quotes in arguments need to be escaped; backslashes before quotes need doubling. See
+// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw
+std::wstring EscapeArg(LPCWSTR sArg)
+{
+ const size_t nOrigSize = wcslen(sArg);
+ LPCWSTR const end = sArg + nOrigSize;
+ std::wstring sResult(L"\"");
+
+ LPCWSTR lastPosQuote = sArg;
+ LPCWSTR posQuote;
+ while ((posQuote = std::find(lastPosQuote, end, L'"')) != end)
+ {
+ LPCWSTR posBackslash = posQuote;
+ while (posBackslash != lastPosQuote && *(posBackslash - 1) == L'\\')
+ --posBackslash;
+
+ sResult.append(lastPosQuote, posBackslash);
+ sResult.append((posQuote - posBackslash) * 2 + 1, L'\\'); // 2n+1 '\' to escape the '"'
+ sResult.append(1, L'"');
+ lastPosQuote = posQuote + 1;
+ }
+
+ LPCWSTR posTrailingBackslashSeq = end;
+ while (posTrailingBackslashSeq != lastPosQuote && *(posTrailingBackslashSeq - 1) == L'\\')
+ --posTrailingBackslashSeq;
+ sResult.append(lastPosQuote, posTrailingBackslashSeq);
+ sResult.append((end - posTrailingBackslashSeq) * 2, L'\\'); // 2n '\' before closing '"'
+ sResult.append(1, L'"');
+
+ return sResult;
+}
+
}
namespace desktop_win32 {
@@ -50,9 +89,12 @@ void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) {
*nameEnd++ = *p;
}
if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' &&
- (nameEnd[-3] == L'E' || nameEnd[-3] == L'e') &&
+ ((nameEnd[-3] == L'E' || nameEnd[-3] == L'e') &&
(nameEnd[-2] == L'X' || nameEnd[-2] == L'x') &&
- (nameEnd[-1] == L'E' || nameEnd[-1] == L'e')))
+ (nameEnd[-1] == L'E' || nameEnd[-1] == L'e') ||
+ (nameEnd[-3] == L'C' || nameEnd[-3] == L'c') &&
+ (nameEnd[-2] == L'O' || nameEnd[-2] == L'o') &&
+ (nameEnd[-1] == L'M' || nameEnd[-1] == L'm'))))
{
*nameEnd = L'.';
nameEnd += 4;
@@ -90,6 +132,151 @@ void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) {
}
}
+int officeloader_impl(bool bAllowConsole)
+{
+ WCHAR szTargetFileName[MAX_PATH] = {};
+ WCHAR szIniDirectory[MAX_PATH];
+ STARTUPINFOW aStartupInfo;
+
+ desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory);
+
+ ZeroMemory(&aStartupInfo, sizeof(aStartupInfo));
+ aStartupInfo.cb = sizeof(aStartupInfo);
+
+ // Create process with same command line, environment and stdio handles which
+ // are directed to the created pipes
+ GetStartupInfoW(&aStartupInfo);
+
+ DWORD dwExitCode = DWORD(-1);
+
+ BOOL fSuccess = FALSE;
+ LPWSTR lpCommandLine = nullptr;
+ bool bFirst = true;
+ WCHAR cwd[MAX_PATH];
+ DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd);
+ if (cwdLen >= MAX_PATH)
+ {
+ cwdLen = 0;
+ }
+ std::vector<std::wstring> aEscapedArgs;
+
+ do
+ {
+ if (bFirst)
+ {
+ int argc = 0;
+ LPWSTR* argv = GetCommandArgs(&argc);
+ std::size_t n = 0;
+ for (int i = 0; i < argc; ++i)
+ {
+ std::wstring sEscapedArg = EscapeArg(argv[i]);
+ aEscapedArgs.push_back(sEscapedArg);
+ n += sEscapedArg.length() + 1; // a space between args
+ }
+ LocalFree(argv);
+ n += MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen + MY_LENGTH(L"\"") + 1;
+ // 4 * cwdLen: each char preceded by backslash, each trailing
+ // backslash doubled
+ lpCommandLine = new WCHAR[n];
+ }
+ WCHAR* p = desktop_win32::commandLineAppend(lpCommandLine, aEscapedArgs[0].c_str(),
+ aEscapedArgs[0].length());
+ for (size_t i = 1; i < aEscapedArgs.size(); ++i)
+ {
+ const std::wstring& rArg = aEscapedArgs[i];
+ if (bFirst || EXITHELPER_NORMAL_RESTART == dwExitCode
+ || wcsncmp(rArg.c_str(), MY_STRING(L"\"-env:")) == 0)
+ {
+ p = desktop_win32::commandLineAppend(p, MY_STRING(L" "));
+ p = desktop_win32::commandLineAppend(p, rArg.c_str(), rArg.length());
+ }
+ }
+
+ 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"\""));
+ bFirst = false;
+
+ WCHAR szParentProcessId[64]; // This is more than large enough for a 128 bit decimal value
+ BOOL bHeadlessMode(FALSE);
+
+ {
+ // Check command line arguments for "--headless" parameter. We only
+ // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless
+ // mode as self-destruction of the soffice.bin process can lead to
+ // certain side-effects (log-off can result in data-loss, ".lock" is not deleted.
+ // See 138244 for more information.
+ int argc2;
+ LPWSTR* argv2 = GetCommandArgs(&argc2);
+
+ if (argc2 > 1)
+ {
+ int n;
+
+ for (n = 1; n < argc2; n++)
+ {
+ if (0 == wcsnicmp(argv2[n], L"-headless", 9)
+ || 0 == wcsnicmp(argv2[n], L"--headless", 10))
+ {
+ bHeadlessMode = TRUE;
+ }
+ }
+ }
+
+ LocalFree(argv2);
+ }
+
+ if (_ltow(static_cast<long>(GetCurrentProcessId()), szParentProcessId, 10) && bHeadlessMode)
+ SetEnvironmentVariableW(L"ATTACHED_PARENT_PROCESSID", szParentProcessId);
+
+ PROCESS_INFORMATION aProcessInfo;
+
+ fSuccess = CreateProcessW(szTargetFileName, lpCommandLine, nullptr, nullptr, TRUE,
+ bAllowConsole ? 0 : DETACHED_PROCESS, nullptr, szIniDirectory,
+ &aStartupInfo, &aProcessInfo);
+
+ if (fSuccess)
+ {
+ DWORD dwWaitResult;
+
+ do
+ {
+ // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWith" 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);
+ }
+ } while (fSuccess
+ && (EXITHELPER_CRASH_WITH_RESTART == dwExitCode
+ || EXITHELPER_NORMAL_RESTART == dwExitCode));
+ delete[] lpCommandLine;
+
+ return fSuccess ? dwExitCode : -1;
+}
+
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/win32/source/loader.hxx b/desktop/win32/source/loader.hxx
index 059fae479958..dfa8f0c971a0 100644
--- a/desktop/win32/source/loader.hxx
+++ b/desktop/win32/source/loader.hxx
@@ -20,6 +20,7 @@
#ifndef INCLUDED_DESKTOP_WIN32_SOURCE_LOADER_HXX
#define INCLUDED_DESKTOP_WIN32_SOURCE_LOADER_HXX
+#include <cstddef>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <string.h>
@@ -78,6 +79,9 @@ inline WCHAR * commandLineAppendEncoded(WCHAR * buffer, WCHAR const * text) {
// corresponding to the current executable.
void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory);
+// Implementation of the process guarding soffice.bin
+int officeloader_impl(bool bAllowConsole);
+
}
#endif
diff --git a/desktop/win32/source/officeloader/officeloader.cxx b/desktop/win32/source/officeloader/officeloader.cxx
deleted file mode 100644
index e1b3323fbe9e..000000000000
--- a/desktop/win32/source/officeloader/officeloader.cxx
+++ /dev/null
@@ -1,221 +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 <cstddef>
-
-#include <systools/win32/uwinapi.h>
-#include <stdlib.h>
-#include <algorithm>
-#include <string>
-#include <vector>
-#include <desktop/exithelper.h>
-
-#include "../loader.hxx"
-
-static LPWSTR *GetCommandArgs( int *pArgc )
-{
- return CommandLineToArgvW( GetCommandLineW(), pArgc );
-}
-
-// tdf#120249: quotes in arguments need to be escaped; backslashes before quotes need doubling. See
-// https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-commandlinetoargvw
-static std::wstring EscapeArg(LPCWSTR sArg)
-{
- const size_t nOrigSize = wcslen(sArg);
- LPCWSTR const end = sArg + nOrigSize;
- std::wstring sResult(L"\"");
-
- LPCWSTR lastPosQuote = sArg;
- LPCWSTR posQuote;
- while ((posQuote = std::find(lastPosQuote, end, L'"')) != end)
- {
- LPCWSTR posBackslash = posQuote;
- while (posBackslash != lastPosQuote && *(posBackslash - 1) == L'\\')
- --posBackslash;
-
- sResult.append(lastPosQuote, posBackslash);
- sResult.append((posQuote - posBackslash) * 2 + 1, L'\\'); // 2n+1 '\' to escape the '"'
- sResult.append(1, L'"');
- lastPosQuote = posQuote + 1;
- }
-
- LPCWSTR posTrailingBackslashSeq = end;
- while (posTrailingBackslashSeq != lastPosQuote && *(posTrailingBackslashSeq - 1) == L'\\')
- --posTrailingBackslashSeq;
- sResult.append(lastPosQuote, posTrailingBackslashSeq);
- sResult.append((end - posTrailingBackslashSeq) * 2, L'\\'); // 2n '\' before closing '"'
- sResult.append(1, L'"');
-
- return sResult;
-}
-
-int WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
-{
- WCHAR szTargetFileName[MAX_PATH] = {};
- WCHAR szIniDirectory[MAX_PATH];
- STARTUPINFOW aStartupInfo;
-
- desktop_win32::extendLoaderEnvironment(szTargetFileName, szIniDirectory);
-
- ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) );
- aStartupInfo.cb = sizeof(aStartupInfo);
-
- // Create process with same command line, environment and stdio handles which
- // are directed to the created pipes
- GetStartupInfoW(&aStartupInfo);
-
- // If this process hasn't its stdio handles set, then check if its parent
- // has a console (i.e. this process is launched from command line), and if so,
- // attach to it. It will enable child process to retrieve this console if it needs
- // to output to console
- if ((aStartupInfo.dwFlags & STARTF_USESTDHANDLES) == 0)
- AttachConsole(ATTACH_PARENT_PROCESS);
-
- DWORD dwExitCode = DWORD(-1);
-
- BOOL fSuccess = FALSE;
- LPWSTR lpCommandLine = nullptr;
- bool bFirst = true;
- WCHAR cwd[MAX_PATH];
- DWORD cwdLen = GetCurrentDirectoryW(MAX_PATH, cwd);
- if (cwdLen >= MAX_PATH) {
- cwdLen = 0;
- }
- std::vector<std::wstring> aEscapedArgs;
-
- do
- {
- if ( bFirst ) {
- int argc = 0;
- LPWSTR* argv = GetCommandArgs(&argc);
- std::size_t n = 0;
- for (int i = 0; i < argc; ++i) {
- std::wstring sEscapedArg = EscapeArg(argv[i]);
- aEscapedArgs.push_back(sEscapedArg);
- n += sEscapedArg.length() + 1; // a space between args
- }
- LocalFree(argv);
- n += MY_LENGTH(L" \"-env:OOO_CWD=2") + 4 * cwdLen +
- MY_LENGTH(L"\"") + 1;
- // 4 * cwdLen: each char preceded by backslash, each trailing
- // backslash doubled
- lpCommandLine = new WCHAR[n];
- }
- WCHAR* p = desktop_win32::commandLineAppend(lpCommandLine, aEscapedArgs[0].c_str(),
- aEscapedArgs[0].length());
- for (size_t i = 1; i < aEscapedArgs.size(); ++i)
- {
- const std::wstring& rArg = aEscapedArgs[i];
- if (bFirst || EXITHELPER_NORMAL_RESTART == dwExitCode
- || wcsncmp(rArg.c_str(), MY_STRING(L"\"-env:")) == 0)
- {
- p = desktop_win32::commandLineAppend(p, MY_STRING(L" "));
- p = desktop_win32::commandLineAppend(p, rArg.c_str(), rArg.length());
- }
- }
-
- 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"\""));
- bFirst = false;
-
- WCHAR szParentProcessId[64]; // This is more than large enough for a 128 bit decimal value
- BOOL bHeadlessMode( FALSE );
-
- {
- // Check command line arguments for "--headless" parameter. We only
- // set the environment variable "ATTACHED_PARENT_PROCESSID" for the headless
- // mode as self-destruction of the soffice.bin process can lead to
- // certain side-effects (log-off can result in data-loss, ".lock" is not deleted.
- // See 138244 for more information.
- int argc2;
- LPWSTR *argv2 = GetCommandArgs( &argc2 );
-
- if ( argc2 > 1 )
- {
- int n;
-
- for ( n = 1; n < argc2; n++ )
- {
- if ( 0 == wcsnicmp( argv2[n], L"-headless", 9 ) ||
- 0 == wcsnicmp( argv2[n], L"--headless", 10 ) )
- {
- bHeadlessMode = TRUE;
- }
- }
- }
-
- LocalFree(argv2);
- }
-
- if ( _ltow( static_cast<long>(GetCurrentProcessId()),szParentProcessId, 10 ) && bHeadlessMode )
- SetEnvironmentVariableW( L"ATTACHED_PARENT_PROCESSID", szParentProcessId );
-
- PROCESS_INFORMATION aProcessInfo;
-
- fSuccess = CreateProcessW(
- szTargetFileName,
- lpCommandLine,
- nullptr,
- nullptr,
- TRUE,
- 0,
- nullptr,
- szIniDirectory,
- &aStartupInfo,
- &aProcessInfo );
-
- 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 );
- }
- } while ( fSuccess
- && ( EXITHELPER_CRASH_WITH_RESTART == dwExitCode || EXITHELPER_NORMAL_RESTART == dwExitCode ));
- delete[] lpCommandLine;
-
- return fSuccess ? dwExitCode : -1;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/win32/source/officeloader/soffice_com.cxx b/desktop/win32/source/officeloader/soffice_com.cxx
new file mode 100644
index 000000000000..5c6974e66a15
--- /dev/null
+++ b/desktop/win32/source/officeloader/soffice_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 soffice.bin use soffice.com's console
+ return desktop_win32::officeloader_impl(true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/desktop/win32/source/officeloader/soffice_exe.cxx b/desktop/win32/source/officeloader/soffice_exe.cxx
new file mode 100644
index 000000000000..03ff0a546b87
--- /dev/null
+++ b/desktop/win32/source/officeloader/soffice_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 soffice.bin when started by soffice.exe
+ return desktop_win32::officeloader_impl(false);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scp2/source/ooo/folderitem_ooo.scp b/scp2/source/ooo/folderitem_ooo.scp
index 3c0423bbb54f..2e67a6a6aea0 100644
--- a/scp2/source/ooo/folderitem_ooo.scp
+++ b/scp2/source/ooo/folderitem_ooo.scp
@@ -26,8 +26,8 @@ FolderItem gid_Folderitem_LibreOffice
#else
FolderID = gid_Folder_Staroffice51;
#endif
- FileID = auto_brand_exe_soffice;
- IconFile = auto_brand_exe_soffice;
+ FileID = auto_brand_exe_soffice_exe;
+ IconFile = auto_brand_exe_soffice_exe;
IconID = 0;
WkDir = gid_Brand_Dir_Program;
Parameter = "";
@@ -49,8 +49,8 @@ FolderItem gid_Folderitem_Soffice_Desktop
#endif
ModuleID = gid_Module_Root;
FolderID = PREDEFINED_DESKTOP;
- FileID = auto_brand_exe_soffice;
- IconFile = auto_brand_exe_soffice;
+ FileID = auto_brand_exe_soffice_exe;
+ IconFile = auto_brand_exe_soffice_exe;
IconID = 0;
ComponentIDFile = "gid_Brand_File_Desktophelper_Txt";
WkDir = gid_Brand_Dir_Program;
@@ -74,8 +74,8 @@ FolderItem gid_Folderitem_LibreOffice_SafeMode
#else
FolderID = gid_Folder_Staroffice51;
#endif
- FileID = auto_brand_exe_soffice;
- IconFile = auto_brand_exe_soffice;
+ FileID = auto_brand_exe_soffice_exe;
+ IconFile = auto_brand_exe_soffice_exe;
IconID = 0;
WkDir = gid_Brand_Dir_Program;
Parameter = "--safe-mode";