diff options
Diffstat (limited to 'desktop/win32')
21 files changed, 1181 insertions, 0 deletions
diff --git a/desktop/win32/source/QuickStart/QuickStart.cxx b/desktop/win32/source/QuickStart/QuickStart.cxx new file mode 100644 index 000000000..3277a6abf --- /dev/null +++ b/desktop/win32/source/QuickStart/QuickStart.cxx @@ -0,0 +1,104 @@ +/* -*- 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 . + */ + +// QuickStart.cpp : Defines the entry point for the application. + +#include <sal/config.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <shellapi.h> + +#include "resource.h" +#include <systools/win32/uwinapi.h> +#include <systools/win32/qswin32.h> + +#include <stdio.h> +#include <stdlib.h> +#include <malloc.h> +#include <memory.h> + +static bool SofficeRuns() +{ + // check for soffice by searching the communication window + return FindWindowExW( nullptr, nullptr, QUICKSTART_CLASSNAME, nullptr ) != nullptr; +} + +static bool launchSoffice( ) +{ + if ( !SofficeRuns() ) + { + wchar_t filename[_MAX_PATH + 1]; + + filename[_MAX_PATH] = 0; + GetModuleFileNameW( nullptr, filename, _MAX_PATH ); // soffice resides in the same dir + wchar_t *p = wcsrchr( filename, L'\\' ); + if ( !p ) + return false; + + wcsncpy( p+1, L"soffice.exe", _MAX_PATH - (p+1 - filename) ); + + wchar_t imagename[_MAX_PATH + 1]; + + imagename[_MAX_PATH] = 0; + _snwprintf(imagename, _MAX_PATH, L"\"%s\" --quickstart", filename ); + + STARTUPINFOW aStartupInfo; + ZeroMemory(&aStartupInfo, sizeof(aStartupInfo)); + aStartupInfo.cb = sizeof(aStartupInfo); + aStartupInfo.wShowWindow = SW_SHOW; + PROCESS_INFORMATION aProcessInfo; + bool bSuccess = CreateProcessW(filename, imagename, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &aStartupInfo, &aProcessInfo); + if ( !bSuccess ) + return false; + + return true; + } + else + return true; +} + +int APIENTRY wWinMain(HINSTANCE /*hInstance*/, + HINSTANCE /*hPrevInstance*/, + LPWSTR /*lpCmdLine*/, + int /*nCmdShow*/) +{ + // Look for --killtray argument + + for ( int i = 1; i < __argc; i++ ) + { + if ( 0 == wcscmp( __wargv[i], L"--killtray" ) ) + { + HWND hwndTray = FindWindowW( QUICKSTART_CLASSNAME, nullptr ); + + if ( hwndTray ) + { + UINT uMsgKillTray = RegisterWindowMessageW( SHUTDOWN_QUICKSTART_MESSAGE ); + SendMessageW( hwndTray, uMsgKillTray, 0, 0 ); + } + + return 0; + } + } + + launchSoffice(); + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/QuickStart/QuickStart.rc b/desktop/win32/source/QuickStart/QuickStart.rc new file mode 100644 index 000000000..cf9131479 --- /dev/null +++ b/desktop/win32/source/QuickStart/QuickStart.rc @@ -0,0 +1,3 @@ +#include "resource.h" + +ICON_ACTIVE ICON DISCARDABLE "icons/soffice.ico" diff --git a/desktop/win32/source/QuickStart/resource.h b/desktop/win32/source/QuickStart/resource.h new file mode 100644 index 000000000..3dfbabcd8 --- /dev/null +++ b/desktop/win32/source/QuickStart/resource.h @@ -0,0 +1,5 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +#define ICON_ACTIVE 1 + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/launcher.cxx b/desktop/win32/source/applauncher/launcher.cxx new file mode 100644 index 000000000..bf80dba2c --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.cxx @@ -0,0 +1,105 @@ +/* -*- 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 "launcher.hxx" + +#include <stdlib.h> +#include <malloc.h> + +extern "C" int APIENTRY wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int ) +{ + // Retrieve startup info + + STARTUPINFOW aStartupInfo; + + ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) ); + aStartupInfo.cb = sizeof( aStartupInfo ); + GetStartupInfoW( &aStartupInfo ); + + // Retrieve command line + + LPWSTR lpCommandLine = static_cast<LPWSTR>(_alloca( sizeof(WCHAR) * (wcslen(GetCommandLineW()) + wcslen(APPLICATION_SWITCH) + 2) )); + + wcscpy( lpCommandLine, GetCommandLineW() ); + wcscat( lpCommandLine, L" " ); + wcscat( lpCommandLine, APPLICATION_SWITCH ); + + // Calculate application name + + WCHAR szApplicationName[MAX_PATH]; + WCHAR szDrive[MAX_PATH]; + WCHAR szDir[MAX_PATH]; + WCHAR szFileName[MAX_PATH]; + WCHAR szExt[MAX_PATH]; + + GetModuleFileNameW( nullptr, szApplicationName, MAX_PATH ); + _wsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt ); + _wmakepath( szApplicationName, szDrive, szDir, L"soffice", L".exe" ); + + PROCESS_INFORMATION aProcessInfo; + + bool fSuccess = CreateProcessW( + szApplicationName, + lpCommandLine, + nullptr, + nullptr, + TRUE, + 0, + nullptr, + nullptr, + &aStartupInfo, + &aProcessInfo ); + + if ( fSuccess ) + { + // Wait for soffice process to be terminated to allow other applications + // to wait for termination of started process + + WaitForSingleObject( aProcessInfo.hProcess, INFINITE ); + + CloseHandle( aProcessInfo.hProcess ); + CloseHandle( aProcessInfo.hThread ); + + return 0; + } + + DWORD dwError = GetLastError(); + + LPWSTR lpMsgBuf = nullptr; + + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + nullptr, + dwError, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language + reinterpret_cast<LPWSTR>(&lpMsgBuf), + 0, + nullptr + ); + + // Display the string. + MessageBoxW( nullptr, lpMsgBuf, nullptr, MB_OK | MB_ICONERROR ); + + // Free the buffer. + HeapFree( GetProcessHeap(), 0, lpMsgBuf ); + + return dwError; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/launcher.hxx b/desktop/win32/source/applauncher/launcher.hxx new file mode 100644 index 000000000..e28cc7466 --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.hxx @@ -0,0 +1,27 @@ +/* -*- 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 . + */ + +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +extern WCHAR APPLICATION_SWITCH[]; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/launcher.rc b/desktop/win32/source/applauncher/launcher.rc new file mode 100644 index 000000000..8e56ef754 --- /dev/null +++ b/desktop/win32/source/applauncher/launcher.rc @@ -0,0 +1,23 @@ +/* + * 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 <windows.h> +#include "version.hrc" + +1 ICON PPS(RES_APP_ICON) diff --git a/desktop/win32/source/applauncher/sbase.cxx b/desktop/win32/source/applauncher/sbase.cxx new file mode 100644 index 000000000..a8e832a5b --- /dev/null +++ b/desktop/win32/source/applauncher/sbase.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--base"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/scalc.cxx b/desktop/win32/source/applauncher/scalc.cxx new file mode 100644 index 000000000..27df42119 --- /dev/null +++ b/desktop/win32/source/applauncher/scalc.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--calc"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sdraw.cxx b/desktop/win32/source/applauncher/sdraw.cxx new file mode 100644 index 000000000..3cfb7e425 --- /dev/null +++ b/desktop/win32/source/applauncher/sdraw.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--draw"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/simpress.cxx b/desktop/win32/source/applauncher/simpress.cxx new file mode 100644 index 000000000..c3b73bf40 --- /dev/null +++ b/desktop/win32/source/applauncher/simpress.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--impress"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/smath.cxx b/desktop/win32/source/applauncher/smath.cxx new file mode 100644 index 000000000..ae441b2e4 --- /dev/null +++ b/desktop/win32/source/applauncher/smath.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--math"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/soffice_safe.cxx b/desktop/win32/source/applauncher/soffice_safe.cxx new file mode 100644 index 000000000..241a03b76 --- /dev/null +++ b/desktop/win32/source/applauncher/soffice_safe.cxx @@ -0,0 +1,14 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--safe-mode"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/sweb.cxx b/desktop/win32/source/applauncher/sweb.cxx new file mode 100644 index 000000000..69aeda135 --- /dev/null +++ b/desktop/win32/source/applauncher/sweb.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--web"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/applauncher/swriter.cxx b/desktop/win32/source/applauncher/swriter.cxx new file mode 100644 index 000000000..fc470d3ac --- /dev/null +++ b/desktop/win32/source/applauncher/swriter.cxx @@ -0,0 +1,24 @@ +/* -*- 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 "launcher.hxx" + +WCHAR APPLICATION_SWITCH[] = L"--writer"; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/win32/source/loader.cxx b/desktop/win32/source/loader.cxx new file mode 100644 index 000000000..d30f0ef90 --- /dev/null +++ b/desktop/win32/source/loader.cxx @@ -0,0 +1,480 @@ +/* -*- 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 "loader.hxx" +#include <cassert> +#include <systools/win32/uwinapi.h> +#include <stdlib.h> +#include <string> +#include <vector> +#include <desktop/exithelper.h> +#include <tools/pathutils.hxx> + +#include <fstream> +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/ini_parser.hpp> + +namespace { + +void fail() +{ + LPWSTR buf = nullptr; + FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, + GetLastError(), 0, reinterpret_cast< LPWSTR >(&buf), 0, nullptr); + MessageBoxW(nullptr, buf, nullptr, MB_OK | MB_ICONERROR); + HeapFree(GetProcessHeap(), 0, buf); + 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; +} + +void AddEscapedArg(LPCWSTR sArg, std::vector<std::wstring>& aEscapedArgs, + std::size_t& iLengthAccumulator) +{ + std::wstring sEscapedArg = EscapeArg(sArg); + aEscapedArgs.push_back(sEscapedArg); + iLengthAccumulator += sEscapedArg.length() + 1; // a space between args +} + +bool HasWildCard(LPCWSTR sArg) +{ + while (*sArg != L'\0') + { + if (*sArg == L'*' || *sArg == L'?') + return true; + sArg++; + } + return false; +} + +} + +namespace desktop_win32 { + +void extendLoaderEnvironment(WCHAR * binPath, WCHAR * iniDirectory) { + if (!GetModuleFileNameW(nullptr, iniDirectory, MAX_PATH)) { + fail(); + } + WCHAR * iniDirEnd = tools::filename(iniDirectory); + WCHAR name[MAX_PATH + MY_LENGTH(L".bin")]; + // hopefully std::size_t is large enough to not overflow + WCHAR * nameEnd = name; + for (WCHAR * p = iniDirEnd; *p != L'\0'; ++p) { + *nameEnd++ = *p; + } + if (!(nameEnd - name >= 4 && nameEnd[-4] == L'.' && + (((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[-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; + } + nameEnd[-3] = 'b'; + nameEnd[-2] = 'i'; + nameEnd[-1] = 'n'; + tools::buildPath(binPath, iniDirectory, iniDirEnd, name, nameEnd - name); + *iniDirEnd = L'\0'; + std::size_t const maxEnv = 32767; + WCHAR env[maxEnv]; + DWORD n = GetEnvironmentVariableW(L"PATH", env, maxEnv); + if ((n >= maxEnv || n == 0) && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { + fail(); + } + // must be first in PATH to override other entries + assert(*(iniDirEnd - 1) == L'\\'); // hence -1 below + if (wcsncmp(env, iniDirectory, iniDirEnd - iniDirectory - 1) != 0 + || env[iniDirEnd - iniDirectory - 1] != L';') + { + WCHAR pad[MAX_PATH + maxEnv]; + // hopefully std::size_t is large enough to not overflow + WCHAR * p = commandLineAppend(pad, iniDirectory, iniDirEnd - iniDirectory - 1); + if (n != 0) { + *p++ = L';'; + for (DWORD i = 0; i <= n; ++i) { + *p++ = env[i]; + } + } else { + *p++ = L'\0'; + } + if (!SetEnvironmentVariableW(L"PATH", pad)) { + fail(); + } + } +} + +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; + + // read limit values from bootstrap.ini + unsigned int nMaxMemoryInMB = 0; + bool bExcludeChildProcesses = true; + + const WCHAR* szIniFile = L"\\bootstrap.ini"; + const size_t nDirLen = wcslen(szIniDirectory); + if (wcslen(szIniFile) + nDirLen < MAX_PATH) + { + WCHAR szBootstrapIni[MAX_PATH]; + wcscpy(szBootstrapIni, szIniDirectory); + wcscpy(&szBootstrapIni[nDirLen], szIniFile); + + try + { + boost::property_tree::ptree pt; + std::ifstream aFile(szBootstrapIni); + boost::property_tree::ini_parser::read_ini(aFile, pt); + nMaxMemoryInMB = pt.get("Win32.LimitMaximumMemoryInMB", nMaxMemoryInMB); + bExcludeChildProcesses = pt.get("Win32.ExcludeChildProcessesFromLimit", bExcludeChildProcesses); + } + catch (...) + { + nMaxMemoryInMB = 0; + } + } + + // create a Windows JobObject with a memory limit + HANDLE hJobObject = nullptr; + if (nMaxMemoryInMB > 0) + { + JOBOBJECT_EXTENDED_LIMIT_INFORMATION aJobLimit; + aJobLimit.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY; + if (bExcludeChildProcesses) + aJobLimit.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; + aJobLimit.JobMemoryLimit = nMaxMemoryInMB * 1024 * 1024; + hJobObject = CreateJobObjectW(nullptr, nullptr); + if (hJobObject != nullptr) + SetInformationJobObject(hJobObject, JobObjectExtendedLimitInformation, &aJobLimit, + sizeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); + } + + do + { + if (bFirst) + { + int argc = 0; + LPWSTR* argv = GetCommandArgs(&argc); + std::size_t n = 0; + for (int i = 0; i < argc; ++i) + { + // check for wildCards in arguments- windows does not expand automatically + if (HasWildCard(argv[i])) + { + WIN32_FIND_DATAW aFindData; + HANDLE h = FindFirstFileW(argv[i], &aFindData); + if (h == INVALID_HANDLE_VALUE) + { + AddEscapedArg(argv[i], aEscapedArgs, n); + } + else + { + const int nPathSize = 32 * 1024; + wchar_t drive[nPathSize]; + wchar_t dir[nPathSize]; + wchar_t path[nPathSize]; + _wsplitpath_s(argv[i], drive, nPathSize, dir, nPathSize, nullptr, 0, + nullptr, 0); + _wmakepath_s(path, nPathSize, drive, dir, aFindData.cFileName, nullptr); + AddEscapedArg(path, aEscapedArgs, n); + + while (FindNextFileW(h, &aFindData)) + { + _wmakepath_s(path, nPathSize, drive, dir, aFindData.cFileName, nullptr); + AddEscapedArg(path, aEscapedArgs, n); + } + FindClose(h); + } + } + else + { + AddEscapedArg(argv[i], aEscapedArgs, n); + } + } + 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; + + if (hJobObject) + AssignProcessToJobObject(hJobObject, aProcessInfo.hProcess); + + do + { + // On Windows XP it seems as the desktop calls WaitForInputIdle after "OpenWith" so + // we have to do so as if we were 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)); + + if (hJobObject) + CloseHandle(hJobObject); + + delete[] lpCommandLine; + + 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 were 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 new file mode 100644 index 000000000..66b0ed8e5 --- /dev/null +++ b/desktop/win32/source/loader.hxx @@ -0,0 +1,89 @@ +/* -*- 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 . + */ + +#pragma once + +#include <cstddef> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#include <string.h> + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace desktop_win32 { + +inline WCHAR * commandLineAppend( + WCHAR * buffer, WCHAR const * text, std::size_t length) +{ + wcsncpy(buffer, text, length + 1); // trailing null + return buffer + length; +} + +inline WCHAR * commandLineAppend(WCHAR * buffer, WCHAR const * text) { + return commandLineAppend(buffer, text, wcslen(text)); +} + +inline WCHAR * commandLineAppendEncoded(WCHAR * buffer, WCHAR const * text) { + std::size_t n = 0; + for (;;) { + WCHAR c = *text++; + if (c == L'\0') { + break; + } else if (c == L'$') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\$")); + n = 0; + } else if (c == L'\\') { + buffer = commandLineAppend(buffer, MY_STRING(L"\\\\")); + n += 2; + } else { + *buffer++ = c; + n = 0; + } + } + // The command line will continue with a double quote, so double any + // preceding backslashes as required by Windows: + for (std::size_t i = 0; i < n; ++i) { + *buffer++ = L'\\'; + } + *buffer = L'\0'; + return buffer; +} + +// Set the PATH environment variable in the current (loader) process, so that a +// following CreateProcess has the necessary environment: +// @param binPath +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full path to the "bin" file corresponding to the current +// executable. +// @param iniDirectory +// Must point to an array of size at least MAX_PATH. Is filled with the null +// terminated full directory path (ending in "\") to the "ini" file +// corresponding to the current executable. +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); + +} + +/* 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 000000000..5c6974e66 --- /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 000000000..03ff0a546 --- /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/desktop/win32/source/officeloader/unopkg_com.cxx b/desktop/win32/source/officeloader/unopkg_com.cxx new file mode 100644 index 000000000..a93ac6036 --- /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 000000000..40b1afa09 --- /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: */ diff --git a/desktop/win32/source/unoinfo.cxx b/desktop/win32/source/unoinfo.cxx new file mode 100644 index 000000000..14cee8819 --- /dev/null +++ b/desktop/win32/source/unoinfo.cxx @@ -0,0 +1,87 @@ +/* -*- 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 <stdio.h> +#include <stdlib.h> +#include <wchar.h> + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#include <tools/pathutils.hxx> + +#define MY_LENGTH(s) (sizeof (s) / sizeof *(s) - 1) +#define MY_STRING(s) (s), MY_LENGTH(s) + +namespace { + +wchar_t * getBrandPath(wchar_t * path) { + DWORD n = GetModuleFileNameW(nullptr, path, MAX_PATH); + if (n == 0 || n >= MAX_PATH) { + exit(EXIT_FAILURE); + } + return tools::filename(path); +} + +void writeNull() { + if (fwrite("\0\0", 1, 2, stdout) != 2) { + exit(EXIT_FAILURE); + } +} + +void writePath( + wchar_t const * frontBegin, wchar_t const * frontEnd, + wchar_t const * backBegin, std::size_t backLength) +{ + wchar_t path[MAX_PATH]; + wchar_t * end = tools::buildPath( + path, frontBegin, frontEnd, backBegin, backLength); + if (end == nullptr) { + exit(EXIT_FAILURE); + } + std::size_t n = (end - path) * sizeof (wchar_t); + if (fwrite(path, 1, n, stdout) != n) { + exit(EXIT_FAILURE); + } +} + +} + +int wmain(int argc, wchar_t ** argv, wchar_t **) { + if (argc == 2 && wcscmp(argv[1], L"c++") == 0) { + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + writePath(path, pathEnd, MY_STRING(L"")); + } else if (argc == 2 && wcscmp(argv[1], L"java") == 0) { + if (fwrite("1", 1, 1, stdout) != 1) { + exit(EXIT_FAILURE); + } + wchar_t path[MAX_PATH]; + wchar_t * pathEnd = getBrandPath(path); + writePath(path, pathEnd, MY_STRING(L"classes\\libreoffice.jar")); + writeNull(); + writePath(path, pathEnd, MY_STRING(L"")); + } else { + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |