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("""
|
libs = Split("""
|
||||||
|
kernel32
|
||||||
|
user32
|
||||||
""")
|
""")
|
||||||
|
|
||||||
Import('BuildUtil')
|
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
|
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");
|
* Licensed under the zlib/libpng license (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,99 +15,118 @@
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <tchar.h>
|
#include <tchar.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
/* Macro to determine the string length of a constant */
|
#define SUBFOLDER _T("Bin")
|
||||||
#define CONST_STRLEN(x) ((sizeof(x) / sizeof(*x)) - 1)
|
|
||||||
|
|
||||||
/* 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
|
#define MemFree LocalFree
|
||||||
this starter executable. Name of the stub executable has to
|
static void* MemReAlloc(void*OrgMem, size_t cb)
|
||||||
match with the one in the sub folder.
|
|
||||||
The command line parameters are passed along.
|
|
||||||
*/
|
|
||||||
int main( int argc, char *argv[] )
|
|
||||||
{
|
{
|
||||||
int err = ERROR_SUCCESS;
|
if (!OrgMem) return LocalAlloc(LMEM_FIXED, cb);
|
||||||
TCHAR szPath[MAX_PATH];
|
return LocalReAlloc(OrgMem, cb, LMEM_MOVEABLE);
|
||||||
|
}
|
||||||
/* Get the full path of the running executable */
|
static void MemZero(void*pMem, size_t cb)
|
||||||
if ( GetModuleFileName( NULL, szPath, MAX_PATH ) )
|
{
|
||||||
{
|
char*p=(char*)pMem;
|
||||||
size_t len = _tcslen(szPath);
|
for(; cb;) p[--cb] = 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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