/* -*- 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 <tools/pathutils.hxx>
#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: */
