/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
#pragma once
#ifndef __cplusplus
#error Need C++ to compile
#endif

#include "main.h"

#ifndef _WINDOWS_
#if defined _MSC_VER
#pragma warning(push, 1)
#endif
#	include <windows.h>
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif


#ifndef _INC_TCHAR
#	ifdef UNICODE
#		define _UNICODE
#	endif
#	include <tchar.h>
#endif

#ifdef UNICODE
#	define Main	MainW
#	define GetArgv( pArgc )			CommandLineToArgvW( GetCommandLine(), pArgc )
#	define PROCESS_CREATIONFLAGS	CREATE_UNICODE_ENVIRONMENT
#else
#	define GetArgv( pArgc )			(*pArgc = __argc, __argv)
#	define PROCESS_CREATIONFLAGS	0
#	define Main	MainA
#endif

#define BIN_EXT_STR			TEXT(".bin")
#define PARAM_LIBPATH_STR	TEXT("-libpath=")
#define PARAM_LOCAL_STR		TEXT("-local")
#define PARAM_REMOTE_STR	TEXT("-remote")

#if defined( REMOTE )
#define DEFAULT_LIBPATH		TEXT("remote;")
#elif defined( LOCAL )
#define DEFAULT_LIBPATH		TEXT("local;")
#endif

extern "C" int Main()
{
    // Retreive startup info

    STARTUPINFO	aStartupInfo;

    ZeroMemory( &aStartupInfo, sizeof(aStartupInfo) );
    aStartupInfo.cb = sizeof( aStartupInfo );
    GetStartupInfo( &aStartupInfo );

    // Retrieve command line

    LPTSTR	lpCommandLine = GetCommandLine();

    LPTSTR	*ppArguments = NULL;
    int		nArguments = 0;

    ppArguments = GetArgv( &nArguments );

    // Calculate application name


    TCHAR	szApplicationName[MAX_PATH];
    TCHAR	szDrive[MAX_PATH];
    TCHAR	szDir[MAX_PATH];
    TCHAR	szFileName[MAX_PATH];
    TCHAR	szExt[MAX_PATH];

    GetModuleFileName( NULL, szApplicationName, MAX_PATH );
    _tsplitpath( szApplicationName, szDrive, szDir, szFileName, szExt );
    _tmakepath( szApplicationName, szDrive, szDir, szFileName, BIN_EXT_STR );

    // Retreive actual environment

    TCHAR	szBuffer[1024];
    TCHAR	szPathValue[1024] = TEXT("");

#ifdef DEFAULT_LIBPATH
    _tmakepath( szPathValue, szDrive, szDir, DEFAULT_LIBPATH, TEXT("") );
#endif

    for ( int argn = 1; argn < nArguments; argn++ )
    {
        if ( 0 == _tcscmp( ppArguments[argn], PARAM_REMOTE_STR ) )
        {
            _tmakepath( szPathValue, szDrive, szDir, TEXT("remote;"), TEXT("") );
            break;
        }
        else if ( 0 == _tcscmp( ppArguments[argn], PARAM_LOCAL_STR ) )
        {
            _tmakepath( szPathValue, szDrive, szDir, TEXT("local;"), TEXT("") );
            break;
        }
        else if ( 0 == _tcsncmp( ppArguments[argn], PARAM_LIBPATH_STR, _tcslen(PARAM_LIBPATH_STR) ) )
        {
            LPTSTR	pFileSpec = NULL;

            GetFullPathName( ppArguments[argn] + _tcslen(PARAM_LIBPATH_STR), sizeof(szPathValue) / sizeof(TCHAR), szPathValue, &pFileSpec );
            _tcscat( szPathValue, TEXT(";") );
            break;
        }
    }

    GetEnvironmentVariable( TEXT("PATH"), szBuffer, sizeof(szBuffer) );
    _tcscat( szPathValue, szBuffer );
    SetEnvironmentVariable( TEXT("PATH"), szPathValue);

    LPVOID	lpEnvironment = GetEnvironmentStrings();
    

    // Retrieve current directory

    TCHAR				szCurrentDirectory[MAX_PATH];
    GetCurrentDirectory( MAX_PATH, szCurrentDirectory );

    // Set the Flags

    DWORD	dwCreationFlags = PROCESS_CREATIONFLAGS;

    PROCESS_INFORMATION	aProcessInfo;

    BOOL	fSuccess = CreateProcess(
        szApplicationName,
        lpCommandLine,
        NULL,
        NULL,
        TRUE,
        dwCreationFlags,
        lpEnvironment,
        szCurrentDirectory,
        &aStartupInfo,
        &aProcessInfo );

    if ( fSuccess )
    {
        DWORD	dwExitCode;

        WaitForSingleObject( aProcessInfo.hProcess, INFINITE );
        fSuccess = GetExitCodeProcess( aProcessInfo.hProcess, &dwExitCode );

        return dwExitCode;
    }

    DWORD	dwError = GetLastError();

    LPVOID lpMsgBuf;

    FormatMessage( 
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        dwError,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR)&lpMsgBuf,
        0,
        NULL
    );

    // Display the string.
    MessageBox( NULL, (LPCTSTR)lpMsgBuf, NULL, MB_OK | MB_ICONERROR );

    // Free the buffer.
    LocalFree( lpMsgBuf );

    return GetLastError();
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
