Rewrote SubStart, does not use CRT
git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6377 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
parent
e6f549adee
commit
4b3a146fdd
3 changed files with 114 additions and 126 deletions
|
@ -1,34 +0,0 @@
|
|||
substart - Redirect to an executable located in the 'Bin' sub folder
|
||||
relative to the starter executable.
|
||||
------------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2010 Thomas Gaugler
|
||||
Licensed under the zlib/libpng license
|
||||
|
||||
This tool runs the executable of the same name in the 'Bin' sub folder
|
||||
and passes along the command line options.
|
||||
|
||||
The main purpose of the tool is that scripts expecting an executable in
|
||||
the root of the program installation folder continue to run.
|
||||
|
||||
USAGE
|
||||
-----
|
||||
|
||||
The original executable has to go into the 'Bin' sub folder and the
|
||||
the substart executable renamed to the original executable name needs
|
||||
to be placed at the original location.
|
||||
|
||||
EXAMPLE
|
||||
-------
|
||||
|
||||
Directory hierarchy:
|
||||
C:\Program Files\NSIS
|
||||
C:\Program Files\NSIS\Bin\makensis.exe
|
||||
C:\Program Files\NSIS\makensis.exe (-> substart.exe renamed to makensis.exe)
|
||||
|
||||
C:\Program Files\NSIS\makensis.exe /VERSION
|
||||
|
||||
|
||||
Please be aware that the name of the substart executable has to match
|
||||
with the one in the sub folder.
|
||||
|
|
@ -7,10 +7,12 @@ files = Split("""
|
|||
""")
|
||||
|
||||
libs = Split("""
|
||||
kernel32
|
||||
user32
|
||||
""")
|
||||
|
||||
Import('BuildUtil')
|
||||
|
||||
substart = BuildUtil(target, files, libs, cli = True, noinstall = True)
|
||||
substart = BuildUtil(target, files, libs, cli = True, noinstall = True, nodeflib = True)
|
||||
|
||||
env.DistributeBin(substart, names=['makensis.exe'], alias='install-compiler') # install as makensis
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* substart.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) 2010 Thomas Gaugler
|
||||
* Copyright (c) 2013 Anders Kjersem
|
||||
*
|
||||
* Licensed under the zlib/libpng license (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -14,99 +15,118 @@
|
|||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* Macro to determine the string length of a constant */
|
||||
#define CONST_STRLEN(x) ((sizeof(x) / sizeof(*x)) - 1)
|
||||
#define SUBFOLDER _T("Bin")
|
||||
|
||||
/* Name of the sub folder containing the executable
|
||||
invoked by this stub executable.
|
||||
/*
|
||||
* 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)
|
||||
*/
|
||||
static const TCHAR SUBFOLDER[] = _T("Bin");
|
||||
#ifdef _DEBUG
|
||||
# define CANLEAK(cod) cod
|
||||
#else
|
||||
# define CANLEAK(cod)
|
||||
#endif
|
||||
|
||||
/* Redirect to an executable located in a sub folder relative to
|
||||
this starter executable. Name of the stub executable has to
|
||||
match with the one in the sub folder.
|
||||
The command line parameters are passed along.
|
||||
*/
|
||||
int main( int argc, char *argv[] )
|
||||
#define MemFree LocalFree
|
||||
static void* MemReAlloc(void*OrgMem, size_t cb)
|
||||
{
|
||||
int err = ERROR_SUCCESS;
|
||||
TCHAR szPath[MAX_PATH];
|
||||
|
||||
/* Get the full path of the running executable */
|
||||
if ( GetModuleFileName( NULL, szPath, MAX_PATH ) )
|
||||
{
|
||||
size_t len = _tcslen(szPath);
|
||||
size_t offset = len + CONST_STRLEN(SUBFOLDER) + 1;
|
||||
|
||||
err = ERROR_BAD_PATHNAME;
|
||||
if (offset < MAX_PATH)
|
||||
{
|
||||
/* Move file name part of full path by length of sub folder
|
||||
name and thereafter fill in the sub folder name in the
|
||||
newly created gap.
|
||||
*/
|
||||
register TCHAR *p = szPath + len;
|
||||
register TCHAR *q = szPath + offset;
|
||||
|
||||
while (p > szPath)
|
||||
{
|
||||
*(q--) = *(p--);
|
||||
if (*p == '\\')
|
||||
{
|
||||
/* Fill in sub folder name */
|
||||
*q = *p;
|
||||
q = ++p;
|
||||
p = (TCHAR *)SUBFOLDER;
|
||||
while (*p)
|
||||
{
|
||||
*(q++) = *(p++);
|
||||
}
|
||||
err = ERROR_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
_tprintf( _T("Path too long: %s\n"), szPath );
|
||||
}
|
||||
else
|
||||
{
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ZeroMemory( &si, sizeof(si) );
|
||||
si.cb = sizeof(si);
|
||||
|
||||
/* Start and wait for a process with the same filename as
|
||||
ourself located in SUBFOLDER.
|
||||
|
||||
WARNING: The subprocess can't parse GetCommandLine()
|
||||
to find its own path since we pass the wrong path! */
|
||||
if ( CreateProcess( szPath, GetCommandLine(), NULL, NULL,
|
||||
TRUE, 0, NULL, NULL, &si, &pi ) )
|
||||
{
|
||||
WaitForSingleObject( pi.hProcess, INFINITE );
|
||||
GetExitCodeProcess( pi.hProcess, (DWORD*) &err );
|
||||
CloseHandle( pi.hProcess );
|
||||
CloseHandle( pi.hThread );
|
||||
}
|
||||
else
|
||||
{
|
||||
err = GetLastError();
|
||||
_tprintf( _T("CreateProcess (%s) failed (%d).\n"), szPath, err );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = GetLastError();
|
||||
_tprintf( _T("GetModuleFileName failed (%d).\n"), err );
|
||||
}
|
||||
|
||||
return err;
|
||||
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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue