
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@7245 212acab6-be3b-0410-9dea-997c60f758d6
132 lines
3.1 KiB
C
132 lines
3.1 KiB
C
/*
|
|
* substart.c - This app runs the executable of the same name in the 'Bin'
|
|
* sub-folder and passes along the command line options.
|
|
*
|
|
* Copyright (c) 2013-2021 Anders Kjersem
|
|
*
|
|
* Licensed under the zlib/libpng license (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
*
|
|
* Licence details can be found in the file COPYING.
|
|
*
|
|
* This software is provided 'as-is', without any express or implied
|
|
* warranty.
|
|
*/
|
|
|
|
#include <windows.h>
|
|
#include <tchar.h>
|
|
|
|
#define SUBFOLDER _T("Bin")
|
|
|
|
/*
|
|
* Leaking things Windows is going to clean up after us anyway avoids
|
|
* linking to a couple of functions, this saves just enough space
|
|
* to get the file size down to 2 KiB (MSVC 7.1)
|
|
*/
|
|
#ifdef _DEBUG
|
|
# define CANLEAK(cod) cod
|
|
#else
|
|
# define CANLEAK(cod)
|
|
#endif
|
|
|
|
#define MemFree LocalFree
|
|
static void* MemReAlloc(void*OrgMem, size_t cb)
|
|
{
|
|
if (!OrgMem) return LocalAlloc(LMEM_FIXED, cb);
|
|
return LocalReAlloc(OrgMem, cb, LMEM_MOVEABLE);
|
|
}
|
|
static void MemZero(void*pMem, size_t cb)
|
|
{
|
|
char*p=(char*)pMem;
|
|
for(; cb;) p[--cb] = 0;
|
|
}
|
|
|
|
static UINT SIOPut(LPCSTR Str, UINT cch)
|
|
{
|
|
HANDLE hSO = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
DWORD cbio;
|
|
return WriteFile(hSO, Str, cch, &cbio, 0) ? cch : 0;
|
|
}
|
|
static UINT SIOFmtPut(LPCSTR Fmt, ...)
|
|
{
|
|
UINT cch;
|
|
char buf[150]; // Plenty for our simple strings
|
|
va_list val;
|
|
va_start(val, Fmt);
|
|
cch = wvsprintfA(buf, Fmt, val);
|
|
cch = SIOPut(buf, cch);
|
|
va_end(val);
|
|
return cch;
|
|
}
|
|
|
|
void mainCRTStartup()
|
|
{
|
|
const UINT cchSubDir = (sizeof(SUBFOLDER) / sizeof(TCHAR)) - 1;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
UINT ec, cch, cchParams;
|
|
TCHAR *p = GetCommandLine(), *cmd = 0;
|
|
|
|
if (*p == _T('\"'))
|
|
do ++p; while(*p && *p != _T('\"'));
|
|
else
|
|
while(*p && *p > _T(' ')) ++p;
|
|
|
|
/* Skip end quote and whitespace */
|
|
do if (!*p) break; else ++p; while(*p <= ' ');
|
|
|
|
ec = ERROR_OUTOFMEMORY;
|
|
cchParams = lstrlen(p), cch = MAX_PATH;
|
|
for (;;)
|
|
{
|
|
TCHAR *mem;
|
|
UINT cchTot = 1 + cch + 1 + cchSubDir + 2 + cchParams + 1, cchSelf;
|
|
mem = (TCHAR*) MemReAlloc(cmd, cchTot * sizeof(TCHAR));
|
|
if (!mem) goto app_die;
|
|
cmd = mem;
|
|
cchSelf = GetModuleFileName(NULL, cmd + 1, cch);
|
|
if (!cchSelf) goto app_diegle;
|
|
if (cchSelf < cch)
|
|
{
|
|
/* Insert subfolder before the filename */
|
|
TCHAR *src = cmd + cchSelf + 1, *dst = src + cchSubDir + 1;
|
|
for(; src > cmd; --src, --dst)
|
|
{
|
|
*dst = *src;
|
|
if (_T('\\') == *src || _T('/') == *src) break;
|
|
}
|
|
*++src = _T('\0');
|
|
lstrcat(src, SUBFOLDER);
|
|
src[cchSubDir] = _T('\\');
|
|
|
|
/* Quote path and append parameters */
|
|
cmd[0] = _T('\"');
|
|
lstrcat(cmd, _T("\" "));
|
|
lstrcat(cmd, p);
|
|
break;
|
|
}
|
|
cch *= 2;
|
|
}
|
|
|
|
MemZero(&si, sizeof(si));
|
|
si.cb = sizeof(si);
|
|
|
|
if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
|
|
{
|
|
DWORD forkec;
|
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
|
GetExitCodeProcess(pi.hProcess, &forkec);
|
|
ec = forkec;
|
|
CANLEAK(CloseHandle(pi.hProcess));
|
|
CANLEAK(CloseHandle(pi.hThread));
|
|
goto app_end;
|
|
}
|
|
|
|
app_diegle:
|
|
ec = GetLastError();
|
|
app_die:
|
|
SIOFmtPut("Unable to start child process, error %#x\n", ec);
|
|
app_end:
|
|
CANLEAK(MemFree(cmd));
|
|
ExitProcess(ec);
|
|
}
|